mirror of
https://github.com/DarkPlacesEngine/gmqcc.git
synced 2025-01-31 12:00:38 +00:00
implement INSTR_STATE in the qcvm
This commit is contained in:
parent
0d1a740bc7
commit
0d8b0d419c
2 changed files with 75 additions and 7 deletions
56
exec.c
56
exec.c
|
@ -55,8 +55,16 @@ qc_program_t* prog_load(const char *filename, bool skipversion)
|
||||||
{
|
{
|
||||||
prog_header_t header;
|
prog_header_t header;
|
||||||
qc_program_t *prog;
|
qc_program_t *prog;
|
||||||
|
size_t i;
|
||||||
fs_file_t *file = fs_file_open(filename, "rb");
|
fs_file_t *file = fs_file_open(filename, "rb");
|
||||||
|
|
||||||
|
/* we need all those in order to support INSTR_STATE: */
|
||||||
|
bool has_self = false,
|
||||||
|
has_time = false,
|
||||||
|
has_think = false,
|
||||||
|
has_nextthink = false,
|
||||||
|
has_frame = false;
|
||||||
|
|
||||||
if (!file)
|
if (!file)
|
||||||
return NULL;
|
return NULL;
|
||||||
|
|
||||||
|
@ -137,6 +145,36 @@ qc_program_t* prog_load(const char *filename, bool skipversion)
|
||||||
memset(vec_add(prog->entitydata, prog->entityfields), 0, prog->entityfields * sizeof(prog->entitydata[0]));
|
memset(vec_add(prog->entitydata, prog->entityfields), 0, prog->entityfields * sizeof(prog->entitydata[0]));
|
||||||
prog->entities = 1;
|
prog->entities = 1;
|
||||||
|
|
||||||
|
/* cache some globals and fields from names */
|
||||||
|
for (i = 0; i < vec_size(prog->defs); ++i) {
|
||||||
|
const char *name = prog_getstring(prog, prog->defs[i].name);
|
||||||
|
if (!strcmp(name, "self")) {
|
||||||
|
prog->cached_globals.self = prog->defs[i].offset;
|
||||||
|
has_self = true;
|
||||||
|
}
|
||||||
|
else if (!strcmp(name, "time")) {
|
||||||
|
prog->cached_globals.time = prog->defs[i].offset;
|
||||||
|
has_time = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
for (i = 0; i < vec_size(prog->fields); ++i) {
|
||||||
|
const char *name = prog_getstring(prog, prog->fields[i].name);
|
||||||
|
if (!strcmp(name, "think")) {
|
||||||
|
prog->cached_fields.think = prog->fields[i].offset;
|
||||||
|
has_think = true;
|
||||||
|
}
|
||||||
|
else if (!strcmp(name, "nextthink")) {
|
||||||
|
prog->cached_fields.nextthink = prog->fields[i].offset;
|
||||||
|
has_nextthink = true;
|
||||||
|
}
|
||||||
|
else if (!strcmp(name, "frame")) {
|
||||||
|
prog->cached_fields.frame = prog->fields[i].offset;
|
||||||
|
has_frame = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (has_self && has_time && has_think && has_nextthink && has_frame)
|
||||||
|
prog->supports_state = true;
|
||||||
|
|
||||||
return prog;
|
return prog;
|
||||||
|
|
||||||
error:
|
error:
|
||||||
|
@ -1574,8 +1612,24 @@ while (prog->vmerror == 0) {
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case INSTR_STATE:
|
case INSTR_STATE:
|
||||||
qcvmerror(prog, "`%s` tried to execute a STATE operation", prog->filename);
|
{
|
||||||
|
qcfloat_t *nextthink;
|
||||||
|
qcfloat_t *time;
|
||||||
|
qcfloat_t *frame;
|
||||||
|
if (!prog->supports_state) {
|
||||||
|
qcvmerror(prog, "`%s` tried to execute a STATE operation but misses its defs!", prog->filename);
|
||||||
|
goto cleanup;
|
||||||
|
}
|
||||||
|
ed = prog_getedict(prog, prog->globals[prog->cached_globals.self]);
|
||||||
|
((qcint_t*)ed)[prog->cached_fields.think] = OPB->function;
|
||||||
|
|
||||||
|
frame = (qcfloat_t*)&((qcint_t*)ed)[prog->cached_fields.frame];
|
||||||
|
*frame = OPA->_float;
|
||||||
|
nextthink = (qcfloat_t*)&((qcint_t*)ed)[prog->cached_fields.nextthink];
|
||||||
|
time = (qcfloat_t*)(prog->globals + prog->cached_globals.time);
|
||||||
|
*nextthink = *time + 0.1;
|
||||||
break;
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
case INSTR_GOTO:
|
case INSTR_GOTO:
|
||||||
st += st->o1.s1 - 1; /* offset the s++ */
|
st += st->o1.s1 - 1; /* offset the s++ */
|
||||||
|
|
14
gmqcc.h
14
gmqcc.h
|
@ -825,6 +825,20 @@ typedef struct qc_program_s {
|
||||||
size_t xflags;
|
size_t xflags;
|
||||||
|
|
||||||
int argc; /* current arg count for debugging */
|
int argc; /* current arg count for debugging */
|
||||||
|
|
||||||
|
/* cached fields */
|
||||||
|
struct {
|
||||||
|
qcint_t frame;
|
||||||
|
qcint_t nextthink;
|
||||||
|
qcint_t think;
|
||||||
|
} cached_fields;
|
||||||
|
|
||||||
|
struct {
|
||||||
|
qcint_t self;
|
||||||
|
qcint_t time;
|
||||||
|
} cached_globals;
|
||||||
|
|
||||||
|
bool supports_state; /* is INSTR_STATE supported? */
|
||||||
} qc_program_t;
|
} qc_program_t;
|
||||||
|
|
||||||
qc_program_t* prog_load (const char *filename, bool ignoreversion);
|
qc_program_t* prog_load (const char *filename, bool ignoreversion);
|
||||||
|
|
Loading…
Reference in a new issue