From 71e59a5502fcd9a3ba89f140834d0f650a456715 Mon Sep 17 00:00:00 2001 From: helixhorned Date: Wed, 11 Aug 2010 22:37:45 +0000 Subject: [PATCH] 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 --- polymer/eduke32/build/include/editor.h | 2 + polymer/eduke32/build/include/m32script.h | 45 +- polymer/eduke32/build/src/build.c | 19 +- polymer/eduke32/build/src/config.c | 8 +- polymer/eduke32/samples/a.m32 | 247 ++--- polymer/eduke32/samples/tests.m32 | 152 +++ polymer/eduke32/source/astub.c | 112 ++- polymer/eduke32/source/m32def.c | 1057 +++++++++++++-------- polymer/eduke32/source/m32def.h | 16 +- polymer/eduke32/source/m32exec.c | 224 +++-- polymer/eduke32/source/m32structures.c | 27 +- polymer/eduke32/source/m32vars.c | 443 ++++----- 12 files changed, 1395 insertions(+), 957 deletions(-) create mode 100644 polymer/eduke32/samples/tests.m32 diff --git a/polymer/eduke32/build/include/editor.h b/polymer/eduke32/build/include/editor.h index 0d1cf3f35..c68cf0f01 100644 --- a/polymer/eduke32/build/include/editor.h +++ b/polymer/eduke32/build/include/editor.h @@ -62,6 +62,8 @@ extern char *mapster32_fullpath; extern char *testplay_addparam; extern int32_t m32_osd_tryscript; +extern int32_t showheightindicators; +extern int32_t showambiencesounds; extern int32_t ExtInit(void); extern int32_t ExtPreInit(int32_t argc,const char **argv); diff --git a/polymer/eduke32/build/include/m32script.h b/polymer/eduke32/build/include/m32script.h index 62ba98ecb..525b8e8ed 100644 --- a/polymer/eduke32/build/include/m32script.h +++ b/polymer/eduke32/build/include/m32script.h @@ -34,8 +34,8 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. #define MAXQUOTELEN 128 // Some misc #defines -#define NO 0 -#define YES 1 +//#define NO 0 +//#define YES 1 typedef int32_t instype; typedef int32_t ofstype; @@ -59,7 +59,7 @@ extern void Gv_Init(void); extern int32_t __fastcall Gv_GetVarX(register int32_t id); 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 SetWATERPalette(void); @@ -101,6 +101,7 @@ enum GameEvent_t { extern ofstype aEventOffsets[MAXEVENTS]; extern int32_t aEventSizes[MAXEVENTS]; extern uint8_t aEventEnabled[MAXEVENTS]; +extern uint16_t aEventNumLocals[MAXEVENTS]; enum GamevarFlags_t { @@ -109,18 +110,20 @@ enum GamevarFlags_t { MAXVARLABEL = MAXLABELLEN, //26, 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_DEFAULT = 0x00000100, // allow override - GAMEVAR_SECRET = 0x00000200, // don't dump... GAMEVAR_SYSTEM = 0x00000800, // cannot change mode flags...(only default value) GAMEVAR_READONLY = 0x00001000, // values are read-only (no setvar allowed) + GAMEVAR_INTPTR = 0x00002000, // plValues is a pointer to an int32_t GAMEVAR_FLOATPTR = 0x00004000, // plValues is a pointer to a float GAMEVAR_SHORTPTR = 0x00008000, // plValues is a pointer to a short 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_SPECIAL = 0x00040000, // flag for structure member shortcut vars }; @@ -128,13 +131,14 @@ enum GamevarFlags_t { enum GamearrayFlags_t { MAXGAMEARRAYS = (MAXGAMEVARS>>2), // must be lower than MAXGAMEVARS MAXARRAYLABEL = MAXVARLABEL, - GAMEARRAY_NORMAL = 0, + GAMEARRAY_READONLY = 0x00001000, + GAMEARRAY_NORMAL = 0, GAMEARRAY_OFCHAR = 0x00000001, GAMEARRAY_OFSHORT = 0x00000002, GAMEARRAY_OFINT = 0x00000004, - GAMEARRAY_TYPEMASK = 0x00000007, + GAMEARRAY_TYPE_MASK = GAMEARRAY_OFCHAR|GAMEARRAY_OFSHORT|GAMEARRAY_OFINT, GAMEARRAY_VARSIZE = 0x00000020, @@ -169,6 +173,7 @@ extern uint32_t m32_drawlinepat; extern int32_t g_iReturnVar; 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_scriptDebug; @@ -228,9 +233,31 @@ extern int32_t zoom; 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_VAR (0) #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 #define M32_SPRITE_VAR_ID 0 @@ -244,6 +271,8 @@ extern int32_t halfxdim16, midydim16; #define M32_HITAG_VAR_ID 7 #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__) #endif diff --git a/polymer/eduke32/build/src/build.c b/polymer/eduke32/build/src/build.c index da7c799ab..4de2dd746 100644 --- a/polymer/eduke32/build/src/build.c +++ b/polymer/eduke32/build/src/build.c @@ -486,8 +486,6 @@ int32_t app_main(int32_t argc, const char **argv) totalclock = 0; - OSD_Exec("m32_autoexec.cfg"); - updatesector(pos.x,pos.y,&cursectnum); 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); exit(0); } + + // executed once per init, but after setgamemode so that OSD has the right width + OSD_Exec("m32_autoexec.cfg"); + overheadeditor(); 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); 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); } CANCEL: @@ -2463,13 +2469,8 @@ void overheadeditor(void) for (i=0; i 0) 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) 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" "showheightindicators = %d\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" "graphicsmode = %d\n\n" "; Ambient sounds in 3D mode (0:off, 1:on)\n" @@ -499,7 +503,7 @@ int32_t writesetup(const char *fn) #endif option[3], msens, unrealedlook, pk_uedaccel, quickmapcycling, revertCTRL,scrollamount,pk_turnaccel,pk_turndecel,autosave, - showheightindicators,graphicsmode,AmbienceToggle,ParentalLock, + showheightindicators,showambiencesounds,graphicsmode,AmbienceToggle,ParentalLock, !!m32_osd_tryscript, #if 1 keys[0], keys[1], keys[2], keys[3], keys[4], keys[5], diff --git a/polymer/eduke32/samples/a.m32 b/polymer/eduke32/samples/a.m32 index 1c64fd0c1..5ca673549 100644 --- a/polymer/eduke32/samples/a.m32 +++ b/polymer/eduke32/samples/a.m32 @@ -4,7 +4,6 @@ include names.h // flag 1: per-block (top-level, event, or state) variable -gamevar h 0 1 gamevar i 0 1 gamevar j 0 1 gamevar k 0 1 @@ -14,17 +13,9 @@ gamevar p 0 1 gamevar q 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 y 0 0 -gamevar x2 0 0 -gamevar y2 0 0 gamevar z 0 0 -gamevar frac 0 0 gamevar gi 0 0 gamevar gj 0 0 @@ -45,37 +36,16 @@ gamevar dayx 65536 0 gamevar drawcol 9 0 -define TQUOTE 3 -definequote 0 OK -definequote 1 DAMN +define TQUOTE 0 +definequote TQUOTE >>> write on me! <<< -definequote 2 BU:%d ABS:%d -definequote TQUOTE write on me! +//light +define LIGHTQUOTE 1 +// x y z r g b mins maxs +definequote LIGHTQUOTE 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 -definequote 4 ASPECT: VR=%d, YX=%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 -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 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 25 WALL[%d].NEXTSECTOR=%d out of range: numsectors=%d!!! -definequote 26 FLOAT ACCESS TEST - definequote 27 OVERRIDE POLYMER PARALLAX & SPECULAR: OFF 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 -// NOTE: inline constants >=32768 are sometimes broken ATM (when loading a second time?). -// This should always work define MAXSPECULAR 100000 gamearray ar 128 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 defstate printlights - print 10 + print "--PRLIGHTS--" for i allsprites, ifactor SECTOREFFECTOR, ifge .lotag 49, ifle .lotag 50 { ife .lotag 50 @@ -166,13 +88,13 @@ defstate printlights else set l 2 } - // range r g b - qsprintf TQUOTE 9 .sectnum .x .y .z .hitag .xvel .yvel .zvel - j k .ang .extra .xoffset .yoffset l .owner - // radius fade horiz minshade maxshade prio tile + // range r g b + qsprintf TQUOTE LIGHTQUOTE .sectnum .x .y .z .hitag .xvel .yvel .zvel + j k .ang .extra .xoffset .yoffset l .owner + // radius fade horiz minshade maxshade prio tile print TQUOTE } - print 11 + print "--ENDPRLIGHTS--" ends // 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 add k j, clamp k -10000 10000 itof k PRSCALE // convert back - qsprintf TQUOTE 29 k, quote TQUOTE + qsprintf TQUOTE "PARALLAX SCALE: %f" k, quote TQUOTE set pr_parallaxscale k break; } @@ -253,23 +175,23 @@ defstate fiddlewithlights { set k pr_parallaxbias 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 break; } case 3: { set k pr_specularfactor - ftoi k PRSCALE, add k j, clamp k -10000 MAXSPECULAR, itof k PRSCALE - qsprintf TQUOTE 31 k, quote TQUOTE + ftoi k PRSCALE, add k j, clamp k 0 MAXSPECULAR, itof k PRSCALE + qsprintf TQUOTE "SPECULAR FACTOR: %f" k, quote TQUOTE set pr_specularfactor k break; } case 4: { set k pr_specularpower - ftoi k PRSCALE, add k j, clamp k -10000 MAXSPECULAR, itof k PRSCALE - qsprintf TQUOTE 32 k, quote TQUOTE + ftoi k PRSCALE, add k j, clamp k 0 MAXSPECULAR, itof k PRSCALE + qsprintf TQUOTE "SPECULAR POWER: %f" k, quote TQUOTE set pr_specularpower k break; } @@ -282,36 +204,39 @@ defstate fiddlewithlights { set i searchwall, seti i // set current sprite = targeted sprite - // horiz - ifeithershift set j 1 else set j 10 - ifhitkey KEY_gUP add .extra j - else ifhitkey KEY_gKP5 sub .extra j - clamp .extra -500 500 + ife .lotag 50 + { + // horiz + ifeithershift set j 1 else set j 10 + ifhitkey KEY_gUP add .extra j + else ifhitkey KEY_gKP5 sub .extra j + clamp .extra -500 500 - // angle - set j 128 - ifeitherctrl set j 4 - ifeithershift { ifeitherctrl set j 1 else set j 32 } - ifhitkey KEY_gLEFT sub .ang j - else ifhitkey KEY_gRIGHT add .ang j + // angle + set j 128 + ifeitherctrl set j 4 + ifeithershift { ifeitherctrl set j 1 else set j 32 } + ifhitkey KEY_gLEFT sub .ang j + else ifhitkey KEY_gRIGHT add .ang j + + // radius + ifeitherctrl + { + ifholdkey KEY_gMINUS add .shade 9 + else ifholdkey KEY_gPLUS sub .shade 9 + + clamp .shade -118 117 + } + } // 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 + ifhitkey KEY_KP9 add .hitag j + else ifhitkey KEY_KP7 sub .hitag j clamp .hitag 0 16000 - // radius - ifeitherctrl - { - ifholdkey KEY_gMINUS add .shade 9 - else ifholdkey KEY_gPLUS sub .shade 9 - - clamp .shade -118 117 - } - // min/max shade ifeithershift set j -1 else set j 1 ifeitherctrl @@ -330,7 +255,7 @@ defstate fiddlewithlights ife k 1 { - qsprintf TQUOTE 15 .xoffset .yoffset + qsprintf TQUOTE "XY offset: %d %d" .xoffset .yoffset quote TQUOTE } } @@ -338,15 +263,15 @@ defstate fiddlewithlights // color/picnum ifeitheralt { - ifhitkey KEY_gEND + ifhitkey KEY_KP1 { - getnumber256 .xvel 12 255 - getnumber256 .yvel 13 255 - getnumber256 .zvel 14 255 + getnumber256 .xvel "RED:" 255 + getnumber256 .yvel "GREEN:" 255 + getnumber256 .zvel "BLUE:" 255 } - else ifhitkey KEY_gDOWN + else ifhitkey KEY_KP2 { - getnumber256 .owner 17 -MAXTILES + getnumber256 .owner "PICNUM:" -MAXTILES } } else @@ -355,9 +280,9 @@ defstate fiddlewithlights ifeithershift inv j set k 0 - ifhitkey KEY_gEND { add .xvel j, set k 1 } - ifhitkey KEY_gDOWN { add .yvel j, set k 1 } - ifhitkey KEY_gPGDN { add .zvel j, set k 1 } + ifhitkey KEY_KP1 { add .xvel j, set k 1 } + ifhitkey KEY_KP2 { add .yvel j, set k 1 } + ifhitkey KEY_KP3 { add .zvel j, set k 1 } ife k 1 { @@ -365,35 +290,13 @@ defstate fiddlewithlights clamp .yvel 1 255 clamp .zvel 1 255 - qsprintf TQUOTE 16 .xvel .yvel .zvel + qsprintf TQUOTE "RGB color: %d %d %d" .xvel .yvel .zvel quote TQUOTE } } } 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 // global parameter: dang defstate rotselspr @@ -488,7 +391,12 @@ onevent EVENT_DRAW2DSCREEN */ ////////// 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 for i spritesofsector cursectnum { @@ -548,7 +456,7 @@ onevent EVENT_DRAW2DSCREEN } } } - set drawlinepat tmp + set drawlinepat oldpat endevent // LOCATORS auto-incrementer @@ -727,25 +635,6 @@ ends onevent EVENT_ANALYZESPRITES state tduprot 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 onevent EVENT_KEYS3D @@ -790,7 +679,7 @@ onevent EVENT_KEYS3D // } ifn tmp 0 { - quote 7 + quote "door sector not an island sector!" return } @@ -805,7 +694,7 @@ onevent EVENT_KEYS3D } ifl l 0 { - quote 8 + quote "door sector has no SE sprite!" return } @@ -868,7 +757,7 @@ onevent EVENT_KEYS3D ifl davr 32768 set davr 32768 ifg davr 256000 set davr 256000 setaspect davr yxaspect - qsprintf TQUOTE 4 davr yxaspect + qsprintf TQUOTE "ASPECT: VR=%d, YX=%d" davr yxaspect quote TQUOTE } endevent @@ -917,10 +806,10 @@ ends // Map corruption checker -gamevar ewall 0 0 -gamevar endwall 0 0 - defstate corruptchk + var ewall + var endwall + ifle numsectors MAXSECTORS ifle numwalls MAXWALLS nullop else { quote 19 printmessage16 19 return } diff --git a/polymer/eduke32/samples/tests.m32 b/polymer/eduke32/samples/tests.m32 new file mode 100644 index 000000000..5dc737d2e --- /dev/null +++ b/polymer/eduke32/samples/tests.m32 @@ -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 diff --git a/polymer/eduke32/source/astub.c b/polymer/eduke32/source/astub.c index bdba16ca1..9414a56b8 100644 --- a/polymer/eduke32/source/astub.c +++ b/polymer/eduke32/source/astub.c @@ -94,6 +94,8 @@ static struct strllist const char *scripthist[SCRIPTHISTSIZ]; int32_t scripthistend = 0; +int32_t showambiencesounds=2; + //////////////////// Key stuff //////////////////// #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; } -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 ------------ 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")) { - if (showval) - OSD_Printf("UnrealEd mouse navigation acceleration is %d\n", pk_uedaccel); - else + if (parm->numparms==1) { pk_uedaccel = atoi(parm->parms[0]); pk_uedaccel = pk_uedaccel<0 ? 0: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")) { m32_osd_tryscript = !m32_osd_tryscript; 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; } @@ -7615,18 +7639,19 @@ static int32_t registerosdcommands(void) OSD_RegisterFunction("noclip","noclip: toggles clipping mode", osdcmd_noclip); - OSD_RegisterFunction("quit","quit: exits the game immediately", osdcmd_quit); - OSD_RegisterFunction("exit","exit: exits the game immediately", osdcmd_quit); + OSD_RegisterFunction("quit","quit: exits the editor immediately", osdcmd_quit); + OSD_RegisterFunction("exit","exit: exits the editor immediately", osdcmd_quit); OSD_RegisterFunction("sensitivity","sensitivity : changes the mouse sensitivity", osdcmd_sensitivity); //PK - OSD_RegisterFunction("pk_turnaccel", "pk_turnaccel: sets turning acceleration", osdcmd_vars_pk); - OSD_RegisterFunction("pk_turndecel", "pk_turndecel: 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_quickmapcycling", "pk_quickmapcycling: allows 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("showheightindicators", "showheightindicators [012]: toggles height indicators in 2D mode", osdcmd_showheightindicators); + OSD_RegisterFunction("pk_turnaccel", "pk_turnaccel : sets turning acceleration+deceleration", osdcmd_vars_pk); + OSD_RegisterFunction("pk_turndecel", "pk_turndecel : 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_quickmapcycling", "pk_quickmapcycling: toggles quick cycling of maps with (Shift-)Ctrl-X", osdcmd_vars_pk); + OSD_RegisterFunction("testplay_addparam", "testplay_addparam \"string\": sets additional parameters for test playing", osdcmd_testplay_addparam); + 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 OSD_RegisterFunction("tint", "tint : queries or sets hightile tinting", osdcmd_tint); #endif @@ -7634,10 +7659,11 @@ static int32_t registerosdcommands(void) // M32 script OSD_RegisterFunction("include", "include : compiles one or more M32 script files", osdcmd_include); 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 ", osdcmd_endisableevent); OSD_RegisterFunction("disableevent", "disableevent ", 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] ", osdcmd_disasm); return 0; } @@ -9008,22 +9034,26 @@ void ExtPreCheckKeys(void) // just before drawrooms } } - for (i=0; i= 256*/ && sprite[i].sectnum != MAXSECTORS) - { - xp1 = mulscale14(sprite[i].x-pos.x,zoom); - yp1 = mulscale14(sprite[i].y-pos.y,zoom); + if (showambiencesounds) + for (i=0; i= 256*/ && sprite[i].sectnum != MAXSECTORS) + { + if (showambiencesounds==1 && sprite[i].sectnum!=cursectnum) + continue; - radius = mulscale14(sprite[i].hitag,zoom); - col = 6; - if (i+16384 == pointhighlight) - if (totalclock & 32) col += (2<<2); - drawlinepat = 0xf0f0f0f0; - drawcircle16(halfxdim16+xp1, midydim16+yp1, radius, editorcolors[(int32_t)col]); - drawlinepat = 0xffffffff; - // radius = mulscale15(sprite[i].hitag,zoom); - // drawcircle16(halfxdim16+xp1, midydim16+yp1, radius, col); - } + xp1 = mulscale14(sprite[i].x-pos.x,zoom); + yp1 = mulscale14(sprite[i].y-pos.y,zoom); + + radius = mulscale14(sprite[i].hitag,zoom); + col = 6; + if (i+16384 == pointhighlight) + if (totalclock & 32) col += (2<<2); + drawlinepat = 0xf0f0f0f0; + drawcircle16(halfxdim16+xp1, midydim16+yp1, radius, editorcolors[(int32_t)col]); + drawlinepat = 0xffffffff; + // radius = mulscale15(sprite[i].hitag,zoom); + // drawcircle16(halfxdim16+xp1, midydim16+yp1, radius, col); + } enddrawing(); } diff --git a/polymer/eduke32/source/m32def.c b/polymer/eduke32/source/m32def.c index 5ffd6a356..da9d05199 100644 --- a/polymer/eduke32/source/m32def.c +++ b/polymer/eduke32/source/m32def.c @@ -29,10 +29,11 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. #include "keys.h" char g_szScriptFileName[BMAX_PATH] = "(none)"; // file we're currently compiling -static char g_szCurrentBlockName[256] = "(none)", g_szLastBlockName[256] = "NULL"; +static char g_szCurrentBlockName[BMAX_PATH] = "(none)", g_szLastBlockName[BMAX_PATH] = "NULL"; ////// compiler state vvv -static const char *textptr; +static const char *textptr, *start_textptr, *g_curkwptr; +static int32_t g_tw; int32_t g_totalLines, g_lineNumber; int32_t g_numCompilerErrors, g_numCompilerWarnings; @@ -79,7 +80,7 @@ static int32_t statesinfo_allocsize = 512; static int32_t interactive_compilation = 0; static char tempbuf[2048]; -static char tlabel[MAXLABELLEN]; +static char tlabel[MAXLABELLEN], tlabel2[MAXLABELLEN]; int32_t g_iReturnVar=0; int32_t m32_sortvar1, m32_sortvar2; @@ -89,6 +90,7 @@ int32_t g_numQuoteRedefinitions = 0; ofstype aEventOffsets[MAXEVENTS]; int32_t aEventSizes[MAXEVENTS]; +uint16_t aEventNumLocals[MAXEVENTS]; gamevar_t aGameVars[MAXGAMEVARS]; gamearray_t aGameArrays[MAXGAMEARRAYS]; @@ -101,6 +103,7 @@ int32_t g_gameArrayCount=0, g_systemArrayCount=0; void C_ReportError(int32_t iError); +static void PrintErrorPosition(); enum ScriptLabel_t { @@ -506,6 +509,7 @@ const tokenmap_t iter_tokens[] = hashtable_t h_gamevars = { MAXGAMEVARS>>1, NULL }; hashtable_t h_arrays = { MAXGAMEARRAYS>>1, NULL }; hashtable_t h_labels = { 11262>>1, NULL }; +static hashtable_t h_localvars = { MAXGAMEVARS>>2, NULL }; // values: offset|(array?(size<<16):0) static hashtable_t h_states = { 1264>>1, NULL }; static hashtable_t h_keywords = { CON_END>>1, NULL }; @@ -522,6 +526,8 @@ static void C_InitHashes() hash_init(&h_gamevars); hash_init(&h_arrays); + hash_init(&h_localvars); + hash_init(&h_labels); hash_init(&h_states); @@ -550,6 +556,7 @@ static void C_InitHashes() hash_add(&h_iter, iter_tokens[i].token, iter_tokens[i].val, 0); } +// returns: 0:success, 1:failure static int32_t C_SetScriptSize(int32_t size) { ofstype oscriptOfs = (unsigned)(g_scriptPtr-script); @@ -597,15 +604,15 @@ static int32_t C_SetScriptSize(int32_t size) return 0; } -static inline int32_t ispecial(char c) +static inline int32_t char_whitespace(char c) { return c==' ' || c=='\t' || c=='\n' || c=='\r' || c=='(' || c==')' || c==',' || c==';'; } -static inline int32_t isaltok(char c) +static inline int32_t char_alnumtok(char c) { return isalnum(c) || c == '#' || c == '{' || c == '}' || c == '/' || c == '\\' || - c == '*' || c == '-' || c == '_' || c == '.'; + c == '*' || c == '-' || c == '_' || c == '.' || c == '"'; } static int32_t C_SkipComments(void) @@ -614,7 +621,7 @@ static int32_t C_SkipComments(void) do { - if (ispecial(c)) + if (char_whitespace(c)) { textptr++; g_lineNumber += (c=='\n'); @@ -650,7 +657,10 @@ static int32_t C_SkipComments(void) } while ((c = *textptr)); - if ((unsigned)(g_scriptPtr-script) > (unsigned)(g_scriptSize-32)) + // Be sure to have enough space allocated for the command to be parsed next. + // Currently, the commands that potentially need the most space are + // various string handling function that accept inline strings. + if ((unsigned)(g_scriptPtr-script) > (unsigned)(g_scriptSize - max(40, MAXQUOTELEN/sizeof(instype)+8))) return C_SetScriptSize(g_scriptSize<<1); return 0; @@ -668,29 +678,32 @@ static inline int32_t C_GetLabelNameID(const memberlabel_t *pLabel, hashtable_t return l; } -static void C_GetNextLabelName(void) +// returns: 1 on EOF or (checkkeyw and keyword encountered), 0 else +static int32_t C_GetNextLabelName(int32_t checkkeyw) { int32_t i; C_SkipComments(); + tlabel[0] = 0; + if (*textptr == 0) { C_CUSTOMERROR("unexpected EOF where label was expected."); - return; + return 1; } - while (!isalnum(*textptr)) + while (*textptr && (char_whitespace(*textptr) || *textptr=='-')) //!isalnum(*textptr)) { g_lineNumber += (*textptr == 0x0a); - textptr++; - if (!*textptr) - return; } + if (!isalpha(*textptr)) + C_CUSTOMERROR("label names must start with an alphabetic character, encountered '%c'.", *textptr); + i = 0; - while (!ispecial(*textptr) && *textptr!='['&& *textptr!=']') + while (*textptr && !char_whitespace(*textptr) && *textptr!='['&& *textptr!=']') { if (i < MAXLABELLEN-1) tlabel[i++] = *(textptr++); @@ -699,8 +712,21 @@ static void C_GetNextLabelName(void) } tlabel[i] = 0; + + if (checkkeyw) + { + if (hash_find(&h_keywords, tlabel)>=0) + { + g_numCompilerErrors++; + C_ReportError(ERROR_ISAKEYWORD); + return 1; + } + } + // if (!(g_numCompilerErrors || g_numCompilerWarnings) && g_scriptDebug > 1) // initprintf("%s:%d: debug: got label `%s'.\n",g_szScriptFileName,g_lineNumber,tlabel); + + return 0; } static int32_t C_CopyLabel(void) @@ -724,6 +750,7 @@ static int32_t C_CopyLabel(void) return 0; } +// returns: -1 on EOF or not a keyword, keyword index (==bytecode value) else static int32_t C_GetKeyword(void) { int32_t i; @@ -736,15 +763,15 @@ static int32_t C_GetKeyword(void) temptextptr = textptr; - while (!isaltok(*temptextptr)) + while (!char_alnumtok(*temptextptr)) { temptextptr++; if (!*temptextptr) - return 0; + return -1; } i = 0; - while (isaltok(*temptextptr)) + while (char_alnumtok(*temptextptr)) tempbuf[i++] = *(temptextptr++); tempbuf[i] = 0; @@ -762,7 +789,7 @@ static int32_t C_GetNextKeyword(void) if (*textptr == 0) return -1; - while (!isaltok(*textptr)) + while (!char_alnumtok(*textptr)) { g_lineNumber += (*textptr == 0x0a); @@ -773,18 +800,20 @@ static int32_t C_GetNextKeyword(void) } l = 0; - while (isaltok(*(textptr+l)) && !(*(textptr + l) == '.')) + while (char_alnumtok(textptr[l]) && textptr[l] != '.') { tempbuf[l] = textptr[l]; l++; } - while (isaltok(*(textptr+l))) + while (char_alnumtok(textptr[l])) { tempbuf[l] = textptr[l]; l++; } tempbuf[l] = 0; + g_curkwptr = textptr; + textptr += l; i = hash_find(&h_keywords, tempbuf); @@ -839,12 +868,36 @@ static int32_t C_GetNextKeyword(void) return i; } -#define GetGamevarID(szGameLabel) hash_find(&h_gamevars, szGameLabel) -#define GetGamearrayID(szGameLabel) hash_find(&h_arrays, szGameLabel) +static int32_t GetGamevarID(const char *szGameLabel, int32_t searchlocals) +{ + if (searchlocals) + { + int32_t retid = hash_find(&h_localvars, szGameLabel); + if (retid>=0 && retid MAXGAMEVARS) // it's a local array + return retid; + } + return hash_find(&h_arrays, szGameLabel); +} + +// gamevar type restrictions +#define GV_WRITABLE GAMEVAR_READONLY +#define GV_SIMPLE GAMEVAR_SPECIAL static void C_GetNextVarType(int32_t type) { - int32_t i, id=0, flags=0, num, indirect=0; + int32_t i, id=0, flags=0, num, indirect=0; //, thenum; C_SkipComments(); @@ -856,10 +909,20 @@ static void C_GetNextVarType(int32_t type) g_wasConstant = 0; - // constant where gamevar expected - if ((type==0 || type==GAMEVAR_SPECIAL) && !cs.labelsOnly && + if (*textptr == '"') + { + C_CUSTOMERROR("String literal encountered where not expected, skipping."); + while (*textptr && *textptr!='"' && *textptr!=0x0a) + textptr++; + if (*textptr == '"') + textptr++; + return; + } + else if (!(type&GV_WRITABLE) && !cs.labelsOnly && (isdigit(textptr[0]) || (textptr[0]=='-' && isdigit(textptr[1])))) { + // literal numeric constant where gamevar expected + // if (!(g_numCompilerErrors || g_numCompilerWarnings) && g_scriptDebug) // initprintf("%s:%d: debug: accepted constant %d in place of gamevar.\n",g_szScriptFileName,g_lineNumber,atol(textptr)); @@ -867,17 +930,23 @@ static void C_GetNextVarType(int32_t type) sscanf(textptr+2, "%" SCNx32, &num); else num = atoi(textptr); - - if (type==GAMEVAR_SPECIAL && (num<0 || num>=65536)) +//thenum=num; + if (type==GV_SIMPLE && (num<0 || num>=65536)) C_CUSTOMERROR("array index %d out of bounds. (max: 65535)", num); - if (g_numCompilerErrors==0 && type!=GAMEVAR_SPECIAL && num != (int16_t)num) + if (g_numCompilerErrors==0 && type!=GV_SIMPLE && num != (int16_t)num) { + // Constant doesn't fit in 16 bits, make it indirect. + // Array indices are interpreted as unsigned, so they always fit into the high bits of the instruction. + indirect = 1; for (i=g_numSavedConstants-1; i>=0; i--) if (constants[i] == num) + { + num = i; break; + } if (i<0) { @@ -900,38 +969,24 @@ static void C_GetNextVarType(int32_t type) } } - if (type!=GAMEVAR_SPECIAL) + if (type!=GV_SIMPLE) g_wasConstant = 1; - *g_scriptPtr++ = MAXGAMEVARS | (num<<16) | indirect; +//printf("num:%d, idx:%d, indir:%d\n",thenum,num,indirect); + *g_scriptPtr++ = (num<<16) | M32_FLAG_CONSTANT | indirect; - while (!ispecial(*textptr) && *textptr != ']') + while (!char_whitespace(*textptr) && *textptr != ']') textptr++; return; } - else if (textptr[0]=='-' && textptr[1] != '.') // && !isdigit(*(textptr+1)) + else if (type != GV_SIMPLE && (textptr[0]=='.' || (textptr[0]=='-' && textptr[1]=='.'))) { - if (type==0) - { -// if (!(g_numCompilerErrors || g_numCompilerWarnings) && g_scriptDebug) -// initprintf("%s:%d: debug: flagging gamevar as negative.\n",g_szScriptFileName,g_lineNumber,atol(textptr)); - flags = M32_FLAG_NEGATE; - } - else - { - C_CUSTOMERROR("error: syntax error. Tried negating written-to variable."); - C_GetNextLabelName(); - return; - } - } - else if (type != GAMEVAR_SPECIAL && - (textptr[0]=='.' || (textptr[0]=='-' && textptr[1]=='.'))) - { - int32_t lLabelID = -1, aridx = M32_THISACTOR_VAR_ID; + // current sprite shortcut access - flags |= M32_FLAG_SPECIAL; + int32_t lLabelID; + flags = M32_FLAG_STRUCT; if (*textptr=='-') { flags |= M32_FLAG_NEGATE; @@ -941,7 +996,7 @@ static void C_GetNextVarType(int32_t type) /// now pointing at 'xxx' - C_GetNextLabelName(); + C_GetNextLabelName(0); lLabelID = C_GetLabelNameID(SpriteLabels, &h_sprite, Bstrtolower(tlabel)); if (lLabelID == -1) @@ -951,21 +1006,41 @@ static void C_GetNextVarType(int32_t type) return; } - id = M32_SPRITE_VAR_ID; - *g_scriptPtr++ = ((aridx<<16) | id | (lLabelID<<2) | flags); + *g_scriptPtr++ = ((M32_THISACTOR_VAR_ID<<16) | flags | (lLabelID<<2) | M32_SPRITE_VAR_ID); return; } - - C_GetNextLabelName(); - if (hash_find(&h_keywords, tlabel)>=0) + else if (textptr[0]=='-' && textptr[1] != '.') // && !isdigit(*(textptr+1)) { - g_numCompilerErrors++; - C_ReportError(ERROR_ISAKEYWORD); - return; + // negation + + if (type==0) + { +// if (!(g_numCompilerErrors || g_numCompilerWarnings) && g_scriptDebug) +// initprintf("%s:%d: debug: flagging gamevar as negative.\n",g_szScriptFileName,g_lineNumber,atol(textptr)); + flags = M32_FLAG_NEGATE; + } + else + { + if (type==GV_WRITABLE) + C_CUSTOMERROR("syntax error. Tried negating written-to variable."); + else if (type==GV_SIMPLE) + C_CUSTOMERROR("syntax error. Tried negating variable in context that doesn't allow it."); + else // type==GV_WRITABLE|GV_SIMPLE + C_CUSTOMERROR("syntax error. Tried negating written-to variable in context that doesn't allow it."); + + C_GetNextLabelName(1); + + return; + } } + // at this point, flags can be 0 or M32_FLAG_NEGATE + + C_GetNextLabelName(1); + C_SkipComments(); //skip comments and whitespace + if (*textptr == '[') //read of array as a gamevar { int32_t lLabelID = -1, aridx; @@ -973,43 +1048,57 @@ static void C_GetNextVarType(int32_t type) textptr++; flags |= M32_FLAG_ARRAY; - if (type & GAMEVAR_SPECIAL) + if (type & GV_SIMPLE) { g_numCompilerErrors++; C_ReportError(ERROR_EXPECTEDSIMPLEVAR); return; } - id = GetGamearrayID(tlabel); + id = GetGamearrayID(tlabel, 1); if (id < 0) { - id = GetGamevarID(tlabel); - if (id >= 4) - id = -1; + id = GetGamevarID(tlabel, 0); - if (id < 0) + if (id < 0 || id >= 4) { - g_numCompilerErrors++; - C_ReportError(ERROR_NOTAGAMEARRAY); + C_CUSTOMERROR("symbol `%s' is neither an array name nor one of `(t)sprite', `sector' or `wall'.", tlabel); return; } flags &= ~M32_FLAG_ARRAY; // not an array - flags |= M32_FLAG_SPECIAL; + flags |= M32_FLAG_STRUCT; } - else + else if (id>16)&0xffff); // decode... + } + + // ---------- + C_SkipComments(); if (*textptr != ']') @@ -1020,16 +1109,26 @@ static void C_GetNextVarType(int32_t type) } textptr++; - // writing arrays in this way is not supported because it would - // require too many changes to other code -// if (type) -// { -// g_numCompilerErrors++; -// C_ReportError(ERROR_INVALIDARRAYWRITE); -// return; -// } + // ---------- - if (flags & M32_FLAG_SPECIAL) + if ((flags & M32_VARTYPE_MASK) == M32_FLAG_LOCAL) + { + // id: local ofs | (size<<16) + int32_t ar_ofs=id&(MAXGAMEVARS-1), ar_size=(id>>16)&0xffff; + + if (aridx<0 || aridx>=ar_size) + C_CUSTOMERROR("local array index %d out of bounds. Size of local array `%s': %d.", aridx, tlabel2, ar_size); + + *g_scriptPtr++ = (flags|(ar_ofs+aridx)); + } + if ((flags & M32_VARTYPE_MASK) == M32_FLAG_ARRAY) + { + if ((aridx & M32_BITS_MASK) == M32_FLAG_CONSTANTINDEX) + *g_scriptPtr++ = (aridx | flags | id); + else // simple or local gamevar + *g_scriptPtr++ = (aridx<<16 | flags | id); + } + else if ((flags & M32_VARTYPE_MASK) == M32_FLAG_STRUCT) { while (*textptr && *textptr != 0x0a && *textptr != '.') textptr++; @@ -1037,14 +1136,14 @@ static void C_GetNextVarType(int32_t type) if (*textptr != '.') { static const char *types[4] = {"sprite","sector","wall","tsprite"}; - C_CUSTOMERROR("error: syntax error. Expected `.