1 //-------------------------------------------------------------------------
2 /*
3 Copyright (C) 2010 EDuke32 developers and contributors
4 
5 This file is part of EDuke32.
6 
7 EDuke32 is free software; you can redistribute it and/or
8 modify it under the terms of the GNU General Public License version 2
9 as published by the Free Software Foundation.
10 
11 This program is distributed in the hope that it will be useful,
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
14 
15 See the GNU General Public License for more details.
16 
17 You should have received a copy of the GNU General Public License
18 along with this program; if not, write to the Free Software
19 Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
20 */
21 //-------------------------------------------------------------------------
22 
23 // This object is shared by the editors of *all* Build games!
24 
25 #include "m32script.h"
26 #include "m32def.h"
27 #include "osd.h"
28 #include "keys.h"
29 #ifdef POLYMER
30 #include "polymer.h"
31 #endif
32 
33 #define _m32vars_c_
34 #include "m32structures.cpp"
35 
Gv_Clear(void)36 static void Gv_Clear(void)
37 {
38     // only call this function ONCE...
39     int32_t i=(MAXGAMEVARS-1);
40 
41     //AddLog("Gv_Clear");
42 
43     for (; i>=0; i--)
44     {
45         DO_FREE_AND_NULL(aGameVars[i].szLabel);
46 
47         if (aGameVars[i].dwFlags & GAMEVAR_USER_MASK)
48             DO_FREE_AND_NULL(aGameVars[i].val.plValues);
49 
50         aGameVars[i].val.lValue = 0;
51         aGameVars[i].dwFlags |= GAMEVAR_RESET;
52 
53         if (i >= MAXGAMEARRAYS)
54             continue;
55 
56         gamearray_t *const gar = &aGameArrays[i];
57 
58         DO_FREE_AND_NULL(gar->szLabel);
59 
60         if (gar->dwFlags & GAMEARRAY_NORMAL)
61             DO_FREE_AND_NULL(gar->vals);
62 
63         gar->dwFlags |= GAMEARRAY_RESET;
64     }
65 
66     g_gameVarCount = g_gameArrayCount = 0;
67 
68     hash_init(&h_gamevars);
69     hash_init(&h_arrays);
70 }
71 
72 #define ASSERT_IMPLIES(x, y) Bassert(!(x) || (y))
73 
Gv_NewArray(const char * pszLabel,void * arrayptr,intptr_t asize,uint32_t dwFlags)74 void Gv_NewArray(const char *pszLabel, void *arrayptr, intptr_t asize, uint32_t dwFlags)
75 {
76     ASSERT_IMPLIES(dwFlags&GAMEARRAY_VARSIZE, dwFlags&GAMEARRAY_READONLY);
77     ASSERT_IMPLIES(dwFlags&GAMEARRAY_STRIDE2, dwFlags&GAMEARRAY_READONLY);
78     ASSERT_IMPLIES(dwFlags&GAMEARRAY_TYPE_MASK,
79                    g_gameArrayCount==0 || (dwFlags&(GAMEARRAY_READONLY|GAMEARRAY_WARN)));
80 
81     if (g_gameArrayCount >= MAXGAMEARRAYS)
82     {
83         C_CUSTOMERROR("too many arrays! (max: %d)", MAXGAMEARRAYS);
84         return;
85     }
86 
87     if (Bstrlen(pszLabel) > (MAXARRAYLABEL-1))
88     {
89         C_CUSTOMERROR("array name `%s' exceeds limit of %d characters.", pszLabel, MAXARRAYLABEL);
90         return;
91     }
92 
93     const int32_t i = hash_find(&h_arrays, pszLabel);
94 
95     if (i>=0 && !(aGameArrays[i].dwFlags & GAMEARRAY_RESET))
96     {
97         // found it it's a duplicate in error
98 
99         if (aGameArrays[i].dwFlags&GAMEARRAY_TYPE_MASK)
100             C_CUSTOMWARNING("ignored redefining system array `%s'.", pszLabel);
101 
102 //        C_ReportError(WARNING_DUPLICATEDEFINITION);
103         return;
104     }
105 
106     if (!(dwFlags&GAMEARRAY_VARSIZE) && !(dwFlags&GAMEARRAY_TYPE_MASK) && (asize<=0 || asize>65536))
107     {
108         // the dummy array with index 0 sets the size to 0 so that accidental accesses as array
109         // will complain.
110         C_CUSTOMERROR("invalid array size %d. Must be between 1 and 65536", (int)asize);
111         return;
112     }
113 
114     gamearray_t *const gar = &aGameArrays[g_gameArrayCount];
115 
116     if (gar->szLabel == NULL)
117         gar->szLabel = (char *)Xcalloc(MAXARRAYLABEL, sizeof(char));
118     if (gar->szLabel != pszLabel)
119         Bstrcpy(gar->szLabel, pszLabel);
120 
121     if (!(dwFlags & GAMEARRAY_TYPE_MASK))
122         gar->vals = (int32_t *)Xcalloc(asize, sizeof(int32_t));
123     else
124         gar->vals = arrayptr;
125 
126     gar->size = asize;
127     gar->dwFlags = dwFlags & ~GAMEARRAY_RESET;
128 
129     hash_add(&h_arrays, gar->szLabel, g_gameArrayCount, 1);
130     g_gameArrayCount++;
131 }
132 
Gv_NewVar(const char * pszLabel,intptr_t lValue,uint32_t dwFlags)133 void Gv_NewVar(const char *pszLabel, intptr_t lValue, uint32_t dwFlags)
134 {
135     int32_t i, j;
136 
137     //Bsprintf(g_szBuf,"Gv_NewVar(%s, %d, %X)",pszLabel, lValue, dwFlags);
138     //AddLog(g_szBuf);
139 
140     if (g_gameVarCount >= MAXGAMEVARS)
141     {
142         C_CUSTOMERROR("too many gamevars! (max: %d)", MAXGAMEVARS);
143         return;
144     }
145 
146     if (Bstrlen(pszLabel) > (MAXVARLABEL-1))
147     {
148         C_CUSTOMERROR("variable name `%s' exceeds limit of %d characters.", pszLabel, MAXVARLABEL);
149         return;
150     }
151 
152     i = hash_find(&h_gamevars,pszLabel);
153 
154     if (i >= 0 && !(aGameVars[i].dwFlags & GAMEVAR_RESET))
155     {
156         // found it...
157         if (aGameVars[i].dwFlags & GAMEVAR_PTR_MASK)
158         {
159             C_ReportError(-1);
160             initprintf("%s:%d: warning: cannot redefine internal gamevar `%s'.\n",g_szScriptFileName,g_lineNumber,label+(g_numLabels<<6));
161             return;
162         }
163         else if (!(aGameVars[i].dwFlags & GAMEVAR_SYSTEM))
164         {
165             // it's a duplicate in error
166 //            g_numCompilerWarnings++;
167 //            C_ReportError(WARNING_DUPLICATEDEFINITION);
168             return;
169         }
170     }
171 
172     if (i == -1)
173         i = g_gameVarCount;
174 
175     // Set values
176     if ((aGameVars[i].dwFlags & GAMEVAR_SYSTEM) == 0)
177     {
178         if (aGameVars[i].szLabel == NULL)
179             aGameVars[i].szLabel = (char *)Xcalloc(MAXVARLABEL, sizeof(uint8_t));
180         if (aGameVars[i].szLabel != pszLabel)
181             Bstrcpy(aGameVars[i].szLabel,pszLabel);
182         aGameVars[i].dwFlags = dwFlags;
183 
184         if (aGameVars[i].dwFlags & GAMEVAR_USER_MASK)
185         {
186             // only free if not system
187             DO_FREE_AND_NULL(aGameVars[i].val.plValues);
188         }
189     }
190 
191     // if existing is system, they only get to change default value....
192     aGameVars[i].lDefault = lValue;
193     aGameVars[i].dwFlags &= ~GAMEVAR_RESET;
194 
195     if (i == g_gameVarCount)
196     {
197         // we're adding a new one.
198         hash_add(&h_gamevars, aGameVars[i].szLabel, g_gameVarCount++, 0);
199     }
200 
201     if (aGameVars[i].dwFlags & GAMEVAR_PERBLOCK)
202     {
203         if (!aGameVars[i].val.plValues)
204             aGameVars[i].val.plValues = (int32_t *)Xcalloc(1+MAXEVENTS+g_stateCount, sizeof(int32_t));
205         for (j=0; j<1+MAXEVENTS+g_stateCount; j++)
206             aGameVars[i].val.plValues[j] = lValue;
207     }
208     else aGameVars[i].val.lValue = lValue;
209 }
210 
Gv_GetVarN(int32_t id)211 int32_t __fastcall Gv_GetVarN(int32_t id)  // 'N' for "no side-effects"... vars and locals only!
212 {
213     if (id == M32_THISACTOR_VAR_ID)
214         return vm.spriteNum;
215 
216     switch (id&M32_VARTYPE_MASK)
217     {
218     case M32_FLAG_VAR:
219         id &= (MAXGAMEVARS-1);
220 
221         switch (aGameVars[id].dwFlags & (GAMEVAR_USER_MASK|GAMEVAR_PTR_MASK))
222         {
223         case 0:
224             return aGameVars[id].val.lValue;
225         case GAMEVAR_PERBLOCK:
226             return aGameVars[id].val.plValues[vm.g_st];
227         case GAMEVAR_FLOATPTR:
228         case GAMEVAR_INTPTR:
229             return *((int32_t *)aGameVars[id].val.lValue);
230         case GAMEVAR_SHORTPTR:
231             return *((int16_t *)aGameVars[id].val.lValue);
232         case GAMEVAR_CHARPTR:
233             return *((uint8_t *)aGameVars[id].val.lValue);
234         default:
235             M32_ERROR("Gv_GetVarN(): WTF??");
236             return -1;
237         }
238 
239     case M32_FLAG_LOCAL:
240     {
241         int32_t index = id&(MAXGAMEVARS-1);
242         // no bounds checking since it's done at script compilation time
243         return ((int32_t *)aGameArrays[M32_LOCAL_ARRAY_ID].vals)[index];
244     }
245 
246     default:
247         M32_ERROR("Gv_GetVarN(): invalid var code %0x08x", id);
248         return -1;
249     }
250 }
251 
Gv_GetVar(int32_t id)252 int32_t __fastcall Gv_GetVar(int32_t id)
253 {
254     int32_t negateResult = !!(id&M32_FLAG_NEGATE);
255 
256     if (id == M32_THISACTOR_VAR_ID)
257         return vm.spriteNum;
258 
259     id &= ~M32_FLAG_NEGATE;
260 
261     if ((id & M32_BITS_MASK) == M32_FLAG_CONSTANT)
262     {
263         switch (id&3)
264         {
265         case 0:
266             return ((int16_t)(id>>16));
267         case 1:
268             return constants[(id>>16)&0xffff];
269         case 2:
270             return (labelval[(id>>16)&0xffff] ^ -negateResult) + negateResult;
271         default:
272             M32_ERROR("Gv_GetVarX() (constant): WTF??");
273             return -1;
274         }
275     }
276 
277 
278     switch (id&M32_VARTYPE_MASK)
279     {
280     case M32_FLAG_ARRAY:
281     {
282         int32_t index;
283 
284         index = (int32_t)((id>>16)&0xffff);
285         if (!(id&M32_FLAG_CONSTANTINDEX))
286             index = Gv_GetVarN(index);
287 
288         id &= (MAXGAMEARRAYS-1);
289 
290         const int32_t siz = Gv_GetArraySize(id);
291         const gamearray_t *const gar = &aGameArrays[id];
292 
293         if (index < 0 || index >= siz)
294         {
295             M32_ERROR("Gv_GetVarX(): invalid array index (%s[%d])", gar->szLabel, index);
296             return -1;
297         }
298 
299         if (gar->dwFlags & GAMEARRAY_STRIDE2)
300             index <<= 1;
301 
302         switch (gar->dwFlags & GAMEARRAY_TYPE_MASK)
303         {
304         case 0:
305         case GAMEARRAY_INT32:
306             return (((int32_t *)gar->vals)[index] ^ -negateResult) + negateResult;
307         case GAMEARRAY_INT16:
308             return (((int16_t *)gar->vals)[index] ^ -negateResult) + negateResult;
309         case GAMEARRAY_UINT8:
310             return (((uint8_t *)gar->vals)[index] ^ -negateResult) + negateResult;
311         default:
312             M32_ERROR("Gv_GetVarX() (array): WTF??");
313             return -1;
314         }
315     }
316     case M32_FLAG_STRUCT:
317     {
318         int32_t index, memberid;
319 
320         index = (id>>16)&0x7fff;
321         if (!(id&M32_FLAG_CONSTANTINDEX))
322             index = Gv_GetVarN(index);
323 
324         memberid = (id>>2)&63;
325 
326         switch (id&3)
327         {
328         case M32_SPRITE_VAR_ID:
329             return (VM_AccessSprite(0, index, memberid, 0) ^ -negateResult) + negateResult;
330         case M32_SECTOR_VAR_ID:
331             return (VM_AccessSector(0, index, memberid, 0) ^ -negateResult) + negateResult;
332         case M32_WALL_VAR_ID:
333             return (VM_AccessWall(0, index, memberid, 0) ^ -negateResult) + negateResult;
334         case M32_TSPRITE_VAR_ID:
335             return (VM_AccessTsprite(0, index, memberid, 0) ^ -negateResult) + negateResult;
336         default:
337             M32_ERROR("Gv_GetVarX(): WTF??");
338             return -1;
339         }
340     }
341     case M32_FLAG_VAR:
342     {
343         id &= (MAXGAMEVARS-1);
344 
345         switch (aGameVars[id].dwFlags & (GAMEVAR_USER_MASK|GAMEVAR_PTR_MASK))
346         {
347         case 0:
348             return (aGameVars[id].val.lValue ^ -negateResult) + negateResult;
349         case GAMEVAR_PERBLOCK:
350             return (aGameVars[id].val.plValues[vm.g_st] ^ -negateResult) + negateResult;
351         case GAMEVAR_FLOATPTR:
352         {
353             union { int32_t ival; float fval; };
354 
355             fval = *(float *)aGameVars[id].val.plValues;
356             if (negateResult)
357                 fval *= -1;
358             return ival;
359         }
360         case GAMEVAR_INTPTR:
361             return (*((int32_t *)aGameVars[id].val.lValue) ^ -negateResult) + negateResult;
362         case GAMEVAR_SHORTPTR:
363             return (*((int16_t *)aGameVars[id].val.lValue) ^ -negateResult) + negateResult;
364         case GAMEVAR_CHARPTR:
365             return (*((uint8_t *)aGameVars[id].val.lValue) ^ -negateResult) + negateResult;
366         default:
367             M32_ERROR("Gv_GetVarX(): WTF??");
368             return -1;
369         }
370     }
371     case M32_FLAG_LOCAL:
372     {
373         int32_t index = id&(MAXGAMEVARS-1);
374         // no bounds checking since it's done at script compilation time
375         return (((int32_t *)aGameArrays[M32_LOCAL_ARRAY_ID].vals)[index] ^ -negateResult) + negateResult;
376     }
377     }  // switch (id&M32_VARTYPE_MASK)
378 
379     return 0;  // never reached
380 }
381 
382 
Gv_SetVar(int32_t id,int32_t lValue)383 void __fastcall Gv_SetVar(int32_t id, int32_t lValue)
384 {
385     switch (id&M32_VARTYPE_MASK)
386     {
387     case M32_FLAG_ARRAY:
388     {
389         int32_t index;
390 
391         index = (id>>16)&0xffff;
392         if (!(id&M32_FLAG_CONSTANTINDEX))
393             index = Gv_GetVarN(index);
394 
395         id &= (MAXGAMEARRAYS-1);
396 
397         const int32_t siz = Gv_GetArraySize(id);
398         gamearray_t *const gar = &aGameArrays[id];
399 
400         if (index < 0 || index >= siz)
401         {
402             M32_ERROR("Gv_SetVarX(): invalid array index %s[%d], size=%d", gar->szLabel, index, siz);
403             return;
404         }
405 
406         // NOTE: GAMEARRAY_READONLY arrays can be modified in expert mode.
407         Bassert((gar->dwFlags & GAMEARRAY_STRIDE2) == 0);
408 
409         switch (gar->dwFlags & GAMEARRAY_TYPE_MASK)
410         {
411         case 0:
412         case GAMEARRAY_INT32:
413             ((int32_t *)gar->vals)[index] = lValue;
414             return;
415         case GAMEARRAY_INT16:
416             ((int16_t *)gar->vals)[index] = (int16_t)lValue;
417             return;
418         case GAMEARRAY_UINT8:
419             ((uint8_t *)gar->vals)[index] = (uint8_t)lValue;
420             return;
421         default:
422             M32_ERROR("Gv_SetVarX() (array): WTF??");
423             return;
424         }
425         return;
426     }
427     case M32_FLAG_STRUCT:
428     {
429         int32_t index, memberid;
430 
431         index = (id>>16)&0x7fff;
432         if (!(id&M32_FLAG_CONSTANTINDEX))
433             index = Gv_GetVarN(index);
434 
435         memberid = (id>>2)&63;
436 
437         switch (id&3)
438         {
439         case M32_SPRITE_VAR_ID:
440             VM_AccessSprite(1, index, memberid, lValue);
441             return;
442         case M32_SECTOR_VAR_ID:
443             VM_AccessSector(1, index, memberid, lValue);
444             return;
445         case M32_WALL_VAR_ID:
446             VM_AccessWall(1, index, memberid, lValue);
447             return;
448         case M32_TSPRITE_VAR_ID:
449             VM_AccessTsprite(1, index, memberid, lValue);
450             return;
451         default:
452             M32_ERROR("Gv_SetVarX(): WTF??");
453             return;
454         }
455     }
456     case M32_FLAG_VAR:
457     {
458         id &= (MAXGAMEVARS-1);
459 
460         switch (aGameVars[id].dwFlags & (GAMEVAR_USER_MASK|GAMEVAR_PTR_MASK))
461         {
462         case 0:
463             aGameVars[id].val.lValue=lValue;
464             return;
465         case GAMEVAR_PERBLOCK:
466             aGameVars[id].val.plValues[vm.g_st] = lValue;
467             return;
468         case GAMEVAR_FLOATPTR:
469         {
470             union { int32_t ival; float fval; };
471             ival = lValue;
472 
473             if (fval!=fval || fval<-3.4e38 || fval > 3.4e38)
474             {
475                 M32_ERROR("Gv_SetVarX(): tried to set float var to NaN or infinity");
476                 return;
477             }
478         }
479         fallthrough__;
480         case GAMEVAR_INTPTR:
481             *((int32_t *)aGameVars[id].val.lValue)=(int32_t)lValue;
482             return;
483         case GAMEVAR_SHORTPTR:
484             *((int16_t *)aGameVars[id].val.lValue)=(int16_t)lValue;
485             return;
486         case GAMEVAR_CHARPTR:
487             *((uint8_t *)aGameVars[id].val.lValue)=(uint8_t)lValue;
488             return;
489         default:
490             M32_ERROR("Gv_SetVarX(): WTF??");
491             return;
492         }
493     }
494     case M32_FLAG_LOCAL:
495     {
496         int32_t index = id&(MAXGAMEVARS-1);
497         ((int32_t *)aGameArrays[M32_LOCAL_ARRAY_ID].vals)[index] = lValue;
498         return;
499     }
500     }
501 }
502 
503 static uint8_t alphakeys[] =
504 {
505     KEYSC_SPACE,
506 
507     KEYSC_A, KEYSC_B, KEYSC_C, KEYSC_D, KEYSC_E, KEYSC_F, KEYSC_G, KEYSC_H,
508     KEYSC_I, KEYSC_J, KEYSC_K, KEYSC_L, KEYSC_M, KEYSC_N, KEYSC_O, KEYSC_P,
509     KEYSC_Q, KEYSC_R, KEYSC_S, KEYSC_T, KEYSC_U, KEYSC_V, KEYSC_W, KEYSC_X,
510     KEYSC_Y, KEYSC_Z,
511 };
512 
513 static uint8_t numberkeys[] =
514 {
515     KEYSC_0, KEYSC_1, KEYSC_2, KEYSC_3, KEYSC_4, KEYSC_5, KEYSC_6, KEYSC_7,
516     KEYSC_8, KEYSC_9,
517 };
518 
Gv_AddSystemVars(void)519 static void Gv_AddSystemVars(void)
520 {
521     // only call ONCE
522     int32_t hlcnt_id, hlscnt_id;
523 
524     // special vars for struct access
525     // MUST be at top and in this order!!!
526     Gv_NewVar("sprite", -1, GAMEVAR_READONLY | GAMEVAR_SYSTEM | GAMEVAR_SPECIAL);
527     Gv_NewVar("sector", -1, GAMEVAR_READONLY | GAMEVAR_SYSTEM | GAMEVAR_SPECIAL);
528     Gv_NewVar("wall", -1, GAMEVAR_READONLY | GAMEVAR_SYSTEM | GAMEVAR_SPECIAL);
529     Gv_NewVar("tsprite", -1, GAMEVAR_READONLY | GAMEVAR_SYSTEM | GAMEVAR_SPECIAL);
530     Gv_NewVar("light", -1, GAMEVAR_READONLY | GAMEVAR_SYSTEM | GAMEVAR_SPECIAL);
531 
532     // these too have to be in here and in order!
533     // keep in sync with m32script.h: IDs of special vars
534 
535     Gv_NewVar("I", 0, GAMEVAR_READONLY | GAMEVAR_SYSTEM);  // THISACTOR
536     Gv_NewVar("RETURN", (intptr_t)&g_iReturnVar, GAMEVAR_INTPTR | GAMEVAR_SYSTEM);
537     Gv_NewVar("LOTAG", 0, GAMEVAR_SYSTEM);
538     Gv_NewVar("HITAG", 0, GAMEVAR_SYSTEM);
539     Gv_NewVar("TEXTURE", 0, GAMEVAR_SYSTEM);
540     Gv_NewVar("DOSCRSHOT", (intptr_t)&g_doScreenShot, GAMEVAR_INTPTR | GAMEVAR_SYSTEM);
541 
542     Gv_NewVar("xdim",(intptr_t)&xdim, GAMEVAR_INTPTR | GAMEVAR_SYSTEM | GAMEVAR_READONLY);
543     Gv_NewVar("ydim",(intptr_t)&ydim, GAMEVAR_INTPTR | GAMEVAR_SYSTEM | GAMEVAR_READONLY);
544     Gv_NewVar("windowx1",(intptr_t)&windowxy1.x, GAMEVAR_INTPTR | GAMEVAR_SYSTEM | GAMEVAR_READONLY);
545     Gv_NewVar("windowx2",(intptr_t)&windowxy2.x, GAMEVAR_INTPTR | GAMEVAR_SYSTEM | GAMEVAR_READONLY);
546     Gv_NewVar("windowy1",(intptr_t)&windowxy1.y, GAMEVAR_INTPTR | GAMEVAR_SYSTEM | GAMEVAR_READONLY);
547     Gv_NewVar("windowy2",(intptr_t)&windowxy2.y, GAMEVAR_INTPTR | GAMEVAR_SYSTEM | GAMEVAR_READONLY);
548     Gv_NewVar("totalclock",(intptr_t)&totalclock, GAMEVAR_INTPTR | GAMEVAR_SYSTEM | GAMEVAR_READONLY);
549 
550     Gv_NewVar("viewingrange",(intptr_t)&viewingrange, GAMEVAR_SYSTEM | GAMEVAR_INTPTR | GAMEVAR_READONLY);
551     Gv_NewVar("yxaspect",(intptr_t)&yxaspect, GAMEVAR_SYSTEM | GAMEVAR_INTPTR | GAMEVAR_READONLY);
552 
553 ///    Gv_NewVar("framerate",(intptr_t)&g_frameRate, GAMEVAR_SYSTEM | GAMEVAR_INTPTR | GAMEVAR_READONLY);
554 ///    Gv_NewVar("display_mirror",(intptr_t)&display_mirror, GAMEVAR_SYSTEM | GAMEVAR_CHARPTR);
555 
556     Gv_NewVar("randomseed",(intptr_t)&randomseed, GAMEVAR_SYSTEM | GAMEVAR_INTPTR);
557 
558     Gv_NewVar("numwalls",(intptr_t)&numwalls, GAMEVAR_SYSTEM | GAMEVAR_SHORTPTR | GAMEVAR_READONLY);
559     Gv_NewVar("numsectors",(intptr_t)&numsectors, GAMEVAR_SYSTEM | GAMEVAR_SHORTPTR | GAMEVAR_READONLY);
560     Gv_NewVar("numsprites",(intptr_t)&Numsprites, GAMEVAR_SYSTEM | GAMEVAR_INTPTR | GAMEVAR_READONLY);
561     {
562         static int32_t numtiles;
563         Gv_NewVar("numtiles",(intptr_t)&numtiles, GAMEVAR_SYSTEM | GAMEVAR_INTPTR | GAMEVAR_READONLY);
564     }
565 #ifdef YAX_ENABLE
566     Gv_NewVar("numbunches",(intptr_t)&numyaxbunches, GAMEVAR_SYSTEM | GAMEVAR_INTPTR | GAMEVAR_READONLY);
567 #endif
568 
569 #ifdef USE_OPENGL
570     Gv_NewVar("rendmode",(intptr_t)&rendmode, GAMEVAR_READONLY | GAMEVAR_INTPTR | GAMEVAR_SYSTEM);
571 #endif
572 
573     // current position
574     Gv_NewVar("posx",(intptr_t)&pos.x, GAMEVAR_INTPTR | GAMEVAR_SYSTEM);
575     Gv_NewVar("posy",(intptr_t)&pos.y, GAMEVAR_INTPTR | GAMEVAR_SYSTEM);
576     Gv_NewVar("posz",(intptr_t)&pos.z, GAMEVAR_INTPTR | GAMEVAR_SYSTEM);
577     Gv_NewVar("ang",(intptr_t)&ang, GAMEVAR_SHORTPTR | GAMEVAR_SYSTEM);
578     Gv_NewVar("horiz",(intptr_t)&horiz, GAMEVAR_INTPTR | GAMEVAR_SYSTEM);
579     Gv_NewVar("cursectnum",(intptr_t)&cursectnum, GAMEVAR_READONLY | GAMEVAR_SHORTPTR | GAMEVAR_SYSTEM);
580     Gv_NewVar("hardcoded_movement",(intptr_t)&g_doHardcodedMovement, GAMEVAR_INTPTR | GAMEVAR_SYSTEM);
581 
582     Gv_NewVar("searchx",(intptr_t)&searchx, GAMEVAR_READONLY | GAMEVAR_INTPTR | GAMEVAR_SYSTEM);
583     Gv_NewVar("searchy",(intptr_t)&searchy, GAMEVAR_READONLY | GAMEVAR_INTPTR | GAMEVAR_SYSTEM);
584     Gv_NewVar("searchstat",(intptr_t)&searchstat, GAMEVAR_READONLY | GAMEVAR_SHORTPTR | GAMEVAR_SYSTEM);
585     Gv_NewVar("searchwall",(intptr_t)&searchwall, GAMEVAR_READONLY | GAMEVAR_SHORTPTR | GAMEVAR_SYSTEM);
586     Gv_NewVar("searchsector",(intptr_t)&searchsector, GAMEVAR_READONLY | GAMEVAR_SHORTPTR | GAMEVAR_SYSTEM);
587     Gv_NewVar("searchbottomwall",(intptr_t)&searchbottomwall, GAMEVAR_READONLY | GAMEVAR_SHORTPTR | GAMEVAR_SYSTEM);
588 
589     Gv_NewVar("pointhighlight",(intptr_t)&pointhighlight, GAMEVAR_SHORTPTR|GAMEVAR_SYSTEM|GAMEVAR_READONLY);
590     Gv_NewVar("linehighlight",(intptr_t)&linehighlight, GAMEVAR_SHORTPTR|GAMEVAR_SYSTEM|GAMEVAR_READONLY);
591 
592     hlcnt_id = g_gameVarCount;
593     Gv_NewVar("highlightcnt",(intptr_t)&highlightcnt, GAMEVAR_SHORTPTR|GAMEVAR_SYSTEM|GAMEVAR_READONLY);
594     hlscnt_id = g_gameVarCount;
595     Gv_NewVar("highlightsectorcnt",(intptr_t)&highlightsectorcnt, GAMEVAR_SHORTPTR|GAMEVAR_SYSTEM|GAMEVAR_READONLY);
596 
597     // clipboard contents
598     Gv_NewVar("temppicnum",(intptr_t)&temppicnum, GAMEVAR_INTPTR|GAMEVAR_SYSTEM|GAMEVAR_READONLY);
599     Gv_NewVar("tempcstat",(intptr_t)&tempcstat, GAMEVAR_INTPTR|GAMEVAR_SYSTEM|GAMEVAR_READONLY);
600     Gv_NewVar("templotag",(intptr_t)&templotag, GAMEVAR_INTPTR|GAMEVAR_SYSTEM|GAMEVAR_READONLY);
601     Gv_NewVar("temphitag",(intptr_t)&temphitag, GAMEVAR_INTPTR|GAMEVAR_SYSTEM|GAMEVAR_READONLY);
602     Gv_NewVar("tempextra",(intptr_t)&tempextra, GAMEVAR_INTPTR|GAMEVAR_SYSTEM|GAMEVAR_READONLY);
603     Gv_NewVar("tempshade",(intptr_t)&tempshade, GAMEVAR_INTPTR|GAMEVAR_SYSTEM|GAMEVAR_READONLY);
604     Gv_NewVar("temppal",(intptr_t)&temppal, GAMEVAR_INTPTR|GAMEVAR_SYSTEM|GAMEVAR_READONLY);
605     Gv_NewVar("tempvis",(intptr_t)&tempvis, GAMEVAR_INTPTR|GAMEVAR_SYSTEM|GAMEVAR_READONLY);
606     Gv_NewVar("tempxrepeat",(intptr_t)&tempxrepeat, GAMEVAR_INTPTR|GAMEVAR_SYSTEM|GAMEVAR_READONLY);
607     Gv_NewVar("tempyrepeat",(intptr_t)&tempyrepeat, GAMEVAR_INTPTR|GAMEVAR_SYSTEM|GAMEVAR_READONLY);
608 
609     // starting position
610     Gv_NewVar("startposx",(intptr_t)&startpos.x, GAMEVAR_READONLY | GAMEVAR_INTPTR | GAMEVAR_SYSTEM);
611     Gv_NewVar("startposy",(intptr_t)&startpos.y, GAMEVAR_READONLY | GAMEVAR_INTPTR | GAMEVAR_SYSTEM);
612     Gv_NewVar("startposz",(intptr_t)&startpos.z, GAMEVAR_READONLY | GAMEVAR_INTPTR | GAMEVAR_SYSTEM);
613     Gv_NewVar("startang",(intptr_t)&startang, GAMEVAR_READONLY | GAMEVAR_SHORTPTR | GAMEVAR_SYSTEM);
614     Gv_NewVar("startsectnum",(intptr_t)&startsectnum, GAMEVAR_READONLY | GAMEVAR_SHORTPTR | GAMEVAR_SYSTEM);
615 
616     Gv_NewVar("mousxplc",(intptr_t)&mousxplc, GAMEVAR_READONLY | GAMEVAR_INTPTR | GAMEVAR_SYSTEM);
617     Gv_NewVar("mousyplc",(intptr_t)&mousyplc, GAMEVAR_READONLY | GAMEVAR_INTPTR | GAMEVAR_SYSTEM);
618     Gv_NewVar("mousebits",(intptr_t)&g_mouseBits, GAMEVAR_INTPTR | GAMEVAR_SYSTEM);
619 
620     Gv_NewVar("zoom",(intptr_t)&zoom, GAMEVAR_READONLY | GAMEVAR_INTPTR | GAMEVAR_SYSTEM);
621     Gv_NewVar("drawlinepat",(intptr_t)&m32_drawlinepat, GAMEVAR_INTPTR | GAMEVAR_SYSTEM);
622     Gv_NewVar("halfxdim16", (intptr_t)&halfxdim16, GAMEVAR_READONLY | GAMEVAR_INTPTR | GAMEVAR_SYSTEM);
623     Gv_NewVar("midydim16", (intptr_t)&midydim16, GAMEVAR_READONLY | GAMEVAR_INTPTR | GAMEVAR_SYSTEM);
624     Gv_NewVar("ydim16",(intptr_t)&ydim16, GAMEVAR_INTPTR | GAMEVAR_SYSTEM | GAMEVAR_READONLY);
625     Gv_NewVar("m32_sideview",(intptr_t)&m32_sideview, GAMEVAR_INTPTR | GAMEVAR_SYSTEM | GAMEVAR_READONLY);
626 
627     Gv_NewVar("SV1",(intptr_t)&m32_sortvar1, GAMEVAR_INTPTR | GAMEVAR_SYSTEM | GAMEVAR_READONLY);
628     Gv_NewVar("SV2",(intptr_t)&m32_sortvar2, GAMEVAR_INTPTR | GAMEVAR_SYSTEM | GAMEVAR_READONLY);
629     Gv_NewVar("spritesortcnt",(intptr_t)&spritesortcnt, GAMEVAR_INTPTR | GAMEVAR_SYSTEM | GAMEVAR_READONLY);
630 
631 #ifdef POLYMER
632     Gv_NewVar("pr_overrideparallax",(intptr_t)&pr_overrideparallax, GAMEVAR_INTPTR | GAMEVAR_SYSTEM);
633     Gv_NewVar("pr_parallaxscale",(intptr_t)&pr_parallaxscale, GAMEVAR_FLOATPTR | GAMEVAR_SYSTEM);
634     Gv_NewVar("pr_parallaxbias",(intptr_t)&pr_parallaxbias, GAMEVAR_FLOATPTR | GAMEVAR_SYSTEM);
635     Gv_NewVar("pr_overridespecular",(intptr_t)&pr_overridespecular, GAMEVAR_INTPTR | GAMEVAR_SYSTEM);
636     Gv_NewVar("pr_specularpower",(intptr_t)&pr_specularpower, GAMEVAR_FLOATPTR | GAMEVAR_SYSTEM);
637     Gv_NewVar("pr_specularfactor",(intptr_t)&pr_specularfactor, GAMEVAR_FLOATPTR | GAMEVAR_SYSTEM);
638 #else
639     {
640         // dummy Polymer variables for non-Polymer builds
641         static int32_t pr_overrideparallax = 0;
642         static float pr_parallaxscale = 0.1f;
643         static float pr_parallaxbias = 0.0f;
644         static int32_t pr_overridespecular = 0;
645         static float pr_specularpower = 15.0f;
646         static float pr_specularfactor = 1.0f;
647 
648         Gv_NewVar("pr_overrideparallax",(intptr_t)&pr_overrideparallax, GAMEVAR_INTPTR | GAMEVAR_SYSTEM);
649         Gv_NewVar("pr_parallaxscale",(intptr_t)&pr_parallaxscale, GAMEVAR_FLOATPTR | GAMEVAR_SYSTEM);
650         Gv_NewVar("pr_parallaxbias",(intptr_t)&pr_parallaxbias, GAMEVAR_FLOATPTR | GAMEVAR_SYSTEM);
651         Gv_NewVar("pr_overridespecular",(intptr_t)&pr_overridespecular, GAMEVAR_INTPTR | GAMEVAR_SYSTEM);
652         Gv_NewVar("pr_specularpower",(intptr_t)&pr_specularpower, GAMEVAR_FLOATPTR | GAMEVAR_SYSTEM);
653         Gv_NewVar("pr_specularfactor",(intptr_t)&pr_specularfactor, GAMEVAR_FLOATPTR | GAMEVAR_SYSTEM);
654     }
655 #endif
656 
657     g_systemVarCount = g_gameVarCount;
658 
659     // must be first!
660     Gv_NewArray(".LOCALS_BASE", NULL, 0, GAMEARRAY_INT32);
661 
662     Gv_NewArray("highlight", (void *)highlight, hlcnt_id,
663                 GAMEARRAY_READONLY|GAMEARRAY_INT16|GAMEARRAY_VARSIZE);
664     Gv_NewArray("highlightsector", (void *)highlightsector, hlscnt_id,
665                 GAMEARRAY_READONLY|GAMEARRAY_INT16|GAMEARRAY_VARSIZE);
666 
667     Gv_NewArray("hsect", (void *)headspritesect, MAXSECTORS+1, GAMEARRAY_READONLY|GAMEARRAY_INT16);
668     Gv_NewArray("psect", (void *)prevspritesect, MAXSPRITES, GAMEARRAY_READONLY|GAMEARRAY_INT16);
669     Gv_NewArray("nsect", (void *)nextspritesect, MAXSPRITES, GAMEARRAY_READONLY|GAMEARRAY_INT16);
670     Gv_NewArray("hstat", (void *)headspritestat, MAXSTATUS+1, GAMEARRAY_READONLY|GAMEARRAY_INT16);
671     Gv_NewArray("pstat", (void *)prevspritestat, MAXSPRITES, GAMEARRAY_READONLY|GAMEARRAY_INT16);
672     Gv_NewArray("nstat", (void *)nextspritestat, MAXSPRITES, GAMEARRAY_READONLY|GAMEARRAY_INT16);
673 #ifdef YAX_ENABLE
674     Gv_NewArray("headsectbunchc", (void *)headsectbunch[0], YAX_MAXBUNCHES, GAMEARRAY_READONLY|GAMEARRAY_INT16);
675     Gv_NewArray("nextsectbunchc", (void *)nextsectbunch[0], MAXSECTORS, GAMEARRAY_READONLY|GAMEARRAY_INT16);
676     Gv_NewArray("headsectbunchf", (void *)headsectbunch[1], YAX_MAXBUNCHES, GAMEARRAY_READONLY|GAMEARRAY_INT16);
677     Gv_NewArray("nextsectbunchf", (void *)nextsectbunch[1], MAXSECTORS, GAMEARRAY_READONLY|GAMEARRAY_INT16);
678 #endif
679     Gv_NewArray("editorcolors", (void *)editorcolors, 256, GAMEARRAY_READONLY|GAMEARRAY_UINT8);
680     Gv_NewArray("tilesizx", (void *)&tilesiz[0].x, MAXTILES, GAMEARRAY_STRIDE2|GAMEARRAY_READONLY|GAMEARRAY_INT16);
681     Gv_NewArray("tilesizy", (void *)&tilesiz[0].y, MAXTILES, GAMEARRAY_STRIDE2|GAMEARRAY_READONLY|GAMEARRAY_INT16);
682 //    Gv_NewArray("picsiz", (void *)picsiz, MAXTILES, GAMEARRAY_READONLY|GAMEARRAY_OFCHAR);
683     Gv_NewArray("picanm", (void *)picanm, MAXTILES, GAMEARRAY_READONLY|GAMEARRAY_INT32);
684 
685     Gv_NewArray("show2dsector", (void *)show2dsector, (MAXSECTORS+7)>>3, GAMEARRAY_READONLY|GAMEARRAY_UINT8);
686     Gv_NewArray("show2dwall", (void *)show2dwall, (MAXWALLS+7)>>3, GAMEARRAY_READONLY|GAMEARRAY_UINT8);
687     Gv_NewArray("show2dsprite", (void *)show2dsprite, (MAXSPRITES+7)>>3, GAMEARRAY_READONLY|GAMEARRAY_UINT8);
688 
689     Gv_NewArray("keystatus", (void *)keystatus, 256, GAMEARRAY_WARN|GAMEARRAY_UINT8);
690     Gv_NewArray("alphakeys", (void *)alphakeys, sizeof(alphakeys), GAMEARRAY_READONLY|GAMEARRAY_UINT8);
691     Gv_NewArray("numberkeys", (void *)numberkeys, sizeof(numberkeys), GAMEARRAY_READONLY|GAMEARRAY_UINT8);
692 
693     g_systemArrayCount = g_gameArrayCount;
694 }
695 
Gv_Init(void)696 void Gv_Init(void)
697 {
698     // only call ONCE
699 
700     Gv_Clear();
701     Gv_AddSystemVars();
702 }
703