A bunch of m32script additions, fixes and general stuff, among them: local vars/arrays, inline quotes and prettier error messages.

git-svn-id: https://svn.eduke32.com/eduke32@1691 1a8010ca-5511-0410-912e-c29ae57300e0
This commit is contained in:
helixhorned 2010-08-11 22:37:45 +00:00
parent a2d2f0ed75
commit 71e59a5502
12 changed files with 1395 additions and 957 deletions

View file

@ -62,6 +62,8 @@ extern char *mapster32_fullpath;
extern char *testplay_addparam; extern char *testplay_addparam;
extern int32_t m32_osd_tryscript; extern int32_t m32_osd_tryscript;
extern int32_t showheightindicators;
extern int32_t showambiencesounds;
extern int32_t ExtInit(void); extern int32_t ExtInit(void);
extern int32_t ExtPreInit(int32_t argc,const char **argv); extern int32_t ExtPreInit(int32_t argc,const char **argv);

View file

@ -34,8 +34,8 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
#define MAXQUOTELEN 128 #define MAXQUOTELEN 128
// Some misc #defines // Some misc #defines
#define NO 0 //#define NO 0
#define YES 1 //#define YES 1
typedef int32_t instype; typedef int32_t instype;
typedef int32_t ofstype; typedef int32_t ofstype;
@ -59,7 +59,7 @@ extern void Gv_Init(void);
extern int32_t __fastcall Gv_GetVarX(register int32_t id); extern int32_t __fastcall Gv_GetVarX(register int32_t id);
extern void __fastcall Gv_SetVarX(register int32_t id, register int32_t lValue); extern void __fastcall Gv_SetVarX(register int32_t id, register int32_t lValue);
extern int32_t __fastcall Gv_GetVarN(register int32_t id); // 'N' for "no side-effects"... vars only! extern int32_t __fastcall Gv_GetVarN(register int32_t id); // 'N' for "no side-effects"... vars and locals only!
extern void SetGAMEPalette(void); extern void SetGAMEPalette(void);
extern void SetWATERPalette(void); extern void SetWATERPalette(void);
@ -101,6 +101,7 @@ enum GameEvent_t {
extern ofstype aEventOffsets[MAXEVENTS]; extern ofstype aEventOffsets[MAXEVENTS];
extern int32_t aEventSizes[MAXEVENTS]; extern int32_t aEventSizes[MAXEVENTS];
extern uint8_t aEventEnabled[MAXEVENTS]; extern uint8_t aEventEnabled[MAXEVENTS];
extern uint16_t aEventNumLocals[MAXEVENTS];
enum GamevarFlags_t { enum GamevarFlags_t {
@ -109,18 +110,20 @@ enum GamevarFlags_t {
MAXVARLABEL = MAXLABELLEN, //26, MAXVARLABEL = MAXLABELLEN, //26,
GAMEVAR_PERBLOCK = 0x00000001, // per-block (state, event, or top-level) variable GAMEVAR_PERBLOCK = 0x00000001, // per-block (state, event, or top-level) variable
GAMEVAR_USER_MASK = (0x00000001), GAMEVAR_USER_MASK = GAMEVAR_PERBLOCK,
GAMEVAR_RESET = 0x00000008, // marks var for to default GAMEVAR_RESET = 0x00000008, // marks var for to default
GAMEVAR_DEFAULT = 0x00000100, // allow override GAMEVAR_DEFAULT = 0x00000100, // allow override
GAMEVAR_SECRET = 0x00000200, // don't dump...
GAMEVAR_SYSTEM = 0x00000800, // cannot change mode flags...(only default value) GAMEVAR_SYSTEM = 0x00000800, // cannot change mode flags...(only default value)
GAMEVAR_READONLY = 0x00001000, // values are read-only (no setvar allowed) GAMEVAR_READONLY = 0x00001000, // values are read-only (no setvar allowed)
GAMEVAR_INTPTR = 0x00002000, // plValues is a pointer to an int32_t GAMEVAR_INTPTR = 0x00002000, // plValues is a pointer to an int32_t
GAMEVAR_FLOATPTR = 0x00004000, // plValues is a pointer to a float GAMEVAR_FLOATPTR = 0x00004000, // plValues is a pointer to a float
GAMEVAR_SHORTPTR = 0x00008000, // plValues is a pointer to a short GAMEVAR_SHORTPTR = 0x00008000, // plValues is a pointer to a short
GAMEVAR_CHARPTR = 0x00010000, // plValues is a pointer to a char GAMEVAR_CHARPTR = 0x00010000, // plValues is a pointer to a char
GAMEVAR_PTR_MASK = GAMEVAR_INTPTR|GAMEVAR_FLOATPTR|GAMEVAR_SHORTPTR|GAMEVAR_CHARPTR,
// GAMEVAR_NORESET = 0x00020000, // var values are not reset when restoring map state // GAMEVAR_NORESET = 0x00020000, // var values are not reset when restoring map state
GAMEVAR_SPECIAL = 0x00040000, // flag for structure member shortcut vars GAMEVAR_SPECIAL = 0x00040000, // flag for structure member shortcut vars
}; };
@ -128,13 +131,14 @@ enum GamevarFlags_t {
enum GamearrayFlags_t { enum GamearrayFlags_t {
MAXGAMEARRAYS = (MAXGAMEVARS>>2), // must be lower than MAXGAMEVARS MAXGAMEARRAYS = (MAXGAMEVARS>>2), // must be lower than MAXGAMEVARS
MAXARRAYLABEL = MAXVARLABEL, MAXARRAYLABEL = MAXVARLABEL,
GAMEARRAY_NORMAL = 0,
GAMEARRAY_READONLY = 0x00001000, GAMEARRAY_READONLY = 0x00001000,
GAMEARRAY_NORMAL = 0,
GAMEARRAY_OFCHAR = 0x00000001, GAMEARRAY_OFCHAR = 0x00000001,
GAMEARRAY_OFSHORT = 0x00000002, GAMEARRAY_OFSHORT = 0x00000002,
GAMEARRAY_OFINT = 0x00000004, GAMEARRAY_OFINT = 0x00000004,
GAMEARRAY_TYPEMASK = 0x00000007, GAMEARRAY_TYPE_MASK = GAMEARRAY_OFCHAR|GAMEARRAY_OFSHORT|GAMEARRAY_OFINT,
GAMEARRAY_VARSIZE = 0x00000020, GAMEARRAY_VARSIZE = 0x00000020,
@ -169,6 +173,7 @@ extern uint32_t m32_drawlinepat;
extern int32_t g_iReturnVar; extern int32_t g_iReturnVar;
extern int32_t m32_sortvar1, m32_sortvar2; extern int32_t m32_sortvar1, m32_sortvar2;
extern int32_t m32_script_expertmode; // if true, make read-only vars writable
//extern int32_t g_numRealPalettes; //extern int32_t g_numRealPalettes;
//extern int32_t g_scriptDebug; //extern int32_t g_scriptDebug;
@ -228,9 +233,31 @@ extern int32_t zoom;
extern int32_t halfxdim16, midydim16; extern int32_t halfxdim16, midydim16;
// gamevar bytecode format:
// FEDC|BA09|8765|4321|FEDC|BA09|8765|4321
// | .. .... .... gamevar ID
// | . constant bit (checked first) / get-payload-var bit for array or struct
// | . negate bit
// | . array bit \___\ if both set:
// | . struct bit / / local var
// .... .... .... ....| optional payload
#define M32_FLAG_CONSTANT (MAXGAMEVARS)
#define M32_FLAG_NEGATE (MAXGAMEVARS<<1) #define M32_FLAG_NEGATE (MAXGAMEVARS<<1)
#define M32_FLAG_VAR (0)
#define M32_FLAG_ARRAY (MAXGAMEVARS<<2) #define M32_FLAG_ARRAY (MAXGAMEVARS<<2)
#define M32_FLAG_SPECIAL (MAXGAMEVARS<<3) #define M32_FLAG_STRUCT (MAXGAMEVARS<<3)
#define M32_FLAG_LOCAL (M32_FLAG_ARRAY|M32_FLAG_STRUCT)
#define M32_VARTYPE_MASK (M32_FLAG_ARRAY|M32_FLAG_STRUCT)
#define M32_FLAG_CONSTANTINDEX M32_FLAG_CONSTANT
// if set, fetch index for array or struct array from 16 high bits as a constant (otherwise: gamevar)
#define M32_BITS_MASK (0x0000ffff-(MAXGAMEVARS-1))
// IDs of special vars // IDs of special vars
#define M32_SPRITE_VAR_ID 0 #define M32_SPRITE_VAR_ID 0
@ -244,6 +271,8 @@ extern int32_t halfxdim16, midydim16;
#define M32_HITAG_VAR_ID 7 #define M32_HITAG_VAR_ID 7
#define M32_TEXTURE_VAR_ID 8 #define M32_TEXTURE_VAR_ID 8
#define M32_LOCAL_ARRAY_ID 0
#define M32_PRINTERROR(Text, ...) OSD_Printf(OSD_ERROR "Line %d, %s: " Text "\n", g_errorLineNum, keyw[g_tw], ## __VA_ARGS__) #define M32_PRINTERROR(Text, ...) OSD_Printf(OSD_ERROR "Line %d, %s: " Text "\n", g_errorLineNum, keyw[g_tw], ## __VA_ARGS__)
#endif #endif

View file

@ -486,8 +486,6 @@ int32_t app_main(int32_t argc, const char **argv)
totalclock = 0; totalclock = 0;
OSD_Exec("m32_autoexec.cfg");
updatesector(pos.x,pos.y,&cursectnum); updatesector(pos.x,pos.y,&cursectnum);
if (cursectnum == -1) if (cursectnum == -1)
@ -507,6 +505,10 @@ int32_t app_main(int32_t argc, const char **argv)
Bprintf("%d * %d not supported in this graphics mode\n",xdim2d,ydim2d); Bprintf("%d * %d not supported in this graphics mode\n",xdim2d,ydim2d);
exit(0); exit(0);
} }
// executed once per init, but after setgamemode so that OSD has the right width
OSD_Exec("m32_autoexec.cfg");
overheadeditor(); overheadeditor();
keystatus[buildkeys[BK_MODE2D_3D]] = 0; keystatus[buildkeys[BK_MODE2D_3D]] = 0;
@ -527,6 +529,10 @@ int32_t app_main(int32_t argc, const char **argv)
Bprintf("%d * %d not supported in this graphics mode\n",xdim,ydim); Bprintf("%d * %d not supported in this graphics mode\n",xdim,ydim);
exit(0); exit(0);
} }
// executed once per init, but after setgamemode so that OSD has the right width
OSD_Exec("m32_autoexec.cfg");
setbrightness(GAMMA_CALC,palette,0); setbrightness(GAMMA_CALC,palette,0);
} }
CANCEL: CANCEL:
@ -2463,13 +2469,8 @@ void overheadeditor(void)
for (i=0; i<numwalls; i++) //make new red lines? for (i=0; i<numwalls; i++) //make new red lines?
{ {
if (wall[i].x == dax && wall[i].y == day) if ((wall[i].x == dax && wall[i].y == day)
{ || (POINT2(i).x == dax && POINT2(i).y == day))
checksectorpointer((int16_t)i,sectorofwall((int16_t)i));
fixrepeats((int16_t)i);
asksave = 1;
}
else if (POINT2(i).x == dax && POINT2(i).y == day)
{ {
checksectorpointer((int16_t)i,sectorofwall((int16_t)i)); checksectorpointer((int16_t)i,sectorofwall((int16_t)i));
fixrepeats((int16_t)i); fixrepeats((int16_t)i);

View file

@ -66,7 +66,6 @@ extern int32_t remapinit;
extern double msens; extern double msens;
extern int32_t editorgridextent, grid, autogrid; extern int32_t editorgridextent, grid, autogrid;
static int32_t default_grid=3; static int32_t default_grid=3;
extern int32_t showheightindicators;
extern int32_t graphicsmode; extern int32_t graphicsmode;
extern int32_t AmbienceToggle; extern int32_t AmbienceToggle;
extern int32_t ParentalLock; extern int32_t ParentalLock;
@ -236,6 +235,8 @@ int32_t loadsetup(const char *fn)
if (readconfig(fp, "showheightindicators", val, VL) > 0) if (readconfig(fp, "showheightindicators", val, VL) > 0)
showheightindicators = min(max(Batoi(val),0),2); showheightindicators = min(max(Batoi(val),0),2);
if (readconfig(fp, "showambiencesounds", val, VL) > 0)
showheightindicators = min(max(Batoi(val),0),2);
if (readconfig(fp, "graphicsmode", val, VL) > 0) if (readconfig(fp, "graphicsmode", val, VL) > 0)
graphicsmode = min(max(Batoi(val),0),2); graphicsmode = min(max(Batoi(val),0),2);
@ -417,6 +418,9 @@ int32_t writesetup(const char *fn)
"; Height indicators (0:none, 1:only 2-sided&different, 2:all)\n" "; Height indicators (0:none, 1:only 2-sided&different, 2:all)\n"
"showheightindicators = %d\n" "showheightindicators = %d\n"
"\n" "\n"
"; Ambience sound circles (0:none, 1:only in current sector, 2:all)\n"
"showambiencesounds = %d\n"
"\n"
"; 2D mode display type (0:classic, 1:textured, 2:textured/animated)\n" "; 2D mode display type (0:classic, 1:textured, 2:textured/animated)\n"
"graphicsmode = %d\n\n" "graphicsmode = %d\n\n"
"; Ambient sounds in 3D mode (0:off, 1:on)\n" "; Ambient sounds in 3D mode (0:off, 1:on)\n"
@ -499,7 +503,7 @@ int32_t writesetup(const char *fn)
#endif #endif
option[3], msens, unrealedlook, pk_uedaccel, quickmapcycling, option[3], msens, unrealedlook, pk_uedaccel, quickmapcycling,
revertCTRL,scrollamount,pk_turnaccel,pk_turndecel,autosave, revertCTRL,scrollamount,pk_turnaccel,pk_turndecel,autosave,
showheightindicators,graphicsmode,AmbienceToggle,ParentalLock, showheightindicators,showambiencesounds,graphicsmode,AmbienceToggle,ParentalLock,
!!m32_osd_tryscript, !!m32_osd_tryscript,
#if 1 #if 1
keys[0], keys[1], keys[2], keys[3], keys[4], keys[5], keys[0], keys[1], keys[2], keys[3], keys[4], keys[5],

View file

@ -4,7 +4,6 @@
include names.h include names.h
// flag 1: per-block (top-level, event, or state) variable // flag 1: per-block (top-level, event, or state) variable
gamevar h 0 1
gamevar i 0 1 gamevar i 0 1
gamevar j 0 1 gamevar j 0 1
gamevar k 0 1 gamevar k 0 1
@ -14,17 +13,9 @@ gamevar p 0 1
gamevar q 0 1 gamevar q 0 1
gamevar r 0 1 gamevar r 0 1
gamearray xx 10
gamearray yy 10
gamevar c 0 0
gamevar d 0 0
gamevar x 0 0 gamevar x 0 0
gamevar y 0 0 gamevar y 0 0
gamevar x2 0 0
gamevar y2 0 0
gamevar z 0 0 gamevar z 0 0
gamevar frac 0 0
gamevar gi 0 0 gamevar gi 0 0
gamevar gj 0 0 gamevar gj 0 0
@ -45,37 +36,16 @@ gamevar dayx 65536 0
gamevar drawcol 9 0 gamevar drawcol 9 0
define TQUOTE 3
definequote 0 OK define TQUOTE 0
definequote 1 DAMN definequote TQUOTE >>> write on me! <<<
definequote 2 BU:%d ABS:%d //light
definequote TQUOTE write on me! define LIGHTQUOTE 1
// x y z r g b mins maxs
definequote 4 ASPECT: VR=%d, YX=%d definequote LIGHTQUOTE light %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d
definequote 5 ALPHA KEY: %d (SCANCODE: %d)
definequote 6 time: %d ms
definequote 7 door sector not an island sector!
definequote 8 door sector has no SE sprite!
//light x y z r g b mins maxs
definequote 9 light %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d
// sec range radius fade ang horiz prio tile // sec range radius fade ang horiz prio tile
definequote 10 --PRLIGHTS--
definequote 11 --ENDPRLIGHTS--
definequote 12 RED:
definequote 13 GREEN:
definequote 14 BLUE:
definequote 15 x/yoffset: %d %d
definequote 16 RGB color: %d %d %d
definequote 17 PICNUM:
definequote 18 NUMBER KEY: %d (SCANCODE: %d)
// Corruption checker // Corruption checker
definequote 19 PANIC!!! SECTOR OR WALL LIMIT EXCEEDED!!! definequote 19 PANIC!!! SECTOR OR WALL LIMIT EXCEEDED!!!
@ -86,66 +56,18 @@ definequote 23 WALL[%d].POINT2=%d out of range: sector[%d].wallptr=%d, endwall=%
definequote 24 WALL[%d].NEXTWALL=%d out of range: numwalls=%d!!! definequote 24 WALL[%d].NEXTWALL=%d out of range: numwalls=%d!!!
definequote 25 WALL[%d].NEXTSECTOR=%d out of range: numsectors=%d!!! definequote 25 WALL[%d].NEXTSECTOR=%d out of range: numsectors=%d!!!
definequote 26 FLOAT ACCESS TEST
definequote 27 OVERRIDE POLYMER PARALLAX & SPECULAR: OFF definequote 27 OVERRIDE POLYMER PARALLAX & SPECULAR: OFF
definequote 28 OVERRIDE POLYMER PARALLAX & SPECULAR: ON definequote 28 OVERRIDE POLYMER PARALLAX & SPECULAR: ON
definequote 29 PARALLAX SCALE: %f
definequote 30 PARALLAX BIAS: %f
definequote 31 SPECULAR FACTOR: %f
definequote 32 SPECULAR POWER: %f
definequote 33 PAL: %d
define PRSCALE 1000 define PRSCALE 1000
// NOTE: inline constants >=32768 are sometimes broken ATM (when loading a second time?).
// This should always work
define MAXSPECULAR 100000 define MAXSPECULAR 100000
gamearray ar 128 gamearray ar 128
gamearray parm 8 gamearray parm 8
// various tests of m32-script features
defstate tests
// array test
getarraysize ar tmp
resizearray ar 65536
getticks parm[2]
for j range 65536
set ar[j] j
set i 0
for j range 65536
add i ar[j]
getticks parm[3]
resizearray ar tmp
ife i 2147450880 quote 0 else quote 1
sub parm[3] parm[2]
qsprintf TQUOTE 6 parm[3]
quote TQUOTE
// iteration and break test
for i range 10
{
addlogvar i
ife i 5 break
}
ife i 5 quote 0 else quote 1
quote 26
set tmp pr_parallaxscale
set gi tmp set gj tmp set gk tmp
al gi al gj al gk
ftoi gi 20 ftoi gj 200 ftoi gk 2000
al gi al gj al gk
mul gk 2
itof gk 2000
ends
// prints out maphack light definitions based on SE lights in map // prints out maphack light definitions based on SE lights in map
defstate printlights defstate printlights
print 10 print "--PRLIGHTS--"
for i allsprites, ifactor SECTOREFFECTOR, ifge .lotag 49, ifle .lotag 50 for i allsprites, ifactor SECTOREFFECTOR, ifge .lotag 49, ifle .lotag 50
{ {
ife .lotag 50 ife .lotag 50
@ -167,12 +89,12 @@ defstate printlights
set l 2 set l 2
} }
// range r g b // range r g b
qsprintf TQUOTE 9 .sectnum .x .y .z .hitag .xvel .yvel .zvel qsprintf TQUOTE LIGHTQUOTE .sectnum .x .y .z .hitag .xvel .yvel .zvel
j k .ang .extra .xoffset .yoffset l .owner j k .ang .extra .xoffset .yoffset l .owner
// radius fade horiz minshade maxshade prio tile // radius fade horiz minshade maxshade prio tile
print TQUOTE print TQUOTE
} }
print 11 print "--ENDPRLIGHTS--"
ends ends
// convenient polymer SE light manipulation with keypad keys // convenient polymer SE light manipulation with keypad keys
@ -245,7 +167,7 @@ defstate fiddlewithlights
ftoi k PRSCALE // must convert to scaled integer, scale is 1:PRSCALE ftoi k PRSCALE // must convert to scaled integer, scale is 1:PRSCALE
add k j, clamp k -10000 10000 add k j, clamp k -10000 10000
itof k PRSCALE // convert back itof k PRSCALE // convert back
qsprintf TQUOTE 29 k, quote TQUOTE qsprintf TQUOTE "PARALLAX SCALE: %f" k, quote TQUOTE
set pr_parallaxscale k set pr_parallaxscale k
break; break;
} }
@ -253,23 +175,23 @@ defstate fiddlewithlights
{ {
set k pr_parallaxbias set k pr_parallaxbias
ftoi k PRSCALE, add k j, clamp k -10000 10000, itof k PRSCALE ftoi k PRSCALE, add k j, clamp k -10000 10000, itof k PRSCALE
qsprintf TQUOTE 30 k, quote TQUOTE qsprintf TQUOTE "PARALLAX BIAS: %f" k, quote TQUOTE
set pr_parallaxbias k set pr_parallaxbias k
break; break;
} }
case 3: case 3:
{ {
set k pr_specularfactor set k pr_specularfactor
ftoi k PRSCALE, add k j, clamp k -10000 MAXSPECULAR, itof k PRSCALE ftoi k PRSCALE, add k j, clamp k 0 MAXSPECULAR, itof k PRSCALE
qsprintf TQUOTE 31 k, quote TQUOTE qsprintf TQUOTE "SPECULAR FACTOR: %f" k, quote TQUOTE
set pr_specularfactor k set pr_specularfactor k
break; break;
} }
case 4: case 4:
{ {
set k pr_specularpower set k pr_specularpower
ftoi k PRSCALE, add k j, clamp k -10000 MAXSPECULAR, itof k PRSCALE ftoi k PRSCALE, add k j, clamp k 0 MAXSPECULAR, itof k PRSCALE
qsprintf TQUOTE 32 k, quote TQUOTE qsprintf TQUOTE "SPECULAR POWER: %f" k, quote TQUOTE
set pr_specularpower k set pr_specularpower k
break; break;
} }
@ -282,6 +204,8 @@ defstate fiddlewithlights
{ {
set i searchwall, seti i // set current sprite = targeted sprite set i searchwall, seti i // set current sprite = targeted sprite
ife .lotag 50
{
// horiz // horiz
ifeithershift set j 1 else set j 10 ifeithershift set j 1 else set j 10
ifhitkey KEY_gUP add .extra j ifhitkey KEY_gUP add .extra j
@ -295,14 +219,6 @@ defstate fiddlewithlights
ifhitkey KEY_gLEFT sub .ang j ifhitkey KEY_gLEFT sub .ang j
else ifhitkey KEY_gRIGHT add .ang j else ifhitkey KEY_gRIGHT add .ang j
// range
ifeithershift set j 10
else ifeitherctrl set j 1000
else set j 100
ifhitkey KEY_gPGUP add .hitag j
else ifhitkey KEY_gHOME sub .hitag j
clamp .hitag 0 16000
// radius // radius
ifeitherctrl ifeitherctrl
{ {
@ -311,6 +227,15 @@ defstate fiddlewithlights
clamp .shade -118 117 clamp .shade -118 117
} }
}
// range
ifeithershift set j 10
else ifeitherctrl set j 1000
else set j 100
ifhitkey KEY_KP9 add .hitag j
else ifhitkey KEY_KP7 sub .hitag j
clamp .hitag 0 16000
// min/max shade // min/max shade
ifeithershift set j -1 else set j 1 ifeithershift set j -1 else set j 1
@ -330,7 +255,7 @@ defstate fiddlewithlights
ife k 1 ife k 1
{ {
qsprintf TQUOTE 15 .xoffset .yoffset qsprintf TQUOTE "XY offset: %d %d" .xoffset .yoffset
quote TQUOTE quote TQUOTE
} }
} }
@ -338,15 +263,15 @@ defstate fiddlewithlights
// color/picnum // color/picnum
ifeitheralt ifeitheralt
{ {
ifhitkey KEY_gEND ifhitkey KEY_KP1
{ {
getnumber256 .xvel 12 255 getnumber256 .xvel "RED:" 255
getnumber256 .yvel 13 255 getnumber256 .yvel "GREEN:" 255
getnumber256 .zvel 14 255 getnumber256 .zvel "BLUE:" 255
} }
else ifhitkey KEY_gDOWN else ifhitkey KEY_KP2
{ {
getnumber256 .owner 17 -MAXTILES getnumber256 .owner "PICNUM:" -MAXTILES
} }
} }
else else
@ -355,9 +280,9 @@ defstate fiddlewithlights
ifeithershift inv j ifeithershift inv j
set k 0 set k 0
ifhitkey KEY_gEND { add .xvel j, set k 1 } ifhitkey KEY_KP1 { add .xvel j, set k 1 }
ifhitkey KEY_gDOWN { add .yvel j, set k 1 } ifhitkey KEY_KP2 { add .yvel j, set k 1 }
ifhitkey KEY_gPGDN { add .zvel j, set k 1 } ifhitkey KEY_KP3 { add .zvel j, set k 1 }
ife k 1 ife k 1
{ {
@ -365,35 +290,13 @@ defstate fiddlewithlights
clamp .yvel 1 255 clamp .yvel 1 255
clamp .zvel 1 255 clamp .zvel 1 255
qsprintf TQUOTE 16 .xvel .yvel .zvel qsprintf TQUOTE "RGB color: %d %d %d" .xvel .yvel .zvel
quote TQUOTE quote TQUOTE
} }
} }
} }
ends ends
/*
defstate testkeyavail
for i range 27
{
ifholdkey alphakeys[i]
{
qsprintf TQUOTE 5 i alphakeys[i]
quote TQUOTE
}
}
for i range 10
{
ifholdkey numberkeys[i]
{
qsprintf TQUOTE 18 i numberkeys[i]
quote TQUOTE
}
}
ends
*/
// rotate highlighted sprites around selected (closest to mouse) sprite // rotate highlighted sprites around selected (closest to mouse) sprite
// global parameter: dang // global parameter: dang
defstate rotselspr defstate rotselspr
@ -488,7 +391,12 @@ onevent EVENT_DRAW2DSCREEN
*/ */
////////// polymer light 2d projections ////////// ////////// polymer light 2d projections //////////
set tmp drawlinepat var c d h x2 y2 oldpat
array xx 2
array yy 2
set oldpat drawlinepat
set drawlinepat 0x11111111 set drawlinepat 0x11111111
for i spritesofsector cursectnum for i spritesofsector cursectnum
{ {
@ -548,7 +456,7 @@ onevent EVENT_DRAW2DSCREEN
} }
} }
} }
set drawlinepat tmp set drawlinepat oldpat
endevent endevent
// LOCATORS auto-incrementer // LOCATORS auto-incrementer
@ -727,25 +635,6 @@ ends
onevent EVENT_ANALYZESPRITES onevent EVENT_ANALYZESPRITES
state tduprot state tduprot
state tduplin state tduplin
/*
ife searchstat 3
for i drawnsprites
{
ife tsprite[i].owner searchwall
{
qsprintf TQUOTE 33 tsprite[i].pal
quote TQUOTE
break
}
// switch sprite[j].picnum
// case LIZTROOP spritepal 1 break
// case PIGCOP spritepal 2 break
// case BOSS1 spritepal 6 break
// endswitch
}
*/
endevent endevent
onevent EVENT_KEYS3D onevent EVENT_KEYS3D
@ -790,7 +679,7 @@ onevent EVENT_KEYS3D
// } // }
ifn tmp 0 ifn tmp 0
{ {
quote 7 quote "door sector not an island sector!"
return return
} }
@ -805,7 +694,7 @@ onevent EVENT_KEYS3D
} }
ifl l 0 ifl l 0
{ {
quote 8 quote "door sector has no SE sprite!"
return return
} }
@ -868,7 +757,7 @@ onevent EVENT_KEYS3D
ifl davr 32768 set davr 32768 ifl davr 32768 set davr 32768
ifg davr 256000 set davr 256000 ifg davr 256000 set davr 256000
setaspect davr yxaspect setaspect davr yxaspect
qsprintf TQUOTE 4 davr yxaspect qsprintf TQUOTE "ASPECT: VR=%d, YX=%d" davr yxaspect
quote TQUOTE quote TQUOTE
} }
endevent endevent
@ -917,10 +806,10 @@ ends
// Map corruption checker // Map corruption checker
gamevar ewall 0 0
gamevar endwall 0 0
defstate corruptchk defstate corruptchk
var ewall
var endwall
ifle numsectors MAXSECTORS ifle numwalls MAXWALLS nullop else ifle numsectors MAXSECTORS ifle numwalls MAXWALLS nullop else
{ quote 19 printmessage16 19 return } { quote 19 printmessage16 19 return }

