Subversion Repositories eduke32

Rev

Rev 4911 | Details | Compare with Previous | Last modification | View Log | RSS feed

Rev Author Line No. Line
1493 helixhorne 1
//-------------------------------------------------------------------------
2
/*
1652 terminx 3
Copyright (C) 2010 EDuke32 developers and contributors
1493 helixhorne 4
 
1652 terminx 5
This file is part of EDuke32.
1493 helixhorne 6
 
7
EDuke32 is free software; you can redistribute it and/or
8
modify it under the terms of the GNU General Public License version 2
9
as published by the Free Software Foundation.
10
 
11
This program is distributed in the hope that it will be useful,
12
but WITHOUT ANY WARRANTY; without even the implied warranty of
13
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
14
 
15
See the GNU General Public License for more details.
16
 
17
You should have received a copy of the GNU General Public License
18
along with this program; if not, write to the Free Software
4541 hendricks2 19
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
1493 helixhorne 20
*/
21
//-------------------------------------------------------------------------
22
 
23
#include <time.h>
24
#include <stdlib.h>
25
 
26
#include "m32script.h"
27
#include "m32def.h"
1848 helixhorne 28
 
1538 helixhorne 29
#include "sounds_mapster32.h"
30
#include "fx_man.h"
1493 helixhorne 31
 
32
#include "osd.h"
1497 helixhorne 33
#include "keys.h"
3243 helixhorne 34
#include "common.h"
1493 helixhorne 35
 
1848 helixhorne 36
// from macros.h
37
#define rnd(X) ((krand()>>8)>=(255-(X)))
38
 
1493 helixhorne 39
vmstate_t vm;
40
vmstate_t vm_default =
41
{
1955 helixhorne 42
    -1,   // g_i
43
    0,    // g_st
44
    NULL, // g_sp
45
    0,    // flags
46
    0,    // miscflags
1493 helixhorne 47
};
48
 
49
int32_t g_errorLineNum, g_tw;
50
 
51
uint8_t aEventEnabled[MAXEVENTS];
52
 
1497 helixhorne 53
uint32_t m32_drawlinepat=0xffffffff;
1692 helixhorne 54
int32_t m32_script_expertmode = 0;
1493 helixhorne 55
 
56
instype *insptr;
1625 terminx 57
int32_t VM_Execute(int32_t once);
1499 helixhorne 58
static instype *x_sortingstateptr;
1493 helixhorne 59
 
1722 helixhorne 60
//#include "m32structures.c"
1493 helixhorne 61
 
1698 helixhorne 62
#ifdef DEBUGGINGAIDS
1500 helixhorne 63
void X_Disasm(ofstype beg, int32_t size)
64
{
65
    instype *p;
66
 
67
    if (!script) return;
68
    if (beg<0 || beg+size>g_scriptSize) return;
69
 
70
    initprintf("beg=%d, size=%d:  ", beg, size);
71
    for (p=script+beg; p<script+beg+size; p++)
72
    {
73
        if (*p>>12 && (*p&0xFFF)<CON_END)
74
            initprintf("%s ", keyw[*p&0xFFF]);
75
        else
76
            initprintf("%d ", *p);
77
    }
78
    initprintf("\n");
79
}
1644 helixhorne 80
#endif
1500 helixhorne 81
 
1625 terminx 82
void VM_ScriptInfo(void)
1493 helixhorne 83
{
84
    if (script)
85
    {
86
        instype *p;
87
        if (insptr)
88
            for (p=max(insptr-20,script); p<min(insptr+20, script+g_scriptSize); p++)
89
            {
90
                if (p==insptr) initprintf("<<");
91
 
92
                if (*p>>12 && (*p&0xFFF)<CON_END)
1791 helixhorne 93
                    initprintf("\n%5d: L%5d:  %s ",(int32_t)(p-script),(int32_t)(*p>>12),keyw[*p&0xFFF]);
1493 helixhorne 94
                else initprintf(" %d",*p);
95
 
96
                if (p==insptr) initprintf(">>");
97
            }
98
        initprintf(" \n");
1500 helixhorne 99
        if (vm.g_i >= 0)
1493 helixhorne 100
            initprintf("current sprite: %d\n",vm.g_i);
101
        if (g_tw>=0 && g_tw<CON_END)
102
            initprintf("g_errorLineNum: %d, g_tw: %s\n",g_errorLineNum,keyw[g_tw]);
103
        else
104
            initprintf("g_errorLineNum: %d, g_tw: %d\n",g_errorLineNum,g_tw);
105
    }
106
}
107
 
1955 helixhorne 108
void M32_PostScriptExec(void)
109
{
110
    if (vm.miscflags&VMFLAG_MISC_UPDATEHL)
111
    {
112
        update_highlight();
113
        vm.miscflags &= ~VMFLAG_MISC_UPDATEHL;
114
    }
115
 
116
    if (vm.miscflags&VMFLAG_MISC_UPDATEHLSECT)
117
    {
118
        update_highlightsector();
3823 helixhorne 119
        if (!in3dmode())
1955 helixhorne 120
            ovh_whiteoutgrab(1);
121
        vm.miscflags &= ~VMFLAG_MISC_UPDATEHLSECT;
122
    }
123
}
124
 
1625 terminx 125
void VM_OnEvent(register int32_t iEventID, register int32_t iActor)
1493 helixhorne 126
{
127
    if (iEventID < 0 || iEventID >= MAXEVENTS)
128
    {
1661 helixhorne 129
        M32_PRINTERROR("Invalid event ID");
1493 helixhorne 130
        return;
131
    }
132
 
133
    if (aEventOffsets[iEventID] < 0 || !aEventEnabled[iEventID])
134
    {
135
        //Bsprintf(g_szBuf,"No event found for %d",iEventID);
136
        //AddLog(g_szBuf);
137
        return;
138
    }
139
 
140
    {
4798 helixhorne 141
        instype *const oinsptr=insptr;
1493 helixhorne 142
        vmstate_t vm_backup;
4798 helixhorne 143
        void *const olocalvars = aGameArrays[M32_LOCAL_ARRAY_ID].vals;
1692 helixhorne 144
#ifdef M32_LOCALS_VARARRAY
145
        int32_t localvars[aEventNumLocals[iEventID]];
146
#else
147
        int32_t localvars[M32_LOCALS_FIXEDNUM];
148
#endif
1493 helixhorne 149
 
4357 helixhorne 150
        // Initialize 'state'-local variables to 0.
1691 helixhorne 151
        if (aEventNumLocals[iEventID] > 0)
1695 helixhorne 152
            Bmemset(localvars, 0, aEventNumLocals[iEventID]*sizeof(int32_t));
1691 helixhorne 153
 
1493 helixhorne 154
        Bmemcpy(&vm_backup, &vm, sizeof(vmstate_t));
155
 
156
        vm.g_i = iActor;    // current sprite ID
157
        if (vm.g_i >= 0)
4911 terminx 158
            vm.g_sp = (tspritetype *)&sprite[vm.g_i];
1493 helixhorne 159
 
160
        vm.g_st = 1+iEventID;
161
 
1528 helixhorne 162
        vm.flags = 0;
1493 helixhorne 163
 
164
        insptr = script + aEventOffsets[iEventID];
1691 helixhorne 165
 
166
        aGameArrays[M32_LOCAL_ARRAY_ID].vals = localvars;
1625 terminx 167
        VM_Execute(0);
1691 helixhorne 168
        aGameArrays[M32_LOCAL_ARRAY_ID].vals = olocalvars;
1493 helixhorne 169
 
1528 helixhorne 170
        if (vm.flags&VMFLAG_ERROR)
1499 helixhorne 171
        {
1493 helixhorne 172
            aEventEnabled[iEventID] = 0;
1499 helixhorne 173
            message("ERROR executing %s. Event disabled.", label+(iEventID*MAXLABELLEN));
174
        }
1493 helixhorne 175
 
1955 helixhorne 176
        M32_PostScriptExec();
1710 helixhorne 177
 
1493 helixhorne 178
        // restore old values...
179
        Bmemcpy(&vm, &vm_backup, sizeof(vmstate_t));
180
        insptr = oinsptr;
181
 
182
        //AddLog("End of Execution");
183
    }
184
}
185
 
186
static int32_t G_GetAngleDelta(int32_t a,int32_t na)
187
{
188
    a &= 2047;
189
    na &= 2047;
190
 
191
    if (klabs(a-na) < 1024)
192
    {
193
//        OSD_Printf("G_GetAngleDelta() returning %d\n",na-a);
194
        return (na-a);
195
    }
196
 
197
    if (na > 1024) na -= 2048;
198
    if (a > 1024) a -= 2048;
199
 
200
//    OSD_Printf("G_GetAngleDelta() returning %d\n",na-a);
201
    return (na-a);
202
}
203
 
1625 terminx 204
static inline void __fastcall VM_DoConditional(register int32_t condition)
1493 helixhorne 205
{
206
    if (condition)
207
    {
208
        // skip 'else' pointer.. and...
209
        insptr+=2;
1625 terminx 210
        VM_Execute(1);
1493 helixhorne 211
        return;
212
    }
213
 
214
    insptr++;
215
    insptr += *insptr;
216
    if (((*insptr)&0xFFF) == CON_ELSE)
217
    {
218
        // else...
219
        // skip 'else' and...
220
        insptr+=2;
1625 terminx 221
        VM_Execute(1);
1493 helixhorne 222
    }
223
}
224
 
4068 helixhorne 225
static int X_DoSortDefault(const void *lv, const void *rv)
1499 helixhorne 226
{
4068 helixhorne 227
    return *(int32_t *)rv - *(int32_t *)lv;
1499 helixhorne 228
}
229
 
4068 helixhorne 230
static int X_DoSort(const void *lv, const void *rv)
1499 helixhorne 231
{
4068 helixhorne 232
    m32_sortvar1 = *(int32_t *)lv;
233
    m32_sortvar2 = *(int32_t *)rv;
1499 helixhorne 234
    insptr = x_sortingstateptr;
1625 terminx 235
    VM_Execute(0);
1499 helixhorne 236
    return g_iReturnVar;
237
}
238
 
1697 helixhorne 239
// in interactive execution, allow the current sprite index to be the aimed-at sprite (in 3d mode)
4911 terminx 240
#define X_ERROR_INVALIDCI()                                                                                            \
241
    if ((vm.g_i < 0 || vm.g_i >= MAXSPRITES) &&                                                                        \
242
        (vm.g_st != 0 || searchstat != 3 || (vm.g_i = searchwall, vm.g_sp = (tspritetype *)&sprite[vm.g_i], 0)))       \
243
    {                                                                                                                  \
244
        M32_ERROR("Current sprite index invalid!");                                                                    \
245
        continue;                                                                                                      \
1493 helixhorne 246
    }
247
 
248
#define X_ERROR_INVALIDSPRI(dasprite)                                   \
249
    if (dasprite < 0 || dasprite>=MAXSPRITES)                           \
250
    {                                                                   \
1877 helixhorne 251
        M32_ERROR("Invalid sprite index %d!",  dasprite); \
1493 helixhorne 252
        continue;                                                       \
253
    }
254
 
255
#define X_ERROR_INVALIDSECT(dasect)                                     \
256
    if (dasect < 0 || dasect>=numsectors)                               \
257
    {                                                                   \
1877 helixhorne 258
        M32_ERROR("Invalid sector index %d!",  dasect); \
1493 helixhorne 259
        continue;                                                       \
260
    }
261
 
4911 terminx 262
#define X_ERROR_INVALIDSP()                                                                                            \
263
    if (!vm.g_sp && (vm.g_st != 0 || searchstat != 3 || (vm.g_sp = (tspritetype *)&sprite[searchwall], 0)))            \
264
    {                                                                                                                  \
265
        M32_ERROR("Current sprite invalid!");                                                                          \
266
        continue;                                                                                                      \
1493 helixhorne 267
    }
268
 
1497 helixhorne 269
#define X_ERROR_INVALIDQUOTE(q, array)                                  \
270
    if (q<0 || q>=MAXQUOTES)                                            \
271
    {                                                                   \
1877 helixhorne 272
        M32_ERROR("Invalid quote number %d!",  q); \
1497 helixhorne 273
        continue;                                                       \
274
    }                                                                   \
275
    else if (array[q] == NULL)                                          \
276
    {                                                                   \
1877 helixhorne 277
        M32_ERROR("Null quote %d!",  q); \
1497 helixhorne 278
        continue;                                                       \
279
    }                                                                   \
1691 helixhorne 280
 
281
static char *GetMaybeInlineQuote(int32_t quotei)
282
{
283
    char *quotetext;
284
    if (quotei==-1)
285
    {
286
        quotetext = (char *)insptr;
287
        while (*insptr++) /* skip the string */;
288
    }
289
    else
290
    {
291
        quotei = Gv_GetVarX(quotei);
292
        do { X_ERROR_INVALIDQUOTE(quotei, ScriptQuotes) } while (0);
293
        if (vm.flags&VMFLAG_ERROR)
294
            return NULL;
295
        quotetext = ScriptQuotes[quotei];
296
    }
297
 
298
    return quotetext;
299
}
4798 helixhorne 300
 
301
static int CheckArray(int aidx)
302
{
303
    if (!(aidx >= 0 && aidx < g_gameArrayCount))
304
        M32_ERROR("Invalid array %d!", aidx);
305
 
306
    return (vm.flags&VMFLAG_ERROR);
307
}
308
 
