m32exec.cpp
1 //------------------------------------------------------------------------- 2 /* 3 Copyright (C) 2010 EDuke32 developers and contributors 4 5 This file is part of EDuke32. 6 7 EDuke32 is free software; you can redistribute it and/or 8 modify it under the terms of the GNU General Public License version 2 9 as published by the Free Software Foundation. 10 11 This program is distributed in the hope that it will be useful, 12 but WITHOUT ANY WARRANTY; without even the implied warranty of 13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. 14 15 See the GNU General Public License for more details. 16 17 You should have received a copy of the GNU General Public License 18 along with this program; if not, write to the Free Software 19 Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. 20 */ 21 //------------------------------------------------------------------------- 22 23 // This object is shared by the editors of *all* Build games! 24 25 #include "compat.h" 26 27 #include "m32script.h" 28 #include "m32def.h" 29 30 //#include "sounds_mapster32.h" 31 32 #include "osd.h" 33 #include "keys.h" 34 #include "common.h" 35 36 #include "colmatch.h" 37 38 // from macros.h 39 #define rnd(X) ((krand()>>8)>=(255-(X))) 40 41 vmstate_t vm; 42 vmstate_t vm_default = 43 { 44 -1, // g_i 45 0, // g_st 46 NULL, // g_sp 47 0, // flags 48 0, // miscflags 49 }; 50 51 int32_t g_errorLineNum, g_tw; 52 53 uint8_t aEventEnabled[MAXEVENTS]; 54 55 uint32_t m32_drawlinepat=0xffffffff; 56 int32_t m32_script_expertmode = 0; 57 58 instype *insptr; 59 60 static instype *x_sortingstateptr; 61 62 //#include "m32structures.cpp" 63 64 #ifdef DEBUGGINGAIDS 65 void X_Disasm(ofstype beg, int32_t size) 66 { 67 instype *p; 68 69 if (!apScript) return; 70 if (beg<0 || beg+size>g_scriptSize) return; 71 72 initprintf("beg=%d, size=%d: ", beg, size); 73 for (p=apScript+beg; p<apScript+beg+size; p++) 74 { 75 if (*p>>12 && (*p&0xFFF)<CON_END) 76 initprintf("%s ", keyw[*p&0xFFF]); 77 else 78 initprintf("%d ", *p); 79 } 80 initprintf("\n"); 81 } 82 #endif 83 84 void VM_ScriptInfo(void) 85 { 86 if (apScript) 87 { 88 instype *p; 89 if (insptr) 90 for (p=max(insptr-20,apScript); p<min(insptr+20, apScript+g_scriptSize); p++) 91 { 92 if (p==insptr) initprintf("<<"); 93 94 if (*p>>12 && (*p&0xFFF)<CON_END) 95 initprintf("\n%5d: L%5d: %s ",(int32_t)(p-apScript),(int32_t)(*p>>12),keyw[*p&0xFFF]); 96 else initprintf(" %d",*p); 97 98 if (p==insptr) initprintf(">>"); 99 } 100 initprintf(" \n"); 101 if (vm.spriteNum >= 0) 102 initprintf("current sprite: %d\n",vm.spriteNum); 103 if (g_tw>=0 && g_tw<CON_END) 104 initprintf("g_errorLineNum: %d, g_tw: %s\n",g_errorLineNum,keyw[g_tw]); 105 else 106 initprintf("g_errorLineNum: %d, g_tw: %d\n",g_errorLineNum,g_tw); 107 } 108 } 109 110 void M32_PostScriptExec(void) 111 { 112 if (vm.miscflags&VMFLAG_MISC_UPDATEHL) 113 { 114 update_highlight(); 115 vm.miscflags &= ~VMFLAG_MISC_UPDATEHL; 116 } 117 118 if (vm.miscflags&VMFLAG_MISC_UPDATEHLSECT) 119 { 120 update_highlightsector(); 121 if (!in3dmode()) 122 ovh_whiteoutgrab(1); 123 vm.miscflags &= ~VMFLAG_MISC_UPDATEHLSECT; 124 } 125 } 126 127 void VM_OnEvent(int32_t iEventID, int32_t spriteNum) 128 { 129 if (iEventID < 0 || iEventID >= MAXEVENTS) 130 { 131 M32_PRINTERROR("Invalid event ID"); 132 return; 133 } 134 135 if (aEventOffsets[iEventID] < 0 || !aEventEnabled[iEventID]) 136 { 137 //Bsprintf(g_szBuf,"No event found for %d",iEventID); 138 //AddLog(g_szBuf); 139 return; 140 } 141 142 { 143 instype *const oinsptr=insptr; 144 vmstate_t vm_backup; 145 void *const olocalvars = aGameArrays[M32_LOCAL_ARRAY_ID].vals; 146 #ifdef M32_LOCALS_VARARRAY 147 int32_t localvars[aEventNumLocals[iEventID]]; 148 #else 149 int32_t localvars[M32_LOCALS_FIXEDNUM]; 150 #endif 151 152 // Initialize 'state'-local variables to 0. 153 if (aEventNumLocals[iEventID] > 0) 154 Bmemset(localvars, 0, aEventNumLocals[iEventID]*sizeof(int32_t)); 155 156 Bmemcpy(&vm_backup, &vm, sizeof(vmstate_t)); 157 158 vm.spriteNum = spriteNum; // current sprite ID 159 if (vm.spriteNum >= 0) 160 vm.pSprite = &sprite[vm.spriteNum]; 161 162 vm.g_st = 1+iEventID; 163 164 vm.flags = 0; 165 166 insptr = apScript + aEventOffsets[iEventID]; 167 168 aGameArrays[M32_LOCAL_ARRAY_ID].vals = localvars; 169 VM_Execute(0); 170 aGameArrays[M32_LOCAL_ARRAY_ID].vals = olocalvars; 171 172 if (vm.flags&VMFLAG_ERROR) 173 { 174 aEventEnabled[iEventID] = 0; 175 message("ERROR executing %s. Event disabled.", label+(iEventID*MAXLABELLEN)); 176 } 177 178 M32_PostScriptExec(); 179 180 // restore old values... 181 Bmemcpy(&vm, &vm_backup, sizeof(vmstate_t)); 182 insptr = oinsptr; 183 184 //AddLog("End of Execution"); 185 } 186 } 187 188 static int32_t G_GetAngleDelta(int32_t a,int32_t na) 189 { 190 a &= 2047; 191 na &= 2047; 192 193 if (klabs(a-na) < 1024) 194 { 195 // OSD_Printf("G_GetAngleDelta() returning %d\n",na-a); 196 return na-a; 197 } 198 199 if (na > 1024) na -= 2048; 200 if (a > 1024) a -= 2048; 201 202 // OSD_Printf("G_GetAngleDelta() returning %d\n",na-a); 203 return na-a; 204 } 205 206 static inline void __fastcall VM_DoConditional(int32_t condition) 207 { 208 if (condition) 209 { 210 // skip 'else' pointer.. and... 211 insptr+=2; 212 VM_Execute(1); 213 return; 214 } 215 216 insptr++; 217 insptr += *insptr; 218 if (((*insptr)&0xFFF) == CON_ELSE) 219 { 220 // else... 221 // skip 'else' and... 222 insptr+=2; 223 VM_Execute(1); 224 } 225 } 226 227 static int X_DoSortDefault(const void *lv, const void *rv) 228 { 229 return *(int32_t const *)rv - *(int32_t const *)lv; 230 } 231 232 static int X_DoSort(const void *lv, const void *rv) 233 { 234 m32_sortvar1 = *(int32_t const *)lv; 235 m32_sortvar2 = *(int32_t const *)rv; 236 insptr = x_sortingstateptr; 237 VM_Execute(0); 238 return g_iReturnVar; 239 } 240 241 // in interactive execution, allow the current sprite index to be the aimed-at sprite (in 3d mode) 242 #define X_ERROR_INVALIDCI() \ 243 if ((vm.spriteNum < 0 || vm.spriteNum >= MAXSPRITES) && \ 244 (vm.g_st != 0 || searchstat != 3 || (vm.spriteNum = searchwall, vm.pSprite = &sprite[vm.spriteNum], 0))) \ 245 { \ 246 M32_ERROR("Current sprite index invalid!"); \ 247 continue; \ 248 } 249 250 #define X_ERROR_INVALIDSPRI(dasprite) \ 251 if (dasprite < 0 || dasprite >= MAXSPRITES) \ 252 { \ 253 M32_ERROR("Invalid sprite index %d!", dasprite); \ 254 continue; \ 255 } 256 257 #define X_ERROR_INVALIDSECT(dasect) \ 258 if (dasect < 0 || dasect >= numsectors) \ 259 { \ 260 M32_ERROR("Invalid sector index %d!", dasect); \ 261 continue; \ 262 } 263 264 #define X_ERROR_INVALIDSP() \ 265 if (!vm.pSprite && (vm.g_st != 0 || searchstat != 3 || (vm.pSprite = &sprite[searchwall], 0))) \ 266 { \ 267 M32_ERROR("Current sprite invalid!"); \ 268 continue; \ 269 } 270 271 #define X_ERROR_INVALIDQUOTE(q, array) \ 272 if (q < 0 || q >= MAXQUOTES) \ 273 { \ 274 M32_ERROR("Invalid quote number %d!", q); \ 275 continue; \ 276 } \ 277 else if (array[q] == NULL) \ 278 { \ 279 M32_ERROR("Null quote %d!", q); \ 280 continue; \ 281 } 282 283 static char *GetMaybeInlineQuote(int32_t quotei) 284 { 285 char *quotetext; 286 if (quotei==-1) 287 { 288 quotetext = (char *)insptr; 289 while (*insptr++) /* skip the string */; 290 } 291 else 292 { 293 quotei = Gv_GetVar(quotei); 294 do { X_ERROR_INVALIDQUOTE(quotei, apStrings) } while (0); 295 if (vm.flags&VMFLAG_ERROR) 296 return NULL; 297 quotetext = apStrings[quotei]; 298 } 299 300 return quotetext; 301 } 302 303 static int CheckArray(int aidx) 304 { 305 if (!(aidx >= 0 && aidx < g_gameArrayCount)) 306 M32_ERROR("Invalid array %d!", aidx); 307 308 return (vm.flags&VMFLAG_ERROR); 309 } 310 311 int32_t VM_Execute(int32_t once) 312 { 313 int32_t tw = *insptr; 314 315 // jump directly into the loop, saving us from the checks during the first iteration 316 goto skip_check; 317 318 while (!once) 319 { 320 if (vm.flags) 321 return 1; 322 323 tw = *insptr; 324 325 skip_check: 326 // Bsprintf(g_szBuf,"Parsing: %d",*insptr); 327 // AddLog(g_szBuf); 328 329 g_errorLineNum = tw>>12; 330 g_tw = (tw &= 0xFFF); 331 332 switch (tw) 333 { 334 // *** basic commands 335 case CON_NULLOP: 336 insptr++; 337 continue; 338 339 case CON_STATE: 340 { 341 instype *const tempscrptr = insptr+2; 342 const int32_t stateidx = *(insptr+1), o_g_st = vm.g_st, oret=vm.flags&VMFLAG_RETURN; 343 void *const olocalvars = aGameArrays[M32_LOCAL_ARRAY_ID].vals; 344 #ifdef M32_LOCALS_VARARRAY 345 int32_t localvars[statesinfo[stateidx].numlocals]; 346 #else 347 int32_t localvars[M32_LOCALS_FIXEDNUM]; 348 #endif 349 350 // needed since any read access before initialization would cause undefined behaviour 351 if (statesinfo[stateidx].numlocals > 0) 352 Bmemset(localvars, 0, statesinfo[stateidx].numlocals*sizeof(int32_t)); 353 354 insptr = apScript + statesinfo[stateidx].ofs; 355 vm.g_st = 1+MAXEVENTS+stateidx; 356 aGameArrays[M32_LOCAL_ARRAY_ID].vals = localvars; 357 VM_Execute(0); 358 aGameArrays[M32_LOCAL_ARRAY_ID].vals = olocalvars; 359 vm.g_st = o_g_st; 360 vm.flags &= ~VMFLAG_RETURN; 361 vm.flags |= oret; 362 insptr = tempscrptr; 363 } 364 continue; 365 366 case CON_RETURN: 367 vm.flags |= VMFLAG_RETURN; 368 return 1; 369 case CON_BREAK: 370 vm.flags |= VMFLAG_BREAK; 371 // XXX: may not be cleared subsequently? 372 fallthrough__; 373 case CON_ENDS: 374 return 1; 375 376 case CON_ELSE: 377 insptr++; 378 insptr += *insptr; 379 continue; 380 381 case CON_ENDSWITCH: 382 vm.flags &= ~VMFLAG_BREAK; 383 fallthrough__; 384 case CON_ENDEVENT: 385 insptr++; 386 return 1; 387 388 case CON_SWITCH: 389 insptr++; // p-code 390 { 391 // command format: 392 // variable ID to check 393 // script offset to 'end' 394 // count of case statements 395 // script offset to default case (null if none) 396 // For each case: value, ptr to code 397 //AddLog("Processing Switch..."); 398 int32_t lValue=Gv_GetVar(*insptr++), lEnd=*insptr++, lCases=*insptr++; 399 instype *lpDefault=insptr++, *lpCases=insptr, *lCodeInsPtr; 400 int32_t bMatched=0, lCheckCase; 401 int32_t left,right; 402 403 insptr += lCases*2; 404 lCodeInsPtr = insptr; 405 //Bsprintf(g_szBuf,"lEnd= %d *lpDefault=%d",lEnd,*lpDefault); AddLog(g_szBuf); 406 //Bsprintf(g_szBuf,"Checking %d cases for %d",lCases, lValue); AddLog(g_szBuf); 407 left = 0; 408 right = lCases-1; 409 while (!bMatched) 410 { 411 //Bsprintf(g_szBuf,"Checking #%d Value= %d",lCheckCase, lpCases[lCheckCase*2]); AddLog(g_szBuf); 412 lCheckCase=(left+right)/2; 413 // initprintf("(%2d..%2d..%2d) [%2d..%2d..%2d]==%2d\n",left,lCheckCase,right,lpCases[left*2],lpCases[lCheckCase*2],lpCases[right*2],lValue); 414 if (lpCases[lCheckCase*2] > lValue) 415 right = lCheckCase-1; 416 else if (lpCases[lCheckCase*2] < lValue) 417 left = lCheckCase+1; 418 else if (lpCases[lCheckCase*2] == lValue) 419 { 420 //AddLog("Found Case Match"); 421 //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); 422 // fake a 2-d Array 423 insptr = lCodeInsPtr + lpCases[lCheckCase*2+1]; 424 //Bsprintf(g_szBuf,"insptr=%d. ", (int32_t)insptr); AddLog(g_szBuf); 425 VM_Execute(0); 426 //AddLog("Done Executing Case"); 427 bMatched=1; 428 } 429 430 if (right-left < 0) 431 break; 432 } 433 434 if (!bMatched) 435 { 436 if (*lpDefault >= 0) 437 { 438 //AddLog("No Matching Case: Using Default"); 439 insptr = lCodeInsPtr + *lpDefault; 440 VM_Execute(0); 441 } 442 // else 443 // { 444 // //AddLog("No Matching Case: No Default to use"); 445 // } 446 } 447 insptr = (instype *)(lCodeInsPtr + lEnd); 448 vm.flags &= ~VMFLAG_BREAK; 449 //Bsprintf(g_szBuf,"insptr=%d. ", (int32_t)insptr); AddLog(g_szBuf); 450 //AddLog("Done Processing Switch"); 451 continue; 452 } 453 454 case CON_GETCURRADDRESS: 455 insptr++; 456 { 457 int32_t j=*insptr++; 458 Gv_SetVar(j, insptr-apScript); 459 } 460 continue; 461 462 case CON_JUMP: 463 insptr++; 464 { 465 int32_t j = Gv_GetVar(*insptr++); 466 if (j<0 || j>=(g_scriptPtr-apScript)) 467 { 468 M32_ERROR("script index out of bounds (%d)", j); 469 continue; 470 } 471 insptr = (instype *)(j+apScript); 472 } 473 continue; 474 475 case CON_RIGHTBRACE: 476 insptr++; 477 return 1; 478 case CON_LEFTBRACE: 479 insptr++; 480 VM_Execute(0); 481 continue; 482 483 // *** arrays 484 case CON_SETARRAY: 485 insptr++; 486 { 487 const int32_t j=*insptr++; 488 const int32_t index = Gv_GetVar(*insptr++); 489 const int32_t value = Gv_GetVar(*insptr++); 490 491 CheckArray(j); 492 493 if (aGameArrays[j].dwFlags & GAMEARRAY_READONLY) 494 M32_ERROR("Tried to set on read-only array `%s'", aGameArrays[j].szLabel); 495 496 if (!(index >= 0 && index < aGameArrays[j].size)) 497 M32_ERROR("Array index %d out of bounds", index); 498 499 if (vm.flags&VMFLAG_ERROR) 500 continue; 501 502 // NOTE: Other array types not implemented, since they're read-only. 503 ((int32_t *)aGameArrays[j].vals)[index] = value; 504 continue; 505 } 506 507 case CON_GETARRAYSIZE: 508 insptr++; 509 { 510 const int32_t j=*insptr++; 511 512 if (CheckArray(j)) 513 continue; 514 515 Gv_SetVar(*insptr++, Gv_GetArraySize(j)); 516 } 517 continue; 518 519 case CON_RESIZEARRAY: 520 insptr++; 521 { 522 const int32_t j=*insptr++; 523 const int32_t asize = Gv_GetVar(*insptr++); 524 525 CheckArray(j); 526 527 if (aGameArrays[j].dwFlags & GAMEARRAY_READONLY) 528 M32_ERROR("Tried to resize read-only array `%s'", aGameArrays[j].szLabel); 529 530 if (!(asize >= 1 && asize <= 65536)) 531 M32_ERROR("Invalid array size %d (must be between 1 and 65536)", asize); 532 533 if (vm.flags&VMFLAG_ERROR) 534 continue; 535 536 // OSD_Printf(OSDTEXT_GREEN "CON_RESIZEARRAY: resizing array %s from %d to %d\n", aGameArrays[j].szLabel, aGameArrays[j].size, asize); 537 aGameArrays[j].vals = Xrealloc(aGameArrays[j].vals, sizeof(int32_t) * asize); 538 aGameArrays[j].size = asize; 539 540 continue; 541 } 542 543 case CON_COPY: 544 insptr++; 545 { 546 const int32_t si=*insptr++; 547 int32_t sidx = Gv_GetVar(*insptr++); 548 const int32_t di=*insptr++; 549 int32_t didx = Gv_GetVar(*insptr++); 550 int32_t numelts = Gv_GetVar(*insptr++); 551 552 CheckArray(si); 553 CheckArray(di); 554 555 if (aGameArrays[di].dwFlags & GAMEARRAY_READONLY) 556 M32_ERROR("Array %d is read-only!", di); 557 if (vm.flags&VMFLAG_ERROR) 558 continue; 559 560 const int32_t ssiz = Gv_GetArraySize(si); 561 const int32_t dsiz = Gv_GetArraySize(di); 562 563 if ((uint32_t)sidx >= (uint32_t)ssiz) 564 M32_ERROR("Invalid source index %d", sidx); 565 if ((uint32_t)didx >= (uint32_t)dsiz) 566 M32_ERROR("Invalid destination index %d", didx); 567 if (vm.flags&VMFLAG_ERROR) 568 continue; 569 570 if (numelts > ssiz-sidx) 571 numelts = ssiz-sidx; 572 if (numelts > dsiz-didx) 573 numelts = dsiz-didx; 574 575 const gamearray_t *const sar = &aGameArrays[si]; 576 gamearray_t *const dar = &aGameArrays[di]; 577 578 switch (sar->dwFlags & GAMEARRAY_TYPE_MASK) 579 { 580 case 0: 581 case GAMEARRAY_INT32: 582 if (sar->dwFlags & GAMEARRAY_STRIDE2) 583 { 584 for (; numelts>0; numelts--, sidx += 2) 585 ((int32_t *)dar->vals)[didx++] = ((int32_t *)sar->vals)[sidx]; 586 } 587 else 588 { 589 Bmemcpy((int32_t *)dar->vals + didx, (int32_t *)sar->vals + sidx, 590 numelts * sizeof(int32_t)); 591 } 592 break; 593 case GAMEARRAY_INT16: 594 for (; numelts>0; numelts--) 595 ((int32_t *)dar->vals)[didx++] = ((int16_t *)sar->vals)[sidx++]; 596 break; 597 case GAMEARRAY_UINT8: 598 for (; numelts>0; numelts--) 599 ((int32_t *)dar->vals)[didx++] = ((uint8_t *)sar->vals)[sidx++]; 600 break; 601 } 602 continue; 603 } 604 605 // *** var & varvar ops 606 case CON_RANDVAR: 607 insptr++; 608 Gv_SetVar(*insptr, mulscale16(krand(), *(insptr+1)+1)); 609 insptr += 2; 610 continue; 611 612 case CON_DISPLAYRANDVAR: 613 insptr++; 614 Gv_SetVar(*insptr, mulscale15(system_15bit_rand(), *(insptr+1)+1)); 615 insptr += 2; 616 continue; 617 618 case CON_SETVAR: 619 insptr++; 620 Gv_SetVar(*insptr, *(insptr+1)); 621 insptr += 2; 622 continue; 623 624 case CON_SETVARVAR: 625 insptr++; 626 { 627 int32_t j=*insptr++; 628 Gv_SetVar(j, Gv_GetVar(*insptr++)); 629 } 630 continue; 631 632 case CON_MULVAR: 633 insptr++; 634 Gv_SetVar(*insptr, Gv_GetVar(*insptr) * *(insptr+1)); 635 insptr += 2; 636 continue; 637 638 case CON_DIVVAR: 639 insptr++; 640 if (*(insptr+1) == 0) 641 { 642 M32_ERROR("Divide by zero."); 643 insptr += 2; 644 continue; 645 } 646 Gv_SetVar(*insptr, Gv_GetVar(*insptr) / *(insptr+1)); 647 insptr += 2; 648 continue; 649 650 case CON_MODVAR: 651 insptr++; 652 if (*(insptr+1) == 0) 653 { 654 M32_ERROR("Mod by zero."); 655 insptr += 2; 656 continue; 657 } 658 Gv_SetVar(*insptr,Gv_GetVar(*insptr)%*(insptr+1)); 659 insptr += 2; 660 continue; 661 662 case CON_ANDVAR: 663 insptr++; 664 Gv_SetVar(*insptr,Gv_GetVar(*insptr) & *(insptr+1)); 665 insptr += 2; 666 continue; 667 668 case CON_ORVAR: 669 insptr++; 670 Gv_SetVar(*insptr,Gv_GetVar(*insptr) | *(insptr+1)); 671 insptr += 2; 672 continue; 673 674 case CON_XORVAR: 675 insptr++; 676 Gv_SetVar(*insptr,Gv_GetVar(*insptr) ^ *(insptr+1)); 677 insptr += 2; 678 continue; 679 680 case CON_RANDVARVAR: 681 insptr++; 682 { 683 int32_t j=*insptr++; 684 Gv_SetVar(j,mulscale16(krand(), Gv_GetVar(*insptr++)+1)); 685 } 686 continue; 687 688 case CON_DISPLAYRANDVARVAR: 689 insptr++; 690 { 691 int32_t j=*insptr++; 692 Gv_SetVar(j,mulscale15(system_15bit_rand(), Gv_GetVar(*insptr++)+1)); 693 } 694 continue; 695 696 case CON_MULVARVAR: 697 insptr++; 698 { 699 int32_t j=*insptr++; 700 Gv_SetVar(j, Gv_GetVar(j)*Gv_GetVar(*insptr++)); 701 } 702 continue; 703 704 case CON_DIVVARVAR: 705 insptr++; 706 { 707 int32_t j=*insptr++; 708 int32_t l2=Gv_GetVar(*insptr++); 709 710 if (l2==0) 711 { 712 M32_ERROR("Divide by zero."); 713 continue; 714 } 715 Gv_SetVar(j, Gv_GetVar(j)/l2); 716 continue; 717 } 718 719 case CON_MODVARVAR: 720 insptr++; 721 { 722 int32_t j=*insptr++; 723 int32_t l2=Gv_GetVar(*insptr++); 724 725 if (l2==0) 726 { 727 M32_ERROR("Mod by zero."); 728 continue; 729 } 730 731 Gv_SetVar(j, Gv_GetVar(j) % l2); 732 continue; 733 } 734 735 case CON_ANDVARVAR: 736 insptr++; 737 { 738 int32_t j=*insptr++; 739 Gv_SetVar(j, Gv_GetVar(j) & Gv_GetVar(*insptr++)); 740 } 741 continue; 742 743 case CON_XORVARVAR: 744 insptr++; 745 { 746 int32_t j=*insptr++; 747 Gv_SetVar(j, Gv_GetVar(j) ^ Gv_GetVar(*insptr++)); 748 } 749 continue; 750 751 case CON_ORVARVAR: 752 insptr++; 753 { 754 int32_t j=*insptr++; 755 Gv_SetVar(j, Gv_GetVar(j) | Gv_GetVar(*insptr++)); 756 } 757 continue; 758 759 case CON_SUBVAR: 760 insptr++; 761 Gv_SetVar(*insptr, Gv_GetVar(*insptr) - *(insptr+1)); 762 insptr += 2; 763 continue; 764 765 case CON_SUBVARVAR: 766 insptr++; 767 { 768 int32_t j=*insptr++; 769 Gv_SetVar(j, Gv_GetVar(j) - Gv_GetVar(*insptr++)); 770 } 771 continue; 772 773 case CON_ADDVAR: 774 insptr++; 775 Gv_SetVar(*insptr, Gv_GetVar(*insptr) + *(insptr+1)); 776 insptr += 2; 777 continue; 778 779 case CON_ADDVARVAR: 780 insptr++; 781 { 782 int32_t j=*insptr++; 783 Gv_SetVar(j, Gv_GetVar(j) + Gv_GetVar(*insptr++)); 784 } 785 continue; 786 787 case CON_SHIFTVARL: 788 insptr++; 789 Gv_SetVar(*insptr, Gv_GetVar(*insptr) << *(insptr+1)); 790 insptr += 2; 791 continue; 792 793 case CON_SHIFTVARVARL: 794 insptr++; 795 { 796 int32_t j=*insptr++; 797 Gv_SetVar(j, Gv_GetVar(j) << Gv_GetVar(*insptr++)); 798 } 799 continue; 800 801 case CON_SHIFTVARR: 802 insptr++; 803 Gv_SetVar(*insptr, Gv_GetVar(*insptr) >> *(insptr+1)); 804 insptr += 2; 805 continue; 806 807 case CON_SHIFTVARVARR: 808 insptr++; 809 { 810 int32_t j=*insptr++; 811 Gv_SetVar(j, Gv_GetVar(j) >> Gv_GetVar(*insptr++)); 812 } 813 continue; 814 815 case CON_SIN: 816 insptr++; 817 Gv_SetVar(*insptr, sintable[Gv_GetVar(*(insptr+1))&2047]); 818 insptr += 2; 819 continue; 820 821 case CON_COS: 822 insptr++; 823 Gv_SetVar(*insptr, sintable[(Gv_GetVar(*(insptr+1))+512)&2047]); 824 insptr += 2; 825 continue; 826 827 case CON_DISPLAYRAND: 828 insptr++; 829 Gv_SetVar(*insptr++, system_15bit_rand()); 830 continue; 831 832 // *** other math 833 case CON_FTOI: 834 insptr++; 835 { 836 union { int32_t ival; float fval; }; 837 838 ival=Gv_GetVar(*insptr); 839 int32_t const scale=*(insptr+1); 840 // rounding must absolutely be! 841 //OSD_Printf("ftoi: bits:%8x, scale=%d, fval=%f, (int32_t)(fval*scale)=%d\n", bits, scale, fval, (int32_t)(fval*scale)); 842 Gv_SetVar(*insptr, (int32_t)Blrintf(fval * scale)); 843 } 844 insptr += 2; 845 continue; 846 847 case CON_ITOF: 848 insptr++; 849 { 850 union { int32_t ival; float fval; }; 851 852 ival=Gv_GetVar(*insptr); 853 int32_t const scale=*(insptr+1); 854 fval = (float)ival/(float)scale; 855 Gv_SetVar(*insptr, ival); 856 } 857 insptr += 2; 858 continue; 859 860 case CON_CLAMP: 861 insptr++; 862 { 863 int32_t var=*insptr++, min=Gv_GetVar(*insptr++), max=Gv_GetVar(*insptr++); 864 int32_t val=Gv_GetVar(var); 865 866 if (val<min) Gv_SetVar(var, min); 867 else if (val>max) Gv_SetVar(var, max); 868 } 869 continue; 870 871 case CON_INV: 872 Gv_SetVar(*(insptr+1), -Gv_GetVar(*(insptr+1))); 873 insptr += 2; 874 continue; 875 876 case CON_SQRT: 877 insptr++; 878 { 879 // syntax sqrt <invar> <outvar> 880 int32_t lInVarID=*insptr++, lOutVarID=*insptr++; 881 882 Gv_SetVar(lOutVarID, ksqrt((uint32_t)Gv_GetVar(lInVarID))); 883 continue; 884 } 885 886 case CON_LDIST: 887 case CON_DIST: 888 insptr++; 889 { 890 int32_t distvar = *insptr++, xvar = Gv_GetVar(*insptr++), yvar = Gv_GetVar(*insptr++); 891 892 if (xvar < 0 || xvar >= MAXSPRITES || sprite[xvar].statnum==MAXSTATUS) 893 { 894 M32_ERROR("invalid sprite %d", xvar); 895 } 896 if (yvar < 0 || yvar >= MAXSPRITES || sprite[yvar].statnum==MAXSTATUS) 897 { 898 M32_ERROR("invalid sprite %d", yvar); 899 } 900 if (vm.flags&VMFLAG_ERROR) continue; 901 902 if (tw==CON_DIST) 903 Gv_SetVar(distvar, dist(&sprite[xvar],&sprite[yvar])); 904 else 905 Gv_SetVar(distvar, ldist(&sprite[xvar],&sprite[yvar])); 906 continue; 907 } 908 909 case CON_GETANGLE: 910 insptr++; 911 { 912 int32_t angvar = *insptr++; 913 int32_t xvar = Gv_GetVar(*insptr++); 914 int32_t yvar = Gv_GetVar(*insptr++); 915 916 Gv_SetVar(angvar, getangle(xvar,yvar)); 917 continue; 918 } 919 920 case CON_GETINCANGLE: 921 insptr++; 922 { 923 int32_t angvar = *insptr++; 924 int32_t xvar = Gv_GetVar(*insptr++); 925 int32_t yvar = Gv_GetVar(*insptr++); 926 927 Gv_SetVar(angvar, G_GetAngleDelta(xvar,yvar)); 928 continue; 929 } 930 931 case CON_A2XY: 932 case CON_AH2XYZ: 933 insptr++; 934 { 935 int32_t ang=Gv_GetVar(*insptr++), horiz=(tw==CON_A2XY)?100:Gv_GetVar(*insptr++); 936 int32_t xvar=*insptr++, yvar=*insptr++; 937 938 int32_t x = sintable[(ang+512)&2047]; 939 int32_t y = sintable[ang&2047]; 940 941 if (tw==CON_AH2XYZ) 942 { 943 int32_t zvar=*insptr++, z=0; 944 945 horiz -= 100; 946 if (horiz) 947 { 948 int32_t veclen = ksqrt(200*200 + horiz*horiz); 949 int32_t dacos = divscale14(200, veclen); 950 951 x = mulscale14(x, dacos); 952 y = mulscale14(y, dacos); 953 z = divscale14(-horiz, veclen); 954 } 955 956 Gv_SetVar(zvar, z); 957 } 958 959 Gv_SetVar(xvar, x); 960 Gv_SetVar(yvar, y); 961 962 continue; 963 } 964 965 case CON_MULSCALE: 966 insptr++; 967 { 968 int32_t var1 = *insptr++, var2 = Gv_GetVar(*insptr++); 969 int32_t var3 = Gv_GetVar(*insptr++), var4 = Gv_GetVar(*insptr++); 970 971 Gv_SetVar(var1, mulscale(var2, var3, var4)); 972 continue; 973 } 974 case CON_DIVSCALE: 975 insptr++; 976 { 977 int32_t var1 = *insptr++, var2 = Gv_GetVar(*insptr++); 978 int32_t var3 = Gv_GetVar(*insptr++), var4 = Gv_GetVar(*insptr++); 979 980 Gv_SetVar(var1, divscale(var2, var3, var4)); 981 continue; 982 } 983 case CON_SCALEVAR: 984 insptr++; 985 { 986 int32_t var1 = *insptr++, var2 = Gv_GetVar(*insptr++); 987 int32_t var3 = Gv_GetVar(*insptr++), var4 = Gv_GetVar(*insptr++); 988 989 Gv_SetVar(var1, scale(var2, var3, var4)); 990 continue; 991 } 992 993 // *** if & while 994 case CON_IFVARVARAND: 995 insptr++; 996 { 997 int32_t j = Gv_GetVar(*insptr++); 998 j &= Gv_GetVar(*insptr++); 999 insptr--; 1000 VM_DoConditional(j); 1001 } 1002 continue; 1003 1004 case CON_IFVARVAROR: 1005 insptr++; 1006 { 1007 int32_t j = Gv_GetVar(*insptr++); 1008 j |= Gv_GetVar(*insptr++); 1009 insptr--; 1010 VM_DoConditional(j); 1011 } 1012 continue; 1013 1014 case CON_IFVARVARXOR: 1015 insptr++; 1016 { 1017 int32_t j = Gv_GetVar(*insptr++); 1018 j ^= Gv_GetVar(*insptr++); 1019 insptr--; 1020 VM_DoConditional(j); 1021 } 1022 continue; 1023 1024 case CON_IFVARVAREITHER: 1025 insptr++; 1026 { 1027 int32_t j = Gv_GetVar(*insptr++); 1028 int32_t l = Gv_GetVar(*insptr++); 1029 insptr--; 1030 VM_DoConditional(j || l); 1031 } 1032 continue; 1033 1034 case CON_IFVARVARBOTH: 1035 insptr++; 1036 { 1037 int32_t j = Gv_GetVar(*insptr++); 1038 int32_t l = Gv_GetVar(*insptr++); 1039 insptr--; 1040 VM_DoConditional(j && l); 1041 } 1042 continue; 1043 1044 case CON_IFVARVARN: 1045 insptr++; 1046 { 1047 int32_t j = Gv_GetVar(*insptr++); 1048 j = (j != Gv_GetVar(*insptr++)); 1049 insptr--; 1050 VM_DoConditional(j); 1051 } 1052 continue; 1053 1054 case CON_IFVARVARE: 1055 insptr++; 1056 { 1057 int32_t j = Gv_GetVar(*insptr++); 1058 j = (j == Gv_GetVar(*insptr++)); 1059 insptr--; 1060 VM_DoConditional(j); 1061 } 1062 continue; 1063 1064 case CON_IFVARVARG: 1065 insptr++; 1066 { 1067 int32_t j = Gv_GetVar(*insptr++); 1068 j = (j > Gv_GetVar(*insptr++)); 1069 insptr--; 1070 VM_DoConditional(j); 1071 } 1072 continue; 1073 1074 case CON_IFVARVARGE: 1075 insptr++; 1076 { 1077 int32_t j = Gv_GetVar(*insptr++); 1078 j = (j >= Gv_GetVar(*insptr++)); 1079 insptr--; 1080 VM_DoConditional(j); 1081 } 1082 continue; 1083 1084 case CON_IFVARVARL: 1085 insptr++; 1086 { 1087 int32_t j = Gv_GetVar(*insptr++); 1088 j = (j < Gv_GetVar(*insptr++)); 1089 insptr--; 1090 VM_DoConditional(j); 1091 } 1092 continue; 1093 1094 case CON_IFVARVARLE: 1095 insptr++; 1096 { 1097 int32_t j = Gv_GetVar(*insptr++); 1098 j = (j <= Gv_GetVar(*insptr++)); 1099 insptr--; 1100 VM_DoConditional(j); 1101 } 1102 continue; 1103 1104 case CON_IFVARVARA: 1105 insptr++; 1106 { 1107 int32_t j = Gv_GetVar(*insptr++); 1108 j = ((uint32_t)j > (uint32_t)Gv_GetVar(*insptr++)); 1109 insptr--; 1110 VM_DoConditional(j); 1111 } 1112 continue; 1113 1114 case CON_IFVARVARAE: 1115 insptr++; 1116 { 1117 int32_t j = Gv_GetVar(*insptr++); 1118 j = ((uint32_t)j >= (uint32_t)Gv_GetVar(*insptr++)); 1119 insptr--; 1120 VM_DoConditional(j); 1121 } 1122 continue; 1123 1124 case CON_IFVARVARB: 1125 insptr++; 1126 { 1127 int32_t j = Gv_GetVar(*insptr++); 1128 j = ((uint32_t)j < (uint32_t)Gv_GetVar(*insptr++)); 1129 insptr--; 1130 VM_DoConditional(j); 1131 } 1132 continue; 1133 1134 case CON_IFVARVARBE: 1135 insptr++; 1136 { 1137 int32_t j = Gv_GetVar(*insptr++); 1138 j = ((uint32_t)j <= (uint32_t)Gv_GetVar(*insptr++)); 1139 insptr--; 1140 VM_DoConditional(j); 1141 } 1142 continue; 1143 1144 case CON_IFVARE: 1145 insptr++; 1146 { 1147 int32_t j=Gv_GetVar(*insptr++); 1148 VM_DoConditional(j == *insptr); 1149 } 1150 continue; 1151 1152 case CON_IFVARN: 1153 insptr++; 1154 { 1155 int32_t j=Gv_GetVar(*insptr++); 1156 VM_DoConditional(j != *insptr); 1157 } 1158 continue; 1159 1160 case CON_WHILEVARN: 1161 { 1162 instype *savedinsptr=insptr+2; 1163 int32_t j; 1164 do 1165 { 1166 insptr=savedinsptr; 1167 j = (Gv_GetVar(*(insptr-1)) != *insptr); 1168 VM_DoConditional(j); 1169 } 1170 while (j && !vm.flags); 1171 vm.flags &= ~VMFLAG_BREAK; 1172 continue; 1173 } 1174 1175 case CON_WHILEVARL: 1176 { 1177 instype *savedinsptr=insptr+2; 1178 int32_t j; 1179 do 1180 { 1181 insptr=savedinsptr; 1182 j = (Gv_GetVar(*(insptr-1)) < *insptr); 1183 VM_DoConditional(j); 1184 } 1185 while (j && !vm.flags); 1186 vm.flags &= ~VMFLAG_BREAK; 1187 continue; 1188 } 1189 1190 case CON_WHILEVARVARN: 1191 { 1192 int32_t j; 1193 instype *savedinsptr=insptr+2; 1194 do 1195 { 1196 insptr=savedinsptr; 1197 j = Gv_GetVar(*(insptr-1)); 1198 j = (j != Gv_GetVar(*insptr++)); 1199 insptr--; 1200 VM_DoConditional(j); 1201 } 1202 while (j && !vm.flags); 1203 vm.flags &= ~VMFLAG_BREAK; 1204 continue; 1205 } 1206 1207 case CON_WHILEVARVARL: 1208 { 1209 int32_t j; 1210 instype *savedinsptr=insptr+2; 1211 do 1212 { 1213 insptr=savedinsptr; 1214 j = Gv_GetVar(*(insptr-1)); 1215 j = (j < Gv_GetVar(*insptr++)); 1216 insptr--; 1217 VM_DoConditional(j); 1218 } 1219 while (j && !vm.flags); 1220 vm.flags &= ~VMFLAG_BREAK; 1221 continue; 1222 } 1223 1224 case CON_COLLECTSECTORS: 1225 insptr++; 1226 { 1227 const int32_t aridx=*insptr++, startsectnum=Gv_GetVar(*insptr++); 1228 const int32_t numsectsVar=*insptr++, state=*insptr++; 1229 1230 if (CheckArray(aridx)) 1231 continue; 1232 1233 gamearray_t *const gar = &aGameArrays[aridx]; 1234 Bassert((gar->dwFlags & (GAMEARRAY_READONLY|GAMEARRAY_VARSIZE)) == 0); 1235 1236 const int32_t o_g_st=vm.g_st, arsize = gar->size; 1237 instype *const end=insptr; 1238 int16_t sectcnt, numsects=0; 1239 1240 // XXX: relies on -fno-strict-aliasing 1241 int16_t *const sectlist = (int16_t *)gar->vals; // actually an int32_t array 1242 int32_t *const sectlist32 = (int32_t *)sectlist; 1243 1244 int32_t j, startwall, endwall, ns; 1245 static uint8_t sectbitmap[bitmap_size(MAXSECTORS)]; 1246 1247 X_ERROR_INVALIDSECT(startsectnum); 1248 if (arsize < numsectors) 1249 { 1250 M32_ERROR("Array size must be at least numsectors (=%d) for collecting!", 1251 numsectors); 1252 continue; 1253 } 1254 1255 // collect! 1256 bfirst_search_init(sectlist, sectbitmap, &numsects, MAXSECTORS, startsectnum); 1257 1258 for (sectcnt=0; sectcnt<numsects; sectcnt++) 1259 for (WALLS_OF_SECTOR(sectlist[sectcnt], j)) 1260 if ((ns=wall[j].nextsector) >= 0 && wall[j].nextsector<numsectors) 1261 { 1262 if (sectbitmap[ns>>3]&(1<<(ns&7))) 1263 continue; 1264 vm.g_st = 1+MAXEVENTS+state; 1265 insptr = apScript + statesinfo[state].ofs; 1266 g_iReturnVar = ns; 1267 VM_Execute(0); 1268 if (g_iReturnVar) 1269 bfirst_search_try(sectlist, sectbitmap, &numsects, wall[j].nextsector); 1270 } 1271 1272 // short->int sector list 1273 for (j=numsects-1; j>=0; j--) 1274 sectlist32[j] = sectlist[j]; 1275 1276 Gv_SetVar(numsectsVar, numsects); 1277 g_iReturnVar = 0; 1278 1279 // restore some VM state 1280 vm.g_st = o_g_st; 1281 insptr = end; 1282 } 1283 continue; 1284 1285 case CON_SORT: 1286 insptr++; 1287 { 1288 const int32_t aridx=*insptr++, count=Gv_GetVar(*insptr++), state=*insptr++; 1289 const int32_t o_g_st = vm.g_st; 1290 instype *const end = insptr; 1291 1292 if (CheckArray(aridx)) 1293 continue; 1294 1295 if (count <= 0) 1296 continue; 1297 1298 gamearray_t *const gar = &aGameArrays[aridx]; 1299 Bassert((gar->dwFlags & (GAMEARRAY_READONLY|GAMEARRAY_VARSIZE)) == 0); 1300 1301 if (count > gar->size) 1302 { 1303 M32_ERROR("Count of elements to sort (%d) exceeds array size (%d)!", 1304 count, gar->size); 1305 continue; 1306 } 1307 1308 if (state < 0) 1309 { 1310 qsort(gar->vals, count, sizeof(int32_t), X_DoSortDefault); 1311 } 1312 else 1313 { 1314 x_sortingstateptr = apScript + statesinfo[state].ofs; 1315 vm.g_st = 1+MAXEVENTS+state; 1316 qsort(gar->vals, count, sizeof(int32_t), X_DoSort); 1317 vm.g_st = o_g_st; 1318 insptr = end; 1319 } 1320 } 1321 continue; 1322 1323 case CON_FOR: // special-purpose iteration 1324 insptr++; 1325 { 1326 const int32_t var = *insptr++, how = *insptr++; 1327 const int32_t parm2 = how<=ITER_DRAWNSPRITES ? 0 : Gv_GetVar(*insptr++); 1328 instype *const end = insptr + *insptr, *const beg = ++insptr; 1329 const int32_t vm_i_bak = vm.spriteNum; 1330 auto const vm_sp_bak = vm.pUSprite; 1331 1332 if (vm.flags&VMFLAG_ERROR) 1333 continue; 1334 1335 switch (how) 1336 { 1337 case ITER_ALLSPRITES: 1338 for (bssize_t jj=0; jj<MAXSPRITES && !vm.flags; jj++) 1339 { 1340 if (sprite[jj].statnum == MAXSTATUS) 1341 continue; 1342 Gv_SetVar(var, jj); 1343 vm.spriteNum = jj; 1344 vm.pSprite = &sprite[jj]; 1345 insptr = beg; 1346 VM_Execute(1); 1347 } 1348 break; 1349 case ITER_ALLSECTORS: 1350 for (bssize_t jj=0; jj<numsectors && !vm.flags; jj++) 1351 { 1352 Gv_SetVar(var, jj); 1353 insptr = beg; 1354 VM_Execute(1); 1355 } 1356 break; 1357 case ITER_ALLWALLS: 1358 for (bssize_t jj=0; jj<numwalls && !vm.flags; jj++) 1359 { 1360 Gv_SetVar(var, jj); 1361 insptr = beg; 1362 VM_Execute(1); 1363 } 1364 break; 1365 case ITER_ACTIVELIGHTS: 1366 #ifdef POLYMER 1367 for (bssize_t jj=0; jj<PR_MAXLIGHTS; jj++) 1368 { 1369 if (!prlights[jj].flags.active) 1370 continue; 1371 1372 Gv_SetVar(var, jj); 1373 insptr = beg; 1374 VM_Execute(1); 1375 } 1376 #else 1377 M32_ERROR("Polymer not compiled in, iteration over lights forbidden."); 1378 #endif 1379 break; 1380 1381 case ITER_SELSPRITES: 1382 for (bssize_t ii=0; ii<highlightcnt && !vm.flags; ii++) 1383 { 1384 int jj = highlight[ii]; 1385 if (jj&0xc000) 1386 { 1387 jj &= (MAXSPRITES-1); 1388 Gv_SetVar(var, jj); 1389 vm.spriteNum = jj; 1390 vm.pSprite = &sprite[jj]; 1391 insptr = beg; 1392 VM_Execute(1); 1393 } 1394 } 1395 break; 1396 case ITER_SELSECTORS: 1397 for (bssize_t ii=0; ii<highlightsectorcnt && !vm.flags; ii++) 1398 { 1399 int jj=highlightsector[ii]; 1400 Gv_SetVar(var, jj); 1401 insptr = beg; 1402 VM_Execute(1); 1403 } 1404 break; 1405 case ITER_SELWALLS: 1406 for (bssize_t ii=0; ii<highlightcnt && !vm.flags; ii++) 1407 { 1408 int jj=highlight[ii]; 1409 if (jj&0xc000) 1410 continue; 1411 Gv_SetVar(var, jj); 1412 insptr = beg; 1413 VM_Execute(1); 1414 } 1415 break; 1416 case ITER_DRAWNSPRITES: 1417 { 1418 uspritetype lastSpriteBackup; 1419 auto const lastSpritePtr = (uspritetype *)&sprite[MAXSPRITES-1]; 1420 1421 // Back up sprite MAXSPRITES-1. 1422 Bmemcpy(&lastSpriteBackup, lastSpritePtr, sizeof(uspritetype)); 1423 1424 EDUKE32_STATIC_ASSERT(sizeof(uspritetype) == sizeof(tspritetype)); // see TSPRITE_SIZE 1425 for (bssize_t ii=0; ii<spritesortcnt && !vm.flags; ii++) 1426 { 1427 vm.pUSprite = lastSpritePtr; 1428 Bmemcpy(lastSpritePtr, &tsprite[ii], sizeof(tspritetype)); 1429 1430 Gv_SetVar(var, ii); 1431 insptr = beg; 1432 VM_Execute(1); 1433 1434 // Copy over potentially altered tsprite. 1435 Bmemcpy(&tsprite[ii], lastSpritePtr, sizeof(tspritetype)); 1436 } 1437 1438 // Restore sprite MAXSPRITES-1. 1439 Bmemcpy(lastSpritePtr, &lastSpriteBackup, sizeof(uspritetype)); 1440 break; 1441 } 1442 case ITER_SPRITESOFSECTOR: 1443 if (parm2 < 0 || parm2 >= MAXSECTORS) 1444 goto badindex; 1445 for (bssize_t jj=headspritesect[parm2]; jj>=0 && !vm.flags; jj=nextspritesect[jj]) 1446 { 1447 Gv_SetVar(var, jj); 1448 vm.spriteNum = jj; 1449 vm.pSprite = &sprite[jj]; 1450 insptr = beg; 1451 VM_Execute(1); 1452 } 1453 break; 1454 case ITER_WALLSOFSECTOR: 1455 if (parm2 < 0 || parm2 >= MAXSECTORS) 1456 goto badindex; 1457 for (bssize_t jj=sector[parm2].wallptr, endwall=jj+sector[parm2].wallnum-1; 1458 jj<=endwall && !vm.flags; jj++) 1459 { 1460 Gv_SetVar(var, jj); 1461 insptr = beg; 1462 VM_Execute(1); 1463 } 1464 break; 1465 case ITER_LOOPOFWALL: 1466 if (parm2 < 0 || parm2 >= numwalls) 1467 goto badindex; 1468 { 1469 int jj = parm2; 1470 do 1471 { 1472 Gv_SetVar(var, jj); 1473 insptr = beg; 1474 VM_Execute(1); 1475 jj = wall[jj].point2; 1476 } 1477 while (jj != parm2 && !vm.flags); 1478 } 1479 break; 1480 case ITER_RANGE: 1481 for (bssize_t jj=0; jj<parm2 && !vm.flags; jj++) 1482 { 1483 Gv_SetVar(var, jj); 1484 insptr = beg; 1485 VM_Execute(1); 1486 } 1487 break; 1488 default: 1489 M32_ERROR("Unknown iteration type %d!", how); 1490 continue; 1491 badindex: 1492 OSD_Printf("%sLine %d, %s %s: index %d out of range!\n", osd->draw.highlight, 1493 g_errorLineNum,keyw[g_tw], iter_tokens[how].token, parm2); 1494 vm.flags |= VMFLAG_ERROR; 1495 continue; 1496 } 1497 vm.spriteNum = vm_i_bak; 1498 vm.pUSprite = vm_sp_bak; 1499 vm.flags &= ~VMFLAG_BREAK; 1500 insptr = end; 1501 } 1502 continue; 1503 1504 case CON_IFVARAND: 1505 insptr++; 1506 { 1507 int32_t j=Gv_GetVar(*insptr++); 1508 VM_DoConditional(j & *insptr); 1509 } 1510 continue; 1511 1512 case CON_IFVAROR: 1513 insptr++; 1514 { 1515 int32_t j=Gv_GetVar(*insptr++); 1516 VM_DoConditional(j | *insptr); 1517 } 1518 continue; 1519 1520 case CON_IFVARXOR: 1521 insptr++; 1522 { 1523 int32_t j=Gv_GetVar(*insptr++); 1524 VM_DoConditional(j ^ *insptr); 1525 } 1526 continue; 1527 1528 case CON_IFVAREITHER: 1529 insptr++; 1530 { 1531 int32_t j=Gv_GetVar(*insptr++); 1532 VM_DoConditional(j || *insptr); 1533 } 1534 continue; 1535 1536 case CON_IFVARBOTH: 1537 insptr++; 1538 { 1539 int32_t j=Gv_GetVar(*insptr++); 1540 VM_DoConditional(j && *insptr); 1541 } 1542 continue; 1543 1544 case CON_IFVARG: 1545 insptr++; 1546 { 1547 int32_t j=Gv_GetVar(*insptr++); 1548 VM_DoConditional(j > *insptr); 1549 } 1550 continue; 1551 1552 case CON_IFVARGE: 1553 insptr++; 1554 { 1555 int32_t j=Gv_GetVar(*insptr++); 1556 VM_DoConditional(j >= *insptr); 1557 } 1558 continue; 1559 1560 case CON_IFVARL: 1561 insptr++; 1562 { 1563 int32_t j=Gv_GetVar(*insptr++); 1564 VM_DoConditional(j < *insptr); 1565 } 1566 continue; 1567 1568 case CON_IFVARLE: 1569 insptr++; 1570 { 1571 int32_t j=Gv_GetVar(*insptr++); 1572 VM_DoConditional(j <= *insptr); 1573 } 1574 continue; 1575 1576 case CON_IFVARA: 1577 insptr++; 1578 { 1579 int32_t j=Gv_GetVar(*insptr++); 1580 VM_DoConditional((uint32_t)j > (uint32_t)*insptr); 1581 } 1582 continue; 1583 1584 case CON_IFVARAE: 1585 insptr++; 1586 { 1587 int32_t j=Gv_GetVar(*insptr++); 1588 VM_DoConditional((uint32_t)j >= (uint32_t)*insptr); 1589 } 1590 continue; 1591 1592 case CON_IFVARB: 1593 insptr++; 1594 { 1595 int32_t j=Gv_GetVar(*insptr++); 1596 VM_DoConditional((uint32_t)j < (uint32_t)*insptr); 1597 } 1598 continue; 1599 1600 case CON_IFVARBE: 1601 insptr++; 1602 { 1603 int32_t j=Gv_GetVar(*insptr++); 1604 VM_DoConditional((uint32_t)j <= (uint32_t)*insptr); 1605 } 1606 continue; 1607 1608 case CON_IFRND: 1609 VM_DoConditional(rnd(Gv_GetVar(*(++insptr)))); 1610 continue; 1611 1612 case CON_IFHITKEY: 1613 case CON_IFHOLDKEY: 1614 case CON_RESETKEY: 1615 case CON_SETKEY: 1616 insptr++; 1617 { 1618 int32_t key=Gv_GetVar(*insptr); 1619 if (key<0 || key >= (int32_t)ARRAY_SIZE(keystatus)) 1620 { 1621 M32_ERROR("Invalid key %d!", key); 1622 continue; 1623 } 1624 1625 if (tw == CON_IFHITKEY || tw == CON_IFHOLDKEY) 1626 VM_DoConditional(keystatus[key]); 1627 else 1628 insptr++; 1629 1630 if (tw != CON_IFHOLDKEY) 1631 { 1632 if (!(key==0 || key==KEYSC_ESC || key==KEYSC_TILDE || key==KEYSC_gENTER || 1633 key==KEYSC_LALT || key==KEYSC_RALT || key==KEYSC_LCTRL || key==KEYSC_RCTRL || 1634 key==KEYSC_LSHIFT || key==KEYSC_RSHIFT)) 1635 keystatus[key] = (tw==CON_SETKEY); 1636 } 1637 } 1638 continue; 1639 1640 case CON_IFEITHERALT: 1641 VM_DoConditional(keystatus[KEYSC_LALT]||keystatus[KEYSC_RALT]); 1642 continue; 1643 1644 case CON_IFEITHERCTRL: 1645 VM_DoConditional(keystatus[KEYSC_LCTRL]||keystatus[KEYSC_RCTRL]); 1646 continue; 1647 1648 case CON_IFEITHERSHIFT: 1649 VM_DoConditional(keystatus[KEYSC_LSHIFT]||keystatus[KEYSC_RSHIFT]); 1650 continue; 1651 1652 // vvv CURSPR 1653 case CON_IFSPRITEPAL: 1654 insptr++; 1655 X_ERROR_INVALIDSP(); 1656 VM_DoConditional(vm.pSprite->pal == Gv_GetVar(*insptr)); 1657 continue; 1658 1659 case CON_IFHIGHLIGHTED: 1660 insptr++; 1661 { 1662 int32_t id=*insptr++, index=Gv_GetVar(*insptr); 1663 1664 if (index<0 || (id==M32_SPRITE_VAR_ID && index>=MAXSPRITES) || (id==M32_WALL_VAR_ID && index>=numwalls)) 1665 { 1666 M32_ERROR("%s index %d out of range!", id==M32_SPRITE_VAR_ID?"Sprite":"Wall", index); 1667 continue; 1668 } 1669 1670 if (id==M32_SPRITE_VAR_ID) 1671 VM_DoConditional(show2dsprite[index>>3]&(1<<(index&7))); 1672 else 1673 VM_DoConditional(show2dwall[index>>3]&(1<<(index&7))); 1674 } 1675 continue; 1676 1677 case CON_IFANGDIFFL: 1678 insptr++; 1679 { 1680 int32_t j; 1681 X_ERROR_INVALIDSP(); 1682 j = klabs(G_GetAngleDelta(ang, vm.pSprite->ang)); 1683 VM_DoConditional(j <= Gv_GetVar(*insptr)); 1684 } 1685 continue; 1686 1687 case CON_IFAWAYFROMWALL: 1688 { 1689 int16_t s1; 1690 int32_t j = 0; 1691 1692 X_ERROR_INVALIDSP(); 1693 s1 = vm.pSprite->sectnum; 1694 updatesector(vm.pSprite->x+108,vm.pSprite->y+108,&s1); 1695 if (s1 == vm.pSprite->sectnum) 1696 { 1697 updatesector(vm.pSprite->x-108,vm.pSprite->y-108,&s1); 1698 if (s1 == vm.pSprite->sectnum) 1699 { 1700 updatesector(vm.pSprite->x+108,vm.pSprite->y-108,&s1); 1701 if (s1 == vm.pSprite->sectnum) 1702 { 1703 updatesector(vm.pSprite->x-108,vm.pSprite->y+108,&s1); 1704 if (s1 == vm.pSprite->sectnum) 1705 j = 1; 1706 } 1707 } 1708 } 1709 VM_DoConditional(j); 1710 } 1711 continue; 1712 1713 case CON_IFCANSEE: 1714 { 1715 int32_t j; 1716 1717 X_ERROR_INVALIDSP(); 1718 j = cansee(vm.pSprite->x,vm.pSprite->y,vm.pSprite->z/*-((krand()&41)<<8)*/,vm.pSprite->sectnum, 1719 pos.x, pos.y, pos.z /*-((krand()&41)<<8)*/, cursectnum); 1720 VM_DoConditional(j); 1721 } 1722 continue; 1723 1724 case CON_IFONWATER: 1725 X_ERROR_INVALIDSP(); 1726 VM_DoConditional(sector[vm.pSprite->sectnum].lotag == 1 && klabs(vm.pSprite->z-sector[vm.pSprite->sectnum].floorz) < (32<<8)); 1727 continue; 1728 1729 case CON_IFINWATER: 1730 X_ERROR_INVALIDSP(); 1731 VM_DoConditional(sector[vm.pSprite->sectnum].lotag == 2); 1732 continue; 1733 1734 case CON_IFACTOR: 1735 insptr++; 1736 X_ERROR_INVALIDSP(); 1737 VM_DoConditional(vm.pSprite->picnum == Gv_GetVar(*insptr)); 1738 continue; 1739 1740 case CON_IFINSIDE: 1741 insptr++; 1742 { 1743 int32_t x=Gv_GetVar(*insptr++), y=Gv_GetVar(*insptr++), sectnum=Gv_GetVar(*insptr++), res; 1744 1745 res = inside(x, y, sectnum); 1746 if (res == -1) 1747 { 1748 M32_ERROR("Sector index %d out of range!", sectnum); 1749 continue; 1750 } 1751 insptr--; 1752 VM_DoConditional(res); 1753 } 1754 continue; 1755 1756 case CON_IFOUTSIDE: 1757 X_ERROR_INVALIDSP(); 1758 VM_DoConditional(sector[vm.pSprite->sectnum].ceilingstat&1); 1759 continue; 1760 1761 case CON_IFPDISTL: 1762 insptr++; 1763 { 1764 X_ERROR_INVALIDSP(); 1765 VM_DoConditional(dist((spritetype *)&pos, vm.pSprite) < Gv_GetVar(*insptr)); 1766 } 1767 continue; 1768 1769 case CON_IFPDISTG: 1770 insptr++; 1771 { 1772 X_ERROR_INVALIDSP(); 1773 VM_DoConditional(dist((spritetype *)&pos, vm.pSprite) > Gv_GetVar(*insptr)); 1774 } 1775 continue; 1776 // ^^^ 1777 1778 // *** BUILD functions 1779 case CON_INSERTSPRITE: 1780 insptr++; 1781 { 1782 int32_t dasectnum = Gv_GetVar(*insptr++), ret; 1783 1784 X_ERROR_INVALIDSECT(dasectnum); 1785 if (Numsprites >= MAXSPRITES) 1786 { 1787 M32_ERROR("Maximum number of sprites reached."); 1788 continue; 1789 } 1790 1791 ret = insertsprite(dasectnum, 0); 1792 vm.spriteNum = ret; 1793 vm.pSprite = &sprite[ret]; 1794 } 1795 continue; 1796 1797 case CON_DUPSPRITE: 1798 case CON_TDUPSPRITE: 1799 insptr++; 1800 { 1801 int32_t ospritenum = Gv_GetVar(*insptr++), nspritenum; 1802 1803 if (ospritenum<0 || ospritenum>=MAXSPRITES || sprite[ospritenum].statnum==MAXSTATUS) 1804 { 1805 M32_ERROR("Tried to duplicate nonexistent sprite %d", ospritenum); 1806 } 1807 if ((tw==CON_DUPSPRITE && Numsprites >= MAXSPRITES) || 1808 (tw==CON_DUPSPRITE && spritesortcnt >= maxspritesonscreen)) 1809 { 1810 M32_ERROR("Maximum number of sprites reached."); 1811 } 1812 1813 if (vm.flags&VMFLAG_ERROR) 1814 continue; 1815 1816 if (tw==CON_DUPSPRITE) 1817 { 1818 nspritenum = insertsprite(sprite[ospritenum].sectnum, sprite[ospritenum].statnum); 1819 1820 if (nspritenum < 0) 1821 { 1822 M32_ERROR("Internal error."); 1823 continue; 1824 } 1825 1826 Bmemcpy(&sprite[nspritenum], &sprite[ospritenum], sizeof(spritetype)); 1827 vm.spriteNum = nspritenum; 1828 vm.pSprite = &sprite[nspritenum]; 1829 } 1830 else 1831 { 1832 tspriteptr_t tsp = renderAddTSpriteFromSprite(ospritenum); 1833 vm.spriteNum = -1; 1834 EDUKE32_STATIC_ASSERT(sizeof(uspritetype) == sizeof(tspritetype)); // see TSPRITE_SIZE 1835 vm.pUSprite = (uspriteptr_t)tsp; 1836 } 1837 } 1838 continue; 1839 1840 case CON_DELETESPRITE: 1841 insptr++; 1842 { 1843 int32_t daspritenum = Gv_GetVar(*insptr++), ret; 1844 1845 X_ERROR_INVALIDSPRI(daspritenum); 1846 ret = deletesprite(daspritenum); 1847 g_iReturnVar = ret; 1848 } 1849 continue; 1850 1851 case CON_GETSPRITELINKTYPE: 1852 insptr++; 1853 { 1854 int32_t spritenum=Gv_GetVar(*insptr++), resvar = *insptr++; 1855 1856 X_ERROR_INVALIDSPRI(spritenum); 1857 Gv_SetVar(resvar, taglab_linktags(1, spritenum)); 1858 } 1859 continue; 1860 1861 case CON_LASTWALL: 1862 insptr++; 1863 { 1864 int32_t dapoint = Gv_GetVar(*insptr++), resvar=*insptr++; 1865 1866 if (dapoint<0 || dapoint>=numwalls) 1867 { 1868 M32_ERROR("Invalid wall %d", dapoint); 1869 continue; 1870 } 1871 1872 Gv_SetVar(resvar, lastwall(dapoint)); 1873 } 1874 continue; 1875 1876 case CON_GETZRANGE: 1877 insptr++; 1878 { 1879 vec3_t vect; 1880 1881 vect.x = Gv_GetVar(*insptr++); 1882 vect.y = Gv_GetVar(*insptr++); 1883 vect.z = Gv_GetVar(*insptr++); 1884 1885 { 1886 int32_t sectnum=Gv_GetVar(*insptr++); 1887 int32_t ceilzvar=*insptr++, ceilhitvar=*insptr++, florzvar=*insptr++, florhitvar=*insptr++; 1888 int32_t walldist=Gv_GetVar(*insptr++), clipmask=Gv_GetVar(*insptr++); 1889 int32_t ceilz, ceilhit, florz, florhit; 1890 1891 X_ERROR_INVALIDSECT(sectnum); 1892 getzrange(&vect, sectnum, &ceilz, &ceilhit, &florz, &florhit, walldist, clipmask); 1893 Gv_SetVar(ceilzvar, ceilz); 1894 Gv_SetVar(ceilhitvar, ceilhit); 1895 Gv_SetVar(florzvar, florz); 1896 Gv_SetVar(florhitvar, florhit); 1897 } 1898 continue; 1899 } 1900 1901 case CON_CALCHYPOTENUSE: 1902 insptr++; 1903 { 1904 int32_t retvar=*insptr++; 1905 int64_t dax=Gv_GetVar(*insptr++), day=Gv_GetVar(*insptr++); 1906 int64_t hypsq = dax*dax + day*day; 1907 1908 if (hypsq > (int64_t)INT32_MAX) 1909 Gv_SetVar(retvar, (int32_t)sqrt((double)hypsq)); 1910 else 1911 Gv_SetVar(retvar, ksqrt((uint32_t)hypsq)); 1912 1913 continue; 1914 } 1915 1916 case CON_LINEINTERSECT: 1917 case CON_RAYINTERSECT: 1918 insptr++; 1919 { 1920 int32_t x1=Gv_GetVar(*insptr++), y1=Gv_GetVar(*insptr++), z1=Gv_GetVar(*insptr++); 1921 int32_t x2=Gv_GetVar(*insptr++), y2=Gv_GetVar(*insptr++), z2=Gv_GetVar(*insptr++); 1922 int32_t x3=Gv_GetVar(*insptr++), y3=Gv_GetVar(*insptr++), x4=Gv_GetVar(*insptr++), y4=Gv_GetVar(*insptr++); 1923 int32_t intxvar=*insptr++, intyvar=*insptr++, intzvar=*insptr++, retvar=*insptr++; 1924 int32_t intx, inty, intz, ret; 1925 1926 if (tw==CON_LINEINTERSECT) 1927 ret = lintersect(x1, y1, z1, x2, y2, z2, x3, y3, x4, y4, &intx, &inty, &intz); 1928 else 1929 ret = rayintersect(x1, y1, z1, x2, y2, z2, x3, y3, x4, y4, &intx, &inty, &intz); 1930 1931 Gv_SetVar(retvar, ret); 1932 if (ret) 1933 { 1934 Gv_SetVar(intxvar, intx); 1935 Gv_SetVar(intyvar, inty); 1936 Gv_SetVar(intzvar, intz); 1937 } 1938 1939 continue; 1940 } 1941 1942 case CON_CLIPMOVE: 1943 insptr++; 1944 { 1945 vec3_t vect; 1946 int32_t retvar=*insptr++, xvar=*insptr++, yvar=*insptr++, z=Gv_GetVar(*insptr++), sectnumvar=*insptr++; 1947 int32_t xvect=Gv_GetVar(*insptr++), yvect=Gv_GetVar(*insptr++); 1948 int32_t walldist=Gv_GetVar(*insptr++), floordist=Gv_GetVar(*insptr++), ceildist=Gv_GetVar(*insptr++); 1949 int32_t clipmask=Gv_GetVar(*insptr++); 1950 int16_t sectnum; 1951 1952 vect.x = Gv_GetVar(xvar); 1953 vect.y = Gv_GetVar(yvar); 1954 vect.z = z; 1955 sectnum = Gv_GetVar(sectnumvar); 1956 1957 X_ERROR_INVALIDSECT(sectnum); 1958 1959 Gv_SetVar(retvar, clipmove(&vect, §num, xvect, yvect, walldist, floordist, ceildist, clipmask)); 1960 Gv_SetVar(sectnumvar, sectnum); 1961 Gv_SetVar(xvar, vect.x); 1962 Gv_SetVar(yvar, vect.y); 1963 1964 continue; 1965 } 1966 1967 case CON_HITSCAN: 1968 insptr++; 1969 { 1970 vec3_t vect; 1971 hitdata_t hit; 1972 1973 vect.x = Gv_GetVar(*insptr++); 1974 vect.y = Gv_GetVar(*insptr++); 1975 vect.z = Gv_GetVar(*insptr++); 1976 1977 { 1978 int32_t sectnum=Gv_GetVar(*insptr++); 1979 int32_t vx=Gv_GetVar(*insptr++), vy=Gv_GetVar(*insptr++), vz=Gv_GetVar(*insptr++); 1980 int32_t hitsectvar=*insptr++, hitwallvar=*insptr++, hitspritevar=*insptr++; 1981 int32_t hitxvar=*insptr++, hityvar=*insptr++, hitzvar=*insptr++, cliptype=Gv_GetVar(*insptr++); 1982 1983 X_ERROR_INVALIDSECT(sectnum); 1984 hitscan((const vec3_t *)&vect, sectnum, vx, vy, vz, &hit, cliptype); 1985 Gv_SetVar(hitsectvar, hit.sect); 1986 Gv_SetVar(hitwallvar, hit.wall); 1987 Gv_SetVar(hitspritevar, hit.sprite); 1988 Gv_SetVar(hitxvar, hit.pos.x); 1989 Gv_SetVar(hityvar, hit.pos.y); 1990 Gv_SetVar(hitzvar, hit.pos.z); 1991 } 1992 continue; 1993 } 1994 1995 case CON_CANSEE: 1996 insptr++; 1997 { 1998 int32_t x1=Gv_GetVar(*insptr++), y1=Gv_GetVar(*insptr++), z1=Gv_GetVar(*insptr++); 1999 int32_t sect1=Gv_GetVar(*insptr++); 2000 int32_t x2=Gv_GetVar(*insptr++), y2=Gv_GetVar(*insptr++), z2=Gv_GetVar(*insptr++); 2001 int32_t sect2=Gv_GetVar(*insptr++), rvar=*insptr++; 2002 2003 X_ERROR_INVALIDSECT(sect1); 2004 X_ERROR_INVALIDSECT(sect2); 2005 2006 Gv_SetVar(rvar, cansee(x1,y1,z1,sect1,x2,y2,z2,sect2)); 2007 continue; 2008 } 2009 2010 case CON_ROTATEPOINT: 2011 insptr++; 2012 { 2013 vec2_t pivot = { Gv_GetVar(*insptr), Gv_GetVar(*(insptr+1)) }; 2014 vec2_t p = { Gv_GetVar(*(insptr+2)), Gv_GetVar(*(insptr+3)) }; 2015 insptr += 4; 2016 int32_t daang=Gv_GetVar(*insptr++); 2017 int32_t x2var=*insptr++, y2var=*insptr++; 2018 vec2_t p2; 2019 2020 rotatepoint(pivot,p,daang,&p2); 2021 Gv_SetVar(x2var, p2.x); 2022 Gv_SetVar(y2var, p2.y); 2023 continue; 2024 } 2025 2026 case CON_NEARTAG: 2027 insptr++; 2028 { 2029 // neartag(int32_t x, int32_t y, int32_t z, short sectnum, short ang, //Starting position & angle 2030 // short *neartagsector, //Returns near sector if sector[].tag != 0 2031 // short *neartagwall, //Returns near wall if wall[].tag != 0 2032 // short *neartagsprite, //Returns near sprite if sprite[].tag != 0 2033 // int32_t *neartaghitdist, //Returns actual distance to object (scale: 1024=largest grid size) 2034 // int32_t neartagrange, //Choose maximum distance to scan (scale: 1024=largest grid size) 2035 // char tagsearch) //1-lotag only, 2-hitag only, 3-lotag&hitag 2036 2037 int32_t x=Gv_GetVar(*insptr++), y=Gv_GetVar(*insptr++), z=Gv_GetVar(*insptr++); 2038 int32_t sectnum=Gv_GetVar(*insptr++), ang=Gv_GetVar(*insptr++); 2039 int32_t neartagsectorvar=*insptr++, neartagwallvar=*insptr++, neartagspritevar=*insptr++, neartaghitdistvar=*insptr++; 2040 int32_t neartagrange=Gv_GetVar(*insptr++), tagsearch=Gv_GetVar(*insptr++); 2041 2042 int16_t neartagsector, neartagwall, neartagsprite; 2043 int32_t neartaghitdist; 2044 2045 X_ERROR_INVALIDSECT(sectnum); 2046 neartag(x, y, z, sectnum, ang, &neartagsector, &neartagwall, &neartagsprite, 2047 &neartaghitdist, neartagrange, tagsearch, NULL); 2048 2049 Gv_SetVar(neartagsectorvar, neartagsector); 2050 Gv_SetVar(neartagwallvar, neartagwall); 2051 Gv_SetVar(neartagspritevar, neartagsprite); 2052 Gv_SetVar(neartaghitdistvar, neartaghitdist); 2053 continue; 2054 } 2055 2056 case CON_BSETSPRITE: // was CON_SETSPRITE 2057 insptr++; 2058 { 2059 int32_t spritenum = Gv_GetVar(*insptr++); 2060 vec3_t davector; 2061 2062 davector.x = Gv_GetVar(*insptr++); 2063 davector.y = Gv_GetVar(*insptr++); 2064 davector.z = Gv_GetVar(*insptr++); 2065 2066 X_ERROR_INVALIDSPRI(spritenum); 2067 setsprite(spritenum, &davector); 2068 continue; 2069 } 2070 2071 case CON_GETFLORZOFSLOPE: 2072 case CON_GETCEILZOFSLOPE: 2073 insptr++; 2074 { 2075 int32_t sectnum = Gv_GetVar(*insptr++), x = Gv_GetVar(*insptr++), y = Gv_GetVar(*insptr++); 2076 int32_t var=*insptr++; 2077 2078 X_ERROR_INVALIDSECT(sectnum); 2079 if (tw == CON_GETFLORZOFSLOPE) 2080 Gv_SetVar(var, getflorzofslope(sectnum,x,y)); 2081 else 2082 Gv_SetVar(var, getceilzofslope(sectnum,x,y)); 2083 continue; 2084 } 2085 2086 case CON_ALIGNFLORSLOPE: 2087 case CON_ALIGNCEILSLOPE: 2088 insptr++; 2089 { 2090 int32_t sectnum = Gv_GetVar(*insptr++), x = Gv_GetVar(*insptr++), y = Gv_GetVar(*insptr++); 2091 int32_t z=Gv_GetVar(*insptr++); 2092 2093 X_ERROR_INVALIDSECT(sectnum); 2094 if (tw == CON_ALIGNFLORSLOPE) 2095 alignflorslope(sectnum, x,y,z); 2096 else 2097 alignceilslope(sectnum, x,y,z); 2098 continue; 2099 } 2100 2101 // CURSPR 2102 case CON_SETFIRSTWALL: 2103 insptr++; 2104 { 2105 int32_t sect=Gv_GetVar(*insptr++), wal=Gv_GetVar(*insptr++); 2106 2107 X_ERROR_INVALIDSECT(sect); 2108 setfirstwall(sect, wal); 2109 } 2110 continue; 2111 2112 case CON_UPDATECURSECTNUM: 2113 insptr++; 2114 updatesectorz(pos.x, pos.y, pos.z, &cursectnum); 2115 continue; 2116 2117 case CON_UPDATESECTOR: 2118 case CON_UPDATESECTORZ: 2119 case CON_UPDATESECTORNEIGHBOR: 2120 case CON_UPDATESECTORNEIGHBORZ: 2121 insptr++; 2122 { 2123 int32_t x=Gv_GetVar(*insptr++), y=Gv_GetVar(*insptr++); 2124 int32_t z=(tw==CON_UPDATESECTORZ || tw==CON_UPDATESECTORNEIGHBORZ)?Gv_GetVar(*insptr++):0; 2125 int32_t var=*insptr++; 2126 int16_t w; 2127 2128 X_ERROR_INVALIDCI(); 2129 w=sprite[vm.spriteNum].sectnum; 2130 2131 switch (tw) 2132 { 2133 case CON_UPDATESECTORNEIGHBORZ: 2134 updatesectorneighborz(x,y,z,&w,getsectordist({x, y}, w)); 2135 continue; 2136 case CON_UPDATESECTORZ: 2137 updatesectorz(x,y,z,&w); 2138 continue; 2139 case CON_UPDATESECTORNEIGHBOR: 2140 updatesectorneighbor(x,y,&w,getsectordist({x, y}, w)); 2141 continue; 2142 default: 2143 updatesector(x,y,&w); 2144 continue; 2145 } 2146 2147 Gv_SetVar(var, w); 2148 continue; 2149 } 2150 2151 case CON_HEADSPRITESTAT: 2152 insptr++; 2153 { 2154 int32_t i=*insptr++; 2155 int32_t j=Gv_GetVar(*insptr++); 2156 if (j < 0 || j > MAXSTATUS) 2157 { 2158 M32_ERROR("invalid status list %d", j); 2159 continue; 2160 } 2161 Gv_SetVar(i,headspritestat[j]); 2162 continue; 2163 } 2164 2165 case CON_PREVSPRITESTAT: 2166 insptr++; 2167 { 2168 int32_t i=*insptr++; 2169 int32_t j=Gv_GetVar(*insptr++); 2170 2171 X_ERROR_INVALIDSPRI(j); 2172 Gv_SetVar(i,prevspritestat[j]); 2173 continue; 2174 } 2175 2176 case CON_NEXTSPRITESTAT: 2177 insptr++; 2178 { 2179 int32_t i=*insptr++; 2180 int32_t j=Gv_GetVar(*insptr++); 2181 2182 X_ERROR_INVALIDSPRI(j); 2183 Gv_SetVar(i,nextspritestat[j]); 2184 continue; 2185 } 2186 2187 case CON_HEADSPRITESECT: 2188 insptr++; 2189 { 2190 int32_t i=*insptr++; 2191 int32_t j=Gv_GetVar(*insptr++); 2192 2193 X_ERROR_INVALIDSECT(j); 2194 Gv_SetVar(i,headspritesect[j]); 2195 continue; 2196 } 2197 2198 case CON_PREVSPRITESECT: 2199 insptr++; 2200 { 2201 int32_t i=*insptr++; 2202 int32_t j=Gv_GetVar(*insptr++); 2203 2204 X_ERROR_INVALIDSPRI(j); 2205 Gv_SetVar(i,prevspritesect[j]); 2206 continue; 2207 } 2208 2209 case CON_NEXTSPRITESECT: 2210 insptr++; 2211 { 2212 int32_t i=*insptr++; 2213 int32_t j=Gv_GetVar(*insptr++); 2214 2215 X_ERROR_INVALIDSPRI(j); 2216 Gv_SetVar(i,nextspritesect[j]); 2217 continue; 2218 } 2219 2220 case CON_CANSEESPR: 2221 insptr++; 2222 { 2223 int32_t lVar1 = Gv_GetVar(*insptr++), lVar2 = Gv_GetVar(*insptr++), res; 2224 2225 if (lVar1<0 || lVar1>=MAXSPRITES || sprite[lVar1].statnum==MAXSTATUS) 2226 { 2227 M32_ERROR("Invalid sprite %d", lVar1); 2228 } 2229 if (lVar2<0 || lVar2>=MAXSPRITES || sprite[lVar2].statnum==MAXSTATUS) 2230 { 2231 M32_ERROR("Invalid sprite %d", lVar2); 2232 } 2233 2234 if (vm.flags&VMFLAG_ERROR) res=0; 2235 else res=cansee(sprite[lVar1].x,sprite[lVar1].y,sprite[lVar1].z,sprite[lVar1].sectnum, 2236 sprite[lVar2].x,sprite[lVar2].y,sprite[lVar2].z,sprite[lVar2].sectnum); 2237 2238 Gv_SetVar(*insptr++, res); 2239 continue; 2240 } 2241 2242 case CON_CHANGESPRITESTAT: 2243 case CON_CHANGESPRITESECT: 2244 insptr++; 2245 { 2246 int32_t i = Gv_GetVar(*insptr++); 2247 int32_t j = Gv_GetVar(*insptr++); 2248 2249 X_ERROR_INVALIDSPRI(i); 2250 if (j<0 || j >= (tw==CON_CHANGESPRITESTAT?MAXSTATUS:numsectors)) 2251 { 2252 M32_ERROR("Invalid %s: %d", tw==CON_CHANGESPRITESTAT?"statnum":"sector", j); 2253 continue; 2254 } 2255 2256 if (tw == CON_CHANGESPRITESTAT) 2257 { 2258 if (sprite[i].statnum == j) continue; 2259 changespritestat(i,j); 2260 } 2261 else 2262 { 2263 if (sprite[i].sectnum == j) continue; 2264 changespritesect(i,j); 2265 } 2266 continue; 2267 } 2268 2269 case CON_DRAGPOINT: 2270 insptr++; 2271 { 2272 int32_t wallnum = Gv_GetVar(*insptr++), newx = Gv_GetVar(*insptr++), newy = Gv_GetVar(*insptr++); 2273 2274 if (wallnum<0 || wallnum>=numwalls) 2275 { 2276 M32_ERROR("Invalid wall %d", wallnum); 2277 continue; 2278 } 2279 dragpoint(wallnum,newx,newy,0); 2280 continue; 2281 } 2282 2283 case CON_SECTOROFWALL: 2284 insptr++; 2285 { 2286 int32_t j = *insptr++; 2287 Gv_SetVar(j, sectorofwall(Gv_GetVar(*insptr++))); 2288 } 2289 continue; 2290 2291 case CON_FIXREPEATS: 2292 insptr++; 2293 fixrepeats(Gv_GetVar(*insptr++)); 2294 continue; 2295 2296 case CON_GETCLOSESTCOL: 2297 insptr++; 2298 { 2299 int32_t r = Gv_GetVar(*insptr++), g = Gv_GetVar(*insptr++), b = Gv_GetVar(*insptr++); 2300 Gv_SetVar(*insptr++, paletteGetClosestColor(r, g, b)); 2301 continue; 2302 } 2303 2304 // *** stuff 2305 case CON_UPDATEHIGHLIGHT: 2306 insptr++; 2307 update_highlight(); 2308 continue; 2309 2310 case CON_UPDATEHIGHLIGHTSECTOR: 2311 insptr++; 2312 update_highlightsector(); 2313 continue; 2314 2315 case CON_SETHIGHLIGHT: 2316 insptr++; 2317 { 2318 int32_t what=Gv_GetVar(*insptr++), index=Gv_GetVar(*insptr++), doset = Gv_GetVar(*insptr++); 2319 2320 if (highlightsectorcnt >= 0) 2321 { 2322 M32_ERROR("sector highlight active or pending, cannot highlight sprites/walls"); 2323 continue; 2324 } 2325 2326 if (what&16384) 2327 { 2328 index &= ~16384; 2329 if (index < 0 || index>=MAXSPRITES || sprite[index].statnum==MAXSTATUS) 2330 { 2331 M32_ERROR("Invalid sprite index %d", index); 2332 continue; 2333 } 2334 2335 if (doset) 2336 show2dsprite[index>>3] |= (1<<(index&7)); 2337 else 2338 show2dsprite[index>>3] &= ~(1<<(index&7)); 2339 } 2340 else 2341 { 2342 if (index < 0 || index>=numwalls) 2343 { 2344 M32_ERROR("Invalid wall index %d", index); 2345 continue; 2346 } 2347 2348 if (doset) 2349 show2dwall[index>>3] |= (1<<(index&7)); 2350 else 2351 show2dwall[index>>3] &= ~(1<<(index&7)); 2352 } 2353 2354 vm.miscflags |= VMFLAG_MISC_UPDATEHL; 2355 2356 continue; 2357 } 2358 2359 case CON_SETHIGHLIGHTSECTOR: 2360 insptr++; 2361 { 2362 int32_t index=Gv_GetVar(*insptr++), doset = Gv_GetVar(*insptr++); 2363 2364 if (highlightcnt >= 0) 2365 { 2366 M32_ERROR("sprite/wall highlight active or pending, cannot highlight sectors"); 2367 continue; 2368 } 2369 2370 X_ERROR_INVALIDSECT(index); 2371 2372 if (doset) 2373 hlsectorbitmap[index>>3] |= (1<<(index&7)); 2374 else 2375 hlsectorbitmap[index>>3] &= ~(1<<(index&7)); 2376 2377 vm.miscflags |= VMFLAG_MISC_UPDATEHLSECT; 2378 2379 continue; 2380 } 2381 2382 case CON_GETTIMEDATE: 2383 insptr++; 2384 { 2385 int32_t v1=*insptr++,v2=*insptr++,v3=*insptr++,v4=*insptr++,v5=*insptr++,v6=*insptr++,v7=*insptr++,v8=*insptr++; 2386 time_t rawtime; 2387 struct tm *ti; 2388 2389 time(&rawtime); 2390 ti = localtime(&rawtime); 2391 // initprintf("Time&date: %s\n",asctime (ti)); 2392 2393 Gv_SetVar(v1, ti->tm_sec); 2394 Gv_SetVar(v2, ti->tm_min); 2395 Gv_SetVar(v3, ti->tm_hour); 2396 Gv_SetVar(v4, ti->tm_mday); 2397 Gv_SetVar(v5, ti->tm_mon); 2398 Gv_SetVar(v6, ti->tm_year+1900); 2399 Gv_SetVar(v7, ti->tm_wday); 2400 Gv_SetVar(v8, ti->tm_yday); 2401 continue; 2402 } 2403 2404 case CON_ADDLOG: 2405 { 2406 insptr++; 2407 2408 OSD_Printf("L=%d\n", g_errorLineNum); 2409 continue; 2410 } 2411 2412 case CON_ADDLOGVAR: 2413 insptr++; 2414 { 2415 char buf[80] = "", buf2[80] = ""; 2416 int32_t code = (int32_t)*insptr, val = Gv_GetVar(code); 2417 int32_t negate=code&M32_FLAG_NEGATE; 2418 2419 if (code & (0xFFFFFFFF-(MAXGAMEVARS-1))) 2420 { 2421 if ((code&M32_VARTYPE_MASK)==M32_FLAG_ARRAY || (code&M32_VARTYPE_MASK)==M32_FLAG_STRUCT) 2422 { 2423 if (code&M32_FLAG_CONSTANT) 2424 Bsprintf(buf2, "%d", (code>>16)&0xffff); 2425 else 2426 { 2427 char *label = aGameVars[(code>>16)&(MAXGAMEVARS-1)].szLabel; 2428 Bsprintf(buf2, "%s", label?label:"???"); 2429 } 2430 } 2431 else if ((code&M32_VARTYPE_MASK)==M32_FLAG_LOCAL) 2432 Bsprintf(buf2, "%d", code&(MAXGAMEVARS-1)); 2433 2434 if ((code&0x0000FFFC) == M32_FLAG_CONSTANT) // addlogvar for a constant.. why not? :P 2435 { 2436 switch (code&3) 2437 { 2438 case 0: Bsprintf(buf, "(immediate constant)"); break; 2439 case 1: Bsprintf(buf, "(indirect constant)"); break; 2440 case 2: Bsprintf(buf, "(label constant)"); break; 2441 default: Bsprintf(buf, "(??? constant)"); break; 2442 } 2443 } 2444 else 2445 { 2446 switch (code&M32_VARTYPE_MASK) 2447 { 2448 case M32_FLAG_ARRAY: 2449 Bsnprintf(buf, sizeof(buf), "%s[%s]", aGameArrays[code&(MAXGAMEARRAYS-1)].szLabel 2450 ? aGameArrays[code&(MAXGAMEARRAYS-1)].szLabel : "???", buf2); 2451 break; 2452 case M32_FLAG_STRUCT: 2453 { 2454 int32_t memberid=(code>>2)&63, lightp = (memberid >= LIGHT_X); 2455 const char *pp1[4] = {"sprite","sector","wall","tsprite"}; 2456 const memberlabel_t *pp2[4] = {SpriteLabels, SectorLabels, WallLabels, SpriteLabels}; 2457 if (lightp) 2458 { 2459 pp1[3] = "light"; 2460 pp2[3] = LightLabels; 2461 memberid -= LIGHT_X; 2462 } 2463 2464 Bsnprintf(buf, sizeof(buf), "%s[%s].%s", pp1[code&3], buf2, pp2[code&3][memberid].name); 2465 } 2466 break; 2467 case M32_FLAG_VAR: 2468 Bstrcpy(buf, "???"); 2469 break; 2470 case M32_FLAG_LOCAL: 2471 Bsnprintf(buf, sizeof(buf), ".local[%s]", buf2); 2472 break; 2473 } 2474 } 2475 } 2476 else 2477 { 2478 if (aGameVars[code].dwFlags & GAMEVAR_PERBLOCK) 2479 { 2480 Bsprintf(buf2, "(%s", vm.g_st==0? "top-level) " : vm.g_st<=MAXEVENTS? "event" : "state"); 2481 if (vm.g_st >= 1+MAXEVENTS && vm.g_st <1+MAXEVENTS+g_stateCount) 2482 Bsprintf(buf, " `%s') ", statesinfo[vm.g_st-1-MAXEVENTS].name); 2483 else if (vm.g_st > 0) 2484 Bsprintf(buf, " %d) ", vm.g_st-1); 2485 Bstrcat(buf2, buf); 2486 } 2487 2488 Bsnprintf(buf, sizeof(buf), "%s%s", buf2, aGameVars[code].szLabel ? aGameVars[code].szLabel : "???"); 2489 } 2490 2491 OSD_Printf("L%d: %s%s=%d\n", g_errorLineNum, negate?"-":"", buf, val); 2492 2493 insptr++; 2494 continue; 2495 } 2496 2497 case CON_DEBUG: 2498 insptr++; 2499 initprintf("%d\n",*insptr++); 2500 continue; 2501 2502 // *** strings 2503 case CON_REDEFINEQUOTE: 2504 insptr++; 2505 { 2506 int32_t q = *insptr++, i = *insptr++; 2507 X_ERROR_INVALIDQUOTE(q, apStrings); 2508 X_ERROR_INVALIDQUOTE(i, apXStrings); 2509 Bstrcpy(apStrings[q],apXStrings[i]); 2510 continue; 2511 } 2512 2513 case CON_GETNUMBER16: /* deprecated */ 2514 case CON_GETNUMBER256: /* deprecated */ 2515 case CON_GETNUMBERFROMUSER: 2516 insptr++; 2517 { 2518 int32_t var=*insptr++, quote=*insptr++; 2519 const char *quotetext = GetMaybeInlineQuote(quote); 2520 if (vm.flags&VMFLAG_ERROR) 2521 continue; 2522 2523 { 2524 int32_t max=Gv_GetVar(*insptr++); 2525 int32_t sign = (tw==CON_GETNUMBERFROMUSER) ? Gv_GetVar(*insptr++) : (max<=0); 2526 char buf[64]; // buffers in getnumber* are 80 bytes long 2527 2528 Bstrncpyz(buf, quotetext, sizeof(buf)); 2529 2530 if (max==0) 2531 max = INT32_MAX; 2532 else 2533 max = klabs(max); 2534 2535 //OSD_Printf("max:%d, sign:%d\n", max, sign); 2536 if (tw==CON_GETNUMBERFROMUSER) 2537 { 2538 Gv_SetVar(var, in3dmode() ? 2539 getnumber256(quotetext, Gv_GetVar(var), max, sign) : 2540 getnumber16(quotetext, Gv_GetVar(var), max, sign)); 2541 } 2542 else if (tw==CON_GETNUMBER16) 2543 Gv_SetVar(var, getnumber16(quotetext, Gv_GetVar(var), max, sign)); 2544 else 2545 Gv_SetVar(var, getnumber256(quotetext, Gv_GetVar(var), max, sign)); 2546 } 2547 } 2548 continue; 2549 2550 case CON_PRINT: 2551 case CON_QUOTE: 2552 case CON_ERRORINS: 2553 case CON_PRINTMESSAGE16: 2554 case CON_PRINTMESSAGE256: 2555 case CON_PRINTEXT256: 2556 case CON_PRINTEXT16: 2557 case CON_DRAWLABEL: 2558 insptr++; 2559 { 2560 int32_t i=*insptr++; 2561 const char *quotetext = GetMaybeInlineQuote(i); 2562 if (vm.flags&VMFLAG_ERROR) 2563 continue; 2564 2565 { 2566 int32_t x=(tw>=CON_PRINTMESSAGE256)?Gv_GetVar(*insptr++):0; 2567 int32_t y=(tw>=CON_PRINTMESSAGE256)?Gv_GetVar(*insptr++):0; 2568 2569 int32_t col=(tw>=CON_PRINTEXT256)?Gv_GetVar(*insptr++):0; 2570 int32_t backcol=(tw>=CON_PRINTEXT256)?Gv_GetVar(*insptr++):0; 2571 int32_t fontsize=(tw>=CON_PRINTEXT256)?Gv_GetVar(*insptr++):0; 2572 2573 if (tw==CON_PRINT || tw==CON_ERRORINS) 2574 { 2575 OSD_Printf("%s\n", quotetext); 2576 if (tw==CON_ERRORINS) 2577 vm.flags |= VMFLAG_ERROR; 2578 } 2579 else if (tw==CON_QUOTE) 2580 { 2581 message("%s", quotetext); 2582 } 2583 else if (tw==CON_PRINTMESSAGE16) 2584 { 2585 if (!in3dmode()) 2586 printmessage16("%s", quotetext); 2587 } 2588 else if (tw==CON_PRINTMESSAGE256) 2589 { 2590 if (in3dmode()) 2591 printmessage256(x, y, quotetext); 2592 } 2593 else if (tw==CON_PRINTEXT256) 2594 { 2595 if (in3dmode()) 2596 { 2597 if (col>=256) 2598 col=0; 2599 else if (col < 0 && col >= -255) 2600 col = editorcolors[-col]; 2601 2602 if (backcol<0 || backcol>=256) 2603 backcol=-1; 2604 2605 printext256(x, y, col, backcol, quotetext, fontsize); 2606 } 2607 } 2608 else if (tw==CON_PRINTEXT16) 2609 { 2610 if (!in3dmode()) 2611 printext16(x, y, editorcolors[col&255], backcol<0 ? -1 : editorcolors[backcol&255], 2612 quotetext, fontsize); 2613 } 2614 else if (tw==CON_DRAWLABEL) 2615 { 2616 if (!in3dmode()) 2617 { 2618 drawsmallabel(quotetext, 2619 editorcolors[backcol&255], // col 2620 fontsize < 0 ? -1 : editorcolors[fontsize&255], editorcolors[fontsize&255] - 3, // backcol 2621 x, y, col); // x y z 2622 } 2623 } 2624 } 2625 } 2626 continue; 2627 2628 case CON_QSTRLEN: 2629 insptr++; 2630 { 2631 int32_t i=*insptr++, quote=*insptr++; 2632 const char *quotetext = GetMaybeInlineQuote(quote); 2633 if (vm.flags&VMFLAG_ERROR) 2634 continue; 2635 2636 Gv_SetVar(i, Bstrlen(quotetext)); 2637 continue; 2638 } 2639 2640 case CON_QSUBSTR: 2641 insptr++; 2642 { 2643 int32_t q1 = Gv_GetVar(*insptr++); 2644 int32_t q2 = *insptr++; 2645 const char *q2text = GetMaybeInlineQuote(q2); 2646 if (vm.flags&VMFLAG_ERROR) 2647 continue; 2648 2649 X_ERROR_INVALIDQUOTE(q1, apStrings); 2650 2651 { 2652 int32_t st = Gv_GetVar(*insptr++); 2653 int32_t ln = Gv_GetVar(*insptr++); 2654 char *s1 = apStrings[q1]; 2655 const char *s2 = q2text; 2656 2657 while (*s2 && st--) s2++; 2658 while ((*s1 = *s2) && ln--) 2659 { 2660 s1++; 2661 s2++; 2662 } 2663 *s1=0; 2664 } 2665 continue; 2666 } 2667 2668 case CON_QSTRNCAT: 2669 case CON_QSTRCAT: 2670 case CON_QSTRCPY: 2671 /// case CON_QGETSYSSTR: 2672 insptr++; 2673 { 2674 int32_t i = Gv_GetVar(*insptr++); 2675 int32_t j = *insptr++; 2676 2677 const char *quotetext = GetMaybeInlineQuote(j); 2678 if (vm.flags&VMFLAG_ERROR) 2679 continue; 2680 2681 X_ERROR_INVALIDQUOTE(i, apStrings); 2682 2683 switch (tw) 2684 { 2685 case CON_QSTRCAT: 2686 Bstrncat(apStrings[i], quotetext, (MAXQUOTELEN-1)-Bstrlen(apStrings[i])); 2687 break; 2688 case CON_QSTRNCAT: 2689 Bstrncat(apStrings[i], quotetext, Gv_GetVar(*insptr++)); 2690 break; 2691 case CON_QSTRCPY: 2692 Bstrcpy(apStrings[i], quotetext); 2693 break; 2694 } 2695 continue; 2696 } 2697 2698 case CON_QSPRINTF: 2699 insptr++; 2700 { 2701 int32_t dq=Gv_GetVar(*insptr++), sq=*insptr++; 2702 const char *sourcetext = GetMaybeInlineQuote(sq); 2703 if (vm.flags&VMFLAG_ERROR) 2704 continue; 2705 2706 X_ERROR_INVALIDQUOTE(dq, apStrings); 2707 2708 { 2709 int32_t arg[32], numvals=0, i=0, j=0, k=0; 2710 int32_t len = Bstrlen(sourcetext); 2711 char tmpbuf[MAXQUOTELEN<<1]; 2712 2713 while (*insptr != -1 && numvals < 32) 2714 arg[numvals++] = Gv_GetVar(*insptr++); 2715 2716 insptr++; // skip the NOP 2717 2718 i = 0; 2719 do 2720 { 2721 while (k < len && j < MAXQUOTELEN && sourcetext[k] != '%') 2722 tmpbuf[j++] = sourcetext[k++]; 2723 2724 if (sourcetext[k] == '%') 2725 { 2726 k++; 2727 2728 if (i>=numvals) goto dodefault; 2729 2730 switch (sourcetext[k]) 2731 { 2732 case 'l': 2733 if (sourcetext[k+1] != 'd') 2734 { 2735 // write the % and l 2736 tmpbuf[j++] = sourcetext[k-1]; 2737 tmpbuf[j++] = sourcetext[k++]; 2738 break; 2739 } 2740 k++; 2741 fallthrough__; 2742 case 'd': 2743 { 2744 char buf[16]; 2745 int32_t ii = 0; 2746 2747 Bsprintf(buf, "%d", arg[i++]); 2748 2749 ii = Bstrlen(buf); 2750 Bmemcpy(&tmpbuf[j], buf, ii); 2751 j += ii; 2752 k++; 2753 } 2754 break; 2755 2756 case 'f': 2757 { 2758 char buf[64]; 2759 int32_t ii = 0; 2760 union { int32_t ival; float fval; }; 2761 ival = arg[i++]; 2762 2763 Bsprintf(buf, "%f", fval); 2764 2765 ii = Bstrlen(buf); 2766 Bmemcpy(&tmpbuf[j], buf, ii); 2767 j += ii; 2768 k++; 2769 } 2770 break; 2771 2772 case 's': 2773 { 2774 if (arg[i]>=0 && arg[i]<MAXQUOTES && apStrings[arg[i]]) 2775 { 2776 int32_t ii = Bstrlen(apStrings[arg[i]]); 2777 Bmemcpy(&tmpbuf[j], apStrings[arg[i]], ii); 2778 j += ii; 2779 } 2780 k++; 2781 } 2782 break; 2783 2784 dodefault: 2785 default: 2786 tmpbuf[j++] = sourcetext[k-1]; 2787 break; 2788 } 2789 } 2790 } 2791 while (k < len && j < MAXQUOTELEN); 2792 2793 tmpbuf[j] = '\0'; 2794 Bmemcpy(apStrings[dq], tmpbuf, MAXQUOTELEN); 2795 apStrings[dq][MAXQUOTELEN-1] = '\0'; 2796 continue; 2797 } 2798 } 2799 2800 // *** findnear* 2801 // CURSPR vvv 2802 case CON_FINDNEARSPRITE: 2803 case CON_FINDNEARSPRITE3D: 2804 case CON_FINDNEARSPRITEVAR: 2805 case CON_FINDNEARSPRITE3DVAR: 2806 insptr++; 2807 { 2808 // syntax findnearactor(var) <type> <maxdist(var)> <getvar> 2809 // gets the sprite ID of the nearest actor within max dist 2810 // that is of <type> into <getvar> 2811 // -1 for none found 2812 // <type> <maxdist(varid)> <varid> 2813 int32_t lType=*insptr++; 2814 int32_t lMaxDist = (tw==CON_FINDNEARSPRITE || tw==CON_FINDNEARSPRITE3D)? 2815 *insptr++ : Gv_GetVar(*insptr++); 2816 int32_t lVarID=*insptr++; 2817 int32_t lFound=-1, j, k = MAXSTATUS-1; 2818 2819 X_ERROR_INVALIDCI(); 2820 do 2821 { 2822 j=headspritestat[k]; // all sprites 2823 if (tw==CON_FINDNEARSPRITE3D || tw==CON_FINDNEARSPRITE3DVAR) 2824 { 2825 while (j>=0) 2826 { 2827 if (sprite[j].picnum == lType && j != vm.spriteNum && dist(&sprite[vm.spriteNum], &sprite[j]) < lMaxDist) 2828 { 2829 lFound=j; 2830 j = MAXSPRITES; 2831 break; 2832 } 2833 j = nextspritestat[j]; 2834 } 2835 if (j == MAXSPRITES) 2836 break; 2837 continue; 2838 } 2839 2840 while (j>=0) 2841 { 2842 if (sprite[j].picnum == lType && j != vm.spriteNum && ldist(&sprite[vm.spriteNum], &sprite[j]) < lMaxDist) 2843 { 2844 lFound=j; 2845 j = MAXSPRITES; 2846 break; 2847 } 2848 j = nextspritestat[j]; 2849 } 2850 2851 if (j == MAXSPRITES) 2852 break; 2853 } 2854 while (k--); 2855 Gv_SetVar(lVarID, lFound); 2856 continue; 2857 } 2858 2859 case CON_FINDNEARSPRITEZVAR: 2860 case CON_FINDNEARSPRITEZ: 2861 insptr++; 2862 { 2863 // syntax findnearactor(var) <type> <maxdist(var)> <getvar> 2864 // gets the sprite ID of the nearest actor within max dist 2865 // that is of <type> into <getvar> 2866 // -1 for none found 2867 // <type> <maxdist(varid)> <varid> 2868 int32_t lType=*insptr++; 2869 int32_t lMaxDist = (tw==CON_FINDNEARSPRITEZVAR) ? Gv_GetVar(*insptr++) : *insptr++; 2870 int32_t lMaxZDist = (tw==CON_FINDNEARSPRITEZVAR) ? Gv_GetVar(*insptr++) : *insptr++; 2871 int32_t lVarID=*insptr++; 2872 int32_t lFound=-1, lTemp, lTemp2, j, k=MAXSTATUS-1; 2873 2874 X_ERROR_INVALIDCI(); 2875 do 2876 { 2877 j=headspritestat[k]; // all sprites 2878 if (j == -1) continue; 2879 do 2880 { 2881 if (sprite[j].picnum == lType && j != vm.spriteNum) 2882 { 2883 lTemp=ldist(&sprite[vm.spriteNum], &sprite[j]); 2884 if (lTemp < lMaxDist) 2885 { 2886 lTemp2=klabs(sprite[vm.spriteNum].z-sprite[j].z); 2887 if (lTemp2 < lMaxZDist) 2888 { 2889 lFound=j; 2890 j = MAXSPRITES; 2891 break; 2892 } 2893 } 2894 } 2895 j = nextspritestat[j]; 2896 } 2897 while (j>=0); 2898 if (j == MAXSPRITES) 2899 break; 2900 } 2901 while (k--); 2902 Gv_SetVar(lVarID, lFound); 2903 2904 continue; 2905 } 2906 // ^^^ 2907 2908 case CON_GETTICKS: 2909 insptr++; 2910 { 2911 int32_t j=*insptr++; 2912 Gv_SetVar(j, timerGetTicks()); 2913 } 2914 continue; 2915 2916 case CON_SETASPECT: 2917 insptr++; 2918 { 2919 int32_t daxrange = Gv_GetVar(*insptr++), dayxaspect = Gv_GetVar(*insptr++); 2920 if (daxrange < (1<<12)) daxrange = (1<<12); 2921 if (daxrange > (1<<20)) daxrange = (1<<20); 2922 if (dayxaspect < (1<<12)) dayxaspect = (1<<12); 2923 if (dayxaspect > (1<<20)) dayxaspect = (1<<20); 2924 renderSetAspect(daxrange, dayxaspect); 2925 continue; 2926 } 2927 2928 // vvv CURSPR 2929 case CON_SETI: 2930 { 2931 int32_t newcurspritei; 2932 2933 insptr++; 2934 newcurspritei = Gv_GetVar(*insptr++); 2935 X_ERROR_INVALIDSPRI(newcurspritei); 2936 vm.spriteNum = newcurspritei; 2937 vm.pSprite = &sprite[vm.spriteNum]; 2938 continue; 2939 } 2940 2941 case CON_SIZEAT: 2942 insptr += 3; 2943 X_ERROR_INVALIDSP(); 2944 vm.pSprite->xrepeat = (uint8_t) Gv_GetVar(*(insptr-2)); 2945 vm.pSprite->yrepeat = (uint8_t) Gv_GetVar(*(insptr-1)); 2946 #ifdef USE_STRUCT_TRACKERS 2947 if (vm.spriteNum != -1) spritechanged[vm.spriteNum]++; 2948 #endif 2949 continue; 2950 2951 case CON_CSTAT: 2952 insptr += 2; 2953 X_ERROR_INVALIDSP(); 2954 vm.pSprite->cstat = (int16_t) *(insptr-1); 2955 #ifdef USE_STRUCT_TRACKERS 2956 if (vm.spriteNum != -1) spritechanged[vm.spriteNum]++; 2957 #endif 2958 continue; 2959 2960 case CON_CSTATOR: 2961 insptr += 2; 2962 X_ERROR_INVALIDSP(); 2963 vm.pSprite->cstat |= (int16_t) Gv_GetVar(*(insptr-1)); 2964 #ifdef USE_STRUCT_TRACKERS 2965 if (vm.spriteNum != -1) spritechanged[vm.spriteNum]++; 2966 #endif 2967 continue; 2968 2969 case CON_CLIPDIST: 2970 insptr += 2; 2971 X_ERROR_INVALIDSP(); 2972 vm.pSprite->clipdist = (uint8_t) Gv_GetVar(*(insptr-1)); 2973 #ifdef USE_STRUCT_TRACKERS 2974 if (vm.spriteNum != -1) spritechanged[vm.spriteNum]++; 2975 #endif 2976 continue; 2977 2978 case CON_SPRITEPAL: 2979 insptr += 2; 2980 X_ERROR_INVALIDSP(); 2981 vm.pSprite->pal = Gv_GetVar(*(insptr-1)); 2982 #ifdef USE_STRUCT_TRACKERS 2983 if (vm.spriteNum != -1) spritechanged[vm.spriteNum]++; 2984 #endif 2985 continue; 2986 2987 case CON_CACTOR: 2988 insptr += 2; 2989 X_ERROR_INVALIDSP(); 2990 vm.pSprite->picnum = Gv_GetVar(*(insptr-1)); 2991 #ifdef USE_STRUCT_TRACKERS 2992 if (vm.spriteNum != -1) spritechanged[vm.spriteNum]++; 2993 #endif 2994 continue; 2995 2996 case CON_SPGETLOTAG: 2997 insptr++; 2998 X_ERROR_INVALIDSP(); 2999 Gv_SetVar(M32_LOTAG_VAR_ID, vm.pSprite->lotag); 3000 continue; 3001 3002 case CON_SPGETHITAG: 3003 insptr++; 3004 X_ERROR_INVALIDSP(); 3005 Gv_SetVar(M32_HITAG_VAR_ID, vm.pSprite->hitag); 3006 continue; 3007 3008 case CON_SECTGETLOTAG: 3009 insptr++; 3010 X_ERROR_INVALIDSP(); 3011 Gv_SetVar(M32_LOTAG_VAR_ID, sector[vm.pSprite->sectnum].lotag); 3012 continue; 3013 3014 case CON_SECTGETHITAG: 3015 insptr++; 3016 X_ERROR_INVALIDSP(); 3017 Gv_SetVar(M32_HITAG_VAR_ID, sector[vm.pSprite->sectnum].hitag); 3018 continue; 3019 3020 case CON_GETTEXTUREFLOOR: 3021 insptr++; 3022 X_ERROR_INVALIDSP(); 3023 Gv_SetVar(M32_TEXTURE_VAR_ID, sector[vm.pSprite->sectnum].floorpicnum); 3024 continue; 3025 3026 case CON_GETTEXTURECEILING: 3027 insptr++; 3028 X_ERROR_INVALIDSP(); 3029 Gv_SetVar(M32_TEXTURE_VAR_ID, sector[vm.pSprite->sectnum].ceilingpicnum); 3030 continue; 3031 // ^^^ 3032 case CON_DRAWLINE16: 3033 case CON_DRAWLINE16B: 3034 case CON_DRAWLINE16Z: 3035 insptr++; 3036 { 3037 int32_t x1=Gv_GetVar(*insptr++), y1=Gv_GetVar(*insptr++); 3038 int32_t z1=tw==CON_DRAWLINE16Z?Gv_GetVar(*insptr++):0; 3039 int32_t x2=Gv_GetVar(*insptr++), y2=Gv_GetVar(*insptr++); 3040 int32_t z2=tw==CON_DRAWLINE16Z?Gv_GetVar(*insptr++):0; 3041 int32_t col=Gv_GetVar(*insptr++), odrawlinepat=drawlinepat; 3042 int32_t xofs=0, yofs=0; 3043 3044 if (tw==CON_DRAWLINE16B || tw==CON_DRAWLINE16Z) 3045 { 3046 editorGet2dScreenCoordinates(&x1,&y1, x1-pos.x,y1-pos.y, zoom); 3047 editorGet2dScreenCoordinates(&x2,&y2, x2-pos.x,y2-pos.y, zoom); 3048 3049 if (tw==CON_DRAWLINE16Z && m32_sideview) 3050 { 3051 y1 += getscreenvdisp(z1-pos.z,zoom); 3052 y2 += getscreenvdisp(z2-pos.z,zoom); 3053 } 3054 3055 xofs = halfxdim16; 3056 yofs = midydim16; 3057 } 3058 3059 drawlinepat = m32_drawlinepat; 3060 editorDraw2dLine(xofs+x1,yofs+y1, xofs+x2,yofs+y2, col>=0?editorcolors[col&15]:((-col)&255)); 3061 drawlinepat = odrawlinepat; 3062 continue; 3063 } 3064 3065 case CON_DRAWCIRCLE16: 3066 case CON_DRAWCIRCLE16B: 3067 case CON_DRAWCIRCLE16Z: 3068 insptr++; 3069 { 3070 int32_t x1=Gv_GetVar(*insptr++), y1=Gv_GetVar(*insptr++); 3071 int32_t z1 = tw==CON_DRAWCIRCLE16Z ? Gv_GetVar(*insptr++) : 0; 3072 int32_t r=Gv_GetVar(*insptr++); 3073 int32_t col=Gv_GetVar(*insptr++), odrawlinepat=drawlinepat; 3074 int32_t xofs=0, yofs=0, eccen=16384; 3075 3076 if (tw==CON_DRAWCIRCLE16B || tw==CON_DRAWCIRCLE16Z) 3077 { 3078 editorGet2dScreenCoordinates(&x1,&y1, x1-pos.x,y1-pos.y, zoom); 3079 if (m32_sideview) 3080 y1 += getscreenvdisp(z1-pos.z, zoom); 3081 r = mulscale14(r,zoom); 3082 eccen = scalescreeny(eccen); 3083 xofs = halfxdim16; 3084 yofs = midydim16; 3085 } 3086 3087 drawlinepat = m32_drawlinepat; 3088 editorDraw2dCircle(xofs+x1, yofs+y1, r, eccen, col>=0?editorcolors[col&15]:((-col)&255)); 3089 drawlinepat = odrawlinepat; 3090 continue; 3091 } 3092 3093 case CON_ROTATESPRITEA: 3094 case CON_ROTATESPRITE16: 3095 case CON_ROTATESPRITE: 3096 insptr++; 3097 { 3098 int32_t x=Gv_GetVar(*insptr++), y=Gv_GetVar(*insptr++), z=Gv_GetVar(*insptr++); 3099 int32_t a=Gv_GetVar(*insptr++), tilenum=Gv_GetVar(*insptr++), shade=Gv_GetVar(*insptr++); 3100 int32_t pal=Gv_GetVar(*insptr++), orientation=Gv_GetVar(*insptr++); 3101 int32_t alpha = (tw == CON_ROTATESPRITEA) ? Gv_GetVar(*insptr++) : 0; 3102 int32_t x1=Gv_GetVar(*insptr++), y1=Gv_GetVar(*insptr++); 3103 int32_t x2=Gv_GetVar(*insptr++), y2=Gv_GetVar(*insptr++); 3104 3105 if (tw != CON_ROTATESPRITE16 && !(orientation&ROTATESPRITE_FULL16)) 3106 { 3107 x<<=16; 3108 y<<=16; 3109 } 3110 3111 orientation &= (ROTATESPRITE_MAX-1); 3112 3113 rotatesprite_(x,y,z,a,tilenum,shade,pal,2|orientation,alpha,0,x1,y1,x2,y2); 3114 continue; 3115 } 3116 3117 case CON_SETGAMEPALETTE: 3118 insptr++; 3119 SetGamePalette(Gv_GetVar(*insptr++)); 3120 continue; 3121 3122 // *** sounds 3123 //case CON_IFSOUND: 3124 // insptr++; 3125 // { 3126 // int32_t j=Gv_GetVar(*insptr); 3127 // if (S_InvalidSound(j)) 3128 // { 3129 // M32_ERROR("Invalid sound %d", j); 3130 // insptr++; 3131 // continue; 3132 // } 3133 // VM_DoConditional(S_CheckSoundPlaying(vm.spriteNum,j)); 3134 // } 3135 // continue; 3136 3137 //case CON_IFNOSOUNDS: 3138 // VM_DoConditional(S_SoundsPlaying(vm.spriteNum) < 0); 3139 //continue; 3140 3141 case CON_IFIN3DMODE: 3142 VM_DoConditional(in3dmode()); 3143 continue; 3144 3145 // ifaimingsprite and -wall also work in 2d mode, but you must "and" with 16383 yourself 3146 case CON_IFAIMINGSPRITE: 3147 VM_DoConditional(AIMING_AT_SPRITE || (!in3dmode() && pointhighlight>=16384)); 3148 continue; 3149 case CON_IFAIMINGWALL: 3150 VM_DoConditional(AIMING_AT_WALL_OR_MASK || (!in3dmode() && linehighlight>=0)); 3151 continue; 3152 case CON_IFAIMINGSECTOR: 3153 VM_DoConditional(AIMING_AT_CEILING_OR_FLOOR); 3154 continue; 3155 case CON_IFINTERACTIVE: 3156 VM_DoConditional(vm.miscflags&VMFLAG_MISC_INTERACTIVE); 3157 continue; 3158 3159 //case CON_GETSOUNDFLAGS: 3160 // insptr++; 3161 // { 3162 // int32_t j=Gv_GetVar(*insptr++), var=*insptr++; 3163 // if (S_InvalidSound(j)) 3164 // { 3165 // M32_ERROR("Invalid sound %d", j); 3166 // insptr++; 3167 // continue; 3168 // } 3169 // 3170 // Gv_SetVar(var, S_SoundFlags(j)); 3171 // } 3172 // continue; 3173 // 3174 //case CON_SOUNDVAR: 3175 //case CON_STOPSOUNDVAR: 3176 //case CON_SOUNDONCEVAR: 3177 //case CON_GLOBALSOUNDVAR: 3178 // insptr++; 3179 // { 3180 // int32_t j=Gv_GetVar(*insptr++); 3181 // 3182 // if (S_InvalidSound(j)) 3183 // { 3184 // M32_ERROR("Invalid sound %d", j); 3185 // continue; 3186 // } 3187 // 3188 // switch (tw) 3189 // { 3190 // case CON_SOUNDONCEVAR: 3191 // if (!S_CheckSoundPlaying(vm.spriteNum,j)) 3192 // A_PlaySound((int16_t)j,vm.spriteNum); 3193 // break; 3194 // case CON_GLOBALSOUNDVAR: 3195 // A_PlaySound((int16_t)j,-1); 3196 // break; 3197 // case CON_STOPSOUNDVAR: 3198 // if (S_CheckSoundPlaying(vm.spriteNum,j)) 3199 // S_StopSound((int16_t)j); 3200 // break; 3201 // case CON_SOUNDVAR: 3202 // A_PlaySound((int16_t)j,vm.spriteNum); 3203 // break; 3204 // } 3205 // } 3206 // continue; 3207 // 3208 //case CON_STOPALLSOUNDS: 3209 // insptr++; 3210 // S_StopAllSounds(); 3211 // continue; 3212 3213 default: 3214 VM_ScriptInfo(); 3215 3216 OSD_Printf("\nAn error has occurred in the Mapster32 virtual machine.\n\n" 3217 "Please e-mail the file mapster32.log along with every M32 file\n" 3218 "you're using and instructions how to reproduce this error to\n" 3219 "development@voidpoint.com.\n\n" 3220 "Thank you!\n"); 3221 vm.flags |= VMFLAG_ERROR; 3222 Bfflush(NULL); 3223 return 1; 3224 } 3225 } 3226 3227 return 0; 3228 }