View file

@ -0,0 +1,152 @@
// load a.m32 first
defstate testkeyavail
for i range 27
{
ifholdkey alphakeys[i]
{
qsprintf TQUOTE "ALPHA KEY: %d (SCANCODE: %d)" i alphakeys[i]
quote TQUOTE
}
}
for i range 10
{
ifholdkey numberkeys[i]
{
qsprintf TQUOTE "NUMBER KEY: %d (SCANCODE: %d)" i numberkeys[i]
quote TQUOTE
}
}
ends
// various tests of m32-script features
defstate arraytest
getarraysize ar tmp
resizearray ar 65536
getticks parm[2]
for j range 65536
set ar[j] j
set i 0
for j range 65536
add i ar[j]
getticks parm[3]
resizearray ar tmp
ife i 2147450880 quote "OK" else quote "DAMN"
sub parm[3] parm[2]
qsprintf TQUOTE "time: %d ms" parm[3]
quote TQUOTE
ends
defstate itertest
// iteration and break test
for i range 10
{
addlogvar i
ife i 5 break
}
ife i 5 quote "OK" else quote "DAMN"
quote "FLOAT ACCESS TEST"
set tmp pr_parallaxscale
set gi tmp set gj tmp set gk tmp
al gi al gj al gk
ftoi gi 20 ftoi gj 200 ftoi gk 2000
al gi al gj al gk
mul gk 2
itof gk 2000
ends
define TEST_ZERO 0
define TEST_PLUS_ONE 1
define TEST_MINUS_ONE -1
define MOST_POSITIVE_DIRECT 32767
define MOST_NEGATIVE_DIRECT -32768
define LEAST_POSITIVE_INDIRECT 32768
define LEAST_NEGATIVE_INDIRECT -32769
define HEX_MOST_POSITIVE_DIRECT 0x7fff
define HEX_MOST_NEGATIVE_DIRECT 0xffff8000
define HEX_LEAST_POSITIVE_INDIRECT 0x8000
define HEX_LEAST_NEGATIVE_INDIRECT 0xffff7fff
define MAX_CONSTANT 2147483647
define MIN_CONSTANT -2147483648
// tests various combinations of constants and labels
defstate consttest
quote " --- Constants test ---", quote " "
quote "Shoud be 0:"
set i 0, set j TEST_ZERO
qsprintf TQUOTE "%d %d %d %d" 0 TEST_ZERO i j
quote TQUOTE, quote " "
quote "Shoud be 1:"
set i 1, set j TEST_PLUS_ONE
qsprintf TQUOTE "%d %d %d %d" 1 TEST_PLUS_ONE i j
quote TQUOTE, quote " "
quote "Shoud be -1:"
set i -1, set j TEST_MINUS_ONE
qsprintf TQUOTE "%d %d %d %d" -1 TEST_MINUS_ONE i j
quote TQUOTE, quote " "
quote "Shoud be 32767:"
set i 32767, set j MOST_POSITIVE_DIRECT
qsprintf TQUOTE "%d %d %d %d" 32767 MOST_POSITIVE_DIRECT i j
quote TQUOTE, quote " "
quote "Shoud be -32768:"
set i -32768, set j MOST_NEGATIVE_DIRECT
qsprintf TQUOTE "%d %d %d %d" -32768 MOST_NEGATIVE_DIRECT i j
quote TQUOTE, quote " "
quote "Shoud be 32768:"
set i 32768, set j LEAST_POSITIVE_INDIRECT
qsprintf TQUOTE "%d %d %d %d" 32768 LEAST_POSITIVE_INDIRECT i j
quote TQUOTE, quote " "
quote "Shoud be -32769:"
set i -32769, set j LEAST_NEGATIVE_INDIRECT
qsprintf TQUOTE "%d %d %d %d" -32769 LEAST_NEGATIVE_INDIRECT i j
quote TQUOTE, quote " "
quote "Hex tests:"
quote "Shoud be 32767:"
set i 0x7fff, set j HEX_MOST_POSITIVE_DIRECT
qsprintf TQUOTE "%d %d %d %d" 0x7fff HEX_MOST_POSITIVE_DIRECT i j
quote TQUOTE, quote " "
quote "Shoud be -32768:"
set i 0xffff8000, set j HEX_MOST_NEGATIVE_DIRECT
qsprintf TQUOTE "%d %d %d %d" 0xffff8000 HEX_MOST_NEGATIVE_DIRECT i j
quote TQUOTE, quote " "
quote "Shoud be 32768:"
set i 0x8000, set j HEX_LEAST_POSITIVE_INDIRECT
qsprintf TQUOTE "%d %d %d %d" 0x8000 HEX_LEAST_POSITIVE_INDIRECT i j
quote TQUOTE, quote " "
quote "Shoud be -32769:"
set i 0xffff7fff, set j HEX_LEAST_NEGATIVE_INDIRECT
qsprintf TQUOTE "%d %d %d %d" 0xffff7fff HEX_LEAST_NEGATIVE_INDIRECT i j
quote TQUOTE, quote " "
quote "min/max tests:"
quote "Shoud be 2147483647:"
set i 2147483647, set j MAX_CONSTANT
qsprintf TQUOTE "%d %d %d %d" 2147483647 MAX_CONSTANT i j
quote TQUOTE, quote " "
quote "Shoud be -2147483648:"
set i -2147483648, set j MIN_CONSTANT
qsprintf TQUOTE "%d %d %d %d" -2147483648 MIN_CONSTANT i j
quote TQUOTE, quote " "
ends