1625 terminx 309
int32_t VM_Execute(int32_t once)
1493 helixhorne 310
{
311
    register int32_t tw = *insptr;
312
 
313
    // jump directly into the loop, saving us from the checks during the first iteration
314
    goto skip_check;
315
 
316
    while (!once)
317
    {
1528 helixhorne 318
        if (vm.flags)
1493 helixhorne 319
            return 1;
320
 
321
        tw = *insptr;
322
 
323
skip_check:
324
        //      Bsprintf(g_szBuf,"Parsing: %d",*insptr);
325
        //      AddLog(g_szBuf);
326
 
327
        g_errorLineNum = tw>>12;
328
        g_tw = (tw &= 0xFFF);
329
 
330
        switch (tw)
331
        {
332
// *** basic commands
333
        case CON_NULLOP:
334
            insptr++;
335
            continue;
336
 
337
        case CON_STATE:
338
        {
4798 helixhorne 339
            instype *const tempscrptr = insptr+2;
340
            const int32_t stateidx = *(insptr+1), o_g_st = vm.g_st, oret=vm.flags&VMFLAG_RETURN;
341
            void *const olocalvars = aGameArrays[M32_LOCAL_ARRAY_ID].vals;
1692 helixhorne 342
#ifdef M32_LOCALS_VARARRAY
343
            int32_t localvars[statesinfo[stateidx].numlocals];
344
#else
345
            int32_t localvars[M32_LOCALS_FIXEDNUM];
346
#endif
1493 helixhorne 347
 
1691 helixhorne 348
            // needed since any read access before initialization would cause undefined behaviour
349
            if (statesinfo[stateidx].numlocals > 0)
1695 helixhorne 350
                Bmemset(localvars, 0, statesinfo[stateidx].numlocals*sizeof(int32_t));
1691 helixhorne 351
 
1493 helixhorne 352
            insptr = script + statesinfo[stateidx].ofs;
353
            vm.g_st = 1+MAXEVENTS+stateidx;
1691 helixhorne 354
            aGameArrays[M32_LOCAL_ARRAY_ID].vals = localvars;
1625 terminx 355
            VM_Execute(0);
1691 helixhorne 356
            aGameArrays[M32_LOCAL_ARRAY_ID].vals = olocalvars;
1493 helixhorne 357
            vm.g_st = o_g_st;
1528 helixhorne 358
            vm.flags &= ~VMFLAG_RETURN;
359
            vm.flags |= oret;
1493 helixhorne 360
            insptr = tempscrptr;
361
        }
362
        continue;
363
 
364
        case CON_RETURN:
1528 helixhorne 365
            vm.flags |= VMFLAG_RETURN;
366
            return 1;
1493 helixhorne 367
        case CON_BREAK:
1528 helixhorne 368
            vm.flags |= VMFLAG_BREAK;
4880 helixhorne 369
            // XXX: may not be cleared subsequently?
1493 helixhorne 370
        case CON_ENDS:
371
            return 1;
372
 
373
        case CON_ELSE:
374
            insptr++;
375
            insptr += *insptr;
376
            continue;
377
 
378
        case CON_ENDSWITCH:
1528 helixhorne 379
            vm.flags &= ~VMFLAG_BREAK;
1493 helixhorne 380
        case CON_ENDEVENT:
381
            insptr++;
382
            return 1;
383
 
384
        case CON_SWITCH:
385
            insptr++; // p-code
386
            {
387
                // command format:
388
                // variable ID to check
389
                // script offset to 'end'
390
                // count of case statements
391
                // script offset to default case (null if none)
392
                // For each case: value, ptr to code
393
                //AddLog("Processing Switch...");
394
                int32_t lValue=Gv_GetVarX(*insptr++), lEnd=*insptr++, lCases=*insptr++;
395
                instype *lpDefault=insptr++, *lpCases=insptr, *lCodeInsPtr;
396
                int32_t bMatched=0, lCheckCase;
397
                int32_t left,right;
398
 
399
                insptr += lCases*2;
400
                lCodeInsPtr = insptr;
1593 terminx 401
                //Bsprintf(g_szBuf,"lEnd= %d *lpDefault=%d",lEnd,*lpDefault); AddLog(g_szBuf);
402
                //Bsprintf(g_szBuf,"Checking %d cases for %d",lCases, lValue); AddLog(g_szBuf);
1493 helixhorne 403
                left = 0;
404
                right = lCases-1;
405
                while (!bMatched)
406
                {
1593 terminx 407
                    //Bsprintf(g_szBuf,"Checking #%d Value= %d",lCheckCase, lpCases[lCheckCase*2]); AddLog(g_szBuf);
1493 helixhorne 408
                    lCheckCase=(left+right)/2;
1593 terminx 409
                    //                initprintf("(%2d..%2d..%2d) [%2d..%2d..%2d]==%2d\n",left,lCheckCase,right,lpCases[left*2],lpCases[lCheckCase*2],lpCases[right*2],lValue);
1493 helixhorne 410
                    if (lpCases[lCheckCase*2] > lValue)
411
                        right = lCheckCase-1;
412
                    else if (lpCases[lCheckCase*2] < lValue)
413
                        left = lCheckCase+1;
414
                    else if (lpCases[lCheckCase*2] == lValue)
415
                    {
416
                        //AddLog("Found Case Match");
1593 terminx 417
                        //Bsprintf(g_szBuf,"insptr=%d. lCheckCase=%d, offset=%d, &script[0]=%d", (int32_t)insptr,(int32_t)lCheckCase,lpCases[lCheckCase*2+1],(int32_t)&script[0]); AddLog(g_szBuf);
1493 helixhorne 418
                        // fake a 2-d Array
419
                        insptr = lCodeInsPtr + lpCases[lCheckCase*2+1];
1593 terminx 420
                        //Bsprintf(g_szBuf,"insptr=%d. ",     (int32_t)insptr); AddLog(g_szBuf);
1625 terminx 421
                        VM_Execute(0);
1493 helixhorne 422
                        //AddLog("Done Executing Case");
423
                        bMatched=1;
424
                    }
1799 helixhorne 425
 
1493 helixhorne 426
                    if (right-left < 0)
427
                        break;
428
                }
1799 helixhorne 429
 
1493 helixhorne 430
                if (!bMatched)
431
                {
432
                    if (*lpDefault >= 0)
433
                    {
434
                        //AddLog("No Matching Case: Using Default");
435
                        insptr = lCodeInsPtr + *lpDefault;
1625 terminx 436
                        VM_Execute(0);
1493 helixhorne 437
                    }
438
//                    else
439
//                    {
440
//                        //AddLog("No Matching Case: No Default to use");
441
//                    }
442
                }
1499 helixhorne 443
                insptr = (instype *)(lCodeInsPtr + lEnd);
1955 helixhorne 444
                vm.flags &= ~VMFLAG_BREAK;
1593 terminx 445
                //Bsprintf(g_szBuf,"insptr=%d. ",     (int32_t)insptr); AddLog(g_szBuf);
1493 helixhorne 446
                //AddLog("Done Processing Switch");
447
                continue;
448
            }
449
 
450
        case CON_GETCURRADDRESS:
451
            insptr++;
452
            {
453
                int32_t j=*insptr++;
454
                Gv_SetVarX(j, insptr-script);
455
            }
456
            continue;
457
 
458
        case CON_JUMP:
459
            insptr++;
460
            {
461
                int32_t j = Gv_GetVarX(*insptr++);
462
                if (j<0 || j>=(g_scriptPtr-script))
463
                {
1877 helixhorne 464
                    M32_ERROR("script index out of bounds (%d)",  j);
1493 helixhorne 465
                    continue;
466
                }
467
                insptr = (instype *)(j+script);
468
            }
469
            continue;
470
 
471
        case CON_RIGHTBRACE:
472
            insptr++;
473
            return 1;
474
        case CON_LEFTBRACE:
475
            insptr++;
1625 terminx 476
            VM_Execute(0);
1493 helixhorne 477
            continue;
478
 
479
// *** arrays
480
        case CON_SETARRAY:
481
            insptr++;
482
            {
4798 helixhorne 483
                const int32_t j=*insptr++;
484
                const int32_t index = Gv_GetVarX(*insptr++);
485
                const int32_t value = Gv_GetVarX(*insptr++);
1493 helixhorne 486
 
4798 helixhorne 487
                CheckArray(j);
488
 
1493 helixhorne 489
                if (aGameArrays[j].dwFlags & GAMEARRAY_READONLY)
4798 helixhorne 490
                    M32_ERROR("Tried to set on read-only array `%s'", aGameArrays[j].szLabel);
491
 
492
                if (!(index >= 0 && index < aGameArrays[j].size))
493
                    M32_ERROR("Array index %d out of bounds", index);
494
 
495
                if (vm.flags&VMFLAG_ERROR)
496
                    continue;
497
 
498
                // NOTE: Other array types not implemented, since they're read-only.
499
                ((int32_t *)aGameArrays[j].vals)[index] = value;
1493 helixhorne 500
                continue;
501
            }
502
 
503
        case CON_GETARRAYSIZE:
504
            insptr++;
505
            {
4798 helixhorne 506
                const int32_t j=*insptr++;
507
 
508
                if (CheckArray(j))
509
                    continue;
510
 
511
                Gv_SetVarX(*insptr++, Gv_GetArraySize(j));
1493 helixhorne 512
            }
513
            continue;
514
 
515
        case CON_RESIZEARRAY:
516
            insptr++;
517
            {
4798 helixhorne 518
                const int32_t j=*insptr++;
519
                const int32_t asize = Gv_GetVarX(*insptr++);
1499 helixhorne 520
 
4798 helixhorne 521
                CheckArray(j);
522
 
523
                if (aGameArrays[j].dwFlags & GAMEARRAY_READONLY)
524
                    M32_ERROR("Tried to resize read-only array `%s'", aGameArrays[j].szLabel);
525
 
526
                if (!(asize >= 1 && asize <= 65536))
1877 helixhorne 527
                    M32_ERROR("Invalid array size %d (must be between 1 and 65536)", asize);
4798 helixhorne 528
 
529
                if (vm.flags&VMFLAG_ERROR)
1528 helixhorne 530
                    continue;
1493 helixhorne 531
 
532
//                OSD_Printf(OSDTEXT_GREEN "CON_RESIZEARRAY: resizing array %s from %d to %d\n", aGameArrays[j].szLabel, aGameArrays[j].size, asize);
4491 helixhorne 533
                aGameArrays[j].vals = Xrealloc(aGameArrays[j].vals, sizeof(int32_t) * asize);
1493 helixhorne 534
                aGameArrays[j].size = asize;
535
 
536
                continue;
537
            }
538
 
539
        case CON_COPY:
540
            insptr++;
541
            {
4798 helixhorne 542
                const int32_t si=*insptr++;
543
                int32_t sidx = Gv_GetVarX(*insptr++);
544
                const int32_t di=*insptr++;
1493 helixhorne 545
                int32_t didx = Gv_GetVarX(*insptr++);
546
                int32_t numelts = Gv_GetVarX(*insptr++);
547
 
4798 helixhorne 548
                CheckArray(si);
549
                CheckArray(di);
550
 
1493 helixhorne 551
                if (aGameArrays[di].dwFlags & GAMEARRAY_READONLY)
1877 helixhorne 552
                    M32_ERROR("Array %d is read-only!", di);
4798 helixhorne 553
                if (vm.flags&VMFLAG_ERROR)
554
                    continue;
1493 helixhorne 555
 
4798 helixhorne 556
                const int32_t ssiz = Gv_GetArraySize(si);
557
                const int32_t dsiz = Gv_GetArraySize(di);
1493 helixhorne 558
 
4799 helixhorne 559
                if ((uint32_t)sidx >= (uint32_t)ssiz)
560
                    M32_ERROR("Invalid source index %d", sidx);
561
                if ((uint32_t)didx >= (uint32_t)dsiz)
562
                    M32_ERROR("Invalid destination index %d", didx);
563
                if (vm.flags&VMFLAG_ERROR)
4798 helixhorne 564
                    continue;
4799 helixhorne 565
 
4798 helixhorne 566
                if (numelts > ssiz-sidx)
567
                    numelts = ssiz-sidx;
568
                if (numelts > dsiz-didx)
569
                    numelts = dsiz-didx;
570
 
4799 helixhorne 571
                const gamearray_t *const sar = &aGameArrays[si];
572
                gamearray_t *const dar = &aGameArrays[di];
573
 
574
                switch (sar->dwFlags & GAMEARRAY_TYPE_MASK)
1493 helixhorne 575
                {
576
                case 0:
577
                case GAMEARRAY_OFINT:
4799 helixhorne 578
                    if (sar->dwFlags & GAMEARRAY_STRIDE2)
579
                    {
580
                        for (; numelts>0; numelts--, sidx += 2)
581
                            ((int32_t *)dar->vals)[didx++] = ((int32_t *)sar->vals)[sidx];
582
                    }
583
                    else
584
                    {
585
                        Bmemcpy((int32_t *)dar->vals + didx, (int32_t *)sar->vals + sidx,
586
                                numelts * sizeof(int32_t));
587
                    }
1493 helixhorne 588
                    break;
589
                case GAMEARRAY_OFSHORT:
590
                    for (; numelts>0; numelts--)
4799 helixhorne 591
                        ((int32_t *)dar->vals)[didx++] = ((int16_t *)sar->vals)[sidx++];
1493 helixhorne 592
                    break;
593
                case GAMEARRAY_OFCHAR:
594
                    for (; numelts>0; numelts--)
4799 helixhorne 595
                        ((int32_t *)dar->vals)[didx++] = ((uint8_t *)sar->vals)[sidx++];
1493 helixhorne 596
                    break;
597
                }
598
                continue;
599
            }
600
 
601
// *** var & varvar ops
602
        case CON_RANDVAR:
603
            insptr++;
604
            Gv_SetVarX(*insptr, mulscale16(krand(), *(insptr+1)+1));
605
            insptr += 2;
606
            continue;
607
 
608
        case CON_DISPLAYRANDVAR:
609
            insptr++;
2105 helixhorne 610
            Gv_SetVarX(*insptr, mulscale15(system_15bit_rand(), *(insptr+1)+1));
1493 helixhorne 611
            insptr += 2;
612
            continue;
613
 
614
        case CON_SETVAR:
615
            insptr++;
616
            Gv_SetVarX(*insptr, *(insptr+1));
617
            insptr += 2;
618
            continue;
619
 
620
        case CON_SETVARVAR:
621
            insptr++;
622
            {
623
                int32_t j=*insptr++;
624
                Gv_SetVarX(j, Gv_GetVarX(*insptr++));
625
            }
626
            continue;
627
 
628
        case CON_MULVAR:
629
            insptr++;
630
            Gv_SetVarX(*insptr, Gv_GetVarX(*insptr) * *(insptr+1));
631
            insptr += 2;
632
            continue;
633
 
634
        case CON_DIVVAR:
635
            insptr++;
636
            if (*(insptr+1) == 0)
637
            {
1877 helixhorne 638
                M32_ERROR("Divide by zero.");
1493 helixhorne 639
                insptr += 2;
640
                continue;
641
            }
642
            Gv_SetVarX(*insptr, Gv_GetVarX(*insptr) / *(insptr+1));
643
            insptr += 2;
644
            continue;
645
 
646
        case CON_MODVAR:
647
            insptr++;
648
            if (*(insptr+1) == 0)
649
            {
1877 helixhorne 650
                M32_ERROR("Mod by zero.");
1493 helixhorne 651
                insptr += 2;
652
                continue;
653
            }
654
            Gv_SetVarX(*insptr,Gv_GetVarX(*insptr)%*(insptr+1));
655
            insptr += 2;
656
            continue;
657
 
658
        case CON_ANDVAR:
659
            insptr++;
660
            Gv_SetVarX(*insptr,Gv_GetVarX(*insptr) & *(insptr+1));
661
            insptr += 2;
662
            continue;
663
 
664
        case CON_ORVAR:
665
            insptr++;
666
            Gv_SetVarX(*insptr,Gv_GetVarX(*insptr) | *(insptr+1));
667
            insptr += 2;
668
            continue;
669
 
670
        case CON_XORVAR:
671
            insptr++;
672
            Gv_SetVarX(*insptr,Gv_GetVarX(*insptr) ^ *(insptr+1));
673
            insptr += 2;
674
            continue;
675
 
676
        case CON_RANDVARVAR:
677
            insptr++;
678
            {
679
                int32_t j=*insptr++;
2105 helixhorne 680
                Gv_SetVarX(j,mulscale16(krand(), Gv_GetVarX(*insptr++)+1));
1493 helixhorne 681
            }
682
            continue;
683
 
684
        case CON_DISPLAYRANDVARVAR:
685
            insptr++;
686
            {
687
                int32_t j=*insptr++;
2105 helixhorne 688
                Gv_SetVarX(j,mulscale15(system_15bit_rand(), Gv_GetVarX(*insptr++)+1));
1493 helixhorne 689
            }
690
            continue;
691
 
692
        case CON_MULVARVAR:
693
            insptr++;
694
            {
695
                int32_t j=*insptr++;
696
                Gv_SetVarX(j, Gv_GetVarX(j)*Gv_GetVarX(*insptr++));
697
            }
698
            continue;
699
 
700
        case CON_DIVVARVAR:
701
            insptr++;
702
            {
703
                int32_t j=*insptr++;
704
                int32_t l2=Gv_GetVarX(*insptr++);
705
 
706
                if (l2==0)
707
                {
1877 helixhorne 708
                    M32_ERROR("Divide by zero.");
1493 helixhorne 709
                    continue;
710
                }
711
                Gv_SetVarX(j, Gv_GetVarX(j)/l2);
712
                continue;
713
            }
714
 
715
        case CON_MODVARVAR:
716
            insptr++;
717
            {
718
                int32_t j=*insptr++;
719
                int32_t l2=Gv_GetVarX(*insptr++);
720
 
721
                if (l2==0)
722
                {
1877 helixhorne 723
                    M32_ERROR("Mod by zero.");
1493 helixhorne 724
                    continue;
725
                }
726
 
727
                Gv_SetVarX(j, Gv_GetVarX(j) % l2);
728
                continue;
729
            }
730
 
731
        case CON_ANDVARVAR:
732
            insptr++;
733
            {
734
                int32_t j=*insptr++;
735
                Gv_SetVarX(j, Gv_GetVarX(j) & Gv_GetVarX(*insptr++));
736
            }
737
            continue;
738
 
739
        case CON_XORVARVAR:
740
            insptr++;
741
            {
742
                int32_t j=*insptr++;
743
                Gv_SetVarX(j, Gv_GetVarX(j) ^ Gv_GetVarX(*insptr++));
744
            }
745
            continue;
746
 
747
        case CON_ORVARVAR:
748
            insptr++;
749
            {
750
                int32_t j=*insptr++;
751
                Gv_SetVarX(j, Gv_GetVarX(j) | Gv_GetVarX(*insptr++));
752
            }
753
            continue;
754
 
755
        case CON_SUBVAR:
756
            insptr++;
757
            Gv_SetVarX(*insptr, Gv_GetVarX(*insptr) - *(insptr+1));
758
            insptr += 2;
759
            continue;
760
 
761
        case CON_SUBVARVAR:
762
            insptr++;
763
            {
764
                int32_t j=*insptr++;
765
                Gv_SetVarX(j, Gv_GetVarX(j) - Gv_GetVarX(*insptr++));
766
            }
767
            continue;
768
 
769
        case CON_ADDVAR:
770
            insptr++;
771
            Gv_SetVarX(*insptr, Gv_GetVarX(*insptr) + *(insptr+1));
772
            insptr += 2;
773
            continue;
774
 
775
        case CON_ADDVARVAR:
776
            insptr++;
777
            {
778
                int32_t j=*insptr++;
779
                Gv_SetVarX(j, Gv_GetVarX(j) + Gv_GetVarX(*insptr++));
780
            }
781
            continue;
782
 
783
        case CON_SHIFTVARL:
784
            insptr++;
785
            Gv_SetVarX(*insptr, Gv_GetVarX(*insptr) << *(insptr+1));
786
            insptr += 2;
787
            continue;
788
 
1710 helixhorne 789
        case CON_SHIFTVARVARL:
790
            insptr++;
791
            {
792
                int32_t j=*insptr++;
793
                Gv_SetVarX(j, Gv_GetVarX(j) << Gv_GetVarX(*insptr++));
794
            }
795
            continue;
796
 
1493 helixhorne 797
        case CON_SHIFTVARR:
798
            insptr++;
799
            Gv_SetVarX(*insptr, Gv_GetVarX(*insptr) >> *(insptr+1));
800
            insptr += 2;
801
            continue;
802
 
1710 helixhorne 803
        case CON_SHIFTVARVARR:
804
            insptr++;
805
            {
806
                int32_t j=*insptr++;
807
                Gv_SetVarX(j, Gv_GetVarX(j) >> Gv_GetVarX(*insptr++));
808
            }
809
            continue;
810
 
1493 helixhorne 811
        case CON_SIN:
812
            insptr++;
813
            Gv_SetVarX(*insptr, sintable[Gv_GetVarX(*(insptr+1))&2047]);
814
            insptr += 2;
815
            continue;
816
 
817
        case CON_COS:
818
            insptr++;
819
            Gv_SetVarX(*insptr, sintable[(Gv_GetVarX(*(insptr+1))+512)&2047]);
820
            insptr += 2;
821
            continue;
822
 
823
        case CON_DISPLAYRAND:
824
            insptr++;
2105 helixhorne 825
            Gv_SetVarX(*insptr++, system_15bit_rand());
1493 helixhorne 826
            continue;
827
 
828
// *** other math
1644 helixhorne 829
        case CON_FTOI:
830
            insptr++;
831
            {
832
                int32_t bits=Gv_GetVarX(*insptr), scale=*(insptr+1);
1677 terminx 833
                float fval = *((float *)&bits);
1696 helixhorne 834
// rounding must absolutely be!
835
//OSD_Printf("ftoi: bits:%8x, scale=%d, fval=%f, (int32_t)(fval*scale)=%d\n", bits, scale, fval, (int32_t)(fval*scale));
4658 terminx 836
                Gv_SetVarX(*insptr, (int32_t)Blrintf(fval * scale));
1644 helixhorne 837
            }
838
            insptr += 2;
839
            continue;
840
 
841
        case CON_ITOF:
842
            insptr++;
843
            {
844
                int32_t scaled=Gv_GetVarX(*insptr), scale=*(insptr+1);
1648 helixhorne 845
                float fval = (float)scaled/(float)scale;
1644 helixhorne 846
                Gv_SetVarX(*insptr, *((int32_t *)&fval));
847
            }
848
            insptr += 2;
849
            continue;
850
 
1521 helixhorne 851
        case CON_CLAMP:
852
            insptr++;
853
            {
854
                int32_t var=*insptr++, min=Gv_GetVarX(*insptr++), max=Gv_GetVarX(*insptr++);
855
                int32_t val=Gv_GetVarX(var);
856
 
857
                if (val<min) Gv_SetVarX(var, min);
858
                else if (val>max) Gv_SetVarX(var, max);
859
            }
860
            continue;
861
 
1493 helixhorne 862
        case CON_INV:
863
            Gv_SetVarX(*(insptr+1), -Gv_GetVarX(*(insptr+1)));
864
            insptr += 2;
865
            continue;
866
 
867
        case CON_SQRT:
868
            insptr++;
869
            {
870
                // syntax sqrt <invar> <outvar>
871
                int32_t lInVarID=*insptr++, lOutVarID=*insptr++;
872
 
2791 helixhorne 873
                Gv_SetVarX(lOutVarID, ksqrt((uint32_t)Gv_GetVarX(lInVarID)));
1493 helixhorne 874
                continue;
875
            }
876
 
877
        case CON_LDIST:
878
        case CON_DIST:
879
            insptr++;
880
            {
881
                int32_t distvar = *insptr++, xvar = Gv_GetVarX(*insptr++), yvar = Gv_GetVarX(*insptr++);
882
 
883
                if (xvar < 0 || xvar >= MAXSPRITES || sprite[xvar].statnum==MAXSTATUS)
884
                {
1877 helixhorne 885
                    M32_ERROR("invalid sprite %d", xvar);
1493 helixhorne 886
                }
887
                if (yvar < 0 || yvar >= MAXSPRITES || sprite[yvar].statnum==MAXSTATUS)
888
                {
1877 helixhorne 889
                    M32_ERROR("invalid sprite %d", yvar);
1493 helixhorne 890
                }
1528 helixhorne 891
                if (vm.flags&VMFLAG_ERROR) continue;
1493 helixhorne 892
 
893
                if (tw==CON_DIST)
894
                    Gv_SetVarX(distvar, dist(&sprite[xvar],&sprite[yvar]));
895
                else
896
                    Gv_SetVarX(distvar, ldist(&sprite[xvar],&sprite[yvar]));
897
                continue;
898
            }
899
 
900
        case CON_GETANGLE:
901
            insptr++;
902
            {
903
                int32_t angvar = *insptr++;
904
                int32_t xvar = Gv_GetVarX(*insptr++);
905
                int32_t yvar = Gv_GetVarX(*insptr++);
906
 
907
                Gv_SetVarX(angvar, getangle(xvar,yvar));
908
                continue;
909
            }
910
 
911
        case CON_GETINCANGLE:
912
            insptr++;
913
            {
914
                int32_t angvar = *insptr++;
915
                int32_t xvar = Gv_GetVarX(*insptr++);
916
                int32_t yvar = Gv_GetVarX(*insptr++);
917
 
918
                Gv_SetVarX(angvar, G_GetAngleDelta(xvar,yvar));
919
                continue;
920
            }
921
 
1697 helixhorne 922
        case CON_A2XY:
923
        case CON_AH2XYZ:
924
            insptr++;
925
            {
926
                int32_t ang=Gv_GetVarX(*insptr++), horiz=(tw==CON_A2XY)?100:Gv_GetVarX(*insptr++);
927
                int32_t xvar=*insptr++, yvar=*insptr++;
928
 
929
                int32_t x = sintable[(ang+512)&2047];
930
                int32_t y = sintable[ang&2047];
931
 
932
                if (tw==CON_AH2XYZ)
933
                {
934
                    int32_t zvar=*insptr++, z=0;
935
 
936
                    horiz -= 100;
937
                    if (horiz)
938
                    {
939
                        int32_t veclen = ksqrt(200*200 + horiz*horiz);
940
                        int32_t dacos = divscale14(200, veclen);
941
 
942
                        x = mulscale14(x, dacos);
943
                        y = mulscale14(y, dacos);
1698 helixhorne 944
                        z = divscale14(-horiz, veclen);
1697 helixhorne 945
                    }
946
 
947
                    Gv_SetVarX(zvar, z);
948
                }
949
 
950
                Gv_SetVarX(xvar, x);
951
                Gv_SetVarX(yvar, y);
952
 
953
                continue;
954
            }
955
 
1493 helixhorne 956
        case CON_MULSCALE:
957
            insptr++;
958
            {
959
                int32_t var1 = *insptr++, var2 = Gv_GetVarX(*insptr++);
960
                int32_t var3 = Gv_GetVarX(*insptr++), var4 = Gv_GetVarX(*insptr++);
961
 
962
                Gv_SetVarX(var1, mulscale(var2, var3, var4));
963
                continue;
964
            }
1683 helixhorne 965
        case CON_DIVSCALE:
966
            insptr++;
967
            {
968
                int32_t var1 = *insptr++, var2 = Gv_GetVarX(*insptr++);
969
                int32_t var3 = Gv_GetVarX(*insptr++), var4 = Gv_GetVarX(*insptr++);
1493 helixhorne 970
 
1683 helixhorne 971
                Gv_SetVarX(var1, divscale(var2, var3, var4));
972
                continue;
973
            }
974
 
1493 helixhorne 975
// *** if & while
976
        case CON_IFVARVARAND:
977
            insptr++;
978
            {
979
                int32_t j = Gv_GetVarX(*insptr++);
980
                j &= Gv_GetVarX(*insptr++);
981
                insptr--;
1625 terminx 982
                VM_DoConditional(j);
1493 helixhorne 983
            }
984
            continue;
985
 
986
        case CON_IFVARVAROR:
987
            insptr++;
988
            {
989
                int32_t j = Gv_GetVarX(*insptr++);
990
                j |= Gv_GetVarX(*insptr++);
991
                insptr--;
1625 terminx 992
                VM_DoConditional(j);
1493 helixhorne 993
            }
994
            continue;
995
 
996
        case CON_IFVARVARXOR:
997
            insptr++;
998
            {
999
                int32_t j = Gv_GetVarX(*insptr++);
1000
                j ^= Gv_GetVarX(*insptr++);
1001
                insptr--;
1625 terminx 1002
                VM_DoConditional(j);
1493 helixhorne 1003
            }
1004
            continue;
1005
 
1006
        case CON_IFVARVAREITHER:
1007
            insptr++;
1008
            {
1009
                int32_t j = Gv_GetVarX(*insptr++);
1010
                int32_t l = Gv_GetVarX(*insptr++);
1011
                insptr--;
1625 terminx 1012
                VM_DoConditional(j || l);
1493 helixhorne 1013
            }
1014
            continue;
1015
 
1016
        case CON_IFVARVARBOTH:
1017
            insptr++;
1018
            {
1019
                int32_t j = Gv_GetVarX(*insptr++);
1020
                int32_t l = Gv_GetVarX(*insptr++);
1021
                insptr--;
1625 terminx 1022
                VM_DoConditional(j && l);
1493 helixhorne 1023
            }
1024
            continue;
1025
 
1026
        case CON_IFVARVARN:
1027
            insptr++;
1028
            {
1029
                int32_t j = Gv_GetVarX(*insptr++);
1030
                j = (j != Gv_GetVarX(*insptr++));
1031
                insptr--;
1625 terminx 1032
                VM_DoConditional(j);
1493 helixhorne 1033
            }
1034
            continue;
1035
 
1036
        case CON_IFVARVARE:
1037
            insptr++;
1038
            {
1039
                int32_t j = Gv_GetVarX(*insptr++);
1040
                j = (j == Gv_GetVarX(*insptr++));
1041
                insptr--;
1625 terminx 1042
                VM_DoConditional(j);
1493 helixhorne 1043
            }
1044
            continue;
1045
 
1046
        case CON_IFVARVARG:
1047
            insptr++;
1048
            {
1049
                int32_t j = Gv_GetVarX(*insptr++);
1050
                j = (j > Gv_GetVarX(*insptr++));
1051
                insptr--;
1625 terminx 1052
                VM_DoConditional(j);
1493 helixhorne 1053
            }
1054
            continue;
1055
 
1056
        case CON_IFVARVARGE:
1057
            insptr++;
1058
            {
1059
                int32_t j = Gv_GetVarX(*insptr++);
1060
                j = (j >= Gv_GetVarX(*insptr++));
1061
                insptr--;
1625 terminx 1062
                VM_DoConditional(j);
1493 helixhorne 1063
            }
1064
            continue;
1065
 
1066
        case CON_IFVARVARL:
1067
            insptr++;
1068
            {
1069
                int32_t j = Gv_GetVarX(*insptr++);
1070
                j = (j < Gv_GetVarX(*insptr++));
1071
                insptr--;
1625 terminx 1072
                VM_DoConditional(j);
1493 helixhorne 1073
            }
1074
            continue;
1075
 
1076
        case CON_IFVARVARLE:
1077
            insptr++;
1078
            {
1079
                int32_t j = Gv_GetVarX(*insptr++);
1080
                j = (j <= Gv_GetVarX(*insptr++));
1081
                insptr--;
1625 terminx 1082
                VM_DoConditional(j);
1493 helixhorne 1083
            }
1084
            continue;
1085
 
1086
        case CON_IFVARE:
1087
            insptr++;
1088
            {
1089
                int32_t j=Gv_GetVarX(*insptr++);
1625 terminx 1090
                VM_DoConditional(j == *insptr);
1493 helixhorne 1091
            }
1092
            continue;
1093
 
1094
        case CON_IFVARN:
1095
            insptr++;
1096
            {
1097
                int32_t j=Gv_GetVarX(*insptr++);
1625 terminx 1098
                VM_DoConditional(j != *insptr);
1493 helixhorne 1099
            }
1100
            continue;
1101
 
1102
        case CON_WHILEVARN:
1103
        {
1104
            instype *savedinsptr=insptr+2;
1105
            int32_t j;
1106
            do
1107
            {
1108
                insptr=savedinsptr;
1109
                j = (Gv_GetVarX(*(insptr-1)) != *insptr);
1625 terminx 1110
                VM_DoConditional(j);
1493 helixhorne 1111
            }
1528 helixhorne 1112
            while (j && !vm.flags);
1113
            vm.flags &= ~VMFLAG_BREAK;
1493 helixhorne 1114
            continue;
1115
        }
1116
 
1117
        case CON_WHILEVARL:
1118
        {
1119
            instype *savedinsptr=insptr+2;
1120
            int32_t j;
1121
            do
1122
            {
1123
                insptr=savedinsptr;
1124
                j = (Gv_GetVarX(*(insptr-1)) < *insptr);
1625 terminx 1125
                VM_DoConditional(j);
1493 helixhorne 1126
            }
1528 helixhorne 1127
            while (j && !vm.flags);
1128
            vm.flags &= ~VMFLAG_BREAK;
1493 helixhorne 1129
            continue;
1130
        }
1131
 
1132
        case CON_WHILEVARVARN:
1133
        {
1134
            int32_t j;
1135
            instype *savedinsptr=insptr+2;
1136
            do
1137
            {
1138
                insptr=savedinsptr;
1139
                j = Gv_GetVarX(*(insptr-1));
1140
                j = (j != Gv_GetVarX(*insptr++));
1141
                insptr--;
1625 terminx 1142
                VM_DoConditional(j);
1493 helixhorne 1143
            }
1528 helixhorne 1144
            while (j && !vm.flags);
1145
            vm.flags &= ~VMFLAG_BREAK;
1493 helixhorne 1146
            continue;
1147
        }
1148
 
1149
        case CON_WHILEVARVARL:
1150
        {
1151
            int32_t j;
1152
            instype *savedinsptr=insptr+2;
1153
            do
1154
            {
1155
                insptr=savedinsptr;
1156
                j = Gv_GetVarX(*(insptr-1));
1157
                j = (j < Gv_GetVarX(*insptr++));
1158
                insptr--;
1625 terminx 1159
                VM_DoConditional(j);
1493 helixhorne 1160
            }
1528 helixhorne 1161
            while (j && !vm.flags);
1162
            vm.flags &= ~VMFLAG_BREAK;
1493 helixhorne 1163
            continue;
1164
        }
1165
 
1927 helixhorne 1166
        case CON_COLLECTSECTORS:
1167
            insptr++;
1168
            {
4798 helixhorne 1169
                const int32_t aridx=*insptr++, startsectnum=Gv_GetVarX(*insptr++);
1170
                const int32_t numsectsVar=*insptr++, state=*insptr++;
1927 helixhorne 1171
 
4798 helixhorne 1172
                if (CheckArray(aridx))
1173
                    continue;
1174
 
1175
                gamearray_t *const gar = &aGameArrays[aridx];
1176
                Bassert((gar->dwFlags & (GAMEARRAY_READONLY|GAMEARRAY_VARSIZE)) == 0);
1177
 
1178
                const int32_t o_g_st=vm.g_st, arsize = gar->size;
1179
                instype *const end=insptr;
1927 helixhorne 1180
                int32_t sectcnt, numsects=0;
4798 helixhorne 1181
 
1182
                // XXX: relies on -fno-strict-aliasing
1183
                int16_t *const sectlist = (int16_t *)gar->vals;  // actually an int32_t array
1184
                int32_t *const sectlist32 = (int32_t *)sectlist;
1185
 
1927 helixhorne 1186
                int32_t j, startwall, endwall, ns;
1187
                static uint8_t sectbitmap[MAXSECTORS>>3];
1188
 
1189
                X_ERROR_INVALIDSECT(startsectnum);
1190
                if (arsize < numsectors)
1191
                {
1192
                    M32_ERROR("Array size must be at least numsectors (=%d) for collecting!",
1193
                              numsectors);
1194
                    continue;
1195
                }
1196
 
1197
                // collect!
1198
                bfirst_search_init(sectlist, sectbitmap, &numsects, MAXSECTORS, startsectnum);
1199
 
1200
                for (sectcnt=0; sectcnt<numsects; sectcnt++)
1201
                    for (WALLS_OF_SECTOR(sectlist[sectcnt], j))
1202
                        if ((ns=wall[j].nextsector) >= 0 && wall[j].nextsector<numsectors)
1203
                        {
1204
                            if (sectbitmap[ns>>3]&(1<<(ns&7)))
1205
                                continue;
1206
                            vm.g_st = 1+MAXEVENTS+state;
1207
                            insptr = script + statesinfo[state].ofs;
1208
                            g_iReturnVar = ns;
1209
                            VM_Execute(0);
1210
                            if (g_iReturnVar)
1211
                                bfirst_search_try(sectlist, sectbitmap, &numsects, wall[j].nextsector);
1212
                        }
1213
 
1214
                // short->int sector list
1215
                for (j=numsects-1; j>=0; j--)
1216
                    sectlist32[j] = sectlist[j];
1217
 
1218
                Gv_SetVarX(numsectsVar, numsects);
1219
                g_iReturnVar = 0;
1220
 
1221
                // restore some VM state
1222
                vm.g_st = o_g_st;
1223
                insptr = end;
1224
            }
1225
            continue;
1226
 
1499 helixhorne 1227
        case CON_SORT:
1228
            insptr++;
1229
            {
4798 helixhorne 1230
                const int32_t aridx=*insptr++, count=Gv_GetVarX(*insptr++), state=*insptr++;
1231
                const int32_t o_g_st = vm.g_st;
1232
                instype *const end = insptr;
1499 helixhorne 1233
 
4798 helixhorne 1234
                if (CheckArray(aridx))
1235
                    continue;
1236
 
1237
                if (count <= 0)
1238
                    continue;
1239
 
1240
                gamearray_t *const gar = &aGameArrays[aridx];
1241
                Bassert((gar->dwFlags & (GAMEARRAY_READONLY|GAMEARRAY_VARSIZE)) == 0);
1242
 
1243
                if (count > gar->size)
1499 helixhorne 1244
                {
4798 helixhorne 1245
                    M32_ERROR("Count of elements to sort (%d) exceeds array size (%d)!",
1246
                              count, gar->size);
1499 helixhorne 1247
                    continue;
1248
                }
1249
 
1250
                if (state < 0)
1251
                {
4798 helixhorne 1252
                    qsort(gar->vals, count, sizeof(int32_t), X_DoSortDefault);
1499 helixhorne 1253
                }
1254
                else
1255
                {
1256
                    x_sortingstateptr = script + statesinfo[state].ofs;
1257
                    vm.g_st = 1+MAXEVENTS+state;
4798 helixhorne 1258
                    qsort(gar->vals, count, sizeof(int32_t), X_DoSort);
1499 helixhorne 1259
                    vm.g_st = o_g_st;
1260
                    insptr = end;
1261
                }
1262
            }
1263
            continue;
1264
 
1493 helixhorne 1265
        case CON_FOR:  // special-purpose iteration
1266
            insptr++;
1267
            {
5018 helixhorne 1268
                const int32_t var = *insptr++, how = *insptr++;
1269
                const int32_t parm2 = how<=ITER_DRAWNSPRITES ? 0 : Gv_GetVarX(*insptr++);
1270
                instype *const end = insptr + *insptr, *const beg = ++insptr;
1271
                const int32_t vm_i_bak = vm.g_i;
1272
                tspritetype *const vm_sp_bak = vm.g_sp;
1493 helixhorne 1273
 
5018 helixhorne 1274
                if (vm.flags&VMFLAG_ERROR)
1275
                    continue;
1493 helixhorne 1276
 
1277
                switch (how)
1278
                {
1279
                case ITER_ALLSPRITES:
5018 helixhorne 1280
                    for (int jj=0; jj<MAXSPRITES && !vm.flags; jj++)
1493 helixhorne 1281
                    {
1282
                        if (sprite[jj].statnum == MAXSTATUS)
1283
                            continue;
1284
                        Gv_SetVarX(var, jj);
1285
                        vm.g_i = jj;
4911 terminx 1286
                        vm.g_sp = (tspritetype *)&sprite[jj];
1493 helixhorne 1287
                        insptr = beg;
1625 terminx 1288
                        VM_Execute(1);
1493 helixhorne 1289
                    }
1290
                    break;
1291
                case ITER_ALLSECTORS:
5018 helixhorne 1292
                    for (int jj=0; jj<numsectors && !vm.flags; jj++)
1493 helixhorne 1293
                    {
1294
                        Gv_SetVarX(var, jj);
1295
                        insptr = beg;
1625 terminx 1296
                        VM_Execute(1);
1493 helixhorne 1297
                    }
1298
                    break;
1299
                case ITER_ALLWALLS:
5018 helixhorne 1300
                    for (int jj=0; jj<numwalls && !vm.flags; jj++)
1493 helixhorne 1301
                    {
1302
                        Gv_SetVarX(var, jj);
1303
                        insptr = beg;
1625 terminx 1304
                        VM_Execute(1);
1493 helixhorne 1305
                    }
1306
                    break;
1877 helixhorne 1307
                case ITER_ACTIVELIGHTS:
1308
#ifdef POLYMER
5018 helixhorne 1309
                    for (int jj=0; jj<PR_MAXLIGHTS; jj++)
1877 helixhorne 1310
                    {
1311
                        if (!prlights[jj].flags.active)
1312
                            continue;
1313
 
1314
                        Gv_SetVarX(var, jj);
1315
                        insptr = beg;
1316
                        VM_Execute(1);
1317
                    }
1318
#else
1319
                    M32_ERROR("Polymer not compiled in, iteration over lights forbidden.");
1320
#endif
1321
                    break;
1322
 
1493 helixhorne 1323
                case ITER_SELSPRITES:
5018 helixhorne 1324
                    for (int ii=0; ii<highlightcnt && !vm.flags; ii++)
1493 helixhorne 1325
                    {
5018 helixhorne 1326
                        int jj = highlight[ii];
1493 helixhorne 1327
                        if (jj&0xc000)
1328
                        {
1329
                            jj &= (MAXSPRITES-1);
1330
                            Gv_SetVarX(var, jj);
1331
                            vm.g_i = jj;
4911 terminx 1332
                            vm.g_sp = (tspritetype *)&sprite[jj];
1493 helixhorne 1333
                            insptr = beg;
1625 terminx 1334
                            VM_Execute(1);
1493 helixhorne 1335
                        }
1336
                    }
1337
                    break;
1338
                case ITER_SELSECTORS:
5018 helixhorne 1339
                    for (int ii=0; ii<highlightsectorcnt && !vm.flags; ii++)
1493 helixhorne 1340
                    {
5018 helixhorne 1341
                        int jj=highlightsector[ii];
1493 helixhorne 1342
                        Gv_SetVarX(var, jj);
1343
                        insptr = beg;
1625 terminx 1344
                        VM_Execute(1);
1493 helixhorne 1345
                    }
1346
                    break;
1347
                case ITER_SELWALLS:
5018 helixhorne 1348
                    for (int ii=0; ii<highlightcnt && !vm.flags; ii++)
1493 helixhorne 1349
                    {
5018 helixhorne 1350
                        int jj=highlight[ii];
1493 helixhorne 1351
                        if (jj&0xc000)
1352
                            continue;
1353
                        Gv_SetVarX(var, jj);
1354
                        insptr = beg;
1625 terminx 1355
                        VM_Execute(1);
1493 helixhorne 1356
                    }
1357
                    break;
1358
                case ITER_DRAWNSPRITES:
5018 helixhorne 1359
                    for (int ii=0; ii<spritesortcnt && !vm.flags; ii++)
1493 helixhorne 1360
                    {
4911 terminx 1361
                        vm.g_sp = (tspritetype *)&sprite[MAXSPRITES-1];
4898 terminx 1362
                        Bmemcpy(&sprite[MAXSPRITES-1], &tsprite[ii], sizeof(tspritetype));
1493 helixhorne 1363
                        Gv_SetVarX(var, ii);
1364
                        insptr = beg;
1625 terminx 1365
                        VM_Execute(1);
4898 terminx 1366
                        Bmemcpy(&tsprite[ii], &sprite[MAXSPRITES-1], sizeof(tspritetype));
1493 helixhorne 1367
                    }
1368
                    break;
1369
                case ITER_SPRITESOFSECTOR:
1370
                    if (parm2 < 0 || parm2 >= MAXSECTORS)
1371
                        goto badindex;
5018 helixhorne 1372
                    for (int jj=headspritesect[parm2]; jj>=0 && !vm.flags; jj=nextspritesect[jj])
1493 helixhorne 1373
                    {
1374
                        Gv_SetVarX(var, jj);
1375
                        vm.g_i = jj;
4911 terminx 1376
                        vm.g_sp = (tspritetype *)&sprite[jj];
1493 helixhorne 1377
                        insptr = beg;
1625 terminx 1378
                        VM_Execute(1);
1493 helixhorne 1379
                    }
1380
                    break;
1381
                case ITER_WALLSOFSECTOR:
1382
                    if (parm2 < 0 || parm2 >= MAXSECTORS)
1383
                        goto badindex;
5018 helixhorne 1384
                    for (int jj=sector[parm2].wallptr, endwall=jj+sector[parm2].wallnum-1;
1593 terminx 1385
                            jj<=endwall && !vm.flags; jj++)
1493 helixhorne 1386
                    {
1387
                        Gv_SetVarX(var, jj);
1388
                        insptr = beg;
1625 terminx 1389
                        VM_Execute(1);
1493 helixhorne 1390
                    }
1391
                    break;
1500 helixhorne 1392
                case ITER_LOOPOFWALL:
1393
                    if (parm2 < 0 || parm2 >= numwalls)
1394
                        goto badindex;
1395
                    {
5018 helixhorne 1396
                        int jj = parm2;
1397
                        do
1398
                        {
1399
                            Gv_SetVarX(var, jj);
1400
                            insptr = beg;
1401
                            VM_Execute(1);
1402
                            jj = wall[jj].point2;
1403
                        }
1404
                        while (jj != parm2 && !vm.flags);
1593 terminx 1405
                    }
1500 helixhorne 1406
                    break;
1493 helixhorne 1407
                case ITER_RANGE:
5018 helixhorne 1408
                    for (int jj=0; jj<parm2 && !vm.flags; jj++)
1493 helixhorne 1409
                    {
1410
                        Gv_SetVarX(var, jj);
1411
                        insptr = beg;
1625 terminx 1412
                        VM_Execute(1);
1493 helixhorne 1413
                    }
1414
                    break;
1415
                default:
1877 helixhorne 1416
                    M32_ERROR("Unknown iteration type %d!", how);
1493 helixhorne 1417
                    continue;
1418
badindex:
1419
                    OSD_Printf(OSD_ERROR "Line %d, %s %s: index %d out of range!\n",g_errorLineNum,keyw[g_tw],
1740 helixhorne 1420
                               iter_tokens[how].token, parm2);
1528 helixhorne 1421
                    vm.flags |= VMFLAG_ERROR;
1493 helixhorne 1422
                    continue;
1423
                }
1424
                vm.g_i = vm_i_bak;
1425
                vm.g_sp = vm_sp_bak;
1528 helixhorne 1426
                vm.flags &= ~VMFLAG_BREAK;
1493 helixhorne 1427
                insptr = end;
1428
            }
1429
            continue;
1430
 
1431
        case CON_IFVARAND:
1432
            insptr++;
1433
            {
1434
                int32_t j=Gv_GetVarX(*insptr++);
1625 terminx 1435
                VM_DoConditional(j & *insptr);
1493 helixhorne 1436
            }
1437
            continue;
1438
 
1439
        case CON_IFVAROR:
1440
            insptr++;
1441
            {
1442
                int32_t j=Gv_GetVarX(*insptr++);
1625 terminx 1443
                VM_DoConditional(j | *insptr);
1493 helixhorne 1444
            }
1445
            continue;
1446
 
1447
        case CON_IFVARXOR:
1448
            insptr++;
1449
            {
1450
                int32_t j=Gv_GetVarX(*insptr++);
1625 terminx 1451
                VM_DoConditional(j ^ *insptr);
1493 helixhorne 1452
            }
1453
            continue;
1454
 
1455
        case CON_IFVAREITHER:
1456
            insptr++;
1457
            {
1458
                int32_t j=Gv_GetVarX(*insptr++);
1625 terminx 1459
                VM_DoConditional(j || *insptr);
1493 helixhorne 1460
            }
1461
            continue;
1462
 
1463
        case CON_IFVARBOTH:
1464
            insptr++;
1465
            {
1466
                int32_t j=Gv_GetVarX(*insptr++);
1625 terminx 1467
                VM_DoConditional(j && *insptr);
1493 helixhorne 1468
            }
1469
            continue;
1470
 
1471
        case CON_IFVARG:
1472
            insptr++;
1473
            {
1474
                int32_t j=Gv_GetVarX(*insptr++);
1625 terminx 1475
                VM_DoConditional(j > *insptr);
1493 helixhorne 1476
            }
1477
            continue;
1478
 
1479
        case CON_IFVARGE:
1480
            insptr++;
1481
            {
1482
                int32_t j=Gv_GetVarX(*insptr++);
1625 terminx 1483
                VM_DoConditional(j >= *insptr);
1493 helixhorne 1484
            }
1485
            continue;
1486
 
1487
        case CON_IFVARL:
1488
            insptr++;
1489
            {
1490
                int32_t j=Gv_GetVarX(*insptr++);
1625 terminx 1491
                VM_DoConditional(j < *insptr);
1493 helixhorne 1492
            }
1493
            continue;
1494
 
1495
        case CON_IFVARLE:
1496
            insptr++;
1497
            {
1498
                int32_t j=Gv_GetVarX(*insptr++);
1625 terminx 1499
                VM_DoConditional(j <= *insptr);
1493 helixhorne 1500
            }
1501
            continue;
1502
 
1503
        case CON_IFRND:
1625 terminx 1504
            VM_DoConditional(rnd(Gv_GetVarX(*(++insptr))));
1493 helixhorne 1505
            continue;
1506
 
1499 helixhorne 1507
        case CON_IFHITKEY:
1508
        case CON_IFHOLDKEY:
1521 helixhorne 1509
        case CON_RESETKEY:
2122 helixhorne 1510
        case CON_SETKEY:
1497 helixhorne 1511
            insptr++;
1512
            {
1513
                int32_t key=Gv_GetVarX(*insptr);
4385 terminx 1514
                if (key<0 || key >= (int32_t)ARRAY_SIZE(keystatus))
1497 helixhorne 1515
                {
1877 helixhorne 1516
                    M32_ERROR("Invalid key %d!", key);
1497 helixhorne 1517
                    continue;
1518
                }
1519
 
2122 helixhorne 1520
                if (tw == CON_IFHITKEY || tw == CON_IFHOLDKEY)
1625 terminx 1521
                    VM_DoConditional(keystatus[key]);
1521 helixhorne 1522
                else
1523
                    insptr++;
1524
 
1525
                if (tw != CON_IFHOLDKEY)
1499 helixhorne 1526
                {
1527
                    if (!(key==0 || key==KEYSC_ESC || key==KEYSC_TILDE || key==KEYSC_gENTER ||
1593 terminx 1528
                            key==KEYSC_LALT || key==KEYSC_RALT || key==KEYSC_LCTRL || key==KEYSC_RCTRL ||
1529
                            key==KEYSC_LSHIFT || key==KEYSC_RSHIFT))
2122 helixhorne 1530
                        keystatus[key] = (tw==CON_SETKEY);
1499 helixhorne 1531
                }
1497 helixhorne 1532
            }
1533
            continue;
1534
 
1535
        case CON_IFEITHERALT:
1625 terminx 1536
            VM_DoConditional(keystatus[KEYSC_LALT]||keystatus[KEYSC_RALT]);
1497 helixhorne 1537
            continue;
1538
 
1539
        case CON_IFEITHERCTRL:
1625 terminx 1540
            VM_DoConditional(keystatus[KEYSC_LCTRL]||keystatus[KEYSC_RCTRL]);
1497 helixhorne 1541
            continue;
1542
 
1543
        case CON_IFEITHERSHIFT:
1625 terminx 1544
            VM_DoConditional(keystatus[KEYSC_LSHIFT]||keystatus[KEYSC_RSHIFT]);
1497 helixhorne 1545
            continue;
1546
 
1493 helixhorne 1547
// vvv CURSPR
1548
        case CON_IFSPRITEPAL:
1549
            insptr++;
1550
            X_ERROR_INVALIDSP();
1625 terminx 1551
            VM_DoConditional(vm.g_sp->pal == Gv_GetVarX(*insptr));
1493 helixhorne 1552
            continue;
1553
 
1710 helixhorne 1554
        case CON_IFHIGHLIGHTED:
1555
            insptr++;
1556
            {
1557
                int32_t id=*insptr++, index=Gv_GetVarX(*insptr);
1558
 
1559
                if (index<0 || (id==M32_SPRITE_VAR_ID && index>=MAXSPRITES) || (id==M32_WALL_VAR_ID && index>=numwalls))
1560
                {
1877 helixhorne 1561
                    M32_ERROR("%s index %d out of range!", id==M32_SPRITE_VAR_ID?"Sprite":"Wall", index);
1710 helixhorne 1562
                    continue;
1563
                }
1564
 
1565
                if (id==M32_SPRITE_VAR_ID)
1566
                    VM_DoConditional(show2dsprite[index>>3]&(1<<(index&7)));
1567
                else
1568
                    VM_DoConditional(show2dwall[index>>3]&(1<<(index&7)));
1569
            }
1570
            continue;
1571
 
1493 helixhorne 1572
        case CON_IFANGDIFFL:
1573
            insptr++;
1574
            {
1575
                int32_t j;
1576
                X_ERROR_INVALIDSP();
1577
                j = klabs(G_GetAngleDelta(ang, vm.g_sp->ang));
1625 terminx 1578
                VM_DoConditional(j <= Gv_GetVarX(*insptr));
1493 helixhorne 1579
            }
1580
            continue;
1581
 
1582
        case CON_IFAWAYFROMWALL:
1583
        {
1584
            int16_t s1;
1585
            int32_t j = 0;
1586
 
1587
            X_ERROR_INVALIDSP();
1588
            s1 = vm.g_sp->sectnum;
1589
            updatesector(vm.g_sp->x+108,vm.g_sp->y+108,&s1);
1590
            if (s1 == vm.g_sp->sectnum)
1591
            {
1592
                updatesector(vm.g_sp->x-108,vm.g_sp->y-108,&s1);
1593
                if (s1 == vm.g_sp->sectnum)
1594
                {
1595
                    updatesector(vm.g_sp->x+108,vm.g_sp->y-108,&s1);
1596
                    if (s1 == vm.g_sp->sectnum)
1597
                    {
1598
                        updatesector(vm.g_sp->x-108,vm.g_sp->y+108,&s1);
1599
                        if (s1 == vm.g_sp->sectnum)
1600
                            j = 1;
1601
                    }
1602
                }
1603
            }
1625 terminx 1604
            VM_DoConditional(j);
1493 helixhorne 1605
        }
1606
        continue;
1607
 
1608
        case CON_IFCANSEE:
1609
        {
1610
            int32_t j;
1611
 
1612
            X_ERROR_INVALIDSP();
1613
            j = cansee(vm.g_sp->x,vm.g_sp->y,vm.g_sp->z/*-((krand()&41)<<8)*/,vm.g_sp->sectnum,
1593 terminx 1614
                       pos.x, pos.y, pos.z /*-((krand()&41)<<8)*/, cursectnum);
1625 terminx 1615
            VM_DoConditional(j);
1493 helixhorne 1616
        }
1617
        continue;
1618
 
1619
        case CON_IFONWATER:
1620
            X_ERROR_INVALIDSP();
1625 terminx 1621
            VM_DoConditional(sector[vm.g_sp->sectnum].lotag == 1 && klabs(vm.g_sp->z-sector[vm.g_sp->sectnum].floorz) < (32<<8));
1493 helixhorne 1622
            continue;
1623
 
1624
        case CON_IFINWATER:
1625
            X_ERROR_INVALIDSP();
1625 terminx 1626
            VM_DoConditional(sector[vm.g_sp->sectnum].lotag == 2);
1493 helixhorne 1627
            continue;
1628
 
1629
        case CON_IFACTOR:
1630
            insptr++;
1631
            X_ERROR_INVALIDSP();
1625 terminx 1632
            VM_DoConditional(vm.g_sp->picnum == Gv_GetVarX(*insptr));
1493 helixhorne 1633
            continue;
1634
 
1635
        case CON_IFINSIDE:
1636
            insptr++;
1637
            {
1638
                int32_t x=Gv_GetVarX(*insptr++), y=Gv_GetVarX(*insptr++), sectnum=Gv_GetVarX(*insptr++), res;
1639
 
1640
                res = inside(x, y, sectnum);
1641
                if (res == -1)
1642
                {
1877 helixhorne 1643
                    M32_ERROR("Sector index %d out of range!", sectnum);
1493 helixhorne 1644
                    continue;
1645
                }
1646
                insptr--;
1625 terminx 1647
                VM_DoConditional(res);
1493 helixhorne 1648
            }
1649
            continue;
1650
 
1651
        case CON_IFOUTSIDE:
1652
            X_ERROR_INVALIDSP();
1625 terminx 1653
            VM_DoConditional(sector[vm.g_sp->sectnum].ceilingstat&1);
1493 helixhorne 1654
            continue;
1655
 
1656
        case CON_IFPDISTL:
1657
            insptr++;
1658
            {
1659
                X_ERROR_INVALIDSP();
1625 terminx 1660
                VM_DoConditional(dist((spritetype *)&pos, vm.g_sp) < Gv_GetVarX(*insptr));
1493 helixhorne 1661
            }
1662
            continue;
1663
 
1664
        case CON_IFPDISTG:
1665
            insptr++;
1666
            {
1667
                X_ERROR_INVALIDSP();
1625 terminx 1668
                VM_DoConditional(dist((spritetype *)&pos, vm.g_sp) > Gv_GetVarX(*insptr));
1493 helixhorne 1669
            }
1670
            continue;
1671
// ^^^
1672
 
1673
// *** BUILD functions
1674
        case CON_INSERTSPRITE:
1675
            insptr++;
1676
            {
1677
                int32_t dasectnum = Gv_GetVarX(*insptr++), ret;
1678
 
1679
                X_ERROR_INVALIDSECT(dasectnum);
2478 helixhorne 1680
                if (Numsprites >= MAXSPRITES)
1493 helixhorne 1681
                {
1877 helixhorne 1682
                    M32_ERROR("Maximum number of sprites reached.");
1493 helixhorne 1683
                    continue;
1684
                }
1685
 
1686
                ret = insertsprite(dasectnum, 0);
1687
                vm.g_i = ret;
4911 terminx 1688
                vm.g_sp = (tspritetype *)&sprite[ret];
1493 helixhorne 1689
            }
1690
            continue;
1691
 
1692
        case CON_DUPSPRITE:
1536 helixhorne 1693
        case CON_TDUPSPRITE:
1493 helixhorne 1694
            insptr++;
1695
            {
1696
                int32_t ospritenum = Gv_GetVarX(*insptr++), nspritenum;
1697
 
1698
                if (ospritenum<0 || ospritenum>=MAXSPRITES || sprite[ospritenum].statnum==MAXSTATUS)
1699
                {
1877 helixhorne 1700
                    M32_ERROR("Tried to duplicate nonexistent sprite %d", ospritenum);
1493 helixhorne 1701
                }
2478 helixhorne 1702
                if ((tw==CON_DUPSPRITE && Numsprites >= MAXSPRITES) ||
1593 terminx 1703
                        (tw==CON_DUPSPRITE && spritesortcnt >= MAXSPRITESONSCREEN))
1493 helixhorne 1704
                {
1877 helixhorne 1705
                    M32_ERROR("Maximum number of sprites reached.");
1493 helixhorne 1706
                }
1707
 
2501 helixhorne 1708
                if (vm.flags&VMFLAG_ERROR)
1709
                    continue;
1710
 
1536 helixhorne 1711
                if (tw==CON_DUPSPRITE)
1712
                {
1713
                    nspritenum = insertsprite(sprite[ospritenum].sectnum, sprite[ospritenum].statnum);
1493 helixhorne 1714
 
1536 helixhorne 1715
                    if (nspritenum < 0)
1716
                    {
1877 helixhorne 1717
                        M32_ERROR("Internal error.");
1536 helixhorne 1718
                        continue;
1719
                    }
1720
 
1721
                    Bmemcpy(&sprite[nspritenum], &sprite[ospritenum], sizeof(spritetype));
1722
                    vm.g_i = nspritenum;
4911 terminx 1723
                    vm.g_sp = (tspritetype *)&sprite[nspritenum];
1536 helixhorne 1724
                }
1725
                else
1493 helixhorne 1726
                {
1536 helixhorne 1727
                    Bmemcpy(&tsprite[spritesortcnt], &sprite[ospritenum], sizeof(spritetype));
1728
                    tsprite[spritesortcnt].owner = ospritenum;
1729
                    vm.g_i = -1;
1730
                    vm.g_sp = &tsprite[spritesortcnt];
1731
                    spritesortcnt++;
1493 helixhorne 1732
                }
1733
            }
1734
            continue;
1735
 
1736
        case CON_DELETESPRITE:
1737
            insptr++;
1738
            {
1739
                int32_t daspritenum = Gv_GetVarX(*insptr++), ret;
1740
 
1741
                X_ERROR_INVALIDSPRI(daspritenum);
1742
                ret = deletesprite(daspritenum);
1501 helixhorne 1743
                g_iReturnVar = ret;
1493 helixhorne 1744
            }
1745
            continue;
1746
 
2590 helixhorne 1747
        case CON_GETSPRITELINKTYPE:
1748
            insptr++;
1749
            {
1750
                int32_t spritenum=Gv_GetVarX(*insptr++), resvar = *insptr++;
1751
 
1752
                X_ERROR_INVALIDSPRI(spritenum);
1753
                Gv_SetVarX(resvar, taglab_linktags(1, spritenum));
1754
            }
1755
            continue;
1756
 
1493 helixhorne 1757
        case CON_LASTWALL:
1758
            insptr++;
1759
            {
1760
                int32_t dapoint = Gv_GetVarX(*insptr++), resvar=*insptr++;
1761
 
1762
                if (dapoint<0 || dapoint>=numwalls)
1763
                {
1877 helixhorne 1764
                    M32_ERROR("Invalid wall %d", dapoint);
1493 helixhorne 1765
                    continue;
1766
                }
1767
 
1768
                Gv_SetVarX(resvar, lastwall(dapoint));
1769
            }
1770
            continue;
1771
 
1772
        case CON_GETZRANGE:
1773
            insptr++;
1774
            {
1775
                vec3_t vect;
1776
 
1777
                vect.x = Gv_GetVarX(*insptr++);
1778
                vect.y = Gv_GetVarX(*insptr++);
1779
                vect.z = Gv_GetVarX(*insptr++);
1780
 
1781
                {
1782
                    int32_t sectnum=Gv_GetVarX(*insptr++);
1783
                    int32_t ceilzvar=*insptr++, ceilhitvar=*insptr++, florzvar=*insptr++, florhitvar=*insptr++;
1784
                    int32_t walldist=Gv_GetVarX(*insptr++), clipmask=Gv_GetVarX(*insptr++);
1785
                    int32_t ceilz, ceilhit, florz, florhit;
1786
 
1787
                    X_ERROR_INVALIDSECT(sectnum);
1788
                    getzrange(&vect, sectnum, &ceilz, &ceilhit, &florz, &florhit, walldist, clipmask);
1789
                    Gv_SetVarX(ceilzvar, ceilz);
1790
                    Gv_SetVarX(ceilhitvar, ceilhit);
1791
                    Gv_SetVarX(florzvar, florz);
1792
                    Gv_SetVarX(florhitvar, florhit);
1793
                }
1794
                continue;
1795
            }
1796
 
1708 helixhorne 1797
        case CON_CALCHYPOTENUSE:
1798
            insptr++;
1799
            {
1800
                int32_t retvar=*insptr++;
1801
                int64_t dax=Gv_GetVarX(*insptr++), day=Gv_GetVarX(*insptr++);
1802
                int64_t hypsq = dax*dax + day*day;
1803
 
1955 helixhorne 1804
                if (hypsq > (int64_t)INT32_MAX)
1708 helixhorne 1805
                    Gv_SetVarX(retvar, (int32_t)sqrt((double)hypsq));
1806
                else
2791 helixhorne 1807
                    Gv_SetVarX(retvar, ksqrt((uint32_t)hypsq));
1708 helixhorne 1808
 
1809
                continue;
1810
            }
1811
 
1812
        case CON_LINEINTERSECT:
1813
        case CON_RAYINTERSECT:
1814
            insptr++;
1815
            {
1816
                int32_t x1=Gv_GetVarX(*insptr++), y1=Gv_GetVarX(*insptr++), z1=Gv_GetVarX(*insptr++);
1817
                int32_t x2=Gv_GetVarX(*insptr++), y2=Gv_GetVarX(*insptr++), z2=Gv_GetVarX(*insptr++);
1818
                int32_t x3=Gv_GetVarX(*insptr++), y3=Gv_GetVarX(*insptr++), x4=Gv_GetVarX(*insptr++), y4=Gv_GetVarX(*insptr++);
1819
                int32_t intxvar=*insptr++, intyvar=*insptr++, intzvar=*insptr++, retvar=*insptr++;
1820
                int32_t intx, inty, intz, ret;
1821
 
1822
                if (tw==CON_LINEINTERSECT)
4903 terminx 1823
                    ret = lintersect(x1, y1, z1, x2, y2, z2, x3, y3, x4, y4, &intx, &inty, &intz);
1708 helixhorne 1824
                else
1825
                    ret = rayintersect(x1, y1, z1, x2, y2, z2, x3, y3, x4, y4, &intx, &inty, &intz);
1826
 
1827
                Gv_SetVarX(retvar, ret);
1828
                if (ret)
1829
                {
1830
                    Gv_SetVarX(intxvar, intx);
1831
                    Gv_SetVarX(intyvar, inty);
1832
                    Gv_SetVarX(intzvar, intz);
1833
                }
1834
 
1835
                continue;
1836
            }
1837
 
1838
        case CON_CLIPMOVE:
1839
            insptr++;
1840
            {
1841
                vec3_t vect;
1842
                int32_t retvar=*insptr++, xvar=*insptr++, yvar=*insptr++, z=Gv_GetVarX(*insptr++), sectnumvar=*insptr++;
1843
                int32_t xvect=Gv_GetVarX(*insptr++), yvect=Gv_GetVarX(*insptr++);
1844
                int32_t walldist=Gv_GetVarX(*insptr++), floordist=Gv_GetVarX(*insptr++), ceildist=Gv_GetVarX(*insptr++);
1845
                int32_t clipmask=Gv_GetVarX(*insptr++);
1846
                int16_t sectnum;
1847
 
1848
                vect.x = Gv_GetVarX(xvar);
1849
                vect.y = Gv_GetVarX(yvar);
1850
                vect.z = z;
1851
                sectnum = Gv_GetVarX(sectnumvar);
1852
 
1853
                X_ERROR_INVALIDSECT(sectnum);
1854
 
1855
                Gv_SetVarX(retvar, clipmove(&vect, &sectnum, xvect, yvect, walldist, floordist, ceildist, clipmask));
1856
                Gv_SetVarX(sectnumvar, sectnum);
1857
                Gv_SetVarX(xvar, vect.x);
1858
                Gv_SetVarX(yvar, vect.y);
1859
 
1860
                continue;
1861
            }
1862
 
1493 helixhorne 1863
        case CON_HITSCAN:
1864
            insptr++;
1865
            {
1866
                vec3_t vect;
2877 helixhorne 1867
                hitdata_t hit;
1493 helixhorne 1868
 
1869
                vect.x = Gv_GetVarX(*insptr++);
1870
                vect.y = Gv_GetVarX(*insptr++);
1871
                vect.z = Gv_GetVarX(*insptr++);
1872
 
1873
                {
1874
                    int32_t sectnum=Gv_GetVarX(*insptr++);
1875
                    int32_t vx=Gv_GetVarX(*insptr++), vy=Gv_GetVarX(*insptr++), vz=Gv_GetVarX(*insptr++);
1876
                    int32_t hitsectvar=*insptr++, hitwallvar=*insptr++, hitspritevar=*insptr++;
1877
                    int32_t hitxvar=*insptr++, hityvar=*insptr++, hitzvar=*insptr++, cliptype=Gv_GetVarX(*insptr++);
1878
 
1879
                    X_ERROR_INVALIDSECT(sectnum);
2877 helixhorne 1880
                    hitscan((const vec3_t *)&vect, sectnum, vx, vy, vz, &hit, cliptype);
1881
                    Gv_SetVarX(hitsectvar, hit.sect);
1882
                    Gv_SetVarX(hitwallvar, hit.wall);
1883
                    Gv_SetVarX(hitspritevar, hit.sprite);
1884
                    Gv_SetVarX(hitxvar, hit.pos.x);
1885
                    Gv_SetVarX(hityvar, hit.pos.y);
1886
                    Gv_SetVarX(hitzvar, hit.pos.z);
1493 helixhorne 1887
                }
1888
                continue;
1889
            }
1890
 
1891
        case CON_CANSEE:
1892
            insptr++;
1893
            {
1894
                int32_t x1=Gv_GetVarX(*insptr++), y1=Gv_GetVarX(*insptr++), z1=Gv_GetVarX(*insptr++);
1895
                int32_t sect1=Gv_GetVarX(*insptr++);
1896
                int32_t x2=Gv_GetVarX(*insptr++), y2=Gv_GetVarX(*insptr++), z2=Gv_GetVarX(*insptr++);
1897
                int32_t sect2=Gv_GetVarX(*insptr++), rvar=*insptr++;
1898
 
1899
                X_ERROR_INVALIDSECT(sect1);
1900
                X_ERROR_INVALIDSECT(sect2);
1901
 
1902
                Gv_SetVarX(rvar, cansee(x1,y1,z1,sect1,x2,y2,z2,sect2));
1903
                continue;
1904
            }
1905
 
1906
        case CON_ROTATEPOINT:
1907
            insptr++;
1908
            {
1909
                int32_t xpivot=Gv_GetVarX(*insptr++), ypivot=Gv_GetVarX(*insptr++);
1910
                int32_t x=Gv_GetVarX(*insptr++), y=Gv_GetVarX(*insptr++), daang=Gv_GetVarX(*insptr++);
1911
                int32_t x2var=*insptr++, y2var=*insptr++;
1912
                int32_t x2, y2;
1913
 
1914
                rotatepoint(xpivot,ypivot,x,y,daang,&x2,&y2);
1915
                Gv_SetVarX(x2var, x2);
1916
                Gv_SetVarX(y2var, y2);
1917
                continue;
1918
            }
1919
 
1920
        case CON_NEARTAG:
1921
            insptr++;
1922
            {
1923
                // neartag(int32_t x, int32_t y, int32_t z, short sectnum, short ang,  //Starting position & angle
1924
                //         short *neartagsector,    //Returns near sector if sector[].tag != 0
1925
                //         short *neartagwall,      //Returns near wall if wall[].tag != 0
1926
                //         short *neartagsprite,    //Returns near sprite if sprite[].tag != 0
1927
                //         int32_t *neartaghitdist, //Returns actual distance to object (scale: 1024=largest grid size)
1928
                //         int32_t neartagrange,    //Choose maximum distance to scan (scale: 1024=largest grid size)
1929
                //         char tagsearch)          //1-lotag only, 2-hitag only, 3-lotag&hitag
1930
 
1931
                int32_t x=Gv_GetVarX(*insptr++), y=Gv_GetVarX(*insptr++), z=Gv_GetVarX(*insptr++);
1932
                int32_t sectnum=Gv_GetVarX(*insptr++), ang=Gv_GetVarX(*insptr++);
1933
                int32_t neartagsectorvar=*insptr++, neartagwallvar=*insptr++, neartagspritevar=*insptr++, neartaghitdistvar=*insptr++;
1934
                int32_t neartagrange=Gv_GetVarX(*insptr++), tagsearch=Gv_GetVarX(*insptr++);
1935
 
1497 helixhorne 1936
                int16_t neartagsector, neartagwall, neartagsprite;
1937
                int32_t neartaghitdist;
1938
 
1493 helixhorne 1939
                X_ERROR_INVALIDSECT(sectnum);
2373 helixhorne 1940
                neartag(x, y, z, sectnum, ang, &neartagsector, &neartagwall, &neartagsprite,
1941
                        &neartaghitdist, neartagrange, tagsearch, NULL);
1493 helixhorne 1942
 
1943
                Gv_SetVarX(neartagsectorvar, neartagsector);
1944
                Gv_SetVarX(neartagwallvar, neartagwall);
1945
                Gv_SetVarX(neartagspritevar, neartagsprite);
1946
                Gv_SetVarX(neartaghitdistvar, neartaghitdist);
1947
                continue;
1948
            }
1949
 
1950
        case CON_BSETSPRITE:  // was CON_SETSPRITE
1951
            insptr++;
1952
            {
1953
                int32_t spritenum = Gv_GetVarX(*insptr++);
1954
                vec3_t davector;
1955
 
1956
                davector.x = Gv_GetVarX(*insptr++);
1957
                davector.y = Gv_GetVarX(*insptr++);
1958
                davector.z = Gv_GetVarX(*insptr++);
1959
 
1960
                X_ERROR_INVALIDSPRI(spritenum);
1961
                setsprite(spritenum, &davector);
1962
                continue;
1963
            }
1964
 
1965
        case CON_GETFLORZOFSLOPE:
1966
        case CON_GETCEILZOFSLOPE:
1967
            insptr++;
1968
            {
1969
                int32_t sectnum = Gv_GetVarX(*insptr++), x = Gv_GetVarX(*insptr++), y = Gv_GetVarX(*insptr++);
1500 helixhorne 1970
                int32_t var=*insptr++;
1493 helixhorne 1971
 
1500 helixhorne 1972
                X_ERROR_INVALIDSECT(sectnum);
1493 helixhorne 1973
                if (tw == CON_GETFLORZOFSLOPE)
1500 helixhorne 1974
                    Gv_SetVarX(var, getflorzofslope(sectnum,x,y));
1975
                else
1976
                    Gv_SetVarX(var, getceilzofslope(sectnum,x,y));
1493 helixhorne 1977
                continue;
1978
            }
1979
 
1500 helixhorne 1980
        case CON_ALIGNFLORSLOPE:
1981
        case CON_ALIGNCEILSLOPE:
1982
            insptr++;
1983
            {
1984
                int32_t sectnum = Gv_GetVarX(*insptr++), x = Gv_GetVarX(*insptr++), y = Gv_GetVarX(*insptr++);
1985
                int32_t z=Gv_GetVarX(*insptr++);
1986
 
1987
                X_ERROR_INVALIDSECT(sectnum);
1988
                if (tw == CON_ALIGNFLORSLOPE)
1989
                    alignflorslope(sectnum, x,y,z);
1990
                else
1991
                    alignceilslope(sectnum, x,y,z);
1992
                continue;
1993
            }
1994
 
1493 helixhorne 1995
// CURSPR
1499 helixhorne 1996
        case CON_SETFIRSTWALL:
1997
            insptr++;
1998
            {
1999
                int32_t sect=Gv_GetVarX(*insptr++), wal=Gv_GetVarX(*insptr++);
2000
 
2001
                X_ERROR_INVALIDSECT(sect);
2002
                setfirstwall(sect, wal);
2003
            }
2004
            continue;
2005
 
2006
        case CON_UPDATECURSECTNUM:
2007
            insptr++;
2008
            updatesectorz(pos.x, pos.y, pos.z, &cursectnum);
2009
            continue;
2010
 
1493 helixhorne 2011
        case CON_UPDATESECTOR:
2012
        case CON_UPDATESECTORZ:
2013
            insptr++;
2014
            {
2015
                int32_t x=Gv_GetVarX(*insptr++), y=Gv_GetVarX(*insptr++);
2016
                int32_t z=(tw==CON_UPDATESECTORZ)?Gv_GetVarX(*insptr++):0;
2017
                int32_t var=*insptr++;
2018
                int16_t w;
2019
 
2020
                X_ERROR_INVALIDCI();
2021
                w=sprite[vm.g_i].sectnum;
2022
 
2023
                if (tw==CON_UPDATESECTOR) updatesector(x,y,&w);
2024
                else updatesectorz(x,y,z,&w);
2025
 
2026
                Gv_SetVarX(var, w);
2027
                continue;
2028
            }
2029
 
2030
        case CON_HEADSPRITESTAT:
2031
            insptr++;
2032
            {
2033
                int32_t i=*insptr++;
2034
                int32_t j=Gv_GetVarX(*insptr++);
2035
                if (j < 0 || j > MAXSTATUS)
2036
                {
1877 helixhorne 2037
                    M32_ERROR("invalid status list %d", j);
1493 helixhorne 2038
                    continue;
2039
                }
2040
                Gv_SetVarX(i,headspritestat[j]);
2041
                continue;
2042
            }
2043
 
2044
        case CON_PREVSPRITESTAT:
2045
            insptr++;
2046
            {
2047
                int32_t i=*insptr++;
2048
                int32_t j=Gv_GetVarX(*insptr++);
2049
 
2050
                X_ERROR_INVALIDSPRI(j);
2051
                Gv_SetVarX(i,prevspritestat[j]);
2052
                continue;
2053
            }
2054
 
2055
        case CON_NEXTSPRITESTAT:
2056
            insptr++;
2057
            {
2058
                int32_t i=*insptr++;
2059
                int32_t j=Gv_GetVarX(*insptr++);
2060
 
2061
                X_ERROR_INVALIDSPRI(j);
2062
                Gv_SetVarX(i,nextspritestat[j]);
2063
                continue;
2064
            }
2065
 
2066
        case CON_HEADSPRITESECT:
2067
            insptr++;
2068
            {
2069
                int32_t i=*insptr++;
2070
                int32_t j=Gv_GetVarX(*insptr++);
2071
 
2072
                X_ERROR_INVALIDSECT(j);
2073
                Gv_SetVarX(i,headspritesect[j]);
2074
                continue;
2075
            }
2076
 
2077
        case CON_PREVSPRITESECT:
2078
            insptr++;
2079
            {
2080
                int32_t i=*insptr++;
2081
                int32_t j=Gv_GetVarX(*insptr++);
2082
 
2083
                X_ERROR_INVALIDSPRI(j);
2084
                Gv_SetVarX(i,prevspritesect[j]);
2085
                continue;
2086
            }
2087
 
2088
        case CON_NEXTSPRITESECT:
2089
            insptr++;
2090
            {
2091
                int32_t i=*insptr++;
2092
                int32_t j=Gv_GetVarX(*insptr++);
2093
 
2094
                X_ERROR_INVALIDSPRI(j);
2095
                Gv_SetVarX(i,nextspritesect[j]);
2096
                continue;
2097
            }
2098
 
2099
        case CON_CANSEESPR:
2100
            insptr++;
2101
            {
2102
                int32_t lVar1 = Gv_GetVarX(*insptr++), lVar2 = Gv_GetVarX(*insptr++), res;
2103
 
2104
                if (lVar1<0 || lVar1>=MAXSPRITES || sprite[lVar1].statnum==MAXSTATUS)
2105
                {
1877 helixhorne 2106
                    M32_ERROR("Invalid sprite %d", lVar1);
1493 helixhorne 2107
                }
2108
                if (lVar2<0 || lVar2>=MAXSPRITES || sprite[lVar2].statnum==MAXSTATUS)
2109
                {
1877 helixhorne 2110
                    M32_ERROR("Invalid sprite %d", lVar2);
1493 helixhorne 2111
                }
2112
 
1528 helixhorne 2113
                if (vm.flags&VMFLAG_ERROR) res=0;
1493 helixhorne 2114
                else res=cansee(sprite[lVar1].x,sprite[lVar1].y,sprite[lVar1].z,sprite[lVar1].sectnum,
2115
                                    sprite[lVar2].x,sprite[lVar2].y,sprite[lVar2].z,sprite[lVar2].sectnum);
2116
 
2117
                Gv_SetVarX(*insptr++, res);
2118
                continue;
2119
            }
2120
 
2121
        case CON_CHANGESPRITESTAT:
2122
        case CON_CHANGESPRITESECT:
2123
            insptr++;
2124
            {
2125
                int32_t i = Gv_GetVarX(*insptr++);
2126
                int32_t j = Gv_GetVarX(*insptr++);
2127
 
2128
                X_ERROR_INVALIDSPRI(i);
2129
                if (j<0 || j >= (tw==CON_CHANGESPRITESTAT?MAXSTATUS:numsectors))
2130
                {
1877 helixhorne 2131
                    M32_ERROR("Invalid %s: %d", tw==CON_CHANGESPRITESTAT?"statnum":"sector", j);
1493 helixhorne 2132
                    continue;
2133
                }
2134
 
2135
                if (tw == CON_CHANGESPRITESTAT)
2136
                {
2137
                    if (sprite[i].statnum == j) continue;
2138
                    changespritestat(i,j);
2139
                }
2140
                else
2141
                {
2142
                    if (sprite[i].sectnum == j) continue;
2143
                    changespritesect(i,j);
2144
                }
2145
                continue;
2146
            }
2147
 
2148
        case CON_DRAGPOINT:
2149
            insptr++;
2150
            {
2151
                int32_t wallnum = Gv_GetVarX(*insptr++), newx = Gv_GetVarX(*insptr++), newy = Gv_GetVarX(*insptr++);
2152
 
2153
                if (wallnum<0 || wallnum>=numwalls)
2154
                {
1877 helixhorne 2155
                    M32_ERROR("Invalid wall %d", wallnum);
1493 helixhorne 2156
                    continue;
2157
                }
3394 helixhorne 2158
                dragpoint(wallnum,newx,newy,0);
1493 helixhorne 2159
                continue;
2160
            }
2161
 
2162
        case CON_SECTOROFWALL:
2163
            insptr++;
2164
            {
2165
                int32_t j = *insptr++;
2166
                Gv_SetVarX(j, sectorofwall(Gv_GetVarX(*insptr++)));
2167
            }
2168
            continue;
2169
 
1579 helixhorne 2170
        case CON_FIXREPEATS:
2171
            insptr++;
1886 helixhorne 2172
            fixrepeats(Gv_GetVarX(*insptr++));
1579 helixhorne 2173
            continue;
2174
 
1683 helixhorne 2175
        case CON_GETCLOSESTCOL:
2176
            insptr++;
2177
            {
2178
                int32_t r = Gv_GetVarX(*insptr++), g = Gv_GetVarX(*insptr++), b = Gv_GetVarX(*insptr++);
2179
                Gv_SetVarX(*insptr++, getclosestcol((r>>2)&63, (g>>2)&63, (b>>2)&63));
2180
                continue;
2181
            }
1710 helixhorne 2182
 
1493 helixhorne 2183
// *** stuff
1710 helixhorne 2184
        case CON_UPDATEHIGHLIGHT:
2185
            insptr++;
2186
            update_highlight();
2187
            continue;
2188
 
1927 helixhorne 2189
        case CON_UPDATEHIGHLIGHTSECTOR:
2190
            insptr++;
2191
            update_highlightsector();
2192
            continue;
2193
 
1710 helixhorne 2194
        case CON_SETHIGHLIGHT:
2195
            insptr++;
2196
            {
2197
                int32_t what=Gv_GetVarX(*insptr++), index=Gv_GetVarX(*insptr++), doset = Gv_GetVarX(*insptr++);
2198
 
1927 helixhorne 2199
                if (highlightsectorcnt >= 0)
2200
                {
2201
                    M32_ERROR("sector highlight active or pending, cannot highlight sprites/walls");
2202
                    continue;
2203
                }
2204
 
1710 helixhorne 2205
                if (what&16384)
2206
                {
2207
                    index &= ~16384;
2208
                    if (index < 0 || index>=MAXSPRITES || sprite[index].statnum==MAXSTATUS)
2209
                    {
1877 helixhorne 2210
                        M32_ERROR("Invalid sprite index %d", index);
1710 helixhorne 2211
                        continue;
2212
                    }
2213
 
2214
                    if (doset)
2215
                        show2dsprite[index>>3] |= (1<<(index&7));
2216
                    else
2217
                        show2dsprite[index>>3] &= ~(1<<(index&7));
2218
                }
1927 helixhorne 2219
                else
1710 helixhorne 2220
                {
1927 helixhorne 2221
                    if (index < 0 || index>=numwalls)
2222
                    {
2223
                        M32_ERROR("Invalid wall index %d", index);
2224
                        continue;
2225
                    }
1710 helixhorne 2226
 
2227
                    if (doset)
2228
                        show2dwall[index>>3] |= (1<<(index&7));
2229
                    else
2230
                        show2dwall[index>>3] &= ~(1<<(index&7));
2231
                }
2232
 
1955 helixhorne 2233
                vm.miscflags |= VMFLAG_MISC_UPDATEHL;
1710 helixhorne 2234
 
2235
                continue;
2236
            }
2237
 
1927 helixhorne 2238
        case CON_SETHIGHLIGHTSECTOR:
2239
            insptr++;
2240
            {
2241
                int32_t index=Gv_GetVarX(*insptr++), doset = Gv_GetVarX(*insptr++);
2242
 
2243
                if (highlightcnt >= 0)
2244
                {
2245
                    M32_ERROR("sprite/wall highlight active or pending, cannot highlight sectors");
2246
                    continue;
2247
                }
2248
 
2249
                X_ERROR_INVALIDSECT(index);
2250
 
2251
                if (doset)
2252
                    hlsectorbitmap[index>>3] |= (1<<(index&7));
2253
                else
2254
                    hlsectorbitmap[index>>3] &= ~(1<<(index&7));
2255
 
1955 helixhorne 2256
                vm.miscflags |= VMFLAG_MISC_UPDATEHLSECT;
1927 helixhorne 2257
 
2258
                continue;
2259
            }
2260
 
1493 helixhorne 2261
        case CON_GETTIMEDATE:
2262
            insptr++;
2263
            {
2264
                int32_t v1=*insptr++,v2=*insptr++,v3=*insptr++,v4=*insptr++,v5=*insptr++,v6=*insptr++,v7=*insptr++,v8=*insptr++;
2265
                time_t rawtime;
1677 terminx 2266
                struct tm *ti;
1493 helixhorne 2267
 
2268
                time(&rawtime);
2269
                ti = localtime(&rawtime);
2270
                // initprintf("Time&date: %s\n",asctime (ti));
2271
 
2272
                Gv_SetVarX(v1, ti->tm_sec);
2273
                Gv_SetVarX(v2, ti->tm_min);
2274
                Gv_SetVarX(v3, ti->tm_hour);
2275
                Gv_SetVarX(v4, ti->tm_mday);
2276
                Gv_SetVarX(v5, ti->tm_mon);
2277
                Gv_SetVarX(v6, ti->tm_year+1900);
2278
                Gv_SetVarX(v7, ti->tm_wday);
2279
                Gv_SetVarX(v8, ti->tm_yday);
2280
                continue;
2281
            }
2282
 
2283
        case CON_ADDLOG:
2284
        {
2285
            insptr++;
2286
 
2287
            OSD_Printf("L=%d\n", g_errorLineNum);
2288
            continue;
2289
        }
2290
 
2291
        case CON_ADDLOGVAR:
2292
            insptr++;
2293
            {
2294
                char buf[80] = "", buf2[80] = "";
2295
                int32_t code = (int32_t)*insptr, val = Gv_GetVarX(code);
1649 helixhorne 2296
                int32_t negate=code&M32_FLAG_NEGATE;
1493 helixhorne 2297
 
2298
                if (code & (0xFFFFFFFF-(MAXGAMEVARS-1)))
2299
                {
1691 helixhorne 2300
                    if ((code&M32_VARTYPE_MASK)==M32_FLAG_ARRAY || (code&M32_VARTYPE_MASK)==M32_FLAG_STRUCT)
1493 helixhorne 2301
                    {
1691 helixhorne 2302
                        if (code&M32_FLAG_CONSTANT)
1493 helixhorne 2303
                            Bsprintf(buf2, "%d", (code>>16)&0xffff);
2304
                        else
1691 helixhorne 2305
                        {
2306
                            char *label = aGameVars[(code>>16)&(MAXGAMEVARS-1)].szLabel;
2307
                            Bsprintf(buf2, "%s", label?label:"???");
2308
                        }
1493 helixhorne 2309
                    }
1691 helixhorne 2310
                    else if ((code&M32_VARTYPE_MASK)==M32_FLAG_LOCAL)
2311
                        Bsprintf(buf2, "%d", code&(MAXGAMEVARS-1));
1493 helixhorne 2312
 
1691 helixhorne 2313
                    if ((code&0x0000FFFC) == M32_FLAG_CONSTANT) // addlogvar for a constant.. why not? :P
1496 helixhorne 2314
                    {
2315
                        switch (code&3)
2316
                        {
2317
                        case 0: Bsprintf(buf, "(immediate constant)"); break;
2318
                        case 1: Bsprintf(buf, "(indirect constant)"); break;
2319
                        case 2: Bsprintf(buf, "(label constant)"); break;
2320
                        default: Bsprintf(buf, "(??? constant)"); break;
2321
                        }
2322
                    }
1493 helixhorne 2323
                    else
1691 helixhorne 2324
                    {
2325
                        switch (code&M32_VARTYPE_MASK)
2326
                        {
2327
                        case M32_FLAG_ARRAY:
2328
                            Bsprintf(buf, "%s[%s]", aGameArrays[code&(MAXGAMEARRAYS-1)].szLabel?
2329
                                     aGameArrays[code&(MAXGAMEARRAYS-1)].szLabel:"???", buf2);
2330
                            break;
2331
                        case M32_FLAG_STRUCT:
1877 helixhorne 2332
                        {
2333
                            int32_t memberid=(code>>2)&63, lightp = (memberid >= LIGHT_X);
2334
                            const char *pp1[4] = {"sprite","sector","wall","tsprite"};
2335
                            const memberlabel_t *pp2[4] = {SpriteLabels, SectorLabels, WallLabels, SpriteLabels};
2336
                            if (lightp)
2337
                            {
2338
                                pp1[3] = "light";
2339
                                pp2[3] = LightLabels;
2340
                                memberid -= LIGHT_X;
2341
                            }
2342
 
2343
                            Bsprintf(buf, "%s[%s].%s", pp1[code&3], buf2, pp2[code&3][memberid].name);
2344
                        }
2345
                        break;
1691 helixhorne 2346
                        case M32_FLAG_VAR:
2347
                            Bsprintf(buf, "???");
2348
                            break;
2349
                        case M32_FLAG_LOCAL:
2350
                            Bsprintf(buf, ".local[%s]", buf2);
2351
                            break;
2352
                        }
2353
                    }
1493 helixhorne 2354
                }
2355
                else
2356
                {
2357
                    if (aGameVars[code].dwFlags & GAMEVAR_PERBLOCK)
2358
                    {
2359
                        Bsprintf(buf2, "(%s", vm.g_st==0? "top-level) " : vm.g_st<=MAXEVENTS? "event" : "state");
2360
                        if (vm.g_st >= 1+MAXEVENTS && vm.g_st <1+MAXEVENTS+g_stateCount)
2361
                            Bsprintf(buf, " `%s') ", statesinfo[vm.g_st-1-MAXEVENTS].name);
2362
                        else if (vm.g_st > 0)
2363
                            Bsprintf(buf, " %d) ", vm.g_st-1);
2364
                        Bstrcat(buf2, buf);
2365
                    }
2366
 
2367
                    Bsprintf(buf, "%s%s", buf2, aGameVars[code].szLabel ? aGameVars[code].szLabel : "???");
2368
                }
2369
 
2370
                OSD_Printf("L%d: %s%s=%d\n", g_errorLineNum, negate?"-":"", buf, val);
2371
 
2372
                insptr++;
2373
                continue;
2374
            }
2375
 
2376
        case CON_DEBUG:
2377
            insptr++;
2378
            initprintf("%d\n",*insptr++);
2379
            continue;
2380
 
2381
// *** strings
2382
        case CON_REDEFINEQUOTE:
2383
            insptr++;
2384
            {
2385
                int32_t q = *insptr++, i = *insptr++;
1497 helixhorne 2386
                X_ERROR_INVALIDQUOTE(q, ScriptQuotes);
2387
                X_ERROR_INVALIDQUOTE(i, ScriptQuoteRedefinitions);
1493 helixhorne 2388
                Bstrcpy(ScriptQuotes[q],ScriptQuoteRedefinitions[i]);
2389
                continue;
2390
            }
2391
 
2392
            insptr++;
1497 helixhorne 2393
            X_ERROR_INVALIDQUOTE(*insptr, ScriptQuotes);
2394
            OSD_Printf("%s", ScriptQuotes[*insptr++]);
2395
            continue;
1493 helixhorne 2396
 
1955 helixhorne 2397
        case CON_GETNUMBER16:  /* deprecated */
2398
        case CON_GETNUMBER256:  /* deprecated */
2399
        case CON_GETNUMBERFROMUSER:
1497 helixhorne 2400
            insptr++;
1493 helixhorne 2401
            {
1691 helixhorne 2402
                int32_t var=*insptr++, quote=*insptr++;
2403
                const char *quotetext = GetMaybeInlineQuote(quote);
2404
                if (vm.flags&VMFLAG_ERROR)
2405
                    continue;
1497 helixhorne 2406
 
1691 helixhorne 2407
                {
1955 helixhorne 2408
                    int32_t max=Gv_GetVarX(*insptr++);
2409
                    int32_t sign = (tw==CON_GETNUMBERFROMUSER) ? Gv_GetVarX(*insptr++) : (max<=0);
1691 helixhorne 2410
                    char buf[64];  // buffers in getnumber* are 80 bytes long
1497 helixhorne 2411
 
2559 helixhorne 2412
                    Bstrncpyz(buf, quotetext, sizeof(buf));
1691 helixhorne 2413
 
1696 helixhorne 2414
                    if (max==0)
1955 helixhorne 2415
                        max = INT32_MAX;
4196 helixhorne 2416
                    else
2417
                        max = klabs(max);
1696 helixhorne 2418
 
1710 helixhorne 2419
//OSD_Printf("max:%d, sign:%d\n", max, sign);
1955 helixhorne 2420
                    if (tw==CON_GETNUMBERFROMUSER)
2421
                    {
3823 helixhorne 2422
                        Gv_SetVarX(var, in3dmode() ?
1955 helixhorne 2423
                                   getnumber256(quotetext, Gv_GetVarX(var), max, sign) :
2424
                                   getnumber16(quotetext, Gv_GetVarX(var), max, sign));
2425
                    }
2426
                    else if (tw==CON_GETNUMBER16)
1691 helixhorne 2427
                        Gv_SetVarX(var, getnumber16(quotetext, Gv_GetVarX(var), max, sign));
2428
                    else
2429
                        Gv_SetVarX(var, getnumber256(quotetext, Gv_GetVarX(var), max, sign));
2430
                }
1493 helixhorne 2431
            }
2432
            continue;
2433
 
1521 helixhorne 2434
        case CON_PRINT:
1493 helixhorne 2435
        case CON_QUOTE:
2436
        case CON_ERRORINS:
2437
        case CON_PRINTMESSAGE16:
2438
        case CON_PRINTMESSAGE256:
2439
        case CON_PRINTEXT256:
1497 helixhorne 2440
        case CON_PRINTEXT16:
1832 helixhorne 2441
        case CON_DRAWLABEL:
1493 helixhorne 2442
            insptr++;
2443
            {
1691 helixhorne 2444
                int32_t i=*insptr++;
2445
                const char *quotetext = GetMaybeInlineQuote(i);
2446
                if (vm.flags&VMFLAG_ERROR)
2447
                    continue;
1493 helixhorne 2448
 
1691 helixhorne 2449
                {
2450
                    int32_t x=(tw>=CON_PRINTMESSAGE256)?Gv_GetVarX(*insptr++):0;
2451
                    int32_t y=(tw>=CON_PRINTMESSAGE256)?Gv_GetVarX(*insptr++):0;
1832 helixhorne 2452
 
1691 helixhorne 2453
                    int32_t col=(tw>=CON_PRINTEXT256)?Gv_GetVarX(*insptr++):0;
2454
                    int32_t backcol=(tw>=CON_PRINTEXT256)?Gv_GetVarX(*insptr++):0;
2455
                    int32_t fontsize=(tw>=CON_PRINTEXT256)?Gv_GetVarX(*insptr++):0;
1493 helixhorne 2456
 
1691 helixhorne 2457
                    if (tw==CON_PRINT || tw==CON_ERRORINS)
1832 helixhorne 2458
                    {
1691 helixhorne 2459
                        OSD_Printf("%s\n", quotetext);
1832 helixhorne 2460
                        if (tw==CON_ERRORINS)
2461
                            vm.flags |= VMFLAG_ERROR;
2462
                    }
1691 helixhorne 2463
                    else if (tw==CON_QUOTE)
1832 helixhorne 2464
                    {
1691 helixhorne 2465
                        message("%s", quotetext);
1832 helixhorne 2466
                    }
1691 helixhorne 2467
                    else if (tw==CON_PRINTMESSAGE16)
1832 helixhorne 2468
                    {
3823 helixhorne 2469
                        if (!in3dmode())
1832 helixhorne 2470
                            printmessage16("%s", quotetext);
2471
                    }
1691 helixhorne 2472
                    else if (tw==CON_PRINTMESSAGE256)
1832 helixhorne 2473
                    {
3823 helixhorne 2474
                        if (in3dmode())
1832 helixhorne 2475
                            printmessage256(x, y, quotetext);
2476
                    }
1691 helixhorne 2477
                    else if (tw==CON_PRINTEXT256)
2478
                    {
3823 helixhorne 2479
                        if (in3dmode())
1832 helixhorne 2480
                        {
2816 helixhorne 2481
                            if (col>=256)
2482
                                col=0;
2483
                            else if (col < 0 && col >= -255)
2484
                                col = editorcolors[-col];
2485
 
2486
                            if (backcol<0 || backcol>=256)
2487
                                backcol=-1;
2488
 
1832 helixhorne 2489
                            printext256(x, y, col, backcol, quotetext, fontsize);
2490
                        }
1691 helixhorne 2491
                    }
2492
                    else if (tw==CON_PRINTEXT16)
2493
                    {
3823 helixhorne 2494
                        if (!in3dmode())
1832 helixhorne 2495
                            printext16(x, y, editorcolors[col&255], backcol<0 ? -1 : editorcolors[backcol&255],
2496
                                       quotetext, fontsize);
1691 helixhorne 2497
                    }
1832 helixhorne 2498
                    else if (tw==CON_DRAWLABEL)
2499
                    {
3823 helixhorne 2500
                        if (!in3dmode())
1832 helixhorne 2501
                        {
2502
                            drawsmallabel(quotetext,
2503
                                          editorcolors[backcol&255],  // col
2504
                                          fontsize < 0 ? -1 : editorcolors[fontsize&255],  // backcol
2505
                                          x, y, col);  // x y z
2506
                        }
2507
                    }
1493 helixhorne 2508
                }
2509
            }
2510
            continue;
2511
 
2512
        case CON_QSTRLEN:
2513
            insptr++;
2514
            {
1691 helixhorne 2515
                int32_t i=*insptr++, quote=*insptr++;
2516
                const char *quotetext = GetMaybeInlineQuote(quote);
2517
                if (vm.flags&VMFLAG_ERROR)
2518
                    continue;
1497 helixhorne 2519
 
1691 helixhorne 2520
                Gv_SetVarX(i, Bstrlen(quotetext));
1493 helixhorne 2521
                continue;
2522
            }
2523
 
2524
        case CON_QSUBSTR:
2525
            insptr++;
2526
            {
2527
                int32_t q1 = Gv_GetVarX(*insptr++);
1691 helixhorne 2528
                int32_t q2 = *insptr++;
2529