OSDN Git Service

wwww
[proj16/16.git] / 16 / v2 / source / verge / ENGINE / VC.C
1 /*\r
2 Copyright (C) 1998 BJ Eirich (aka vecna)\r
3 This program is free software; you can redistribute it and/or\r
4 modify it under the terms of the GNU General Public License\r
5 as published by the Free Software Foundation; either version 2\r
6 of the License, or (at your option) any later version.\r
7 This program is distributed in the hope that it will be useful,\r
8 but WITHOUT ANY WARRANTY; without even the implied warranty of\r
9 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.\r
10 See the GNU General Public Lic\r
11 See the GNU General Public License for more details.\r
12 You should have received a copy of the GNU General Public License\r
13 along with this program; if not, write to the Free Software\r
14 Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.\r
15 */\r
16 \r
17 // -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-\r
18 \r
19 #define VC_H\r
20 #include <math.h>\r
21 #include "verge.h"\r
22 #include "vccode.h"\r
23 #include "sincos.h"\r
24 #include "mikmod.h"\r
25 \r
26 #define USERFUNC_MARKER 10000\r
27 \r
28 // ================================= Data ====================================\r
29 \r
30 char *sysvc, *mapvc, *basevc;         // VC pool ptrs\r
31 char *code;                           // VC current instruction pointer (IP)\r
32 \r
33 int *globalint;                       // system.vc global int variables\r
34 int maxint;                           // maximum allocated # of ints\r
35 char *stringbuf;                      // vc string workspace\r
36 int vcreturn;                         // return value of last function\r
37 char *movescriptbuf;                  // VC EntityMove buffer\r
38 char vctrack=0;                       // VC call tracking to verge.log\r
39 \r
40 quad *vcstack;                        // VC stack (seperate from main stack)\r
41 quad *vcsp;                           // VC stack pointer [esp]\r
42 \r
43 int mapevents;                        // number of map events in this VC\r
44 char *mapvctbl[1024];                 // map VC offset table\r
45 \r
46 int hookretrace=0;\r
47 int hooktimer=0;\r
48 int invc=0;\r
49 \r
50 // -----------------\r
51 \r
52 typedef struct\r
53 {\r
54   char fname[40];\r
55   char argtype[20];\r
56   int numargs, numlocals;\r
57   int returntype;\r
58   int syscodeofs;\r
59 } funcdecl;\r
60 \r
61 funcdecl *funcs;\r
62 int numfuncs;\r
63 \r
64 typedef struct\r
65 {\r
66   char vname[40];\r
67   int vsofs;\r
68   int arraylen;\r
69 } strdecl;\r
70 \r
71 strdecl *str;\r
72 int numstr=0;\r
73 int stralloc;\r
74 \r
75 typedef struct\r
76 {\r
77   char vname[40];\r
78   int varstartofs;\r
79   int arraylen;\r
80 } vardecl;\r
81 \r
82 vardecl *vars;\r
83 int numvars;\r
84 char kill=0;\r
85 \r
86 // -- local func vars --\r
87 \r
88 typedef struct\r
89 {\r
90   int nargs[20];\r
91   char s[2560];\r
92 } lvars;\r
93 \r
94 //lvars *lvar;\r
95 lvars lvar;\r
96 \r
97 // ============================== Prototypes =================================\r
98 \r
99 void ResolveString(char *buffer);\r
100 void ExecuteSection();\r
101 void ExecuteEvent(int i);\r
102 void ExecuteUserFunc(int i);\r
103 \r
104 // ================================= Code ====================================\r
105 \r
106 int ProcessOperand();                 // Mutually dependant functions suck.\r
107 int ProcessIfOperand();               // Hell yeah they do, bitch.\r
108 void HandleExternFunc();\r
109 void HandleStdLib();\r
110 void ExecuteBlock();\r
111 \r
112 void LoadSystemVC()\r
113 {\r
114   VFILE *f=0;\r
115   int i=0;\r
116 \r
117   Log("Initializing VC interpreter");\r
118   if (!(f=vopen("system.idx"))) err("Could not open system.idx.");\r
119   vread(&numvars, 4, f);\r
120   vars=(vardecl *) valloc(numvars*sizeof(vardecl), "LoadSystemVC:vars", OID_VC);\r
121   vread(vars, numvars*48, f);\r
122   vread(&numfuncs, 4, f);\r
123   funcs=(funcdecl *) valloc(numfuncs*sizeof(funcdecl), "LoadSystemVC:funcs", OID_VC);\r
124   vread(funcs, numfuncs*76, f);\r
125   vread(&numstr, 4, f);\r
126   str=(strdecl *) valloc(numstr*sizeof(strdecl), "LoadSystemVC:str", OID_VC);\r
127   vread(str, numstr*44, f);\r
128   vclose(f);\r
129 \r
130   if (!(f=vopen("system.vcs"))) err("Could not open system.vcs");\r
131   i=filesize(f);\r
132   sysvc=(char *) valloc(i, "LoadSystemVC:sysvc", OID_VC);\r
133   vread(&numfuncs, 4, f);\r
134   vread(&maxint, 4, f);\r
135   vread(&stralloc, 4, f);\r
136 \r
137   globalint=(int *) valloc(maxint ? maxint*4 : 4, "globalint", OID_VC);\r
138   if (stralloc)\r
139   {\r
140     stringbuf=(char *) valloc((stralloc*256),\r
141       "LoadSystemVC:stringbuf", OID_VC);\r
142   }\r
143   else\r
144   {\r
145     stringbuf=(char *) valloc(256,\r
146       "LoadSystemVC:stringbuf (256)", OID_VC);\r
147   }\r
148   vread(sysvc, i, f);\r
149   vclose(f);\r
150 \r
151   // Initialize VC stack\r
152   vcstack=(quad *) valloc(6000, "vcstack", OID_VC);\r
153   vcsp=vcstack;\r
154 \r
155   movescriptbuf=(char *) valloc(65535, "movescriptbuf", OID_VC);\r
156 \r
157 Log("system vclib init: %d funcs, %d ints (%d bytes), %d strings (%d bytes)",\r
158   numfuncs, numvars, maxint*4, numstr, stralloc*256);\r
159 }\r
160 \r
161 void LoadMapVC(VFILE *f)\r
162 { int codesize=0;\r
163 \r
164   vread(&mapevents, 4, f);\r
165   vread(mapvctbl, 4*mapevents, f);\r
166   vread(&codesize, 4, f);\r
167   mapvc=(char *) valloc(codesize, "mapvc", OID_VC);\r
168   vread(mapvc, codesize, f);\r
169 }\r
170 \r
171 byte GrabC()\r
172 {\r
173   return *code++;\r
174 }\r
175 \r
176 word GrabW(void)\r
177 {\r
178   word *ptr=(word *) code;\r
179   code+=2;\r
180   return *ptr;\r
181 }\r
182 \r
183 quad GrabD(void)\r
184 {\r
185   quad *ptr=(quad *) code;\r
186   code+=4;\r
187   return *ptr;\r
188 }\r
189 \r
190 void GrabString(char *str)\r
191 { int i=0;\r
192 \r
193   i=0;\r
194   while (*code)\r
195   {\r
196     str[i]=*code;\r
197     code++;\r
198     i++;\r
199   }\r
200   str[i]=0;\r
201   code++;\r
202 }\r
203 \r
204 int ReadInt(char category, int loc, int ofs)\r
205 {\r
206   switch (category)\r
207   {\r
208     case op_UVAR:    return globalint[loc];\r
209     case op_UVARRAY: return globalint[loc];\r
210     case op_HVAR0:   switch (loc)\r
211                      {\r
212                        case 0: return xwin;\r
213                        case 1: return ywin;\r
214                        case 2: return cameratracking;\r
215                        case 3: return timer_count;\r
216                        case 4: return up;\r
217                        case 5: return down;\r
218                        case 6: return left;\r
219                        case 7: return right;\r
220                        case 8: return b1;\r
221                        case 9: return b2;\r
222                        case 10: return b3;\r
223                        case 11: return b4;\r
224                        case 12: return sx;\r
225                        case 13: return sy;\r
226                        case 14: return playernum;\r
227                        case 15: return cc;\r
228                        case 16: return tracker;\r
229                        case 17: return mx;\r
230                        case 18: return my;\r
231                        case 19: return mb;\r
232                        case 20: return vctrack;\r
233                        case 21: return width;\r
234                        case 22: return depth;\r
235                        case 23: return mp_volume;\r
236                        case 24: return (int)vsp;\r
237                        case 25: return lastent;\r
238                        case 26: return last_pressed;\r
239                      }\r
240     case op_HVAR1:   switch (loc)\r
241                      {\r
242                        case 0: return (int) screen[ofs];\r
243                        case 1: return entity[ofs].x;\r
244                        case 2: return entity[ofs].y;\r
245                        case 3: return entity[ofs].tx;\r
246                        case 4: return entity[ofs].ty;\r
247                        case 5: return entity[ofs].facing;\r
248                        case 6: return entity[ofs].moving;\r
249                        case 7: return entity[ofs].specframe;\r
250                        case 8: return entity[ofs].speed;\r
251 //                       case 9: return entity[ofs].movecode;\r
252                        case 10: return entidx[ofs];\r
253                        case 11: return key[ofs];\r
254                        case 12: return layer[ofs].hline;\r
255                        case 13: return (int) (*(byte *)ofs);\r
256                        case 14: return (int) (*(word *)ofs);\r
257                        case 15: return (int) (*(quad *)ofs);\r
258                        case 16: return (int) pal[ofs];\r
259                        case 17: return (int) (*(char *)ofs);\r
260                        case 18: return (int) (*(short*)ofs);\r
261                        case 19: return (int) (*(int  *)ofs);\r
262                      }\r
263      case op_LVAR:   return lvar.nargs[loc];\r
264     default:\r
265       err("VC Execution error: Invalid ReadInt category %d", (int) category);\r
266   }\r
267   return 0;\r
268 }\r
269 \r
270 void WriteInt(char category, int loc, int ofs, int value)\r
271 {\r
272   switch (category)\r
273   {\r
274     case op_UVAR:    globalint[loc]=value; break;\r
275     case op_UVARRAY: globalint[loc]=value; break;\r
276     case op_HVAR0:   switch (loc)\r
277                      {\r
278                        case 0: xwin=value; return;\r
279                        case 1: ywin=value; return;\r
280                        case 2: cameratracking=value; return;\r
281                        case 3: timer_count=value; return;\r
282                        case 16: tracker=value; return;\r
283                        case 20: vctrack=value; return;\r
284                        case 23: mp_volume=value; return;\r
285                        case 26: last_pressed=value; return;\r
286                      }\r
287     case op_HVAR1:   switch (loc)\r
288                      {\r
289                        case 0: screen[ofs]=(byte) value; return;\r
290                        case 1: entity[ofs].x=value; return;\r
291                        case 2: entity[ofs].y=value; return;\r
292                        case 3: entity[ofs].tx=value; return;\r
293                        case 4: entity[ofs].ty=value; return;\r
294                        case 5: entity[ofs].facing=value; return;\r
295                        case 6: entity[ofs].moving=value; return;\r
296                        case 7: entity[ofs].specframe=value; return;\r
297                        case 8: entity[ofs].speed=value; return;\r
298 //                       case 9: entity[ofs].movecode=value; return;\r
299 //                       case 10:\r
300                        case 11: key[ofs]=value; return;\r
301                        case 12: layer[ofs].hline=value; return;\r
302                        case 13: (*(byte *)ofs)=(byte) value; return;\r
303                        case 14: (*(word *)ofs)=(word) value; return;\r
304                        case 15: (*(quad *)ofs)=(quad) value; return;\r
305                        case 16: pal[ofs]=value; return;\r
306                        case 17: (*(char *)ofs)=(byte) value; return;\r
307                        case 18: (*(short*)ofs)=(word) value; return;\r
308                        case 19: (*(int  *)ofs)=(quad) value; return;\r
309                      }\r
310     case op_LVAR:   lvar.nargs[loc]=value; return;\r
311     default:\r
312       err("VC Execution error: Invalid WriteInt category %d", (int) category);\r
313   }\r
314 }\r
315 \r
316 int ResolveOperand()\r
317 {\r
318   int cr=0;\r
319   int d=0;\r
320   byte c=0;\r
321 \r
322   cr=ProcessOperand();                 // Get base number\r
323   while (1)\r
324   {\r
325      c=GrabC();\r
326      switch (c)\r
327      {\r
328         case op_ADD: cr += ProcessOperand(); continue;\r
329         case op_SUB: cr -= ProcessOperand(); continue;\r
330         case op_DIV: d=ProcessOperand();\r
331                      if (!d) cr=0; else cr /= d; continue;\r
332         case op_MULT: cr = cr * ProcessOperand(); continue;\r
333         case op_MOD: d=ProcessOperand();\r
334                      if (!d) cr=0; else cr %= d; continue;\r
335         case op_SHL: cr = cr << ProcessOperand(); continue;\r
336         case op_SHR: cr = cr >> ProcessOperand(); continue;\r
337         case op_AND: cr = cr & ProcessOperand(); continue;\r
338         case op_OR:  cr = cr | ProcessOperand(); continue;\r
339         case op_XOR: cr = cr ^ ProcessOperand(); continue;\r
340         case op_END: break;\r
341      }\r
342      break;\r
343   }\r
344   return cr;\r
345 }\r
346 \r
347 int ProcessOperand()\r
348 { byte op_desc=0;\r
349   byte c=0;\r
350   quad d=0;\r
351   quad ofs=0;\r
352 \r
353   op_desc=GrabC();\r
354   switch (op_desc)\r
355   {\r
356      case op_IMMEDIATE: return GrabD();\r
357      case op_HVAR0: c=GrabC(); return ReadInt(op_HVAR0, c, 0);\r
358      case op_HVAR1: c=GrabC(); ofs=ResolveOperand(); return ReadInt(op_HVAR1, c, ofs);\r
359      case op_UVAR:  d=GrabD(); return ReadInt(op_UVAR, d, 0);\r
360      case op_UVARRAY: d=GrabD(); d+=ResolveOperand(); return ReadInt(op_UVARRAY, d, 0);\r
361      case op_LVAR: c=GrabC(); return lvar.nargs[c];\r
362      case op_BFUNC: HandleStdLib();\r
363                     return vcreturn;\r
364      case op_UFUNC: HandleExternFunc();\r
365                     return vcreturn;\r
366      case op_GROUP: return ResolveOperand();\r
367      default: sprintf(strbuf,"VC Execution error: Invalid operand %d.",op_desc);\r
368               err(strbuf); break;\r
369   }\r
370   return 0;\r
371 }\r
372 \r
373 void HandleStringOperand(char *buffer)\r
374 {\r
375   char tbuf[256];\r
376   char *d=0;\r
377   word w=0;\r
378   int c=0;\r
379   int i=0;\r
380   int j=0;\r
381   int z=0;\r
382 \r
383   c=GrabC();\r
384   switch (c)\r
385   {\r
386     case s_IMMEDIATE: GrabString(buffer); break;\r
387     case s_GLOBAL: w=GrabW();\r
388                    d=(char *) (int) stringbuf + (w*256);\r
389                    z=strlen(d);\r
390                    if (strlen(buffer)+z+1>250)\r
391                      err("Combined string length exceeds 250 char max.");\r
392                    memcpy(buffer, d, z+1);\r
393                    break;\r
394     case s_ARRAY:  w=GrabW();\r
395                    w+=ResolveOperand();\r
396                    d=(char *) (int) stringbuf + (w*256);\r
397                    z=strlen(d);\r
398                    if (strlen(buffer)+z+1>250)\r
399                      err("Combined string length exceeds 250 char max.");\r
400                    memcpy(buffer, d, z+1);\r
401                    break;\r
402     case s_NUMSTR: i=ResolveOperand();\r
403                    sprintf(buffer,"%d",i);\r
404                    break;\r
405     case s_LEFT:   ResolveString(tbuf);\r
406                    i=ResolveOperand();\r
407                    c=i<strlen(tbuf) ? i : strlen(tbuf);\r
408                    if (strlen(buffer)+c+1>250)\r
409                      err("Combined string length exceeds 250 char max.");\r
410                    memcpy(buffer, tbuf, c);\r
411                    buffer[c]=0;\r
412                    break;\r
413     case s_RIGHT:  ResolveString(tbuf);\r
414                    i=ResolveOperand();\r
415                    c=i<strlen(tbuf) ? i : strlen(tbuf);\r
416                    if (strlen(buffer)+c+1>250)\r
417                      err("Combined string length exceeds 250 char max.");\r
418                    memcpy(buffer, tbuf+strlen(tbuf)-c, c);\r
419                    buffer[c]=0;\r
420                    break;\r
421     case s_MID:    ResolveString(tbuf);\r
422                    i=ResolveOperand();\r
423                    j=ResolveOperand();\r
424                    i=i<strlen(tbuf) ? i : strlen(tbuf);\r
425                    j=j<strlen(tbuf)-i ? j : strlen(tbuf)-i;\r
426                    if (strlen(buffer)+j+1>250)\r
427                      err("Combined string length exceeds 250 char max.");\r
428                    memcpy(buffer, tbuf+i, j);\r
429                    buffer[j]=0;\r
430                    break;\r
431     case s_CHR:    if (strlen(buffer)+2>50)\r
432                      err("Combined string length exceeds 250 char max.");\r
433                    buffer[0]=(char) ResolveOperand();\r
434                    buffer[1]=0;\r
435                    break;\r
436     case s_LOCAL:  c=GrabC();\r
437                    d=&lvar.s[c*256];\r
438                    z=strlen(d);\r
439                    if (strlen(buffer)+z+1>250)\r
440                      err("Combined string length exceeds 250 char max.");\r
441                    memcpy(buffer, d, z+1);\r
442                    break;\r
443     default: err("Invalid VC string operand %d", (int) c);\r
444   }\r
445 }\r
446 \r
447 void ResolveString(char *buffer)\r
448 { char c=0;\r
449 \r
450   HandleStringOperand(buffer);\r
451   while (1)\r
452   {\r
453     c=GrabC();\r
454     switch (c)\r
455     {\r
456       case s_ADD:\r
457         HandleStringOperand((char *) (int) buffer + strlen(buffer)); break;\r
458       case s_END: return;\r
459       default:\r
460         err("VC execution error: Unknown string operator %d",(int) c);\r
461     }\r
462   }\r
463 }\r
464 \r
465 void vcpush(quad info)\r
466 {\r
467   if (vcsp>=vcstack+1500) err("VC stack overflow.");\r
468   *vcsp=info;\r
469   vcsp++;\r
470 }\r
471 \r
472 quad vcpop()\r
473 {\r
474   if (vcsp==vcstack) err("VC stack underflow.");\r
475   vcsp--;\r
476   return *vcsp;\r
477 }\r
478 \r
479 void  ReadVCVar()\r
480 { int i=0;\r
481   int j=0;\r
482 \r
483   strlwr((char *) args[1]);\r
484   for (i=0; i<=numvars; i++)\r
485     if (!strcmp(vars[i].vname, (char *) args[1])) break;\r
486   if (i<numvars)\r
487   {\r
488     j=vars[i].varstartofs;\r
489     if (vars[i].arraylen>1)\r
490       j+=atoi((char *) args[2]);\r
491     j=globalint[j];\r
492     sprintf(strbuf,"%s:%d",vars[i].vname, j);\r
493     Con_Printf(strbuf);\r
494     return;\r
495   }\r
496   for (i=0; i<=numstr; i++)\r
497     if (!strcmp(str[i].vname, (char *) args[1])) break;\r
498   if (i<numstr)\r
499   {\r
500     j=(int) stringbuf + (i*256);\r
501     sprintf(strbuf,"%s:%s",str[i].vname, (char *) j);\r
502     Con_Printf(strbuf);\r
503     return;\r
504   }\r
505   Con_Printf("No such VC variable.");\r
506 }\r
507 \r
508 void WriteVCVar()\r
509 { int i=0;\r
510   int j=0;\r
511 \r
512   strlwr((char *) args[1]);\r
513   for (i=0; i<=numvars; i++)\r
514     if (!strcmp(vars[i].vname, (char *) args[1])) break;\r
515   if (i<numvars)\r
516   {\r
517     j=vars[i].varstartofs;\r
518     if (vars[i].arraylen>1)\r
519     {\r
520       j+=atoi((char *) args[2]);\r
521       globalint[j]=atoi((char *) args[3]);\r
522     }\r
523     else globalint[j]=atoi((char *) args[2]);\r
524     sprintf(strbuf,"%s:%d", vars[i].vname, atoi((char *) args[2]));\r
525     Con_Printf(strbuf);\r
526     return;\r
527   }\r
528   for (i=0; i<=numstr; i++)\r
529     if (!strcmp(str[i].vname, (char *) args[1])) break;\r
530   if (i<numstr)\r
531   {\r
532     j=(int) stringbuf + (i*256);\r
533     memcpy((char *) j, (char *) args[2], strlen((char *) args[2])+1);\r
534     sprintf(strbuf,"%s:%s", str[i].vname, (char *) args[2]);\r
535     Con_Printf(strbuf);\r
536     return;\r
537   }\r
538   Con_Printf("No such VC variable.");\r
539 }\r
540 \r
541 // ======================= VC Standard Function Library =======================\r
542 \r
543 int ClipOn=1;\r
544 int LucentOn=0;\r
545 \r
546 void vc_Exit_()\r
547 {\r
548   ResolveString(strbuf);\r
549   err(strbuf);\r
550 }\r
551 \r
552 void vc_Message()\r
553 {\r
554   int i=0;\r
555   char str1[100];\r
556 \r
557   ResolveString(str1);\r
558   i=ResolveOperand();\r
559   Message(str1, i);\r
560 }\r
561 \r
562 void vc_Malloc()\r
563 {\r
564   int i=0;\r
565 \r
566   i=ResolveOperand();\r
567   vcreturn=(int) valloc(i, "vcreturn", OID_TEMP);\r
568 \r
569   Log("VC allocating %u bytes, ptr at %u.", i, vcreturn);\r
570 \r
571   if (!vcreturn) Message("Warning: VC failed malloc", 750);\r
572 }\r
573 \r
574 void vc_Free()\r
575 {\r
576   int i=0;\r
577 \r
578   i=ResolveOperand();\r
579   vfree((char *) i);\r
580 \r
581   Log("VC freeing allocated heap at %u.", i);\r
582 }\r
583 \r
584 void vc_pow()\r
585 {\r
586   int i=0;\r
587   int j=0;\r
588 \r
589   i=ResolveOperand();\r
590   j=ResolveOperand();\r
591   vcreturn=pow(i,j);\r
592 }\r
593 \r
594 void vc_loadimage()\r
595 {\r
596   byte *t=0;\r
597   char s[256];\r
598 \r
599   ResolveString(s);\r
600   t=VLoadImageBuf(s);\r
601   vcreturn=(int) t;\r
602 }\r
603 \r
604 void vc_copysprite()\r
605 {\r
606   int a=0;\r
607   int b=0;\r
608   int c=0;\r
609   int d=0;\r
610   byte *e=0;\r
611 \r
612   a=ResolveOperand();\r
613   b=ResolveOperand();\r
614   c=ResolveOperand();\r
615   d=ResolveOperand();\r
616   e=(byte *) ResolveOperand();\r
617   if (!ClipOn && !LucentOn) CopySprite(a,b,c,d,e);\r
618   if ( ClipOn && !LucentOn) CopySpriteClip(a,b,c,d,e);\r
619   if (!ClipOn &&  LucentOn) CopySpriteLucent(a,b,c,d,e);\r
620   if ( ClipOn &&  LucentOn) CopySpriteLucentClip(a,b,c,d,e);\r
621 }\r
622 \r
623 void vc_tcopysprite()\r
624 {\r
625   int a=0;\r
626   int b=0;\r
627   int c=0;\r
628   int d=0;\r
629   byte *e=0;\r
630 \r
631   a=ResolveOperand();\r
632   b=ResolveOperand();\r
633   c=ResolveOperand();\r
634   d=ResolveOperand();\r
635   e=(byte *) ResolveOperand();\r
636   if (!ClipOn && !LucentOn) TCopySprite(a,b,c,d,e);\r
637   if ( ClipOn && !LucentOn) TCopySpriteClip(a,b,c,d,e);\r
638   if (!ClipOn &&  LucentOn) TCopySpriteLucent(a,b,c,d,e);\r
639   if ( ClipOn &&  LucentOn) TCopySpriteLucentClip(a,b,c,d,e);\r
640 }\r
641 \r
642 void vc_EntitySpawn()\r
643 {\r
644   int a=0;\r
645   int b=0;\r
646   char chrname[80];\r
647 \r
648   a=ResolveOperand();\r
649   b=ResolveOperand();\r
650   ResolveString(chrname);\r
651   vcreturn=AllocateEntity(a, b, chrname);\r
652 }\r
653 \r
654 void vc_SetPlayer()\r
655 {\r
656   int i=0;\r
657 \r
658   i=ResolveOperand();\r
659   if (i>=entities) err("SetPlayer(): Entity index out of range");\r
660 \r
661   player=&entity[i];\r
662   playernum=i;\r
663 \r
664 //  entity[i].movecode=0;\r
665   entity[i].moving=0;\r
666 }\r
667 \r
668 void vc_Map()\r
669 {\r
670   hookretrace=0;\r
671   hooktimer=0;\r
672   kill=1;\r
673   ResolveString(startmap);\r
674 }\r
675 \r
676 void vc_LoadFont()\r
677 {\r
678   char vcstr[80];\r
679 \r
680   ResolveString(vcstr);\r
681   vcreturn=LoadFont(vcstr);\r
682 }\r
683 \r
684 void vc_PlayFLI()\r
685 {\r
686   char s[256];\r
687   BITMAP flibuf;\r
688   byte *data=0;\r
689   VFILE *f=0;\r
690   int i=0;\r
691 \r
692   ResolveString(s);\r
693   flibuf.w=sx;\r
694   flibuf.h=sy;\r
695   flibuf.data=screen;\r
696   if (!(f=vopen(s))) err("PlayFLI: Could not open %s.",s);\r
697   i=filesize(f);\r
698   data=(byte *) malloc(i);\r
699   if (!data) err("Not enough memory to play FLI.");\r
700   vread(data, i, f);\r
701   vclose(f);\r
702   play_memory_fli(data, &flibuf, 0, ShowPage);\r
703   timer_count=0;\r
704   set_intensity(63);\r
705 }\r
706 \r
707 void vc_PrintString()\r
708 {\r
709   char s[256];\r
710   int i=0;\r
711 \r
712   i=ResolveOperand();\r
713   ResolveString(s);\r
714   printstring(i,s);\r
715 }\r
716 \r
717 void vc_LoadRaw()\r
718 {\r
719   char s[256];\r
720   char *t=0;\r
721   VFILE *f=0;\r
722   int i=0;\r
723 \r
724   ResolveString(s);\r
725   if (!(f=vopen(s))) err("LoadRaw(): Could not open file %s",s);\r
726   i=filesize(f);\r
727   t=(char *) valloc(i, "LoadRaw:t", OID_VC);\r
728   vread(t, i, f);\r
729   vclose(f);\r
730   vcreturn=(int) t;\r
731 }\r
732 \r
733 void vc_SetTile()\r
734 {\r
735   int x=0;\r
736   int y=0;\r
737   int layr=0;\r
738   int value=0;\r
739 \r
740   x=ResolveOperand();\r
741   y=ResolveOperand();\r
742   layr=ResolveOperand();\r
743   value=ResolveOperand();\r
744 \r
745   switch (layr)\r
746   {\r
747     case 0:\r
748     case 1:\r
749     case 2:\r
750     case 3:\r
751     case 4:\r
752     case 5: layers[layr][(y*layer[layr].sizex)+x] = (short) value; break;\r
753     case 6: obstruct[(y*layer[0].sizex)+x] = (byte) value; break;\r
754     case 7: zone[(y*layer[0].sizex)+x] = (byte) value; break;\r
755     default: err("SetTile(): Invalid layer value");\r
756   }\r
757 }\r
758 \r
759 void vc_ScaleSprite()\r
760 {\r
761   int x,y,iw,ih,dw,dh,image;\r
762 \r
763   x=ResolveOperand();\r
764   y=ResolveOperand();\r
765   iw=ResolveOperand();\r
766   ih=ResolveOperand();\r
767   dw=ResolveOperand();\r
768   dh=ResolveOperand();\r
769   image=ResolveOperand();\r
770   if (!LucentOn) CopySpriteZoomClip(x,y,iw,ih,dw,dh,(byte *)image);\r
771   if ( LucentOn) CopySpriteZoomLucentClip(x,y,iw,ih,dw,dh,(byte *)image);\r
772 }\r
773 \r
774 void vc_EntityMove()\r
775 {\r
776   int i;\r
777 \r
778   i=ResolveOperand();\r
779   entity[i].moving=0;\r
780   entity[i].speedct=0;\r
781 \r
782    entity[i].delayct=0;\r
783    entity[i].mode=0;\r
784    entity[i].data1=0;\r
785 \r
786   ResolveString((char *) (int) movescriptbuf + (int) (i*256));\r
787   entity[i].scriptofs=(char *) (int) movescriptbuf + (int) (i*256);\r
788   entity[i].movecode=4;\r
789 }\r
790 \r
791 void vc_HLine()\r
792 {\r
793   int x, y, x2, c;\r
794 \r
795   x=ResolveOperand();\r
796   y=ResolveOperand();\r
797   x2=ResolveOperand();\r
798   c=ResolveOperand();\r
799   if (!LucentOn) HLineClip(x,y,x2,c);\r
800   if ( LucentOn) HLineLucentClip(x,y,x2,c);\r
801 \r
802 }\r
803 \r
804 void vc_VLine()\r
805 {\r
806   int x, y, y2, c;\r
807 \r
808   x=ResolveOperand();\r
809   y=ResolveOperand();\r
810   y2=ResolveOperand();\r
811   c=ResolveOperand();\r
812   if (!LucentOn) VLineClip(x,y,y2,c);\r
813   if ( LucentOn) VLineLucentClip(x,y,y2,c);\r
814 }\r
815 \r
816 void vc_Line()\r
817 {\r
818   int x, y, x2, y2, c;\r
819 \r
820   x=ResolveOperand();\r
821   y=ResolveOperand();\r
822   x2=ResolveOperand();\r
823   y2=ResolveOperand();\r
824   c=ResolveOperand();\r
825   if (!LucentOn) LineClip(x,y,x2,y2,c);\r
826   if ( LucentOn) LineLucentClip(x,y,x2,y2,c);\r
827 }\r
828 \r
829 void vc_Circle()\r
830 {\r
831   int x, y, radius, c;\r
832 \r
833   x=ResolveOperand();\r
834   y=ResolveOperand();\r
835   radius=ResolveOperand();\r
836   c=ResolveOperand();\r
837   if (!LucentOn) CircleClip(x,y,radius,c);\r
838   if ( LucentOn) CircleLucentClip(x,y,radius,c);\r
839 }\r
840 \r
841 void vc_CircleFill()\r
842 {\r
843   int x, y, radius, c;\r
844 \r
845   x=ResolveOperand();\r
846   y=ResolveOperand();\r
847   radius=ResolveOperand();\r
848   c=ResolveOperand();\r
849   if (!LucentOn) CircleFillClip(x,y,radius,c);\r
850   if ( LucentOn) CircleFillLucentClip(x,y,radius,c);\r
851 }\r
852 \r
853 void vc_Rect()\r
854 {\r
855   int x, y, x2, y2, c;\r
856 \r
857   x=ResolveOperand();\r
858   y=ResolveOperand();\r
859   x2=ResolveOperand();\r
860   y2=ResolveOperand();\r
861   c=ResolveOperand();\r
862   if (!LucentOn) RectClip(x,y,x2,y2,c);\r
863   if ( LucentOn) RectLucentClip(x,y,x2,y2,c);\r
864 }\r
865 \r
866 void vc_RectFill()\r
867 {\r
868   int x, y, x2, y2, c;\r
869 \r
870   x=ResolveOperand();\r
871   y=ResolveOperand();\r
872   x2=ResolveOperand();\r
873   y2=ResolveOperand();\r
874   c=ResolveOperand();\r
875   if (!LucentOn) RectFillClip(x,y,x2,y2,c);\r
876   if ( LucentOn) RectFillLucentClip(x,y,x2,y2,c);\r
877 }\r
878 \r
879 void vc_strlen()\r
880 {\r
881   char str[256];\r
882 \r
883   ResolveString(str);\r
884   vcreturn=strlen(str);\r
885 }\r
886 \r
887 void vc_strcmp()\r
888 {\r
889   char str1[256], str2[256];\r
890 \r
891   ResolveString(str1);\r
892   ResolveString(str2);\r
893   vcreturn=strcmp(str1, str2);\r
894 }\r
895 \r
896 void vc_FontWidth()\r
897 {\r
898   int i;\r
899 \r
900   i=ResolveOperand();\r
901   if (i>=numfonts)\r
902   {\r
903     vcreturn=0;\r
904     return;\r
905   }\r
906   vcreturn=font[i].width;\r
907 }\r
908 \r
909 void vc_FontHeight()\r
910 {\r
911   int i;\r
912 \r
913   i=ResolveOperand();\r
914   if (i>=numfonts)\r
915   {\r
916     vcreturn=0;\r
917     return;\r
918   }\r
919   vcreturn=font[i].height;\r
920 }\r
921 \r
922 void vc_SetPixel()\r
923 {\r
924   int x, y, c;\r
925 \r
926   x=ResolveOperand();\r
927   y=ResolveOperand();\r
928   c=ResolveOperand();\r
929   SetPixelClip(x,y,c);\r
930 }\r
931 \r
932 void vc_GetPixel()\r
933 {\r
934   int x, y;\r
935 \r
936   x=ResolveOperand();\r
937   y=ResolveOperand();\r
938   vcreturn=GetPixelClip(x,y);\r
939 }\r
940 \r
941 void vc_EntityOnScreen()\r
942 {\r
943   int i,j;\r
944 \r
945   i=ResolveOperand();\r
946   for (j=0; j<cc; j++)\r
947    if (entidx[j]==i)\r
948    {\r
949      vcreturn=1;\r
950      return;\r
951    }\r
952   vcreturn=0;\r
953 }\r
954 \r
955 void vc_GetTile()\r
956 {\r
957   int x, y, l;\r
958 \r
959   x=ResolveOperand();\r
960   y=ResolveOperand();\r
961   l=ResolveOperand();\r
962 \r
963   switch (l)\r
964   {\r
965     case 0:\r
966     case 1:\r
967     case 2:\r
968     case 3:\r
969     case 4:\r
970     case 5: vcreturn=(int) layers[l][(y*layer[l].sizex)+x]; break;\r
971     case 6: vcreturn=(int) obstruct[(y*layer[0].sizex)+x]; break;\r
972     case 7: vcreturn=(int) zone[(y*layer[0].sizex)+x]; break;\r
973     default: err("GetTile(): Invalid layer value");\r
974   }\r
975 }\r
976 \r
977 void vc_SetResolution()\r
978 {\r
979   int xres, yres;\r
980 \r
981   xres=ResolveOperand();\r
982   yres=ResolveOperand();\r
983   ShutdownVideo(0);\r
984   vcreturn=InitVideo(xres,yres);\r
985 }\r
986 \r
987 void vc_SetRString()\r
988 {\r
989   ResolveString(rstring);\r
990 }\r
991 \r
992 void vc_SetClipRect()\r
993 {\r
994   cx1=ResolveOperand();\r
995   cy1=ResolveOperand();\r
996   cx2=ResolveOperand();\r
997   cy2=ResolveOperand();\r
998 }\r
999 \r
1000 void vc_SetRenderDest()\r
1001 {\r
1002   sx=ResolveOperand();\r
1003   sy=ResolveOperand();\r
1004   screen=(byte *) ResolveOperand();\r
1005 }\r
1006 \r
1007 void vc_RestoreRenderSettings()\r
1008 {\r
1009   cx1=0;\r
1010   cy1=0;\r
1011   cx2=tsx-1;\r
1012   cy2=tsy-1;\r
1013   sx=tsx;\r
1014   sy=tsy;\r
1015   screen=vscreen;\r
1016 }\r
1017 \r
1018 void vc_PartyMove()\r
1019 {\r
1020   player=0;\r
1021 \r
1022   entity[playernum].moving=0;\r
1023   entity[playernum].speedct=0;\r
1024   entity[playernum].delayct=0;\r
1025   entity[playernum].mode=0;\r
1026   entity[playernum].data1=0;\r
1027 \r
1028   vcpush(cameratracking);\r
1029   vcpush(tracker);\r
1030   if (cameratracking==1)\r
1031   {\r
1032     cameratracking=2;\r
1033     tracker=playernum;\r
1034   }\r
1035 \r
1036   ResolveString((char *) (int) movescriptbuf + (int) (playernum*256));\r
1037   entity[playernum].scriptofs=(char *) (int) movescriptbuf + (int) (playernum*256);\r
1038   entity[playernum].movecode=4;\r
1039 \r
1040   while (entity[playernum].movecode)\r
1041   {\r
1042     while (timer_count)\r
1043     {\r
1044       ProcessEntities();\r
1045       timer_count--;\r
1046     }\r
1047     Render();\r
1048     ShowPage();\r
1049   }\r
1050   tracker=vcpop();\r
1051   cameratracking=vcpop();\r
1052   player=&entity[playernum];\r
1053   timer_count=0;\r
1054 }\r
1055 \r
1056 void vc_WrapBlit()\r
1057 {\r
1058   int a,b,c,d,e;\r
1059 \r
1060   a=ResolveOperand();\r
1061   b=ResolveOperand();\r
1062   c=ResolveOperand();\r
1063   d=ResolveOperand();\r
1064   e=ResolveOperand();\r
1065   if (!LucentOn) WrapBlit(a,b,c,d,(byte *) e);\r
1066             else WrapBlitLucent(a,b,c,d,(byte *) e);\r
1067 }\r
1068 \r
1069 \r
1070 void vc_TWrapBlit()\r
1071 {\r
1072   int a,b,c,d,e;\r
1073 \r
1074   a=ResolveOperand();\r
1075   b=ResolveOperand();\r
1076   c=ResolveOperand();\r
1077   d=ResolveOperand();\r
1078   e=ResolveOperand();\r
1079   if (!LucentOn) WrapBlitMasked(a,b,c,d,(byte *) e);\r
1080             else WrapBlitLucentMasked(a,b,c,d,(byte *) e);\r
1081 }\r
1082 \r
1083 void vc_SetMousePos()\r
1084 {\r
1085   int x, y;\r
1086 \r
1087   x=ResolveOperand();\r
1088   y=ResolveOperand();\r
1089   SetMouse(x, y);\r
1090 }\r
1091 \r
1092 void vc_HookRetrace()\r
1093 {\r
1094   int script=0;\r
1095   char which;\r
1096 \r
1097   which=GrabC();\r
1098   switch (which)\r
1099   {\r
1100     case 1: script=ResolveOperand(); break;\r
1101     case 2: script=GrabD(); break;\r
1102   }\r
1103   if (which==2) script+=USERFUNC_MARKER;\r
1104   hookretrace=script;\r
1105 }\r
1106 \r
1107 void vc_HookTimer()\r
1108 {\r
1109   int script=0;\r
1110   char which;\r
1111 \r
1112   which=GrabC();\r
1113   switch (which)\r
1114   {\r
1115     case 1: script=ResolveOperand(); break;\r
1116     case 2: script=GrabD(); break;\r
1117   }\r
1118   if (which==2) script+=USERFUNC_MARKER;\r
1119   hooktimer=script;\r
1120 }\r
1121 \r
1122 void vc_HookKey()\r
1123 {\r
1124   int key, script=0;\r
1125   char which;\r
1126 \r
1127   key=ResolveOperand();\r
1128   which=GrabC();\r
1129 \r
1130   switch (which)\r
1131   {\r
1132     case 1: script=ResolveOperand(); break;\r
1133     case 2: script=GrabD(); break;\r
1134   }\r
1135   if (which==2) script+=USERFUNC_MARKER;\r
1136   bindarray[key]=script;\r
1137 }\r
1138 \r
1139 void vc_PlayMusic()\r
1140 {\r
1141   char songname[256];\r
1142 \r
1143   ResolveString(songname);\r
1144   PlayMusic(songname);\r
1145 }\r
1146 \r
1147 void vc_PaletteMorph()\r
1148 {\r
1149   int r,g,b,percent,intensity,i,wr,wg,wb;\r
1150 \r
1151   r=ResolveOperand(); if (r<0) r=0; if (r>63) r=63;\r
1152   g=ResolveOperand(); if (g<0) g=0; if (g>63) g=63;\r
1153   b=ResolveOperand(); if (b<0) b=0; if (b>63) b=63;\r
1154   percent=100-ResolveOperand();\r
1155   intensity=ResolveOperand();\r
1156 \r
1157   for (i=0; i<256; i++)\r
1158   {\r
1159      wr=pal[(i*3)];\r
1160      wg=pal[(i*3)+1];\r
1161      wb=pal[(i*3)+2];\r
1162 \r
1163      wr=((wr*percent)+(r*(100-percent)))/100;\r
1164      wg=((wg*percent)+(g*(100-percent)))/100;\r
1165      wb=((wb*percent)+(b*(100-percent)))/100;\r
1166 \r
1167      pal2[(i*3)]=wr*intensity/63;\r
1168      pal2[(i*3)+1]=wg*intensity/63;\r
1169      pal2[(i*3)+2]=wb*intensity/63;\r
1170   }\r
1171   SetPalette(pal2);\r
1172 }\r
1173 \r
1174 void EnforceNoDirectories(char *s)\r
1175 {\r
1176   char y[256], *p;\r
1177 \r
1178   strcpy(y, s);\r
1179   p=(char *) (int) y + (int) strlen(y);\r
1180   while (p>y && *p != '/' && *p != '\\')\r
1181     p--;\r
1182   if (*p == '/' || *p == '\\') p++;\r
1183   strcpy(s, p);\r
1184 }\r
1185 \r
1186 void vc_OpenFile()\r
1187 {\r
1188   VFILE *f;\r
1189   char fname[256];\r
1190 \r
1191   ResolveString(fname);\r
1192   EnforceNoDirectories(fname);\r
1193 \r
1194   f=vopen(fname);\r
1195   vcreturn=(quad) f;\r
1196 \r
1197   Log(" --> VC opened file %s, ptr %u", fname, (quad) f);\r
1198 }\r
1199 \r
1200 void vc_CloseFile()\r
1201 {\r
1202   VFILE *f;\r
1203 \r
1204   f=(VFILE *) ResolveOperand();\r
1205   vclose(f);\r
1206 \r
1207   Log(" --> VC closed file at ptr %u", (quad) f);\r
1208 }\r
1209 \r
1210 void vc_QuickRead()\r
1211 {\r
1212   char fname[256], c, *p;\r
1213   int d=0, l, i;\r
1214   VFILE *f;\r
1215   word w=0;\r
1216 \r
1217   ResolveString(fname);\r
1218   EnforceNoDirectories(fname);\r
1219   c=GrabC();\r
1220   if (c==op_STRING)\r
1221   {\r
1222     w=GrabW();\r
1223     d=0;\r
1224   }\r
1225   if (c==op_SARRAY)\r
1226   {\r
1227     w=GrabW();\r
1228     d=ResolveOperand();\r
1229   }\r
1230   l=ResolveOperand();\r
1231   l=l ? l : 1;\r
1232   if (!(f=vopen(fname))) err("QuickRead() - could not open %s",fname);\r
1233 \r
1234   p=(char *) (quad) stringbuf + ((w+d)*256);\r
1235   for (i=0; i<l; i++)\r
1236     vgets(p, 255, f);\r
1237   while (*p)\r
1238   {\r
1239     if (*p == 10 || *p == 13) *p=0;\r
1240     p++;\r
1241   }\r
1242   vclose(f);\r
1243 }\r
1244 \r
1245 void vc_AddFollower()\r
1246 {\r
1247   int i;\r
1248 \r
1249   i=ResolveOperand();\r
1250   if (i>=entities) err("AddFollower(): Not a valid entity index. (%d)",i);\r
1251   follower[(int)numfollowers]=i;\r
1252   numfollowers++;\r
1253 //  ResetFollowers();\r
1254 }\r
1255 \r
1256 void vc_FlatPoly()\r
1257 {\r
1258   int a, b, c, d, e, f, g;\r
1259 \r
1260   a=ResolveOperand();\r
1261   b=ResolveOperand();\r
1262   c=ResolveOperand();\r
1263   d=ResolveOperand();\r
1264   e=ResolveOperand();\r
1265   f=ResolveOperand();\r
1266   g=ResolveOperand();\r
1267   FlatPoly(a,b,c,d,e,f,g);\r
1268 }\r
1269 \r
1270 void vc_TMapPoly()\r
1271 {\r
1272   int a,b,c,d,e,f,g,h,i,j,k,l,m,n,o;\r
1273 \r
1274   a=ResolveOperand();\r
1275   b=ResolveOperand();\r
1276   c=ResolveOperand();\r
1277   d=ResolveOperand();\r
1278   e=ResolveOperand();\r
1279   f=ResolveOperand();\r
1280   g=ResolveOperand();\r
1281   h=ResolveOperand();\r
1282   i=ResolveOperand();\r
1283   j=ResolveOperand();\r
1284   k=ResolveOperand();\r
1285   l=ResolveOperand();\r
1286   m=ResolveOperand();\r
1287   n=ResolveOperand();\r
1288   o=ResolveOperand();\r
1289   TMapPoly(a,b,c,d,e,f,g,h,i,j,k,l,m,n,(char *) o);\r
1290 }\r
1291 \r
1292 void vc_CacheSound()\r
1293 {\r
1294   char fname[256];\r
1295 \r
1296   ResolveString(fname);\r
1297   vcreturn=CacheSound(fname);\r
1298 \r
1299 }\r
1300 \r
1301 void vc_PlaySound()\r
1302 {\r
1303   int a, b, c;\r
1304 \r
1305   a=ResolveOperand();\r
1306   b=ResolveOperand();\r
1307   c=ResolveOperand();\r
1308   PlaySound(a, b, c);\r
1309 }\r
1310 \r
1311 void vc_RotScale()\r
1312 {\r
1313   int a, b, c, d, e, f, g;\r
1314 \r
1315   a=ResolveOperand();\r
1316   b=ResolveOperand();\r
1317   c=ResolveOperand();\r
1318   d=ResolveOperand();\r
1319   e=ResolveOperand();\r
1320   f=ResolveOperand();\r
1321   g=ResolveOperand();\r
1322 \r
1323   RotScale(a, b, c, d, e*3.14159 / 180, (float) f/1000, (byte *) g);\r
1324 }\r
1325 \r
1326 void vc_MapLine()\r
1327 {\r
1328   int x, y, sy, l;\r
1329   int xtc, ytc, xofs, yofs;\r
1330 \r
1331   x=ResolveOperand();\r
1332   y=ResolveOperand();\r
1333   sy=ResolveOperand();\r
1334   l=ResolveOperand();\r
1335 \r
1336   xtc=x >> 4;\r
1337   ytc=y >> 4;\r
1338   xofs= -(x&15);\r
1339   yofs=  (y&15);\r
1340 \r
1341   MapLine(xofs, sy, yofs, (word *) (layers[l]+((ytc*layer[l].sizex)+xtc)));\r
1342 }\r
1343 \r
1344 void vc_TMapLine()\r
1345 {\r
1346   int x, y, sy, l;\r
1347   int xtc, ytc, xofs, yofs;\r
1348 \r
1349   x=ResolveOperand();\r
1350   y=ResolveOperand();\r
1351   sy=ResolveOperand();\r
1352   l=ResolveOperand();\r
1353 \r
1354   xtc=x >> 4;\r
1355   ytc=y >> 4;\r
1356   xofs= -(x&15);\r
1357   yofs=  (y&15);\r
1358 \r
1359   TMapLine(xofs, sy, yofs, (word *) (layers[l]+((ytc*layer[l].sizex)+xtc)));\r
1360 }\r
1361 \r
1362 void vc_val()\r
1363 {\r
1364   char s[256];\r
1365 \r
1366   ResolveString(s);\r
1367   vcreturn=atoi(s);\r
1368 }\r
1369 \r
1370 void vc_TScaleSprite()\r
1371 {\r
1372   int x,y,iw,ih,dw,dh,image;\r
1373 \r
1374   x=ResolveOperand();\r
1375   y=ResolveOperand();\r
1376   iw=ResolveOperand();\r
1377   ih=ResolveOperand();\r
1378   dw=ResolveOperand();\r
1379   dh=ResolveOperand();\r
1380   image=ResolveOperand();\r
1381   if (!LucentOn) TCopySpriteZoomClip(x,y,iw,ih,dw,dh,(byte *) image);\r
1382   if ( LucentOn) TCopySpriteZoomLucentClip(x,y,iw,ih,dw,dh,(byte *) image);\r
1383 }\r
1384 \r
1385 void vc_GrabRegion()\r
1386 {\r
1387   int x1, y1, x2, y2;\r
1388   int i, j, w, h;\r
1389   char *ptr;\r
1390 \r
1391   x1=ResolveOperand();\r
1392   y1=ResolveOperand();\r
1393   x2=ResolveOperand()+1;\r
1394   y2=ResolveOperand()+1;\r
1395   ptr=(char *) ResolveOperand();\r
1396 \r
1397   if (x2>sx-1) x2=sx-1;\r
1398   if (y2>sy-1) y2=sy-1;\r
1399   if (x1<0) x1=0;\r
1400   if (y1<0) y1=0;\r
1401 \r
1402   w=x2 - x1;\r
1403   h=y2 - y1;\r
1404 \r
1405   for (j=y1; j<y2; j++)\r
1406     for (i=x1; i<x2; i++)\r
1407       ptr[((j-y1)*w)+i]=screen[(j*sx)+i];\r
1408 }\r
1409 \r
1410 void vc_Log()\r
1411 {\r
1412   char s[256];\r
1413 \r
1414   ResolveString(s);\r
1415   Log(s);\r
1416 }\r
1417 \r
1418 void vc_fseekline()\r
1419 {\r
1420   int line, i;\r
1421   VFILE *f;\r
1422 \r
1423   line=ResolveOperand();\r
1424   f=(VFILE *) ResolveOperand();\r
1425 \r
1426   vseek(f, 0, 0);\r
1427   line=( line==0 ? 0 : line-1 );\r
1428 \r
1429   for (i=0; i<line; i++)\r
1430     vgets(strbuf, 255, f);\r
1431 }\r
1432 \r
1433 void vc_fseekpos()\r
1434 {\r
1435   int pos;\r
1436   VFILE *f;\r
1437 \r
1438   pos=ResolveOperand();\r
1439   f=(VFILE *) ResolveOperand();\r
1440   vseek(f, pos, 0);\r
1441 }\r
1442 \r
1443 void vc_fread()\r
1444 {\r
1445   char *buffer;\r
1446   int len;\r
1447   VFILE *f;\r
1448 \r
1449   buffer=(char *) ResolveOperand();\r
1450   len=ResolveOperand();\r
1451   f=(VFILE *) ResolveOperand();\r
1452   vread(buffer, len, f);\r
1453 }\r
1454 \r
1455 void vc_fgetbyte()\r
1456 {\r
1457   VFILE *f;\r
1458   byte i;\r
1459 \r
1460   f=(VFILE *) ResolveOperand();\r
1461   vread(&i, 1, f);\r
1462   vcreturn=(int) i;\r
1463 }\r
1464 \r
1465 void vc_fgetword()\r
1466 {\r
1467   VFILE *f;\r
1468   word i;\r
1469 \r
1470   f=(VFILE *) ResolveOperand();\r
1471   vread(&i, 2, f);\r
1472   vcreturn=(int) i;\r
1473 }\r
1474 \r
1475 void vc_fgetquad()\r
1476 {\r
1477   VFILE *f;\r
1478   quad i;\r
1479 \r
1480   f=(VFILE *) ResolveOperand();\r
1481   vread(&i, 4, f);\r
1482   vcreturn=(int) i;\r
1483 }\r
1484 \r
1485 void vc_fgetline()\r
1486 {\r
1487   char c, *p;\r
1488   VFILE *f;\r
1489   word w=0;\r
1490   quad d;\r
1491 \r
1492   c=GrabC();\r
1493   if (c==op_STRING)\r
1494   {\r
1495     w=GrabW();\r
1496     d=0;\r
1497   }\r
1498   if (c==op_SARRAY)\r
1499   {\r
1500     w=GrabW();\r
1501     d=ResolveOperand();\r
1502   }\r
1503   f=(VFILE *) ResolveOperand();\r
1504   p=(char *) (quad) stringbuf + (w*256);\r
1505   vgets(p, 255, f);\r
1506   while (*p)\r
1507   {\r
1508     if (*p == 10 || *p == 13) *p=0;\r
1509     p++;\r
1510   }\r
1511 }\r
1512 \r
1513 void vc_fgettoken()\r
1514 {\r
1515   char c, *p;\r
1516   VFILE *f;\r
1517   word w=0;\r
1518   quad d;\r
1519 \r
1520   c=GrabC();\r
1521   if (c==op_STRING)\r
1522   {\r
1523     w=GrabW();\r
1524     d=0;\r
1525   }\r
1526   if (c==op_SARRAY)\r
1527   {\r
1528     w=GrabW();\r
1529     d=ResolveOperand();\r
1530   }\r
1531   f=(VFILE *) ResolveOperand();\r
1532   p=(char *) (quad) stringbuf + (w*256);\r
1533   vscanf(f, "%s", p);\r
1534 }\r
1535 \r
1536 void vc_fwritestring()\r
1537 {\r
1538   char s[256];\r
1539   FILE *f;\r
1540 \r
1541   ResolveString(s);\r
1542   f=(FILE *) ResolveOperand();\r
1543   fprintf(f,"%s\n",s);\r
1544 }\r
1545 \r
1546 void vc_fwrite()\r
1547 {\r
1548   int a, b, c;\r
1549 \r
1550   a=ResolveOperand();\r
1551   b=ResolveOperand();\r
1552   c=ResolveOperand();\r
1553   fwrite((char *) a, 1, b, (FILE *) c);\r
1554 }\r
1555 \r
1556 void vc_frename()\r
1557 {\r
1558   char s1[256], s2[256];\r
1559 \r
1560   ResolveString(s1);\r
1561   ResolveString(s2);\r
1562   EnforceNoDirectories(s1);\r
1563   EnforceNoDirectories(s2);\r
1564   rename(s1, s2);\r
1565 \r
1566   Log(" --> VC renamed %s to %s.", s1, s2);\r
1567 }\r
1568 \r
1569 void vc_fdelete()\r
1570 {\r
1571   char s[256];\r
1572 \r
1573   ResolveString(s);\r
1574   EnforceNoDirectories(s);\r
1575   remove(s);\r
1576 \r
1577   Log(" --> VC deleted %s.", s);\r
1578 }\r
1579 \r
1580 void vc_fwopen()\r
1581 {\r
1582   char s[256];\r
1583 \r
1584   ResolveString(s);\r
1585   EnforceNoDirectories(s);\r
1586   vcreturn=(int) fopen(s,"wb");\r
1587 \r
1588   Log(" --> VC opened %s for writing, ptr %u.", s, vcreturn);\r
1589 }\r
1590 \r
1591 void vc_fwclose()\r
1592 {\r
1593   FILE *f;\r
1594 \r
1595   f=(FILE *) ResolveOperand();\r
1596   fclose(f);\r
1597 \r
1598   Log(" --> VC close file opened for writing, ptr %u.", (int) f);\r
1599 }\r
1600 \r
1601 void vc_memcpy()\r
1602 {\r
1603   int a, b, c;\r
1604 \r
1605   a=ResolveOperand();\r
1606   b=ResolveOperand();\r
1607   c=ResolveOperand();\r
1608   memcpy((char *) a, (char *) b, c);\r
1609 }\r
1610 \r
1611 void vc_memset()\r
1612 {\r
1613   int a, b, c;\r
1614 \r
1615   a=ResolveOperand();\r
1616   b=ResolveOperand();\r
1617   c=ResolveOperand();\r
1618   memset((char *) a, (byte) b, c);\r
1619 }\r
1620 \r
1621 void vc_Silhouette()\r
1622 {\r
1623   int x=ResolveOperand();\r
1624   int y=ResolveOperand();\r
1625   int w=ResolveOperand();\r
1626   int h=ResolveOperand();\r
1627   byte *img=(byte *) ResolveOperand();\r
1628   byte c=(byte) ResolveOperand();\r
1629 \r
1630   if (ClipOn)\r
1631   {\r
1632     LucentOn ? SilhouetteLucentClip(x,y,w,h,c,img)\r
1633              : SilhouetteClip(x,y,w,h,c,img);\r
1634   }\r
1635   else\r
1636   {\r
1637     LucentOn ? SilhouetteLucent(x,y,w,h,c,img)\r
1638              : Silhouette(x,y,w,h,c,img);\r
1639   }\r
1640 }\r
1641 \r
1642 void vc_SilhouetteScale()\r
1643 {\r
1644   int x=ResolveOperand();\r
1645   int y=ResolveOperand();\r
1646   int sw=ResolveOperand();\r
1647   int sh=ResolveOperand();\r
1648   int dw=ResolveOperand();\r
1649   int dh=ResolveOperand();\r
1650   byte *img=(byte *) ResolveOperand();\r
1651   byte c=(byte) ResolveOperand();\r
1652 \r
1653   if (ClipOn)\r
1654   {\r
1655     LucentOn ? SilhouetteZoomLucentClip(x,y,sw,sh,dw,dh,c,img)\r
1656              : SilhouetteZoomClip(x,y,sw,sh,dw,dh,c,img);\r
1657   }\r
1658   else\r
1659   {\r
1660     LucentOn ? SilhouetteZoomLucent(x,y,sw,sh,dw,dh,c,img)\r
1661              : SilhouetteZoom(x,y,sw,sh,dw,dh,c,img);\r
1662   }\r
1663 }\r
1664 \r
1665 void vc_Tint()\r
1666 {\r
1667   int x=ResolveOperand();\r
1668   int y=ResolveOperand();\r
1669   int w=ResolveOperand();\r
1670   int h=ResolveOperand();\r
1671   byte *img=(byte *)ResolveOperand();\r
1672   byte c=(byte)ResolveOperand();\r
1673 \r
1674   ClipOn ? TintClip(x,y,w,h,c,img)\r
1675          : Tint(x,y,w,h,c,img);\r
1676 }\r
1677 \r
1678 void vc_TintScale()\r
1679 {\r
1680   int x=ResolveOperand();\r
1681   int y=ResolveOperand();\r
1682   int sw=ResolveOperand();\r
1683   int sh=ResolveOperand();\r
1684   int dw=ResolveOperand();\r
1685   int dh=ResolveOperand();\r
1686   byte *img=(byte *) ResolveOperand();\r
1687   byte c=(byte) ResolveOperand();\r
1688 \r
1689   ClipOn ? TintZoomClip(x,y,sw,sh,dw,dh,c,img)\r
1690          : TintZoom(x,y,sw,sh,dw,dh,c,img);\r
1691 }\r
1692 \r
1693 void vc_Mosaic()\r
1694 {\r
1695   int a,b,c,d,e,f,g;\r
1696 \r
1697   a=ResolveOperand();\r
1698   b=ResolveOperand();\r
1699   c=ResolveOperand();\r
1700   d=ResolveOperand();\r
1701   e=ResolveOperand();\r
1702   f=ResolveOperand();\r
1703   g=ResolveOperand();\r
1704   Mosaic(a,b,(byte *) c,d,e,f,g);\r
1705 }\r
1706 \r
1707 void vc_WriteVars()\r
1708 {\r
1709   FILE *f;\r
1710 \r
1711   f=(FILE *) ResolveOperand();\r
1712   fwrite(globalint, 4, maxint, f);\r
1713   fwrite(stringbuf, 256, stralloc, f);\r
1714 }\r
1715 \r
1716 void vc_ReadVars()\r
1717 {\r
1718   VFILE *f;\r
1719 \r
1720   f=(VFILE *) ResolveOperand();\r
1721   vread(globalint, 4*maxint, f);\r
1722   vread(stringbuf, 256*stralloc, f);\r
1723 }\r
1724 \r
1725 void vc_Asc()\r
1726 {\r
1727   char s[256];\r
1728 \r
1729   ResolveString(s);\r
1730   vcreturn=(int) s[0];\r
1731 }\r
1732 \r
1733 void vc_NumForScript()\r
1734 {\r
1735   vcreturn=GrabD();\r
1736 }\r
1737 \r
1738 void vc_Filesize()\r
1739 {\r
1740   char s[256];\r
1741   VFILE *f;\r
1742 \r
1743   ResolveString(s);\r
1744   f=vopen(s);\r
1745   vcreturn=filesize(f);\r
1746   vclose(f);\r
1747 }\r
1748 \r
1749 void vc_FTell()\r
1750 {\r
1751   VFILE *f=(VFILE *)ResolveOperand();\r
1752   vcreturn=vtell(f);\r
1753 }\r
1754 \r
1755 void vc_CheckCorrupt()\r
1756 {\r
1757   Log("checking for corruption...");\r
1758   CheckCorruption();\r
1759 }\r
1760 \r
1761 void HandleStdLib()\r
1762 {\r
1763   int x=0;\r
1764   byte c=0;\r
1765 \r
1766   c=GrabC();\r
1767   switch (c)\r
1768   {\r
1769     case 1: vc_Exit_(); break;\r
1770     case 2: vc_Message(); break;\r
1771     case 3: vc_Malloc(); break;\r
1772     case 4: vc_Free(); break;\r
1773     case 5: vc_pow(); break;\r
1774     case 6: vc_loadimage(); break;\r
1775     case 7: vc_copysprite(); break;\r
1776     case 8: vc_tcopysprite(); break;\r
1777     case 9: Render(); break;\r
1778     case 10: ShowPage(); break;\r
1779     case 11: vc_EntitySpawn(); break;\r
1780     case 12: vc_SetPlayer(); break;\r
1781     case 13: vc_Map(); break;\r
1782     case 14: vc_LoadFont(); break;\r
1783     case 15: vc_PlayFLI(); break;\r
1784     case 16: curx=ResolveOperand(); cury=ResolveOperand(); break;\r
1785     case 17: vc_PrintString(); break;\r
1786     case 18: vc_LoadRaw(); break;\r
1787     case 19: vc_SetTile(); break;\r
1788     case 20: allowconsole=ResolveOperand(); break;\r
1789     case 21: vc_ScaleSprite(); break;\r
1790     case 22: ProcessEntities(); break;\r
1791     case 23: UpdateControls(); break;\r
1792     case 24: UnPress(ResolveOperand()); break;\r
1793     case 25: vc_EntityMove(); break;\r
1794     case 26: vc_HLine(); break;\r
1795     case 27: vc_VLine(); break;\r
1796     case 28: vc_Line(); break;\r
1797     case 29: vc_Circle(); break;\r
1798     case 30: vc_CircleFill(); break;\r
1799     case 31: vc_Rect(); break;\r
1800     case 32: vc_RectFill(); break;\r
1801     case 33: vc_strlen(); break;\r
1802     case 34: vc_strcmp(); break;\r
1803     case 35: break; //CD_Stop(); break;\r
1804     case 36: ResolveOperand(); break; //CD_Play(ResolveOperand()); break;\r
1805     case 37: vc_FontWidth(); break;\r
1806     case 38: vc_FontHeight(); break;\r
1807     case 39: vc_SetPixel(); break;\r
1808     case 40: vc_GetPixel(); break;\r
1809     case 41: vc_EntityOnScreen(); break;\r
1810     case 42: vcreturn=0;\r
1811              if ((x=ResolveOperand()))\r
1812                vcreturn=rand()%x;\r
1813              break;\r
1814     case 43: vc_GetTile(); break;\r
1815     case 44: vc_HookRetrace(); break;\r
1816     case 45: vc_HookTimer(); break;\r
1817     case 46: vc_SetResolution(); break;\r
1818     case 47: vc_SetRString(); break;\r
1819     case 48: vc_SetClipRect(); break;\r
1820     case 49: vc_SetRenderDest(); break;\r
1821     case 50: vc_RestoreRenderSettings(); break;\r
1822     case 51: vc_PartyMove(); break;\r
1823     case 52: vcreturn=sintbl[ResolveOperand()]; break;\r
1824     case 53: vcreturn=costbl[ResolveOperand()]; break;\r
1825     case 54: vcreturn=tantbl[ResolveOperand()]; break;\r
1826     case 55: ReadMouse(); break;\r
1827     case 56: ClipOn=ResolveOperand(); break;\r
1828     case 57: LucentOn=ResolveOperand(); break;\r
1829     case 58: vc_WrapBlit(); break;\r
1830     case 59: vc_TWrapBlit(); break;\r
1831     case 60: vc_SetMousePos(); break;\r
1832     case 61: vc_HookKey(); break;\r
1833     case 62: vc_PlayMusic(); break;\r
1834     case 63: StopMusic(); break;\r
1835     case 64: vc_PaletteMorph(); break;\r
1836     case 65: vc_OpenFile(); break;\r
1837     case 66: vc_CloseFile(); break;\r
1838     case 67: vc_QuickRead(); break;\r
1839     case 68: vc_AddFollower(); break;\r
1840 //    case 69: vc_KillFollower(); break;\r
1841 //    case 70: vc_KillAllFollowers(); break;\r
1842 //    case 71: ResetFollowers();\r
1843     case 72: vc_FlatPoly(); break;\r
1844     case 73: vc_TMapPoly(); break;\r
1845     case 74: vc_CacheSound(); break;\r
1846     case 75: FreeAllSounds(); break;\r
1847     case 76: vc_PlaySound(); break;\r
1848     case 77: vc_RotScale(); break;\r
1849     case 78: vc_MapLine(); break;\r
1850     case 79: vc_TMapLine(); break;\r
1851     case 80: vc_val(); break;\r
1852     case 81: vc_TScaleSprite(); break;\r
1853     case 82: vc_GrabRegion(); break;\r
1854     case 83: vc_Log(); break;\r
1855     case 84: vc_fseekline(); break;\r
1856     case 85: vc_fseekpos(); break;\r
1857     case 86: vc_fread(); break;\r
1858     case 87: vc_fgetbyte(); break;\r
1859     case 88: vc_fgetword(); break;\r
1860     case 89: vc_fgetquad(); break;\r
1861     case 90: vc_fgetline(); break;\r
1862     case 91: vc_fgettoken(); break;\r
1863     case 92: vc_fwritestring(); break;\r
1864     case 93: vc_fwrite(); break;\r
1865     case 94: vc_frename(); break;\r
1866     case 95: vc_fdelete(); break;\r
1867     case 96: vc_fwopen(); break;\r
1868     case 97: vc_fwclose(); break;\r
1869     case 98: vc_memcpy(); break;\r
1870     case 99: vc_memset(); break;\r
1871     case 100: vc_Silhouette(); break;\r
1872     case 101: vcreturn=(int) InitMosaicTable(); break;\r
1873     case 102: vc_Mosaic(); break;\r
1874     case 103: vc_WriteVars(); break;\r
1875     case 104: vc_ReadVars(); break;\r
1876     case 105: ExecuteEvent(ResolveOperand()); break;\r
1877     case 106: vc_Asc(); break;\r
1878     case 107: ExecuteUserFunc(ResolveOperand()); break;\r
1879     case 108: vc_NumForScript(); break;\r
1880     case 109: vc_Filesize(); break;\r
1881     case 110: vc_FTell(); break;\r
1882     case 111: vc_CheckCorrupt(); break;\r
1883     default: err("VC Execution error: Invalid STDLIB index. (%d)",(int) c);\r
1884   }\r
1885 }\r
1886 \r
1887 // ========================== VC Interpretation Core ==========================\r
1888 \r
1889 int ProcessIf()\r
1890 {\r
1891   byte exec, c;\r
1892 \r
1893   exec=ProcessIfOperand();               // Get base value;\r
1894 \r
1895   while (1)\r
1896   {\r
1897     c=GrabC();\r
1898     switch (c)\r
1899     {\r
1900       case i_AND: exec=exec & ProcessIfOperand(); continue;\r
1901       case i_OR: exec=exec | ProcessIfOperand(); continue;\r
1902       case i_UNGROUP: break;\r
1903     }\r
1904     break;\r
1905   }\r
1906   return exec;\r
1907 }\r
1908 \r
1909 int ProcessIfOperand()\r
1910 {\r
1911   byte op_desc;\r
1912   int eval;\r
1913 \r
1914   eval=ResolveOperand();\r
1915   op_desc=GrabC();\r
1916   switch (op_desc)\r
1917   {\r
1918      case i_ZERO: if (!eval) return 1; else return 0;\r
1919      case i_NONZERO: if (eval) return 1; else return 0;\r
1920      case i_EQUALTO: if (eval == ResolveOperand()) return 1; else return 0;\r
1921      case i_NOTEQUAL: if (eval != ResolveOperand()) return 1; else return 0;\r
1922      case i_GREATERTHAN: if (eval > ResolveOperand()) return 1; else return 0;\r
1923      case i_GREATERTHANOREQUAL: if (eval >= ResolveOperand()) return 1; else return 0;\r
1924      case i_LESSTHAN: if (eval < ResolveOperand()) return 1; else return 0;\r
1925      case i_LESSTHANOREQUAL: if (eval <= ResolveOperand()) return 1; else return 0;\r
1926      case i_GROUP: if (ProcessIf()) return 1; else return 0;\r
1927   }\r
1928   return 0;\r
1929 }\r
1930 \r
1931 void HandleIf()\r
1932 {\r
1933   char *d;\r
1934 \r
1935   if (ProcessIf())\r
1936   {\r
1937     GrabD();\r
1938     return;\r
1939   }\r
1940   d=(char *) GrabD();\r
1941   code=(char *) (int) basevc + (int) d;\r
1942 \r
1943   return;\r
1944 }\r
1945 \r
1946 void HandleExternFunc()\r
1947 {\r
1948   word i, j, k;\r
1949   //lvars *ob   = NULL;\r
1950   //lvars *save = NULL;\r
1951   lvars temp;\r
1952   lvars ob;\r
1953 \r
1954   // save lvar\r
1955   memcpy(&temp, &lvar, sizeof(lvars));\r
1956 \r
1957   memset(&ob, 0, sizeof(lvars));\r
1958   //ob = (lvars *)valloc(sizeof(lvars)); //2640); //sizeof(lvars)); //2640);\r
1959   //MSS_CHECK_POINTER_VALIDITY(ob);\r
1960   //MSS_SET_BLOCK_LABEL(ob, "ob");\r
1961 \r
1962   k = 0;\r
1963   i = GrabW();\r
1964   for (j=0; j<funcs[i].numargs; j++)\r
1965   {\r
1966     switch (funcs[i].argtype[j])\r
1967     {\r
1968       case 1: ob.nargs[j] = ResolveOperand(); break;\r
1969       case 3: ResolveString(ob.s + (k << 8)), k++; break;\r
1970     }\r
1971   }\r
1972 \r
1973   // copy in ob\r
1974   memcpy(&lvar, &ob, sizeof(lvars));\r
1975   //lvar = &ob;\r
1976   //save = lvar\r
1977   //lvar = ob;\r
1978   //ob   = save;\r
1979 \r
1980   vcpush((quad)basevc);\r
1981   vcpush((quad)code);\r
1982 \r
1983   basevc = sysvc;\r
1984   code = (char *)(sysvc + funcs[i].syscodeofs);\r
1985 \r
1986   if (vctrack)\r
1987   {\r
1988     Log(" --> Entering user func %s, codeofs %d",\r
1989       funcs[i].fname, funcs[i].syscodeofs);\r
1990   }\r
1991 \r
1992   ExecuteBlock();\r
1993   basevc = (char *)vcpop();\r
1994 \r
1995   // restore lvar\r
1996   memcpy(&lvar, &temp, sizeof(lvars));\r
1997   //memcpy(lvar, &temp, sizeof(lvars));\r
1998   //vfree(lvar);\r
1999   //lvar = ob;\r
2000 \r
2001   if (vctrack)\r
2002   {\r
2003     Log(" --> Returned from %s", funcs[i].fname);\r
2004   }\r
2005 \r
2006 //  MSS_CHECK_ALL_BLOCKS;\r
2007 }\r
2008 \r
2009 void HandleAssign()\r
2010 {\r
2011   byte c, d;\r
2012   word w;\r
2013   quad location=0, value, ofs=0;\r
2014 \r
2015   c=GrabC();\r
2016   if (c==op_STRING)\r
2017   {\r
2018     w=GrabW();\r
2019     c=GrabC();\r
2020     if (c!=a_SET) err("VC execution error: Corrupt string assignment");\r
2021     location=(quad) stringbuf + (w*256);\r
2022     ResolveString((char *) location);\r
2023     return;\r
2024   }\r
2025   if (c==op_SARRAY)\r
2026   {\r
2027     w=GrabW();\r
2028     w+=ResolveOperand();\r
2029     c=GrabC();\r
2030     if (c!=a_SET) err("VC execution error: Corrupt string assignment");\r
2031     location=(quad) stringbuf + (w*256);\r
2032     ResolveString((char *) location);\r
2033     return;\r
2034   }\r
2035   if (c==op_SLOCAL)\r
2036   {\r
2037     w=GrabW();\r
2038     c=GrabC();\r
2039     if (c!=a_SET) err("VC execution error: Corrupt string assignment");\r
2040     location=(quad) &lvar.s[w*256];\r
2041     ResolveString((char *) location);\r
2042     return;\r
2043   }\r
2044   switch (c)\r
2045   {\r
2046     case op_UVAR:    location=GrabD(); break;\r
2047     case op_UVARRAY: location=GrabD(); location+=ResolveOperand(); break;\r
2048     case op_HVAR0:   location=(int) GrabC(); break;\r
2049     case op_HVAR1:   location=(int) GrabC(); ofs=ResolveOperand(); break;\r
2050     case op_LVAR:    location=(int) GrabC(); break;\r
2051     default: err("VC Execution error: Unknown assignment category.");\r
2052   }\r
2053   value=ReadInt(c, location, ofs);\r
2054   d=GrabC();\r
2055   switch(d)\r
2056   {\r
2057     case a_SET: value=ResolveOperand(); break;\r
2058     case a_INC: value++; break;\r
2059     case a_DEC: value--; break;\r
2060     case a_INCSET: value+=ResolveOperand(); break;\r
2061     case a_DECSET: value-=ResolveOperand(); break;\r
2062     default:\r
2063       err("VC Execution error: Invalid assignment operator %d.", (int) d);\r
2064   }\r
2065   WriteInt(c, location, ofs, value);\r
2066 }\r
2067 \r
2068 void HandleSwitch()\r
2069 {\r
2070   int realvalue=0;\r
2071   int compvalue=0;\r
2072   byte c=0;\r
2073   byte *next=0;\r
2074 \r
2075   realvalue=ResolveOperand();\r
2076   c=GrabC();\r
2077   while (c!=opRETURN)\r
2078   {\r
2079     compvalue=ResolveOperand();\r
2080     next=(byte *) GrabD();\r
2081     if (compvalue!=realvalue)\r
2082     {\r
2083       code=(char *) (int) basevc+(int) next;\r
2084       c=GrabC();\r
2085       continue;\r
2086     }\r
2087     ExecuteSection();\r
2088     c=GrabC();\r
2089   }\r
2090 }\r
2091 \r
2092 void ExecuteVC()\r
2093 {\r
2094   byte c=0;\r
2095 \r
2096   while (1)\r
2097   {\r
2098     if (kill) break;\r
2099     c=GrabC();\r
2100     switch (c)\r
2101     {\r
2102       case opEXEC_STDLIB: HandleStdLib(); break;\r
2103       case opEXEC_LOCALFUNC: break;\r
2104       case opEXEC_EXTERNFUNC: HandleExternFunc(); break;\r
2105       case opIF: HandleIf(); break;\r
2106       case opELSE: break;\r
2107       case opGOTO: code=basevc+GrabD(); break;\r
2108       case opSWITCH: HandleSwitch(); break;\r
2109       case opASSIGN: HandleAssign(); break;\r
2110       case opRETURN: code=(char *) vcpop(); break;\r
2111       case opSETRETVAL: vcreturn=ResolveOperand(); break;\r
2112       default:\r
2113         err("Internal VC execution error. (%d)",(int) code - (int) basevc);\r
2114     }\r
2115     if ((int) code != -1) continue; else break;\r
2116   }\r
2117 }\r
2118 \r
2119 void ExecuteBlock()\r
2120 {\r
2121   byte c=0;\r
2122 \r
2123   while (1)\r
2124   {\r
2125     if (kill) break;\r
2126     c=GrabC();\r
2127     switch (c)\r
2128     {\r
2129       case opEXEC_STDLIB: HandleStdLib(); break;\r
2130       case opEXEC_LOCALFUNC: break;\r
2131       case opEXEC_EXTERNFUNC: HandleExternFunc(); break;\r
2132       case opIF: HandleIf(); break;\r
2133       case opELSE: break;\r
2134       case opGOTO: code=basevc+GrabD(); break;\r
2135       case opSWITCH: HandleSwitch(); break;\r
2136       case opASSIGN: HandleAssign(); break;\r
2137       case opRETURN: code=(char *) vcpop(); break;\r
2138       case opSETRETVAL: vcreturn=ResolveOperand(); break;\r
2139       default:\r
2140         err("Internal VC execution error. (%d)",(int) code - (int) basevc);\r
2141     }\r
2142     if (c != opRETURN) continue; else break;\r
2143   }\r
2144 }\r
2145 \r
2146 void ExecuteSection()\r
2147 {\r
2148   byte c=0;\r
2149 \r
2150   while (1)\r
2151   {\r
2152     if (kill) break;\r
2153     c=GrabC();\r
2154     switch (c)\r
2155     {\r
2156       case opEXEC_STDLIB: HandleStdLib(); break;\r
2157       case opEXEC_LOCALFUNC: break;\r
2158       case opEXEC_EXTERNFUNC: HandleExternFunc(); break;\r
2159       case opIF: HandleIf(); break;\r
2160       case opELSE: break;\r
2161       case opGOTO: code=basevc+GrabD(); break;\r
2162       case opSWITCH: HandleSwitch(); break;\r
2163       case opASSIGN: HandleAssign(); break;\r
2164       case opRETURN: break;\r
2165       case opSETRETVAL: vcreturn=ResolveOperand(); break;\r
2166       default:\r
2167         err("Internal VC execution error. (%d)", (int) code - (int) basevc);\r
2168     }\r
2169     if (c != opRETURN) continue; else break;\r
2170   }\r
2171 }\r
2172 \r
2173 void ExecuteEvent(int i)\r
2174 {\r
2175   invc++;\r
2176   vcpush((quad) code);\r
2177   vcpush((quad) basevc);\r
2178   if (i>mapevents) err("VC event out of bounds (%d)",i);\r
2179   basevc=mapvc;\r
2180   code=(char *) (int) mapvc + (int) mapvctbl[i];\r
2181   vcpush(-1);\r
2182   ExecuteVC();\r
2183   basevc=(char *) vcpop();\r
2184   code=(char *) vcpop();\r
2185   invc--;\r
2186 }\r
2187 \r
2188 void ExecuteUserFunc(int i)\r
2189 {\r
2190   //lvars *ob=0;\r
2191   lvars temp;\r
2192 \r
2193   // save lvar\r
2194   memcpy(&temp, &lvar, sizeof(lvars));\r
2195 \r
2196   vcpush((quad) code);\r
2197   vcpush((quad) basevc);\r
2198 \r
2199   if (i > numfuncs)\r
2200     err("VC event out of bounds");\r
2201 \r
2202   basevc = sysvc;\r
2203   code = (char *)(sysvc + funcs[i].syscodeofs);\r
2204 \r
2205   vcpush(-1);\r
2206 \r
2207   memset(&lvar, 0, sizeof(lvar));\r
2208   //ob = lvar;\r
2209   //lvar = (lvars *)valloc(sizeof(lvars)); //2640);\r
2210   //MSS_SET_BLOCK_LABEL(lvar, "lvar");\r
2211 \r
2212   ExecuteVC();\r
2213   basevc = (char *) vcpop();\r
2214   code = (char *) vcpop();\r
2215 \r
2216   //free(lvar);\r
2217   //lvar = ob;\r
2218 \r
2219   // restore lvar\r
2220   memcpy(&lvar, &temp, sizeof(lvars));\r
2221 }\r
2222 \r
2223 void HookRetrace()\r
2224 {\r
2225   if (!hookretrace) return;\r
2226   if (hookretrace<USERFUNC_MARKER) ExecuteEvent(hookretrace);\r
2227   if (hookretrace>=USERFUNC_MARKER) ExecuteUserFunc(hookretrace-USERFUNC_MARKER);\r
2228 }\r
2229 \r
2230 void HookTimer()\r
2231 {\r
2232   if (!hooktimer) return;\r
2233   if (hooktimer<USERFUNC_MARKER) ExecuteEvent(hooktimer);\r
2234   if (hooktimer>=USERFUNC_MARKER) ExecuteUserFunc(hooktimer-USERFUNC_MARKER);\r
2235 }\r
2236 \r
2237 void HookKey(int script)\r
2238 {\r
2239   if (!script) return;\r
2240   if (script<USERFUNC_MARKER) ExecuteEvent(script);\r
2241   if (script>=USERFUNC_MARKER) ExecuteUserFunc(script-USERFUNC_MARKER);\r
2242 }\r