View file

@ -94,6 +94,8 @@ static struct strllist
const char *scripthist[SCRIPTHISTSIZ]; const char *scripthist[SCRIPTHISTSIZ];
int32_t scripthistend = 0; int32_t scripthistend = 0;
int32_t showambiencesounds=2;
//////////////////// Key stuff //////////////////// //////////////////// Key stuff ////////////////////
#define eitherALT (keystatus[KEYSC_LALT] || keystatus[KEYSC_RALT]) #define eitherALT (keystatus[KEYSC_LALT] || keystatus[KEYSC_RALT])
@ -7318,19 +7320,6 @@ static int32_t osdcmd_testplay_addparam(const osdfuncparm_t *parm)
return OSDCMD_OK; return OSDCMD_OK;
} }
static int32_t osdcmd_showheightindicators(const osdfuncparm_t *parm)
{
extern int32_t showheightindicators;
if (parm->numparms == 1)
showheightindicators = clamp(atoi(parm->parms[0]), 0, 2);
OSD_Printf("height indicators: %s\n",
showheightindicators==0 ? "none" :
(showheightindicators==1 ? "two-sided walls only" : "all"));
return OSDCMD_OK;
}
//PK vvv ------------ //PK vvv ------------
static int32_t osdcmd_vars_pk(const osdfuncparm_t *parm) static int32_t osdcmd_vars_pk(const osdfuncparm_t *parm)
@ -7368,20 +7357,55 @@ static int32_t osdcmd_vars_pk(const osdfuncparm_t *parm)
} }
else if (!Bstrcasecmp(parm->name, "pk_uedaccel")) else if (!Bstrcasecmp(parm->name, "pk_uedaccel"))
{ {
if (showval) if (parm->numparms==1)
OSD_Printf("UnrealEd mouse navigation acceleration is %d\n", pk_uedaccel);
else
{ {
pk_uedaccel = atoi(parm->parms[0]); pk_uedaccel = atoi(parm->parms[0]);
pk_uedaccel = pk_uedaccel<0 ? 0:pk_uedaccel; pk_uedaccel = pk_uedaccel<0 ? 0:pk_uedaccel;
pk_uedaccel = pk_uedaccel>5 ? 5:pk_uedaccel; pk_uedaccel = pk_uedaccel>5 ? 5:pk_uedaccel;
} }
if (parm->numparms <= 1)
OSD_Printf("UnrealEd mouse navigation acceleration is %d\n", pk_uedaccel);
else
return OSDCMD_SHOWHELP;
} }
else if (!Bstrcasecmp(parm->name, "osd_tryscript")) else if (!Bstrcasecmp(parm->name, "osd_tryscript"))
{ {
m32_osd_tryscript = !m32_osd_tryscript; m32_osd_tryscript = !m32_osd_tryscript;
OSD_Printf("Try M32 script execution on invalid OSD command: %s\n", m32_osd_tryscript?"on":"off"); OSD_Printf("Try M32 script execution on invalid OSD command: %s\n", m32_osd_tryscript?"on":"off");
} }
else if (!Bstrcasecmp(parm->name, "script_expertmode"))
{
m32_script_expertmode = !m32_script_expertmode;
if (m32_script_expertmode)
OSD_Printf("M32 Script expert mode ENABLED. Be sure to know what you are doing!\n");
else
OSD_Printf("M32 Script expert mode DISABLED.\n");
}
else if (!Bstrcasecmp(parm->name, "show_heightindicators"))
{
static const char *how[3] = {"none", "two-sided walls only", "all"};
if (parm->numparms == 1)
showheightindicators = clamp(atoi(parm->parms[0]), 0, 2);
if (parm->numparms <= 1)
OSD_Printf("height indicators: %s\n", how[showheightindicators]);
else
return OSDCMD_SHOWHELP;
}
else if (!Bstrcasecmp(parm->name, "show_ambiencesounds"))
{
static const char *how[3] = {"none", "current sector only", "all"};
if (parm->numparms == 1)
showambiencesounds = clamp(atoi(parm->parms[0]), 0, 2);
if (parm->numparms <= 1)
OSD_Printf("ambience sound circles: %s\n", how[showambiencesounds]);
else
return OSDCMD_SHOWHELP;
}
return OSDCMD_OK; return OSDCMD_OK;
} }
@ -7615,18 +7639,19 @@ static int32_t registerosdcommands(void)
OSD_RegisterFunction("noclip","noclip: toggles clipping mode", osdcmd_noclip); OSD_RegisterFunction("noclip","noclip: toggles clipping mode", osdcmd_noclip);
OSD_RegisterFunction("quit","quit: exits the game immediately", osdcmd_quit); OSD_RegisterFunction("quit","quit: exits the editor immediately", osdcmd_quit);
OSD_RegisterFunction("exit","exit: exits the game immediately", osdcmd_quit); OSD_RegisterFunction("exit","exit: exits the editor immediately", osdcmd_quit);
OSD_RegisterFunction("sensitivity","sensitivity <value>: changes the mouse sensitivity", osdcmd_sensitivity); OSD_RegisterFunction("sensitivity","sensitivity <value>: changes the mouse sensitivity", osdcmd_sensitivity);
//PK //PK
OSD_RegisterFunction("pk_turnaccel", "pk_turnaccel: sets turning acceleration", osdcmd_vars_pk); OSD_RegisterFunction("pk_turnaccel", "pk_turnaccel <value>: sets turning acceleration+deceleration", osdcmd_vars_pk);
OSD_RegisterFunction("pk_turndecel", "pk_turndecel: sets turning deceleration", osdcmd_vars_pk); OSD_RegisterFunction("pk_turndecel", "pk_turndecel <value>: sets turning deceleration", osdcmd_vars_pk);
OSD_RegisterFunction("pk_uedaccel", "pk_uedaccel: sets UnrealEd movement speed factor (0-5, exponentially)", osdcmd_vars_pk); OSD_RegisterFunction("pk_uedaccel", "pk_uedaccel <value>: sets UnrealEd movement speed factor (0-5, exponentially)", osdcmd_vars_pk);
OSD_RegisterFunction("pk_quickmapcycling", "pk_quickmapcycling: allows cycling of maps with (Shift-)Ctrl-X", osdcmd_vars_pk); OSD_RegisterFunction("pk_quickmapcycling", "pk_quickmapcycling: toggles quick cycling of maps with (Shift-)Ctrl-X", osdcmd_vars_pk);
OSD_RegisterFunction("testplay_addparam", "testplay_addparam \"string\": set additional parameters for test playing", osdcmd_testplay_addparam); OSD_RegisterFunction("testplay_addparam", "testplay_addparam \"string\": sets additional parameters for test playing", osdcmd_testplay_addparam);
OSD_RegisterFunction("showheightindicators", "showheightindicators [012]: toggles height indicators in 2D mode", osdcmd_showheightindicators); OSD_RegisterFunction("show_heightindicators", "show_heightindicators <0, 1 or 2>: sets display of height indicators in 2D mode", osdcmd_vars_pk);
OSD_RegisterFunction("show_ambiencesounds", "show_ambiencesounds <0, 1 or 2>: sets display of MUSICANDSFX circles in 2D mode", osdcmd_vars_pk);
#ifdef POLYMOST #ifdef POLYMOST
OSD_RegisterFunction("tint", "tint <pal> <r> <g> <b> <flags>: queries or sets hightile tinting", osdcmd_tint); OSD_RegisterFunction("tint", "tint <pal> <r> <g> <b> <flags>: queries or sets hightile tinting", osdcmd_tint);
#endif #endif
@ -7634,10 +7659,11 @@ static int32_t registerosdcommands(void)
// M32 script // M32 script
OSD_RegisterFunction("include", "include <filnames...>: compiles one or more M32 script files", osdcmd_include); OSD_RegisterFunction("include", "include <filnames...>: compiles one or more M32 script files", osdcmd_include);
OSD_RegisterFunction("do", "do (m32 script ...): executes M32 script statements", osdcmd_do); OSD_RegisterFunction("do", "do (m32 script ...): executes M32 script statements", osdcmd_do);
OSD_RegisterFunction("scriptinfo", "scriptinfo: shows information about compiled M32 script", osdcmd_scriptinfo); OSD_RegisterFunction("script_info", "script_info: shows information about compiled M32 script", osdcmd_scriptinfo);
OSD_RegisterFunction("script_expertmode", "script_expertmode: toggles M32 script expert mode", osdcmd_vars_pk);
OSD_RegisterFunction("enableevent", "enableevent <all|EVENT_...|(event number)>", osdcmd_endisableevent); OSD_RegisterFunction("enableevent", "enableevent <all|EVENT_...|(event number)>", osdcmd_endisableevent);
OSD_RegisterFunction("disableevent", "disableevent <all|EVENT_...|(event number)>", osdcmd_endisableevent); OSD_RegisterFunction("disableevent", "disableevent <all|EVENT_...|(event number)>", osdcmd_endisableevent);
OSD_RegisterFunction("osd_tryscript", "osd_tryscript: Toggles execution of M32 script on invalid OSD command", osdcmd_vars_pk); OSD_RegisterFunction("osd_tryscript", "osd_tryscript: toggles execution of M32 script on invalid OSD command", osdcmd_vars_pk);
// OSD_RegisterFunction("disasm", "disasm [s|e] <state or event number>", osdcmd_disasm); // OSD_RegisterFunction("disasm", "disasm [s|e] <state or event number>", osdcmd_disasm);
return 0; return 0;
} }
@ -9008,9 +9034,13 @@ void ExtPreCheckKeys(void) // just before drawrooms
} }
} }
if (showambiencesounds)
for (i=0; i<numsprites; i++) for (i=0; i<numsprites; i++)
if (sprite[i].picnum == 5 /*&& zoom >= 256*/ && sprite[i].sectnum != MAXSECTORS) if (sprite[i].picnum == MUSICANDSFX /*&& zoom >= 256*/ && sprite[i].sectnum != MAXSECTORS)
{ {
if (showambiencesounds==1 && sprite[i].sectnum!=cursectnum)
continue;
xp1 = mulscale14(sprite[i].x-pos.x,zoom); xp1 = mulscale14(sprite[i].x-pos.x,zoom);
yp1 = mulscale14(sprite[i].y-pos.y,zoom); yp1 = mulscale14(sprite[i].y-pos.y,zoom);

File diff suppressed because it is too large Load diff

View file

@ -25,17 +25,20 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
#ifndef _m32def_h_ #ifndef _m32def_h_
#define _m32def_h_ #define _m32def_h_
#define ABORTERRCNT 8 // the parsing routines aren't good at error recovery yet...
#define ABORTERRCNT 1
// these two are for m32def.c
#define C_CUSTOMERROR(Text, ...) do { \ #define C_CUSTOMERROR(Text, ...) do { \
C_ReportError(-1); \ C_ReportError(-1); \
initprintf("%s:%d: error: " Text "\n", g_szScriptFileName, g_lineNumber, ## __VA_ARGS__); \ initprintf("%s:%d: error: " Text "\n", g_szScriptFileName, g_lineNumber, ## __VA_ARGS__); \
PrintErrorPosition(); \
g_numCompilerErrors++; \ g_numCompilerErrors++; \
} while (0) } while (0)
#define C_CUSTOMWARNING(Text, ...) do { \ #define C_CUSTOMWARNING(Text, ...) do { \
C_ReportError(-1); \ C_ReportError(-1); \
initprintf("%s:%d: warning: " Text "\n", g_szScriptFileName, g_lineNumber, ## __VA_ARGS__); \ initprintf("%s:%d: warning: " Text "\n", g_szScriptFileName, g_lineNumber, ## __VA_ARGS__); \
PrintErrorPosition(); \
g_numCompilerWarnings++; \ g_numCompilerWarnings++; \
} while (0) } while (0)
@ -52,8 +55,9 @@ void C_CompilationInfo(void);
typedef struct typedef struct
{ {
int32_t ofs; int32_t ofs; // offset into script[]
int32_t codesize; int32_t codesize;
uint16_t numlocals; // number of local int32_t vars to allocate
char name[MAXLABELLEN]; char name[MAXLABELLEN];
} statesinfo_t; } statesinfo_t;
@ -99,7 +103,6 @@ extern vmstate_t vm_default;
extern int32_t g_errorLineNum; extern int32_t g_errorLineNum;
extern int32_t g_tw;
extern const char *keyw[]; extern const char *keyw[];
enum SystemString_t { enum SystemString_t {
@ -228,6 +231,7 @@ enum IterationTypes_t
ITER_SELSECTORS, ITER_SELSECTORS,
ITER_SELWALLS, ITER_SELWALLS,
ITER_DRAWNSPRITES, ITER_DRAWNSPRITES,
// ---
ITER_SPRITESOFSECTOR, ITER_SPRITESOFSECTOR,
ITER_WALLSOFSECTOR, ITER_WALLSOFSECTOR,
ITER_LOOPOFWALL, ITER_LOOPOFWALL,

View file

@ -151,6 +151,12 @@ void VM_OnEvent(register int32_t iEventID, register int32_t iActor)
{ {
instype *oinsptr=insptr; instype *oinsptr=insptr;
vmstate_t vm_backup; vmstate_t vm_backup;
void *olocalvars = aGameArrays[M32_LOCAL_ARRAY_ID].vals;
void *localvars = alloca(aEventNumLocals[iEventID] * sizeof(int32_t));
// needed since any read access before initialization would cause undefined behaviour
if (aEventNumLocals[iEventID] > 0)
Bmemset(localvars, aEventNumLocals[iEventID]*sizeof(int32_t), 0);
Bmemcpy(&vm_backup, &vm, sizeof(vmstate_t)); Bmemcpy(&vm_backup, &vm, sizeof(vmstate_t));
@ -163,7 +169,10 @@ void VM_OnEvent(register int32_t iEventID, register int32_t iActor)
vm.flags = 0; vm.flags = 0;
insptr = script + aEventOffsets[iEventID]; insptr = script + aEventOffsets[iEventID];
aGameArrays[M32_LOCAL_ARRAY_ID].vals = localvars;
VM_Execute(0); VM_Execute(0);
aGameArrays[M32_LOCAL_ARRAY_ID].vals = olocalvars;
if (vm.flags&VMFLAG_ERROR) if (vm.flags&VMFLAG_ERROR)
{ {
@ -279,6 +288,26 @@ static int32_t X_DoSort(const int32_t *lv, const int32_t *rv)
continue; \ continue; \
} \ } \
static char *GetMaybeInlineQuote(int32_t quotei)
{
char *quotetext;
if (quotei==-1)
{
quotetext = (char *)insptr;
while (*insptr++) /* skip the string */;
}
else
{
quotei = Gv_GetVarX(quotei);
do { X_ERROR_INVALIDQUOTE(quotei, ScriptQuotes) } while (0);
if (vm.flags&VMFLAG_ERROR)
return NULL;
quotetext = ScriptQuotes[quotei];
}
return quotetext;
}
int32_t VM_Execute(int32_t once) int32_t VM_Execute(int32_t once)
{ {
register int32_t tw = *insptr; register int32_t tw = *insptr;
@ -311,10 +340,18 @@ skip_check:
{ {
instype *tempscrptr = insptr+2; instype *tempscrptr = insptr+2;
int32_t stateidx = *(insptr+1), o_g_st = vm.g_st, oret=vm.flags&VMFLAG_RETURN; int32_t stateidx = *(insptr+1), o_g_st = vm.g_st, oret=vm.flags&VMFLAG_RETURN;
void *olocalvars = aGameArrays[M32_LOCAL_ARRAY_ID].vals;
void *localvars = alloca(statesinfo[stateidx].numlocals * sizeof(int32_t));
// needed since any read access before initialization would cause undefined behaviour
if (statesinfo[stateidx].numlocals > 0)
Bmemset(localvars, statesinfo[stateidx].numlocals*sizeof(int32_t), 0);
insptr = script + statesinfo[stateidx].ofs; insptr = script + statesinfo[stateidx].ofs;
vm.g_st = 1+MAXEVENTS+stateidx; vm.g_st = 1+MAXEVENTS+stateidx;
aGameArrays[M32_LOCAL_ARRAY_ID].vals = localvars;
VM_Execute(0); VM_Execute(0);
aGameArrays[M32_LOCAL_ARRAY_ID].vals = olocalvars;
vm.g_st = o_g_st; vm.g_st = o_g_st;
vm.flags &= ~VMFLAG_RETURN; vm.flags &= ~VMFLAG_RETURN;
vm.flags |= oret; vm.flags |= oret;
@ -544,7 +581,7 @@ skip_check:
if (asize<=0 || asize>65536) if (asize<=0 || asize>65536)
{ {
M32_PRINTERROR("Invalid array size %d (max: 65536)"); M32_PRINTERROR("Invalid array size %d (must be between 1 and 65536)", asize);
vm.flags |= VMFLAG_ERROR; vm.flags |= VMFLAG_ERROR;
continue; continue;
} }
@ -598,7 +635,7 @@ skip_check:
if ((sidx+numelts) > ssiz) numelts = ssiz-sidx; if ((sidx+numelts) > ssiz) numelts = ssiz-sidx;
if ((didx+numelts) > dsiz) numelts = dsiz-didx; if ((didx+numelts) > dsiz) numelts = dsiz-didx;
switch (aGameArrays[si].dwFlags & GAMEARRAY_TYPEMASK) switch (aGameArrays[si].dwFlags & GAMEARRAY_TYPE_MASK)
{ {
case 0: case 0:
case GAMEARRAY_OFINT: case GAMEARRAY_OFINT:
@ -2025,16 +2062,20 @@ badindex:
char pp1[4][8] = {"sprite","sector","wall","tsprite"}; char pp1[4][8] = {"sprite","sector","wall","tsprite"};
const memberlabel_t *pp2[4] = {SpriteLabels, SectorLabels, WallLabels, SpriteLabels}; const memberlabel_t *pp2[4] = {SpriteLabels, SectorLabels, WallLabels, SpriteLabels};
if ((code&M32_FLAG_ARRAY) || (code&M32_FLAG_SPECIAL)) if ((code&M32_VARTYPE_MASK)==M32_FLAG_ARRAY || (code&M32_VARTYPE_MASK)==M32_FLAG_STRUCT)
{ {
if (code&MAXGAMEVARS) if (code&M32_FLAG_CONSTANT)
Bsprintf(buf2, "%d", (code>>16)&0xffff); Bsprintf(buf2, "%d", (code>>16)&0xffff);
else else
Bsprintf(buf2, "%s", aGameVars[(code>>16)&(MAXGAMEVARS-1)].szLabel? {
aGameVars[(code>>16)&(MAXGAMEVARS-1)].szLabel:"???"); char *label = aGameVars[(code>>16)&(MAXGAMEVARS-1)].szLabel;
Bsprintf(buf2, "%s", label?label:"???");
} }
}
else if ((code&M32_VARTYPE_MASK)==M32_FLAG_LOCAL)
Bsprintf(buf2, "%d", code&(MAXGAMEVARS-1));
if ((code&0x0000FFFC) == MAXGAMEVARS) // addlogvar for a constant.. why not? :P if ((code&0x0000FFFC) == M32_FLAG_CONSTANT) // addlogvar for a constant.. why not? :P
{ {
switch (code&3) switch (code&3)
{ {
@ -2044,13 +2085,25 @@ badindex:
default: Bsprintf(buf, "(??? constant)"); break; default: Bsprintf(buf, "(??? constant)"); break;
} }
} }
else if (code&M32_FLAG_ARRAY) else
{
switch (code&M32_VARTYPE_MASK)
{
case M32_FLAG_ARRAY:
Bsprintf(buf, "%s[%s]", aGameArrays[code&(MAXGAMEARRAYS-1)].szLabel? Bsprintf(buf, "%s[%s]", aGameArrays[code&(MAXGAMEARRAYS-1)].szLabel?
aGameArrays[code&(MAXGAMEARRAYS-1)].szLabel:"???", buf2); aGameArrays[code&(MAXGAMEARRAYS-1)].szLabel:"???", buf2);
else if (code&M32_FLAG_SPECIAL) break;
case M32_FLAG_STRUCT:
Bsprintf(buf, "%s[%s].%s", pp1[code&3], buf2, pp2[code&3][(code>>2)&31].name); Bsprintf(buf, "%s[%s].%s", pp1[code&3], buf2, pp2[code&3][(code>>2)&31].name);
else break;
case M32_FLAG_VAR:
Bsprintf(buf, "???"); Bsprintf(buf, "???");
break;
case M32_FLAG_LOCAL:
Bsprintf(buf, ".local[%s]", buf2);
break;
}
}
} }
else else
{ {
@ -2098,17 +2151,24 @@ badindex:
case CON_GETNUMBER256: case CON_GETNUMBER256:
insptr++; insptr++;
{ {
int32_t var=*insptr++, quote=Gv_GetVarX(*insptr++), max=Gv_GetVarX(*insptr++), sign=ksgn(max)<0?1:0; int32_t var=*insptr++, quote=*insptr++;
char buf[60]; const char *quotetext = GetMaybeInlineQuote(quote);
if (vm.flags&VMFLAG_ERROR)
continue;
X_ERROR_INVALIDQUOTE(quote, ScriptQuotes); {
Bmemcpy(buf, ScriptQuotes[quote], sizeof(buf)-1); int32_t max=Gv_GetVarX(*insptr++), sign=ksgn(max)<0?1:0;
char buf[64]; // buffers in getnumber* are 80 bytes long
// no danger of accessing unallocated memory since we took care in C_SetScriptSize()
Bmemcpy(buf, quotetext, sizeof(buf));
buf[sizeof(buf)-1]='\0'; buf[sizeof(buf)-1]='\0';
if (tw==CON_GETNUMBER16) if (tw==CON_GETNUMBER16)
Gv_SetVarX(var, getnumber16(ScriptQuotes[quote], Gv_GetVarX(var), max, sign)); Gv_SetVarX(var, getnumber16(quotetext, Gv_GetVarX(var), max, sign));
else else
Gv_SetVarX(var, getnumber256(ScriptQuotes[quote], Gv_GetVarX(var), max, sign)); Gv_SetVarX(var, getnumber256(quotetext, Gv_GetVarX(var), max, sign));
}
} }
continue; continue;
@ -2121,7 +2181,12 @@ badindex:
case CON_PRINTEXT16: case CON_PRINTEXT16:
insptr++; insptr++;
{ {
int32_t i=Gv_GetVarX(*insptr++); int32_t i=*insptr++;
const char *quotetext = GetMaybeInlineQuote(i);
if (vm.flags&VMFLAG_ERROR)
continue;
{
int32_t x=(tw>=CON_PRINTMESSAGE256)?Gv_GetVarX(*insptr++):0; int32_t x=(tw>=CON_PRINTMESSAGE256)?Gv_GetVarX(*insptr++):0;
int32_t y=(tw>=CON_PRINTMESSAGE256)?Gv_GetVarX(*insptr++):0; int32_t y=(tw>=CON_PRINTMESSAGE256)?Gv_GetVarX(*insptr++):0;
int32_t col=(tw>=CON_PRINTEXT256)?Gv_GetVarX(*insptr++):0; int32_t col=(tw>=CON_PRINTEXT256)?Gv_GetVarX(*insptr++):0;
@ -2130,26 +2195,25 @@ badindex:
if (tw==CON_ERRORINS) vm.flags |= VMFLAG_ERROR; if (tw==CON_ERRORINS) vm.flags |= VMFLAG_ERROR;
X_ERROR_INVALIDQUOTE(i, ScriptQuotes); if (tw==CON_PRINT || tw==CON_ERRORINS)
OSD_Printf("%s\n", quotetext);
if (tw==CON_PRINT) else if (tw==CON_QUOTE)
OSD_Printf("%s\n", ScriptQuotes[i]); message("%s", quotetext);
if (tw==CON_QUOTE)
message("%s", ScriptQuotes[i]);
else if (tw==CON_PRINTMESSAGE16) else if (tw==CON_PRINTMESSAGE16)
printmessage16("%s", ScriptQuotes[i]); printmessage16("%s", quotetext);
else if (tw==CON_PRINTMESSAGE256) else if (tw==CON_PRINTMESSAGE256)
printmessage256(x, y, ScriptQuotes[i]); printmessage256(x, y, quotetext);
else if (tw==CON_PRINTEXT256) else if (tw==CON_PRINTEXT256)
{ {
if (col<0 || col>=256) col=0; if (col<0 || col>=256) col=0;
if (backcol<0 || backcol>=256) backcol=-1; if (backcol<0 || backcol>=256) backcol=-1;
printext256(x, y, col, backcol, ScriptQuotes[i], fontsize); printext256(x, y, col, backcol, quotetext, fontsize);
} }
else if (tw==CON_PRINTEXT16) else if (tw==CON_PRINTEXT16)
{ {
printext16(x, y, editorcolors[col&15], backcol<0 ? -1 : editorcolors[backcol&15], printext16(x, y, editorcolors[col&15], backcol<0 ? -1 : editorcolors[backcol&15],
ScriptQuotes[i], fontsize); quotetext, fontsize);
}
} }
} }
continue; continue;
@ -2157,11 +2221,12 @@ badindex:
case CON_QSTRLEN: case CON_QSTRLEN:
insptr++; insptr++;
{ {
int32_t i=*insptr++; int32_t i=*insptr++, quote=*insptr++;
int32_t j=Gv_GetVarX(*insptr++); const char *quotetext = GetMaybeInlineQuote(quote);
if (vm.flags&VMFLAG_ERROR)
continue;
X_ERROR_INVALIDQUOTE(j, ScriptQuotes); Gv_SetVarX(i, Bstrlen(quotetext));
Gv_SetVarX(i, Bstrlen(ScriptQuotes[j]));
continue; continue;
} }
@ -2169,16 +2234,18 @@ badindex:
insptr++; insptr++;
{ {
int32_t q1 = Gv_GetVarX(*insptr++); int32_t q1 = Gv_GetVarX(*insptr++);
int32_t q2 = Gv_GetVarX(*insptr++); int32_t q2 = *insptr++;
int32_t st = Gv_GetVarX(*insptr++); const char *q2text = GetMaybeInlineQuote(q2);
int32_t ln = Gv_GetVarX(*insptr++); if (vm.flags&VMFLAG_ERROR)
continue;
X_ERROR_INVALIDQUOTE(q1, ScriptQuotes); X_ERROR_INVALIDQUOTE(q1, ScriptQuotes);
X_ERROR_INVALIDQUOTE(q2, ScriptQuotes);
{ {
int32_t st = Gv_GetVarX(*insptr++);
int32_t ln = Gv_GetVarX(*insptr++);
char *s1 = ScriptQuotes[q1]; char *s1 = ScriptQuotes[q1];
char *s2 = ScriptQuotes[q2]; const char *s2 = q2text;
while (*s2 && st--) s2++; while (*s2 && st--) s2++;
while ((*s1 = *s2) && ln--) while ((*s1 = *s2) && ln--)
@ -2198,10 +2265,13 @@ badindex:
insptr++; insptr++;
{ {
int32_t i = Gv_GetVarX(*insptr++); int32_t i = Gv_GetVarX(*insptr++);
int32_t j = Gv_GetVarX(*insptr++); int32_t j = *insptr++;
const char *quotetext = GetMaybeInlineQuote(j);
if (vm.flags&VMFLAG_ERROR)
continue;
X_ERROR_INVALIDQUOTE(i, ScriptQuotes); X_ERROR_INVALIDQUOTE(i, ScriptQuotes);
X_ERROR_INVALIDQUOTE(j, ScriptQuotes);
switch (tw) switch (tw)
{ {
@ -2226,13 +2296,13 @@ badindex:
break; break;
#endif #endif
case CON_QSTRCAT: case CON_QSTRCAT:
Bstrncat(ScriptQuotes[i],ScriptQuotes[j],(MAXQUOTELEN-1)-Bstrlen(ScriptQuotes[i])); Bstrncat(ScriptQuotes[i], quotetext, (MAXQUOTELEN-1)-Bstrlen(ScriptQuotes[i]));
break; break;
case CON_QSTRNCAT: case CON_QSTRNCAT:
Bstrncat(ScriptQuotes[i],ScriptQuotes[j],Gv_GetVarX(*insptr++)); Bstrncat(ScriptQuotes[i], quotetext, Gv_GetVarX(*insptr++));
break; break;
case CON_QSTRCPY: case CON_QSTRCPY:
Bstrcpy(ScriptQuotes[i],ScriptQuotes[j]); Bstrcpy(ScriptQuotes[i], quotetext);
break; break;
} }
continue; continue;
@ -2241,14 +2311,16 @@ badindex:
case CON_QSPRINTF: case CON_QSPRINTF:
insptr++; insptr++;
{ {
int32_t dq = Gv_GetVarX(*insptr++), sq = Gv_GetVarX(*insptr++); int32_t dq=Gv_GetVarX(*insptr++), sq=*insptr++;
const char *sourcetext = GetMaybeInlineQuote(sq);
if (vm.flags&VMFLAG_ERROR)
continue;
X_ERROR_INVALIDQUOTE(dq, ScriptQuotes); X_ERROR_INVALIDQUOTE(dq, ScriptQuotes);
X_ERROR_INVALIDQUOTE(sq, ScriptQuotes);
{ {
int32_t arg[32], numvals=0, i=0, j=0, k=0; int32_t arg[32], numvals=0, i=0, j=0, k=0;
int32_t len = Bstrlen(ScriptQuotes[sq]); int32_t len = Bstrlen(sourcetext);
char tmpbuf[MAXQUOTELEN<<1]; char tmpbuf[MAXQUOTELEN<<1];
while (*insptr != -1 && numvals < 32) while (*insptr != -1 && numvals < 32)
@ -2259,23 +2331,23 @@ badindex:
i = 0; i = 0;
do do
{ {
while (k < len && j < MAXQUOTELEN && ScriptQuotes[sq][k] != '%') while (k < len && j < MAXQUOTELEN && sourcetext[k] != '%')
tmpbuf[j++] = ScriptQuotes[sq][k++]; tmpbuf[j++] = sourcetext[k++];
if (ScriptQuotes[sq][k] == '%') if (sourcetext[k] == '%')
{ {
k++; k++;
if (i>=numvals) goto dodefault; if (i>=numvals) goto dodefault;
switch (ScriptQuotes[sq][k]) switch (sourcetext[k])
{ {
case 'l': case 'l':
if (ScriptQuotes[sq][k+1] != 'd') if (sourcetext[k+1] != 'd')
{ {
// write the % and l // write the % and l
tmpbuf[j++] = ScriptQuotes[sq][k-1]; tmpbuf[j++] = sourcetext[k-1];
tmpbuf[j++] = ScriptQuotes[sq][k++]; tmpbuf[j++] = sourcetext[k++];
break; break;
} }
k++; k++;
@ -2321,7 +2393,7 @@ badindex:
dodefault: dodefault:
default: default:
tmpbuf[j++] = ScriptQuotes[sq][k-1]; tmpbuf[j++] = sourcetext[k-1];
break; break;
} }
} }

View file

@ -33,25 +33,27 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
#define ACCESS_USEVARS 2 #define ACCESS_USEVARS 2
#define ACCESS_SPRITEEXT 4 #define ACCESS_SPRITEEXT 4
int32_t m32_script_expertmode = 0;
static int32_t __fastcall VM_AccessWall(int32_t how, int32_t lVar1, int32_t lLabelID, int32_t lVar2) static int32_t __fastcall VM_AccessWall(int32_t how, int32_t lVar1, int32_t lLabelID, int32_t lVar2)
{ {
int32_t lValue; int32_t lValue;
int32_t i = (how&ACCESS_USEVARS) ? Gv_GetVarX(lVar1) : lVar1; int32_t i = (how&ACCESS_USEVARS) ? Gv_GetVarX(lVar1) : lVar1;
if (i<0 || i >= numwalls) if (!m32_script_expertmode && (i<0 || i >= numwalls))
goto badwall; goto badwall;
if (how&ACCESS_SET) if (how&ACCESS_SET)
{ {
if (WallLabels[lLabelID].flags & 1) if (!m32_script_expertmode && (WallLabels[lLabelID].flags & 1))
goto readonly; goto readonly;
lValue = (how&ACCESS_USEVARS) ? Gv_GetVarX(lVar2) : lVar2; lValue = (how&ACCESS_USEVARS) ? Gv_GetVarX(lVar2) : lVar2;
asksave = 1; asksave = 1;
if (WallLabels[lLabelID].min != 0 || WallLabels[lLabelID].max != 0) if (!m32_script_expertmode && (WallLabels[lLabelID].min != 0 || WallLabels[lLabelID].max != 0))
{ {
if (lValue < WallLabels[lLabelID].min) if (lValue < WallLabels[lLabelID].min)
lValue = WallLabels[lLabelID].min; lValue = WallLabels[lLabelID].min;
@ -134,19 +136,19 @@ static int32_t __fastcall VM_AccessSector(int32_t how, int32_t lVar1, int32_t lL
if ((how&ACCESS_USEVARS) && lVar1 != M32_THISACTOR_VAR_ID) if ((how&ACCESS_USEVARS) && lVar1 != M32_THISACTOR_VAR_ID)
i = Gv_GetVarX(lVar1); i = Gv_GetVarX(lVar1);
if (i<0 || i >= numsectors) if (!m32_script_expertmode && (i<0 || i >= numsectors))
goto badsector; goto badsector;
if (how&ACCESS_SET) if (how&ACCESS_SET)
{ {
if (SectorLabels[lLabelID].flags & 1) if (!m32_script_expertmode && (SectorLabels[lLabelID].flags & 1))
goto readonly; goto readonly;
lValue = (how&ACCESS_USEVARS) ? Gv_GetVarX(lVar2) : lVar2; lValue = (how&ACCESS_USEVARS) ? Gv_GetVarX(lVar2) : lVar2;
asksave = 1; asksave = 1;
if (SectorLabels[lLabelID].min != 0 || SectorLabels[lLabelID].max != 0) if (!m32_script_expertmode && (SectorLabels[lLabelID].min != 0 || SectorLabels[lLabelID].max != 0))
{ {
if (lValue < SectorLabels[lLabelID].min) if (lValue < SectorLabels[lLabelID].min)
lValue = SectorLabels[lLabelID].min; lValue = SectorLabels[lLabelID].min;
@ -252,18 +254,18 @@ static int32_t __fastcall VM_AccessSprite(int32_t how, int32_t lVar1, int32_t lL
i = Gv_GetVarX(lVar1); i = Gv_GetVarX(lVar1);
if (i < 0 || i >= MAXSPRITES) if (i < 0 || i >= MAXSPRITES)
goto badactor; goto badsprite;
if (how&ACCESS_SET) if (how&ACCESS_SET)
{ {
if (SpriteLabels[lLabelID].flags & 1) if (!m32_script_expertmode && (SpriteLabels[lLabelID].flags & 1))
goto readonly; goto readonly;
lValue = (how&ACCESS_USEVARS) ? Gv_GetVarX(lVar2) : lVar2; lValue = (how&ACCESS_USEVARS) ? Gv_GetVarX(lVar2) : lVar2;
asksave = 1; asksave = 1;
if (SpriteLabels[lLabelID].min != 0 || SpriteLabels[lLabelID].max != 0) if (!m32_script_expertmode && (SpriteLabels[lLabelID].min != 0 || SpriteLabels[lLabelID].max != 0))
{ {
if (lValue < SpriteLabels[lLabelID].min) if (lValue < SpriteLabels[lLabelID].min)
lValue = SpriteLabels[lLabelID].min; lValue = SpriteLabels[lLabelID].min;
@ -342,14 +344,11 @@ static int32_t __fastcall VM_AccessSprite(int32_t how, int32_t lVar1, int32_t lL
return lValue; return lValue;
} }
badactor: badsprite:
// OSD_Printf(CON_ERROR "tried to set %s on invalid target sprite (%d) from spr %d pic %d gv %s\n",g_errorLineNum,keyw[g_tw],
// SpriteLabels[lLabelID].name,i,vm.g_i,vm.g_sp->picnum,
// (lVar1<MAXGAMEVARS)?aGameVars[lVar1].szLabel:"extended");
M32_PRINTERROR("tried to set %s on invalid target sprite (%d)", SpriteLabels[lLabelID].name, i); M32_PRINTERROR("tried to set %s on invalid target sprite (%d)", SpriteLabels[lLabelID].name, i);
return -1; return -1;
readonly: readonly:
M32_PRINTERROR("Sprite structure member `%s' is read-only.", SpriteLabels[lLabelID].name); M32_PRINTERROR("sprite structure member `%s' is read-only.", SpriteLabels[lLabelID].name);
return -1; return -1;
} }

View file

@ -42,6 +42,7 @@ static void Gv_Clear(void)
{ {
if (aGameVars[i].szLabel) if (aGameVars[i].szLabel)
Bfree(aGameVars[i].szLabel); Bfree(aGameVars[i].szLabel);
aGameVars[i].szLabel = NULL; aGameVars[i].szLabel = NULL;
aGameVars[i].dwFlags = 0; aGameVars[i].dwFlags = 0;
@ -50,22 +51,30 @@ static void Gv_Clear(void)
Bfree(aGameVars[i].val.plValues); Bfree(aGameVars[i].val.plValues);
aGameVars[i].val.plValues = NULL; aGameVars[i].val.plValues = NULL;
} }
aGameVars[i].val.lValue = 0; aGameVars[i].val.lValue = 0;
aGameVars[i].dwFlags |= GAMEVAR_RESET; aGameVars[i].dwFlags |= GAMEVAR_RESET;
if (i >= MAXGAMEARRAYS) if (i >= MAXGAMEARRAYS)
continue; continue;
if (aGameArrays[i].szLabel) if (aGameArrays[i].szLabel)
Bfree(aGameArrays[i].szLabel); Bfree(aGameArrays[i].szLabel);
aGameArrays[i].szLabel = NULL; aGameArrays[i].szLabel = NULL;
if (aGameArrays[i].vals) if (aGameArrays[i].vals)
Bfree(aGameArrays[i].vals); Bfree(aGameArrays[i].vals);
aGameArrays[i].vals = NULL; aGameArrays[i].vals = NULL;
aGameArrays[i].dwFlags |= GAMEARRAY_RESET; aGameArrays[i].dwFlags |= GAMEARRAY_RESET;
} }
g_gameVarCount = g_gameArrayCount = 0; g_gameVarCount = g_gameArrayCount = 0;
hash_init(&h_gamevars); hash_init(&h_gamevars);
hash_init(&h_arrays); hash_init(&h_arrays);
return; return;
} }
@ -90,7 +99,7 @@ int32_t Gv_NewArray(const char *pszLabel, void *arrayptr, intptr_t asize, uint32
{ {
// found it it's a duplicate in error // found it it's a duplicate in error
if (aGameArrays[i].dwFlags&GAMEARRAY_TYPEMASK) if (aGameArrays[i].dwFlags&GAMEARRAY_TYPE_MASK)
{ {
C_CUSTOMWARNING("ignored redefining system array `%s'.", pszLabel); C_CUSTOMWARNING("ignored redefining system array `%s'.", pszLabel);
} }
@ -98,8 +107,10 @@ int32_t Gv_NewArray(const char *pszLabel, void *arrayptr, intptr_t asize, uint32
return 0; return 0;
} }
if (!(dwFlags&GAMEARRAY_VARSIZE) && (asize<=0 || asize>=65536)) 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", (int32_t)asize); C_CUSTOMERROR("invalid array size %d. Must be between 1 and 65536", (int32_t)asize);
return 0; return 0;
} }
@ -111,7 +122,7 @@ int32_t Gv_NewArray(const char *pszLabel, void *arrayptr, intptr_t asize, uint32
if (aGameArrays[i].szLabel != pszLabel) if (aGameArrays[i].szLabel != pszLabel)
Bstrcpy(aGameArrays[i].szLabel, pszLabel); Bstrcpy(aGameArrays[i].szLabel, pszLabel);
if (!(dwFlags & GAMEARRAY_TYPEMASK)) if (!(dwFlags & GAMEARRAY_TYPE_MASK))
aGameArrays[i].vals = Bcalloc(asize, sizeof(int32_t)); aGameArrays[i].vals = Bcalloc(asize, sizeof(int32_t));
else else
aGameArrays[i].vals = arrayptr; aGameArrays[i].vals = arrayptr;
@ -148,7 +159,7 @@ int32_t Gv_NewVar(const char *pszLabel, intptr_t lValue, uint32_t dwFlags)
if (i >= 0 && !(aGameVars[i].dwFlags & GAMEVAR_RESET)) if (i >= 0 && !(aGameVars[i].dwFlags & GAMEVAR_RESET))
{ {
// found it... // found it...
if (aGameVars[i].dwFlags & (GAMEVAR_INTPTR|GAMEVAR_FLOATPTR|GAMEVAR_SHORTPTR|GAMEVAR_CHARPTR)) if (aGameVars[i].dwFlags & GAMEVAR_PTR_MASK)
{ {
C_ReportError(-1); C_ReportError(-1);
initprintf("%s:%d: warning: cannot redefine internal gamevar `%s'.\n",g_szScriptFileName,g_lineNumber,label+(g_numLabels<<6)); initprintf("%s:%d: warning: cannot redefine internal gamevar `%s'.\n",g_szScriptFileName,g_lineNumber,label+(g_numLabels<<6));
@ -206,22 +217,17 @@ int32_t Gv_NewVar(const char *pszLabel, intptr_t lValue, uint32_t dwFlags)
return 1; return 1;
} }
int32_t __fastcall Gv_GetVarN(register int32_t id) // 'N' for "no side-effects"... vars only! int32_t __fastcall Gv_GetVarN(register int32_t id) // 'N' for "no side-effects"... vars and locals only!
{ {
if (id == M32_THISACTOR_VAR_ID) if (id == M32_THISACTOR_VAR_ID)
return vm.g_i; return vm.g_i;
if (id & (0xFFFFFFFF-(MAXGAMEVARS-1))) switch (id&M32_VARTYPE_MASK)
{ {
M32_PRINTERROR("Gv_GetVarN(): invalid var index %d", id); case M32_FLAG_VAR:
vm.flags |= VMFLAG_ERROR;
return -1;
}
id &= (MAXGAMEVARS-1); id &= (MAXGAMEVARS-1);
switch (aGameVars[id].dwFlags & switch (aGameVars[id].dwFlags & (GAMEVAR_USER_MASK|GAMEVAR_PTR_MASK))
(GAMEVAR_USER_MASK|GAMEVAR_INTPTR|GAMEVAR_FLOATPTR|GAMEVAR_SHORTPTR|GAMEVAR_CHARPTR))
{ {
case 0: case 0:
return aGameVars[id].val.lValue; return aGameVars[id].val.lValue;
@ -239,6 +245,19 @@ int32_t __fastcall Gv_GetVarN(register int32_t id) // 'N' for "no side-effects"
vm.flags |= VMFLAG_ERROR; vm.flags |= VMFLAG_ERROR;
return -1; 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_PRINTERROR("Gv_GetVarN(): invalid var code %0x08x", id);
vm.flags |= VMFLAG_ERROR;
return -1;
}
} }
int32_t __fastcall Gv_GetVarX(register int32_t id) int32_t __fastcall Gv_GetVarX(register int32_t id)
@ -246,7 +265,9 @@ int32_t __fastcall Gv_GetVarX(register int32_t id)
if (id == M32_THISACTOR_VAR_ID) if (id == M32_THISACTOR_VAR_ID)
return vm.g_i; return vm.g_i;
if ((id & 0x0000FFFC) == MAXGAMEVARS) register int32_t negateResult = !!(id&M32_FLAG_NEGATE);
if ((id & M32_BITS_MASK) == M32_FLAG_CONSTANT)
{ {
switch (id&3) switch (id&3)
{ {
@ -255,7 +276,7 @@ int32_t __fastcall Gv_GetVarX(register int32_t id)
case 1: case 1:
return constants[(id>>16)&0xffff]; return constants[(id>>16)&0xffff];
case 2: case 2:
return labelval[(id>>16)&0xffff]; return (labelval[(id>>16)&0xffff] ^ -negateResult) + negateResult;
default: default:
M32_PRINTERROR("Gv_GetVarX() (constant): WTF??"); M32_PRINTERROR("Gv_GetVarX() (constant): WTF??");
vm.flags |= VMFLAG_ERROR; vm.flags |= VMFLAG_ERROR;
@ -263,18 +284,16 @@ int32_t __fastcall Gv_GetVarX(register int32_t id)
} }
} }
{
register int32_t negateResult = (id&M32_FLAG_NEGATE)>>(LOG2MAXGV+1);
if (id & (0xFFFFFFFF-(MAXGAMEVARS-1))) switch (id&M32_VARTYPE_MASK)
{ {
if (id&M32_FLAG_ARRAY) // array case M32_FLAG_ARRAY:
{ {
register int32_t index; register int32_t index;
int32_t siz; int32_t siz;
index = (int32_t)((id>>16)&0xffff); index = (int32_t)((id>>16)&0xffff);
if (!(id&MAXGAMEVARS)) if (!(id&M32_FLAG_CONSTANTINDEX))
index = Gv_GetVarN(index); index = Gv_GetVarN(index);
id &= (MAXGAMEARRAYS-1); id &= (MAXGAMEARRAYS-1);
@ -290,28 +309,27 @@ int32_t __fastcall Gv_GetVarX(register int32_t id)
return -1; return -1;
} }
switch (aGameArrays[id].dwFlags & GAMEARRAY_TYPEMASK) switch (aGameArrays[id].dwFlags & GAMEARRAY_TYPE_MASK)
{ {
case 0: case 0:
case GAMEARRAY_OFINT: case GAMEARRAY_OFINT:
return ((((int32_t *)aGameArrays[id].vals)[index] ^ -negateResult) + negateResult); return (((int32_t *)aGameArrays[id].vals)[index] ^ -negateResult) + negateResult;
case GAMEARRAY_OFSHORT: case GAMEARRAY_OFSHORT:
return ((((int16_t *)aGameArrays[id].vals)[index] ^ -negateResult) + negateResult); return (((int16_t *)aGameArrays[id].vals)[index] ^ -negateResult) + negateResult;
case GAMEARRAY_OFCHAR: case GAMEARRAY_OFCHAR:
return ((((uint8_t *)aGameArrays[id].vals)[index] ^ -negateResult) + negateResult); return (((uint8_t *)aGameArrays[id].vals)[index] ^ -negateResult) + negateResult;
default: default:
M32_PRINTERROR("Gv_GetVarX() (array): WTF??"); M32_PRINTERROR("Gv_GetVarX() (array): WTF??");
vm.flags |= VMFLAG_ERROR; vm.flags |= VMFLAG_ERROR;
return -1; return -1;
} }
} }
case M32_FLAG_STRUCT:
if (id&M32_FLAG_SPECIAL) // struct shortcut vars
{ {
register int32_t index, memberid; register int32_t index, memberid;
index = (id>>16)&0x7fff; index = (id>>16)&0x7fff;
if (!(id&MAXGAMEVARS)) if (!(id&M32_FLAG_CONSTANTINDEX))
index = Gv_GetVarN(index); index = Gv_GetVarN(index);
memberid = (id>>2)&31; memberid = (id>>2)&31;
@ -319,68 +337,67 @@ int32_t __fastcall Gv_GetVarX(register int32_t id)
switch (id&3) switch (id&3)
{ {
case M32_SPRITE_VAR_ID: case M32_SPRITE_VAR_ID:
return ((VM_AccessSprite(0, index, memberid, 0) ^ -negateResult) + negateResult); return (VM_AccessSprite(0, index, memberid, 0) ^ -negateResult) + negateResult;
case M32_SECTOR_VAR_ID: case M32_SECTOR_VAR_ID:
// if (index == vm.g_i) index = sprite[vm.g_i].sectnum; return (VM_AccessSector(0, index, memberid, 0) ^ -negateResult) + negateResult;
return ((VM_AccessSector(0, index, memberid, 0) ^ -negateResult) + negateResult);
case M32_WALL_VAR_ID: case M32_WALL_VAR_ID:
return ((VM_AccessWall(0, index, memberid, 0) ^ -negateResult) + negateResult); return (VM_AccessWall(0, index, memberid, 0) ^ -negateResult) + negateResult;
case M32_TSPRITE_VAR_ID: case M32_TSPRITE_VAR_ID:
return ((VM_AccessTsprite(0, index, memberid, 0) ^ -negateResult) + negateResult); return (VM_AccessTsprite(0, index, memberid, 0) ^ -negateResult) + negateResult;
// default:
// M32_PRINTERROR("Gv_GetVarX() (special): WTF??");
// return -1;
} }
} }
case M32_FLAG_VAR:
{
id &= (MAXGAMEVARS-1); id &= (MAXGAMEVARS-1);
if (!negateResult) switch (aGameVars[id].dwFlags & (GAMEVAR_USER_MASK|GAMEVAR_PTR_MASK))
{
M32_PRINTERROR("Gv_GetVarX(): invalid gamevar ID (%d)", id);
vm.flags |= VMFLAG_ERROR;
return -1;
}
}
switch (aGameVars[id].dwFlags &
(GAMEVAR_USER_MASK|GAMEVAR_INTPTR|GAMEVAR_FLOATPTR|GAMEVAR_SHORTPTR|GAMEVAR_CHARPTR))
{ {
case 0: case 0:
return ((aGameVars[id].val.lValue ^ -negateResult) + negateResult); return (aGameVars[id].val.lValue ^ -negateResult) + negateResult;
case GAMEVAR_PERBLOCK: case GAMEVAR_PERBLOCK:
return ((aGameVars[id].val.plValues[vm.g_st] ^ -negateResult) + negateResult); return (aGameVars[id].val.plValues[vm.g_st] ^ -negateResult) + negateResult;
case GAMEVAR_FLOATPTR: case GAMEVAR_FLOATPTR:
if (negateResult)
{ {
float fval = -(*(float *)aGameVars[id].val.lValue); float fval = *(float *)aGameVars[id].val.lValue;
if (negateResult)
fval *= -1;
return *(int32_t *)&fval; return *(int32_t *)&fval;
} }
case GAMEVAR_INTPTR: case GAMEVAR_INTPTR:
return ((*((int32_t *)aGameVars[id].val.lValue) ^ -negateResult) + negateResult); return (*((int32_t *)aGameVars[id].val.lValue) ^ -negateResult) + negateResult;
case GAMEVAR_SHORTPTR: case GAMEVAR_SHORTPTR:
return ((*((int16_t *)aGameVars[id].val.lValue) ^ -negateResult) + negateResult); return (*((int16_t *)aGameVars[id].val.lValue) ^ -negateResult) + negateResult;
case GAMEVAR_CHARPTR: case GAMEVAR_CHARPTR:
return ((*((uint8_t *)aGameVars[id].val.lValue) ^ -negateResult) + negateResult); return (*((uint8_t *)aGameVars[id].val.lValue) ^ -negateResult) + negateResult;
default: default:
M32_PRINTERROR("Gv_GetVarX(): WTF??"); M32_PRINTERROR("Gv_GetVarX(): WTF??");
vm.flags |= VMFLAG_ERROR; vm.flags |= VMFLAG_ERROR;
return -1; 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(register int32_t id, register int32_t lValue) void __fastcall Gv_SetVarX(register int32_t id, register int32_t lValue)
{ {
if (id & (0xFFFFFFFF-(MAXGAMEVARS-1))) switch (id&M32_VARTYPE_MASK)
{ {
if (id&M32_FLAG_ARRAY) // array case M32_FLAG_ARRAY:
{ {
register int32_t index; register int32_t index;
int32_t siz; int32_t siz;
index = (id>>16)&0xffff; index = (id>>16)&0xffff;
if (!(id&MAXGAMEVARS)) if (!(id&M32_FLAG_CONSTANTINDEX))
index = Gv_GetVarN(index); index = Gv_GetVarN(index);
id &= (MAXGAMEARRAYS-1); id &= (MAXGAMEARRAYS-1);
@ -391,12 +408,12 @@ void __fastcall Gv_SetVarX(register int32_t id, register int32_t lValue)
if (index < 0 || index >= siz) if (index < 0 || index >= siz)
{ {
M32_PRINTERROR("Gv_SetVarX(): invalid array index (%s[%d])", aGameArrays[id].szLabel, index); M32_PRINTERROR("Gv_SetVarX(): invalid array index %s[%d], size=%d", aGameArrays[id].szLabel, index, siz);
vm.flags |= VMFLAG_ERROR; vm.flags |= VMFLAG_ERROR;
return; return;
} }
switch (aGameArrays[id].dwFlags & GAMEARRAY_TYPEMASK) switch (aGameArrays[id].dwFlags & GAMEARRAY_TYPE_MASK)
{ {
case 0: case 0:
case GAMEARRAY_OFINT: case GAMEARRAY_OFINT:
@ -415,13 +432,12 @@ void __fastcall Gv_SetVarX(register int32_t id, register int32_t lValue)
} }
return; return;
} }
case M32_FLAG_STRUCT:
if (id&M32_FLAG_SPECIAL) // struct shortcut vars
{ {
register int32_t index, memberid; register int32_t index, memberid;
index = (id>>16)&0x7fff; index = (id>>16)&0x7fff;
if (!(id&MAXGAMEVARS)) if (!(id&M32_FLAG_CONSTANTINDEX))
index = Gv_GetVarN(index); index = Gv_GetVarN(index);
memberid = (id>>2)&31; memberid = (id>>2)&31;
@ -432,7 +448,6 @@ void __fastcall Gv_SetVarX(register int32_t id, register int32_t lValue)
VM_AccessSprite(1, index, memberid, lValue); VM_AccessSprite(1, index, memberid, lValue);
return; return;
case M32_SECTOR_VAR_ID: case M32_SECTOR_VAR_ID:
// if (index == vm.g_i) index = sprite[vm.g_i].sectnum;
VM_AccessSector(1, index, memberid, lValue); VM_AccessSector(1, index, memberid, lValue);
return; return;
case M32_WALL_VAR_ID: case M32_WALL_VAR_ID:
@ -441,19 +456,13 @@ void __fastcall Gv_SetVarX(register int32_t id, register int32_t lValue)
case M32_TSPRITE_VAR_ID: case M32_TSPRITE_VAR_ID:
VM_AccessTsprite(1, index, memberid, lValue); VM_AccessTsprite(1, index, memberid, lValue);
return; return;
// default:
// M32_PRINTERROR("Gv_SetVarX(): WTF??");
// return;
} }
} }
case M32_FLAG_VAR:
{
id &= (MAXGAMEVARS-1);
M32_PRINTERROR("Gv_SetVarX(): invalid gamevar ID (%d)", id); switch (aGameVars[id].dwFlags & (GAMEVAR_USER_MASK|GAMEVAR_PTR_MASK))
vm.flags |= VMFLAG_ERROR;
return;
}
switch (aGameVars[id].dwFlags &
(GAMEVAR_USER_MASK|GAMEVAR_INTPTR|GAMEVAR_FLOATPTR|GAMEVAR_SHORTPTR|GAMEVAR_CHARPTR))
{ {
case 0: case 0:
aGameVars[id].val.lValue=lValue; aGameVars[id].val.lValue=lValue;
@ -487,6 +496,14 @@ void __fastcall Gv_SetVarX(register int32_t id, register int32_t lValue)
return; 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[] = static uint8_t alphakeys[] =
{ {
@ -616,6 +633,8 @@ static void Gv_AddSystemVars(void)
g_systemVarCount = g_gameVarCount; g_systemVarCount = g_gameVarCount;
// must be first!
Gv_NewArray(".LOCALS_BASE", NULL, 0, GAMEARRAY_OFINT);
Gv_NewArray("highlight", (void *)highlight, hlcnt_id, Gv_NewArray("highlight", (void *)highlight, hlcnt_id,
GAMEARRAY_READONLY|GAMEARRAY_OFSHORT|GAMEARRAY_VARSIZE); GAMEARRAY_READONLY|GAMEARRAY_OFSHORT|GAMEARRAY_VARSIZE);