File smokin-guns-1.1-x86_64.patch of Package smokin-guns

Index: code/asm/qasm-inline.h
===================================================================
--- /dev/null
+++ code/asm/qasm-inline.h
@@ -0,0 +1,39 @@
+/*
+===========================================================================
+Copyright (C) 1999-2005 Id Software, Inc.
+
+This file is part of Quake III Arena source code.
+
+Quake III Arena source code 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.
+
+Quake III Arena source code 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 Quake III Arena source code; if not, write to the Free Software
+Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+===========================================================================
+*/
+#ifndef __ASM_INLINE_I386__
+#define __ASM_INLINE_I386__
+
+#include "../qcommon/q_platform.h"
+
+#if idx64
+  #define EAX "%%rax"
+  #define EBX "%%rbx"
+  #define ESP "%%rsp"
+  #define EDI "%%rdi"
+#else
+  #define EAX "%%eax"
+  #define EBX "%%ebx"
+  #define ESP "%%esp"
+  #define EDI "%%edi"
+#endif
+
+#endif
Index: code/asm/ftola.asm
===================================================================
--- /dev/null
+++ code/asm/ftola.asm
@@ -0,0 +1,87 @@
+; ===========================================================================
+; Copyright (C) 2011 Thilo Schulz <thilo@tjps.eu>
+; 
+; This file is part of Quake III Arena source code.
+; 
+; Quake III Arena source code 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.
+; 
+; Quake III Arena source code 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 Quake III Arena source code; if not, write to the Free Software
+; Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+; ===========================================================================
+
+; MASM ftol conversion functions using SSE or FPU
+; assume __cdecl calling convention is being used for x86, __fastcall for x64
+
+IFNDEF idx64
+.model flat, c
+ENDIF
+
+.data
+
+ifndef idx64
+  fpucw WORD 0F7Fh
+endif
+
+.code
+
+IFDEF idx64
+; qftol using SSE
+
+  qftolsse PROC
+    cvttss2si eax, xmm0
+	ret
+  qftolsse ENDP
+
+  qvmftolsse PROC
+    movss xmm0, dword ptr [rdi + rbx * 4]
+	cvttss2si eax, xmm0
+	ret
+  qvmftolsse ENDP
+
+ELSE
+; qftol using FPU
+
+  qftolx87m macro src
+    sub esp, 2
+    fnstcw word ptr [esp]
+    fldcw fpucw
+    fld dword ptr src
+	fistp dword ptr src
+	fldcw [esp]
+	mov eax, src
+	add esp, 2
+	ret
+  endm
+  
+  qftolx87 PROC
+    qftolx87m [esp + 6]
+  qftolx87 ENDP
+
+  qvmftolx87 PROC
+    qftolx87m [edi + ebx * 4]
+  qvmftolx87 ENDP
+
+; qftol using SSE
+  qftolsse PROC
+    movss xmm0, dword ptr [esp + 4]
+    cvttss2si eax, xmm0
+	ret
+  qftolsse ENDP
+
+  qvmftolsse PROC
+    movss xmm0, dword ptr [edi + ebx * 4]
+	cvttss2si eax, xmm0
+	ret
+  qvmftolsse ENDP
+ENDIF
+
+end
Index: code/asm/ftola.c
===================================================================
--- /dev/null
+++ code/asm/ftola.c
@@ -0,0 +1,99 @@
+/*
+===========================================================================
+Copyright (C) 2011 Thilo Schulz <thilo@tjps.eu>
+
+This file is part of Quake III Arena source code.
+
+Quake III Arena source code 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.
+
+Quake III Arena source code 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 Quake III Arena source code; if not, write to the Free Software
+Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+===========================================================================
+*/
+
+#include "qasm-inline.h"
+
+static const unsigned short fpucw = 0x0C7F;
+
+/*
+ * GNU inline asm ftol conversion functions using SSE or FPU
+ */
+
+long qftolsse(float f)
+{
+  long retval;
+  
+  __asm__ volatile
+  (
+    "cvttss2si %1, %0\n"
+    : "=r" (retval)
+    : "x" (f)
+  );
+  
+  return retval;
+}
+
+int qvmftolsse(void)
+{
+  int retval;
+  
+  __asm__ volatile
+  (
+    "movss (" EDI ", " EBX ", 4), %%xmm0\n"
+    "cvttss2si %%xmm0, %0\n"
+    : "=r" (retval)
+    :
+    : "%xmm0"
+  );
+  
+  return retval;
+}
+
+long qftolx87(float f)
+{
+  long retval;
+  unsigned short oldcw;
+
+  __asm__ volatile
+  (
+    "fnstcw %2\n"
+    "fldcw %3\n"
+    "flds %1\n"
+    "fistpl %1\n"
+    "fldcw %2\n"
+    "mov %1, %0\n"
+    : "=r" (retval)
+    : "m" (f), "m" (oldcw), "m" (fpucw)
+  );
+  
+  return retval;
+}
+
+int qvmftolx87(void)
+{
+  int retval;
+  unsigned short oldcw;
+
+  __asm__ volatile
+  (
+    "fnstcw %1\n"
+    "fldcw %2\n"
+    "flds (" EDI ", " EBX ", 4)\n"
+    "fistpl (" EDI ", " EBX ", 4)\n"
+    "fldcw %1\n"
+    "mov (" EDI ", " EBX ", 4), %0\n"
+    : "=r" (retval)
+    : "m" (oldcw), "m" (fpucw)
+  );
+  
+  return retval;
+}
Index: code/asm/qasm.h
===================================================================
--- code/asm/qasm.h.orig
+++ code/asm/qasm.h
@@ -29,7 +29,7 @@ Foundation, Inc., 51 Franklin St, Fifth
 .section .note.GNU-stack,"",@progbits
 #endif
 
-#ifdef __ELF__
+#if defined(__ELF__) || defined(__WIN64__)
 #define C(label) label
 #else
 #define C(label) _##label
Index: code/asm/snapvector.asm
===================================================================
--- /dev/null
+++ code/asm/snapvector.asm
@@ -0,0 +1,93 @@
+; ===========================================================================
+; Copyright (C) 2011 Thilo Schulz <thilo@tjps.eu>
+; 
+; This file is part of Quake III Arena source code.
+; 
+; Quake III Arena source code 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.
+; 
+; Quake III Arena source code 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 Quake III Arena source code; if not, write to the Free Software
+; Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+; ===========================================================================
+
+; MASM version of snapvector conversion function using SSE or FPU
+; assume __cdecl calling convention is being used for x86, __fastcall for x64
+;
+; function prototype:
+; void qsnapvector(vec3_t vec)
+
+IFNDEF idx64
+.model flat, c
+ENDIF
+
+.data
+
+  ALIGN 16
+  ssemask DWORD 0FFFFFFFFh, 0FFFFFFFFh, 0FFFFFFFFh, 00000000h
+  ssecw DWORD 00001F80h
+
+IFNDEF idx64
+  fpucw WORD 037Fh
+ENDIF
+
+.code
+
+IFDEF idx64
+; qsnapvector using SSE
+
+  qsnapvectorsse PROC
+    sub rsp, 8
+	movaps xmm1, ssemask		; initialize the mask register
+	movups xmm0, [rcx]			; here is stored our vector. Read 4 values in one go
+	movaps xmm2, xmm0			; keep a copy of the original data
+	andps xmm0, xmm1			; set the fourth value to zero in xmm0
+	andnps xmm1, xmm2			; copy fourth value to xmm1 and set rest to zero
+	cvtps2dq xmm0, xmm0			; convert 4 single fp to int
+	cvtdq2ps xmm0, xmm0			; convert 4 int to single fp
+	orps xmm0, xmm1				; combine all 4 values again
+	movups [rcx], xmm0			; write 3 rounded and 1 unchanged values back to memory
+	ret
+  qsnapvectorsse ENDP
+
+ELSE
+
+  qsnapvectorsse PROC
+	mov eax, dword ptr 4[esp]		; store address of vector in eax
+	movaps xmm1, ssemask			; initialize the mask register for maskmovdqu
+	movups xmm0, [eax]			; here is stored our vector. Read 4 values in one go
+	movaps xmm2, xmm0			; keep a copy of the original data
+	andps xmm0, xmm1			; set the fourth value to zero in xmm0
+	andnps xmm1, xmm2			; copy fourth value to xmm1 and set rest to zero
+	cvtps2dq xmm0, xmm0			; convert 4 single fp to int
+	cvtdq2ps xmm0, xmm0			; convert 4 int to single fp
+	orps xmm0, xmm1				; combine all 4 values again
+	movups [eax], xmm0			; write 3 rounded and 1 unchanged values back to memory
+	ret
+  qsnapvectorsse ENDP
+
+  qroundx87 macro src
+	fld dword ptr src
+	fistp dword ptr src
+	fild dword ptr src
+	fstp dword ptr src
+  endm    
+
+  qsnapvectorx87 PROC
+	mov eax, dword ptr 4[esp]
+	qroundx87 [eax]
+	qroundx87 4[eax]
+	qroundx87 8[eax]
+	ret
+  qsnapvectorx87 ENDP
+
+ENDIF
+
+end
Index: code/asm/snapvector.c
===================================================================
--- /dev/null
+++ code/asm/snapvector.c
@@ -0,0 +1,73 @@
+/*
+===========================================================================
+Copyright (C) 2011 Thilo Schulz <thilo@tjps.eu>
+
+This file is part of Quake III Arena source code.
+
+Quake III Arena source code 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.
+
+Quake III Arena source code 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 Quake III Arena source code; if not, write to the Free Software
+Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+===========================================================================
+*/
+
+#include "qasm-inline.h"
+#include "../qcommon/q_shared.h"
+
+/*
+ * GNU inline asm version of qsnapvector
+ * See MASM snapvector.asm for commentary
+ */
+
+static unsigned char ssemask[16] __attribute__((aligned(16))) =
+{
+	"\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x00\x00\x00\x00"
+};
+
+void qsnapvectorsse(vec3_t vec)
+{
+	__asm__ volatile
+	(
+		"movaps (%0), %%xmm1\n"
+		"movups (%1), %%xmm0\n"
+		"movaps %%xmm0, %%xmm2\n"
+		"andps %%xmm1, %%xmm0\n"
+		"andnps %%xmm2, %%xmm1\n"
+		"cvtps2dq %%xmm0, %%xmm0\n"
+		"cvtdq2ps %%xmm0, %%xmm0\n"
+		"orps %%xmm1, %%xmm0\n"
+		"movups %%xmm0, (%1)\n"
+		:
+		: "r" (ssemask), "r" (vec)
+		: "memory", "%xmm0", "%xmm1", "%xmm2"
+	);
+	
+}
+
+#define QROUNDX87(src) \
+	"flds " src "\n" \
+	"fistps " src "\n" \
+	"filds " src "\n" \
+	"fstps " src "\n"	
+
+void qsnapvectorx87(vec3_t vec)
+{
+	__asm__ volatile
+	(
+		QROUNDX87("(%0)")
+		QROUNDX87("4(%0)")
+		QROUNDX87("8(%0)")
+		:
+		: "r" (vec)
+		: "memory"
+	);
+}
Index: code/qcommon/cm_polylib.c
===================================================================
--- code/qcommon/cm_polylib.c.orig
+++ code/qcommon/cm_polylib.c
@@ -273,11 +273,11 @@ CopyWinding
 */
 winding_t	*CopyWinding (winding_t *w)
 {
-	unsigned long	size;
+	intptr_t	size;
 	winding_t	*c;
 
 	c = AllocWinding (w->numpoints);
-	size = (long)((winding_t *)0)->p[w->numpoints];
+	size = (intptr_t) ((winding_t *)0)->p[w->numpoints];
 	Com_Memcpy (c, w, size);
 	return c;
 }
Index: code/qcommon/common.c
===================================================================
--- code/qcommon/common.c.orig
+++ code/qcommon/common.c
@@ -109,6 +109,14 @@ cvar_t	*com_basegame;
 cvar_t  *com_homepath;
 cvar_t	*com_busyWait;
 
+#if idx64
+  void (*Q_VMftol)(void);
+#elif id386
+	long (QDECL *Q_ftol)(float f);
+	void (QDECL *Q_VMftol)(void);
+	void (QDECL *Q_SnapVector)(vec3_t vec);
+#endif
+
 // com_speeds times
 int		time_game;
 int		time_frontend;		// renderer frontend time
