raze/source/duke3d/src/m32vars.cpp

701 lines
26 KiB
C++
Raw Normal View History

//-------------------------------------------------------------------------
/*
Copyright (C) 2010 EDuke32 developers and contributors
This file is part of EDuke32.
EDuke32 is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License version 2
as published by the Free Software Foundation.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
See the GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
//-------------------------------------------------------------------------
// This object is shared by the editors of *all* Build games!
#include "m32script.h"
#include "m32def.h"
#include "osd.h"
#include "keys.h"
#ifdef POLYMER
#include "polymer.h"
#endif
#define _m32vars_c_
#include "m32structures.cpp"
static void Gv_Clear(void)
{
// only call this function ONCE...
int32_t i=(MAXGAMEVARS-1);
//AddLog("Gv_Clear");
for (; i>=0; i--)
{
DO_FREE_AND_NULL(aGameVars[i].szLabel);
if (aGameVars[i].dwFlags & GAMEVAR_USER_MASK)
DO_FREE_AND_NULL(aGameVars[i].val.plValues);
aGameVars[i].val.lValue = 0;
aGameVars[i].dwFlags |= GAMEVAR_RESET;
if (i >= MAXGAMEARRAYS)
continue;
gamearray_t *const gar = &aGameArrays[i];
DO_FREE_AND_NULL(gar->szLabel);
if (gar->dwFlags & GAMEARRAY_NORMAL)
DO_FREE_AND_NULL(gar->vals);
gar->dwFlags |= GAMEARRAY_RESET;
}
g_gameVarCount = g_gameArrayCount = 0;
hash_init(&h_gamevars);
hash_init(&h_arrays);
return;
}
#define ASSERT_IMPLIES(x, y) Bassert(!(x) || (y))
void Gv_NewArray(const char *pszLabel, void *arrayptr, intptr_t asize, uint32_t dwFlags)
{
ASSERT_IMPLIES(dwFlags&GAMEARRAY_VARSIZE, dwFlags&GAMEARRAY_READONLY);
ASSERT_IMPLIES(dwFlags&GAMEARRAY_STRIDE2, dwFlags&GAMEARRAY_READONLY);
ASSERT_IMPLIES(dwFlags&GAMEARRAY_TYPE_MASK,
g_gameArrayCount==0 || (dwFlags&(GAMEARRAY_READONLY|GAMEARRAY_WARN)));
if (g_gameArrayCount >= MAXGAMEARRAYS)
{
C_CUSTOMERROR("too many arrays! (max: %d)", MAXGAMEARRAYS);
return;
}
if (Bstrlen(pszLabel) > (MAXARRAYLABEL-1))
{
C_CUSTOMERROR("array name `%s' exceeds limit of %d characters.", pszLabel, MAXARRAYLABEL);
return;
}
const int32_t i = hash_find(&h_arrays, pszLabel);
if (i>=0 && !(aGameArrays[i].dwFlags & GAMEARRAY_RESET))
{
// found it it's a duplicate in error
if (aGameArrays[i].dwFlags&GAMEARRAY_TYPE_MASK)
C_CUSTOMWARNING("ignored redefining system array `%s'.", pszLabel);
// C_ReportError(WARNING_DUPLICATEDEFINITION);
return;
}
if (!(dwFlags&GAMEARRAY_VARSIZE) && !(dwFlags&GAMEARRAY_TYPE_MASK) && (asize<=0 || asize>65536))
{
// the dummy array with index 0 sets the size to 0 so that accidental accesses as array
// will complain.
C_CUSTOMERROR("invalid array size %d. Must be between 1 and 65536", (int)asize);
return;
}
gamearray_t *const gar = &aGameArrays[g_gameArrayCount];
if (gar->szLabel == NULL)
gar->szLabel = (char *)Xcalloc(MAXARRAYLABEL, sizeof(char));
if (gar->szLabel != pszLabel)
Bstrcpy(gar->szLabel, pszLabel);
if (!(dwFlags & GAMEARRAY_TYPE_MASK))
gar->vals = (int32_t *)Xcalloc(asize, sizeof(int32_t));
else
gar->vals = arrayptr;
gar->size = asize;
gar->dwFlags = dwFlags & ~GAMEARRAY_RESET;
hash_add(&h_arrays, gar->szLabel, g_gameArrayCount, 1);
g_gameArrayCount++;
}
void Gv_NewVar(const char *pszLabel, intptr_t lValue, uint32_t dwFlags)
{
int32_t i, j;
//Bsprintf(g_szBuf,"Gv_NewVar(%s, %d, %X)",pszLabel, lValue, dwFlags);
//AddLog(g_szBuf);
if (g_gameVarCount >= MAXGAMEVARS)
{
C_CUSTOMERROR("too many gamevars! (max: %d)", MAXGAMEVARS);
return;
}
if (Bstrlen(pszLabel) > (MAXVARLABEL-1))
{
C_CUSTOMERROR("variable name `%s' exceeds limit of %d characters.", pszLabel, MAXVARLABEL);
return;
}
i = hash_find(&h_gamevars,pszLabel);
if (i >= 0 && !(aGameVars[i].dwFlags & GAMEVAR_RESET))
{
// found it...
if (aGameVars[i].dwFlags & GAMEVAR_PTR_MASK)
{
C_ReportError(-1);
initprintf("%s:%d: warning: cannot redefine internal gamevar `%s'.\n",g_szScriptFileName,g_lineNumber,label+(g_numLabels<<6));
return;
}
else if (!(aGameVars[i].dwFlags & GAMEVAR_SYSTEM))
{
// it's a duplicate in error
// g_numCompilerWarnings++;
// C_ReportError(WARNING_DUPLICATEDEFINITION);
return;
}
}
if (i == -1)
i = g_gameVarCount;
// Set values
if ((aGameVars[i].dwFlags & GAMEVAR_SYSTEM) == 0)
{
if (aGameVars[i].szLabel == NULL)
aGameVars[i].szLabel = (char *)Xcalloc(MAXVARLABEL, sizeof(uint8_t));
if (aGameVars[i].szLabel != pszLabel)
Bstrcpy(aGameVars[i].szLabel,pszLabel);
aGameVars[i].dwFlags = dwFlags;
if (aGameVars[i].dwFlags & GAMEVAR_USER_MASK)
{
// only free if not system
DO_FREE_AND_NULL(aGameVars[i].val.plValues);
}
}
// if existing is system, they only get to change default value....
aGameVars[i].lDefault = lValue;
aGameVars[i].dwFlags &= ~GAMEVAR_RESET;
if (i == g_gameVarCount)
{
// we're adding a new one.
hash_add(&h_gamevars, aGameVars[i].szLabel, g_gameVarCount++, 0);
}
if (aGameVars[i].dwFlags & GAMEVAR_PERBLOCK)
{
if (!aGameVars[i].val.plValues)
aGameVars[i].val.plValues = (int32_t *)Xcalloc(1+MAXEVENTS+g_stateCount, sizeof(int32_t));
for (j=0; j<1+MAXEVENTS+g_stateCount; j++)
aGameVars[i].val.plValues[j] = lValue;
}
else aGameVars[i].val.lValue = lValue;
}
int32_t __fastcall Gv_GetVarN(int32_t id) // 'N' for "no side-effects"... vars and locals only!
{
if (id == M32_THISACTOR_VAR_ID)
return vm.spriteNum;
switch (id&M32_VARTYPE_MASK)
{
case M32_FLAG_VAR:
id &= (MAXGAMEVARS-1);
switch (aGameVars[id].dwFlags & (GAMEVAR_USER_MASK|GAMEVAR_PTR_MASK))
{
case 0:
return aGameVars[id].val.lValue;
case GAMEVAR_PERBLOCK:
return aGameVars[id].val.plValues[vm.g_st];
case GAMEVAR_FLOATPTR:
case GAMEVAR_INTPTR:
return *((int32_t *)aGameVars[id].val.lValue);
case GAMEVAR_SHORTPTR:
return *((int16_t *)aGameVars[id].val.lValue);
case GAMEVAR_CHARPTR:
return *((uint8_t *)aGameVars[id].val.lValue);
default:
M32_ERROR("Gv_GetVarN(): WTF??");
return -1;
}
case M32_FLAG_LOCAL:
{
int32_t index = id&(MAXGAMEVARS-1);
// no bounds checking since it's done at script compilation time
return ((int32_t *)aGameArrays[M32_LOCAL_ARRAY_ID].vals)[index];
}
default:
M32_ERROR("Gv_GetVarN(): invalid var code %0x08x", id);
return -1;
}
}
int32_t __fastcall Gv_GetVarX(int32_t id)
{
int32_t negateResult = !!(id&M32_FLAG_NEGATE);
if (id == M32_THISACTOR_VAR_ID)
return vm.spriteNum;
id &= ~M32_FLAG_NEGATE;
if ((id & M32_BITS_MASK) == M32_FLAG_CONSTANT)
{
switch (id&3)
{
case 0:
return ((int16_t)(id>>16));
case 1:
return constants[(id>>16)&0xffff];
case 2:
return (labelval[(id>>16)&0xffff] ^ -negateResult) + negateResult;
default:
M32_ERROR("Gv_GetVarX() (constant): WTF??");
return -1;
}
}
switch (id&M32_VARTYPE_MASK)
{
case M32_FLAG_ARRAY:
{
int32_t index;
index = (int32_t)((id>>16)&0xffff);
if (!(id&M32_FLAG_CONSTANTINDEX))
index = Gv_GetVarN(index);
id &= (MAXGAMEARRAYS-1);
const int32_t siz = Gv_GetArraySize(id);
const gamearray_t *const gar = &aGameArrays[id];
if (index < 0 || index >= siz)
{
M32_ERROR("Gv_GetVarX(): invalid array index (%s[%d])", gar->szLabel, index);
return -1;
}
if (gar->dwFlags & GAMEARRAY_STRIDE2)
index <<= 1;
switch (gar->dwFlags & GAMEARRAY_TYPE_MASK)
{
case 0:
case GAMEARRAY_INT32:
return (((int32_t *)gar->vals)[index] ^ -negateResult) + negateResult;
case GAMEARRAY_INT16:
return (((int16_t *)gar->vals)[index] ^ -negateResult) + negateResult;
case GAMEARRAY_UINT8:
return (((uint8_t *)gar->vals)[index] ^ -negateResult) + negateResult;
default:
M32_ERROR("Gv_GetVarX() (array): WTF??");
return -1;
}
}
case M32_FLAG_STRUCT:
{
int32_t index, memberid;
index = (id>>16)&0x7fff;
if (!(id&M32_FLAG_CONSTANTINDEX))
index = Gv_GetVarN(index);
memberid = (id>>2)&63;
switch (id&3)
{
case M32_SPRITE_VAR_ID:
return (VM_AccessSprite(0, index, memberid, 0) ^ -negateResult) + negateResult;
case M32_SECTOR_VAR_ID:
return (VM_AccessSector(0, index, memberid, 0) ^ -negateResult) + negateResult;
case M32_WALL_VAR_ID:
return (VM_AccessWall(0, index, memberid, 0) ^ -negateResult) + negateResult;
case M32_TSPRITE_VAR_ID:
return (VM_AccessTsprite(0, index, memberid, 0) ^ -negateResult) + negateResult;
default:
M32_ERROR("Gv_GetVarX(): WTF??");
return -1;
}
}
case M32_FLAG_VAR:
{
id &= (MAXGAMEVARS-1);
switch (aGameVars[id].dwFlags & (GAMEVAR_USER_MASK|GAMEVAR_PTR_MASK))
{
case 0:
return (aGameVars[id].val.lValue ^ -negateResult) + negateResult;
case GAMEVAR_PERBLOCK:
return (aGameVars[id].val.plValues[vm.g_st] ^ -negateResult) + negateResult;
case GAMEVAR_FLOATPTR:
{
float fval = *(float *)aGameVars[id].val.lValue;
if (negateResult)
fval *= -1;
return *(int32_t *)&fval;
}
case GAMEVAR_INTPTR:
return (*((int32_t *)aGameVars[id].val.lValue) ^ -negateResult) + negateResult;
case GAMEVAR_SHORTPTR:
return (*((int16_t *)aGameVars[id].val.lValue) ^ -negateResult) + negateResult;
case GAMEVAR_CHARPTR:
return (*((uint8_t *)aGameVars[id].val.lValue) ^ -negateResult) + negateResult;
default:
M32_ERROR("Gv_GetVarX(): WTF??");
return -1;
}
}
case M32_FLAG_LOCAL:
{
int32_t index = id&(MAXGAMEVARS-1);
// no bounds checking since it's done at script compilation time
return (((int32_t *)aGameArrays[M32_LOCAL_ARRAY_ID].vals)[index] ^ -negateResult) + negateResult;
}
} // switch (id&M32_VARTYPE_MASK)
return 0; // never reached
}
void __fastcall Gv_SetVarX(int32_t id, int32_t lValue)
{
switch (id&M32_VARTYPE_MASK)
{
case M32_FLAG_ARRAY:
{
int32_t index;
index = (id>>16)&0xffff;
if (!(id&M32_FLAG_CONSTANTINDEX))
index = Gv_GetVarN(index);
id &= (MAXGAMEARRAYS-1);
const int32_t siz = Gv_GetArraySize(id);
gamearray_t *const gar = &aGameArrays[id];
if (index < 0 || index >= siz)
{
M32_ERROR("Gv_SetVarX(): invalid array index %s[%d], size=%d", gar->szLabel, index, siz);
return;
}
// NOTE: GAMEARRAY_READONLY arrays can be modified in expert mode.
Bassert((gar->dwFlags & GAMEARRAY_STRIDE2) == 0);
switch (gar->dwFlags & GAMEARRAY_TYPE_MASK)
{
case 0:
case GAMEARRAY_INT32:
((int32_t *)gar->vals)[index] = lValue;
return;
case GAMEARRAY_INT16:
((int16_t *)gar->vals)[index] = (int16_t)lValue;
return;
case GAMEARRAY_UINT8:
((uint8_t *)gar->vals)[index] = (uint8_t)lValue;
return;
default:
M32_ERROR("Gv_SetVarX() (array): WTF??");
return;
}
return;
}
case M32_FLAG_STRUCT:
{
int32_t index, memberid;
index = (id>>16)&0x7fff;
if (!(id&M32_FLAG_CONSTANTINDEX))
index = Gv_GetVarN(index);
memberid = (id>>2)&63;
switch (id&3)
{
case M32_SPRITE_VAR_ID:
VM_AccessSprite(1, index, memberid, lValue);
return;
case M32_SECTOR_VAR_ID:
VM_AccessSector(1, index, memberid, lValue);
return;
case M32_WALL_VAR_ID:
VM_AccessWall(1, index, memberid, lValue);
return;
case M32_TSPRITE_VAR_ID:
VM_AccessTsprite(1, index, memberid, lValue);
return;
default:
M32_ERROR("Gv_SetVarX(): WTF??");
return;
}
}
case M32_FLAG_VAR:
{
id &= (MAXGAMEVARS-1);
switch (aGameVars[id].dwFlags & (GAMEVAR_USER_MASK|GAMEVAR_PTR_MASK))
{
case 0:
aGameVars[id].val.lValue=lValue;
return;
case GAMEVAR_PERBLOCK:
aGameVars[id].val.plValues[vm.g_st] = lValue;
return;
case GAMEVAR_FLOATPTR:
{
int32_t ival = lValue;
float fval = *(float *)&ival;
if (fval!=fval || fval<-3.4e38 || fval > 3.4e38)
{
M32_ERROR("Gv_SetVarX(): tried to set float var to NaN or infinity");
return;
}
}
fallthrough__;
case GAMEVAR_INTPTR:
*((int32_t *)aGameVars[id].val.lValue)=(int32_t)lValue;
return;
case GAMEVAR_SHORTPTR:
*((int16_t *)aGameVars[id].val.lValue)=(int16_t)lValue;
return;
case GAMEVAR_CHARPTR:
*((uint8_t *)aGameVars[id].val.lValue)=(uint8_t)lValue;
return;
default:
M32_ERROR("Gv_SetVarX(): WTF??");
return;
}
}
case M32_FLAG_LOCAL:
{
int32_t index = id&(MAXGAMEVARS-1);
((int32_t *)aGameArrays[M32_LOCAL_ARRAY_ID].vals)[index] = lValue;
return;
}
}
}
static uint8_t alphakeys[] =
{
KEYSC_SPACE,
KEYSC_A, KEYSC_B, KEYSC_C, KEYSC_D, KEYSC_E, KEYSC_F, KEYSC_G, KEYSC_H,
KEYSC_I, KEYSC_J, KEYSC_K, KEYSC_L, KEYSC_M, KEYSC_N, KEYSC_O, KEYSC_P,
KEYSC_Q, KEYSC_R, KEYSC_S, KEYSC_T, KEYSC_U, KEYSC_V, KEYSC_W, KEYSC_X,
KEYSC_Y, KEYSC_Z,
};
static uint8_t numberkeys[] =
{
KEYSC_0, KEYSC_1, KEYSC_2, KEYSC_3, KEYSC_4, KEYSC_5, KEYSC_6, KEYSC_7,
KEYSC_8, KEYSC_9,
};
static void Gv_AddSystemVars(void)
{
// only call ONCE
int32_t hlcnt_id, hlscnt_id;
// special vars for struct access
// MUST be at top and in this order!!!
Gv_NewVar("sprite", -1, GAMEVAR_READONLY | GAMEVAR_SYSTEM | GAMEVAR_SPECIAL);
Gv_NewVar("sector", -1, GAMEVAR_READONLY | GAMEVAR_SYSTEM | GAMEVAR_SPECIAL);
Gv_NewVar("wall", -1, GAMEVAR_READONLY | GAMEVAR_SYSTEM | GAMEVAR_SPECIAL);
Gv_NewVar("tsprite", -1, GAMEVAR_READONLY | GAMEVAR_SYSTEM | GAMEVAR_SPECIAL);
Gv_NewVar("light", -1, GAMEVAR_READONLY | GAMEVAR_SYSTEM | GAMEVAR_SPECIAL);
// these too have to be in here and in order!
// keep in sync with m32script.h: IDs of special vars
Gv_NewVar("I", 0, GAMEVAR_READONLY | GAMEVAR_SYSTEM); // THISACTOR
Gv_NewVar("RETURN", (intptr_t)&g_iReturnVar, GAMEVAR_INTPTR | GAMEVAR_SYSTEM);
Gv_NewVar("LOTAG", 0, GAMEVAR_SYSTEM);
Gv_NewVar("HITAG", 0, GAMEVAR_SYSTEM);
Gv_NewVar("TEXTURE", 0, GAMEVAR_SYSTEM);
Gv_NewVar("DOSCRSHOT", (intptr_t)&g_doScreenShot, GAMEVAR_INTPTR | GAMEVAR_SYSTEM);
Gv_NewVar("xdim",(intptr_t)&xdim, GAMEVAR_INTPTR | GAMEVAR_SYSTEM | GAMEVAR_READONLY);
Gv_NewVar("ydim",(intptr_t)&ydim, GAMEVAR_INTPTR | GAMEVAR_SYSTEM | GAMEVAR_READONLY);
Gv_NewVar("windowx1",(intptr_t)&windowxy1.x, GAMEVAR_INTPTR | GAMEVAR_SYSTEM | GAMEVAR_READONLY);
Gv_NewVar("windowx2",(intptr_t)&windowxy2.x, GAMEVAR_INTPTR | GAMEVAR_SYSTEM | GAMEVAR_READONLY);
Gv_NewVar("windowy1",(intptr_t)&windowxy1.y, GAMEVAR_INTPTR | GAMEVAR_SYSTEM | GAMEVAR_READONLY);
Gv_NewVar("windowy2",(intptr_t)&windowxy2.y, GAMEVAR_INTPTR | GAMEVAR_SYSTEM | GAMEVAR_READONLY);
Gv_NewVar("totalclock",(intptr_t)&totalclock, GAMEVAR_INTPTR | GAMEVAR_SYSTEM | GAMEVAR_READONLY);
Gv_NewVar("viewingrange",(intptr_t)&viewingrange, GAMEVAR_SYSTEM | GAMEVAR_INTPTR | GAMEVAR_READONLY);
Gv_NewVar("yxaspect",(intptr_t)&yxaspect, GAMEVAR_SYSTEM | GAMEVAR_INTPTR | GAMEVAR_READONLY);
/// Gv_NewVar("framerate",(intptr_t)&g_frameRate, GAMEVAR_SYSTEM | GAMEVAR_INTPTR | GAMEVAR_READONLY);
/// Gv_NewVar("display_mirror",(intptr_t)&display_mirror, GAMEVAR_SYSTEM | GAMEVAR_CHARPTR);
Gv_NewVar("randomseed",(intptr_t)&randomseed, GAMEVAR_SYSTEM | GAMEVAR_INTPTR);
Gv_NewVar("numwalls",(intptr_t)&numwalls, GAMEVAR_SYSTEM | GAMEVAR_SHORTPTR | GAMEVAR_READONLY);
Gv_NewVar("numsectors",(intptr_t)&numsectors, GAMEVAR_SYSTEM | GAMEVAR_SHORTPTR | GAMEVAR_READONLY);
Gv_NewVar("numsprites",(intptr_t)&Numsprites, GAMEVAR_SYSTEM | GAMEVAR_INTPTR | GAMEVAR_READONLY);
{
static int32_t numtiles;
Gv_NewVar("numtiles",(intptr_t)&numtiles, GAMEVAR_SYSTEM | GAMEVAR_INTPTR | GAMEVAR_READONLY);
}
#ifdef YAX_ENABLE
Gv_NewVar("numbunches",(intptr_t)&numyaxbunches, GAMEVAR_SYSTEM | GAMEVAR_INTPTR | GAMEVAR_READONLY);
#endif
#ifdef USE_OPENGL
Gv_NewVar("rendmode",(intptr_t)&rendmode, GAMEVAR_READONLY | GAMEVAR_INTPTR | GAMEVAR_SYSTEM);
#endif
// current position
Gv_NewVar("posx",(intptr_t)&pos.x, GAMEVAR_INTPTR | GAMEVAR_SYSTEM);
Gv_NewVar("posy",(intptr_t)&pos.y, GAMEVAR_INTPTR | GAMEVAR_SYSTEM);
Gv_NewVar("posz",(intptr_t)&pos.z, GAMEVAR_INTPTR | GAMEVAR_SYSTEM);
Gv_NewVar("ang",(intptr_t)&ang, GAMEVAR_SHORTPTR | GAMEVAR_SYSTEM);
Gv_NewVar("horiz",(intptr_t)&horiz, GAMEVAR_INTPTR | GAMEVAR_SYSTEM);
Gv_NewVar("cursectnum",(intptr_t)&cursectnum, GAMEVAR_READONLY | GAMEVAR_SHORTPTR | GAMEVAR_SYSTEM);
Gv_NewVar("hardcoded_movement",(intptr_t)&g_doHardcodedMovement, GAMEVAR_INTPTR | GAMEVAR_SYSTEM);
Gv_NewVar("searchx",(intptr_t)&searchx, GAMEVAR_READONLY | GAMEVAR_INTPTR | GAMEVAR_SYSTEM);
Gv_NewVar("searchy",(intptr_t)&searchy, GAMEVAR_READONLY | GAMEVAR_INTPTR | GAMEVAR_SYSTEM);
Gv_NewVar("searchstat",(intptr_t)&searchstat, GAMEVAR_READONLY | GAMEVAR_SHORTPTR | GAMEVAR_SYSTEM);
Gv_NewVar("searchwall",(intptr_t)&searchwall, GAMEVAR_READONLY | GAMEVAR_SHORTPTR | GAMEVAR_SYSTEM);
Gv_NewVar("searchsector",(intptr_t)&searchsector, GAMEVAR_READONLY | GAMEVAR_SHORTPTR | GAMEVAR_SYSTEM);
Gv_NewVar("searchbottomwall",(intptr_t)&searchbottomwall, GAMEVAR_READONLY | GAMEVAR_SHORTPTR | GAMEVAR_SYSTEM);
Gv_NewVar("pointhighlight",(intptr_t)&pointhighlight, GAMEVAR_SHORTPTR|GAMEVAR_SYSTEM|GAMEVAR_READONLY);
Gv_NewVar("linehighlight",(intptr_t)&linehighlight, GAMEVAR_SHORTPTR|GAMEVAR_SYSTEM|GAMEVAR_READONLY);
hlcnt_id = g_gameVarCount;
Gv_NewVar("highlightcnt",(intptr_t)&highlightcnt, GAMEVAR_SHORTPTR|GAMEVAR_SYSTEM|GAMEVAR_READONLY);
hlscnt_id = g_gameVarCount;
Gv_NewVar("highlightsectorcnt",(intptr_t)&highlightsectorcnt, GAMEVAR_SHORTPTR|GAMEVAR_SYSTEM|GAMEVAR_READONLY);
// clipboard contents
Gv_NewVar("temppicnum",(intptr_t)&temppicnum, GAMEVAR_INTPTR|GAMEVAR_SYSTEM|GAMEVAR_READONLY);
Gv_NewVar("tempcstat",(intptr_t)&tempcstat, GAMEVAR_INTPTR|GAMEVAR_SYSTEM|GAMEVAR_READONLY);
Gv_NewVar("templotag",(intptr_t)&templotag, GAMEVAR_INTPTR|GAMEVAR_SYSTEM|GAMEVAR_READONLY);
Gv_NewVar("temphitag",(intptr_t)&temphitag, GAMEVAR_INTPTR|GAMEVAR_SYSTEM|GAMEVAR_READONLY);
Gv_NewVar("tempextra",(intptr_t)&tempextra, GAMEVAR_INTPTR|GAMEVAR_SYSTEM|GAMEVAR_READONLY);
Gv_NewVar("tempshade",(intptr_t)&tempshade, GAMEVAR_INTPTR|GAMEVAR_SYSTEM|GAMEVAR_READONLY);
Gv_NewVar("temppal",(intptr_t)&temppal, GAMEVAR_INTPTR|GAMEVAR_SYSTEM|GAMEVAR_READONLY);
Gv_NewVar("tempvis",(intptr_t)&tempvis, GAMEVAR_INTPTR|GAMEVAR_SYSTEM|GAMEVAR_READONLY);
Gv_NewVar("tempxrepeat",(intptr_t)&tempxrepeat, GAMEVAR_INTPTR|GAMEVAR_SYSTEM|GAMEVAR_READONLY);
Gv_NewVar("tempyrepeat",(intptr_t)&tempyrepeat, GAMEVAR_INTPTR|GAMEVAR_SYSTEM|GAMEVAR_READONLY);
// starting position
Gv_NewVar("startposx",(intptr_t)&startpos.x, GAMEVAR_READONLY | GAMEVAR_INTPTR | GAMEVAR_SYSTEM);
Gv_NewVar("startposy",(intptr_t)&startpos.y, GAMEVAR_READONLY | GAMEVAR_INTPTR | GAMEVAR_SYSTEM);
Gv_NewVar("startposz",(intptr_t)&startpos.z, GAMEVAR_READONLY | GAMEVAR_INTPTR | GAMEVAR_SYSTEM);
Gv_NewVar("startang",(intptr_t)&startang, GAMEVAR_READONLY | GAMEVAR_SHORTPTR | GAMEVAR_SYSTEM);
Gv_NewVar("startsectnum",(intptr_t)&startsectnum, GAMEVAR_READONLY | GAMEVAR_SHORTPTR | GAMEVAR_SYSTEM);
Gv_NewVar("mousxplc",(intptr_t)&mousxplc, GAMEVAR_READONLY | GAMEVAR_INTPTR | GAMEVAR_SYSTEM);
Gv_NewVar("mousyplc",(intptr_t)&mousyplc, GAMEVAR_READONLY | GAMEVAR_INTPTR | GAMEVAR_SYSTEM);
Gv_NewVar("zoom",(intptr_t)&zoom, GAMEVAR_READONLY | GAMEVAR_INTPTR | GAMEVAR_SYSTEM);
Gv_NewVar("drawlinepat",(intptr_t)&m32_drawlinepat, GAMEVAR_INTPTR | GAMEVAR_SYSTEM);
Gv_NewVar("halfxdim16", (intptr_t)&halfxdim16, GAMEVAR_READONLY | GAMEVAR_INTPTR | GAMEVAR_SYSTEM);
Gv_NewVar("midydim16", (intptr_t)&midydim16, GAMEVAR_READONLY | GAMEVAR_INTPTR | GAMEVAR_SYSTEM);
Gv_NewVar("ydim16",(intptr_t)&ydim16, GAMEVAR_INTPTR | GAMEVAR_SYSTEM | GAMEVAR_READONLY);
Gv_NewVar("m32_sideview",(intptr_t)&m32_sideview, GAMEVAR_INTPTR | GAMEVAR_SYSTEM | GAMEVAR_READONLY);
Gv_NewVar("SV1",(intptr_t)&m32_sortvar1, GAMEVAR_INTPTR | GAMEVAR_SYSTEM | GAMEVAR_READONLY);
Gv_NewVar("SV2",(intptr_t)&m32_sortvar2, GAMEVAR_INTPTR | GAMEVAR_SYSTEM | GAMEVAR_READONLY);
Gv_NewVar("spritesortcnt",(intptr_t)&spritesortcnt, GAMEVAR_INTPTR | GAMEVAR_SYSTEM | GAMEVAR_READONLY);
#ifdef POLYMER
Gv_NewVar("pr_overrideparallax",(intptr_t)&pr_overrideparallax, GAMEVAR_INTPTR | GAMEVAR_SYSTEM);
Gv_NewVar("pr_parallaxscale",(intptr_t)&pr_parallaxscale, GAMEVAR_FLOATPTR | GAMEVAR_SYSTEM);
Gv_NewVar("pr_parallaxbias",(intptr_t)&pr_parallaxbias, GAMEVAR_FLOATPTR | GAMEVAR_SYSTEM);
Gv_NewVar("pr_overridespecular",(intptr_t)&pr_overridespecular, GAMEVAR_INTPTR | GAMEVAR_SYSTEM);
Gv_NewVar("pr_specularpower",(intptr_t)&pr_specularpower, GAMEVAR_FLOATPTR | GAMEVAR_SYSTEM);
Gv_NewVar("pr_specularfactor",(intptr_t)&pr_specularfactor, GAMEVAR_FLOATPTR | GAMEVAR_SYSTEM);
#else
{
// dummy Polymer variables for non-Polymer builds
static int32_t pr_overrideparallax = 0;
static float pr_parallaxscale = 0.1f;
static float pr_parallaxbias = 0.0f;
static int32_t pr_overridespecular = 0;
static float pr_specularpower = 15.0f;
static float pr_specularfactor = 1.0f;
Gv_NewVar("pr_overrideparallax",(intptr_t)&pr_overrideparallax, GAMEVAR_INTPTR | GAMEVAR_SYSTEM);
Gv_NewVar("pr_parallaxscale",(intptr_t)&pr_parallaxscale, GAMEVAR_FLOATPTR | GAMEVAR_SYSTEM);
Gv_NewVar("pr_parallaxbias",(intptr_t)&pr_parallaxbias, GAMEVAR_FLOATPTR | GAMEVAR_SYSTEM);
Gv_NewVar("pr_overridespecular",(intptr_t)&pr_overridespecular, GAMEVAR_INTPTR | GAMEVAR_SYSTEM);
Gv_NewVar("pr_specularpower",(intptr_t)&pr_specularpower, GAMEVAR_FLOATPTR | GAMEVAR_SYSTEM);
Gv_NewVar("pr_specularfactor",(intptr_t)&pr_specularfactor, GAMEVAR_FLOATPTR | GAMEVAR_SYSTEM);
}
#endif
g_systemVarCount = g_gameVarCount;
// must be first!
Gv_NewArray(".LOCALS_BASE", NULL, 0, GAMEARRAY_INT32);
Gv_NewArray("highlight", (void *)highlight, hlcnt_id,
GAMEARRAY_READONLY|GAMEARRAY_INT16|GAMEARRAY_VARSIZE);
Gv_NewArray("highlightsector", (void *)highlightsector, hlscnt_id,
GAMEARRAY_READONLY|GAMEARRAY_INT16|GAMEARRAY_VARSIZE);
Gv_NewArray("hsect", (void *)headspritesect, MAXSECTORS+1, GAMEARRAY_READONLY|GAMEARRAY_INT16);
Gv_NewArray("psect", (void *)prevspritesect, MAXSPRITES, GAMEARRAY_READONLY|GAMEARRAY_INT16);
Gv_NewArray("nsect", (void *)nextspritesect, MAXSPRITES, GAMEARRAY_READONLY|GAMEARRAY_INT16);
Gv_NewArray("hstat", (void *)headspritestat, MAXSTATUS+1, GAMEARRAY_READONLY|GAMEARRAY_INT16);
Gv_NewArray("pstat", (void *)prevspritestat, MAXSPRITES, GAMEARRAY_READONLY|GAMEARRAY_INT16);
Gv_NewArray("nstat", (void *)nextspritestat, MAXSPRITES, GAMEARRAY_READONLY|GAMEARRAY_INT16);
#ifdef YAX_ENABLE
Gv_NewArray("headsectbunchc", (void *)headsectbunch[0], YAX_MAXBUNCHES, GAMEARRAY_READONLY|GAMEARRAY_INT16);
Gv_NewArray("nextsectbunchc", (void *)nextsectbunch[0], MAXSECTORS, GAMEARRAY_READONLY|GAMEARRAY_INT16);
Gv_NewArray("headsectbunchf", (void *)headsectbunch[1], YAX_MAXBUNCHES, GAMEARRAY_READONLY|GAMEARRAY_INT16);
Gv_NewArray("nextsectbunchf", (void *)nextsectbunch[1], MAXSECTORS, GAMEARRAY_READONLY|GAMEARRAY_INT16);
#endif
Gv_NewArray("editorcolors", (void *)editorcolors, 256, GAMEARRAY_READONLY|GAMEARRAY_UINT8);
Gv_NewArray("tilesizx", (void *)&tilesiz[0].x, MAXTILES, GAMEARRAY_STRIDE2|GAMEARRAY_READONLY|GAMEARRAY_INT16);
Gv_NewArray("tilesizy", (void *)&tilesiz[0].y, MAXTILES, GAMEARRAY_STRIDE2|GAMEARRAY_READONLY|GAMEARRAY_INT16);
// Gv_NewArray("picsiz", (void *)picsiz, MAXTILES, GAMEARRAY_READONLY|GAMEARRAY_OFCHAR);
Gv_NewArray("picanm", (void *)picanm, MAXTILES, GAMEARRAY_READONLY|GAMEARRAY_INT32);
Gv_NewArray("show2dsector", (void *)show2dsector, (MAXSECTORS+7)>>3, GAMEARRAY_READONLY|GAMEARRAY_UINT8);
Gv_NewArray("show2dwall", (void *)show2dwall, (MAXWALLS+7)>>3, GAMEARRAY_READONLY|GAMEARRAY_UINT8);
Gv_NewArray("show2dsprite", (void *)show2dsprite, (MAXSPRITES+7)>>3, GAMEARRAY_READONLY|GAMEARRAY_UINT8);
Gv_NewArray("keystatus", (void *)keystatus, 256, GAMEARRAY_WARN|GAMEARRAY_UINT8);
Gv_NewArray("alphakeys", (void *)alphakeys, sizeof(alphakeys), GAMEARRAY_READONLY|GAMEARRAY_UINT8);
Gv_NewArray("numberkeys", (void *)numberkeys, sizeof(numberkeys), GAMEARRAY_READONLY|GAMEARRAY_UINT8);
g_systemArrayCount = g_gameArrayCount;
}
void Gv_Init(void)
{
// only call ONCE
Gv_Clear();
Gv_AddSystemVars();
}