From 2b8253352699e0bc6b26423f4295b021b7c2b6bf Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Sun, 16 Jan 2022 19:32:47 +0900 Subject: [PATCH] [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. --- include/QF/progs.h | 3 +- libs/console/menu.c | 6 ++-- libs/gamecode/opcodes.py | 36 +++++++++++++------ libs/gamecode/pr_edict.c | 10 +++--- libs/gamecode/pr_exec.c | 67 ++++++++++++++++++++++++----------- libs/gamecode/pr_resolve.c | 4 +-- libs/gamecode/pr_v6p_opcode.c | 2 +- nq/source/sv_progs.c | 2 +- qw/source/sv_progs.c | 2 +- 9 files changed, 87 insertions(+), 45 deletions(-) diff --git a/include/QF/progs.h b/include/QF/progs.h index 572528891..798806de5 100644 --- a/include/QF/progs.h +++ b/include/QF/progs.h @@ -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; diff --git a/libs/console/menu.c b/libs/console/menu.c index e6dcc72a4..a98c2d71a 100644 --- a/libs/console/menu.c +++ b/libs/console/menu.c @@ -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 (); diff --git a/libs/gamecode/opcodes.py b/libs/gamecode/opcodes.py index db39a5621..4b123ce19 100644 --- a/libs/gamecode/opcodes.py +++ b/libs/gamecode/opcodes.py @@ -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, diff --git a/libs/gamecode/pr_edict.c b/libs/gamecode/pr_edict.c index f16c2bd41..c766c0861 100644 --- a/libs/gamecode/pr_edict.c +++ b/libs/gamecode/pr_edict.c @@ -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; } diff --git a/libs/gamecode/pr_exec.c b/libs/gamecode/pr_exec.c index 8a0429807..adf9cf515 100644 --- a/libs/gamecode/pr_exec.c +++ b/libs/gamecode/pr_exec.c @@ -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]) diff --git a/libs/gamecode/pr_resolve.c b/libs/gamecode/pr_resolve.c index 6270653d2..c62a8e9cb 100644 --- a/libs/gamecode/pr_resolve.c +++ b/libs/gamecode/pr_resolve.c @@ -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")) diff --git a/libs/gamecode/pr_v6p_opcode.c b/libs/gamecode/pr_v6p_opcode.c index 5ded2c764..6163050eb 100644 --- a/libs/gamecode/pr_v6p_opcode.c +++ b/libs/gamecode/pr_v6p_opcode.c @@ -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; } diff --git a/nq/source/sv_progs.c b/nq/source/sv_progs.c index 2c9d82836..3a8c44dd2 100644 --- a/nq/source/sv_progs.c +++ b/nq/source/sv_progs.c @@ -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; } diff --git a/qw/source/sv_progs.c b/qw/source/sv_progs.c index 93f6042a0..6351317e8 100644 --- a/qw/source/sv_progs.c +++ b/qw/source/sv_progs.c @@ -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; }