@@ -2606,6 +2614,53 @@ static void Com_DetectAltivec(void)
 
 /*
 =================
+Com_DetectSSE
+Find out whether we have SSE support for Q_ftol function
+=================
+*/
+
+#if id386 || idx64
+
+static void Com_DetectSSE(void)
+{
+#if !idx64
+	cpuFeatures_t feat;
+	
+	feat = Sys_GetProcessorFeatures();
+
+	if(feat & CF_SSE)
+	{
+		if(feat & CF_SSE2)
+			Q_SnapVector = qsnapvectorsse;
+		else
+			Q_SnapVector = qsnapvectorx87;
+
+		Q_ftol = qftolsse;
+#endif
+		Q_VMftol = qvmftolsse;
+
+		Com_Printf("Have SSE support\n");
+#if !idx64
+	}
+	else
+	{
+		Q_ftol = qftolx87;
+		Q_VMftol = qvmftolx87;
+		Q_SnapVector = qsnapvectorx87;
+
+		Com_Printf("No SSE support on this machine\n");
+	}
+#endif
+}
+
+#else
+
+#define Com_DetectSSE()
+
+#endif
+
+/*
+=================
 Com_InitRand
 Seed the random number generator, if possible with an OS supplied random seed.
 =================
@@ -2654,6 +2709,8 @@ void Com_Init( char *commandLine ) {
 //	Swap_Init ();
 	Cbuf_Init ();
 
+	Com_DetectSSE();
+
 	// override anything from the config files with command line args
 	Com_StartupVariable( NULL );
 
Index: code/qcommon/q_platform.h
===================================================================
--- code/qcommon/q_platform.h.orig
+++ code/qcommon/q_platform.h
@@ -24,6 +24,8 @@ Foundation, Inc., 51 Franklin St, Fifth
 #define __Q_PLATFORM_H
 
 // this is for determining if we have an asm version of a C function
+#define idx64 0
+
 #ifdef Q3_VM
 
 #define id386 0
@@ -76,6 +78,9 @@ Foundation, Inc., 51 Franklin St, Fifth
 
 #if defined(_WIN64) || defined(__WIN64__)
 
+#undef idx64
+#define idx64 1
+
 #undef QDECL
 #define QDECL __cdecl
 
@@ -85,7 +90,7 @@ Foundation, Inc., 51 Franklin St, Fifth
 #define OS_STRING "win_mingw64"
 #endif
 
-#define ID_INLINE inline
+#define ID_INLINE __inline
 #define PATH_SEP '\\'
 
 #if defined( __WIN64__ ) 
@@ -144,6 +149,8 @@ Foundation, Inc., 51 Franklin St, Fifth
 #define ARCH_STRING "i386"
 #define Q3_LITTLE_ENDIAN
 #elif defined __x86_64__
+#undef idx64
+#define idx64 1
 #define ARCH_STRING "x86_64"
 #define Q3_LITTLE_ENDIAN
 #endif
@@ -170,6 +177,8 @@ Foundation, Inc., 51 Franklin St, Fifth
 #if defined __i386__
 #define ARCH_STRING "i386"
 #elif defined __x86_64__
+#undef idx64
+#define idx64 1
 #define ARCH_STRING "x86_64"
 #elif defined __powerpc64__
 #define ARCH_STRING "ppc64"
@@ -232,6 +241,8 @@ Foundation, Inc., 51 Franklin St, Fifth
 #ifdef __i386__
 #define ARCH_STRING "i386"
 #elif defined __amd64__
+#undef idx64
+#define idx64 1
 #define ARCH_STRING "amd64"
 #elif defined __axp__
 #define ARCH_STRING "alpha"
Index: code/qcommon/q_shared.h
===================================================================
--- code/qcommon/q_shared.h.orig
+++ code/qcommon/q_shared.h
@@ -500,6 +500,58 @@ extern	vec3_t	axisDefault[3];
 
 #define	IS_NAN(x) (((*(int *)&x)&nanmask)==nanmask)
 
+int Q_isnan(float x);
+
+#if idx64
+  extern long qftolsse(float f);
+  extern void qvmftolsse(void);
+  extern void qsnapvectorsse(vec3_t vec);
+
+  #define Q_ftol qftolsse
+  #define Q_SnapVector qsnapvectorsse
+
+  extern void (*Q_VMftol)(void);
+#elif id386
+  extern long QDECL qftolx87(float f);
+  extern long QDECL qftolsse(float f);
+  extern void QDECL qvmftolx87(void);
+  extern void QDECL qvmftolsse(void);
+  extern void QDECL qsnapvectorx87(vec3_t vec);
+  extern void QDECL qsnapvectorsse(vec3_t vec);
+
+  extern long (QDECL *Q_ftol)(float f);
+  extern void (QDECL *Q_VMftol)(void);
+  extern void (QDECL *Q_SnapVector)(vec3_t vec);
+#else
+  #define Q_ftol(f) lrintf((f))
+  #define Q_SnapVector(vec)\
+	do\
+	{\
+		vec3_t *temp = (vec);\
+		\
+		(*temp)[0] = round((*temp)[0]);\
+		(*temp)[1] = round((*temp)[1]);\
+		(*temp)[2] = round((*temp)[2]);\
+	} while(0)
+#endif
+/*
+// if your system does not have lrintf() and round() you can try this block. Please also open a bug report at bugzilla.icculus.org
+// or write a mail to the ioq3 mailing list.
+#else
+  #define Q_ftol(v) ((long) (v))
+  #define Q_round(v) do { if((v) < 0) (v) -= 0.5f; else (v) += 0.5f; (v) = Q_ftol((v)); } while(0)
+  #define Q_SnapVector(vec) \
+	do\
+	{\
+		vec3_t *temp = (vec);\
+		\
+		Q_round((*temp)[0]);\
+		Q_round((*temp)[1]);\
+		Q_round((*temp)[2]);\
+	} while(0)
+#endif
+*/
+
 #if idppc
 
 static ID_INLINE float Q_rsqrt( float number ) {
@@ -736,8 +788,6 @@ void RotateVectorAroundVector( vec3_t or
 void MatrixMultiply(float in1[3][3], float in2[3][3], float out[3][3]);
 void AngleVectors( const vec3_t angles, vec3_t forward, vec3_t right, vec3_t up);
 void PerpendicularVector( vec3_t dst, const vec3_t src );
-int Q_isnan( float x );
-
 
 #ifndef MAX
 #define MAX(x,y) ((x)>(y)?(x):(y))
Index: code/qcommon/vm_interpreted.c
===================================================================
--- code/qcommon/vm_interpreted.c.orig
+++ code/qcommon/vm_interpreted.c
@@ -193,9 +193,8 @@ void VM_PrepareInterpreter( vm_t *vm, vm
 
 		op = (int)code[ byte_pc ];
 		codeBase[int_pc] = op;
-		if ( byte_pc > header->codeLength ) {
-			Com_Error( ERR_FATAL, "VM_PrepareInterpreter: pc > header->codeLength" );
-		}
+		if(byte_pc > header->codeLength)
+			Com_Error(ERR_DROP, "VM_PrepareInterpreter: pc > header->codeLength");
 
 		byte_pc++;
 		int_pc++;
@@ -266,6 +265,9 @@ void VM_PrepareInterpreter( vm_t *vm, vm
 		case OP_LEF:
 		case OP_GTF:
 		case OP_GEF:
+			if(codeBase[int_pc] < 0 || codeBase[int_pc] > vm->instructionCount)
+				Com_Error(ERR_DROP, "VM_PrepareInterpreter: Jump to invalid instruction number");
+
 			// codeBase[pc] is the instruction index. Convert that into an offset into
 			//the int-aligned codeBase[] by the lookup table.
 			codeBase[int_pc] = vm->instructionPointers[codeBase[int_pc]];
@@ -313,11 +315,12 @@ locals from sp
 ==============
 */
 
-#define	DEBUGSTR va("%s%i", VM_Indent(vm), opStack-stack )
+#define	DEBUGSTR va("%s%i", VM_Indent(vm), opStackOfs)
 
 int	VM_CallInterpreted( vm_t *vm, int *args ) {
-	int		stack[OPSTACK_SIZE];
-	int		*opStack;
+	byte		stack[OPSTACK_SIZE + 15];
+	register int		*opStack;
+	register uint8_t 	opStackOfs;
 	int		programCounter;
 	int		programStack;
 	int		stackOnEntry;
@@ -346,10 +349,6 @@ int	VM_CallInterpreted( vm_t *vm, int *a
 	codeImage = (int *)vm->codeBase;
 	dataMask = vm->dataMask;
 
-	// leave a free spot at start of stack so
-	// that as long as opStack is valid, opStack-1 will
-	// not corrupt anything
-	opStack = stack;
 	programCounter = 0;
 
 	programStack -= 48;
@@ -369,6 +368,13 @@ int	VM_CallInterpreted( vm_t *vm, int *a
 
 	VM_Debug(0);
 
+	// leave a free spot at start of stack so
+	// that as long as opStack is valid, opStack-1 will
+	// not corrupt anything
+	opStack = PADP(stack, 16);
+	*opStack = 0xDEADBEEF;
+	opStackOfs = 0;
+
 //	vm_debugLevel=2;
 	// main interpreter loop, will exit when a LEAVE instruction
 	// grabs the -1 program counter
@@ -380,27 +386,23 @@ int	VM_CallInterpreted( vm_t *vm, int *a
 //		unsigned int	r2;
 
 nextInstruction:
-		r0 = ((int *)opStack)[0];
-		r1 = ((int *)opStack)[-1];
+		r0 = opStack[opStackOfs];
+		r1 = opStack[(uint8_t) (opStackOfs - 1)];
 nextInstruction2:
 #ifdef DEBUG_VM
 		if ( (unsigned)programCounter >= vm->codeLength ) {
 			Com_Error( ERR_DROP, "VM pc out of range" );
-		}
-
-		if ( opStack < stack ) {
-			Com_Error( ERR_DROP, "VM opStack underflow" );
-		}
-		if ( opStack >= stack+OPSTACK_SIZE ) {
-			Com_Error( ERR_DROP, "VM opStack overflow" );
+			return 0;
 		}
 
 		if ( programStack <= vm->stackBottom ) {
 			Com_Error( ERR_DROP, "VM stack overflow" );
+			return 0;
 		}
 
 		if ( programStack & 3 ) {
 			Com_Error( ERR_DROP, "VM program stack misaligned" );
+			return 0;
 		}
 
 		if ( vm_debugLevel > 1 ) {
@@ -414,79 +416,67 @@ nextInstruction2:
 #ifdef DEBUG_VM
 		default:
 			Com_Error( ERR_DROP, "Bad VM instruction" );  // this should be scanned on load!
+			return 0;
 #endif
 		case OP_BREAK:
 			vm->breakCount++;
 			goto nextInstruction2;
 		case OP_CONST:
-			opStack++;
+			opStackOfs++;
 			r1 = r0;
-			r0 = *opStack = r2;
+			r0 = opStack[opStackOfs] = r2;
 
 			programCounter += 1;
 			goto nextInstruction2;
 		case OP_LOCAL:
-			opStack++;
+			opStackOfs++;
 			r1 = r0;
-			r0 = *opStack = r2+programStack;
+			r0 = opStack[opStackOfs] = r2+programStack;
 
 			programCounter += 1;
 			goto nextInstruction2;
 
 		case OP_LOAD4:
 #ifdef DEBUG_VM
-			if ( *opStack & 3 ) {
+			if(opStack[opStackOfs] & 3)
+			{
 				Com_Error( ERR_DROP, "OP_LOAD4 misaligned" );
+				return 0;
 			}
 #endif
-			r0 = *opStack = *(int *)&image[ r0&dataMask&~3 ];
+			r0 = opStack[opStackOfs] = *(int *) &image[r0 & dataMask & ~3 ];
 			goto nextInstruction2;
 		case OP_LOAD2:
-			r0 = *opStack = *(unsigned short *)&image[ r0&dataMask&~1 ];
+			r0 = opStack[opStackOfs] = *(unsigned short *)&image[ r0&dataMask&~1 ];
 			goto nextInstruction2;
 		case OP_LOAD1:
-			r0 = *opStack = image[ r0&dataMask ];
+			r0 = opStack[opStackOfs] = image[ r0&dataMask ];
 			goto nextInstruction2;
 
 		case OP_STORE4:
 			*(int *)&image[ r1&(dataMask & ~3) ] = r0;
-			opStack -= 2;
+			opStackOfs -= 2;
 			goto nextInstruction;
 		case OP_STORE2:
 			*(short *)&image[ r1&(dataMask & ~1) ] = r0;
-			opStack -= 2;
+			opStackOfs -= 2;
 			goto nextInstruction;
 		case OP_STORE1:
 			image[ r1&dataMask ] = r0;
-			opStack -= 2;
+			opStackOfs -= 2;
 			goto nextInstruction;
 
 		case OP_ARG:
 			// single byte offset from programStack
 			*(int *)&image[ (codeImage[programCounter] + programStack)&dataMask&~3 ] = r0;
-			opStack--;
+			opStackOfs--;
 			programCounter += 1;
 			goto nextInstruction;
 
 		case OP_BLOCK_COPY:
-			{
-				int		*src, *dest;
-				int		count, srci, desti;
-
-				count = r2;
-				// MrE: copy range check
-				srci = r0 & dataMask;
-				desti = r1 & dataMask;
-				count = ((srci + count) & dataMask) - srci;
-				count = ((desti + count) & dataMask) - desti;
-
-				src = (int *)&image[ srci ];
-				dest = (int *)&image[ desti ];
-				
-				memcpy(dest, src, count);
-				programCounter += 1;
-				opStack -= 2;
-			}
+			VM_BlockCopy(r1, r0, r2);
+			programCounter += 1;
+			opStackOfs -= 2;
 			goto nextInstruction;
 
 		case OP_CALL:
@@ -495,7 +485,7 @@ nextInstruction2:
 
 			// jump to the location on the stack
 			programCounter = r0;
-			opStack--;
+			opStackOfs--;
 			if ( programCounter < 0 ) {
 				// system call
 				int		r;
@@ -540,8 +530,8 @@ nextInstruction2:
 #endif
 
 				// save return value
-				opStack++;
-				*opStack = r;
+				opStackOfs++;
+				opStack[opStackOfs] = r;
 				programCounter = *(int *)&image[ programStack ];
 //				vm->callLevel = temp;
 #ifdef DEBUG_VM
@@ -551,6 +541,7 @@ nextInstruction2:
 #endif
 			} else if ( (unsigned)programCounter >= vm->instructionCount ) {
 				Com_Error( ERR_DROP, "VM program counter out of range in OP_CALL" );
+				return 0;
 			} else {
 				programCounter = vm->instructionPointers[ programCounter ];
 			}
@@ -558,10 +549,10 @@ nextInstruction2:
 
 		// push and pop are only needed for discarded or bad function return values
 		case OP_PUSH:
-			opStack++;
+			opStackOfs++;
 			goto nextInstruction;
 		case OP_POP:
-			opStack--;
+			opStackOfs--;
 			goto nextInstruction;
 
 		case OP_ENTER:
@@ -608,6 +599,7 @@ nextInstruction2:
 				goto done;
 			} else if ( (unsigned)programCounter >= vm->codeLength ) {
 				Com_Error( ERR_DROP, "VM program counter out of range in OP_LEAVE" );
+				return 0;
 			}
 			goto nextInstruction;
 
@@ -619,15 +611,18 @@ nextInstruction2:
 
 		case OP_JUMP:
 			if ( (unsigned)r0 >= vm->instructionCount )
+			{
 				Com_Error( ERR_DROP, "VM program counter out of range in OP_JUMP" );
+				return 0;
+			}
 
 			programCounter = vm->instructionPointers[ r0 ];
 
-			opStack--;
+			opStackOfs--;
 			goto nextInstruction;
 
 		case OP_EQ:
-			opStack -= 2;
+			opStackOfs -= 2;
 			if ( r1 == r0 ) {
 				programCounter = r2;	//vm->instructionPointers[r2];
 				goto nextInstruction;
@@ -637,7 +632,7 @@ nextInstruction2:
 			}
 
 		case OP_NE:
-			opStack -= 2;
+			opStackOfs -= 2;
 			if ( r1 != r0 ) {
 				programCounter = r2;	//vm->instructionPointers[r2];
 				goto nextInstruction;
@@ -647,7 +642,7 @@ nextInstruction2:
 			}
 
 		case OP_LTI:
-			opStack -= 2;
+			opStackOfs -= 2;
 			if ( r1 < r0 ) {
 				programCounter = r2;	//vm->instructionPointers[r2];
 				goto nextInstruction;
@@ -657,7 +652,7 @@ nextInstruction2:
 			}
 
 		case OP_LEI:
-			opStack -= 2;
+			opStackOfs -= 2;
 			if ( r1 <= r0 ) {
 				programCounter = r2;	//vm->instructionPointers[r2];
 				goto nextInstruction;
@@ -667,7 +662,7 @@ nextInstruction2:
 			}
 
 		case OP_GTI:
-			opStack -= 2;
+			opStackOfs -= 2;
 			if ( r1 > r0 ) {
 				programCounter = r2;	//vm->instructionPointers[r2];
 				goto nextInstruction;
@@ -677,7 +672,7 @@ nextInstruction2:
 			}
 
 		case OP_GEI:
-			opStack -= 2;
+			opStackOfs -= 2;
 			if ( r1 >= r0 ) {
 				programCounter = r2;	//vm->instructionPointers[r2];
 				goto nextInstruction;
@@ -687,7 +682,7 @@ nextInstruction2:
 			}
 
 		case OP_LTU:
-			opStack -= 2;
+			opStackOfs -= 2;
 			if ( ((unsigned)r1) < ((unsigned)r0) ) {
 				programCounter = r2;	//vm->instructionPointers[r2];
 				goto nextInstruction;
@@ -697,7 +692,7 @@ nextInstruction2:
 			}
 
 		case OP_LEU:
-			opStack -= 2;
+			opStackOfs -= 2;
 			if ( ((unsigned)r1) <= ((unsigned)r0) ) {
 				programCounter = r2;	//vm->instructionPointers[r2];
 				goto nextInstruction;
@@ -707,7 +702,7 @@ nextInstruction2:
 			}
 
 		case OP_GTU:
-			opStack -= 2;
+			opStackOfs -= 2;
 			if ( ((unsigned)r1) > ((unsigned)r0) ) {
 				programCounter = r2;	//vm->instructionPointers[r2];
 				goto nextInstruction;
@@ -717,7 +712,7 @@ nextInstruction2:
 			}
 
 		case OP_GEU:
-			opStack -= 2;
+			opStackOfs -= 2;
 			if ( ((unsigned)r1) >= ((unsigned)r0) ) {
 				programCounter = r2;	//vm->instructionPointers[r2];
 				goto nextInstruction;
@@ -727,68 +722,74 @@ nextInstruction2:
 			}
 
 		case OP_EQF:
-			if ( ((float *)opStack)[-1] == *(float *)opStack ) {
+			opStackOfs -= 2;
+			
+			if(((float *) opStack)[(uint8_t) (opStackOfs + 1)] == ((float *) opStack)[(uint8_t) (opStackOfs + 2)])
+			{
 				programCounter = r2;	//vm->instructionPointers[r2];
-				opStack -= 2;
 				goto nextInstruction;
 			} else {
 				programCounter += 1;
-				opStack -= 2;
 				goto nextInstruction;
 			}
 
 		case OP_NEF:
-			if ( ((float *)opStack)[-1] != *(float *)opStack ) {
+			opStackOfs -= 2;
+
+			if(((float *) opStack)[(uint8_t) (opStackOfs + 1)] != ((float *) opStack)[(uint8_t) (opStackOfs + 2)])
+			{
 				programCounter = r2;	//vm->instructionPointers[r2];
-				opStack -= 2;
 				goto nextInstruction;
 			} else {
 				programCounter += 1;
-				opStack -= 2;
 				goto nextInstruction;
 			}
 
 		case OP_LTF:
-			if ( ((float *)opStack)[-1] < *(float *)opStack ) {
+			opStackOfs -= 2;
+
+			if(((float *) opStack)[(uint8_t) (opStackOfs + 1)] < ((float *) opStack)[(uint8_t) (opStackOfs + 2)])
+			{
 				programCounter = r2;	//vm->instructionPointers[r2];
-				opStack -= 2;
 				goto nextInstruction;
 			} else {
 				programCounter += 1;
-				opStack -= 2;
 				goto nextInstruction;
 			}
 
 		case OP_LEF:
-			if ( ((float *)opStack)[-1] <= *(float *)opStack ) {
+			opStackOfs -= 2;
+
+			if(((float *) opStack)[(uint8_t) ((uint8_t) (opStackOfs + 1))] <= ((float *) opStack)[(uint8_t) ((uint8_t) (opStackOfs + 2))])
+			{
 				programCounter = r2;	//vm->instructionPointers[r2];
-				opStack -= 2;
 				goto nextInstruction;
 			} else {
 				programCounter += 1;
-				opStack -= 2;
 				goto nextInstruction;
 			}
 
 		case OP_GTF:
-			if ( ((float *)opStack)[-1] > *(float *)opStack ) {
+			opStackOfs -= 2;
+
+			if(((float *) opStack)[(uint8_t) (opStackOfs + 1)] > ((float *) opStack)[(uint8_t) (opStackOfs + 2)])
+			{
 				programCounter = r2;	//vm->instructionPointers[r2];
-				opStack -= 2;
 				goto nextInstruction;
 			} else {
 				programCounter += 1;
-				opStack -= 2;
 				goto nextInstruction;
 			}
 
 		case OP_GEF:
-			if ( ((float *)opStack)[-1] >= *(float *)opStack ) {
+			opStackOfs -= 2;
+
+			if(((float *) opStack)[(uint8_t) (opStackOfs + 1)] >= ((float *) opStack)[(uint8_t) (opStackOfs + 2)])
+			{
 				programCounter = r2;	//vm->instructionPointers[r2];
-				opStack -= 2;
 				goto nextInstruction;
 			} else {
 				programCounter += 1;
-				opStack -= 2;
 				goto nextInstruction;
 			}
 
@@ -796,101 +797,101 @@ nextInstruction2:
 		//===================================================================
 
 		case OP_NEGI:
-			*opStack = -r0;
+			opStack[opStackOfs] = -r0;
 			goto nextInstruction;
 		case OP_ADD:
-			opStack[-1] = r1 + r0;
-			opStack--;
+			opStackOfs--;
+			opStack[opStackOfs] = r1 + r0;
 			goto nextInstruction;
 		case OP_SUB:
-			opStack[-1] = r1 - r0;
-			opStack--;
+			opStackOfs--;
+			opStack[opStackOfs] = r1 - r0;
 			goto nextInstruction;
 		case OP_DIVI:
-			opStack[-1] = r1 / r0;
-			opStack--;
+			opStackOfs--;
+			opStack[opStackOfs] = r1 / r0;
 			goto nextInstruction;
 		case OP_DIVU:
-			opStack[-1] = ((unsigned)r1) / ((unsigned)r0);
-			opStack--;
+			opStackOfs--;
+			opStack[opStackOfs] = ((unsigned) r1) / ((unsigned) r0);
 			goto nextInstruction;
 		case OP_MODI:
-			opStack[-1] = r1 % r0;
-			opStack--;
+			opStackOfs--;
+			opStack[opStackOfs] = r1 % r0;
 			goto nextInstruction;
 		case OP_MODU:
-			opStack[-1] = ((unsigned)r1) % (unsigned)r0;
-			opStack--;
+			opStackOfs--;
+			opStack[opStackOfs] = ((unsigned) r1) % ((unsigned) r0);
 			goto nextInstruction;
 		case OP_MULI:
-			opStack[-1] = r1 * r0;
-			opStack--;
+			opStackOfs--;
+			opStack[opStackOfs] = r1 * r0;
 			goto nextInstruction;
 		case OP_MULU:
-			opStack[-1] = ((unsigned)r1) * ((unsigned)r0);
-			opStack--;
+			opStackOfs--;
+			opStack[opStackOfs] = ((unsigned) r1) * ((unsigned) r0);
 			goto nextInstruction;
 
 		case OP_BAND:
-			opStack[-1] = ((unsigned)r1) & ((unsigned)r0);
-			opStack--;
+			opStackOfs--;
+			opStack[opStackOfs] = ((unsigned) r1) & ((unsigned) r0);
 			goto nextInstruction;
 		case OP_BOR:
-			opStack[-1] = ((unsigned)r1) | ((unsigned)r0);
-			opStack--;
+			opStackOfs--;
+			opStack[opStackOfs] = ((unsigned) r1) | ((unsigned) r0);
 			goto nextInstruction;
 		case OP_BXOR:
-			opStack[-1] = ((unsigned)r1) ^ ((unsigned)r0);
-			opStack--;
+			opStackOfs--;
+			opStack[opStackOfs] = ((unsigned) r1) ^ ((unsigned) r0);
 			goto nextInstruction;
 		case OP_BCOM:
-			*opStack = ~ ((unsigned)r0);
+			opStack[opStackOfs] = ~((unsigned) r0);
 			goto nextInstruction;
 
 		case OP_LSH:
-			opStack[-1] = r1 << r0;
-			opStack--;
+			opStackOfs--;
+			opStack[opStackOfs] = r1 << r0;
 			goto nextInstruction;
 		case OP_RSHI:
-			opStack[-1] = r1 >> r0;
-			opStack--;
+			opStackOfs--;
+			opStack[opStackOfs] = r1 >> r0;
 			goto nextInstruction;
 		case OP_RSHU:
-			opStack[-1] = ((unsigned)r1) >> r0;
-			opStack--;
+			opStackOfs--;
+			opStack[opStackOfs] = ((unsigned) r1) >> r0;
 			goto nextInstruction;
 
 		case OP_NEGF:
-			*(float *)opStack =  -*(float *)opStack;
+			((float *) opStack)[opStackOfs] =  -((float *) opStack)[opStackOfs];
 			goto nextInstruction;
 		case OP_ADDF:
-			*(float *)(opStack-1) = *(float *)(opStack-1) + *(float *)opStack;
-			opStack--;
+			opStackOfs--;
+			((float *) opStack)[opStackOfs] = ((float *) opStack)[opStackOfs] + ((float *) opStack)[(uint8_t) (opStackOfs + 1)];
 			goto nextInstruction;
 		case OP_SUBF:
-			*(float *)(opStack-1) = *(float *)(opStack-1) - *(float *)opStack;
-			opStack--;
+			opStackOfs--;
+			((float *) opStack)[opStackOfs] = ((float *) opStack)[opStackOfs] - ((float *) opStack)[(uint8_t) (opStackOfs + 1)];
 			goto nextInstruction;
 		case OP_DIVF:
-			*(float *)(opStack-1) = *(float *)(opStack-1) / *(float *)opStack;
-			opStack--;
+			opStackOfs--;
+			((float *) opStack)[opStackOfs] = ((float *) opStack)[opStackOfs] / ((float *) opStack)[(uint8_t) (opStackOfs + 1)];
 			goto nextInstruction;
 		case OP_MULF:
-			*(float *)(opStack-1) = *(float *)(opStack-1) * *(float *)opStack;
-			opStack--;
+			opStackOfs--;
+			((float *) opStack)[opStackOfs] = ((float *) opStack)[opStackOfs] * ((float *) opStack)[(uint8_t) (opStackOfs + 1)];
 			goto nextInstruction;
 
 		case OP_CVIF:
-			*(float *)opStack =  (float)*opStack;
+			((float *) opStack)[opStackOfs] = (float) opStack[opStackOfs];
 			goto nextInstruction;
 		case OP_CVFI:
-			*opStack = (int) *(float *)opStack;
+			opStack[opStackOfs] = Q_ftol(((float *) opStack)[opStackOfs]);
 			goto nextInstruction;
 		case OP_SEX8:
-			*opStack = (signed char)*opStack;
+			opStack[opStackOfs] = (signed char) opStack[opStackOfs];
 			goto nextInstruction;
 		case OP_SEX16:
-			*opStack = (short)*opStack;
+			opStack[opStackOfs] = (short) opStack[opStackOfs];
 			goto nextInstruction;
 		}
 	}
@@ -898,12 +899,11 @@ nextInstruction2:
 done:
 	vm->currentlyInterpreting = qfalse;
 
-	if ( opStack != &stack[1] ) {
-		Com_Error( ERR_DROP, "Interpreter error: opStack = %ld", (long int) (opStack - stack) );
-	}
+	if (opStackOfs != 1 || *opStack != 0xDEADBEEF)
+		Com_Error(ERR_DROP, "Interpreter error: opStack[0] = %X, opStackOfs = %d", opStack[0], opStackOfs);
 
 	vm->programStack = stackOnEntry;
 
 	// return the result
-	return *opStack;
+	return opStack[opStackOfs];
 }
Index: code/qcommon/vm.c
===================================================================
--- code/qcommon/vm.c.orig
+++ code/qcommon/vm.c
@@ -378,15 +378,20 @@ vmHeader_t *VM_LoadQVM( vm_t *vm, qboole
 	// load the image
 	Com_sprintf( filename, sizeof(filename), "vm/%s.qvm", vm->name );
 	Com_Printf( "Loading vm file %s...\n", filename );
-	length = FS_ReadFile( filename, &header.v );
+
+	length = FS_ReadFileDir(filename, vm->searchPath, &header.v);
+
 	if ( !header.h ) {
 		Com_Printf( "Failed.\n" );
 		VM_Free( vm );
+
+		Com_Printf(S_COLOR_YELLOW "Warning: Couldn't open VM file %s\n", filename);
+
 		return NULL;
 	}
 
 	// show where the qvm was loaded from
-	Cmd_ExecuteString( va( "which %s\n", filename ) );
+	FS_Which(filename, vm->searchPath);
 
 	if( LittleLong( header.h->vmMagic ) == VM_MAGIC_VER2 ) {
 		Com_Printf( "...which has vmMagic VM_MAGIC_VER2\n" );
@@ -401,9 +406,13 @@ vmHeader_t *VM_LoadQVM( vm_t *vm, qboole
 			|| header.h->bssLength < 0
 			|| header.h->dataLength < 0
 			|| header.h->litLength < 0
-			|| header.h->codeLength <= 0 ) {
-			VM_Free( vm );
-			Com_Error( ERR_FATAL, "%s has bad header", filename );
+			|| header.h->codeLength <= 0 )
+		{
+			VM_Free(vm);
+			FS_FreeFile(header.v);
+			
+			Com_Printf(S_COLOR_YELLOW "Warning: %s has bad header\n", filename);
+			return NULL;
 		}
 	} else if( LittleLong( header.h->vmMagic ) == VM_MAGIC ) {
 		// byte swap the header
@@ -416,14 +425,21 @@ vmHeader_t *VM_LoadQVM( vm_t *vm, qboole
 		if ( header.h->bssLength < 0
 			|| header.h->dataLength < 0
 			|| header.h->litLength < 0
-			|| header.h->codeLength <= 0 ) {
-			VM_Free( vm );
-			Com_Error( ERR_FATAL, "%s has bad header", filename );
+			|| header.h->codeLength <= 0 )
+		{
+			VM_Free(vm);
+			FS_FreeFile(header.v);
+
+			Com_Printf(S_COLOR_YELLOW "Warning: %s has bad header\n", filename);
+			return NULL;
 		}
 	} else {
 		VM_Free( vm );
-		Com_Error( ERR_FATAL, "%s does not have a recognisable "
-				"magic number in its header", filename );
+		FS_FreeFile(header.v);
+
+		Com_Printf(S_COLOR_YELLOW "Warning: %s does not have a recognisable "
+				"magic number in its header\n", filename);
+		return NULL;
 	}
 
 	// round up to next power of 2 so all data operations can
@@ -525,7 +541,9 @@ vm_t *VM_Create( const char *module, int
 				vmInterpret_t interpret ) {
 	vm_t		*vm;
 	vmHeader_t	*header;
-	int			i, remaining;
+	int			i, remaining, retval;
+	char filename[MAX_OSPATH];
+	void *startSearch = NULL;
 
 	if ( !module || !module[0] || !systemCalls ) {
 		Com_Error( ERR_FATAL, "VM_Create: bad parms" );
@@ -554,29 +572,45 @@ vm_t *VM_Create( const char *module, int
 
 	vm = &vmTable[i];
 
-	Q_strncpyz( vm->name, module, sizeof( vm->name ) );
-	vm->systemCall = systemCalls;
-
-	if ( interpret == VMI_NATIVE ) {
-		// try to load as a system dll
-		Com_Printf( "Loading dll file %s.\n", vm->name );
-		vm->dllHandle = Sys_LoadDll( module, &vm->entryPoint, VM_DllSyscall );
-		if ( vm->dllHandle ) {
-			return vm;
-		}
-
-		Com_Printf( "Failed to load dll, looking for qvm.\n" );
-		interpret = VMI_COMPILED;
-	}
+	Q_strncpyz(vm->name, module, sizeof(vm->name));
 
-	// load the image
-	if( !( header = VM_LoadQVM( vm, qtrue ) ) ) {
+	do
+	{
+		retval = FS_FindVM(&startSearch, filename, sizeof(filename), module, (interpret == VMI_NATIVE));
+		
+		if(retval == VMI_NATIVE)
+		{
+			Com_Printf("Try loading dll file %s\n", filename);
+
+			vm->dllHandle = Sys_LoadDll(filename, &vm->entryPoint, VM_DllSyscall);
+			
+			if(vm->dllHandle)
+			{
+				vm->systemCall = systemCalls;
+				return vm;
+			}
+			
+			Com_Printf("Failed loading dll, trying next\n");
+		}
+		else if(retval == VMI_COMPILED)
+		{
+			vm->searchPath = startSearch;
+			if((header = VM_LoadQVM(vm, qtrue)))
+				break;
+
+			// VM_Free overwrites the name on failed load
+			Q_strncpyz(vm->name, module, sizeof(vm->name));
+		}
+	} while(retval >= 0);
+	
+	if(retval < 0)
 		return NULL;
-	}
+
+	vm->systemCall = systemCalls;
 
 	// allocate space for the jump targets, which will be filled in by the compile/prep functions
 	vm->instructionCount = header->instructionCount;
-	vm->instructionPointers = Hunk_Alloc( vm->instructionCount*4, h_high );
+	vm->instructionPointers = Hunk_Alloc(vm->instructionCount * sizeof(*vm->instructionPointers), h_high);
 
 	// copy or compile the instructions
 	vm->codeLength = header->codeLength;
@@ -589,7 +623,8 @@ vm_t *VM_Create( const char *module, int
 		interpret = VMI_BYTECODE;
 	}
 #else
-	if ( interpret >= VMI_COMPILED ) {
+	if(interpret != VMI_BYTECODE)
+	{
 		vm->compiled = qtrue;
 		VM_Compile( vm, header );
 	}
@@ -915,3 +950,25 @@ void VM_LogSyscalls( int *args ) {
 	fprintf(f, "%i: %p (%i) = %i %i %i %i\n", callnum, (void*)(args - (int *)currentVM->dataBase),
 		args[0], args[1], args[2], args[3], args[4] );
 }
+
+/*
+=================
+VM_BlockCopy
+Executes a block copy operation within currentVM data space
+=================
+*/
+
+void VM_BlockCopy(unsigned int dest, unsigned int src, size_t n)
+{
+	unsigned int dataMask = currentVM->dataMask;
+
+	if ((dest & dataMask) != dest
+	|| (src & dataMask) != src
+	|| ((dest + n) & dataMask) != dest + n
+	|| ((src + n) & dataMask) != src + n)
+	{
+		Com_Error(ERR_DROP, "OP_BLOCK_COPY out of range!");
+	}
+
+	Com_Memcpy(currentVM->dataBase + dest, currentVM->dataBase + src, n);
+}
Index: code/qcommon/files.c
===================================================================
--- code/qcommon/files.c.orig
+++ code/qcommon/files.c
@@ -218,6 +218,7 @@ typedef struct fileInPack_s {
 } fileInPack_t;
 
 typedef struct {
+        char			pakPathname[MAX_OSPATH];	// c:\quake3\baseq3
 	char			pakFilename[MAX_OSPATH];	// c:\quake3\baseq3\pak0.pk3
 	char			pakBasename[MAX_OSPATH];	// pak0
 	char			pakGamename[MAX_OSPATH];	// baseq3
@@ -233,6 +234,7 @@ typedef struct {
 
 typedef struct {
 	char		path[MAX_OSPATH];		// c:\quake3
+	char		fullpath[MAX_OSPATH];		// c:\quake3\baseq3
 	char		gamedir[MAX_OSPATH];	// baseq3
 } directory_t;
 
@@ -432,7 +434,7 @@ static fileHandle_t	FS_HandleForFile(voi
 }
 
 static FILE	*FS_FileForHandle( fileHandle_t f ) {
-	if ( f < 0 || f > MAX_FILE_HANDLES ) {
+	if ( f < 1 || f > MAX_FILE_HANDLES ) {
 		Com_Error( ERR_DROP, "FS_FileForHandle: out of range" );
 	}
 	if (fsh[f].zipFile == qtrue) {
@@ -454,6 +456,25 @@ void	FS_ForceFlush( fileHandle_t f ) {
 
 /*
 ================
+FS_fplength
+================
+*/
+
+long FS_fplength(FILE *h)
+{
+	long		pos;
+	long		end;
+
+	pos = ftell(h);
+	fseek(h, 0, SEEK_END);
+	end = ftell(h);
+	fseek(h, pos, SEEK_SET);
+
+	return end;
+}
+
+/*
+================
 FS_filelength
 
 If this is called on a non-unique FILE (from a pak file),
@@ -461,18 +482,16 @@ it will return the size of the pak file,
 size of the file.
 ================
 */
-int FS_filelength( fileHandle_t f ) {
-	int		pos;
-	int		end;
-	FILE*	h;
+long FS_filelength(fileHandle_t f)
+{
+	FILE	*h;
 
 	h = FS_FileForHandle(f);
-	pos = ftell (h);
-	fseek (h, 0, SEEK_END);
-	end = ftell (h);
-	fseek (h, pos, SEEK_SET);
-
-	return end;
+	
+	if(h == NULL)
+	        return -1;
+        else
+	        return FS_fplength(h);
 }
 
 /*
@@ -580,7 +599,7 @@ static void FS_CheckFilenameIsNotExecuta
 	if( !Q_stricmp( COM_GetExtension( filename ), DLL_EXT ) )
 	{
 		Com_Error( ERR_FATAL, "%s: Not allowed to manipulate '%s' due "
-			"to %s extension\n", function, filename, DLL_EXT );
+			"to %s extension", function, filename, DLL_EXT );
 	}
 }
 
@@ -611,6 +630,28 @@ void FS_HomeRemove( const char *homePath
 
 /*
 ================
+FS_FileInPathExists
+
+Tests if path and file exists
+================
+*/
+qboolean FS_FileInPathExists(const char *testpath)
+{
+	FILE *filep;
+
+	filep = fopen(testpath, "rb");
+	
+	if(filep)
+	{
+		fclose(filep);
+		return qtrue;
+	}
+	
+	return qfalse;
+}
+
+/*
+================
 FS_FileExists
 
 Tests if the file exists in the current gamedir, this DOES NOT
@@ -619,19 +660,9 @@ search the paths.  This is to determine
 NOTE TTimo: this goes with FS_FOpenFileWrite for opening the file afterwards
 ================
 */
-qboolean FS_FileExists( const char *file )
+qboolean FS_FileExists(const char *file)
 {
-	FILE *f;
-	char *testpath;
-
-	testpath = FS_BuildOSPath( fs_homepath->string, fs_gamedir, file );
-
-	f = fopeni( testpath, "rb" );
-	if (f) {
-		fclose( f );
-		return qtrue;
-	}
-	return qfalse;
+	return FS_FileInPathExists(FS_BuildOSPath(fs_homepath->string, fs_gamedir, file));
 }
 
 /*
@@ -643,18 +674,12 @@ Tests if the file exists
 */
 qboolean FS_SV_FileExists( const char *file )
 {
-	FILE *f;
 	char *testpath;
 
 	testpath = FS_BuildOSPath( fs_homepath->string, file, "");
 	testpath[strlen(testpath)-1] = '\0';
 
-	f = fopeni( testpath, "rb" );
-	if (f) {
-		fclose( f );
-		return qtrue;
-	}
-	return qfalse;
+	return FS_FileInPathExists(testpath);
 }
 
 
@@ -708,7 +733,8 @@ Search for a file somewhere below the ho
 in that order
 ===========
 */
-int FS_SV_FOpenFileRead( const char *filename, fileHandle_t *fp ) {
+long FS_SV_FOpenFileRead(const char *filename, fileHandle_t *fp)
+{
 	char *ospath;
 	fileHandle_t	f = 0;
 
@@ -1081,250 +1107,392 @@ qboolean FS_IsDemoExt(const char *filena
 
 /*
 ===========
-FS_FOpenFileRead
+FS_FOpenFileReadDir
 
-Finds the file in the search path.
+Tries opening file "filename" in searchpath "search"
 Returns filesize and an open FILE pointer.
-Used for streaming data out of either a
-separate file or a ZIP file.
 ===========
 */
 extern qboolean		com_fullyInitialized;
 
-int FS_FOpenFileRead( const char *filename, fileHandle_t *file, qboolean uniqueFILE ) {
-	searchpath_t	*search;
-	char			*netpath;
-	pack_t			*pak;
-	fileInPack_t	*pakFile;
-	directory_t		*dir;
+long FS_FOpenFileReadDir(const char *filename, searchpath_t *search, fileHandle_t *file, qboolean uniqueFILE)
+{
 	long			hash;
-	FILE			*temp;
-	int				l;
-
-	hash = 0;
-
-	if ( !fs_searchpaths ) {
-		Com_Error( ERR_FATAL, "Filesystem call made without initialization" );
-	}
-
-	if ( file == NULL ) {
-		// just wants to see if file is there
-		for ( search = fs_searchpaths ; search ; search = search->next ) {
-			//
-			if ( search->pack ) {
-				hash = FS_HashFileName(filename, search->pack->hashSize);
-			}
-			// is the element a pak file?
-			if ( search->pack && search->pack->hashTable[hash] ) {
-				// look through all the pak file elements
-				pak = search->pack;
-				pakFile = pak->hashTable[hash];
-				do {
-					// case and separator insensitive comparisons
-					if ( !FS_FilenameCompare( pakFile->name, filename ) ) {
-						// found it!
-						return qtrue;
-					}
-					pakFile = pakFile->next;
-				} while(pakFile != NULL);
-			} else if ( search->dir ) {
-				dir = search->dir;
-
-				netpath = FS_BuildOSPath( dir->path, dir->gamedir, filename );
-				temp = fopeni (netpath, "rb");
-				if ( !temp ) {
-					continue;
-				}
-				fclose(temp);
-				return qtrue;
-			}
-		}
-		return qfalse;
-	}
+	pack_t		*pak;
+	fileInPack_t	*pakFile;
+	directory_t	*dir;
+	char		*netpath;
+	FILE		*filep;
+	int			len;
 
-	if ( !filename ) {
-		Com_Error( ERR_FATAL, "FS_FOpenFileRead: NULL 'filename' parameter passed" );
-	}
+	if(filename == NULL)
+		Com_Error(ERR_FATAL, "FS_FOpenFileRead: NULL 'filename' parameter passed");
 
 	// qpaths are not supposed to have a leading slash
-	if ( filename[0] == '/' || filename[0] == '\\' ) {
+	if(filename[0] == '/' || filename[0] == '\\')
 		filename++;
-	}
 
 	// make absolutely sure that it can't back up the path.
 	// The searchpaths do guarantee that something will always
 	// be prepended, so we don't need to worry about "c:" or "//limbo"
-	if ( strstr( filename, ".." ) || strstr( filename, "::" ) ) {
+	if(strstr(filename, ".." ) || strstr(filename, "::"))
+	{
+	        if(file == NULL)
+	                return qfalse;
+	                
 		*file = 0;
 		return -1;
 	}
-
+        
 	// make sure the q3key file is only readable by the quake3.exe at initialization
 	// any other time the key should only be accessed in memory using the provided functions
-	if( com_fullyInitialized && strstr( filename, "q3key" ) ) {
+	if(com_fullyInitialized && strstr(filename, "q3key"))
+	{
+	        if(file == NULL)
+	                return qfalse;
+
 		*file = 0;
 		return -1;
 	}
 
-	//
-	// search through the path, one element at a time
-	//
+	if(file == NULL)
+	{
+		// just wants to see if file is there
+
+		// is the element a pak file?
+		if(search->pack)
+		{
+			hash = FS_HashFileName(filename, search->pack->hashSize);
+                        
+                        if(search->pack->hashTable[hash])
+                        {
+				// look through all the pak file elements
+				pak = search->pack;
+				pakFile = pak->hashTable[hash];
+
+				do
+				{
+					// case and separator insensitive comparisons
+					if(!FS_FilenameCompare(pakFile->name, filename))
+					{
+						// found it!
+						if(pakFile->len)
+        						return pakFile->len;
+                                                else
+                                                {
+                                                        // It's not nice, but legacy code depends
+                                                        // on positive value if file exists no matter
+                                                        // what size
+                                                        return 1;
+                                                }
+					}
+
+					pakFile = pakFile->next;
+				} while(pakFile != NULL);
+			}
+		}
+		else if(search->dir)
+		{
+			dir = search->dir;
+		
+			netpath = FS_BuildOSPath(dir->path, dir->gamedir, filename);
+			filep = fopeni (netpath, "rb");
+
+			if(filep)
+			{
+			        len = FS_fplength(filep);
+				fclose(filep);
+				
+				if(len)
+        				return len;
+                                else
+                                        return 1;
+			}
+		}
+		
+		return 0;
+	}
 
 	*file = FS_HandleForFile();
 	fsh[*file].handleFiles.unique = uniqueFILE;
+	
+	// is the element a pak file?
+	if(search->pack)
+	{
+		hash = FS_HashFileName(filename, search->pack->hashSize);
 
-	for ( search = fs_searchpaths ; search ; search = search->next ) {
-		//
-		if ( search->pack ) {
-			hash = FS_HashFileName(filename, search->pack->hashSize);
-		}
-		// is the element a pak file?
-		if ( search->pack && search->pack->hashTable[hash] ) {
+		if(search->pack->hashTable[hash])
+		{
 			// disregard if it doesn't match one of the allowed pure pak files
-			if ( !FS_PakIsPure(search->pack) ) {
-				continue;
+			if(!FS_PakIsPure(search->pack))
+			{
+				*file = 0;
+				return -1;
 			}
 
 			// look through all the pak file elements
 			pak = search->pack;
 			pakFile = pak->hashTable[hash];
-			do {
+		
+			do
+			{
 				// case and separator insensitive comparisons
-				if ( !FS_FilenameCompare( pakFile->name, filename ) ) {
+				if(!FS_FilenameCompare(pakFile->name, filename))
+				{
 					// found it!
 
 					// mark the pak as having been referenced and mark specifics on cgame and ui
 					// shaders, txt, arena files  by themselves do not count as a reference as 
 					// these are loaded from all pk3s 
 					// from every pk3 file.. 
-					l = strlen(filename);
-					
+					len = strlen(filename);
+
 					if (!(pak->referenced & FS_GENERAL_REF))
 					{
-						if(!FS_IsExt(filename, ".shader", l) &&
-						   !FS_IsExt(filename, ".txt", l) &&
-						   !FS_IsExt(filename, ".cfg", l) &&
-						   !FS_IsExt(filename, ".config", l) &&
-						   !FS_IsExt(filename, ".bot", l) &&
-						   !FS_IsExt(filename, ".arena", l) &&
-						   !FS_IsExt(filename, ".menu", l) &&
+						if(!FS_IsExt(filename, ".shader", len) &&
+						   !FS_IsExt(filename, ".txt", len) &&
+						   !FS_IsExt(filename, ".cfg", len) &&
+						   !FS_IsExt(filename, ".config", len) &&
+						   !FS_IsExt(filename, ".bot", len) &&
+						   !FS_IsExt(filename, ".arena", len) &&
+						   !FS_IsExt(filename, ".menu", len) &&
 						   !strstr(filename, "levelshots"))
 						{
 							pak->referenced |= FS_GENERAL_REF;
 						}
 					}
 
-					if (!(pak->referenced & FS_QAGAME_REF) && strstr(filename, "qagame.qvm")) {
+					if(strstr(filename, "qagame.qvm"))
 						pak->referenced |= FS_QAGAME_REF;
-					}
-					if (!(pak->referenced & FS_CGAME_REF) && strstr(filename, "cgame.qvm")) {
+					if(strstr(filename, "cgame.qvm"))
 						pak->referenced |= FS_CGAME_REF;
-					}
-					if (!(pak->referenced & FS_UI_REF) && strstr(filename, "ui.qvm")) {
+					if(strstr(filename, "ui.qvm"))
 						pak->referenced |= FS_UI_REF;
-					}
 
-					if ( uniqueFILE ) {
+					if(uniqueFILE)
+					{
 						// open a new file on the pakfile
-						fsh[*file].handleFiles.file.z = unzOpen (pak->pakFilename);
-						if (fsh[*file].handleFiles.file.z == NULL) {
-							Com_Error (ERR_FATAL, "Couldn't open %s", pak->pakFilename);
-						}
-					} else {
-						fsh[*file].handleFiles.file.z = pak->handle;
+						fsh[*file].handleFiles.file.z = unzOpen(pak->pakFilename);
+					
+						if(fsh[*file].handleFiles.file.z == NULL)
+							Com_Error(ERR_FATAL, "Couldn't open %s", pak->pakFilename);
 					}
-					Q_strncpyz( fsh[*file].name, filename, sizeof( fsh[*file].name ) );
+					else
+						fsh[*file].handleFiles.file.z = pak->handle;
+
+					Q_strncpyz(fsh[*file].name, filename, sizeof(fsh[*file].name));
 					fsh[*file].zipFile = qtrue;
+				
 					// set the file position in the zip file (also sets the current file info)
 					unzSetOffset(fsh[*file].handleFiles.file.z, pakFile->pos);
+
 					// open the file in the zip
-					unzOpenCurrentFile( fsh[*file].handleFiles.file.z );
+					unzOpenCurrentFile(fsh[*file].handleFiles.file.z);
 					fsh[*file].zipFilePos = pakFile->pos;
 
-					if ( fs_debug->integer ) {
-						Com_Printf( "FS_FOpenFileRead: %s (found in '%s')\n",
-							filename, pak->pakFilename );
+					if(fs_debug->integer)
+					{
+						Com_Printf("FS_FOpenFileRead: %s (found in '%s')\n", 
+							filename, pak->pakFilename);
 					}
+				
 					return pakFile->len;
 				}
+			
 				pakFile = pakFile->next;
 			} while(pakFile != NULL);
-		} else if ( search->dir ) {
-			// check a file in the directory tree
+		}
+	}
+	else if(search->dir)
+	{
+		// check a file in the directory tree
 
-			// if we are running restricted, the only files we
-			// will allow to come from the directory are .cfg files
-			l = strlen( filename );
-			// FIXME TTimo I'm not sure about the fs_numServerPaks test
-			// if you are using FS_ReadFile to find out if a file exists,
-			//   this test can make the search fail although the file is in the directory
-			// I had the problem on https://zerowing.idsoftware.com/bugzilla/show_bug.cgi?id=8
-			// turned out I used FS_FileExists instead
-			if(fs_numServerPaks)
+		// if we are running restricted, the only files we
+		// will allow to come from the directory are .cfg files
+		len = strlen(filename);
+		// FIXME TTimo I'm not sure about the fs_numServerPaks test
+		// if you are using FS_ReadFile to find out if a file exists,
+		//   this test can make the search fail although the file is in the directory
+		// I had the problem on https://zerowing.idsoftware.com/bugzilla/show_bug.cgi?id=8
+		// turned out I used FS_FileExists instead
+		if(fs_numServerPaks)
+		{
+			if(!FS_IsExt(filename, ".cfg", len) &&		// for config files
+			   !FS_IsExt(filename, ".menu", len) &&		// menu files
+			   !FS_IsExt(filename, ".game", len) &&		// menu files
+			   !FS_IsExt(filename, ".cfg", len) &&		// for journal files
+			   !FS_IsDemoExt(filename, len))			// demos
 			{
-				if(!FS_IsExt(filename, ".cfg", l) &&		// for config files
-				   !FS_IsExt(filename, ".menu", l) &&		// menu files
-				   !FS_IsExt(filename, ".game", l) &&		// menu files
-				   !FS_IsExt(filename, ".cfg", l) &&		// for journal files
-				   !FS_IsDemoExt(filename, l))			// demos
-				{
-					continue;
-				}
+				*file = 0;
+				return -1;
 			}
+		}
 
-			dir = search->dir;
+		dir = search->dir;
 
-			netpath = FS_BuildOSPath( dir->path, dir->gamedir, filename );
-			fsh[*file].handleFiles.file.o = fopeni (netpath, "rb");
-			if ( !fsh[*file].handleFiles.file.o ) {
-				continue;
-			}
+		netpath = FS_BuildOSPath(dir->path, dir->gamedir, filename);
+		filep = fopen(netpath, "rb");
 
-			Q_strncpyz( fsh[*file].name, filename, sizeof( fsh[*file].name ) );
-			fsh[*file].zipFile = qfalse;
-			if ( fs_debug->integer ) {
-				Com_Printf( "FS_FOpenFileRead: %s (found in '%s/%s')\n", filename,
-					dir->path, dir->gamedir );
-			}
+		if (filep == NULL)
+		{
+			*file = 0;
+                        return -1;
+		}
+
+		Q_strncpyz(fsh[*file].name, filename, sizeof(fsh[*file].name));
+		fsh[*file].zipFile = qfalse;
+		
+		if(fs_debug->integer)
+		{
+			Com_Printf("FS_FOpenFileRead: %s (found in '%s/%s')\n", filename,
+				dir->path, dir->gamedir);
+		}
+
+		fsh[*file].handleFiles.file.o = filep;
+		return FS_fplength(filep);
+	}
+
+	return -1;
+}
+
+/*
+===========
+FS_FOpenFileRead
+
+Finds the file in the search path.
+Returns filesize and an open FILE pointer.
+Used for streaming data out of either a
+separate file or a ZIP file.
+===========
+*/
+long FS_FOpenFileRead(const char *filename, fileHandle_t *file, qboolean uniqueFILE)
+{
+	searchpath_t *search;
+	long len;
+
+	if(!fs_searchpaths)
+		Com_Error(ERR_FATAL, "Filesystem call made without initialization");
 
-			return FS_filelength (*file);
-		}		
+	for(search = fs_searchpaths; search; search = search->next)
+	{
+	        len = FS_FOpenFileReadDir(filename, search, file, uniqueFILE);
+	        
+	        if(file == NULL)
+	        {
+	                if(len > 0)
+	                        return len;
+	        }
+	        else
+	        {
+	                if(len >= 0 && *file)
+	                        return len;
+	        }
+	        
 	}
 	
 #ifdef FS_MISSING
-	if (missingFiles) {
+	if(missingFiles)
 		fprintf(missingFiles, "%s\n", filename);
-	}
 #endif
-	*file = 0;
+
+        if(file)
+        	*file = 0;
+        	
 	return -1;
 }
 
+/*
+=================
+FS_FindVM
 
-char *FS_FindDll( const char *filename ) {
-	searchpath_t	*search;
-	directory_t		*dir;
+Find a suitable VM file in search path order.
 
-	if ( !fs_searchpaths ) {
-		Com_Error( ERR_FATAL, "Filesystem call made without initialization" );
-	}
+In each searchpath try:
+ - open DLL file if DLL loading enabled
+ - open QVM file
 
-	for ( search = fs_searchpaths ; search ; search = search->next ) {
-		if ( search->dir ) {
-			FILE *f;
-			char *netpath;
+Enable search for DLL by setting enableDll to FSVM_ENABLEDLL
+
+write found DLL or QVM to "found" and return VMI_NATIVE if DLL, VMI_COMPILED if QVM
+Return the searchpath in "startSearch".
+=================
+*/
+
+vmInterpret_t FS_FindVM(void **startSearch, char *found, int foundlen, const char *name, int enableDll)
+{
+	searchpath_t *search, *lastSearch;
+	directory_t *dir;
+	pack_t *pack;
+	char dllName[MAX_OSPATH], qvmName[MAX_OSPATH];
+	char *netpath;
+
+	if(!fs_searchpaths)
+		Com_Error(ERR_FATAL, "Filesystem call made without initialization");
+
+	if(enableDll)
+		Com_sprintf(dllName, sizeof(dllName), "%s" ARCH_STRING DLL_EXT, name);
+		
+	Com_sprintf(qvmName, sizeof(dllName), "vm/%s.qvm", name);
 
+	lastSearch = *startSearch;
+	if(*startSearch == NULL)
+		search = fs_searchpaths;
+	else
+		search = lastSearch->next;
+        
+	while(search)
+	{
+		if(search->dir && !fs_numServerPaks)
+		{
 			dir = search->dir;
-			netpath = FS_BuildOSPath( dir->path, dir->gamedir, filename );
-			f = fopen( netpath, "rb" );
-			if (f) {
-				fclose( f );
-				return netpath;
+
+			if(enableDll)
+			{
+				netpath = FS_BuildOSPath(dir->path, dir->gamedir, dllName);
+
+				if(FS_FileInPathExists(netpath))
+				{
+					Q_strncpyz(found, netpath, foundlen);
+					*startSearch = search;
+					
+					return VMI_NATIVE;
+				}
+			}
+
+			if(FS_FOpenFileReadDir(qvmName, search, NULL, qfalse) > 0)
+			{
+				*startSearch = search;
+				return VMI_COMPILED;
+			}
+		}
+		else if(search->pack)
+		{
+			pack = search->pack;
+
+		        if(lastSearch && lastSearch->pack)
+		        {
+		                // make sure we only try loading one VM file per game dir
+		                // i.e. if VM from pak7.pk3 fails we won't try one from pak6.pk3
+		                
+		                if(!FS_FilenameCompare(lastSearch->pack->pakPathname, pack->pakPathname))
+                                {
+                                        search = search->next;
+                                        continue;
+                                }
+		        }
+
+			if(FS_FOpenFileReadDir(qvmName, search, NULL, qfalse) > 0)
+			{
+				*startSearch = search;
+
+				return VMI_COMPILED;
 			}
 		}
+		
+		search = search->next;
 	}
 
-	return NULL;
+	return -1;
 }
 
 /*
@@ -1493,7 +1661,7 @@ int FS_Seek( fileHandle_t f, long offset
 
 		if( offset < 0 || origin == FS_SEEK_END ) {
 			Com_Error( ERR_FATAL, "Negative offsets and FS_SEEK_END not implemented "
-					"for FS_Seek on pk3 file contents\n" );
+					"for FS_Seek on pk3 file contents" );
 			return -1;
 		}
 
@@ -1611,17 +1779,20 @@ int	FS_FileIsInPAK(const char *filename,
 
 /*
 ============
-FS_ReadFile
+FS_ReadFileDir
 
 Filename are relative to the quake search path
 a null buffer will just return the file length without loading
+If searchPath is non-NULL search only in that specific search path
 ============
 */
-int FS_ReadFile( const char *qpath, void **buffer ) {
+long FS_ReadFileDir(const char *qpath, void *searchPath, void **buffer)
+{
 	fileHandle_t	h;
+	searchpath_t	*search;
 	byte*			buf;
 	qboolean		isConfig;
-	int				len;
+	long				len;
 
 	if ( !fs_searchpaths ) {
 		Com_Error( ERR_FATAL, "Filesystem call made without initialization" );
@@ -1678,8 +1849,19 @@ int FS_ReadFile( const char *qpath, void
 		isConfig = qfalse;
 	}
 
-	// look for it in the filesystem or pack files
-	len = FS_FOpenFileRead( qpath, &h, qfalse );
+	search = searchPath;
+
+	if(search == NULL)
+	{
+		// look for it in the filesystem or pack files
+		len = FS_FOpenFileRead(qpath, &h, qfalse);
+        }
+	else
+	{
+		// look for it in a specific search path only
+		len = FS_FOpenFileReadDir(qpath, search, &h, qfalse);
+	}
+
 	if ( h == 0 ) {
 		if ( buffer ) {
 			*buffer = NULL;
@@ -1727,6 +1909,19 @@ int FS_ReadFile( const char *qpath, void
 }
 
 /*
+============
+FS_ReadFile
+
+Filename are relative to the quake search path
+a null buffer will just return the file length without loading
+============
+*/
+long FS_ReadFile(const char *qpath, void **buffer)
+{
+	return FS_ReadFileDir(qpath, NULL, buffer);
+}
+
+/*
 =============
 FS_FreeFile
 =============
@@ -2582,21 +2777,40 @@ void FS_TouchFile_f( void ) {
 
 /*
 ============
+FS_Which
+============
+*/
+
+qboolean FS_Which(const char *filename, void *searchPath)
+{
+	searchpath_t *search = searchPath;
+
+	if(FS_FOpenFileReadDir(filename, search, NULL, qfalse) > 0)
+	{
+		if(search->pack)
+		{
+			Com_Printf("File \"%s\" found in \"%s\"\n", filename, search->pack->pakFilename);
+			return qtrue;
+		}
+		else if(search->dir)
+		{
+			Com_Printf( "File \"%s\" found at \"%s\"\n", filename, search->dir->fullpath);
+			return qtrue;
+		}
+	}
+
+	return qfalse;
+}
+
+/*
+============
 FS_Which_f
 ============
 */
 void FS_Which_f( void ) {
 	searchpath_t	*search;
-	char			*netpath;
-	pack_t			*pak;
-	fileInPack_t	*pakFile;
-	directory_t		*dir;
-	long			hash;
-	FILE			*temp;
-	char			*filename;
-	char			buf[ MAX_OSPATH ];
+	char		*filename;
 
-	hash = 0;
 	filename = Cmd_Argv(1);
 
 	if ( !filename[0] ) {
@@ -2610,40 +2824,13 @@ void FS_Which_f( void ) {
 	}
 
 	// just wants to see if file is there
-	for ( search = fs_searchpaths ; search ; search = search->next ) {
-		if ( search->pack ) {
-			hash = FS_HashFileName(filename, search->pack->hashSize);
-		}
-		// is the element a pak file?
-		if ( search->pack && search->pack->hashTable[hash] ) {
-			// look through all the pak file elements
-			pak = search->pack;
-			pakFile = pak->hashTable[hash];
-			do {
-				// case and separator insensitive comparisons
-				if ( !FS_FilenameCompare( pakFile->name, filename ) ) {
-					// found it!
-					Com_Printf( "File \"%s\" found in \"%s\"\n", filename, pak->pakFilename );
-					return;
-				}
-				pakFile = pakFile->next;
-			} while(pakFile != NULL);
-		} else if ( search->dir ) {
-			dir = search->dir;
-
-			netpath = FS_BuildOSPath( dir->path, dir->gamedir, filename );
-			temp = fopen (netpath, "rb");
-			if ( !temp ) {
-				continue;
-			}
-			fclose(temp);
-			Com_sprintf( buf, sizeof( buf ), "%s/%s", dir->path, dir->gamedir );
-			FS_ReplaceSeparators( buf );
-			Com_Printf( "File \"%s\" found at \"%s\"\n", filename, buf );
+	for(search = fs_searchpaths; search; search = search->next)
+	{
+		if(FS_Which(filename, search))
 			return;
-		}
 	}
-	Com_Printf( "File not found: \"%s\"\n", filename );
+
+	Com_Printf("File not found: \"%s\"\n", filename);
 	return;
 }
 
@@ -2673,7 +2860,7 @@ void FS_AddGameDirectory( const char *pa
 	int				i;
 	searchpath_t	*search;
 	pack_t			*pak;
-	char			*pakfile;
+	char			curpath[MAX_OSPATH + 1], *pakfile;
 	int				numfiles;
 	char			**pakfiles;
 
@@ -2686,22 +2873,11 @@ void FS_AddGameDirectory( const char *pa
 
 	Q_strncpyz( fs_gamedir, dir, sizeof( fs_gamedir ) );
 
-	//
-	// add the directory to the search path
-	//
-	search = Z_Malloc (sizeof(searchpath_t));
-	search->dir = Z_Malloc( sizeof( *search->dir ) );
-
-	Q_strncpyz( search->dir->path, path, sizeof( search->dir->path ) );
-	Q_strncpyz( search->dir->gamedir, dir, sizeof( search->dir->gamedir ) );
-	search->next = fs_searchpaths;
-	fs_searchpaths = search;
-
 	// find all pak files in this directory
-	pakfile = FS_BuildOSPath( path, dir, "" );
-	pakfile[ strlen(pakfile) - 1 ] = 0;	// strip the trailing slash
+	Q_strncpyz(curpath, FS_BuildOSPath(path, dir, ""), sizeof(curpath));
+	curpath[strlen(curpath) - 1] = '\0';	// strip the trailing slash
 
-	pakfiles = Sys_ListFiles( pakfile, ".pk3", NULL, &numfiles, qfalse );
+	pakfiles = Sys_ListFiles(curpath, ".pk3", NULL, &numfiles, qfalse);
 
 	qsort( pakfiles, numfiles, sizeof(char*), paksort );
 
@@ -2709,8 +2885,10 @@ void FS_AddGameDirectory( const char *pa
 		pakfile = FS_BuildOSPath( path, dir, pakfiles[i] );
 		if ( ( pak = FS_LoadZipFile( pakfile, pakfiles[i] ) ) == 0 )
 			continue;
+
+		Q_strncpyz(pak->pakPathname, curpath, sizeof(pak->pakPathname));
 		// store the game name for downloading
-		strcpy(pak->pakGamename, dir);
+		Q_strncpyz(pak->pakGamename, dir, sizeof(pak->pakGamename));
 
 		fs_packFiles += pak->numfiles;
 
@@ -2722,6 +2900,19 @@ void FS_AddGameDirectory( const char *pa
 
 	// done
 	Sys_FreeFileList( pakfiles );
+
+	//
+	// add the directory to the search path
+	//
+	search = Z_Malloc (sizeof(searchpath_t));
+	search->dir = Z_Malloc( sizeof( *search->dir ) );
+
+	Q_strncpyz(search->dir->path, path, sizeof(search->dir->path));
+	Q_strncpyz(search->dir->fullpath, curpath, sizeof(search->dir->fullpath));
+	Q_strncpyz(search->dir->gamedir, dir, sizeof(search->dir->gamedir));
+
+	search->next = fs_searchpaths;
+	fs_searchpaths = search;
 }
 
 /*
@@ -2807,7 +2998,7 @@ qboolean FS_ComparePaks( char *neededpak
 		// never autodownload any of the id paks
 		if(FS_idPak(fs_serverReferencedPakNames[i], BASEGAME, NUM_ID_PAKS)
 #ifndef STANDALONE
-	           || FS_idPak(fs_serverReferencedPakNames[i], BASETA, NUM_TA_PAKS)
+		   || FS_idPak(fs_serverReferencedPakNames[i], BASETA, NUM_TA_PAKS)
 #endif
 		  )
 		{
@@ -3871,7 +4062,7 @@ void	FS_FilenameCompletion( const char *
 const char *FS_GetCurrentGameDir(void)
 {
 	if(fs_gamedirvar->string[0])
-	        return fs_gamedirvar->string;
+		return fs_gamedirvar->string;
 
-        return com_basegame->string;
+	return com_basegame->string;
 }
Index: code/qcommon/vm_local.h
===================================================================
--- code/qcommon/vm_local.h.orig
+++ code/qcommon/vm_local.h
@@ -25,7 +25,7 @@ Foundation, Inc., 51 Franklin St, Fifth
 
 // don't change, this is hardcoded into x86 VMs, opStack protection relies
 // on this
-#define	OPSTACK_SIZE	256
+#define	OPSTACK_SIZE	1024
 #define	OPSTACK_MASK	(OPSTACK_SIZE-1)
 
 // don't change
@@ -142,7 +142,8 @@ struct vm_s {
 
 	//------------------------------------
 
-    char		name[MAX_QPATH];
+	char		name[MAX_QPATH];
+	void	*searchPath;				// hint for FS_ReadFileDir()
 
 	// for dynamic linked modules
 	void		*dllHandle;
@@ -157,7 +158,7 @@ struct vm_s {
 	int			entryOfs;
 	int			codeLength;
 
-	int			*instructionPointers;
+	intptr_t	*instructionPointers;
 	int			instructionCount;
 
 	byte		*dataBase;
@@ -190,3 +191,5 @@ vmSymbol_t *VM_ValueToFunctionSymbol( vm
 int VM_SymbolToValue( vm_t *vm, const char *symbol );
 const char *VM_ValueToSymbol( vm_t *vm, int value );
 void VM_LogSyscalls( int *args );
+
+void VM_BlockCopy(unsigned int dest, unsigned int src, size_t n);
Index: code/qcommon/vm_x86.c
===================================================================
--- code/qcommon/vm_x86.c.orig
+++ code/qcommon/vm_x86.c
@@ -23,6 +23,7 @@ Foundation, Inc., 51 Franklin St, Fifth
 // vm_x86.c -- load time compiler and execution environment for x86
 
 #include "vm_local.h"
+
 #ifdef _WIN32
 #include <windows.h>
 #endif
@@ -45,12 +46,15 @@ static void VM_Destroy_Compiled(vm_t* se
 
 /*
 
-  eax	scratch
-  ebx	scratch
-  ecx	scratch (required for shifts)
-  edx	scratch (required for divisions)
-  esi	program stack
-  edi	opstack
+  eax		scratch
+  ebx/bl	opStack offset
+  ecx		scratch (required for shifts)
+  edx		scratch (required for divisions)
+  esi		program stack
+  edi   	opStack base
+x86_64:
+  r8		vm->instructionPointers
+  r9		vm->dataBase
 
 */
 
@@ -64,29 +68,6 @@ static	int		pc = 0;
 
 #define FTOL_PTR
 
-#ifdef _MSC_VER
-
-#if defined( FTOL_PTR )
-int _ftol( float );
-static	int		ftolPtr = (int)_ftol;
-#endif
-
-#else // _MSC_VER
-
-#if defined( FTOL_PTR )
-
-int qftol( void );
-int qftol027F( void );
-int qftol037F( void );
-int qftol0E7F( void );
-int qftol0F7F( void );
-
-
-static	int		ftolPtr = (int)qftol0F7F;
-#endif // FTOL_PTR
-
-#endif
-
 static	int	instruction, pass;
 static	int	lastConst = 0;
 static	int	oc0, oc1, pop0, pop1;
@@ -95,20 +76,30 @@ static	int jlabel;
 typedef enum
 {
 	LAST_COMMAND_NONE	= 0,
-	LAST_COMMAND_MOV_EDI_EAX,
-	LAST_COMMAND_SUB_DI_4,
-	LAST_COMMAND_SUB_DI_8,
+	LAST_COMMAND_MOV_STACK_EAX,
+	LAST_COMMAND_SUB_BL_1,
+	LAST_COMMAND_SUB_BL_2,
 } ELastCommand;
 
+typedef enum
+{
+	VM_JMP_VIOLATION = 0,
+	VM_BLOCK_COPY = 1
+} ESysCallType;
+
 static	ELastCommand	LastCommand;
 
-static void ErrJump( void ) 
-{ 
-	Com_Error( ERR_DROP, "program tried to execute code outside VM\n" ); 
-	exit(1);
+static int iss8(int32_t v)
+{
+	return (SCHAR_MIN <= v && v <= SCHAR_MAX);
 }
 
-static void (*const errJumpPtr)(void) = ErrJump;
+#if 0
+static int isu8(uint32_t v)
+{
+	return (v <= UCHAR_MAX);
+}
+#endif
 
 static int NextConstant4(void)
 {
@@ -139,18 +130,32 @@ static void Emit1( int v )
 	LastCommand = LAST_COMMAND_NONE;
 }
 
-#if 0
-static void Emit2( int v ) {
-	Emit1( v & 255 );
-	Emit1( ( v >> 8 ) & 255 );
+static void Emit2(int v)
+{
+	Emit1(v & 255);
+	Emit1((v >> 8) & 255);
 }
-#endif
 
-static void Emit4( int v ) {
-	Emit1( v & 255 );
-	Emit1( ( v >> 8 ) & 255 );
-	Emit1( ( v >> 16 ) & 255 );
-	Emit1( ( v >> 24 ) & 255 );
+
+static void Emit4(int v)
+{
+	Emit1(v & 0xFF);
+	Emit1((v >> 8) & 0xFF);
+	Emit1((v >> 16) & 0xFF);
+	Emit1((v >> 24) & 0xFF);
+}
+
+static void EmitPtr(void *ptr)
+{
+	intptr_t v = (intptr_t) ptr;
+	
+	Emit4(v);
+#if idx64
+	Emit1((v >> 32) & 0xFF);
+	Emit1((v >> 40) & 0xFF);
+	Emit1((v >> 48) & 0xFF);
+	Emit1((v >> 56) & 0xFF);
+#endif
 }
 
 static int Hex( int c ) {
@@ -186,23 +191,46 @@ static void EmitString( const char *stri
 		string += 3;
 	}
 }
+static void EmitRexString(byte rex, const char *string)
+{
+#if idx64
+	if(rex)
+		Emit1(rex);
+#endif
+
+	EmitString(string);
+}
 
 
+#define MASK_REG(modrm, mask) \
+	EmitString("81"); \
+	EmitString((modrm)); \
+	Emit4((mask))
+
+// add bl, bytes
+#define STACK_PUSH(bytes) \
+	EmitString("80 C3"); \
+	Emit1(bytes)
+
+// sub bl, bytes
+#define STACK_POP(bytes) \
+	EmitString("80 EB"); \
+	Emit1(bytes)
 
 static void EmitCommand(ELastCommand command)
 {
 	switch(command)
 	{
-		case LAST_COMMAND_MOV_EDI_EAX:
-			EmitString( "89 07" );		// mov dword ptr [edi], eax
+		case LAST_COMMAND_MOV_STACK_EAX:
+			EmitString("89 04 9F");		// mov dword ptr [edi + ebx * 4], eax
 			break;
 
-		case LAST_COMMAND_SUB_DI_4:
-			EmitString( "83 EF 04" );	// sub edi, 4
+		case LAST_COMMAND_SUB_BL_1:
+			STACK_POP(1);			// sub bl, 1
 			break;
 
-		case LAST_COMMAND_SUB_DI_8:
-			EmitString( "83 EF 08" );	// sub edi, 8
+		case LAST_COMMAND_SUB_BL_2:
+			STACK_POP(2);			// sub bl, 2
 			break;
 		default:
 			break;
@@ -210,115 +238,133 @@ static void EmitCommand(ELastCommand com
 	LastCommand = command;
 }
 
-static void EmitAddEDI4( vm_t *vm ) {
-	if ( jlabel ) {
-		EmitString( "83 C7 04" );	//	add edi,4
-		return;
-	}
-	if ( LastCommand == LAST_COMMAND_SUB_DI_4 ) 
-	{	// sub edi, 4
-		compiledOfs -= 3;
-		vm->instructionPointers[ instruction-1 ] = compiledOfs;
-		return;
-	}
-	if ( LastCommand == LAST_COMMAND_SUB_DI_8 ) 
-	{	// sub edi, 8
-		compiledOfs -= 3;
-		vm->instructionPointers[ instruction-1 ] = compiledOfs;
-		EmitString( "83 EF 04" );	//	sub edi,4
-		return;
-	}
-	EmitString( "83 C7 04" );	//	add edi,4
-}
-
-static void EmitMovEAXEDI(vm_t *vm) {
-	if ( jlabel ) {
-		EmitString( "8B 07" );		// mov eax, dword ptr [edi]
-		return;
-	}
-	if (LastCommand == LAST_COMMAND_MOV_EDI_EAX) 
-	{	// mov [edi], eax
-		compiledOfs -= 2;
-		vm->instructionPointers[ instruction-1 ] = compiledOfs;
-		return;
-	}
-	if (pop1 == OP_DIVI || pop1 == OP_DIVU || pop1 == OP_MULI || pop1 == OP_MULU ||
-		pop1 == OP_STORE4 || pop1 == OP_STORE2 || pop1 == OP_STORE1 ) 
-	{	
-		return;
-	}
-	if (pop1 == OP_CONST && buf[compiledOfs-6] == 0xC7 && buf[compiledOfs-5] == 0x07 ) 
-	{	// mov edi, 0x123456
-		compiledOfs -= 6;
-		vm->instructionPointers[ instruction-1 ] = compiledOfs;
-		EmitString( "B8" );			// mov	eax, 0x12345678
-		Emit4( lastConst );
-		return;
-	}
-	EmitString( "8B 07" );		    // mov eax, dword ptr [edi]
-}
-
-void EmitMovECXEDI( vm_t *vm ) {
-	if ( jlabel ) {
-		EmitString( "8B 0F" );		// mov ecx, dword ptr [edi]
-		return;
-	}
-	if ( LastCommand == LAST_COMMAND_MOV_EDI_EAX ) // mov [edi], eax
+static void EmitPushStack(vm_t *vm)
+{
+	if (!jlabel)
 	{
-		compiledOfs -= 2;
-		vm->instructionPointers[ instruction-1 ] = compiledOfs;
-		EmitString( "89 C1" );		// mov ecx, eax
-		return;
-	}
-	if (pop1 == OP_DIVI || pop1 == OP_DIVU || pop1 == OP_MULI || pop1 == OP_MULU ||
-		pop1 == OP_STORE4 || pop1 == OP_STORE2 || pop1 == OP_STORE1 ) 
-	{	
-		EmitString( "89 C1" );		// mov ecx, eax
-		return;
+		if(LastCommand == LAST_COMMAND_SUB_BL_1)
+		{	// sub bl, 1
+			compiledOfs -= 3;
+			vm->instructionPointers[instruction - 1] = compiledOfs;
+			return;
+		}
+		if(LastCommand == LAST_COMMAND_SUB_BL_2)
+		{	// sub bl, 2
+			compiledOfs -= 3;
+			vm->instructionPointers[instruction - 1] = compiledOfs;
+			STACK_POP(1);		//	sub bl, 1
+			return;
+		}
 	}
-	EmitString( "8B 0F" );		    // mov ecx, dword ptr [edi]
-}
 
+	STACK_PUSH(1);		// add bl, 1
+}
 
-qboolean EmitMovEBXEDI(vm_t *vm, int andit) {
-	if ( jlabel ) {
-		EmitString( "8B 1F" );		// mov ebx, dword ptr [edi]
-		return qfalse;
-	}
-	if ( LastCommand == LAST_COMMAND_MOV_EDI_EAX ) 
-	{	// mov dword ptr [edi], eax
-		compiledOfs -= 2;
-		vm->instructionPointers[ instruction-1 ] = compiledOfs;
-		EmitString( "8B D8");		// mov bx, eax
-		return qfalse;
+static void EmitMovEAXStack(vm_t *vm, int andit)
+{
+	if(!jlabel)
+	{
+		if(LastCommand == LAST_COMMAND_MOV_STACK_EAX) 
+		{	// mov [edi + ebx * 4], eax
+			compiledOfs -= 3;
+			vm->instructionPointers[instruction - 1] = compiledOfs;
+		}
+		else if(pop1 == OP_CONST && buf[compiledOfs-7] == 0xC7 && buf[compiledOfs-6] == 0x04 && buf[compiledOfs - 5] == 0x9F)
+		{	// mov [edi + ebx * 4], 0x12345678
+			compiledOfs -= 7;
+			vm->instructionPointers[instruction - 1] = compiledOfs;
+			EmitString("B8");	// mov	eax, 0x12345678
+
+			if(andit)
+				Emit4(lastConst & andit);
+			else
+				Emit4(lastConst);
+			
+			return;
+		}
+		else if(pop1 != OP_DIVI && pop1 != OP_DIVU && pop1 != OP_MULI && pop1 != OP_MULU &&
+			pop1 != OP_STORE4 && pop1 != OP_STORE2 && pop1 != OP_STORE1)
+		{	
+			EmitString("8B 04 9F");	// mov eax, dword ptr [edi + ebx * 4]
+		}
 	}
-	if ( pop1 == OP_DIVI || pop1 == OP_DIVU || pop1 == OP_MULI || pop1 == OP_MULU ||
-		pop1 == OP_STORE4 || pop1 == OP_STORE2 || pop1 == OP_STORE1 ) 
-	{	
-		EmitString( "8B D8");		// mov bx, eax
-		return qfalse;
+	else
+		EmitString("8B 04 9F");		// mov eax, dword ptr [edi + ebx * 4]
+
+	if(andit)
+	{
+		EmitString("25");		// and eax, 0x12345678
+		Emit4(andit);
 	}
-	if ( pop1 == OP_CONST && buf[compiledOfs-6] == 0xC7 && buf[compiledOfs-5] == 0x07 ) 
-	{	// mov dword ptr [edi], 0x12345678
-		compiledOfs -= 6;
-		vm->instructionPointers[ instruction-1 ] = compiledOfs;
-		EmitString( "BB" );			// mov	ebx, 0x12345678
-		if (andit) {
-			Emit4( lastConst & andit );
-		} else {
-			Emit4( lastConst );
+}
+
+void EmitMovECXStack(vm_t *vm)
+{
+	if(!jlabel)
+	{
+		if(LastCommand == LAST_COMMAND_MOV_STACK_EAX) // mov [edi + ebx * 4], eax
+		{
+			compiledOfs -= 3;
+			vm->instructionPointers[instruction - 1] = compiledOfs;
+			EmitString("89 C1");		// mov ecx, eax
+			return;
+		}
+		if(pop1 == OP_DIVI || pop1 == OP_DIVU || pop1 == OP_MULI || pop1 == OP_MULU ||
+			pop1 == OP_STORE4 || pop1 == OP_STORE2 || pop1 == OP_STORE1) 
+		{	
+			EmitString("89 C1");		// mov ecx, eax
+			return;
 		}
-		return qtrue;
 	}
 
-	EmitString( "8B 1F" );		    // mov ebx, dword ptr [edi]
-	return qfalse;
+	EmitString("8B 0C 9F");		// mov ecx, dword ptr [edi + ebx * 4]
+}
+
+
+void EmitMovEDXStack(vm_t *vm, int andit)
+{
+	if(!jlabel)
+	{
+		if(LastCommand == LAST_COMMAND_MOV_STACK_EAX)
+		{	// mov dword ptr [edi + ebx * 4], eax
+			compiledOfs -= 3;
+			vm->instructionPointers[instruction - 1] = compiledOfs;
+
+			EmitString("8B D0");	// mov edx, eax
+		}
+		else if(pop1 == OP_DIVI || pop1 == OP_DIVU || pop1 == OP_MULI || pop1 == OP_MULU ||
+			pop1 == OP_STORE4 || pop1 == OP_STORE2 || pop1 == OP_STORE1)
+		{	
+			EmitString("8B D0");	// mov edx, eax
+		}
+		else if(pop1 == OP_CONST && buf[compiledOfs-7] == 0xC7 && buf[compiledOfs-6] == 0x07 && buf[compiledOfs - 5] == 0x9F)
+		{	// mov dword ptr [edi + ebx * 4], 0x12345678
+			compiledOfs -= 7;
+			vm->instructionPointers[instruction - 1] = compiledOfs;
+			EmitString("BA");		// mov edx, 0x12345678
+
+			if(andit)
+				Emit4(lastConst & andit);
+			else
+				Emit4(lastConst);
+			
+			return;
+		}
+		else
+			EmitString("8B 14 9F");	// mov edx, dword ptr [edi + ebx * 4]
+		
+	}
+	else
+		EmitString("8B 14 9F");		// mov edx, dword ptr [edi + ebx * 4]
+	
+	if(andit)
+		MASK_REG("E2", andit);		// and edx, 0x12345678
 }
 
 #define JUSED(x) \
 	do { \
-		if (x < 0 || x >= jusedSize) { \
-		        VMFREE_BUFFERS(); \
+		if (x < 0 || x >= vm->instructionCount) { \
+			VMFREE_BUFFERS(); \
 			Com_Error( ERR_DROP, \
 					"VM_CompileX86: jump target out of range at offset %d", pc ); \
 		} \
@@ -327,67 +373,213 @@ qboolean EmitMovEBXEDI(vm_t *vm, int and
 
 #define SET_JMPOFS(x) do { buf[(x)] = compiledOfs - ((x) + 1); } while(0)
 
+
+/*
+=================
+ErrJump
+Error handler for jump/call to invalid instruction number
+=================
+*/
+
+static void ErrJump(void)
+{ 
+	Com_Error(ERR_DROP, "program tried to execute code outside VM");
+	exit(1);
+}
+
 /*
 =================
 DoSyscall
-Uses asm to get arguments from stack to work around different calling conventions
+Uses asm to retrieve arguments from registers to work around different calling conventions
 =================
 */
 
+#if defined(_MSC_VER) && idx64
+
+extern void qsyscall64(void);
+extern uint8_t qvmcall64(int *programStack, int *opStack, intptr_t *instructionPointers, byte *dataBase);
+
+// Microsoft does not support inline assembler on x64 platforms. Meh.
+void DoSyscall(int syscallNum, int programStack, int *opStackBase, uint8_t opStackOfs, intptr_t arg)
+{
+#else
 static void DoSyscall(void)
 {
-        vm_t *savedVM;
-	int *data;
-
 	int syscallNum;
 	int programStack;
-	int *opStack;
-	
-	// Get arguments directly from registers to work around different calling conventions
+	int *opStackBase;
+	uint8_t opStackOfs;
+	intptr_t arg;
+#endif
+
+	vm_t *savedVM;
+
 #ifdef _MSC_VER
+  #ifndef idx64
 	__asm
 	{
-		mov		dword ptr syscallNum, eax
-		mov		dword ptr programStack, esi
-		mov		dword ptr opStack, edi
+		mov	dword ptr syscallNum, eax
+		mov	dword ptr programStack, esi
+		mov	byte ptr opStackOfs, bl
+		mov	dword ptr opStackBase, edi
+		mov	dword ptr arg, ecx
 	}
+  #endif
 #else
 	__asm__ volatile(
 		""
-		: "=a" (syscallNum), "=S" (programStack), "=D" (opStack)
-		:
-		: "memory"
+		: "=a" (syscallNum), "=S" (programStack), "=D" (opStackBase), "=b" (opStackOfs),
+		  "=c" (arg)
 		);
 #endif
 
-	// save currentVM so as to allow for recursive VM entry
-	savedVM = currentVM;
-	data = (int *) (savedVM->dataBase + programStack + 4);
-
-	// modify VM stack pointer for recursive VM entry
-	savedVM->programStack = programStack - 4;
-	*data = syscallNum;
-	opStack[1] = savedVM->systemCall(data);
+	if(syscallNum < 0)
+	{
+		int *data;
+#if idx64
+		int index;
+		intptr_t args[11];
+#endif
+		
+		// save currentVM so as to allow for recursive VM entry
+		savedVM = currentVM;
+		data = (int *) (savedVM->dataBase + programStack + 4);
+
+		// modify VM stack pointer for recursive VM entry
+		savedVM->programStack = programStack - 4;
+
+#if idx64
+		args[0] = ~syscallNum;
+		for(index = 1; index < ARRAY_LEN(args); index++)
+			args[index] = data[index];
+			
+		opStackBase[opStackOfs + 1] = savedVM->systemCall(args);
+#else
+		data[0] = ~syscallNum;
+		opStackBase[opStackOfs + 1] = savedVM->systemCall(data);
+#endif
+
+		currentVM = savedVM;
+	}
+	else
+	{
+		switch(syscallNum)
+		{
+		case VM_JMP_VIOLATION:
+			ErrJump();
+		break;
+		case VM_BLOCK_COPY: 
+			if(opStackOfs < 1)
+				Com_Error(ERR_DROP, "VM_BLOCK_COPY failed due to corrupted opStack");
+			
+			VM_BlockCopy(opStackBase[(opStackOfs - 1)], opStackBase[opStackOfs], arg);
+		break;
+		default:
+			Com_Error(ERR_DROP, "Unknown VM operation %d", syscallNum);
+		break;
+		}
+	}
+}
 
-	currentVM = savedVM;
+/*
+=================
+EmitCallRel
+Relative call to vm->codeBase + callOfs
+=================
+*/
+
+void EmitCallRel(vm_t *vm, int callOfs)
+{
+	EmitString("E8");			// call 0x12345678
+	Emit4(callOfs - compiledOfs - 4);
+}
+
+/*
+=================
+EmitCallDoSyscall
+Call to DoSyscall()
+=================
+*/
+
+int EmitCallDoSyscall(vm_t *vm)
+{
+	// use edx register to store DoSyscall address
+#if defined(_MSC_VER) && idx64
+	EmitRexString(0x48, "BA");		// mov edx, qsyscall64
+	EmitPtr(qsyscall64);
+#else
+	EmitRexString(0x48, "BA");		// mov edx, DoSyscall
+	EmitPtr(DoSyscall);
+#endif
+
+	// Push important registers to stack as we can't really make
+	// any assumptions about calling conventions.
+	EmitString("51");			// push ebx
+	EmitString("56");			// push esi
+	EmitString("57");			// push edi
+#if idx64
+	EmitRexString(0x41, "50");		// push r8
+	EmitRexString(0x41, "51");		// push r9
+#endif
+
+	// align the stack pointer to a 16-byte-boundary
+	EmitString("55");			// push ebp
+	EmitRexString(0x48, "89 E5");		// mov ebp, esp
+	EmitRexString(0x48, "83 E4 F0");	// and esp, 0xFFFFFFF0
+			
+	// call the syscall wrapper function DoSyscall()
+
+	EmitString("FF D2");			// call edx
+
+	// reset the stack pointer to its previous value
+	EmitRexString(0x48, "89 EC");		// mov esp, ebp
+	EmitString("5D");			// pop ebp
+
+#if idx64
+	EmitRexString(0x41, "59");		// pop r9
+	EmitRexString(0x41, "58");		// pop r8
+#endif
+	EmitString("5F");			// pop edi
+	EmitString("5E");			// pop esi
+	EmitString("59");			// pop ebx
+
+	EmitString("C3");			// ret
+
+	return compiledOfs;
+}
+
+/*
+=================
+EmitCallErrJump
+Emit the code that triggers execution of the jump violation handler
+=================
+*/
+
+static void EmitCallErrJump(vm_t *vm, int sysCallOfs)
+{
+	EmitString("B8");			// mov eax, 0x12345678
+	Emit4(VM_JMP_VIOLATION);
+
+	EmitCallRel(vm, sysCallOfs);
 }
 
 /*
 =================
 EmitCallProcedure
+VM OP_CALL procedure for call destinations obtained at runtime
 =================
 */
 
-int EmitCallProcedure(vm_t *vm)
+int EmitCallProcedure(vm_t *vm, int sysCallOfs)
 {
 	int jmpSystemCall, jmpBadAddr;
 	int retval;
 
-	EmitString("8B 07");		// mov eax, dword ptr [edi]
-	EmitString("83 EF 04");		// sub edi, 4
+	EmitString("8B 04 9F");		// mov eax, dword ptr [edi + ebx * 4]
+	STACK_POP(1);			// sub bl, 1
 	EmitString("85 C0");		// test eax, eax
 
-	// Jump to syscall code
+	// Jump to syscall code, 1 byte offset should suffice
 	EmitString("7C");		// jl systemCall
 	jmpSystemCall = compiledOfs++;
 		
@@ -399,17 +591,19 @@ int EmitCallProcedure(vm_t *vm)
 	// Error jump if invalid jump target
 	EmitString("73");		// jae badAddr
 	jmpBadAddr = compiledOfs++;
-		
-	EmitString("FF 14 85");		// call dword ptr [vm->instructionPointers + eax * 4]
+
+#if idx64
+	EmitRexString(0x49, "FF 14 C0");	// call qword ptr [r8 + eax * 8]
+#else
+	EmitString("FF 14 85");			// call dword ptr [vm->instructionPointers + eax * 4]
 	Emit4((intptr_t) vm->instructionPointers);
-	EmitString("8B 07");		// mov eax, dword ptr [edi]
-	EmitString("C3");		// ret
+#endif
+	EmitString("8B 04 9F");			// mov eax, dword ptr [edi + ebx * 4]
+	EmitString("C3");			// ret
 		
 	// badAddr:
 	SET_JMPOFS(jmpBadAddr);
-	EmitString("B8");		// mov eax, ErrJump
-	Emit4((intptr_t) ErrJump);
-	EmitString("FF D0");		// call eax
+	EmitCallErrJump(vm, sysCallOfs);
 
 	/************ System Call ************/
 	
@@ -417,74 +611,115 @@ int EmitCallProcedure(vm_t *vm)
 	SET_JMPOFS(jmpSystemCall);
 	retval = compiledOfs;
 
-	EmitString("F7 D0");		// not eax
-	// use ecx register to store DoSyscall address
-	EmitString("B9");		// mov ecx, DoSyscall
-	Emit4((intptr_t) DoSyscall);
-
-	// align the stack pointer to a 16-byte-boundary
-	EmitString("55");		// push ebp
-	EmitString("89 E5");		// mov ebp, esp
-	EmitString("83 E4 F0");		// and esp, 0xFFFFFFF0
-			
-	// call the syscall wrapper function
-	EmitString("FF D1");		// call ecx
-
-	// reset the stack pointer to its previous value
-	EmitString("89 EC");		// mov esp, ebp
-	EmitString("5D");		// pop ebp
+	EmitCallRel(vm, sysCallOfs);
 
 	// have opStack reg point at return value
-	EmitString("83 C7 04");		// add edi, 4
+	STACK_PUSH(1);			// add bl, 1
 	EmitString("C3");		// ret
 
 	return retval;
 }
 
-void EmitCall(vm_t *vm, int sysCallOfs)
+/*
+=================
+EmitJumpIns
+Jump to constant instruction number
+=================
+*/
+
+void EmitJumpIns(vm_t *vm, const char *jmpop, int cdest)
 {
-       	EmitString("51");	// push ecx
-       	EmitString("8B 0D");	// mov ecx, dword ptr [&vm->codeBase]
-       	Emit4((intptr_t) &vm->codeBase);
-
-       	if(sysCallOfs)
-       	{
-	       	if(sysCallOfs < 0x80 || sysCallOfs > 0x7f)
-	       	{
-		       	EmitString("83 C1");	// add ecx, sysCallOfs
-		       	Emit1(sysCallOfs);
-		}
-		else
-		{
-			EmitString("81 C1");	// add ecx, sysCallOfs
-			Emit4(sysCallOfs);
-		}
-	}
+	JUSED(cdest);
+
+	EmitString(jmpop);	// j??? 0x12345678
+
+	// we only know all the jump addresses in the third pass
+	if(pass == 2)
+		Emit4(vm->instructionPointers[cdest] - compiledOfs - 4);
+	else
+		compiledOfs += 4;
+}
+
+/*
+=================
+EmitCallIns
+Call to constant instruction number
+=================
+*/
 
-	EmitString("FF D1");	// call ecx
-	EmitString("59");	// pop ecx
+void EmitCallIns(vm_t *vm, int cdest)
+{
+	JUSED(cdest);
+
+	EmitString("E8");	// call 0x12345678
+
+	// we only know all the jump addresses in the third pass
+	if(pass == 2)
+		Emit4(vm->instructionPointers[cdest] - compiledOfs - 4);
+	else
+		compiledOfs += 4;
 }
 
 /*
 =================
 EmitCallConst
+Call to constant instruction number or syscall
 =================
 */
 
-void EmitCallConst(vm_t *vm, int cdest, int sysCallOfs)
+void EmitCallConst(vm_t *vm, int cdest, int callProcOfsSyscall)
 {
 	if(cdest < 0)
 	{
 		EmitString("B8");	// mov eax, cdest
 		Emit4(cdest);
 
-		EmitCall(vm, sysCallOfs);
+		EmitCallRel(vm, callProcOfsSyscall);
 	}
 	else
+		EmitCallIns(vm, cdest);
+}
+
+/*
+=================
+EmitBranchConditions
+Emits x86 branch condition as given in op
+=================
+*/
+void EmitBranchConditions(vm_t *vm, int op)
+{
+	switch(op)
 	{
-			JUSED(cdest);
-			EmitString("FF 15");	// call dword ptr [vm->instructionPointers + cdest]
-			Emit4((intptr_t) &vm->instructionPointers[cdest]);
+	case OP_EQ:
+		EmitJumpIns(vm, "0F 84", Constant4());	// je 0x12345678
+	break;
+	case OP_NE:
+		EmitJumpIns(vm, "0F 85", Constant4());	// jne 0x12345678
+	break;
+	case OP_LTI:
+		EmitJumpIns(vm, "0F 8C", Constant4());	// jl 0x12345678
+	break;
+	case OP_LEI:
+		EmitJumpIns(vm, "0F 8E", Constant4());	// jle 0x12345678
+	break;
+	case OP_GTI:
+		EmitJumpIns(vm, "0F 8F", Constant4());	// jg 0x12345678
+	break;
+	case OP_GEI:
+		EmitJumpIns(vm, "0F 8D", Constant4());	// jge 0x12345678
+	break;
+	case OP_LTU:
+		EmitJumpIns(vm, "0F 82", Constant4());	// jb 0x12345678
+	break;
+	case OP_LEU:
+		EmitJumpIns(vm, "0F 86", Constant4());	// jbe 0x12345678
+	break;
+	case OP_GTU:
+		EmitJumpIns(vm, "0F 87", Constant4());	// ja 0x12345678
+	break;
+	case OP_GEU:
+		EmitJumpIns(vm, "0F 83", Constant4());	// jae 0x12345678
+	break;
 	}
 }
 
@@ -492,11 +727,14 @@ void EmitCallConst(vm_t *vm, int cdest,
 /*
 =================
 ConstOptimize
+Constant values for immediately following instructions may be translated to immediate values
+instead of opStack operations, which will save expensive operations on memory
 =================
 */
-qboolean ConstOptimize(vm_t *vm, int sysCallOfs)
+
+qboolean ConstOptimize(vm_t *vm, int callProcOfsSyscall)
 {
-	int v, opt;
+	int v;
 	int op1;
 
 	// we can safely perform optimizations only in case if 
@@ -509,302 +747,314 @@ qboolean ConstOptimize(vm_t *vm, int sys
 	switch ( op1 ) {
 
 	case OP_LOAD4:
-		EmitAddEDI4(vm);
-		EmitString( "BB" );         // mov ebx, 0x12345678
-		Emit4( (Constant4()&vm->dataMask) + (int)vm->dataBase);
-		EmitString( "8B 03" );      // mov eax, dword ptr [ebx]
-		EmitCommand(LAST_COMMAND_MOV_EDI_EAX); // mov dword ptr [edi], eax
+		EmitPushStack(vm);
+#if idx64
+		EmitRexString(0x41, "8B 81");			// mov eax, dword ptr [r9 + 0x12345678]
+		Emit4(Constant4() & vm->dataMask);
+#else
+		EmitString("B8");				// mov eax, 0x12345678
+		EmitPtr(vm->dataBase + (Constant4() & vm->dataMask));
+		EmitString("8B 00");				// mov eax, dword ptr [eax]
+#endif
+		EmitCommand(LAST_COMMAND_MOV_STACK_EAX);	// mov dword ptr [edi + ebx * 4], eax
+
 		pc++;						// OP_LOAD4
 		instruction += 1;
 		return qtrue;
 
 	case OP_LOAD2:
-		EmitAddEDI4(vm);
-		EmitString( "BB" );         // mov ebx, 0x12345678
-		Emit4( (Constant4()&vm->dataMask) + (int)vm->dataBase);
-		EmitString( "0F B7 03" );   // movzx eax, word ptr [ebx]
-		EmitCommand(LAST_COMMAND_MOV_EDI_EAX); // mov dword ptr [edi], eax
+		EmitPushStack(vm);
+#if idx64
+		EmitRexString(0x41, "0F B7 81");		// movzx eax, word ptr [r9 + 0x12345678]
+		Emit4(Constant4() & vm->dataMask);
+#else
+		EmitString("B8");				// mov eax, 0x12345678
+		EmitPtr(vm->dataBase + (Constant4() & vm->dataMask));
+		EmitString("0F B7 00");				// movzx eax, word ptr [eax]
+#endif
+		EmitCommand(LAST_COMMAND_MOV_STACK_EAX);	// mov dword ptr [edi + ebx * 4], eax
+
 		pc++;						// OP_LOAD2
 		instruction += 1;
 		return qtrue;
 
 	case OP_LOAD1:
-		EmitAddEDI4(vm);
-		EmitString( "BB" );         // mov ebx, 0x12345678
-		Emit4( (Constant4()&vm->dataMask) + (int)vm->dataBase);
-		EmitString( "0F B6 03" );	// movzx eax, byte ptr [ebx]
-		EmitCommand(LAST_COMMAND_MOV_EDI_EAX); // mov dword ptr [edi], eax
+		EmitPushStack(vm);
+#if idx64
+		EmitRexString(0x41, "0F B6 81");		// movzx eax, byte ptr [r9 + 0x12345678]
+		Emit4(Constant4() & vm->dataMask);
+#else
+		EmitString("B8");				// mov eax, 0x12345678
+		EmitPtr(vm->dataBase + (Constant4() & vm->dataMask));
+		EmitString("0F B6 00");				// movzx eax, byte ptr [eax]
+#endif
+		EmitCommand(LAST_COMMAND_MOV_STACK_EAX);	// mov dword ptr [edi + ebx * 4], eax
+
 		pc++;						// OP_LOAD1
 		instruction += 1;
 		return qtrue;
 
 	case OP_STORE4:
-		opt = EmitMovEBXEDI(vm, (vm->dataMask & ~3));
-		EmitString( "B8" );			// mov	eax, 0x12345678
-		Emit4( Constant4() );
-//		if (!opt) {
-//			EmitString( "81 E3" );  // and ebx, 0x12345678
-//			Emit4( vm->dataMask & ~3 );
-//		}
-		EmitString( "89 83" );      // mov dword ptr [ebx+0x12345678], eax
-		Emit4( (int)vm->dataBase );
-		EmitCommand(LAST_COMMAND_SUB_DI_4);		// sub edi, 4
+		EmitMovEAXStack(vm, (vm->dataMask & ~3));
+#if idx64
+		EmitRexString(0x41, "C7 04 01");		// mov dword ptr [r9 + eax], 0x12345678
+		Emit4(Constant4());
+#else
+		EmitString("C7 80");				// mov dword ptr [eax + 0x12345678], 0x12345678
+		Emit4((intptr_t) vm->dataBase);
+		Emit4(Constant4());
+#endif
+		EmitCommand(LAST_COMMAND_SUB_BL_1);		// sub bl, 1
 		pc++;						// OP_STORE4
 		instruction += 1;
 		return qtrue;
 
 	case OP_STORE2:
-		opt = EmitMovEBXEDI(vm, (vm->dataMask & ~1));
-		EmitString( "B8" );			// mov	eax, 0x12345678
-		Emit4( Constant4() );
-//		if (!opt) {
-//			EmitString( "81 E3" );  // and ebx, 0x12345678
-//			Emit4( vm->dataMask & ~1 );
-//		}
-		EmitString( "66 89 83" );   // mov word ptr [ebx+0x12345678], eax
-		Emit4( (int)vm->dataBase );
-		EmitCommand(LAST_COMMAND_SUB_DI_4); // sub edi, 4
-		pc++;                       // OP_STORE2
+		EmitMovEAXStack(vm, (vm->dataMask & ~1));
+#if idx64
+		Emit1(0x66);					// mov word ptr [r9 + eax], 0x1234
+		EmitRexString(0x41, "C7 04 01");
+		Emit2(Constant4());
+#else
+		EmitString("66 C7 80");				// mov word ptr [eax + 0x12345678], 0x1234
+		Emit4((intptr_t) vm->dataBase);
+		Emit2(Constant4());
+#endif
+		EmitCommand(LAST_COMMAND_SUB_BL_1);		// sub bl, 1
+
+		pc++;						// OP_STORE2
 		instruction += 1;
 		return qtrue;
 
 	case OP_STORE1:
-		opt = EmitMovEBXEDI(vm, vm->dataMask);
-		EmitString( "B8" );			// mov	eax, 0x12345678
-		Emit4( Constant4() );
-//		if (!opt) {
-//			EmitString( "81 E3" );	// and ebx, 0x12345678
-//			Emit4( vm->dataMask );
-//		}
-		EmitString( "88 83" );		// mov byte ptr [ebx+0x12345678], eax
-		Emit4( (int)vm->dataBase );
-		EmitCommand(LAST_COMMAND_SUB_DI_4);		// sub edi, 4
-		pc++;						// OP_STORE4
+		EmitMovEAXStack(vm, vm->dataMask);
+#if idx64
+		EmitRexString(0x41, "C6 04 01");		// mov byte [r9 + eax], 0x12
+		Emit1(Constant4());
+#else
+		EmitString("C6 80");				// mov byte ptr [eax + 0x12345678], 0x12
+		Emit4((intptr_t) vm->dataBase);
+		Emit1(Constant4());
+#endif
+		EmitCommand(LAST_COMMAND_SUB_BL_1);		// sub bl, 1
+
+		pc++;						// OP_STORE1
 		instruction += 1;
 		return qtrue;
 
 	case OP_ADD:
 		v = Constant4();
-		EmitMovEAXEDI( vm ); 
-		if ( v >= 0 && v <= 127 ) {
-			EmitString( "83 C0" );	// add eax, 0x7F
-			Emit1( v );
-		} else {
-			EmitString( "05" );	    // add eax, 0x12345678
-			Emit4( v );
+
+		EmitMovEAXStack(vm, 0);
+		if(iss8(v))
+		{
+			EmitString("83 C0");			// add eax, 0x7F
+			Emit1(v);
 		}
-		EmitCommand( LAST_COMMAND_MOV_EDI_EAX );
+		else
+		{
+			EmitString("05");			// add eax, 0x12345678
+			Emit4(v);
+		}
+		EmitCommand(LAST_COMMAND_MOV_STACK_EAX);
+
 		pc++;						// OP_ADD
 		instruction += 1;
 		return qtrue;
 
 	case OP_SUB:
 		v = Constant4();
-		EmitMovEAXEDI( vm );
-		if ( v >= 0 && v <= 127 ) {
-			EmitString( "83 E8" );	// sub eax, 0x7F
-			Emit1( v );
-		} else {
-			EmitString( "2D" );		// sub eax, 0x12345678
-			Emit4( v );
+
+		EmitMovEAXStack(vm, 0);
+		if(iss8(v))
+		{
+			EmitString("83 E8");			// sub eax, 0x7F
+			Emit1(v);
 		}
-		EmitCommand( LAST_COMMAND_MOV_EDI_EAX );
+		else
+		{
+			EmitString("2D");			// sub eax, 0x12345678
+			Emit4(v);
+		}
+		EmitCommand(LAST_COMMAND_MOV_STACK_EAX);
+
 		pc++;						// OP_SUB
 		instruction += 1;
 		return qtrue;
 
 	case OP_MULI:
 		v = Constant4();
-		EmitMovEAXEDI( vm );
-		if ( v >= 0 && v <= 127 ) {
-			EmitString( "6B C0" );	// imul eax, 0x7F
-			Emit1( v );
-		} else {
-			EmitString( "69 C0" );	// imul eax, 0x12345678
-			Emit4( v );
+
+		EmitMovEAXStack(vm, 0);
+		if(iss8(v))
+		{
+			EmitString("6B C0");			// imul eax, 0x7F
+			Emit1(v);
 		}
-		EmitCommand( LAST_COMMAND_MOV_EDI_EAX );
+		else
+		{
+			EmitString("69 C0");			// imul eax, 0x12345678
+			Emit4(v);
+		}
+		EmitCommand(LAST_COMMAND_MOV_STACK_EAX);
 		pc++;						// OP_MULI
 		instruction += 1;
+
 		return qtrue;
 
 	case OP_LSH:
 		v = NextConstant4();
-		if ( v < 0 || v > 31 )
+		if(v < 0 || v > 31)
 			break;
-		EmitMovEAXEDI( vm );
-		EmitString( "C1 E0" );	// shl dword ptr [edi], 0x12
-		Emit1( v );
-		EmitCommand( LAST_COMMAND_MOV_EDI_EAX );
-		pc += 5;				// CONST + OP_LSH
+
+		EmitMovEAXStack(vm, 0);
+		EmitString("C1 E0");				// shl eax, 0x12
+		Emit1(v);
+		EmitCommand(LAST_COMMAND_MOV_STACK_EAX);
+
+		pc += 5;					// CONST + OP_LSH
 		instruction += 1;
 		return qtrue;
 
 	case OP_RSHI:
 		v = NextConstant4();
-		if ( v < 0 || v > 31 )
+		if(v < 0 || v > 31)
 			break;
-		EmitMovEAXEDI( vm );
-		EmitString( "C1 F8" );	// sar eax, 0x12
-		Emit1( v );
-		EmitCommand( LAST_COMMAND_MOV_EDI_EAX );
-		pc += 5;				// CONST + OP_RSHI
+			
+		EmitMovEAXStack(vm, 0);
+		EmitString("C1 F8");				// sar eax, 0x12
+		Emit1(v);
+		EmitCommand(LAST_COMMAND_MOV_STACK_EAX);
+
+		pc += 5;					// CONST + OP_RSHI
 		instruction += 1;
 		return qtrue;
 
 	case OP_RSHU:
 		v = NextConstant4();
-		if ( v < 0 || v > 31 )
+		if(v < 0 || v > 31)
 			break;
-		EmitMovEAXEDI( vm );
-		EmitString( "C1 E8" );	// shr eax, 0x12
-		Emit1( v );
-		EmitCommand( LAST_COMMAND_MOV_EDI_EAX );
-		pc += 5;				// CONST + OP_RSHU
+			
+		EmitMovEAXStack(vm, 0);
+		EmitString("C1 E8");				// shr eax, 0x12
+		Emit1(v);
+		EmitCommand(LAST_COMMAND_MOV_STACK_EAX);
+
+		pc += 5;					// CONST + OP_RSHU
 		instruction += 1;
 		return qtrue;
 	
 	case OP_BAND:
 		v = Constant4();
-		EmitMovEAXEDI( vm );
-		if ( v >= 0 && v <= 127 ) {
-			EmitString( "83 E0" ); // and eax, 0x7F
-			Emit1( v );
-		} else {
-			EmitString( "25" ); // and eax, 0x12345678
-			Emit4( v );
+
+		EmitMovEAXStack(vm, 0);
+		if(iss8(v))
+		{
+			EmitString("83 E0");			// and eax, 0x7F
+			Emit1(v);
+		}
+		else
+		{
+			EmitString("25");			// and eax, 0x12345678
+			Emit4(v);
 		}
-		EmitCommand( LAST_COMMAND_MOV_EDI_EAX );
-		pc += 1;				   // OP_BAND
+		EmitCommand(LAST_COMMAND_MOV_STACK_EAX);
+		
+		pc += 1;					// OP_BAND
 		instruction += 1;
 		return qtrue;
 
 	case OP_BOR:
 		v = Constant4();
-		EmitMovEAXEDI( vm );
-		if ( v >= 0 && v <= 127 ) {
-			EmitString( "83 C8" ); // or eax, 0x7F
-			Emit1( v );
-		} else {
-			EmitString( "0D" );    // or eax, 0x12345678
-			Emit4( v );
+
+		EmitMovEAXStack(vm, 0);
+		if(iss8(v))
+		{
+			EmitString("83 C8");			// or eax, 0x7F
+			Emit1(v);
 		}
-		EmitCommand( LAST_COMMAND_MOV_EDI_EAX );
-		pc += 1;				   // OP_BOR
+		else
+		{
+			EmitString("0D");			// or eax, 0x12345678
+			Emit4(v);
+		}
+		EmitCommand(LAST_COMMAND_MOV_STACK_EAX);
+		
+		pc += 1;				 	// OP_BOR
 		instruction += 1;
 		return qtrue;
 
 	case OP_BXOR:
 		v = Constant4();
-		EmitMovEAXEDI( vm );
-		if ( v >= 0 && v <= 127 ) {
-			EmitString( "83 F0" ); // xor eax, 0x7F
-			Emit1( v );
-		} else {
-			EmitString( "35" );    // xor eax, 0x12345678
-			Emit4( v );
+		
+		EmitMovEAXStack(vm, 0);
+		if(iss8(v))
+		{
+			EmitString("83 F0");			// xor eax, 0x7F
+			Emit1(v);
 		}
-		EmitCommand( LAST_COMMAND_MOV_EDI_EAX );
-		pc += 1;				   // OP_BXOR
-		instruction += 1;
-		return qtrue;
-
-	case OP_EQF:
-	case OP_NEF:
-		if ( NextConstant4() != 0 )
-			break;
-		pc += 5;				   // CONST + OP_EQF|OP_NEF
-		EmitMovEAXEDI( vm );
-		EmitCommand(LAST_COMMAND_SUB_DI_4);
-		// floating point hack :)
-		EmitString( "25" );        // and eax, 0x7FFFFFFF
-		Emit4( 0x7FFFFFFF );
-		if ( op1 == OP_EQF )
-			EmitString( "75 06" ); // jnz +6
 		else
-			EmitString( "74 06" ); // jz +6
-		EmitString( "FF 25" );	   // jmp [0x12345678]
-		v = Constant4();
-		JUSED(v);
-		Emit4( (int)vm->instructionPointers + v*4 );
+		{
+			EmitString("35");			// xor eax, 0x12345678
+			Emit4(v);
+		}
+		EmitCommand(LAST_COMMAND_MOV_STACK_EAX);
+		
+		pc += 1;					// OP_BXOR
 		instruction += 1;
 		return qtrue;
 
 	case OP_EQ:
 	case OP_NE:
-		v = Constant4();
-		EmitMovEAXEDI( vm );
-		EmitCommand(LAST_COMMAND_SUB_DI_4);
-		if ( v == 0 ) {
-			EmitString( "85 C0" ); // test eax, eax
-		} else {
-			EmitString( "3D" );    // cmp eax, 0x12345678
-			Emit4( v );
-		}
-		pc += 1;				   // OP_EQ/OP_NE
-		if ( op1 == OP_EQ )
-			EmitString( "75 06" ); // jne +6
-		else
-			EmitString( "74 06" ); // je +6
-		EmitString( "FF 25" );	   // jmp [0x12345678]
-		v = Constant4();
-		JUSED(v);
-		Emit4( (int)vm->instructionPointers + v*4 );
-		instruction += 1;
-		return qtrue;
-
-	case OP_GEI:
+	case OP_LTI:
+	case OP_LEI:
 	case OP_GTI:
-		v = Constant4();
-		EmitMovEAXEDI( vm );
-		EmitCommand( LAST_COMMAND_SUB_DI_4 );
-		EmitString( "3D" );        // cmp eax, 0x12345678
-		Emit4( v );
-		pc += 1;			       // OP_GEI|OP_GTI
-		if ( op1 == OP_GEI )
-			EmitString( "7C 06" ); // jl +6
-		else
-			EmitString( "7E 06" ); // jle +6
-		EmitString( "FF 25" );     // jmp [0x12345678]
-		v = Constant4();
-		JUSED(v);
-		Emit4( (int)vm->instructionPointers + v*4 );
-		instruction += 1;
+	case OP_GEI:
+	case OP_LTU:
+	case OP_LEU:
+	case OP_GTU:
+	case OP_GEU:
+		EmitMovEAXStack(vm, 0);
+		EmitCommand(LAST_COMMAND_SUB_BL_1);
+		EmitString("3D");				// cmp eax, 0x12345678
+		Emit4(Constant4());
+
+		pc++;						// OP_*
+		EmitBranchConditions(vm, op1);
+		instruction++;
+
 		return qtrue;
 
-	case OP_LEI:
-	case OP_LTI:
-		v = Constant4();
-		EmitMovEAXEDI( vm );
-		EmitCommand( LAST_COMMAND_SUB_DI_4 );
-		EmitString( "3D" );        // cmp eax, 0x12345678
-		Emit4( v );
-		pc += 1;			       // OP_GEI|OP_GTI
-		if ( op1 == OP_LEI )
-			EmitString( "7F 06" ); // jg +6
+	case OP_EQF:
+	case OP_NEF:
+		if(NextConstant4())
+			break;
+		pc += 5;					// CONST + OP_EQF|OP_NEF
+
+		EmitMovEAXStack(vm, 0);
+		EmitCommand(LAST_COMMAND_SUB_BL_1);
+		// floating point hack :)
+		EmitString("25");				// and eax, 0x7FFFFFFF
+		Emit4(0x7FFFFFFF);
+		if(op1 == OP_EQF)
+			EmitJumpIns(vm, "0F 84", Constant4());	// jz 0x12345678
 		else
-			EmitString( "7D 06" ); // jge +6
-		EmitString( "FF 25" );     // jmp [0x12345678]
-		v = Constant4();
-		JUSED(v);
-		Emit4( (int)vm->instructionPointers + v*4 );
+			EmitJumpIns(vm, "0F 85", Constant4());	// jnz 0x12345678
+		
 		instruction += 1;
 		return qtrue;
 
+
 	case OP_JUMP:
-		v = Constant4();
-		JUSED(v);
-		EmitString( "FF 25" );    // jmp dword ptr [instructionPointers + 0x12345678]
-		Emit4( (int)vm->instructionPointers + v*4 );
+		EmitJumpIns(vm, "E9", Constant4());		// jmp 0x12345678
+
 		pc += 1;                  // OP_JUMP
 		instruction += 1;
 		return qtrue;
 
 	case OP_CALL:
-		if ( NextConstant4() < 0 )
-			break;
 		v = Constant4();
-		EmitCallConst(vm, v, sysCallOfs);
+		EmitCallConst(vm, v, callProcOfsSyscall);
 
 		pc += 1;                  // OP_CALL
 		instruction += 1;
@@ -817,23 +1067,23 @@ qboolean ConstOptimize(vm_t *vm, int sys
 	return qfalse;
 }
 
-
 /*
 =================
 VM_Compile
 =================
 */
-void VM_Compile( vm_t *vm, vmHeader_t *header ) {
+void VM_Compile(vm_t *vm, vmHeader_t *header)
+{
 	int		op;
 	int		maxLength;
 	int		v;
 	int		i;
-        int		sysCallOfs;
+        int		callProcOfsSyscall, callProcOfs, callDoSyscallOfs;
 
 	jusedSize = header->instructionCount + 2;
 
 	// allocate a very large temp buffer, we will shrink it later
-	maxLength = header->codeLength * 8;
+	maxLength = header->codeLength * 8 + 64;
 	buf = Z_Malloc(maxLength);
 	jused = Z_Malloc(jusedSize);
 	code = Z_Malloc(header->codeLength+32);
@@ -855,10 +1105,13 @@ void VM_Compile( vm_t *vm, vmHeader_t *h
 
 	// Start buffer with x86-VM specific procedures
 	compiledOfs = 0;
-	sysCallOfs = EmitCallProcedure(vm);
+
+	callDoSyscallOfs = compiledOfs;
+	callProcOfs = EmitCallDoSyscall(vm);
+	callProcOfsSyscall = EmitCallProcedure(vm, callDoSyscallOfs);
 	vm->entryOfs = compiledOfs;
 
-	for(pass=0;pass<2;pass++) {
+	for(pass=0; pass < 3; pass++) {
 	oc0 = -23423;
 	oc1 = -234354;
 	pop0 = -43435;
@@ -901,525 +1154,491 @@ void VM_Compile( vm_t *vm, vmHeader_t *h
 		case 0:
 			break;
 		case OP_BREAK:
-			EmitString( "CC" );			// int 3
+			EmitString("CC");				// int 3
 			break;
 		case OP_ENTER:
-			EmitString( "81 EE" );		// sub	esi, 0x12345678
-			Emit4( Constant4() );
+			EmitString("81 EE");				// sub esi, 0x12345678
+			Emit4(Constant4());
 			break;
 		case OP_CONST:
-			if(ConstOptimize(vm, sysCallOfs))
+			if(ConstOptimize(vm, callProcOfsSyscall))
 				break;
 
-			EmitAddEDI4(vm);
-			EmitString( "C7 07" );		// mov	dword ptr [edi], 0x12345678
+			EmitPushStack(vm);
+			EmitString("C7 04 9F");				// mov dword ptr [edi + ebx * 4], 0x12345678
 			lastConst = Constant4();
-			Emit4( lastConst );
-			if (code[pc] == OP_JUMP) {
+
+			Emit4(lastConst);
+			if(code[pc] == OP_JUMP)
 				JUSED(lastConst);
-			}
+
 			break;
 		case OP_LOCAL:
-			EmitAddEDI4(vm);
-			EmitString( "8D 86" );		// lea eax, [0x12345678 + esi]
+			EmitPushStack(vm);
+			EmitString("8D 86");				// lea eax, [0x12345678 + esi]
 			oc0 = oc1;
 			oc1 = Constant4();
-			Emit4( oc1 );
-			EmitCommand(LAST_COMMAND_MOV_EDI_EAX);		// mov dword ptr [edi], eax
+			Emit4(oc1);
+			EmitCommand(LAST_COMMAND_MOV_STACK_EAX);	// mov dword ptr [edi + ebx * 4], eax
 			break;
 		case OP_ARG:
-			EmitMovEAXEDI(vm);			// mov	eax,dword ptr [edi]
-			EmitString( "89 86" );		// mov	dword ptr [esi+database],eax
-			Emit4((Constant1() & vm->dataMask & 0xFF) + (int) vm->dataBase);
-			EmitCommand(LAST_COMMAND_SUB_DI_4);		// sub edi, 4
+			EmitMovEAXStack(vm, 0);				// mov eax, dword ptr [edi + ebx * 4]
+			EmitString("8B D6");				// mov edx, esi
+			EmitString("81 C2");				// add edx, 0x12345678
+			Emit4((Constant1() & 0xFF));
+			MASK_REG("E2", vm->dataMask);			// and edx, 0x12345678
+#if idx64
+			EmitRexString(0x41, "89 04 11");		// mov dword ptr [r9 + edx], eax
+#else
+			EmitString("89 82");				// mov dword ptr [edx + 0x12345678], eax
+			Emit4((intptr_t) vm->dataBase);
+#endif
+			EmitCommand(LAST_COMMAND_SUB_BL_1);		// sub bl, 1
 			break;
 		case OP_CALL:
-			EmitCall(vm, 0);
+			EmitCallRel(vm, callProcOfs);
 			break;
 		case OP_PUSH:
-			EmitAddEDI4(vm);
+			EmitPushStack(vm);
 			break;
 		case OP_POP:
-			EmitCommand(LAST_COMMAND_SUB_DI_4);		// sub edi, 4
+			EmitCommand(LAST_COMMAND_SUB_BL_1);		// sub bl, 1
 			break;
 		case OP_LEAVE:
 			v = Constant4();
-			EmitString( "81 C6" );		// add	esi, 0x12345678
-			Emit4( v );
-			EmitString( "C3" );			// ret
+			EmitString("81 C6");				// add	esi, 0x12345678
+			Emit4(v);
+			EmitString("C3");				// ret
 			break;
 		case OP_LOAD4:
-			if (code[pc] == OP_CONST && code[pc+5] == OP_ADD && code[pc+6] == OP_STORE4) {
-				if (oc0 == oc1 && pop0 == OP_LOCAL && pop1 == OP_LOCAL) {
-					compiledOfs -= 11;
-					vm->instructionPointers[ instruction-1 ] = compiledOfs;
+			if (code[pc] == OP_CONST && code[pc+5] == OP_ADD && code[pc+6] == OP_STORE4)
+			{
+				if(oc0 == oc1 && pop0 == OP_LOCAL && pop1 == OP_LOCAL)
+				{
+					compiledOfs -= 12;
+					vm->instructionPointers[instruction - 1] = compiledOfs;
 				}
-				pc++;						// OP_CONST
+
+				pc++;				// OP_CONST
 				v = Constant4();
-				EmitMovEBXEDI(vm, vm->dataMask);
-				if (v == 1 && oc0 == oc1 && pop0 == OP_LOCAL && pop1 == OP_LOCAL) {
-					EmitString( "FF 83");		// inc dword ptr [ebx + 0x12345678]
-					Emit4( (int)vm->dataBase );
-				} else {
-					EmitString( "8B 83" );		// mov	eax, dword ptr [ebx + 0x12345678]
-					Emit4( (int)vm->dataBase );
-					EmitString( "05"  );		// add eax, const
-					Emit4( v );
-					if (oc0 == oc1 && pop0 == OP_LOCAL && pop1 == OP_LOCAL) {
-						EmitString( "89 83" );		// mov dword ptr [ebx+0x12345678], eax
-						Emit4( (int)vm->dataBase );
-					} else {
-						EmitCommand(LAST_COMMAND_SUB_DI_4);		// sub edi, 4
-						EmitString( "8B 1F" );		// mov	ebx, dword ptr [edi]
-						EmitString( "89 83" );		// mov dword ptr [ebx+0x12345678], eax
-						Emit4( (int)vm->dataBase );
+
+				EmitMovEDXStack(vm, vm->dataMask);
+				if(v == 1 && oc0 == oc1 && pop0 == OP_LOCAL && pop1 == OP_LOCAL)
+				{
+#if idx64
+					EmitRexString(0x41, "FF 04 11");	// inc dword ptr [r9 + edx]
+#else
+					EmitString("FF 82");			// inc dword ptr [edx + 0x12345678]
+					Emit4((intptr_t) vm->dataBase);
+#endif
+				}
+				else
+				{
+#if idx64
+					EmitRexString(0x41, "8B 04 11");	// mov eax, dword ptr [r9 + edx]
+#else
+					EmitString("8B 82");			// mov eax, dword ptr [edx + 0x12345678]
+					Emit4((intptr_t) vm->dataBase);
+#endif
+					EmitString("05");			// add eax, v
+					Emit4(v);
+					
+					if (oc0 == oc1 && pop0 == OP_LOCAL && pop1 == OP_LOCAL)
+					{
+#if idx64
+						EmitRexString(0x41, "89 04 11");	// mov dword ptr [r9 + edx], eax
+#else
+						EmitString("89 82");			// mov dword ptr [edx + 0x12345678], eax
+						Emit4((intptr_t) vm->dataBase);
+#endif
+					}
+					else
+					{
+						EmitCommand(LAST_COMMAND_SUB_BL_1);	// sub bl, 1
+						EmitString("8B 14 9F");			// mov edx, dword ptr [edi + ebx * 4]
+						MASK_REG("E2", vm->dataMask);		// and edx, 0x12345678
+#if idx64
+						EmitRexString(0x41, "89 04 11");	// mov dword ptr [r9 + edx], eax
+#else
+						EmitString("89 82");			// mov dword ptr [edx + 0x12345678], eax
+						Emit4((intptr_t) vm->dataBase);
+#endif
 					}
 				}
-				EmitCommand(LAST_COMMAND_SUB_DI_4);		// sub edi, 4
+
+				EmitCommand(LAST_COMMAND_SUB_BL_1);		// sub bl, 1
 				pc++;						// OP_ADD
 				pc++;						// OP_STORE
 				instruction += 3;
 				break;
 			}
 
-			if (code[pc] == OP_CONST && code[pc+5] == OP_SUB && code[pc+6] == OP_STORE4) {
-				if (oc0 == oc1 && pop0 == OP_LOCAL && pop1 == OP_LOCAL) {
-					compiledOfs -= 11;
-					vm->instructionPointers[ instruction-1 ] = compiledOfs;
+			if(code[pc] == OP_CONST && code[pc+5] == OP_SUB && code[pc+6] == OP_STORE4)
+			{
+				if(oc0 == oc1 && pop0 == OP_LOCAL && pop1 == OP_LOCAL)
+				{
+					compiledOfs -= 12;
+					vm->instructionPointers[instruction - 1] = compiledOfs;
 				}
-				EmitMovEBXEDI(vm, vm->dataMask);
-				EmitString( "8B 83" );		// mov	eax, dword ptr [ebx + 0x12345678]
-				Emit4( (int)vm->dataBase );
-				pc++;						// OP_CONST
+				
+				pc++;					// OP_CONST
 				v = Constant4();
-				if (v == 1 && oc0 == oc1 && pop0 == OP_LOCAL && pop1 == OP_LOCAL) {
-					EmitString( "FF 8B");		// dec dword ptr [ebx + 0x12345678]
-					Emit4( (int)vm->dataBase );
-				} else {
-					EmitString( "2D"  );		// sub eax, const
-					Emit4( v );
-					if (oc0 == oc1 && pop0 == OP_LOCAL && pop1 == OP_LOCAL) {
-						EmitString( "89 83" );		// mov dword ptr [ebx+0x12345678], eax
-						Emit4( (int)vm->dataBase );
-					} else {
-						EmitCommand(LAST_COMMAND_SUB_DI_4);		// sub edi, 4
-						EmitString( "8B 1F" );		// mov	ebx, dword ptr [edi]
-						EmitString( "89 83" );		// mov dword ptr [ebx+0x12345678], eax
-						Emit4( (int)vm->dataBase );
+
+				EmitMovEDXStack(vm, vm->dataMask);
+				if(v == 1 && oc0 == oc1 && pop0 == OP_LOCAL && pop1 == OP_LOCAL)
+				{
+#if idx64
+					EmitRexString(0x41, "FF 0C 11");	// dec dword ptr [r9 + edx]
+#else
+					EmitString("FF 8A");			// dec dword ptr [edx + 0x12345678]
+					Emit4((intptr_t) vm->dataBase);
+#endif
+				}
+				else
+				{
+#if idx64
+					EmitRexString(0x41, "8B 04 11");	// mov eax, dword ptr [r9 + edx]
+#else
+					EmitString("8B 82");			// mov eax, dword ptr [edx + 0x12345678]
+					Emit4((intptr_t) vm->dataBase);
+#endif
+					EmitString("2D");			// sub eax, v
+					Emit4(v);
+					
+					if(oc0 == oc1 && pop0 == OP_LOCAL && pop1 == OP_LOCAL)
+					{
+#if idx64
+						EmitRexString(0x41, "89 04 11");	// mov dword ptr [r9 + edx], eax
+#else
+						EmitString("89 82");			// mov dword ptr [edx + 0x12345678], eax
+						Emit4((intptr_t) vm->dataBase);
+#endif
+					}
+					else
+					{
+						EmitCommand(LAST_COMMAND_SUB_BL_1);	// sub bl, 1
+						EmitString("8B 14 9F");			// mov edx, dword ptr [edi + ebx * 4]
+						MASK_REG("E2", vm->dataMask);		// and edx, 0x12345678
+#if idx64
+						EmitRexString(0x41, "89 04 11");	// mov dword ptr [r9 + edx], eax
+#else
+						EmitString("89 82");			// mov dword ptr [edx + 0x12345678], eax
+						Emit4((intptr_t) vm->dataBase);
+#endif
 					}
 				}
-				EmitCommand(LAST_COMMAND_SUB_DI_4);		// sub edi, 4
+				EmitCommand(LAST_COMMAND_SUB_BL_1);		// sub bl, 1
 				pc++;						// OP_SUB
 				pc++;						// OP_STORE
 				instruction += 3;
 				break;
 			}
 
-			if (buf[compiledOfs-2] == 0x89 && buf[compiledOfs-1] == 0x07) {
-				compiledOfs -= 2;
-				vm->instructionPointers[ instruction-1 ] = compiledOfs;
-				EmitString( "8B 80");	// mov eax, dword ptr [eax + 0x1234567]
-				Emit4( (int)vm->dataBase );
-				EmitCommand(LAST_COMMAND_MOV_EDI_EAX);		// mov dword ptr [edi], eax
+			if(buf[compiledOfs - 3] == 0x89 && buf[compiledOfs - 2] == 0x04 && buf[compiledOfs - 1] == 0x9F)
+			{
+				compiledOfs -= 3;
+				vm->instructionPointers[instruction - 1] = compiledOfs;
+				MASK_REG("E0", vm->dataMask);			// and eax, 0x12345678
+#if idx64
+				EmitRexString(0x41, "8B 04 01");		// mov eax, dword ptr [r9 + eax]
+#else
+				EmitString("8B 80");				// mov eax, dword ptr [eax + 0x1234567]
+				Emit4((intptr_t) vm->dataBase);
+#endif
+				EmitCommand(LAST_COMMAND_MOV_STACK_EAX);	// mov dword ptr [edi + ebx * 4], eax
 				break;
 			}
-			EmitMovEBXEDI(vm, vm->dataMask);
-			EmitString( "8B 83" );		// mov	eax, dword ptr [ebx + 0x12345678]
-			Emit4( (int)vm->dataBase );
-			EmitCommand(LAST_COMMAND_MOV_EDI_EAX);		// mov dword ptr [edi], eax
+			
+			EmitMovEAXStack(vm, vm->dataMask);
+#if idx64
+			EmitRexString(0x41, "8B 04 01");		// mov eax, dword ptr [r9 + eax]
+#else
+			EmitString("8B 80");				// mov eax, dword ptr [eax + 0x12345678]
+			Emit4((intptr_t) vm->dataBase);
+#endif
+			EmitCommand(LAST_COMMAND_MOV_STACK_EAX);	// mov dword ptr [edi + ebx * 4], eax
 			break;
 		case OP_LOAD2:
-			EmitMovEBXEDI(vm, vm->dataMask);
-			EmitString( "0F B7 83" );	// movzx	eax, word ptr [ebx + 0x12345678]
-			Emit4( (int)vm->dataBase );
-			EmitCommand(LAST_COMMAND_MOV_EDI_EAX);		// mov dword ptr [edi], eax
+			EmitMovEAXStack(vm, vm->dataMask);
+#if idx64
+			EmitRexString(0x41, "0F B7 04 01");		// movzx eax, word ptr [r9 + eax]
+#else
+			EmitString("0F B7 80");				// movzx eax, word ptr [eax + 0x12345678]
+			Emit4((intptr_t) vm->dataBase);
+#endif
+			EmitCommand(LAST_COMMAND_MOV_STACK_EAX);	// mov dword ptr [edi + ebx * 4], eax
 			break;
 		case OP_LOAD1:
-			EmitMovEBXEDI(vm, vm->dataMask);
-			EmitString( "0F B6 83" );	// movzx eax, byte ptr [ebx + 0x12345678]
-			Emit4( (int)vm->dataBase );
-			EmitCommand(LAST_COMMAND_MOV_EDI_EAX);		// mov dword ptr [edi], eax
+			EmitMovEAXStack(vm, vm->dataMask);
+#if idx64
+			EmitRexString(0x41, "0F B6 04 01");		// movzx eax, byte ptr [r9 + eax]
+#else
+			EmitString("0F B6 80");				// movzx eax, byte ptr [eax + 0x12345678]
+			Emit4((intptr_t) vm->dataBase);
+#endif
+			EmitCommand(LAST_COMMAND_MOV_STACK_EAX);	// mov dword ptr [edi + ebx * 4], eax
 			break;
 		case OP_STORE4:
-			EmitMovEAXEDI(vm);
-			EmitString( "8B 5F FC" );	// mov	ebx, dword ptr [edi-4]
-//			if (pop1 != OP_CALL) {
-//				EmitString( "81 E3" );		// and ebx, 0x12345678
-//				Emit4( vm->dataMask & ~3 );
-//			}
-			EmitString( "89 83" );		// mov dword ptr [ebx+0x12345678], eax
-			Emit4( (int)vm->dataBase );
-			EmitCommand(LAST_COMMAND_SUB_DI_8);		// sub edi, 8
+			EmitMovEAXStack(vm, 0);	
+			EmitString("8B 54 9F FC");			// mov edx, dword ptr -4[edi + ebx * 4]
+			MASK_REG("E2", vm->dataMask & ~3);		// and edx, 0x12345678
+#if idx64
+			EmitRexString(0x41, "89 04 11");		// mov dword ptr [r9 + edx], eax
+#else
+			EmitString("89 82");				// mov dword ptr [edx + 0x12345678], eax
+			Emit4((intptr_t) vm->dataBase);
+#endif
+			EmitCommand(LAST_COMMAND_SUB_BL_2);		// sub bl, 2
 			break;
 		case OP_STORE2:
-			EmitMovEAXEDI(vm);
-			EmitString( "8B 5F FC" );	// mov	ebx, dword ptr [edi-4]
-//			EmitString( "81 E3" );		// and ebx, 0x12345678
-//			Emit4( vm->dataMask & ~1 );
-			EmitString( "66 89 83" );	// mov word ptr [ebx+0x12345678], eax
-			Emit4( (int)vm->dataBase );
-			EmitCommand(LAST_COMMAND_SUB_DI_8);		// sub edi, 8
+			EmitMovEAXStack(vm, 0);	
+			EmitString("8B 54 9F FC");			// mov edx, dword ptr -4[edi + ebx * 4]
+			MASK_REG("E2", vm->dataMask & ~1);		// and edx, 0x12345678
+#if idx64
+			Emit1(0x66);					// mov word ptr [r9 + edx], eax
+			EmitRexString(0x41, "89 04 11");
+#else
+			EmitString("66 89 82");				// mov word ptr [edx + 0x12345678], eax
+			Emit4((intptr_t) vm->dataBase);
+#endif
+			EmitCommand(LAST_COMMAND_SUB_BL_2);		// sub bl, 2
 			break;
 		case OP_STORE1:
-			EmitMovEAXEDI(vm);
-			EmitString( "8B 5F FC" );	// mov	ebx, dword ptr [edi-4]
-//			EmitString( "81 E3" );		// and ebx, 0x12345678
-//			Emit4( vm->dataMask );
-			EmitString( "88 83" );		// mov byte ptr [ebx+0x12345678], eax
-			Emit4( (int)vm->dataBase );
-			EmitCommand(LAST_COMMAND_SUB_DI_8);		// sub edi, 8
+			EmitMovEAXStack(vm, 0);	
+			EmitString("8B 54 9F FC");			// mov edx, dword ptr -4[edi + ebx * 4]
+			MASK_REG("E2", vm->dataMask);			// and edx, 0x12345678
+#if idx64
+			EmitRexString(0x41, "88 04 11");		// mov byte ptr [r9 + edx], eax
+#else
+			EmitString("88 82");				// mov byte ptr [edx + 0x12345678], eax
+			Emit4((intptr_t) vm->dataBase);
+#endif
+			EmitCommand(LAST_COMMAND_SUB_BL_2);		// sub bl, 2
 			break;
 
 		case OP_EQ:
-			EmitMovEAXEDI( vm );
-			EmitCommand( LAST_COMMAND_SUB_DI_8 );	// sub edi, 8
-			EmitString( "3B 47 04" );				// cmp	eax, dword ptr [edi+4]
-			EmitString( "75 06" );		// jne +6
-			EmitString( "FF 25" );		// jmp	[0x12345678]
-			v = Constant4();
-			JUSED(v);
-			Emit4( (int)vm->instructionPointers + v*4 );
-			break;
 		case OP_NE:
-			EmitMovEAXEDI( vm );
-			EmitCommand( LAST_COMMAND_SUB_DI_8 );	// sub edi, 8
-			EmitString( "3B 47 04" );	// cmp	eax, dword ptr [edi+4]
-			EmitString( "74 06" );		// je +6
-			EmitString( "FF 25" );		// jmp	[0x12345678]
-			v = Constant4();
-			JUSED(v);
-			Emit4( (int)vm->instructionPointers + v*4 );
-			break;
 		case OP_LTI:
-			EmitMovEAXEDI( vm );	
-			EmitCommand(LAST_COMMAND_SUB_DI_8);		// sub edi, 8
-			EmitString( "39 47 04" );	// cmp	dword ptr [edi+4], eax
-			EmitString( "7D 06" );		// jnl +6
-			EmitString( "FF 25" );		// jmp	[0x12345678]
-			v = Constant4();
-			JUSED(v);
-			Emit4( (int)vm->instructionPointers + v*4 );
-			break;
 		case OP_LEI:
-			EmitMovEAXEDI( vm );
-			EmitCommand(LAST_COMMAND_SUB_DI_8);		// sub edi, 8
-			EmitString( "39 47 04" );	// cmp	dword ptr [edi+4], eax
-			EmitString( "7F 06" );		// jnle +6
-			EmitString( "FF 25" );		// jmp	[0x12345678]
-			v = Constant4();
-			JUSED(v);
-			Emit4( (int)vm->instructionPointers + v*4 );
-			break;
 		case OP_GTI:
-			EmitMovEAXEDI( vm );
-			EmitCommand(LAST_COMMAND_SUB_DI_8);		// sub edi, 8
-			EmitString( "39 47 04" );	// cmp	eax, dword ptr [edi+4]
-			EmitString( "7E 06" );		// jng +6
-			EmitString( "FF 25" );		// jmp	[0x12345678]
-			v = Constant4();
-			JUSED(v);
-			Emit4( (int)vm->instructionPointers + v*4 );
-			break;
 		case OP_GEI:
-			EmitMovEAXEDI( vm );	
-			EmitCommand(LAST_COMMAND_SUB_DI_8);		// sub edi, 8
-			EmitString( "39 47 04" );	// cmp	eax, dword ptr [edi+4]
-			EmitString( "7C 06" );		// jnge +6
-			EmitString( "FF 25" );		// jmp	[0x12345678]
-			v = Constant4();
-			JUSED(v);
-			Emit4( (int)vm->instructionPointers + v*4 );
-			break;
 		case OP_LTU:
-			EmitMovEAXEDI( vm );	
-			EmitCommand(LAST_COMMAND_SUB_DI_8);		// sub edi, 8
-			EmitString( "39 47 04" );	// cmp	eax, dword ptr [edi+4]
-			EmitString( "73 06" );		// jnb +6
-			EmitString( "FF 25" );		// jmp	[0x12345678]
-			v = Constant4();
-			JUSED(v);
-			Emit4( (int)vm->instructionPointers + v*4 );
-			break;
 		case OP_LEU:
-			EmitMovEAXEDI( vm );	
-			EmitCommand(LAST_COMMAND_SUB_DI_8);		// sub edi, 8
-			EmitString( "39 47 04" );	// cmp	eax, dword ptr [edi+4]
-			EmitString( "77 06" );		// jnbe +6
-			EmitString( "FF 25" );		// jmp	[0x12345678]
-			v = Constant4();
-			JUSED(v);
-			Emit4( (int)vm->instructionPointers + v*4 );
-			break;
 		case OP_GTU:
-			EmitMovEAXEDI( vm );	
-			EmitCommand(LAST_COMMAND_SUB_DI_8);		// sub edi, 8
-			EmitString( "39 47 04" );	// cmp	eax, dword ptr [edi+4]
-			EmitString( "76 06" );		// jna +6
-			EmitString( "FF 25" );		// jmp	[0x12345678]
-			v = Constant4();
-			JUSED(v);
-			Emit4( (int)vm->instructionPointers + v*4 );
-			break;
 		case OP_GEU:
-			EmitMovEAXEDI( vm );	
-			EmitCommand(LAST_COMMAND_SUB_DI_8);		// sub edi, 8
-			EmitString( "39 47 04" );	// cmp	eax, dword ptr [edi+4]
-			EmitString( "72 06" );		// jnae +6
-			EmitString( "FF 25" );		// jmp	[0x12345678]
-			v = Constant4();
-			JUSED(v);
-			Emit4( (int)vm->instructionPointers + v*4 );
-			break;
+			EmitMovEAXStack(vm, 0);
+			EmitCommand(LAST_COMMAND_SUB_BL_2);		// sub bl, 2
+			EmitString("39 44 9F 04");			// cmp	eax, dword ptr 4[edi + ebx * 4]
+
+			EmitBranchConditions(vm, op);
+		break;
 		case OP_EQF:
-			EmitCommand(LAST_COMMAND_SUB_DI_8);		// sub edi, 8
-			EmitString( "D9 47 04" );	// fld dword ptr [edi+4]
-			EmitString( "D8 5F 08" );	// fcomp dword ptr [edi+8]
-			EmitString( "DF E0" );		// fnstsw ax
-			EmitString( "F6 C4 40" );	// test	ah,0x40
-			EmitString( "74 06" );		// je +6
-			EmitString( "FF 25" );		// jmp	[0x12345678]
-			v = Constant4();
-			JUSED(v);
-			Emit4( (int)vm->instructionPointers + v*4 );
-			break;
 		case OP_NEF:
-			EmitCommand(LAST_COMMAND_SUB_DI_8);		// sub edi, 8
-			EmitString( "D9 47 04" );	// fld dword ptr [edi+4]
-			EmitString( "D8 5F 08" );	// fcomp dword ptr [edi+8]
-			EmitString( "DF E0" );		// fnstsw ax
-			EmitString( "F6 C4 40" );	// test	ah,0x40
-			EmitString( "75 06" );		// jne +6
-			EmitString( "FF 25" );		// jmp	[0x12345678]
-			v = Constant4();
-			JUSED(v);
-			Emit4( (int)vm->instructionPointers + v*4 );
-			break;
 		case OP_LTF:
-			EmitCommand(LAST_COMMAND_SUB_DI_8);		// sub edi, 8
-			EmitString( "D9 47 04" );	// fld dword ptr [edi+4]
-			EmitString( "D8 5F 08" );	// fcomp dword ptr [edi+8]
-			EmitString( "DF E0" );		// fnstsw ax
-			EmitString( "F6 C4 01" );	// test	ah,0x01
-			EmitString( "74 06" );		// je +6
-			EmitString( "FF 25" );		// jmp	[0x12345678]
-			v = Constant4();
-			JUSED(v);
-			Emit4( (int)vm->instructionPointers + v*4 );
-			break;
 		case OP_LEF:
-			EmitCommand(LAST_COMMAND_SUB_DI_8);		// sub edi, 8
-			EmitString( "D9 47 04" );	// fld dword ptr [edi+4]
-			EmitString( "D8 5F 08" );	// fcomp dword ptr [edi+8]
-			EmitString( "DF E0" );		// fnstsw ax
-			EmitString( "F6 C4 41" );	// test	ah,0x41
-			EmitString( "74 06" );		// je +6
-			EmitString( "FF 25" );		// jmp	[0x12345678]
-			v = Constant4();
-			JUSED(v);
-			Emit4( (int)vm->instructionPointers + v*4 );
-			break;
 		case OP_GTF:
-			EmitCommand(LAST_COMMAND_SUB_DI_8);		// sub edi, 8
-			EmitString( "D9 47 04" );	// fld dword ptr [edi+4]
-			EmitString( "D8 5F 08" );	// fcomp dword ptr [edi+8]
-			EmitString( "DF E0" );		// fnstsw ax
-			EmitString( "F6 C4 41" );	// test	ah,0x41
-			EmitString( "75 06" );		// jne +6
-			EmitString( "FF 25" );		// jmp	[0x12345678]
-			v = Constant4();
-			JUSED(v);
-			Emit4( (int)vm->instructionPointers + v*4 );
-			break;
 		case OP_GEF:
-			EmitCommand(LAST_COMMAND_SUB_DI_8);		// sub edi, 8
-			EmitString( "D9 47 04" );	// fld dword ptr [edi+4]
-			EmitString( "D8 5F 08" );	// fcomp dword ptr [edi+8]
-			EmitString( "DF E0" );		// fnstsw ax
-			EmitString( "F6 C4 01" );	// test	ah,0x01
-			EmitString( "75 06" );		// jne +6
-			EmitString( "FF 25" );		// jmp	[0x12345678]
-			v = Constant4();
-			JUSED(v);
-			Emit4( (int)vm->instructionPointers + v*4 );
+			EmitCommand(LAST_COMMAND_SUB_BL_2);		// sub bl, 2
+			EmitString("D9 44 9F 04");			// fld dword ptr 4[edi + ebx * 4]
+			EmitString("D8 5C 9F 08");			// fcomp dword ptr 8[edi + ebx * 4]
+			EmitString("DF E0");				// fnstsw ax
+
+			switch(op)
+			{
+			case OP_EQF:
+				EmitString("F6 C4 40");			// test	ah,0x40
+				EmitJumpIns(vm, "0F 85", Constant4());	// jne 0x12345678
+			break;
+			case OP_NEF:
+				EmitString("F6 C4 40");			// test	ah,0x40
+				EmitJumpIns(vm, "0F 84", Constant4());	// je 0x12345678
+			break;
+			case OP_LTF:
+				EmitString("F6 C4 01");			// test	ah,0x01
+				EmitJumpIns(vm, "0F 85", Constant4());	// jne 0x12345678
+			break;
+			case OP_LEF:
+				EmitString("F6 C4 41");			// test	ah,0x41
+				EmitJumpIns(vm, "0F 85", Constant4());	// jne 0x12345678
+			break;
+			case OP_GTF:
+				EmitString("F6 C4 41");			// test	ah,0x41
+				EmitJumpIns(vm, "0F 84", Constant4());	// je 0x12345678
+			break;
+			case OP_GEF:
+				EmitString("F6 C4 01");			// test	ah,0x01
+				EmitJumpIns(vm, "0F 84", Constant4());	// je 0x12345678
 			break;
+			}
+		break;			
 		case OP_NEGI:
-			EmitMovEAXEDI( vm );
-			EmitString( "F7 D8" );		// neg eax
-			EmitCommand( LAST_COMMAND_MOV_EDI_EAX );
+			EmitMovEAXStack(vm, 0);
+			EmitString("F7 D8");				// neg eax
+			EmitCommand(LAST_COMMAND_MOV_STACK_EAX);
 			break;
 		case OP_ADD:
-			EmitMovEAXEDI(vm);			// mov eax, dword ptr [edi]
-			EmitString( "01 47 FC" );	// add dword ptr [edi-4],eax
-			EmitCommand(LAST_COMMAND_SUB_DI_4);		// sub edi, 4
+			EmitMovEAXStack(vm, 0);				// mov eax, dword ptr [edi + ebx * 4]
+			EmitString("01 44 9F FC");			// add dword ptr -4[edi + ebx * 4], eax
+			EmitCommand(LAST_COMMAND_SUB_BL_1);		// sub bl, 1
 			break;
 		case OP_SUB:
-			EmitMovEAXEDI(vm);			// mov eax, dword ptr [edi]
-			EmitString( "29 47 FC" );	// sub dword ptr [edi-4],eax
-			EmitCommand(LAST_COMMAND_SUB_DI_4);		// sub edi, 4
+			EmitMovEAXStack(vm, 0);				// mov eax, dword ptr [edi + ebx * 4]
+			EmitString("29 44 9F FC");			// sub dword ptr -4[edi + ebx * 4], eax
+			EmitCommand(LAST_COMMAND_SUB_BL_1);		// sub bl, 1
 			break;
 		case OP_DIVI:
-			EmitString( "8B 47 FC" );	// mov eax,dword ptr [edi-4]
-			EmitString( "99" );			// cdq
-			EmitString( "F7 3F" );		// idiv dword ptr [edi]
-			EmitString( "89 47 FC" );	// mov dword ptr [edi-4],eax
-			EmitCommand(LAST_COMMAND_SUB_DI_4);		// sub edi, 4
+			EmitString("8B 44 9F FC");			// mov eax,dword ptr -4[edi + ebx * 4]
+			EmitString("99");				// cdq
+			EmitString("F7 3C 9F");				// idiv dword ptr [edi + ebx * 4]
+			EmitString("89 44 9F FC");			// mov dword ptr -4[edi + ebx * 4],eax
+			EmitCommand(LAST_COMMAND_SUB_BL_1);		// sub bl, 1
 			break;
 		case OP_DIVU:
-			EmitString( "8B 47 FC" );	// mov eax,dword ptr [edi-4]
-			EmitString( "33 D2" );		// xor edx, edx
-			EmitString( "F7 37" );		// div dword ptr [edi]
-			EmitString( "89 47 FC" );	// mov dword ptr [edi-4],eax
-			EmitCommand(LAST_COMMAND_SUB_DI_4);		// sub edi, 4
+			EmitString("8B 44 9F FC");			// mov eax,dword ptr -4[edi + ebx * 4]
+			EmitString("33 D2");				// xor edx, edx
+			EmitString("F7 34 9F");				// div dword ptr [edi + ebx * 4]
+			EmitString("89 44 9F FC");			// mov dword ptr -4[edi + ebx * 4],eax
+			EmitCommand(LAST_COMMAND_SUB_BL_1);		// sub bl, 1
 			break;
 		case OP_MODI:
-			EmitString( "8B 47 FC" );	// mov eax,dword ptr [edi-4]
-			EmitString( "99" );			// cdq
-			EmitString( "F7 3F" );		// idiv dword ptr [edi]
-			EmitString( "89 57 FC" );	// mov dword ptr [edi-4],edx
-			EmitCommand(LAST_COMMAND_SUB_DI_4);		// sub edi, 4
+			EmitString("8B 44 9F FC");			// mov eax,dword ptr -4[edi + ebx * 4]
+			EmitString("99" );				// cdq
+			EmitString("F7 3C 9F");				// idiv dword ptr [edi + ebx * 4]
+			EmitString("89 54 9F FC");			// mov dword ptr -4[edi + ebx * 4],edx
+			EmitCommand(LAST_COMMAND_SUB_BL_1);		// sub bl, 1
 			break;
 		case OP_MODU:
-			EmitString( "8B 47 FC" );	// mov eax,dword ptr [edi-4]
-			EmitString( "33 D2" );		// xor edx, edx
-			EmitString( "F7 37" );		// div dword ptr [edi]
-			EmitString( "89 57 FC" );	// mov dword ptr [edi-4],edx
-			EmitCommand(LAST_COMMAND_SUB_DI_4);		// sub edi, 4
+			EmitString("8B 44 9F FC");			// mov eax,dword ptr -4[edi + ebx * 4]
+			EmitString("33 D2");				// xor edx, edx
+			EmitString("F7 34 9F");				// div dword ptr [edi + ebx * 4]
+			EmitString("89 54 9F FC");			// mov dword ptr -4[edi + ebx * 4],edx
+			EmitCommand(LAST_COMMAND_SUB_BL_1);		// sub bl, 1
 			break;
 		case OP_MULI:
-			EmitString( "8B 47 FC" );	// mov eax,dword ptr [edi-4]
-			EmitString( "F7 2F" );		// imul dword ptr [edi]
-			EmitString( "89 47 FC" );	// mov dword ptr [edi-4],eax
-			EmitCommand(LAST_COMMAND_SUB_DI_4);		// sub edi, 4
+			EmitString("8B 44 9F FC");			// mov eax,dword ptr -4[edi + ebx * 4]
+			EmitString("F7 2C 9F");				// imul dword ptr [edi + ebx * 4]
+			EmitString("89 44 9F FC");			// mov dword ptr -4[edi + ebx * 4],eax
+			EmitCommand(LAST_COMMAND_SUB_BL_1);		// sub bl, 1
 			break;
 		case OP_MULU:
-			EmitString( "8B 47 FC" );	// mov eax,dword ptr [edi-4]
-			EmitString( "F7 27" );		// mul dword ptr [edi]
-			EmitString( "89 47 FC" );	// mov dword ptr [edi-4],eax
-			EmitCommand(LAST_COMMAND_SUB_DI_4);		// sub edi, 4
+			EmitString("8B 44 9F FC");			// mov eax,dword ptr -4[edi + ebx * 4]
+			EmitString("F7 24 9F");				// mul dword ptr [edi + ebx * 4]
+			EmitString("89 44 9F FC");			// mov dword ptr -4[edi + ebx * 4],eax
+			EmitCommand(LAST_COMMAND_SUB_BL_1);		// sub bl, 1
 			break;
 		case OP_BAND:
-			EmitMovEAXEDI(vm);			// mov eax, dword ptr [edi]
-			EmitString( "21 47 FC" );	// and dword ptr [edi-4],eax
-			EmitCommand(LAST_COMMAND_SUB_DI_4);		// sub edi, 4
+			EmitMovEAXStack(vm, 0);				// mov eax, dword ptr [edi + ebx * 4]
+			EmitString("21 44 9F FC");			// and dword ptr -4[edi + ebx * 4],eax
+			EmitCommand(LAST_COMMAND_SUB_BL_1);		// sub bl, 1
 			break;
 		case OP_BOR:
-			EmitMovEAXEDI(vm);			// mov eax, dword ptr [edi]
-			EmitString( "09 47 FC" );	// or dword ptr [edi-4],eax
-			EmitCommand(LAST_COMMAND_SUB_DI_4);		// sub edi, 4
+			EmitMovEAXStack(vm, 0);				// mov eax, dword ptr [edi + ebx * 4]
+			EmitString("09 44 9F FC");			// or dword ptr -4[edi + ebx * 4],eax
+			EmitCommand(LAST_COMMAND_SUB_BL_1);		// sub bl, 1
 			break;
 		case OP_BXOR:
-			EmitMovEAXEDI(vm);			// mov eax, dword ptr [edi]
-			EmitString( "31 47 FC" );	// xor dword ptr [edi-4],eax
-			EmitCommand(LAST_COMMAND_SUB_DI_4);		// sub edi, 4
+			EmitMovEAXStack(vm, 0);				// mov eax, dword ptr [edi + ebx * 4]
+			EmitString("31 44 9F FC");			// xor dword ptr -4[edi + ebx * 4],eax
+			EmitCommand(LAST_COMMAND_SUB_BL_1);		// sub bl, 1
 			break;
 		case OP_BCOM:
-			EmitString( "F7 17" );		// not dword ptr [edi]
+			EmitString("F7 14 9F");				// not dword ptr [edi + ebx * 4]
 			break;
 		case OP_LSH:
-			//EmitString( "8B 0F" );				// mov ecx, dword ptr [edi]
-			EmitMovECXEDI( vm );
-			EmitString( "D3 67 FC" );				// shl dword ptr [edi-4], cl
-			EmitCommand(LAST_COMMAND_SUB_DI_4);		// sub edi, 4
+			EmitMovECXStack(vm);
+			EmitString("D3 64 9F FC");			// shl dword ptr -4[edi + ebx * 4], cl
+			EmitCommand(LAST_COMMAND_SUB_BL_1);		// sub bl, 1
 			break;
 		case OP_RSHI:
-			//EmitString( "8B 0F" );				// mov ecx, dword ptr [edi]
-			EmitMovECXEDI( vm );
-			EmitString( "D3 7F FC" );				// sar dword ptr [edi-4], cl
-			EmitCommand(LAST_COMMAND_SUB_DI_4);		// sub edi, 4
+			EmitMovECXStack(vm);
+			EmitString("D3 7C 9F FC");			// sar dword ptr -4[edi + ebx * 4], cl
+			EmitCommand(LAST_COMMAND_SUB_BL_1);		// sub bl, 1
 			break;
 		case OP_RSHU:
-			//EmitString( "8B 0F" );				// mov ecx, dword ptr [edi]
-			EmitMovECXEDI( vm );
-			EmitString( "D3 6F FC" );				// shr dword ptr [edi-4], cl
-			EmitCommand(LAST_COMMAND_SUB_DI_4);		// sub edi, 4
+			EmitMovECXStack(vm);
+			EmitString("D3 6C 9F FC");			// shr dword ptr -4[edi + ebx * 4], cl
+			EmitCommand(LAST_COMMAND_SUB_BL_1);		// sub bl, 1
 			break;
 		case OP_NEGF:
-			EmitString( "D9 07" );		// fld dword ptr [edi]
-			EmitString( "D9 E0" );		// fchs
-			EmitString( "D9 1F" );		// fstp dword ptr [edi]
+			EmitString("D9 04 9F");				// fld dword ptr [edi + ebx * 4]
+			EmitString("D9 E0");				// fchs
+			EmitString("D9 1C 9F");				// fstp dword ptr [edi + ebx * 4]
 			break;
 		case OP_ADDF:
-			EmitString( "D9 47 FC" );	// fld dword ptr [edi-4]
-			EmitString( "D8 07" );		// fadd dword ptr [edi]
-			EmitString( "D9 5F FC" );	// fstp dword ptr [edi-4]
-			EmitCommand(LAST_COMMAND_SUB_DI_4);		// sub edi, 4
+			EmitString("D9 44 9F FC");			// fld dword ptr -4[edi + ebx * 4]
+			EmitString("D8 04 9F");				// fadd dword ptr [edi + ebx * 4]
+			EmitString("D9 5C 9F FC");			// fstp dword ptr -4[edi + ebx * 4]
+			EmitCommand(LAST_COMMAND_SUB_BL_1);		// sub bl, 1
 			break;
 		case OP_SUBF:
-			EmitCommand(LAST_COMMAND_SUB_DI_4);		// sub edi, 4
-			EmitString( "D9 07" );		// fld dword ptr [edi]
-			EmitString( "D8 67 04" );	// fsub dword ptr [edi+4]
-			EmitString( "D9 1F" );		// fstp dword ptr [edi]
+			EmitCommand(LAST_COMMAND_SUB_BL_1);		// sub bl, 1
+			EmitString("D9 04 9F");				// fld dword ptr [edi + ebx * 4]
+			EmitString("D8 64 9F 04");			// fsub dword ptr 4[edi + ebx * 4]
+			EmitString("D9 1C 9F");				// fstp dword ptr [edi + ebx * 4]
 			break;
 		case OP_DIVF:
-			EmitCommand(LAST_COMMAND_SUB_DI_4);		// sub edi, 4
-			EmitString( "D9 07" );		// fld dword ptr [edi]
-			EmitString( "D8 77 04" );	// fdiv dword ptr [edi+4]
-			EmitString( "D9 1F" );		// fstp dword ptr [edi]
+			EmitCommand(LAST_COMMAND_SUB_BL_1);		// sub bl, 1
+			EmitString("D9 04 9F");				// fld dword ptr [edi + ebx * 4]
+			EmitString("D8 74 9F 04");			// fdiv dword ptr 4[edi + ebx * 4]
+			EmitString("D9 1C 9F");				// fstp dword ptr [edi + ebx * 4]
 			break;
 		case OP_MULF:
-			EmitCommand(LAST_COMMAND_SUB_DI_4);		// sub edi, 4
-			EmitString( "D9 07" );		// fld dword ptr [edi]
-			EmitString( "D8 4f 04" );	// fmul dword ptr [edi+4]
-			EmitString( "D9 1F" );		// fstp dword ptr [edi]
+			EmitCommand(LAST_COMMAND_SUB_BL_1);		// sub bl, 1
+			EmitString("D9 04 9F");				// fld dword ptr [edi + ebx * 4]
+			EmitString("D8 4C 9F 04");			// fmul dword ptr 4[edi + ebx * 4]
+			EmitString("D9 1C 9F");				// fstp dword ptr [edi + ebx * 4]
 			break;
 		case OP_CVIF:
-			EmitString( "DB 07" );		// fild dword ptr [edi]
-			EmitString( "D9 1F" );		// fstp dword ptr [edi]
+			EmitString("DB 04 9F");				// fild dword ptr [edi + ebx * 4]
+			EmitString("D9 1C 9F");				// fstp dword ptr [edi + ebx * 4]
 			break;
 		case OP_CVFI:
 #ifndef FTOL_PTR // WHENHELLISFROZENOVER
 			// not IEEE complient, but simple and fast
-			EmitString( "D9 07" );		// fld dword ptr [edi]
-			EmitString( "DB 1F" );		// fistp dword ptr [edi]
+			EmitString("D9 04 9F");				// fld dword ptr [edi + ebx * 4]
+			EmitString("DB 1C 9F");				// fistp dword ptr [edi + ebx * 4]
 #else // FTOL_PTR
 			// call the library conversion function
-			EmitString( "D9 07" );		// fld dword ptr [edi]
-			EmitString( "FF 15" );		// call ftolPtr
-			Emit4( (int)&ftolPtr );
-			EmitCommand(LAST_COMMAND_MOV_EDI_EAX);		// mov dword ptr [edi], eax
+			EmitRexString(0x48, "BA");			// mov edx, Q_VMftol
+			EmitPtr(Q_VMftol);
+			EmitRexString(0x48, "FF D2");			// call edx
+			EmitCommand(LAST_COMMAND_MOV_STACK_EAX);	// mov dword ptr [edi + ebx * 4], eax
 #endif
 			break;
 		case OP_SEX8:
-			EmitString( "0F BE 07" );	// movsx eax, byte ptr [edi]
-			EmitCommand(LAST_COMMAND_MOV_EDI_EAX);		// mov dword ptr [edi], eax
+			EmitString("0F BE 04 9F");			// movsx eax, byte ptr [edi + ebx * 4]
+			EmitCommand(LAST_COMMAND_MOV_STACK_EAX);	// mov dword ptr [edi + ebx * 4], eax
 			break;
 		case OP_SEX16:
-			EmitString( "0F BF 07" );	// movsx eax, word ptr [edi]
-			EmitCommand(LAST_COMMAND_MOV_EDI_EAX);		// mov dword ptr [edi], eax
+			EmitString("0F BF 04 9F");			// movsx eax, word ptr [edi + ebx * 4]
+			EmitCommand(LAST_COMMAND_MOV_STACK_EAX);	// mov dword ptr [edi + ebx * 4], eax
 			break;
 
 		case OP_BLOCK_COPY:
-			// FIXME: range check
-			EmitString( "56" );			// push esi
-			EmitString( "57" );			// push edi
-			EmitString( "8B 37" );		// mov esi,[edi]
-			EmitString( "8B 7F FC" );	// mov edi,[edi-4]
-			EmitString( "B9" );			// mov ecx,0x12345678
-			Emit4( Constant4() >> 2 );
-			EmitString( "B8" );			// mov eax, datamask
-			Emit4( vm->dataMask );
-			EmitString( "BB" );			// mov ebx, database
-			Emit4( (int)vm->dataBase );
-			EmitString( "23 F0" );		// and esi, eax
-			EmitString( "03 F3" );		// add esi, ebx
-			EmitString( "23 F8" );		// and edi, eax
-			EmitString( "03 FB" );		// add edi, ebx
-			EmitString( "F3 A5" );		// rep movsd
-			EmitString( "5F" );			// pop edi
-			EmitString( "5E" );			// pop esi
-			EmitCommand(LAST_COMMAND_SUB_DI_8);		// sub edi, 8
+			EmitString("B8");				// mov eax, 0x12345678
+			Emit4(VM_BLOCK_COPY);
+			EmitString("B9");				// mov ecx, 0x12345678
+			Emit4(Constant4());
+
+			EmitCallRel(vm, callDoSyscallOfs);
+
+			EmitCommand(LAST_COMMAND_SUB_BL_2);		// sub bl, 2
 			break;
 
 		case OP_JUMP:
-			EmitCommand(LAST_COMMAND_SUB_DI_4);	// sub edi, 4
-			EmitString( "8B 47 04" );		// mov eax,dword ptr [edi+4]
+			EmitCommand(LAST_COMMAND_SUB_BL_1);	// sub bl, 1
+			EmitString("8B 44 9F 04");		// mov eax, dword ptr 4[edi + ebx * 4]
 			EmitString("81 F8");			// cmp eax, vm->instructionCount
 			Emit4(vm->instructionCount);
-			EmitString( "73 07" );			// jae +7
-			EmitString( "FF 24 85" );		// jmp dword ptr [instructionPointers + eax * 4]
+#if idx64
+			EmitString("73 04");			// jae +4
+			EmitRexString(0x49, "FF 24 C0");        // jmp qword ptr [r8 + eax * 8]
+#else
+			EmitString("73 07");			// jae +7
+			EmitString("FF 24 85");			// jmp dword ptr [instructionPointers + eax * 4]
 			Emit4((intptr_t) vm->instructionPointers);
-			EmitString( "FF 15" );			// call errJumpPtr
-			Emit4((intptr_t) &errJumpPtr);
+#endif
+			EmitCallErrJump(vm, callDoSyscallOfs);
 			break;
 		default:
 			VMFREE_BUFFERS();
@@ -1471,7 +1690,7 @@ void VM_Compile( vm_t *vm, vmHeader_t *h
 
 	// offset all the instruction pointers for the new location
 	for ( i = 0 ; i < header->instructionCount ; i++ ) {
-		vm->instructionPointers[i] += (int)vm->codeBase;
+		vm->instructionPointers[i] += (intptr_t) vm->codeBase;
 	}
 }
 
@@ -1493,13 +1712,16 @@ VM_CallCompiled
 This function is called directly by the generated code
 ==============
 */
-int	VM_CallCompiled( vm_t *vm, int *args ) {
-	int		stack[1024];
+
+int VM_CallCompiled(vm_t *vm, int *args)
+{
+	byte	stack[OPSTACK_SIZE * 4 + 15];
+	void	*entryPoint;
 	int		programCounter;
-	int		programStack;
-	int		stackOnEntry;
+	int		programStack, stackOnEntry;
 	byte	*image;
-	void	*opStack;
+	int	*opStack;
+	int		opStackOfs;
 
 	currentVM = vm;
 
@@ -1507,8 +1729,7 @@ int	VM_CallCompiled( vm_t *vm, int *args
 	vm->currentlyInterpreting = qtrue;
 
 	// we might be called recursively, so this might not be the very top
-	programStack = vm->programStack;
-	stackOnEntry = programStack;
+	programStack = stackOnEntry = vm->programStack;
 
 	// set up the stack frame
 	image = vm->dataBase;
@@ -1531,47 +1752,67 @@ int	VM_CallCompiled( vm_t *vm, int *args
 	*(int *)&image[ programStack ] = -1;	// will terminate the loop on return
 
 	// off we go into generated code...
-	opStack = &stack;
+	entryPoint = vm->codeBase + vm->entryOfs;
+	opStack = PADP(stack, 16);
+	*opStack = 0xDEADBEEF;
+	opStackOfs = 0;
 
-	{
 #ifdef _MSC_VER
-		void *entryPoint = vm->codeBase + vm->entryOfs;
+  #if idx64
+	opStackOfs = qvmcall64(&programStack, opStack, vm->instructionPointers, vm->dataBase);
+  #else
+	__asm
+	{
+		pushad
 
-		__asm {
-			pushad
-			mov    esi, programStack
-			mov    edi, opStack
-			call   entryPoint
-			mov    programStack, esi
-			mov    opStack, edi
-			popad
-		}
-#else
-		/* These registers are used as scratch registers and are destroyed after the
-		 * call.  Do not use clobber, so they can be used as input for the asm. */
-		unsigned eax;
-		unsigned ebx;
-		unsigned ecx;
-		unsigned edx;
-
-		__asm__ volatile(
-			"call *%6"
-			: "+S" (programStack), "+D" (opStack),
-			  "=a" (eax), "=b" (ebx), "=c" (ecx), "=d" (edx)
-			: "mr" (vm->codeBase + vm->entryOfs)
-			: "cc", "memory"
-		);
-#endif
-	}
+		mov	esi, dword ptr programStack
+		mov	edi, dword ptr opStack
+		mov	ebx, dword ptr opStackOfs
+
+		call	entryPoint
 
-	if ( opStack != &stack[1] ) {
-		Com_Error( ERR_DROP, "opStack corrupted in compiled code" );
+		mov	dword ptr opStackOfs, ebx
+		mov	dword ptr opStack, edi
+		mov	dword ptr programStack, esi
+		
+		popad
 	}
-	if ( programStack != stackOnEntry - 48 ) {
-		Com_Error( ERR_DROP, "programStack corrupted in compiled code" );
+  #endif		
+#elif idx64
+	__asm__ volatile(
+		"movq %5, %%rax\r\n"
+		"movq %3, %%r8\r\n"
+		"movq %4, %%r9\r\n"
+		"push %%r15\r\n"
+		"push %%r14\r\n"
+		"push %%r13\r\n"
+		"push %%r12\r\n"
+		"callq *%%rax\r\n"
+		"pop %%r12\r\n"
+		"pop %%r13\r\n"
+		"pop %%r14\r\n"
+		"pop %%r15\r\n"
+		: "+S" (programStack), "+D" (opStack), "+b" (opStackOfs)
+		: "g" (vm->instructionPointers), "g" (vm->dataBase), "g" (entryPoint)
+		: "cc", "memory", "%rax", "%rcx", "%rdx", "%r8", "%r9", "%r10", "%r11"
+	);
+#else
+	__asm__ volatile(
+		"calll *%3\r\n"
+		: "+S" (programStack), "+D" (opStack), "+b" (opStackOfs)
+		: "g" (entryPoint)
+		: "cc", "memory", "%eax", "%ecx", "%edx"
+	);
+#endif
+
+	if(opStackOfs != 1 || *opStack != 0xDEADBEEF)
+	{
+		Com_Error(ERR_DROP, "opStack corrupted in compiled code");
 	}
+	if(programStack != stackOnEntry - 48)
+		Com_Error(ERR_DROP, "programStack corrupted in compiled code");
 
 	vm->programStack = stackOnEntry;
 
-	return *(int *)opStack;
+	return opStack[opStackOfs];
 }
Index: code/qcommon/vm_x86_64.c
===================================================================
--- code/qcommon/vm_x86_64.c.orig
+++ code/qcommon/vm_x86_64.c
@@ -77,7 +77,7 @@ static void VM_Destroy_Compiled(vm_t* se
   rsi		scratch
   rdi		program frame pointer (programStack)
   r8		pointer data (vm->dataBase)
-  r9		opStack data base (opStack)
+  r9		opStack base (opStack)
   r10		start of generated code
 */
 
@@ -257,10 +257,10 @@ void emit(const char* fmt, ...)
 #endif
 
 #define STACK_PUSH(bytes) \
-	emit("addb $0x%x, %%bl", bytes); \
+	emit("addb $0x%x, %%bl", bytes >> 2); \
 
 #define STACK_POP(bytes) \
-	emit("subb $0x%x, %%bl", bytes); \
+	emit("subb $0x%x, %%bl", bytes >> 2); \
 
 #define CHECK_INSTR_REG(reg) \
 	emit("cmpl $%u, %%"#reg, header->instructionCount); \
@@ -272,7 +272,7 @@ void emit(const char* fmt, ...)
 #define PREPARE_JMP(reg) \
 	CHECK_INSTR_REG(reg); \
 	emit("movq $%"PRIu64", %%rsi", (intptr_t)vm->instructionPointers); \
-	emit("movl (%%rsi, %%rax, 4), %%eax"); \
+	emit("movl (%%rsi, %%rax, 8), %%eax"); \
 	emit("addq %%r10, %%rax")
 
 #define CHECK_INSTR(nr) \
@@ -295,7 +295,7 @@ void emit(const char* fmt, ...)
 		got_const = 0; \
 		vm->instructionPointers[instruction-1] = assembler_get_code_size(); \
 		STACK_PUSH(4); \
-		emit("movl $%d, (%%r9, %%rbx, 1)", const_value); \
+		emit("movl $%d, (%%r9, %%rbx, 4)", const_value); \
 	}
 #else
 #define MAYBE_EMIT_CONST()
@@ -305,8 +305,8 @@ void emit(const char* fmt, ...)
 #define IJ(op) \
 	MAYBE_EMIT_CONST(); \
 	STACK_POP(8); \
-	emit("movl 4(%%r9, %%rbx, 1), %%eax"); \
-	emit("cmpl 8(%%r9, %%rbx, 1), %%eax"); \
+	emit("movl 4(%%r9, %%rbx, 4), %%eax"); \
+	emit("cmpl 8(%%r9, %%rbx, 4), %%eax"); \
 	emit(op " i_%08x", instruction+1); \
 	JMPIARG(); \
 	neednilabel = 1
@@ -315,8 +315,8 @@ void emit(const char* fmt, ...)
 #define FJ(bits, op) \
 	MAYBE_EMIT_CONST(); \
 	STACK_POP(8); \
-	emit("flds 4(%%r9, %%rbx, 1)");\
-	emit("fcomps 8(%%r9, %%rbx, 1)");\
+	emit("flds 4(%%r9, %%rbx, 4)");\
+	emit("fcomps 8(%%r9, %%rbx, 4)");\
 	emit("fnstsw %%ax");\
 	emit("testb $" #bits ", %%ah");\
 	emit(op " i_%08x", instruction+1);\
@@ -328,8 +328,8 @@ void emit(const char* fmt, ...)
 #define XJ(op) \
 	MAYBE_EMIT_CONST(); \
 	STACK_POP(8); \
-	emit("movss 4(%%r9, %%rbx, 1), %%xmm0");\
-	emit("ucomiss 8(%%r9, %%rbx, 1), %%xmm0");\
+	emit("movss 4(%%r9, %%rbx, 4), %%xmm0");\
+	emit("ucomiss 8(%%r9, %%rbx, 4), %%xmm0");\
 	emit("jp i_%08x", instruction+1);\
 	emit(op " i_%08x", instruction+1);\
 	JMPIARG(); \
@@ -338,35 +338,35 @@ void emit(const char* fmt, ...)
 
 #define SIMPLE(op) \
 	MAYBE_EMIT_CONST(); \
-	emit("movl (%%r9, %%rbx, 1), %%eax"); \
+	emit("movl (%%r9, %%rbx, 4), %%eax"); \
 	STACK_POP(4); \
-	emit(op " %%eax, (%%r9, %%rbx, 1)")
+	emit(op " %%eax, (%%r9, %%rbx, 4)")
 
 #ifdef USE_X87
 #define FSIMPLE(op) \
 	MAYBE_EMIT_CONST(); \
 	STACK_POP(4); \
-	emit("flds (%%r9, %%rbx, 1)"); \
-	emit(op " 4(%%r9, %%rbx, 1)"); \
-	emit("fstps (%%r9, %%rbx, 1)")
+	emit("flds (%%r9, %%rbx, 4)"); \
+	emit(op " 4(%%r9, %%rbx, 4)"); \
+	emit("fstps (%%r9, %%rbx, 4)")
 #define XSIMPLE(op)
 #else
 #define FSIMPLE(op)
 #define XSIMPLE(op) \
 	MAYBE_EMIT_CONST(); \
 	STACK_POP(4); \
-	emit("movss (%%r9, %%rbx, 1), %%xmm0"); \
-	emit(op " 4(%%r9, %%rbx, 1), %%xmm0"); \
-	emit("movss %%xmm0, (%%r9, %%rbx, 1)")
+	emit("movss (%%r9, %%rbx, 4), %%xmm0"); \
+	emit(op " 4(%%r9, %%rbx, 4), %%xmm0"); \
+	emit("movss %%xmm0, (%%r9, %%rbx, 4)")
 #endif
 
 #define SHIFT(op) \
 	MAYBE_EMIT_CONST(); \
 	STACK_POP(4); \
-	emit("movl 4(%%r9, %%rbx, 1), %%ecx"); \
-	emit("movl (%%r9, %%rbx, 1), %%eax"); \
+	emit("movl 4(%%r9, %%rbx, 4), %%ecx"); \
+	emit("movl (%%r9, %%rbx, 4), %%eax"); \
 	emit(op " %%cl, %%eax"); \
-	emit("movl %%eax, (%%r9, %%rbx, 1)")
+	emit("movl %%eax, (%%r9, %%rbx, 4)")
 
 #ifdef DEBUG_VM
 #define NOTIMPL(x) \
@@ -381,21 +381,6 @@ static void* getentrypoint(vm_t* vm)
        return vm->codeBase;
 }
 
-static void CROSSCALL block_copy_vm(unsigned dest, unsigned src, unsigned count)
-{
-	unsigned dataMask = currentVM->dataMask;
-
-	if ((dest & dataMask) != dest
-	|| (src & dataMask) != src
-	|| ((dest+count) & dataMask) != dest + count
-	|| ((src+count) & dataMask) != src + count)
-	{
-		Com_Error(ERR_DROP, "OP_BLOCK_COPY out of range!");
-	}
-
-	memcpy(currentVM->dataBase+dest, currentVM->dataBase+src, count);
-}
-
 static void CROSSCALL eop(void)
 {
 	Com_Error(ERR_DROP, "End of program reached without return!");
@@ -564,7 +549,7 @@ void VM_Compile( vm_t *vm, vmHeader_t *h
 				else
 				{
 					MAYBE_EMIT_CONST();
-					emit("movl (%%r9, %%rbx, 1), %%eax");  // get instr from stack
+					emit("movl (%%r9, %%rbx, 4), %%eax");  // get instr from stack
 					STACK_POP(4);
 
 					emit("orl %%eax, %%eax");
@@ -605,7 +590,7 @@ void VM_Compile( vm_t *vm, vmHeader_t *h
 				emit("pop %%rdi");
 //				emit("frstor 4(%%r9, %%rsi, 1)");
 				STACK_PUSH(4);
-				emit("movl %%eax, (%%r9, %%rbx, 1)"); // store return value
+				emit("movl %%eax, (%%r9, %%rbx, 4)"); // store return value
 				neednilabel = 1;
 				break;
 			case OP_PUSH:
@@ -623,7 +608,7 @@ void VM_Compile( vm_t *vm, vmHeader_t *h
 				const_value = iarg;
 #else
 				STACK_PUSH(4);
-				emit("movl $%d, (%%r9, %%rbx, 1)", iarg);
+				emit("movl $%d, (%%r9, %%rbx, 4)", iarg);
 #endif
 				break;
 			case OP_LOCAL:
@@ -631,7 +616,7 @@ void VM_Compile( vm_t *vm, vmHeader_t *h
 				emit("movl %%edi, %%esi");
 				emit("addl $%d,%%esi", iarg);
 				STACK_PUSH(4);
-				emit("movl %%esi, (%%r9, %%rbx, 1)");
+				emit("movl %%esi, (%%r9, %%rbx, 4)");
 				break;
 			case OP_JUMP:
 				if(got_const) {
@@ -639,7 +624,7 @@ void VM_Compile( vm_t *vm, vmHeader_t *h
 					got_const = 0;
 					JMPIARG();
 				} else {
-					emit("movl (%%r9, %%rbx, 1), %%eax"); // get instr from stack
+					emit("movl (%%r9, %%rbx, 4), %%eax"); // get instr from stack
 					STACK_POP(4);
 
 					PREPARE_JMP(eax);
@@ -685,8 +670,8 @@ void VM_Compile( vm_t *vm, vmHeader_t *h
 #ifndef USE_X87
 				MAYBE_EMIT_CONST();
 				STACK_POP(8);
-				emit("movss 4(%%r9, %%rbx, 1), %%xmm0");
-				emit("ucomiss 8(%%r9, %%rbx, 1), %%xmm0");
+				emit("movss 4(%%r9, %%rbx, 4), %%xmm0");
+				emit("ucomiss 8(%%r9, %%rbx, 4), %%xmm0");
 				emit("jp dojump_i_%08x", instruction);
 				emit("jz i_%08x", instruction+1);
 				emit("dojump_i_%08x:", instruction);
@@ -712,54 +697,54 @@ void VM_Compile( vm_t *vm, vmHeader_t *h
 				break;
 			case OP_LOAD1:
 				MAYBE_EMIT_CONST();
-				emit("movl (%%r9, %%rbx, 1), %%eax"); // get value from stack
+				emit("movl (%%r9, %%rbx, 4), %%eax"); // get value from stack
 				RANGECHECK(eax, 1);
 				emit("movb (%%r8, %%rax, 1), %%al"); // deref into eax
 				emit("andq $255, %%rax");
-				emit("movl %%eax, (%%r9, %%rbx, 1)"); // store on stack
+				emit("movl %%eax, (%%r9, %%rbx, 4)"); // store on stack
 				break;
 			case OP_LOAD2:
 				MAYBE_EMIT_CONST();
-				emit("movl (%%r9, %%rbx, 1), %%eax"); // get value from stack
+				emit("movl (%%r9, %%rbx, 4), %%eax"); // get value from stack
 				RANGECHECK(eax, 2);
 				emit("movw (%%r8, %%rax, 1), %%ax"); // deref into eax
-				emit("movl %%eax, (%%r9, %%rbx, 1)"); // store on stack
+				emit("movl %%eax, (%%r9, %%rbx, 4)"); // store on stack
 				break;
 			case OP_LOAD4:
 				MAYBE_EMIT_CONST();
-				emit("movl (%%r9, %%rbx, 1), %%eax"); // get value from stack
+				emit("movl (%%r9, %%rbx, 4), %%eax"); // get value from stack
 				RANGECHECK(eax, 4); // not a pointer!?
 				emit("movl (%%r8, %%rax, 1), %%eax"); // deref into eax
-				emit("movl %%eax, (%%r9, %%rbx, 1)"); // store on stack
+				emit("movl %%eax, (%%r9, %%rbx, 4)"); // store on stack
 				break;
 			case OP_STORE1:
 				MAYBE_EMIT_CONST();
-				emit("movl (%%r9, %%rbx, 1), %%eax"); // get value from stack
+				emit("movl (%%r9, %%rbx, 4), %%eax"); // get value from stack
 				STACK_POP(8);
 				emit("andq $255, %%rax");
-				emit("movl 4(%%r9, %%rbx, 1), %%esi"); // get pointer from stack
+				emit("movl 4(%%r9, %%rbx, 4), %%esi"); // get pointer from stack
 				RANGECHECK(esi, 1);
 				emit("movb %%al, (%%r8, %%rsi, 1)"); // store in memory
 				break;
 			case OP_STORE2:
 				MAYBE_EMIT_CONST();
-				emit("movl (%%r9, %%rbx, 1), %%eax"); // get value from stack
+				emit("movl (%%r9, %%rbx, 4), %%eax"); // get value from stack
 				STACK_POP(8);
-				emit("movl 4(%%r9, %%rbx, 1), %%esi"); // get pointer from stack
+				emit("movl 4(%%r9, %%rbx, 4), %%esi"); // get pointer from stack
 				RANGECHECK(esi, 2);
 				emit("movw %%ax, (%%r8, %%rsi, 1)"); // store in memory
 				break;
 			case OP_STORE4:
 				MAYBE_EMIT_CONST();
-				emit("movl (%%r9, %%rbx, 1), %%eax"); // get value from stack
+				emit("movl (%%r9, %%rbx, 4), %%eax"); // get value from stack
 				STACK_POP(8);
-				emit("movl 4(%%r9, %%rbx, 1), %%esi"); // get pointer from stack
+				emit("movl 4(%%r9, %%rbx, 4), %%esi"); // get pointer from stack
 				RANGECHECK(esi, 4);
 				emit("movl %%eax, (%%r8, %%rsi, 1)"); // store in memory
 				break;
 			case OP_ARG:
 				MAYBE_EMIT_CONST();
-				emit("movl (%%r9, %%rbx, 1), %%eax"); // get value from stack
+				emit("movl (%%r9, %%rbx, 4), %%eax"); // get value from stack
 				STACK_POP(4);
 				emit("movl $0x%hx, %%esi", barg);
 				emit("addl %%edi, %%esi");
@@ -779,10 +764,10 @@ void VM_Compile( vm_t *vm, vmHeader_t *h
 				emit("andq $127, %%rsi");  //   |
 				emit("subq %%rsi, %%rsp"); // <-+
 				emit("push %%rsi");
-				emit("movl 4(%%r9, %%rbx, 1), %%edi");  // 1st argument dest
-				emit("movl 8(%%r9, %%rbx, 1), %%rsi");  // 2nd argument src
+				emit("movl 4(%%r9, %%rbx, 4), %%edi");  // 1st argument dest
+				emit("movl 8(%%r9, %%rbx, 4), %%rsi");  // 2nd argument src
 				emit("movl $%d, %%edx", iarg); // 3rd argument count
-				emit("movq $%"PRIu64", %%rax", (intptr_t) block_copy_vm);
+				emit("movq $%"PRIu64", %%rax", (intptr_t) VM_BlockCopy);
 				emit("callq *%%rax");
 				emit("pop %%rsi");
 				emit("addq %%rsi, %%rsp");
@@ -794,21 +779,21 @@ void VM_Compile( vm_t *vm, vmHeader_t *h
 				break;
 			case OP_SEX8:
 				MAYBE_EMIT_CONST();
-				emit("movw (%%r9, %%rbx, 1), %%ax");
+				emit("movw (%%r9, %%rbx, 4), %%ax");
 				emit("andq $255, %%rax");
 				emit("cbw");
 				emit("cwde");
-				emit("movl %%eax, (%%r9, %%rbx, 1)");
+				emit("movl %%eax, (%%r9, %%rbx, 4)");
 				break;
 			case OP_SEX16:
 				MAYBE_EMIT_CONST();
-				emit("movw (%%r9, %%rbx, 1), %%ax");
+				emit("movw (%%r9, %%rbx, 4), %%ax");
 				emit("cwde");
-				emit("movl %%eax, (%%r9, %%rbx, 1)");
+				emit("movl %%eax, (%%r9, %%rbx, 4)");
 				break;
 			case OP_NEGI:
 				MAYBE_EMIT_CONST();
-				emit("negl (%%r9, %%rbx, 1)");
+				emit("negl (%%r9, %%rbx, 4)");
 				break;
 			case OP_ADD:
 				SIMPLE("addl");
@@ -819,49 +804,49 @@ void VM_Compile( vm_t *vm, vmHeader_t *h
 			case OP_DIVI:
 				MAYBE_EMIT_CONST();
 				STACK_POP(4);
-				emit("movl (%%r9, %%rbx, 1), %%eax");
+				emit("movl (%%r9, %%rbx, 4), %%eax");
 				emit("cdq");
-				emit("idivl 4(%%r9, %%rbx, 1)");
-				emit("movl %%eax, (%%r9, %%rbx, 1)");
+				emit("idivl 4(%%r9, %%rbx, 4)");
+				emit("movl %%eax, (%%r9, %%rbx, 4)");
 				break;
 			case OP_DIVU:
 				MAYBE_EMIT_CONST();
 				STACK_POP(4);
-				emit("movl (%%r9, %%rbx, 1), %%eax");
+				emit("movl (%%r9, %%rbx, 4), %%eax");
 				emit("xorq %%rdx, %%rdx");
-				emit("divl 4(%%r9, %%rbx, 1)");
-				emit("movl %%eax, (%%r9, %%rbx, 1)");
+				emit("divl 4(%%r9, %%rbx, 4)");
+				emit("movl %%eax, (%%r9, %%rbx, 4)");
 				break;
 			case OP_MODI:
 				MAYBE_EMIT_CONST();
 				STACK_POP(4);
-				emit("movl (%%r9, %%rbx, 1), %%eax");
+				emit("movl (%%r9, %%rbx, 4), %%eax");
 				emit("xorl %%edx, %%edx");
 				emit("cdq");
-				emit("idivl 4(%%r9, %%rbx, 1)");
-				emit("movl %%edx, (%%r9, %%rbx, 1)");
+				emit("idivl 4(%%r9, %%rbx, 4)");
+				emit("movl %%edx, (%%r9, %%rbx, 4)");
 				break;
 			case OP_MODU:
 				MAYBE_EMIT_CONST();
 				STACK_POP(4);
-				emit("movl (%%r9, %%rbx, 1), %%eax");
+				emit("movl (%%r9, %%rbx, 4), %%eax");
 				emit("xorl %%edx, %%edx");
-				emit("divl 4(%%r9, %%rbx, 1)");
-				emit("movl %%edx, (%%r9, %%rbx, 1)");
+				emit("divl 4(%%r9, %%rbx, 4)");
+				emit("movl %%edx, (%%r9, %%rbx, 4)");
 				break;
 			case OP_MULI:
 				MAYBE_EMIT_CONST();
 				STACK_POP(4);
-				emit("movl (%%r9, %%rbx, 1), %%eax");
-				emit("imull 4(%%r9, %%rbx, 1)");
-				emit("movl %%eax, (%%r9, %%rbx, 1)");
+				emit("movl (%%r9, %%rbx, 4), %%eax");
+				emit("imull 4(%%r9, %%rbx, 4)");
+				emit("movl %%eax, (%%r9, %%rbx, 4)");
 				break;
 			case OP_MULU:
 				MAYBE_EMIT_CONST();
 				STACK_POP(4);
-				emit("movl (%%r9, %%rbx, 1), %%eax");
-				emit("mull 4(%%r9, %%rbx, 1)");
-				emit("movl %%eax, (%%r9, %%rbx, 1)");
+				emit("movl (%%r9, %%rbx, 4), %%eax");
+				emit("mull 4(%%r9, %%rbx, 4)");
+				emit("movl %%eax, (%%r9, %%rbx, 4)");
 				break;
 			case OP_BAND:
 				SIMPLE("andl");
@@ -874,7 +859,7 @@ void VM_Compile( vm_t *vm, vmHeader_t *h
 				break;
 			case OP_BCOM:
 				MAYBE_EMIT_CONST();
-				emit("notl (%%r9, %%rbx, 1)");
+				emit("notl (%%r9, %%rbx, 4)");
 				break;
 			case OP_LSH:
 				SHIFT("shl");
@@ -888,12 +873,12 @@ void VM_Compile( vm_t *vm, vmHeader_t *h
 			case OP_NEGF:
 				MAYBE_EMIT_CONST();
 #ifdef USE_X87
-				emit("flds (%%r9, %%rbx, 1)");
+				emit("flds (%%r9, %%rbx, 4)");
 				emit("fchs");
-				emit("fstps (%%r9, %%rbx, 1)");
+				emit("fstps (%%r9, %%rbx, 4)");
 #else
 				emit("movl $0x80000000, %%eax");
-				emit("xorl %%eax, (%%r9, %%rbx, 1)");
+				emit("xorl %%eax, (%%r9, %%rbx, 4)");
 #endif
 				break;
 			case OP_ADDF:
@@ -915,27 +900,27 @@ void VM_Compile( vm_t *vm, vmHeader_t *h
 			case OP_CVIF:
 				MAYBE_EMIT_CONST();
 #ifdef USE_X87
-				emit("filds (%%r9, %%rbx, 1)");
-				emit("fstps (%%r9, %%rbx, 1)");
+				emit("filds (%%r9, %%rbx, 4)");
+				emit("fstps (%%r9, %%rbx, 4)");
 #else
-				emit("movl (%%r9, %%rbx, 1), %%eax");
+				emit("movl (%%r9, %%rbx, 4), %%eax");
 				emit("cvtsi2ss %%eax, %%xmm0");
-				emit("movss %%xmm0, (%%r9, %%rbx, 1)");
+				emit("movss %%xmm0, (%%r9, %%rbx, 4)");
 #endif
 				break;
 			case OP_CVFI:
 				MAYBE_EMIT_CONST();
 #ifdef USE_X87
-				emit("flds (%%r9, %%rbx, 1)");
-				emit("fnstcw 4(%%r9, %%rbx, 1)");
-				emit("movw $0x0F7F, 8(%%r9, %%rbx, 1)"); // round toward zero
-				emit("fldcw 8(%%r9, %%rbx, 1)");
-				emit("fistpl (%%r9, %%rbx, 1)");
-				emit("fldcw 4(%%r9, %%rbx, 1)");
+				emit("flds (%%r9, %%rbx, 4)");
+				emit("fnstcw 4(%%r9, %%rbx, 4)");
+				emit("movw $0x0F7F, 8(%%r9, %%rbx, 4)"); // round toward zero
+				emit("fldcw 8(%%r9, %%rbx, 4)");
+				emit("fistpl (%%r9, %%rbx, 4)");
+				emit("fldcw 4(%%r9, %%rbx, 4)");
 #else
-				emit("movss (%%r9, %%rbx, 1), %%xmm0");
+				emit("movss (%%r9, %%rbx, 4), %%xmm0");
 				emit("cvttss2si %%xmm0, %%eax");
-				emit("movl %%eax, (%%r9, %%rbx, 1)");
+				emit("movl %%eax, (%%r9, %%rbx, 4)");
 #endif
 				break;
 			default:
@@ -1029,7 +1014,9 @@ This function is called directly by the
 static char* memData;
 #endif
 
-int	VM_CallCompiled( vm_t *vm, int *args ) {
+int VM_CallCompiled(vm_t *vm, int *args)
+{
+	int stack[OPSTACK_SIZE + 3];
 	int		programCounter;
 	int		programStack;
 	int		stackOnEntry;
@@ -1037,7 +1024,6 @@ int	VM_CallCompiled( vm_t *vm, int *args
 	byte	*image;
 	void	*entryPoint;
 	int		*opStack;
-	int stack[OPSTACK_SIZE + 3] = { 0xDEADBEEF };
 
 	currentVM = vm;
 	
@@ -1079,22 +1065,30 @@ int	VM_CallCompiled( vm_t *vm, int *args
 	entryPoint = getentrypoint(vm);
 	opStack = PADP(stack, 4);
 
+	*opStack = 0xDEADBEEF;
+	opStackRet = 0;
+
 	__asm__ __volatile__ (
-		"	movq $0x0,%%rbx		\r\n" \
-		"	movl %5,%%edi		\r\n" \
 		"	movq %4,%%r8		\r\n" \
 		"	movq %3,%%r9		\r\n" \
 		"	movq %2,%%r10		\r\n" \
+		"	push %%r15		\r\n" \
+		"	push %%r14		\r\n" \
+		"	push %%r13		\r\n" \
+		"	push %%r12		\r\n" \
 		"       subq $24, %%rsp # fix alignment as call pushes one value \r\n" \
 		"	callq *%%r10		\r\n" \
 		"       addq $24, %%rsp         \r\n" \
-		"	movl %%edi, %0		\r\n" \
-		"	movq %%rbx, %1		\r\n" \
-		: "=g" (programStack), "=g" (opStackRet)
+		"	pop %%r12		\r\n" \
+		"	pop %%r13		\r\n" \
+		"	pop %%r14		\r\n" \
+		"	pop %%r15		\r\n"
+		: "+D" (programStack), "+b" (opStackRet)
 		: "g" (entryPoint), "g" (opStack), "g" (vm->dataBase), "g" (programStack)
-		: "%rsi", "%rdi", "%rax", "%rbx", "%rcx", "%rdx", "%r8", "%r9", "%r10", "%r15", "%xmm0"
+		: "%rsi", "%rax", "%rcx", "%rdx", "%r8", "%r9", "%r10", "%r11", "%xmm0"
 	);
-	if(opStackRet != 4 || *opStack != 0xDEADBEEF)
+
+	if(opStackRet != 1 || *opStack != 0xDEADBEEF)
 		Com_Error(ERR_DROP, "opStack corrupted in compiled code (offset %ld)", opStackRet);
 
 	if ( programStack != stackOnEntry - 48 ) {
Index: code/sys/sys_unix.c
===================================================================
--- code/sys/sys_unix.c.orig
+++ code/sys/sys_unix.c
@@ -36,6 +36,7 @@ Foundation, Inc., 51 Franklin St, Fifth
 #include <pwd.h>
 #include <libgen.h>
 #include <fcntl.h>
+#include <fenv.h>
 
 qboolean stdinIsATTY;
 
@@ -245,31 +246,6 @@ int Sys_Milliseconds (void)
 	return curtime;
 }
 
-#if !id386
-/*
-==================
-fastftol
-==================
-*/
-long fastftol( float f )
-{
-	return (long)f;
-}
-
-/*
-==================
-Sys_SnapVector
-==================
-*/
-void Sys_SnapVector( float *v )
-{
-	v[0] = rint(v[0]);
-	v[1] = rint(v[1]);
-	v[2] = rint(v[2]);
-}
-#endif
-
-
 /*
 ==================
 Sys_RandomBytes
@@ -878,6 +854,12 @@ void Sys_GLimpInit( void )
 	// NOP
 }
 
+void Sys_SetFloatEnv(void)
+{
+	// rounding towards 0
+	fesetround(FE_TOWARDZERO);
+}
+
 /*
 ==============
 Sys_PlatformInit
Index: code/sys/sys_main.c
===================================================================
--- code/sys/sys_main.c.orig
+++ code/sys/sys_main.c
@@ -427,35 +427,23 @@ void Sys_UnloadDll( void *dllHandle )
 Sys_LoadDll
 
 Used to load a development dll instead of a virtual machine
-#1 look in fs_homepath
-#2 look in fs_basepath
 =================
 */
-void *Sys_LoadDll( const char *name,
-	intptr_t (**entryPoint)(int, ...),
-	intptr_t (*systemcalls)(intptr_t, ...) )
+void *Sys_LoadDll(const char *name,
+	intptr_t (QDECL **entryPoint)(int, ...),
+	intptr_t (*systemcalls)(intptr_t, ...))
 {
-	void  *libHandle;
-	void  (*dllEntry)( intptr_t (*syscallptr)(intptr_t, ...) );
-	char  fname[MAX_OSPATH];
-	char  *netpath;
+	void *libHandle;
+	void (*dllEntry)(intptr_t (*syscallptr)(intptr_t, ...));
 
-	assert( name );
+	assert(name);
 
-	Com_sprintf(fname, sizeof(fname), "%s" ARCH_STRING DLL_EXT, name);
+	Com_Printf( "Loading DLL file: %s\n", name);
+	libHandle = Sys_LoadLibrary(name);
 
-	netpath = FS_FindDll(fname);
-
-	if(!netpath) {
-		Com_Printf( "Sys_LoadDll(%s) could not find it\n", fname );
-		return NULL;
-	}
-
-	Com_Printf( "Loading DLL file: %s\n", netpath);
-	libHandle = Sys_LoadLibrary(netpath);
-
-	if(!libHandle) {
-		Com_Printf( "Sys_LoadDll(%s) failed:\n\"%s\"\n", netpath, Sys_LibraryError() );
+	if(!libHandle)
+	{
+		Com_Printf("Sys_LoadDll(%s) failed:\n\"%s\"\n", name, Sys_LibraryError());
 		return NULL;
 	}
 
Index: code/client/snd_wavelet.c
===================================================================
--- code/client/snd_wavelet.c.orig
+++ code/client/snd_wavelet.c
@@ -23,8 +23,6 @@ Foundation, Inc., 51 Franklin St, Fifth
 
 #include "snd_local.h"
 
-long myftol( float f );
-
 #define C0 0.4829629131445341
 #define C1 0.8365163037378079
 #define C2 0.2241438680420134
Index: code/client/cl_cgame.c
===================================================================
--- code/client/cl_cgame.c.orig
+++ code/client/cl_cgame.c
@@ -595,6 +595,7 @@ intptr_t CL_CgameSystemCalls( intptr_t *
 		return re.RegisterShaderNoMip( VMA(1) );
 	case CG_R_REGISTERFONT:
 		re.RegisterFont( VMA(1), args[2], VMA(3));
+		return 0;
 	case CG_R_CLEARSCENE:
 		re.ClearScene();
 		return 0;
@@ -706,7 +707,7 @@ intptr_t CL_CgameSystemCalls( intptr_t *
 	case CG_REAL_TIME:
 		return Com_RealTime( VMA(1) );
 	case CG_SNAPVECTOR:
-		Sys_SnapVector( VMA(1) );
+		Q_SnapVector(VMA(1));
 		return 0;
 
 	case CG_CIN_PLAYCINEMATIC:
Index: code/asm/vm_x86_64.asm
===================================================================
--- /dev/null
+++ code/asm/vm_x86_64.asm
@@ -0,0 +1,76 @@
+; ===========================================================================
+; Copyright (C) 2011 Thilo Schulz <thilo@tjps.eu>
+; 
+; This file is part of Quake III Arena source code.
+; 
+; Quake III Arena source code 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.
+; 
+; Quake III Arena source code 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 Quake III Arena source code; if not, write to the Free Software
+; Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+; ===========================================================================
+
+; Call wrapper for vm_x86 when built with MSVC in 64 bit mode,
+; since MSVC does not support inline x64 assembler code anymore.
+;
+; assumes __fastcall calling convention
+
+DoSyscall PROTO
+
+.code
+
+; Call to static void DoSyscall(int syscallNum, int programStack, int *opStackBase, uint8_t opStackOfs, intptr_t arg)
+
+qsyscall64 PROC
+  sub rsp, 28h						; after this esp will be aligned to 16 byte boundary
+  mov qword ptr [rsp + 20h], rcx	; 5th parameter "arg" is passed on stack
+  mov r9b, bl						; opStackOfs
+  mov r8, rdi						; opStackBase
+  mov edx, esi						; programStack
+  mov ecx, eax						; syscallNum
+  mov rax, DoSyscall				; store call address of DoSyscall in rax
+  call rax
+  add rsp, 28h
+  ret
+qsyscall64 ENDP
+
+
+; Call to compiled code after setting up the register environment for the VM
+; prototype:
+; uint8_t qvmcall64(int *programStack, int *opStack, intptr_t *instructionPointers, byte *dataBase);
+
+qvmcall64 PROC
+  push rsi							; push non-volatile registers to stack
+  push rdi
+  push rbx
+  ; need to save pointer in rcx so we can write back the programData value to caller
+  push rcx
+
+  ; registers r8 and r9 have correct value already thanx to __fastcall
+  xor rbx, rbx						; opStackOfs starts out being 0
+  mov rdi, rdx						; opStack
+  mov esi, dword ptr [rcx]			; programStack
+  
+  call qword ptr [r8]				; instructionPointers[0] is also the entry point
+
+  pop rcx
+
+  mov dword ptr [rcx], esi			; write back the programStack value
+  mov al, bl						; return opStack offset
+
+  pop rbx
+  pop rdi
+  pop rsi
+  
+  ret
+qvmcall64 ENDP
+
+end
Index: code/qcommon/qcommon.h
===================================================================
--- code/qcommon/qcommon.h.orig
+++ code/qcommon/qcommon.h
@@ -628,7 +628,7 @@ qboolean FS_FileExists( const char *file
 
 qboolean FS_CreatePath (char *OSPath);
 
-char *FS_FindDll( const char *filename );
+vmInterpret_t FS_FindVM(void **startSearch, char *found, int foundlen, const char *name, int enableDll);
 
 char   *FS_BuildOSPath( const char *base, const char *game, const char *qpath );
 qboolean FS_CompareZipChecksum(const char *zipfile);
@@ -644,9 +644,9 @@ fileHandle_t	FS_FCreateOpenPipeFile( con
 // will properly create any needed paths and deal with seperater character issues
 
 fileHandle_t FS_SV_FOpenFileWrite( const char *filename );
-int		FS_SV_FOpenFileRead( const char *filename, fileHandle_t *fp );
+long		FS_SV_FOpenFileRead( const char *filename, fileHandle_t *fp );
 void	FS_SV_Rename( const char *from, const char *to );
-int		FS_FOpenFileRead( const char *qpath, fileHandle_t *file, qboolean uniqueFILE );
+long		FS_FOpenFileRead( const char *qpath, fileHandle_t *file, qboolean uniqueFILE );
 // if uniqueFILE is true, then a new FILE will be fopened even if the file
 // is found in an already open pak file.  If uniqueFILE is false, you must call
 // FS_FCloseFile instead of fclose, otherwise the pak FILE would be improperly closed
@@ -665,7 +665,8 @@ int		FS_Read( void *buffer, int len, fil
 void	FS_FCloseFile( fileHandle_t f );
 // note: you can't just fclose from another DLL, due to MS libc issues
 
-int		FS_ReadFile( const char *qpath, void **buffer );
+long	FS_ReadFileDir(const char *qpath, void *searchPath, void **buffer);
+long	FS_ReadFile(const char *qpath, void **buffer);
 // returns the length of the file
 // a null buffer will just return the file length without loading
 // as a quick check for existance. -1 length == not present
@@ -682,7 +683,7 @@ void	FS_FreeFile( void *buffer );
 void	FS_WriteFile( const char *qpath, const void *buffer, int size );
 // writes a complete file, creating any subdirectories needed
 
-int		FS_filelength( fileHandle_t f );
+long FS_filelength(fileHandle_t f);
 // doesn't work for files that are opened from a pack file
 
 int		FS_FTell( fileHandle_t f );
@@ -740,6 +741,7 @@ void	FS_FilenameCompletion( const char *
 		qboolean stripExt, void(*callback)(const char *s), qboolean allowNonPureFilesOnDisk );
 
 const char *FS_GetCurrentGameDir(void);
+qboolean FS_Which(const char *filename, void *searchPath);
 
 /*
 ==============================================================
Index: Makefile
===================================================================
--- Makefile.orig
+++ Makefile
@@ -172,6 +172,10 @@ ifndef BUILD_SDK_DIFF
 SDK_DIFF=0
 endif
 
+ifndef USE_OLD_VM64
+USE_OLD_VM64=0
+endif
+
 #############################################################################
 
 BD=$(BUILD_DIR)/debug-$(PLATFORM)-$(ARCH)
@@ -677,11 +681,10 @@ else # ifeq freebsd
 
 ifeq ($(PLATFORM),openbsd)
 
-  #default to i386, no tests done on anything else
-  ARCH=i386
+  ARCH=$(shell uname -m)
 
   BASE_CFLAGS = -Wall -fno-strict-aliasing -Wimplicit -Wstrict-prototypes \
-    -DUSE_ICON
+    -DUSE_ICON -DMAP_ANONYMOUS=MAP_ANON
   CLIENT_CFLAGS = $(SDL_CFLAGS)
   SERVER_CFLAGS = 
 
@@ -769,7 +772,7 @@ else # ifeq netbsd
 
 ifeq ($(PLATFORM),irix64)
 
-  ARCH=mips  #default to MIPS
+  ARCH=mips
 
   CC = c99
   MKDIR = mkdir -p
@@ -1664,15 +1667,30 @@ ifeq ($(ARCH),i386)
   Q3OBJ += \
     $(B)/client/snd_mixa.o \
     $(B)/client/matha.o \
-    $(B)/client/ftola.o \
-    $(B)/client/snapvectora.o
+    $(B)/client/snapvector.o \
+    $(B)/client/ftola.o
 endif
 ifeq ($(ARCH),x86)
   Q3OBJ += \
     $(B)/client/snd_mixa.o \
     $(B)/client/matha.o \
-    $(B)/client/ftola.o \
-    $(B)/client/snapvectora.o
+    $(B)/client/snapvector.o \
+    $(B)/client/ftola.o
+endif
+ifeq ($(ARCH),x86_64)
+  Q3OBJ += \
+    $(B)/client/snapvector.o \
+    $(B)/client/ftola.o
+endif
+ifeq ($(ARCH),amd64)
+  Q3OBJ += \
+    $(B)/client/snapvector.o \
+    $(B)/client/ftola.o
+endif
+ifeq ($(ARCH),x64)
+  Q3OBJ += \
+    $(B)/client/snapvector.o \
+    $(B)/client/ftola.o
 endif
 
 ifeq ($(USE_VOIP),1)
@@ -1733,19 +1751,42 @@ endif
 
 ifeq ($(HAVE_VM_COMPILED),true)
   ifeq ($(ARCH),i386)
-    Q3OBJ += $(B)/client/vm_x86.o
+    Q3OBJ += \
+      $(B)/client/vm_x86.o
   endif
   ifeq ($(ARCH),x86)
-    Q3OBJ += $(B)/client/vm_x86.o
+    Q3OBJ += \
+      $(B)/client/vm_x86.o
   endif
   ifeq ($(ARCH),x86_64)
-    Q3OBJ += $(B)/client/vm_x86_64.o $(B)/client/vm_x86_64_assembler.o
+    ifeq ($(USE_OLD_VM64),1)
+      Q3OBJ += \
+        $(B)/client/vm_x86_64.o \
+        $(B)/client/vm_x86_64_assembler.o
+    else
+      Q3OBJ += \
+        $(B)/client/vm_x86.o
+    endif
   endif
   ifeq ($(ARCH),amd64)
-    Q3OBJ += $(B)/client/vm_x86_64.o $(B)/client/vm_x86_64_assembler.o
+    ifeq ($(USE_OLD_VM64),1)
+      Q3OBJ += \
+        $(B)/client/vm_x86_64.o \
+        $(B)/client/vm_x86_64_assembler.o
+    else
+      Q3OBJ += \
+        $(B)/client/vm_x86.o
+    endif
   endif
   ifeq ($(ARCH),x64)
-    Q3OBJ += $(B)/client/vm_x86_64.o $(B)/client/vm_x86_64_assembler.o
+    ifeq ($(USE_OLD_VM64),1)
+      Q3OBJ += \
+        $(B)/client/vm_x86_64.o \
+        $(B)/client/vm_x86_64_assembler.o
+    else
+      Q3OBJ += \
+        $(B)/client/vm_x86.o
+    endif
   endif
   ifeq ($(ARCH),ppc)
     Q3OBJ += $(B)/client/vm_powerpc.o $(B)/client/vm_powerpc_asm.o
@@ -1895,15 +1936,30 @@ Q3DOBJ = \
 
 ifeq ($(ARCH),i386)
   Q3DOBJ += \
-      $(B)/ded/ftola.o \
-      $(B)/ded/snapvectora.o \
-      $(B)/ded/matha.o
+      $(B)/ded/matha.o \
+      $(B)/ded/snapvector.o \
+      $(B)/ded/ftola.o
 endif
 ifeq ($(ARCH),x86)
   Q3DOBJ += \
-      $(B)/ded/ftola.o \
-      $(B)/ded/snapvectora.o \
-      $(B)/ded/matha.o
+      $(B)/ded/matha.o \
+      $(B)/ded/snapvector.o \
+      $(B)/ded/ftola.o 
+endif
+ifeq ($(ARCH),x86_64)
+  Q3DOBJ += \
+      $(B)/ded/snapvector.o \
+      $(B)/ded/ftola.o 
+endif
+ifeq ($(ARCH),amd64)
+  Q3DOBJ += \
+      $(B)/ded/snapvector.o \
+      $(B)/ded/ftola.o 
+endif
+ifeq ($(ARCH),x64)
+  Q3DOBJ += \
+      $(B)/ded/snapvector.o \
+      $(B)/ded/ftola.o 
 endif
 
 ifeq ($(USE_INTERNAL_ZLIB),1)
@@ -1918,19 +1974,42 @@ endif
 
 ifeq ($(HAVE_VM_COMPILED),true)
   ifeq ($(ARCH),i386)
-    Q3DOBJ += $(B)/ded/vm_x86.o
+    Q3DOBJ += \
+      $(B)/ded/vm_x86.o
   endif
   ifeq ($(ARCH),x86)
-    Q3DOBJ += $(B)/ded/vm_x86.o
+    Q3DOBJ += \
+      $(B)/ded/vm_x86.o
   endif
   ifeq ($(ARCH),x86_64)
-    Q3DOBJ += $(B)/ded/vm_x86_64.o $(B)/ded/vm_x86_64_assembler.o
+    ifeq ($(USE_OLD_VM64),1)
+      Q3DOBJ += \
+        $(B)/ded/vm_x86_64.o \
+        $(B)/ded/vm_x86_64_assembler.o
+    else
+      Q3DOBJ += \
+        $(B)/ded/vm_x86.o
+    endif
   endif
   ifeq ($(ARCH),amd64)
-    Q3DOBJ += $(B)/ded/vm_x86_64.o $(B)/ded/vm_x86_64_assembler.o
+    ifeq ($(USE_OLD_VM64),1)
+      Q3DOBJ += \
+        $(B)/ded/vm_x86_64.o \
+        $(B)/ded/vm_x86_64_assembler.o
+    else
+      Q3DOBJ += \
+        $(B)/ded/vm_x86.o
+    endif
   endif
   ifeq ($(ARCH),x64)
-    Q3DOBJ += $(B)/ded/vm_x86_64.o $(B)/ded/vm_x86_64_assembler.o
+    ifeq ($(USE_OLD_VM64),1)
+      Q3DOBJ += \
+        $(B)/ded/vm_x86_64.o \
+        $(B)/ded/vm_x86_64_assembler.o
+    else
+      Q3DOBJ += \
+        $(B)/ded/vm_x86.o
+    endif
   endif
   ifeq ($(ARCH),ppc)
     Q3DOBJ += $(B)/ded/vm_powerpc.o $(B)/ded/vm_powerpc_asm.o
@@ -2308,6 +2387,10 @@ $(B)/missionpack/vm/ui.qvm: $(MPUIVMOBJ)
 $(B)/client/%.o: $(ASMDIR)/%.s
 	$(DO_AS)
 
+# k8 so inline assembler knows about SSE
+$(B)/client/%.o: $(ASMDIR)/%.c
+	$(DO_CC) -march=k8
+
 $(B)/client/%.o: $(CDIR)/%.c
 	$(DO_CC)
 
@@ -2351,6 +2434,10 @@ $(B)/client/%.o: $(SYSDIR)/%.rc
 $(B)/ded/%.o: $(ASMDIR)/%.s
 	$(DO_AS)
 
+# k8 so inline assembler knows about SSE
+$(B)/ded/%.o: $(ASMDIR)/%.c
+	$(DO_CC) -march=k8
+
 $(B)/ded/%.o: $(SDIR)/%.c
 	$(DO_DED_CC)
 
Index: code/server/sv_game.c
===================================================================
--- code/server/sv_game.c.orig
+++ code/server/sv_game.c
@@ -427,7 +427,7 @@ intptr_t SV_GameSystemCalls( intptr_t *a
 	case G_REAL_TIME:
 		return Com_RealTime( VMA(1) );
 	case G_SNAPVECTOR:
-		Sys_SnapVector( VMA(1) );
+		Q_SnapVector(VMA(1));
 		return 0;
 
 		//====================================
@@ -535,7 +535,7 @@ intptr_t SV_GameSystemCalls( intptr_t *a
 
 	case BOTLIB_EA_ACTION:
 		botlib_export->ea.EA_Action( args[1], args[2] );
-		break;
+		return 0;
 	case BOTLIB_EA_GESTURE:
 		botlib_export->ea.EA_Gesture( args[1] );
 		return 0;
@@ -841,7 +841,7 @@ intptr_t SV_GameSystemCalls( intptr_t *a
 	default:
 		Com_Error( ERR_DROP, "Bad game system trap: %ld", (long int) args[0] );
 	}
-	return -1;
+	return 0;
 }
 
 /*
openSUSE Build Service is sponsored by