It should be stable now.
git-svn-id: https://svn.code.sf.net/p/fteqw/code/trunk@1241 fc73d0e0-1445-4013-8a0c-d673dee63da5
This commit is contained in:
parent
0f1a586272
commit
cd19c7ac80
1 changed files with 51 additions and 42 deletions
|
@ -114,7 +114,6 @@ void *Sys_LoadDLL(const char *name, void **vmMain, int (EXPORT_FN *syscall)(int
|
|||
FreeLibrary(hVM);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return hVM;
|
||||
}
|
||||
|
||||
|
@ -249,6 +248,11 @@ typedef struct qvm_s
|
|||
unsigned long *sp; // stack pointer, initially points to end of ss, goes down
|
||||
unsigned long bp; // base pointer, initially len_ds+len_ss/2
|
||||
|
||||
unsigned long *min_sp;
|
||||
unsigned long *max_sp;
|
||||
unsigned long min_bp;
|
||||
unsigned long max_bp;
|
||||
|
||||
// status
|
||||
unsigned int len_cs; // size of cs
|
||||
unsigned int len_ds; // size of ds
|
||||
|
@ -259,7 +263,7 @@ typedef struct qvm_s
|
|||
unsigned int mem_size;
|
||||
qbyte *mem_ptr;
|
||||
|
||||
unsigned int cycles; // command cicles executed
|
||||
// unsigned int cycles; // command cicles executed
|
||||
sys_callex_t syscall;
|
||||
} qvm_t;
|
||||
|
||||
|
@ -407,7 +411,7 @@ qvm_t *QVM_Load(const char *name, sys_callex_t syscall)
|
|||
qvm->len_ss=256*1024; // 256KB stack space
|
||||
|
||||
// memory
|
||||
qvm->ds_mask = qvm->len_ds*sizeof(qbyte)+(qvm->len_ss+4)*sizeof(qbyte);//+4 for a stack check decrease
|
||||
qvm->ds_mask = qvm->len_ds*sizeof(qbyte)+(qvm->len_ss+16*4)*sizeof(qbyte);//+4 for a stack check decrease
|
||||
for (i = 0; i < 31; i++)
|
||||
{
|
||||
if ((1<<i) >= qvm->ds_mask) //is this bit greater than our minimum?
|
||||
|
@ -430,11 +434,18 @@ qvm_t *QVM_Load(const char *name, sys_callex_t syscall)
|
|||
qvm->pc=qvm->cs;
|
||||
qvm->sp=(long*)(qvm->ss+qvm->len_ss);
|
||||
qvm->bp=qvm->len_ds+qvm->len_ss/2;
|
||||
qvm->cycles=0;
|
||||
// qvm->cycles=0;
|
||||
qvm->syscall=syscall;
|
||||
|
||||
qvm->ds_mask--;
|
||||
|
||||
qvm->min_sp = (long*)(qvm->ds+qvm->len_ds+qvm->len_ss/2);
|
||||
qvm->max_sp = (long*)(qvm->ds+qvm->len_ds+qvm->len_ss);
|
||||
qvm->min_bp = qvm->len_ds;
|
||||
qvm->max_bp = qvm->len_ds+qvm->len_ss/2;
|
||||
|
||||
qvm->bp = qvm->max_bp;
|
||||
|
||||
// load instructions
|
||||
{
|
||||
qbyte *src=raw+header->codeOffset;
|
||||
|
@ -530,7 +541,7 @@ static void inline QVM_Goto(qvm_t *vm, int addr)
|
|||
static void inline QVM_Call(qvm_t *vm, int addr)
|
||||
{
|
||||
vm->sp--;
|
||||
if (vm->sp < (unsigned long*)(vm->ss)) Sys_Error("QVM Stack underflow");
|
||||
if (vm->sp < vm->min_sp) Sys_Error("QVM Stack underflow");
|
||||
|
||||
if(addr<0)
|
||||
{
|
||||
|
@ -544,7 +555,7 @@ static void inline QVM_Call(qvm_t *vm, int addr)
|
|||
}
|
||||
}
|
||||
|
||||
if(addr>vm->len_cs)
|
||||
if(addr>=vm->len_cs)
|
||||
Sys_Error("VM run time error: program jumped off to hyperspace\n");
|
||||
|
||||
vm->sp[0]=(long)(vm->pc-vm->cs); // push pc /return address/
|
||||
|
@ -564,14 +575,14 @@ static void inline QVM_Enter(qvm_t *vm, long size)
|
|||
long *fp;
|
||||
|
||||
vm->bp-=size;
|
||||
if(vm->bp<vm->len_ds)
|
||||
if(vm->bp<vm->min_bp)
|
||||
Sys_Error("VM run time error: out of stack\n");
|
||||
|
||||
fp=(long*)(vm->ds+vm->bp);
|
||||
fp[0]=0; // unknown /maybe size/
|
||||
fp[0]=vm->sp-vm->max_sp; // unknown /maybe size/
|
||||
fp[1]=*vm->sp++; // saved PC
|
||||
|
||||
if ((long*)vm->sp > (long*)(vm->ss+vm->len_ss)) Sys_Error("QVM Stack overflow");
|
||||
if (vm->sp > vm->max_sp) Sys_Error("QVM Stack overflow");
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -584,7 +595,7 @@ static void inline QVM_Return(qvm_t *vm, long size)
|
|||
fp=(long*)(vm->ds+vm->bp);
|
||||
vm->bp+=size;
|
||||
|
||||
if(vm->bp>vm->len_ds+vm->len_ss/2)
|
||||
if(vm->bp>vm->max_bp)
|
||||
Sys_Error("VM run time error: freed too much stack\n");
|
||||
|
||||
if(fp[1]>=vm->len_cs*2)
|
||||
|
@ -594,15 +605,11 @@ static void inline QVM_Return(qvm_t *vm, long size)
|
|||
if (vm->cs+fp[1])
|
||||
Sys_Error("VM run time error: program returned to negative hyperspace\n");
|
||||
|
||||
if (vm->sp-vm->max_sp != fp[0])
|
||||
Sys_Error("VM run time error: stack push/pop mismatch \n");
|
||||
vm->pc=vm->cs+fp[1]; // restore PC
|
||||
// fp[1] = fp[0];
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
// ------------------------- * execution * -------------------------
|
||||
|
||||
/*
|
||||
|
@ -612,31 +619,25 @@ int QVM_Exec(register qvm_t *qvm, int command, int arg0, int arg1, int arg2, int
|
|||
{
|
||||
//remember that the stack is backwards. push takes 1.
|
||||
|
||||
//FIXME: does it matter that our stack pointer (qvm->sp) is backwards compared to q3?
|
||||
//We are more consistant of course, but this simply isn't what q3 does.
|
||||
|
||||
//all stack shifts in this function are referenced through these 2 macros.
|
||||
#define POP(t) qvm->sp+=t;if (qvm->sp > stackstart) Sys_Error("QVM Stack underflow");
|
||||
#define PUSH(v) qvm->sp--;if (qvm->sp < stackend) Sys_Error("QVM Stack overflow");*qvm->sp=v
|
||||
#define POP(t) qvm->sp+=t;if (qvm->sp > qvm->max_sp) Sys_Error("QVM Stack underflow");
|
||||
#define PUSH(v) qvm->sp--;if (qvm->sp < qvm->min_sp) Sys_Error("QVM Stack overflow");*qvm->sp=v
|
||||
qvm_op_t op=-1;
|
||||
unsigned long param;
|
||||
|
||||
long *fp;
|
||||
unsigned long *stackstart;
|
||||
unsigned long *stackend;
|
||||
unsigned long *oldpc;
|
||||
|
||||
static int recurse = 0;
|
||||
|
||||
if (recurse++)
|
||||
Sys_Error("QVM recursivly entered\n");
|
||||
|
||||
stackstart = (unsigned long*)(qvm->ss+qvm->len_ss);
|
||||
stackend = (unsigned long*)(qvm->ss);
|
||||
oldpc = qvm->pc;
|
||||
|
||||
// setup execution environment
|
||||
qvm->pc=NULL;
|
||||
qvm->sp=(long*)(qvm->ss+qvm->len_ss);
|
||||
qvm->bp=qvm->len_ds+qvm->len_ss/2;
|
||||
qvm->cycles=0;
|
||||
// qvm->cycles=0;
|
||||
// prepare local stack
|
||||
qvm->bp-=(13+2)*sizeof(int);
|
||||
qvm->bp -= 15*4; //we have to do this each call for the sake of (reliable) recursion.
|
||||
fp=(long*)(qvm->ds+qvm->bp);
|
||||
// push all params
|
||||
fp[0]=0;
|
||||
|
@ -662,15 +663,15 @@ int QVM_Exec(register qvm_t *qvm, int command, int arg0, int arg1, int arg2, int
|
|||
// fetch next command
|
||||
op=*qvm->pc++;
|
||||
param=*qvm->pc++;
|
||||
qvm->cycles++;
|
||||
// qvm->cycles++;
|
||||
|
||||
switch(op)
|
||||
{
|
||||
// aux
|
||||
case OP_UNDEF:
|
||||
case OP_NOP:
|
||||
default:
|
||||
break;
|
||||
default:
|
||||
case OP_BREAK: // break to debugger
|
||||
*(int*)NULL=-1;
|
||||
break;
|
||||
|
@ -685,8 +686,14 @@ int QVM_Exec(register qvm_t *qvm, int command, int arg0, int arg1, int arg2, int
|
|||
if (!qvm->pc)
|
||||
{
|
||||
// pick return value from stack
|
||||
recurse--;
|
||||
return qvm->sp[0];
|
||||
qvm->pc = oldpc;
|
||||
|
||||
qvm->bp += 15*4;
|
||||
if(qvm->bp!=qvm->max_bp)
|
||||
Sys_Error("VM run time error: freed too much stack\n");
|
||||
param = qvm->sp[0];
|
||||
POP(1);
|
||||
return param;
|
||||
}
|
||||
break;
|
||||
case OP_CALL:
|
||||
|
@ -697,7 +704,7 @@ int QVM_Exec(register qvm_t *qvm, int command, int arg0, int arg1, int arg2, int
|
|||
|
||||
// stack
|
||||
case OP_PUSH:
|
||||
PUSH(0);
|
||||
PUSH(*qvm->sp);
|
||||
break;
|
||||
case OP_POP:
|
||||
POP(1);
|
||||
|
@ -791,24 +798,26 @@ int QVM_Exec(register qvm_t *qvm, int command, int arg0, int arg1, int arg2, int
|
|||
*(unsigned long*)&qvm->sp[0]=*(unsigned long*)&qvm->ds[qvm->sp[0]&qvm->ds_mask];
|
||||
break;
|
||||
case OP_STORE1:
|
||||
*(qbyte*)&qvm->ds[qvm->sp[1]&qvm->ds_mask]=((qbyte)qvm->sp[0]&0xFF);
|
||||
*(qbyte*)&qvm->ds[qvm->sp[1]&qvm->ds_mask]=(qbyte)(qvm->sp[0]&0xFF);
|
||||
POP(2);
|
||||
break;
|
||||
case OP_STORE2:
|
||||
*(unsigned short*)&qvm->ds[qvm->sp[1]&qvm->ds_mask]=((unsigned short)qvm->sp[0]&0xFFFF);
|
||||
*(unsigned short*)&qvm->ds[qvm->sp[1]&qvm->ds_mask]=(unsigned short)(qvm->sp[0]&0xFFFF);
|
||||
POP(2);
|
||||
break;
|
||||
case OP_STORE4:
|
||||
*(unsigned long*)&qvm->ds[qvm->sp[1]&qvm->ds_mask]=qvm->sp[0];
|
||||
*(unsigned long*)&qvm->ds[qvm->sp[1]&qvm->ds_mask]=*(unsigned long*)&qvm->sp[0];
|
||||
POP(2);
|
||||
break;
|
||||
case OP_ARG:
|
||||
*(unsigned long*)&qvm->ds[(qvm->bp+param)&qvm->ds_mask]=qvm->sp[0];
|
||||
*(unsigned long*)&qvm->ds[(param+qvm->bp)&qvm->ds_mask]=*(unsigned long*)&qvm->sp[0];
|
||||
POP(1);
|
||||
break;
|
||||
case OP_BLOCK_COPY:
|
||||
if (qvm->sp[1]+param < qvm->ds_mask && qvm->sp[0] + param < qvm->ds_mask)
|
||||
{
|
||||
memmove(qvm->ds+(qvm->sp[1]&qvm->ds_mask), qvm->ds+(qvm->sp[0]&qvm->ds_mask), param);
|
||||
}
|
||||
POP(2);
|
||||
break;
|
||||
|
||||
|
@ -844,7 +853,7 @@ int QVM_Exec(register qvm_t *qvm, int command, int arg0, int arg1, int arg2, int
|
|||
break;
|
||||
case OP_MODU:
|
||||
*(unsigned long*)&qvm->sp[1]%=(*(unsigned long*)&qvm->sp[0]);
|
||||
qvm->sp++;
|
||||
POP(1);
|
||||
break;
|
||||
case OP_MULI:
|
||||
*(signed long*)&qvm->sp[1]*=*(signed long*)&qvm->sp[0];
|
||||
|
@ -907,7 +916,7 @@ int QVM_Exec(register qvm_t *qvm, int command, int arg0, int arg1, int arg2, int
|
|||
|
||||
// format conversion
|
||||
case OP_CVIF:
|
||||
*(float*)&qvm->sp[0]=(float)qvm->sp[0];
|
||||
*(float*)&qvm->sp[0]=(float)(signed long)qvm->sp[0];
|
||||
break;
|
||||
case OP_CVFI:
|
||||
*(signed long*)&qvm->sp[0]=(signed long)(*(float*)&qvm->sp[0]);
|
||||
|
|
Loading…
Reference in a new issue