diff --git a/source/duke3d/src/gamedef.cpp b/source/duke3d/src/gamedef.cpp index 2ce3da01b..cade66929 100644 --- a/source/duke3d/src/gamedef.cpp +++ b/source/duke3d/src/gamedef.cpp @@ -674,7 +674,37 @@ static const vec2_t varvartable[] = { CON_XORVARVAR, CON_XORVAR }, }; +static const vec2_t globalvartable[] = +{ + { CON_SHIFTVARL, CON_SHIFTGLOBALVARL }, + { CON_SHIFTVARR, CON_SHIFTGLOBALVARR }, + { CON_RANDVAR, CON_RANDGLOBALVAR }, + { CON_MODVAR, CON_MODGLOBALVAR }, + { CON_ANDVAR, CON_ANDGLOBALVAR }, + { CON_ADDVAR, CON_ADDGLOBALVAR }, + { CON_ORVAR, CON_ORGLOBALVAR }, + { CON_SETVAR, CON_SETGLOBALVAR }, + { CON_SUBVAR, CON_SUBGLOBALVAR }, + { CON_XORVAR, CON_XORGLOBALVAR }, + { CON_MULVAR, CON_MULGLOBALVAR }, + { CON_DIVVAR, CON_DIVGLOBALVAR }, + { CON_WHILEVARL, CON_WHILEGLOBALVARL }, + { CON_WHILEVARN, CON_WHILEGLOBALVARN }, +}; + static inthashtable_t h_varvar = { NULL, INTHASH_SIZE(ARRAY_SIZE(varvartable)) }; +static inthashtable_t h_globalvar = { NULL, INTHASH_SIZE(ARRAY_SIZE(globalvartable)) }; + +static inthashtable_t *const inttables[] = { + &h_varvar, + &h_globalvar, +}; + +static inthashtable_t *const inttables_free[] = { + &h_varvar, + &h_globalvar, +}; + const tokenmap_t iter_tokens [] = { @@ -704,7 +734,7 @@ char const * VM_GetKeywordForID(int32_t id) if (keyword.val == id) return keyword.token; - return ""; + return id < CON_OPCODE_END ? "" : ""; } #endif @@ -3324,139 +3354,6 @@ DO_DEFSTATE: continue; } - case CON_ADDVARVAR: - case CON_ANDVARVAR: - case CON_DISPLAYRANDVARVAR: - case CON_DIVVARVAR: - case CON_MODVARVAR: - case CON_MULVARVAR: - case CON_ORVARVAR: - case CON_RANDVARVAR: - case CON_SETVARVAR: - case CON_SHIFTVARVARL: - case CON_SHIFTVARVARR: - case CON_SUBVARVAR: - case CON_XORVARVAR: - { -setvarvar: - auto ins = &g_scriptPtr[-1]; - - C_GetNextVarType(GAMEVAR_READONLY); - C_GetNextVar(); - - int const opcode = inthash_find(&h_varvar, *ins & VM_INSTMASK); - - if (ins[2] == GV_FLAG_CONSTANT && opcode != -1) - { - if (!(g_errorCnt || g_warningCnt) && g_scriptDebug > 1) - { - initprintf("%s:%d: replacing %s with %s\n", g_scriptFileName, g_lineNumber, - VM_GetKeywordForID(*ins & VM_INSTMASK), VM_GetKeywordForID(opcode)); - } - - g_scriptPtr--; - tw = opcode; - scriptWriteAtOffset(opcode | LINE_NUMBER, ins); - scriptWriteAtOffset(ins[3], &ins[2]); - } - - continue; - } - - case CON_GETACTORVAR: - case CON_GETPLAYERVAR: - case CON_SETACTORVAR: - case CON_SETPLAYERVAR: - { - // syntax [gs]etactorvar[]. - // gets the value of the per-actor variable varx into VAR - - if (C_GetStructureIndexes(1, NULL) == -1) - continue; - - if (g_scriptPtr[-1] == g_thisActorVarID) // convert to "setvarvar" - { - g_scriptPtr--; - g_scriptPtr[-1]=CON_SETVARVAR; - if (tw == CON_SETACTORVAR || tw == CON_SETPLAYERVAR) - { - tw = inthash_find(&h_varvar, tw); - goto setvarvar; - } - else - { - g_scriptPtr++; - C_GetNextVar(); - g_scriptPtr-=2; - C_GetNextVarType(GAMEVAR_READONLY); - g_scriptPtr++; - } - continue; - } - - /// now pointing at 'xxx' - - C_GetNextLabelName(); - - if (EDUKE32_PREDICT_FALSE(hash_find(&h_keywords,LAST_LABEL)>=0)) - { - g_errorCnt++; - C_ReportError(ERROR_ISAKEYWORD); - continue; - } - - i=GetDefID(LAST_LABEL); - - if (EDUKE32_PREDICT_FALSE(i<0)) - { - g_errorCnt++; - C_ReportError(ERROR_NOTAGAMEVAR); - continue; - } - if (EDUKE32_PREDICT_FALSE(aGameVars[i].flags & GAMEVAR_READONLY)) - { - g_errorCnt++; - C_ReportError(ERROR_VARREADONLY); - continue; - } - - switch (tw) - { - case CON_SETACTORVAR: - if (EDUKE32_PREDICT_FALSE(!(aGameVars[i].flags & GAMEVAR_PERACTOR))) - { - g_errorCnt++; - C_ReportError(-1); - initprintf("%s:%d: error: variable `%s' is not per-actor.\n",g_scriptFileName,g_lineNumber,LAST_LABEL); - continue; - } - break; - case CON_SETPLAYERVAR: - if (EDUKE32_PREDICT_FALSE(!(aGameVars[i].flags & GAMEVAR_PERPLAYER))) - { - g_errorCnt++; - C_ReportError(-1); - initprintf("%s:%d: error: variable `%s' is not per-player.\n",g_scriptFileName,g_lineNumber,LAST_LABEL); - continue; - } - break; - } - - scriptWriteValue(i); // the ID of the DEF (offset into array...) - - switch (tw) - { - case CON_GETACTORVAR: - case CON_GETPLAYERVAR: - C_GetNextVarType(GAMEVAR_READONLY); - break; - default: - C_GetNextVar(); - break; - } - continue; - } - case CON_SETACTOR: { intptr_t * const ins = &g_scriptPtr[-1]; @@ -3708,50 +3605,207 @@ setvarvar: case CON_SHIFTVARR: case CON_SUBVAR: case CON_XORVAR: +setvar: + { + auto ins = &g_scriptPtr[-1]; + C_GetNextVarType(GAMEVAR_READONLY); + C_GetNextValue(LABEL_DEFINE); +#if 0 + if (tw == CON_DIVVAR || tw == CON_MULVAR) { - intptr_t *inst = &g_scriptPtr[-1]; - char *tptr = textptr; - // syntax: [rand|add|set]var - // sets var1 to const1 - // adds const1 to var1 (const1 can be negative...) - //printf("Found [add|set]var at line= %d\n",g_lineNumber); + int32_t const i = ins[2]; - C_GetNextVarType(GAMEVAR_READONLY); - - C_GetNextValue(LABEL_DEFINE); // the number to check against... - - if (tw == CON_DIVVAR || tw == CON_MULVAR) + if (i == -1) { - int32_t i = g_scriptPtr[-1]; - j = klabs(i); + int constexpr const opcode = CON_INV; - if (i == -1) + // if (!(g_errorCnt || g_warningCnt) && g_scriptDebug > 1) { - *inst = CON_INV | LINE_NUMBER; - g_scriptPtr--; - continue; + initprintf("%s:%d: %s -> %s\n", g_scriptFileName, g_lineNumber, + VM_GetKeywordForID(tw), VM_GetKeywordForID(opcode)); } - if (C_IntPow2(j)) + scriptWriteAtOffset(opcode | LINE_NUMBER, ins); + g_scriptPtr--; + continue; + } + else if (C_IntPow2((j = klabs(i)))) + { + int const opcode = (tw == CON_DIVVAR) ? CON_SHIFTVARR : CON_SHIFTVARL; + + // if (!(g_errorCnt || g_warningCnt) && g_scriptDebug > 1) { - *inst = ((tw == CON_DIVVAR) ? CON_SHIFTVARR : CON_SHIFTVARL) | LINE_NUMBER; - g_scriptPtr[-1] = C_Pow2IntLogBase2(j); - // initprintf("%s:%d: replacing multiply/divide with shift\n",g_szScriptFileName,g_lineNumber); + initprintf("%s:%d: %s -> %s\n", g_scriptFileName, g_lineNumber, + VM_GetKeywordForID(tw), VM_GetKeywordForID(opcode)); + } - if (i == j) - continue; + scriptWriteAtOffset(opcode | LINE_NUMBER, ins); + scriptWriteAtOffset(C_Pow2IntLogBase2(j), &ins[2]); + if (i != j) + { scriptWriteValue(CON_INV | LINE_NUMBER); - textptr = tptr; - C_GetNextVarType(GAMEVAR_READONLY); - C_GetNextValue(LABEL_DEFINE); - g_scriptPtr--; - // initprintf("%s:%d: adding inversion\n",g_szScriptFileName,g_lineNumber); + scriptWriteValue(ins[1]); + initprintf("%s:%d: +++ CON_INV\n", g_scriptFileName, g_lineNumber); } } } +#endif + // replace instructions with special versions that operate only on globals + if ((aGameVars[ins[1]].flags & (GAMEVAR_USER_MASK | GAMEVAR_PTR_MASK)) == 0) + { + int const opcode = inthash_find(&h_globalvar, *ins & VM_INSTMASK); + + if (opcode != -1) + { + //if (!(g_errorCnt || g_warningCnt) && g_scriptDebug > 1) + { + initprintf("%s:%d: %s -> %s\n", g_scriptFileName, g_lineNumber, + VM_GetKeywordForID(*ins & VM_INSTMASK), VM_GetKeywordForID(opcode)); + } + + tw = opcode; + scriptWriteAtOffset(opcode | LINE_NUMBER, ins); + } + } continue; + } + + case CON_ADDVARVAR: + case CON_ANDVARVAR: + case CON_DISPLAYRANDVARVAR: + case CON_DIVVARVAR: + case CON_MODVARVAR: + case CON_MULVARVAR: + case CON_ORVARVAR: + case CON_RANDVARVAR: + case CON_SETVARVAR: + case CON_SHIFTVARVARL: + case CON_SHIFTVARVARR: + case CON_SUBVARVAR: + case CON_XORVARVAR: + { +setvarvar: + auto ins = &g_scriptPtr[-1]; + auto tptr = textptr; + + C_GetNextVarType(GAMEVAR_READONLY); + C_GetNextVar(); + + int const opcode = inthash_find(&h_varvar, *ins & VM_INSTMASK); + + if (ins[2] == GV_FLAG_CONSTANT && opcode != -1) + { + if (!(g_errorCnt || g_warningCnt) && g_scriptDebug > 1) + { + initprintf("%s:%d: %s -> %s\n", g_scriptFileName, g_lineNumber, + VM_GetKeywordForID(*ins & VM_INSTMASK), VM_GetKeywordForID(opcode)); + } + + tw = opcode; + scriptWriteAtOffset(opcode | LINE_NUMBER, ins); + g_scriptPtr = &ins[1]; + textptr = tptr; + goto setvar; + } + + continue; + } + + case CON_GETACTORVAR: + case CON_GETPLAYERVAR: + case CON_SETACTORVAR: + case CON_SETPLAYERVAR: + { + // syntax [gs]etactorvar[]. + // gets the value of the per-actor variable varx into VAR + + if (C_GetStructureIndexes(1, NULL) == -1) + continue; + + if (g_scriptPtr[-1] == g_thisActorVarID) // convert to "setvarvar" + { + g_scriptPtr--; + g_scriptPtr[-1]=CON_SETVARVAR; + if (tw == CON_SETACTORVAR || tw == CON_SETPLAYERVAR) + { + tw = inthash_find(&h_varvar, tw); + goto setvarvar; + } + else + { + g_scriptPtr++; + C_GetNextVar(); + g_scriptPtr-=2; + C_GetNextVarType(GAMEVAR_READONLY); + g_scriptPtr++; + } + continue; + } + + /// now pointing at 'xxx' + + C_GetNextLabelName(); + + if (EDUKE32_PREDICT_FALSE(hash_find(&h_keywords,LAST_LABEL)>=0)) + { + g_errorCnt++; + C_ReportError(ERROR_ISAKEYWORD); + continue; + } + + i=GetDefID(LAST_LABEL); + + if (EDUKE32_PREDICT_FALSE(i<0)) + { + g_errorCnt++; + C_ReportError(ERROR_NOTAGAMEVAR); + continue; + } + if (EDUKE32_PREDICT_FALSE(aGameVars[i].flags & GAMEVAR_READONLY)) + { + g_errorCnt++; + C_ReportError(ERROR_VARREADONLY); + continue; + } + + switch (tw) + { + case CON_SETACTORVAR: + if (EDUKE32_PREDICT_FALSE(!(aGameVars[i].flags & GAMEVAR_PERACTOR))) + { + g_errorCnt++; + C_ReportError(-1); + initprintf("%s:%d: error: variable `%s' is not per-actor.\n",g_scriptFileName,g_lineNumber,LAST_LABEL); + continue; + } + break; + case CON_SETPLAYERVAR: + if (EDUKE32_PREDICT_FALSE(!(aGameVars[i].flags & GAMEVAR_PERPLAYER))) + { + g_errorCnt++; + C_ReportError(-1); + initprintf("%s:%d: error: variable `%s' is not per-player.\n",g_scriptFileName,g_lineNumber,LAST_LABEL); + continue; + } + break; + } + + scriptWriteValue(i); // the ID of the DEF (offset into array...) + + switch (tw) + { + case CON_GETACTORVAR: + case CON_GETPLAYERVAR: + C_GetNextVarType(GAMEVAR_READONLY); + break; + default: + C_GetNextVar(); + break; + } + continue; + } case CON_WRITEARRAYTOFILE: case CON_READARRAYFROMFILE: @@ -4223,6 +4277,7 @@ setvarvar: case CON_WHILEVARN: { singlevar: + auto const ins = &g_scriptPtr[-1]; auto const lastScriptPtr = &g_scriptPtr[-1] - apScript; g_skipBranch = false; @@ -4233,6 +4288,23 @@ singlevar: if (C_CheckMalformedBranch(lastScriptPtr)) continue; + if (aGameVars[ins[1]].flags == 0) + { + int const opcode = inthash_find(&h_globalvar, *ins & VM_INSTMASK); + + if (opcode != -1) + { + if (!(g_errorCnt || g_warningCnt) && g_scriptDebug > 1) + { + initprintf("%s:%d: %s -> %s\n", g_scriptFileName, g_lineNumber, + VM_GetKeywordForID(*ins & VM_INSTMASK), VM_GetKeywordForID(opcode)); + } + + tw = opcode; + scriptWriteAtOffset(opcode | LINE_NUMBER, ins); + } + } + auto const offset = g_scriptPtr - apScript; g_scriptPtr++; //Leave a spot for the fail location @@ -5954,12 +6026,14 @@ void C_PrintStats(void) initprintf("\n"); } +// TODO: add some kind of mapping between the table and the struct holding the tokens void scriptInitTables() { for (auto table : tables) hash_init(table); - inthash_init(&h_varvar); + for (auto table : inttables) + inthash_init(table); for (auto &keyword : vm_keywords) hash_add(&h_keywords, keyword.token, keyword.val, 0); @@ -5969,6 +6043,9 @@ void scriptInitTables() for (auto &varvar : varvartable) inthash_add(&h_varvar, varvar.x, varvar.y, 0); + + for (auto &globalvar : globalvartable) + inthash_add(&h_globalvar, globalvar.x, globalvar.y, 0); } void C_Compile(const char *fileName) @@ -6102,6 +6179,7 @@ void C_Compile(const char *fileName) hash_free(i); inthash_free(&h_varvar); + inthash_free(&h_globalvar); freehashnames(); freesoundhashnames(); diff --git a/source/duke3d/src/gamedef.h b/source/duke3d/src/gamedef.h index 9ff526e47..577c068f1 100644 --- a/source/duke3d/src/gamedef.h +++ b/source/duke3d/src/gamedef.h @@ -834,6 +834,7 @@ enum IterationTypes_t ITER_END }; +// most keywords have opcodes but some opcodes don't have keywords enum ScriptKeywords_t { CON_ACTION, @@ -842,6 +843,7 @@ enum ScriptKeywords_t CON_ACTIVATECHEAT, CON_ACTORSOUND, CON_ADDAMMO, + CON_ADDGLOBALVAR, CON_ADDINVENTORY, CON_ADDKILLS, CON_ADDLOGVAR, @@ -851,6 +853,7 @@ enum ScriptKeywords_t CON_ADDVARVAR, CON_ADDWEAPON, CON_AI, + CON_ANDGLOBALVAR, CON_ANDVAR, CON_ANDVARVAR, CON_ANGOFF, @@ -883,6 +886,7 @@ enum ScriptKeywords_t CON_DISPLAYRANDVAR, CON_DISPLAYRANDVARVAR, CON_DIST, + CON_DIVGLOBALVAR, CON_DIVR, CON_DIVRU, CON_DIVSCALE, @@ -905,11 +909,11 @@ enum ScriptKeywords_t CON_EVENTLOADACTOR, CON_EZSHOOT, CON_FALL, - CON_FINDNEARACTOR3D, CON_FINDNEARACTOR, + CON_FINDNEARACTOR3D, CON_FINDNEARACTORZ, - CON_FINDNEARSPRITE3D, CON_FINDNEARSPRITE, + CON_FINDNEARSPRITE3D, CON_FINDNEARSPRITEZ, CON_FINDOTHERPLAYER, CON_FINDPLAYER, @@ -1051,12 +1055,14 @@ enum ScriptKeywords_t CON_MAIL, CON_MIKESND, CON_MINITEXT, + CON_MODGLOBALVAR, CON_MODVAR, CON_MODVARVAR, CON_MONEY, CON_MOVE, CON_MOVESECTOR, CON_MOVESPRITE, + CON_MULGLOBALVAR, CON_MULSCALE, CON_MULVAR, CON_MULVARVAR, @@ -1075,6 +1081,7 @@ enum ScriptKeywords_t CON_OPERATEMASTERSWITCHES, CON_OPERATERESPAWNS, CON_OPERATESECTORS, + CON_ORGLOBALVAR, CON_ORVAR, CON_ORVARVAR, CON_PALFROM, @@ -1097,6 +1104,7 @@ enum ScriptKeywords_t CON_QSUBSTR, CON_QUAKE, CON_QUOTE, + CON_RANDGLOBALVAR, CON_RANDVAR, CON_RANDVARVAR, CON_RAYINTERSECT, @@ -1136,6 +1144,7 @@ enum ScriptKeywords_t CON_SETARRAY, CON_SETASPECT, CON_SETGAMEPALETTE, + CON_SETGLOBALVAR, CON_SETINPUT, CON_SETMUSICPOSITION, CON_SETPLAYER, @@ -1154,6 +1163,8 @@ enum ScriptKeywords_t CON_SETVARVAR, CON_SETWALL, CON_SHADETO, + CON_SHIFTGLOBALVARL, + CON_SHIFTGLOBALVARR, CON_SHIFTVARL, CON_SHIFTVARR, CON_SHIFTVARVARL, @@ -1168,8 +1179,8 @@ enum ScriptKeywords_t CON_SIZETO, CON_SLEEPTIME, CON_SMAXAMMO, - CON_SOUNDONCE, CON_SOUND, + CON_SOUNDONCE, CON_SPAWN, CON_SPAWNCEILINGGLASS, CON_SPAWNWALLGLASS, @@ -1183,14 +1194,15 @@ enum ScriptKeywords_t CON_STARTCUTSCENE, CON_STARTLEVEL, CON_STARTSCREEN, - CON_STARTTRACKSLOT, CON_STARTTRACK, + CON_STARTTRACKSLOT, CON_STATE, CON_STOPACTORSOUND, CON_STOPALLMUSIC, CON_STOPALLSOUNDS, CON_STOPSOUND, CON_STRENGTH, + CON_SUBGLOBALVAR, CON_SUBVAR, CON_SUBVARVAR, CON_SWAPARRAYS, @@ -1203,18 +1215,21 @@ enum ScriptKeywords_t CON_UPDATESECTORZ, CON_USERQUOTE, CON_WACKPLAYER, + CON_WHILEGLOBALVARL, + CON_WHILEGLOBALVARN, CON_WHILEVARL, CON_WHILEVARN, CON_WHILEVARVARL, CON_WHILEVARVARN, CON_WRITEARRAYTOFILE, + CON_XORGLOBALVAR, CON_XORVAR, CON_XORVARVAR, CON_ZSHOOT, CON_OPCODE_END, - // these are the keywords that don't get written into the bytecode + // these are the keywords that don't have instructions written into the bytecode CON_ACTOR, CON_APPENDEVENT, CON_BETANAME, diff --git a/source/duke3d/src/gameexec.cpp b/source/duke3d/src/gameexec.cpp index 050253a44..ab7532234 100644 --- a/source/duke3d/src/gameexec.cpp +++ b/source/duke3d/src/gameexec.cpp @@ -1304,10 +1304,13 @@ next_instruction: case CON_SETVAR: insptr++; - if ((aGameVars[*insptr].flags & (GAMEVAR_USER_MASK | GAMEVAR_PTR_MASK)) == 0) - aGameVars[*insptr].global = insptr[1]; - else - Gv_SetVarX(*insptr, insptr[1]); + Gv_SetVarX(*insptr, insptr[1]); + insptr += 2; + continue; + + case CON_SETGLOBALVAR: + insptr++; + aGameVars[*insptr].global = insptr[1]; insptr += 2; continue; @@ -1324,12 +1327,36 @@ next_instruction: } continue; + case CON_ADDVAR: + insptr++; + Gv_AddVar(*insptr, insptr[1]); + insptr += 2; + continue; + + case CON_ADDGLOBALVAR: + insptr++; + aGameVars[*insptr].global += insptr[1]; + insptr += 2; + continue; + case CON_ADDVARVAR: insptr++; tw = *insptr++; Gv_AddVar(tw, Gv_GetVarX(*insptr++)); continue; + case CON_SUBVAR: + insptr++; + Gv_SubVar(*insptr, insptr[1]); + insptr += 2; + continue; + + case CON_SUBGLOBALVAR: + insptr++; + aGameVars[*insptr].global -= insptr[1]; + insptr += 2; + continue; + case CON_SUBVARVAR: insptr++; tw = *insptr++; @@ -1352,12 +1379,46 @@ next_instruction: VM_CONDITIONAL(tw); continue; + case CON_MULVAR: + insptr++; + Gv_MulVar(*insptr, insptr[1]); + insptr += 2; + continue; + + case CON_MULGLOBALVAR: + insptr++; + aGameVars[*insptr].global *= insptr[1]; + insptr += 2; + continue; + case CON_MULVARVAR: insptr++; tw = *insptr++; Gv_MulVar(tw, Gv_GetVarX(*insptr++)); continue; + case CON_DIVVAR: + insptr++; + if (EDUKE32_PREDICT_FALSE(insptr[1] == 0)) + { + CON_CRITICALERRPRINTF("divide by zero!\n"); + continue; + } + Gv_DivVar(*insptr, insptr[1]); + insptr += 2; + continue; + + case CON_DIVGLOBALVAR: + insptr++; + if (EDUKE32_PREDICT_FALSE(insptr[1] == 0)) + { + CON_CRITICALERRPRINTF("divide by zero!\n"); + continue; + } + aGameVars[*insptr].global = tabledivide32(aGameVars[*insptr].global, insptr[1]); + insptr += 2; + continue; + case CON_DIVVARVAR: insptr++; { @@ -1387,35 +1448,6 @@ next_instruction: VM_CONDITIONAL(tw != *insptr); continue; - case CON_ADDVAR: - insptr++; - Gv_AddVar(*insptr, insptr[1]); - insptr += 2; - continue; - - case CON_SUBVAR: - insptr++; - Gv_SubVar(*insptr, insptr[1]); - insptr += 2; - continue; - - case CON_MULVAR: - insptr++; - Gv_MulVar(*insptr, insptr[1]); - insptr += 2; - continue; - - case CON_DIVVAR: - insptr++; - if (EDUKE32_PREDICT_FALSE(insptr[1] == 0)) - { - CON_CRITICALERRPRINTF("divide by zero!\n"); - continue; - } - Gv_DivVar(*insptr, insptr[1]); - insptr += 2; - continue; - case CON_IFVARVARG: insptr++; tw = Gv_GetVarX(*insptr++); @@ -1614,13 +1646,13 @@ next_instruction: continue; } - case CON_WHILEVARL: + case CON_WHILEGLOBALVARN: { auto const savedinsptr = &insptr[2]; do { insptr = savedinsptr; - tw = (Gv_GetVarX(insptr[-1]) < *insptr); + tw = (aGameVars[insptr[-1]].global != *insptr); VM_CONDITIONAL(tw); } while (tw); continue; @@ -1640,6 +1672,30 @@ next_instruction: continue; } + case CON_WHILEVARL: + { + auto const savedinsptr = &insptr[2]; + do + { + insptr = savedinsptr; + tw = (Gv_GetVarX(insptr[-1]) < *insptr); + VM_CONDITIONAL(tw); + } while (tw); + continue; + } + + case CON_WHILEGLOBALVARL: + { + auto const savedinsptr = &insptr[2]; + do + { + insptr = savedinsptr; + tw = (aGameVars[insptr[-1]].global < *insptr); + VM_CONDITIONAL(tw); + } while (tw); + continue; + } + case CON_WHILEVARVARL: { auto const savedinsptr = &insptr[2]; @@ -1654,33 +1710,15 @@ next_instruction: continue; } - case CON_MODVAR: - insptr++; - if (EDUKE32_PREDICT_FALSE(insptr[1] == 0)) - { - CON_CRITICALERRPRINTF("mod by zero!\n"); - continue; - } - - Gv_ModVar(*insptr, insptr[1]); - insptr += 2; - continue; - case CON_ANDVAR: insptr++; Gv_AndVar(*insptr, insptr[1]); insptr += 2; continue; - case CON_ORVAR: + case CON_ANDGLOBALVAR: insptr++; - Gv_OrVar(*insptr, insptr[1]); - insptr += 2; - continue; - - case CON_XORVAR: - insptr++; - Gv_XorVar(*insptr, insptr[1]); + aGameVars[*insptr].global &= insptr[1]; insptr += 2; continue; @@ -1690,12 +1728,36 @@ next_instruction: Gv_AndVar(tw, Gv_GetVarX(*insptr++)); continue; + case CON_XORVAR: + insptr++; + Gv_XorVar(*insptr, insptr[1]); + insptr += 2; + continue; + + case CON_XORGLOBALVAR: + insptr++; + aGameVars[*insptr].global ^= insptr[1]; + insptr += 2; + continue; + case CON_XORVARVAR: insptr++; tw = *insptr++; Gv_XorVar(tw, Gv_GetVarX(*insptr++)); continue; + case CON_ORVAR: + insptr++; + Gv_OrVar(*insptr, insptr[1]); + insptr += 2; + continue; + + case CON_ORGLOBALVAR: + insptr++; + aGameVars[*insptr].global |= insptr[1]; + insptr += 2; + continue; + case CON_ORVARVAR: insptr++; tw = *insptr++; @@ -1708,9 +1770,9 @@ next_instruction: insptr += 2; continue; - case CON_SHIFTVARR: + case CON_SHIFTGLOBALVARL: insptr++; - Gv_ShiftVarR(*insptr, insptr[1]); + aGameVars[*insptr].global <<= insptr[1]; insptr += 2; continue; @@ -1720,12 +1782,48 @@ next_instruction: Gv_ShiftVarL(tw, Gv_GetVarX(*insptr++)); continue; + case CON_SHIFTVARR: + insptr++; + Gv_ShiftVarR(*insptr, insptr[1]); + insptr += 2; + continue; + + case CON_SHIFTGLOBALVARR: + insptr++; + aGameVars[*insptr].global >>= insptr[1]; + insptr += 2; + continue; + case CON_SHIFTVARVARR: insptr++; tw = *insptr++; Gv_ShiftVarR(tw, Gv_GetVarX(*insptr++)); continue; + case CON_MODVAR: + insptr++; + if (EDUKE32_PREDICT_FALSE(insptr[1] == 0)) + { + CON_CRITICALERRPRINTF("mod by zero!\n"); + continue; + } + + Gv_ModVar(*insptr, insptr[1]); + insptr += 2; + continue; + + case CON_MODGLOBALVAR: + insptr++; + if (EDUKE32_PREDICT_FALSE(insptr[1] == 0)) + { + CON_CRITICALERRPRINTF("mod by zero!\n"); + continue; + } + + aGameVars[*insptr].global %= insptr[1]; + insptr += 2; + continue; + case CON_MODVARVAR: insptr++; { @@ -1743,6 +1841,24 @@ next_instruction: continue; } + case CON_RANDVAR: + insptr++; + Gv_SetVarX(*insptr, mulscale16(krand(), insptr[1] + 1)); + insptr += 2; + continue; + + case CON_RANDGLOBALVAR: + insptr++; + aGameVars[*insptr].global = mulscale16(krand(), insptr[1] + 1); + insptr += 2; + continue; + + case CON_RANDVARVAR: + insptr++; + tw = *insptr++; + Gv_SetVarX(tw, mulscale16(krand(), Gv_GetVarX(*insptr++) + 1)); + continue; + case CON_SETPLAYER: insptr++; { @@ -5461,12 +5577,6 @@ badindex: continue; } - case CON_RANDVAR: - insptr++; - Gv_SetVarX(*insptr, mulscale16(krand(), insptr[1] + 1)); - insptr += 2; - continue; - case CON_DISPLAYRANDVAR: insptr++; Gv_SetVarX(*insptr, mulscale15(system_15bit_rand(), insptr[1] + 1)); @@ -5532,13 +5642,6 @@ badindex: insptr += 2; continue; - - case CON_RANDVARVAR: - insptr++; - tw = *insptr++; - Gv_SetVarX(tw, mulscale16(krand(), Gv_GetVarX(*insptr++) + 1)); - continue; - case CON_DISPLAYRANDVARVAR: insptr++; tw = *insptr++;