[gamecode] Add double time state instructions

This has been a long-held wishlist item, really, and I thought I might
as well take the opportunity to add the instructions. The double
versions of STATE require both the nextthink field and time global to be
double (but they're not resolved properly yet: marked with
"FIXME double time" comments).

Also, the frame number for double time state is integer rather than
float.
This commit is contained in:
Bill Currie 2022-01-16 19:32:47 +09:00
parent d57712975e
commit 2b82533526
9 changed files with 87 additions and 45 deletions

View file

@ -1962,7 +1962,8 @@ struct progs_s {
/// \name globals and fields needed by the VM
///@{
struct {
float *time; ///< required for OP_STATE
double *dtime; ///< required for OP_STATE d
float *ftime; ///< required for OP_STATE f
pr_int_t *self; ///< required for OP_STATE
pointer_t *stack; ///< required for OP_(PUSH|POP)*
} globals;

View file

@ -134,7 +134,7 @@ menu_resolve_globals (progs_t *pr)
if (!(def = PR_FindGlobal (pr, sym = "time")))
goto error;
menu_pr_state.globals.time = &G_FLOAT (pr, def->ofs);
menu_pr_state.globals.ftime = &G_FLOAT (pr, def->ofs);//FIXME double time
return 1;
error:
Sys_Printf ("%s: undefined symbol %s\n", pr->progs_name, sym);
@ -672,7 +672,7 @@ Menu_Draw (view_t *view)
if (menu->fadescreen)
r_funcs->Draw_FadeScreen ();
*menu_pr_state.globals.time = *con_data.realtime;
*menu_pr_state.globals.ftime = *con_data.realtime;//FIXME double time
if (menu->draw) {
int ret;
@ -729,7 +729,7 @@ void
Menu_Draw_Hud (view_t *view)
{
run_menu_pre ();
*menu_pr_state.globals.time = *con_data.realtime;
*menu_pr_state.globals.ftime = *con_data.realtime;//FIXME double time
PR_ExecuteProgram (&menu_pr_state, menu_draw_hud);
run_menu_post ();

View file

@ -19,14 +19,16 @@ bitmap_txt = """
1 1010 t100 swizzle
1 1011 tooo vecops
1 1101 01oo move
1 1101 0111 convert (conversion mode in st->b)
1 1101 11oo memset
1 1101 1111 with (mode in st->a, value in st->b, reg in st->c)
1 1101 c111 statef
1 1110 c1cc branch
1 1110 t111 state
1 1110 c111 stated
1 1111 00mm lea
1 1111 01td vecops2
1 1111 1nnn
1 1111 10nn
1 1111 1100 convert (conversion mode in st->b)
1 1111 1101 with (mode in st->a, value in st->b, reg in st->c)
1 1111 1110
1 1111 1111 hops
"""
@ -328,19 +330,32 @@ shiftops_formats = {
],
},
}
state_formats = {
"opcode": "OP_STATE_{state[t]}",
"mnemonic": "state.{state[t]}",
statef_formats = {
"opcode": "OP_STATE_{state[c]}",
"mnemonic": "state.{state[c]}",
"opname": "state",
"format": "{state_fmt[t]}",
"format": "{state_fmt[c]}",
"widths": "1, 1, 1",
"types": "ev_float, ev_func, {state_types[t]}",
"types": "ev_float, ev_func, {state_types[c]}",
"args": {
"state": ["ft", "ftt"],
"state_fmt": ["%Ga, %Gb", "%Ga, %Gb, %Gc"],
"state_types": ["ev_invalid", "ev_float"],
},
}
stated_formats = {
"opcode": "OP_STATE_{state[c]}",
"mnemonic": "state.{state[c]}",
"opname": "state",
"format": "{state_fmt[c]}",
"widths": "1, 1, 1",
"types": "ev_float, ev_func, {state_types[c]}",
"args": {
"state": ["dt", "dtt"],
"state_fmt": ["%Ga, %Gb", "%Ga, %Gb, %Gc"],
"state_types": ["ev_invalid", "ev_double"],
},
}
store_formats = {
"opcode": "OP_STORE_{op_mode[mm]}_{ss+1}",
"mnemonic": "store",
@ -476,7 +491,8 @@ group_map = {
"popregs": popregs_formats,
"scale": scale_formats,
"shiftops": shiftops_formats,
"state": state_formats,
"statef": statef_formats,
"stated": stated_formats,
"store": store_formats,
"string": string_formats,
"swizzle": swizzle_formats,

View file

@ -79,9 +79,9 @@ ED_Alloc (progs_t *pr)
e = EDICT_NUM (pr, i);
// the first couple seconds of server time can involve a lot of
// freeing and allocating, so relax the replacement policy
if (e->free && (!pr->globals.time
if (e->free && (!pr->globals.ftime//FIXME double time
|| e->freetime < 2
|| *pr->globals.time - e->freetime > 0.5)) {
|| *pr->globals.ftime - e->freetime > 0.5)) {
ED_ClearEdict (pr, e, 0);
return e;
}
@ -123,8 +123,8 @@ ED_Free (progs_t *pr, edict_t *ed)
ED_ClearEdict (pr, ed, 0);
}
ed->free = true;
if (pr->globals.time)
ed->freetime = *pr->globals.time;
if (pr->globals.ftime)//FIXME double time
ed->freetime = *pr->globals.ftime;
}
//===========================================================================
@ -199,7 +199,7 @@ ED_Count (progs_t *pr)
for (i = 0; i < *pr->num_edicts; i++) {
ent = EDICT_NUM (pr, i);
if (ent->free) {
if (pr->globals.time && *pr->globals.time - ent->freetime <= 0.5)
if (pr->globals.ftime && *pr->globals.ftime - ent->freetime <= 0.5)//FIXME double time
zombie++;
continue;
}

View file

@ -1482,7 +1482,7 @@ op_call:
int nextthink = pr->fields.nextthink + self;
int frame = pr->fields.frame + self;
int think = pr->fields.think + self;
float time = *pr->globals.time + 0.1;
float time = *pr->globals.ftime + 0.1;
pr->pr_edict_area[nextthink].float_var = time;
pr->pr_edict_area[frame].float_var = OPA(float);
pr->pr_edict_area[think].func_var = OPB(uint);
@ -1494,7 +1494,7 @@ op_call:
int nextthink = pr->fields.nextthink + self;
int frame = pr->fields.frame + self;
int think = pr->fields.think + self;
float time = *pr->globals.time + OPC(float);
float time = *pr->globals.ftime + OPC(float);
pr->pr_edict_area[nextthink].float_var = time;
pr->pr_edict_area[frame].float_var = OPA(float);
pr->pr_edict_area[think].func_var = OPB(uint);
@ -2891,9 +2891,13 @@ pr_exec_ruamoko (progs_t *pr, int exitdepth)
MM(ivec4) = STK(ivec4);
break;
// 0 0100
// spare
// 0 0101
// spare
// 0 0110
// spare
// 0 0111
// spare
#define OP_cmp_1(OP, T, rt, cmp, ct) \
case OP_##OP##_##T##_1: \
@ -2936,7 +2940,6 @@ pr_exec_ruamoko (progs_t *pr, int exitdepth)
OP_cmp(GE, >=);
// 0 1110
OP_cmp(LE, <=);
// 0 1111
// spare
@ -3276,12 +3279,16 @@ pr_exec_ruamoko (progs_t *pr, int exitdepth)
memmove (pr->pr_globals + OPC(int), pr->pr_globals + OPA(int),
st->b * sizeof (pr_type_t));
break;
case OP_CONV:
switch (st->b) {
#include "libs/gamecode/pr_convert.cinc"
default:
PR_RunError (pr, "invalid conversion code: %04o",
st->b);
case OP_STATE_ft:
{
int self = *pr->globals.self;
int nextthink = pr->fields.nextthink + self;
int frame = pr->fields.frame + self;
int think = pr->fields.think + self;
float time = *pr->globals.ftime + 0.1;
pr->pr_edict_area[nextthink].float_var = time;
pr->pr_edict_area[frame].float_var = OPA(float);
pr->pr_edict_area[think].func_var = op_b->func_var;
}
break;
OP_cmp_T (GE, U, long, lvec2, lvec4, >=, ulong, ulvec2, ulvec4);
@ -3294,8 +3301,17 @@ pr_exec_ruamoko (progs_t *pr, int exitdepth)
case OP_MEMSET_PI:
pr_memset (pr->pr_globals + OPC(int), OPA(int), st->b);
break;
case OP_WITH:
pr_with (pr, st);
case OP_STATE_ftt:
{
int self = *pr->globals.self;
int nextthink = pr->fields.nextthink + self;
int frame = pr->fields.frame + self;
int think = pr->fields.think + self;
float time = *pr->globals.ftime + OPC(float);
pr->pr_edict_area[nextthink].float_var = time;
pr->pr_edict_area[frame].float_var = OPA(float);
pr->pr_edict_area[think].func_var = op_b->func_var;
}
break;
// 1 1110
OP_cmp_T (LE, u, int, ivec2, ivec4, <=, uint, uivec2, uivec4);
@ -3317,15 +3333,15 @@ pr_exec_ruamoko (progs_t *pr, int exitdepth)
st = pr->pr_statements + pr->pr_xstatement;
}
break;
case OP_STATE_ft:
case OP_STATE_dt:
{
int self = *pr->globals.self;
int nextthink = pr->fields.nextthink + self;
int frame = pr->fields.frame + self;
int think = pr->fields.think + self;
float time = *pr->globals.time + 0.1;
pr->pr_edict_area[nextthink].float_var = time;
pr->pr_edict_area[frame].float_var = OPA(float);
double time = *pr->globals.dtime + 0.1;
*(double *) (&pr->pr_edict_area[nextthink]) = time;
pr->pr_edict_area[frame].integer_var = OPA(int);
pr->pr_edict_area[think].func_var = op_b->func_var;
}
break;
@ -3348,15 +3364,15 @@ pr_exec_ruamoko (progs_t *pr, int exitdepth)
st = pr->pr_statements + pr->pr_xstatement;
}
break;
case OP_STATE_ftt:
case OP_STATE_dtt:
{
int self = *pr->globals.self;
int nextthink = pr->fields.nextthink + self;
int frame = pr->fields.frame + self;
int think = pr->fields.think + self;
float time = *pr->globals.time + OPC(float);
pr->pr_edict_area[nextthink].float_var = time;
pr->pr_edict_area[frame].float_var = OPA(float);
double time = *pr->globals.dtime + OPC(double);
*(double *) (&pr->pr_edict_area[nextthink]) = time;
pr->pr_edict_area[frame].integer_var = OPA(int);
pr->pr_edict_area[think].func_var = op_b->func_var;
}
break;
@ -3384,8 +3400,17 @@ pr_exec_ruamoko (progs_t *pr, int exitdepth)
OPC(dvec4) = vqmuld (OPA(dvec4), OPB(dvec4));
break;
// 10nn spare
// 1100 spare
// 1101 spare
case OP_CONV:
switch (st->b) {
#include "libs/gamecode/pr_convert.cinc"
default:
PR_RunError (pr, "invalid conversion code: %04o",
st->b);
}
break;
case OP_WITH:
pr_with (pr, st);
break;
// 1110 spare
#define OP_hop2(vec, op) ((vec)[0] op (vec)[1])
#define OP_hop3(vec, op) ((vec)[0] op (vec)[1] op (vec)[2])

View file

@ -143,9 +143,9 @@ PR_ResolveGlobals (progs_t *pr)
pr->pr_param_alignment = G_INT (pr, def->ofs);
}
memcpy (pr->pr_real_params, pr->pr_params, sizeof (pr->pr_params));
if (!pr->globals.time) {
if (!pr->globals.ftime) {//FIXME double time
if ((def = PR_FindGlobal (pr, "time")))
pr->globals.time = &G_FLOAT (pr, def->ofs);
pr->globals.ftime = &G_FLOAT (pr, def->ofs);
}
if (!pr->globals.self) {
if ((def = PR_FindGlobal (pr, ".self"))

View file

@ -1637,7 +1637,7 @@ PR_Check_Opcodes (progs_t *pr)
int pushpop_ok = 0;
pr_uint_t i;
if (pr->globals.time && pr->globals.self && pr->fields.nextthink != -1
if (pr->globals.ftime && pr->globals.self && pr->fields.nextthink != -1
&& pr->fields.think != -1 && pr->fields.frame != -1) {
state_ok = 1;
}

View file

@ -460,7 +460,7 @@ resolve (progs_t *pr)
resolve_fields (pr, nq_opt_fields, 0);
// progs engine needs these globals anyway
sv_pr_state.globals.self = sv_globals.self;
sv_pr_state.globals.time = sv_globals.time;
sv_pr_state.globals.ftime = sv_globals.time;//FIXME double time
return ret;
}

View file

@ -493,7 +493,7 @@ resolve (progs_t *pr)
resolve_fields (pr, qw_opt_fields, 0);
// progs engine needs these globals anyway
sv_pr_state.globals.self = sv_globals.self;
sv_pr_state.globals.time = sv_globals.time;
sv_pr_state.globals.ftime = sv_globals.time;//FIXME double time
return ret;
}