/* Copyright (C) 1998 BJ Eirich (aka vecna) This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public Lic See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ // -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- #define VC_H #include #include "verge.h" #include "vccode.h" #include "sincos.h" #include "mikmod.h" #define USERFUNC_MARKER 10000 // ================================= Data ==================================== char *sysvc, *mapvc, *basevc; // VC pool ptrs char *code; // VC current instruction pointer (IP) int *globalint; // system.vc global int variables int maxint; // maximum allocated # of ints char *stringbuf; // vc string workspace int vcreturn; // return value of last function char *movescriptbuf; // VC EntityMove buffer char vctrack=0; // VC call tracking to verge.log quad *vcstack; // VC stack (seperate from main stack) quad *vcsp; // VC stack pointer [esp] int mapevents; // number of map events in this VC char *mapvctbl[1024]; // map VC offset table int hookretrace=0; int hooktimer=0; int invc=0; // ----------------- typedef struct { char fname[40]; char argtype[20]; int numargs, numlocals; int returntype; int syscodeofs; } funcdecl; funcdecl *funcs; int numfuncs; typedef struct { char vname[40]; int vsofs; int arraylen; } strdecl; strdecl *str; int numstr=0; int stralloc; typedef struct { char vname[40]; int varstartofs; int arraylen; } vardecl; vardecl *vars; int numvars; char kill=0; // -- local func vars -- typedef struct { int nargs[20]; char s[2560]; } lvars; //lvars *lvar; lvars lvar; // ============================== Prototypes ================================= void ResolveString(char *buffer); void ExecuteSection(); void ExecuteEvent(int i); void ExecuteUserFunc(int i); // ================================= Code ==================================== int ProcessOperand(); // Mutually dependant functions suck. int ProcessIfOperand(); // Hell yeah they do, bitch. void HandleExternFunc(); void HandleStdLib(); void ExecuteBlock(); void LoadSystemVC() { VFILE *f=0; int i=0; Log("Initializing VC interpreter"); if (!(f=vopen("system.idx"))) err("Could not open system.idx."); vread(&numvars, 4, f); vars=(vardecl *) valloc(numvars*sizeof(vardecl), "LoadSystemVC:vars", OID_VC); vread(vars, numvars*48, f); vread(&numfuncs, 4, f); funcs=(funcdecl *) valloc(numfuncs*sizeof(funcdecl), "LoadSystemVC:funcs", OID_VC); vread(funcs, numfuncs*76, f); vread(&numstr, 4, f); str=(strdecl *) valloc(numstr*sizeof(strdecl), "LoadSystemVC:str", OID_VC); vread(str, numstr*44, f); vclose(f); if (!(f=vopen("system.vcs"))) err("Could not open system.vcs"); i=filesize(f); sysvc=(char *) valloc(i, "LoadSystemVC:sysvc", OID_VC); vread(&numfuncs, 4, f); vread(&maxint, 4, f); vread(&stralloc, 4, f); globalint=(int *) valloc(maxint ? maxint*4 : 4, "globalint", OID_VC); if (stralloc) { stringbuf=(char *) valloc((stralloc*256), "LoadSystemVC:stringbuf", OID_VC); } else { stringbuf=(char *) valloc(256, "LoadSystemVC:stringbuf (256)", OID_VC); } vread(sysvc, i, f); vclose(f); // Initialize VC stack vcstack=(quad *) valloc(6000, "vcstack", OID_VC); vcsp=vcstack; movescriptbuf=(char *) valloc(65535, "movescriptbuf", OID_VC); Log("system vclib init: %d funcs, %d ints (%d bytes), %d strings (%d bytes)", numfuncs, numvars, maxint*4, numstr, stralloc*256); } void LoadMapVC(VFILE *f) { int codesize=0; vread(&mapevents, 4, f); vread(mapvctbl, 4*mapevents, f); vread(&codesize, 4, f); mapvc=(char *) valloc(codesize, "mapvc", OID_VC); vread(mapvc, codesize, f); } byte GrabC() { return *code++; } word GrabW(void) { word *ptr=(word *) code; code+=2; return *ptr; } quad GrabD(void) { quad *ptr=(quad *) code; code+=4; return *ptr; } void GrabString(char *str) { int i=0; i=0; while (*code) { str[i]=*code; code++; i++; } str[i]=0; code++; } int ReadInt(char category, int loc, int ofs) { switch (category) { case op_UVAR: return globalint[loc]; case op_UVARRAY: return globalint[loc]; case op_HVAR0: switch (loc) { case 0: return xwin; case 1: return ywin; case 2: return cameratracking; case 3: return timer_count; case 4: return up; case 5: return down; case 6: return left; case 7: return right; case 8: return b1; case 9: return b2; case 10: return b3; case 11: return b4; case 12: return sx; case 13: return sy; case 14: return playernum; case 15: return cc; case 16: return tracker; case 17: return mx; case 18: return my; case 19: return mb; case 20: return vctrack; case 21: return width; case 22: return depth; case 23: return mp_volume; case 24: return (int)vsp; case 25: return lastent; case 26: return last_pressed; } case op_HVAR1: switch (loc) { case 0: return (int) screen[ofs]; case 1: return entity[ofs].x; case 2: return entity[ofs].y; case 3: return entity[ofs].tx; case 4: return entity[ofs].ty; case 5: return entity[ofs].facing; case 6: return entity[ofs].moving; case 7: return entity[ofs].specframe; case 8: return entity[ofs].speed; // case 9: return entity[ofs].movecode; case 10: return entidx[ofs]; case 11: return key[ofs]; case 12: return layer[ofs].hline; case 13: return (int) (*(byte *)ofs); case 14: return (int) (*(word *)ofs); case 15: return (int) (*(quad *)ofs); case 16: return (int) pal[ofs]; case 17: return (int) (*(char *)ofs); case 18: return (int) (*(short*)ofs); case 19: return (int) (*(int *)ofs); } case op_LVAR: return lvar.nargs[loc]; default: err("VC Execution error: Invalid ReadInt category %d", (int) category); } return 0; } void WriteInt(char category, int loc, int ofs, int value) { switch (category) { case op_UVAR: globalint[loc]=value; break; case op_UVARRAY: globalint[loc]=value; break; case op_HVAR0: switch (loc) { case 0: xwin=value; return; case 1: ywin=value; return; case 2: cameratracking=value; return; case 3: timer_count=value; return; case 16: tracker=value; return; case 20: vctrack=value; return; case 23: mp_volume=value; return; case 26: last_pressed=value; return; } case op_HVAR1: switch (loc) { case 0: screen[ofs]=(byte) value; return; case 1: entity[ofs].x=value; return; case 2: entity[ofs].y=value; return; case 3: entity[ofs].tx=value; return; case 4: entity[ofs].ty=value; return; case 5: entity[ofs].facing=value; return; case 6: entity[ofs].moving=value; return; case 7: entity[ofs].specframe=value; return; case 8: entity[ofs].speed=value; return; // case 9: entity[ofs].movecode=value; return; // case 10: case 11: key[ofs]=value; return; case 12: layer[ofs].hline=value; return; case 13: (*(byte *)ofs)=(byte) value; return; case 14: (*(word *)ofs)=(word) value; return; case 15: (*(quad *)ofs)=(quad) value; return; case 16: pal[ofs]=value; return; case 17: (*(char *)ofs)=(byte) value; return; case 18: (*(short*)ofs)=(word) value; return; case 19: (*(int *)ofs)=(quad) value; return; } case op_LVAR: lvar.nargs[loc]=value; return; default: err("VC Execution error: Invalid WriteInt category %d", (int) category); } } int ResolveOperand() { int cr=0; int d=0; byte c=0; cr=ProcessOperand(); // Get base number while (1) { c=GrabC(); switch (c) { case op_ADD: cr += ProcessOperand(); continue; case op_SUB: cr -= ProcessOperand(); continue; case op_DIV: d=ProcessOperand(); if (!d) cr=0; else cr /= d; continue; case op_MULT: cr = cr * ProcessOperand(); continue; case op_MOD: d=ProcessOperand(); if (!d) cr=0; else cr %= d; continue; case op_SHL: cr = cr << ProcessOperand(); continue; case op_SHR: cr = cr >> ProcessOperand(); continue; case op_AND: cr = cr & ProcessOperand(); continue; case op_OR: cr = cr | ProcessOperand(); continue; case op_XOR: cr = cr ^ ProcessOperand(); continue; case op_END: break; } break; } return cr; } int ProcessOperand() { byte op_desc=0; byte c=0; quad d=0; quad ofs=0; op_desc=GrabC(); switch (op_desc) { case op_IMMEDIATE: return GrabD(); case op_HVAR0: c=GrabC(); return ReadInt(op_HVAR0, c, 0); case op_HVAR1: c=GrabC(); ofs=ResolveOperand(); return ReadInt(op_HVAR1, c, ofs); case op_UVAR: d=GrabD(); return ReadInt(op_UVAR, d, 0); case op_UVARRAY: d=GrabD(); d+=ResolveOperand(); return ReadInt(op_UVARRAY, d, 0); case op_LVAR: c=GrabC(); return lvar.nargs[c]; case op_BFUNC: HandleStdLib(); return vcreturn; case op_UFUNC: HandleExternFunc(); return vcreturn; case op_GROUP: return ResolveOperand(); default: sprintf(strbuf,"VC Execution error: Invalid operand %d.",op_desc); err(strbuf); break; } return 0; } void HandleStringOperand(char *buffer) { char tbuf[256]; char *d=0; word w=0; int c=0; int i=0; int j=0; int z=0; c=GrabC(); switch (c) { case s_IMMEDIATE: GrabString(buffer); break; case s_GLOBAL: w=GrabW(); d=(char *) (int) stringbuf + (w*256); z=strlen(d); if (strlen(buffer)+z+1>250) err("Combined string length exceeds 250 char max."); memcpy(buffer, d, z+1); break; case s_ARRAY: w=GrabW(); w+=ResolveOperand(); d=(char *) (int) stringbuf + (w*256); z=strlen(d); if (strlen(buffer)+z+1>250) err("Combined string length exceeds 250 char max."); memcpy(buffer, d, z+1); break; case s_NUMSTR: i=ResolveOperand(); sprintf(buffer,"%d",i); break; case s_LEFT: ResolveString(tbuf); i=ResolveOperand(); c=i250) err("Combined string length exceeds 250 char max."); memcpy(buffer, tbuf, c); buffer[c]=0; break; case s_RIGHT: ResolveString(tbuf); i=ResolveOperand(); c=i250) err("Combined string length exceeds 250 char max."); memcpy(buffer, tbuf+strlen(tbuf)-c, c); buffer[c]=0; break; case s_MID: ResolveString(tbuf); i=ResolveOperand(); j=ResolveOperand(); i=i250) err("Combined string length exceeds 250 char max."); memcpy(buffer, tbuf+i, j); buffer[j]=0; break; case s_CHR: if (strlen(buffer)+2>50) err("Combined string length exceeds 250 char max."); buffer[0]=(char) ResolveOperand(); buffer[1]=0; break; case s_LOCAL: c=GrabC(); d=&lvar.s[c*256]; z=strlen(d); if (strlen(buffer)+z+1>250) err("Combined string length exceeds 250 char max."); memcpy(buffer, d, z+1); break; default: err("Invalid VC string operand %d", (int) c); } } void ResolveString(char *buffer) { char c=0; HandleStringOperand(buffer); while (1) { c=GrabC(); switch (c) { case s_ADD: HandleStringOperand((char *) (int) buffer + strlen(buffer)); break; case s_END: return; default: err("VC execution error: Unknown string operator %d",(int) c); } } } void vcpush(quad info) { if (vcsp>=vcstack+1500) err("VC stack overflow."); *vcsp=info; vcsp++; } quad vcpop() { if (vcsp==vcstack) err("VC stack underflow."); vcsp--; return *vcsp; } void ReadVCVar() { int i=0; int j=0; strlwr((char *) args[1]); for (i=0; i<=numvars; i++) if (!strcmp(vars[i].vname, (char *) args[1])) break; if (i1) j+=atoi((char *) args[2]); j=globalint[j]; sprintf(strbuf,"%s:%d",vars[i].vname, j); Con_Printf(strbuf); return; } for (i=0; i<=numstr; i++) if (!strcmp(str[i].vname, (char *) args[1])) break; if (i1) { j+=atoi((char *) args[2]); globalint[j]=atoi((char *) args[3]); } else globalint[j]=atoi((char *) args[2]); sprintf(strbuf,"%s:%d", vars[i].vname, atoi((char *) args[2])); Con_Printf(strbuf); return; } for (i=0; i<=numstr; i++) if (!strcmp(str[i].vname, (char *) args[1])) break; if (i=entities) err("SetPlayer(): Entity index out of range"); player=&entity[i]; playernum=i; // entity[i].movecode=0; entity[i].moving=0; } void vc_Map() { hookretrace=0; hooktimer=0; kill=1; ResolveString(startmap); } void vc_LoadFont() { char vcstr[80]; ResolveString(vcstr); vcreturn=LoadFont(vcstr); } void vc_PlayFLI() { char s[256]; BITMAP flibuf; byte *data=0; VFILE *f=0; int i=0; ResolveString(s); flibuf.w=sx; flibuf.h=sy; flibuf.data=screen; if (!(f=vopen(s))) err("PlayFLI: Could not open %s.",s); i=filesize(f); data=(byte *) malloc(i); if (!data) err("Not enough memory to play FLI."); vread(data, i, f); vclose(f); play_memory_fli(data, &flibuf, 0, ShowPage); timer_count=0; set_intensity(63); } void vc_PrintString() { char s[256]; int i=0; i=ResolveOperand(); ResolveString(s); printstring(i,s); } void vc_LoadRaw() { char s[256]; char *t=0; VFILE *f=0; int i=0; ResolveString(s); if (!(f=vopen(s))) err("LoadRaw(): Could not open file %s",s); i=filesize(f); t=(char *) valloc(i, "LoadRaw:t", OID_VC); vread(t, i, f); vclose(f); vcreturn=(int) t; } void vc_SetTile() { int x=0; int y=0; int layr=0; int value=0; x=ResolveOperand(); y=ResolveOperand(); layr=ResolveOperand(); value=ResolveOperand(); switch (layr) { case 0: case 1: case 2: case 3: case 4: case 5: layers[layr][(y*layer[layr].sizex)+x] = (short) value; break; case 6: obstruct[(y*layer[0].sizex)+x] = (byte) value; break; case 7: zone[(y*layer[0].sizex)+x] = (byte) value; break; default: err("SetTile(): Invalid layer value"); } } void vc_ScaleSprite() { int x,y,iw,ih,dw,dh,image; x=ResolveOperand(); y=ResolveOperand(); iw=ResolveOperand(); ih=ResolveOperand(); dw=ResolveOperand(); dh=ResolveOperand(); image=ResolveOperand(); if (!LucentOn) CopySpriteZoomClip(x,y,iw,ih,dw,dh,(byte *)image); if ( LucentOn) CopySpriteZoomLucentClip(x,y,iw,ih,dw,dh,(byte *)image); } void vc_EntityMove() { int i; i=ResolveOperand(); entity[i].moving=0; entity[i].speedct=0; entity[i].delayct=0; entity[i].mode=0; entity[i].data1=0; ResolveString((char *) (int) movescriptbuf + (int) (i*256)); entity[i].scriptofs=(char *) (int) movescriptbuf + (int) (i*256); entity[i].movecode=4; } void vc_HLine() { int x, y, x2, c; x=ResolveOperand(); y=ResolveOperand(); x2=ResolveOperand(); c=ResolveOperand(); if (!LucentOn) HLineClip(x,y,x2,c); if ( LucentOn) HLineLucentClip(x,y,x2,c); } void vc_VLine() { int x, y, y2, c; x=ResolveOperand(); y=ResolveOperand(); y2=ResolveOperand(); c=ResolveOperand(); if (!LucentOn) VLineClip(x,y,y2,c); if ( LucentOn) VLineLucentClip(x,y,y2,c); } void vc_Line() { int x, y, x2, y2, c; x=ResolveOperand(); y=ResolveOperand(); x2=ResolveOperand(); y2=ResolveOperand(); c=ResolveOperand(); if (!LucentOn) LineClip(x,y,x2,y2,c); if ( LucentOn) LineLucentClip(x,y,x2,y2,c); } void vc_Circle() { int x, y, radius, c; x=ResolveOperand(); y=ResolveOperand(); radius=ResolveOperand(); c=ResolveOperand(); if (!LucentOn) CircleClip(x,y,radius,c); if ( LucentOn) CircleLucentClip(x,y,radius,c); } void vc_CircleFill() { int x, y, radius, c; x=ResolveOperand(); y=ResolveOperand(); radius=ResolveOperand(); c=ResolveOperand(); if (!LucentOn) CircleFillClip(x,y,radius,c); if ( LucentOn) CircleFillLucentClip(x,y,radius,c); } void vc_Rect() { int x, y, x2, y2, c; x=ResolveOperand(); y=ResolveOperand(); x2=ResolveOperand(); y2=ResolveOperand(); c=ResolveOperand(); if (!LucentOn) RectClip(x,y,x2,y2,c); if ( LucentOn) RectLucentClip(x,y,x2,y2,c); } void vc_RectFill() { int x, y, x2, y2, c; x=ResolveOperand(); y=ResolveOperand(); x2=ResolveOperand(); y2=ResolveOperand(); c=ResolveOperand(); if (!LucentOn) RectFillClip(x,y,x2,y2,c); if ( LucentOn) RectFillLucentClip(x,y,x2,y2,c); } void vc_strlen() { char str[256]; ResolveString(str); vcreturn=strlen(str); } void vc_strcmp() { char str1[256], str2[256]; ResolveString(str1); ResolveString(str2); vcreturn=strcmp(str1, str2); } void vc_FontWidth() { int i; i=ResolveOperand(); if (i>=numfonts) { vcreturn=0; return; } vcreturn=font[i].width; } void vc_FontHeight() { int i; i=ResolveOperand(); if (i>=numfonts) { vcreturn=0; return; } vcreturn=font[i].height; } void vc_SetPixel() { int x, y, c; x=ResolveOperand(); y=ResolveOperand(); c=ResolveOperand(); SetPixelClip(x,y,c); } void vc_GetPixel() { int x, y; x=ResolveOperand(); y=ResolveOperand(); vcreturn=GetPixelClip(x,y); } void vc_EntityOnScreen() { int i,j; i=ResolveOperand(); for (j=0; j63) r=63; g=ResolveOperand(); if (g<0) g=0; if (g>63) g=63; b=ResolveOperand(); if (b<0) b=0; if (b>63) b=63; percent=100-ResolveOperand(); intensity=ResolveOperand(); for (i=0; i<256; i++) { wr=pal[(i*3)]; wg=pal[(i*3)+1]; wb=pal[(i*3)+2]; wr=((wr*percent)+(r*(100-percent)))/100; wg=((wg*percent)+(g*(100-percent)))/100; wb=((wb*percent)+(b*(100-percent)))/100; pal2[(i*3)]=wr*intensity/63; pal2[(i*3)+1]=wg*intensity/63; pal2[(i*3)+2]=wb*intensity/63; } SetPalette(pal2); } void EnforceNoDirectories(char *s) { char y[256], *p; strcpy(y, s); p=(char *) (int) y + (int) strlen(y); while (p>y && *p != '/' && *p != '\\') p--; if (*p == '/' || *p == '\\') p++; strcpy(s, p); } void vc_OpenFile() { VFILE *f; char fname[256]; ResolveString(fname); EnforceNoDirectories(fname); f=vopen(fname); vcreturn=(quad) f; Log(" --> VC opened file %s, ptr %u", fname, (quad) f); } void vc_CloseFile() { VFILE *f; f=(VFILE *) ResolveOperand(); vclose(f); Log(" --> VC closed file at ptr %u", (quad) f); } void vc_QuickRead() { char fname[256], c, *p; int d=0, l, i; VFILE *f; word w=0; ResolveString(fname); EnforceNoDirectories(fname); c=GrabC(); if (c==op_STRING) { w=GrabW(); d=0; } if (c==op_SARRAY) { w=GrabW(); d=ResolveOperand(); } l=ResolveOperand(); l=l ? l : 1; if (!(f=vopen(fname))) err("QuickRead() - could not open %s",fname); p=(char *) (quad) stringbuf + ((w+d)*256); for (i=0; i=entities) err("AddFollower(): Not a valid entity index. (%d)",i); follower[(int)numfollowers]=i; numfollowers++; // ResetFollowers(); } void vc_FlatPoly() { int a, b, c, d, e, f, g; a=ResolveOperand(); b=ResolveOperand(); c=ResolveOperand(); d=ResolveOperand(); e=ResolveOperand(); f=ResolveOperand(); g=ResolveOperand(); FlatPoly(a,b,c,d,e,f,g); } void vc_TMapPoly() { int a,b,c,d,e,f,g,h,i,j,k,l,m,n,o; a=ResolveOperand(); b=ResolveOperand(); c=ResolveOperand(); d=ResolveOperand(); e=ResolveOperand(); f=ResolveOperand(); g=ResolveOperand(); h=ResolveOperand(); i=ResolveOperand(); j=ResolveOperand(); k=ResolveOperand(); l=ResolveOperand(); m=ResolveOperand(); n=ResolveOperand(); o=ResolveOperand(); TMapPoly(a,b,c,d,e,f,g,h,i,j,k,l,m,n,(char *) o); } void vc_CacheSound() { char fname[256]; ResolveString(fname); vcreturn=CacheSound(fname); } void vc_PlaySound() { int a, b, c; a=ResolveOperand(); b=ResolveOperand(); c=ResolveOperand(); PlaySound(a, b, c); } void vc_RotScale() { int a, b, c, d, e, f, g; a=ResolveOperand(); b=ResolveOperand(); c=ResolveOperand(); d=ResolveOperand(); e=ResolveOperand(); f=ResolveOperand(); g=ResolveOperand(); RotScale(a, b, c, d, e*3.14159 / 180, (float) f/1000, (byte *) g); } void vc_MapLine() { int x, y, sy, l; int xtc, ytc, xofs, yofs; x=ResolveOperand(); y=ResolveOperand(); sy=ResolveOperand(); l=ResolveOperand(); xtc=x >> 4; ytc=y >> 4; xofs= -(x&15); yofs= (y&15); MapLine(xofs, sy, yofs, (word *) (layers[l]+((ytc*layer[l].sizex)+xtc))); } void vc_TMapLine() { int x, y, sy, l; int xtc, ytc, xofs, yofs; x=ResolveOperand(); y=ResolveOperand(); sy=ResolveOperand(); l=ResolveOperand(); xtc=x >> 4; ytc=y >> 4; xofs= -(x&15); yofs= (y&15); TMapLine(xofs, sy, yofs, (word *) (layers[l]+((ytc*layer[l].sizex)+xtc))); } void vc_val() { char s[256]; ResolveString(s); vcreturn=atoi(s); } void vc_TScaleSprite() { int x,y,iw,ih,dw,dh,image; x=ResolveOperand(); y=ResolveOperand(); iw=ResolveOperand(); ih=ResolveOperand(); dw=ResolveOperand(); dh=ResolveOperand(); image=ResolveOperand(); if (!LucentOn) TCopySpriteZoomClip(x,y,iw,ih,dw,dh,(byte *) image); if ( LucentOn) TCopySpriteZoomLucentClip(x,y,iw,ih,dw,dh,(byte *) image); } void vc_GrabRegion() { int x1, y1, x2, y2; int i, j, w, h; char *ptr; x1=ResolveOperand(); y1=ResolveOperand(); x2=ResolveOperand()+1; y2=ResolveOperand()+1; ptr=(char *) ResolveOperand(); if (x2>sx-1) x2=sx-1; if (y2>sy-1) y2=sy-1; if (x1<0) x1=0; if (y1<0) y1=0; w=x2 - x1; h=y2 - y1; for (j=y1; j VC renamed %s to %s.", s1, s2); } void vc_fdelete() { char s[256]; ResolveString(s); EnforceNoDirectories(s); remove(s); Log(" --> VC deleted %s.", s); } void vc_fwopen() { char s[256]; ResolveString(s); EnforceNoDirectories(s); vcreturn=(int) fopen(s,"wb"); Log(" --> VC opened %s for writing, ptr %u.", s, vcreturn); } void vc_fwclose() { FILE *f; f=(FILE *) ResolveOperand(); fclose(f); Log(" --> VC close file opened for writing, ptr %u.", (int) f); } void vc_memcpy() { int a, b, c; a=ResolveOperand(); b=ResolveOperand(); c=ResolveOperand(); memcpy((char *) a, (char *) b, c); } void vc_memset() { int a, b, c; a=ResolveOperand(); b=ResolveOperand(); c=ResolveOperand(); memset((char *) a, (byte) b, c); } void vc_Silhouette() { int x=ResolveOperand(); int y=ResolveOperand(); int w=ResolveOperand(); int h=ResolveOperand(); byte *img=(byte *) ResolveOperand(); byte c=(byte) ResolveOperand(); if (ClipOn) { LucentOn ? SilhouetteLucentClip(x,y,w,h,c,img) : SilhouetteClip(x,y,w,h,c,img); } else { LucentOn ? SilhouetteLucent(x,y,w,h,c,img) : Silhouette(x,y,w,h,c,img); } } void vc_SilhouetteScale() { int x=ResolveOperand(); int y=ResolveOperand(); int sw=ResolveOperand(); int sh=ResolveOperand(); int dw=ResolveOperand(); int dh=ResolveOperand(); byte *img=(byte *) ResolveOperand(); byte c=(byte) ResolveOperand(); if (ClipOn) { LucentOn ? SilhouetteZoomLucentClip(x,y,sw,sh,dw,dh,c,img) : SilhouetteZoomClip(x,y,sw,sh,dw,dh,c,img); } else { LucentOn ? SilhouetteZoomLucent(x,y,sw,sh,dw,dh,c,img) : SilhouetteZoom(x,y,sw,sh,dw,dh,c,img); } } void vc_Tint() { int x=ResolveOperand(); int y=ResolveOperand(); int w=ResolveOperand(); int h=ResolveOperand(); byte *img=(byte *)ResolveOperand(); byte c=(byte)ResolveOperand(); ClipOn ? TintClip(x,y,w,h,c,img) : Tint(x,y,w,h,c,img); } void vc_TintScale() { int x=ResolveOperand(); int y=ResolveOperand(); int sw=ResolveOperand(); int sh=ResolveOperand(); int dw=ResolveOperand(); int dh=ResolveOperand(); byte *img=(byte *) ResolveOperand(); byte c=(byte) ResolveOperand(); ClipOn ? TintZoomClip(x,y,sw,sh,dw,dh,c,img) : TintZoom(x,y,sw,sh,dw,dh,c,img); } void vc_Mosaic() { int a,b,c,d,e,f,g; a=ResolveOperand(); b=ResolveOperand(); c=ResolveOperand(); d=ResolveOperand(); e=ResolveOperand(); f=ResolveOperand(); g=ResolveOperand(); Mosaic(a,b,(byte *) c,d,e,f,g); } void vc_WriteVars() { FILE *f; f=(FILE *) ResolveOperand(); fwrite(globalint, 4, maxint, f); fwrite(stringbuf, 256, stralloc, f); } void vc_ReadVars() { VFILE *f; f=(VFILE *) ResolveOperand(); vread(globalint, 4*maxint, f); vread(stringbuf, 256*stralloc, f); } void vc_Asc() { char s[256]; ResolveString(s); vcreturn=(int) s[0]; } void vc_NumForScript() { vcreturn=GrabD(); } void vc_Filesize() { char s[256]; VFILE *f; ResolveString(s); f=vopen(s); vcreturn=filesize(f); vclose(f); } void vc_FTell() { VFILE *f=(VFILE *)ResolveOperand(); vcreturn=vtell(f); } void vc_CheckCorrupt() { Log("checking for corruption..."); CheckCorruption(); } void HandleStdLib() { int x=0; byte c=0; c=GrabC(); switch (c) { case 1: vc_Exit_(); break; case 2: vc_Message(); break; case 3: vc_Malloc(); break; case 4: vc_Free(); break; case 5: vc_pow(); break; case 6: vc_loadimage(); break; case 7: vc_copysprite(); break; case 8: vc_tcopysprite(); break; case 9: Render(); break; case 10: ShowPage(); break; case 11: vc_EntitySpawn(); break; case 12: vc_SetPlayer(); break; case 13: vc_Map(); break; case 14: vc_LoadFont(); break; case 15: vc_PlayFLI(); break; case 16: curx=ResolveOperand(); cury=ResolveOperand(); break; case 17: vc_PrintString(); break; case 18: vc_LoadRaw(); break; case 19: vc_SetTile(); break; case 20: allowconsole=ResolveOperand(); break; case 21: vc_ScaleSprite(); break; case 22: ProcessEntities(); break; case 23: UpdateControls(); break; case 24: UnPress(ResolveOperand()); break; case 25: vc_EntityMove(); break; case 26: vc_HLine(); break; case 27: vc_VLine(); break; case 28: vc_Line(); break; case 29: vc_Circle(); break; case 30: vc_CircleFill(); break; case 31: vc_Rect(); break; case 32: vc_RectFill(); break; case 33: vc_strlen(); break; case 34: vc_strcmp(); break; case 35: break; //CD_Stop(); break; case 36: ResolveOperand(); break; //CD_Play(ResolveOperand()); break; case 37: vc_FontWidth(); break; case 38: vc_FontHeight(); break; case 39: vc_SetPixel(); break; case 40: vc_GetPixel(); break; case 41: vc_EntityOnScreen(); break; case 42: vcreturn=0; if ((x=ResolveOperand())) vcreturn=rand()%x; break; case 43: vc_GetTile(); break; case 44: vc_HookRetrace(); break; case 45: vc_HookTimer(); break; case 46: vc_SetResolution(); break; case 47: vc_SetRString(); break; case 48: vc_SetClipRect(); break; case 49: vc_SetRenderDest(); break; case 50: vc_RestoreRenderSettings(); break; case 51: vc_PartyMove(); break; case 52: vcreturn=sintbl[ResolveOperand()]; break; case 53: vcreturn=costbl[ResolveOperand()]; break; case 54: vcreturn=tantbl[ResolveOperand()]; break; case 55: ReadMouse(); break; case 56: ClipOn=ResolveOperand(); break; case 57: LucentOn=ResolveOperand(); break; case 58: vc_WrapBlit(); break; case 59: vc_TWrapBlit(); break; case 60: vc_SetMousePos(); break; case 61: vc_HookKey(); break; case 62: vc_PlayMusic(); break; case 63: StopMusic(); break; case 64: vc_PaletteMorph(); break; case 65: vc_OpenFile(); break; case 66: vc_CloseFile(); break; case 67: vc_QuickRead(); break; case 68: vc_AddFollower(); break; // case 69: vc_KillFollower(); break; // case 70: vc_KillAllFollowers(); break; // case 71: ResetFollowers(); case 72: vc_FlatPoly(); break; case 73: vc_TMapPoly(); break; case 74: vc_CacheSound(); break; case 75: FreeAllSounds(); break; case 76: vc_PlaySound(); break; case 77: vc_RotScale(); break; case 78: vc_MapLine(); break; case 79: vc_TMapLine(); break; case 80: vc_val(); break; case 81: vc_TScaleSprite(); break; case 82: vc_GrabRegion(); break; case 83: vc_Log(); break; case 84: vc_fseekline(); break; case 85: vc_fseekpos(); break; case 86: vc_fread(); break; case 87: vc_fgetbyte(); break; case 88: vc_fgetword(); break; case 89: vc_fgetquad(); break; case 90: vc_fgetline(); break; case 91: vc_fgettoken(); break; case 92: vc_fwritestring(); break; case 93: vc_fwrite(); break; case 94: vc_frename(); break; case 95: vc_fdelete(); break; case 96: vc_fwopen(); break; case 97: vc_fwclose(); break; case 98: vc_memcpy(); break; case 99: vc_memset(); break; case 100: vc_Silhouette(); break; case 101: vcreturn=(int) InitMosaicTable(); break; case 102: vc_Mosaic(); break; case 103: vc_WriteVars(); break; case 104: vc_ReadVars(); break; case 105: ExecuteEvent(ResolveOperand()); break; case 106: vc_Asc(); break; case 107: ExecuteUserFunc(ResolveOperand()); break; case 108: vc_NumForScript(); break; case 109: vc_Filesize(); break; case 110: vc_FTell(); break; case 111: vc_CheckCorrupt(); break; default: err("VC Execution error: Invalid STDLIB index. (%d)",(int) c); } } // ========================== VC Interpretation Core ========================== int ProcessIf() { byte exec, c; exec=ProcessIfOperand(); // Get base value; while (1) { c=GrabC(); switch (c) { case i_AND: exec=exec & ProcessIfOperand(); continue; case i_OR: exec=exec | ProcessIfOperand(); continue; case i_UNGROUP: break; } break; } return exec; } int ProcessIfOperand() { byte op_desc; int eval; eval=ResolveOperand(); op_desc=GrabC(); switch (op_desc) { case i_ZERO: if (!eval) return 1; else return 0; case i_NONZERO: if (eval) return 1; else return 0; case i_EQUALTO: if (eval == ResolveOperand()) return 1; else return 0; case i_NOTEQUAL: if (eval != ResolveOperand()) return 1; else return 0; case i_GREATERTHAN: if (eval > ResolveOperand()) return 1; else return 0; case i_GREATERTHANOREQUAL: if (eval >= ResolveOperand()) return 1; else return 0; case i_LESSTHAN: if (eval < ResolveOperand()) return 1; else return 0; case i_LESSTHANOREQUAL: if (eval <= ResolveOperand()) return 1; else return 0; case i_GROUP: if (ProcessIf()) return 1; else return 0; } return 0; } void HandleIf() { char *d; if (ProcessIf()) { GrabD(); return; } d=(char *) GrabD(); code=(char *) (int) basevc + (int) d; return; } void HandleExternFunc() { word i, j, k; //lvars *ob = NULL; //lvars *save = NULL; lvars temp; lvars ob; // save lvar memcpy(&temp, &lvar, sizeof(lvars)); memset(&ob, 0, sizeof(lvars)); //ob = (lvars *)valloc(sizeof(lvars)); //2640); //sizeof(lvars)); //2640); //MSS_CHECK_POINTER_VALIDITY(ob); //MSS_SET_BLOCK_LABEL(ob, "ob"); k = 0; i = GrabW(); for (j=0; j Entering user func %s, codeofs %d", funcs[i].fname, funcs[i].syscodeofs); } ExecuteBlock(); basevc = (char *)vcpop(); // restore lvar memcpy(&lvar, &temp, sizeof(lvars)); //memcpy(lvar, &temp, sizeof(lvars)); //vfree(lvar); //lvar = ob; if (vctrack) { Log(" --> Returned from %s", funcs[i].fname); } // MSS_CHECK_ALL_BLOCKS; } void HandleAssign() { byte c, d; word w; quad location=0, value, ofs=0; c=GrabC(); if (c==op_STRING) { w=GrabW(); c=GrabC(); if (c!=a_SET) err("VC execution error: Corrupt string assignment"); location=(quad) stringbuf + (w*256); ResolveString((char *) location); return; } if (c==op_SARRAY) { w=GrabW(); w+=ResolveOperand(); c=GrabC(); if (c!=a_SET) err("VC execution error: Corrupt string assignment"); location=(quad) stringbuf + (w*256); ResolveString((char *) location); return; } if (c==op_SLOCAL) { w=GrabW(); c=GrabC(); if (c!=a_SET) err("VC execution error: Corrupt string assignment"); location=(quad) &lvar.s[w*256]; ResolveString((char *) location); return; } switch (c) { case op_UVAR: location=GrabD(); break; case op_UVARRAY: location=GrabD(); location+=ResolveOperand(); break; case op_HVAR0: location=(int) GrabC(); break; case op_HVAR1: location=(int) GrabC(); ofs=ResolveOperand(); break; case op_LVAR: location=(int) GrabC(); break; default: err("VC Execution error: Unknown assignment category."); } value=ReadInt(c, location, ofs); d=GrabC(); switch(d) { case a_SET: value=ResolveOperand(); break; case a_INC: value++; break; case a_DEC: value--; break; case a_INCSET: value+=ResolveOperand(); break; case a_DECSET: value-=ResolveOperand(); break; default: err("VC Execution error: Invalid assignment operator %d.", (int) d); } WriteInt(c, location, ofs, value); } void HandleSwitch() { int realvalue=0; int compvalue=0; byte c=0; byte *next=0; realvalue=ResolveOperand(); c=GrabC(); while (c!=opRETURN) { compvalue=ResolveOperand(); next=(byte *) GrabD(); if (compvalue!=realvalue) { code=(char *) (int) basevc+(int) next; c=GrabC(); continue; } ExecuteSection(); c=GrabC(); } } void ExecuteVC() { byte c=0; while (1) { if (kill) break; c=GrabC(); switch (c) { case opEXEC_STDLIB: HandleStdLib(); break; case opEXEC_LOCALFUNC: break; case opEXEC_EXTERNFUNC: HandleExternFunc(); break; case opIF: HandleIf(); break; case opELSE: break; case opGOTO: code=basevc+GrabD(); break; case opSWITCH: HandleSwitch(); break; case opASSIGN: HandleAssign(); break; case opRETURN: code=(char *) vcpop(); break; case opSETRETVAL: vcreturn=ResolveOperand(); break; default: err("Internal VC execution error. (%d)",(int) code - (int) basevc); } if ((int) code != -1) continue; else break; } } void ExecuteBlock() { byte c=0; while (1) { if (kill) break; c=GrabC(); switch (c) { case opEXEC_STDLIB: HandleStdLib(); break; case opEXEC_LOCALFUNC: break; case opEXEC_EXTERNFUNC: HandleExternFunc(); break; case opIF: HandleIf(); break; case opELSE: break; case opGOTO: code=basevc+GrabD(); break; case opSWITCH: HandleSwitch(); break; case opASSIGN: HandleAssign(); break; case opRETURN: code=(char *) vcpop(); break; case opSETRETVAL: vcreturn=ResolveOperand(); break; default: err("Internal VC execution error. (%d)",(int) code - (int) basevc); } if (c != opRETURN) continue; else break; } } void ExecuteSection() { byte c=0; while (1) { if (kill) break; c=GrabC(); switch (c) { case opEXEC_STDLIB: HandleStdLib(); break; case opEXEC_LOCALFUNC: break; case opEXEC_EXTERNFUNC: HandleExternFunc(); break; case opIF: HandleIf(); break; case opELSE: break; case opGOTO: code=basevc+GrabD(); break; case opSWITCH: HandleSwitch(); break; case opASSIGN: HandleAssign(); break; case opRETURN: break; case opSETRETVAL: vcreturn=ResolveOperand(); break; default: err("Internal VC execution error. (%d)", (int) code - (int) basevc); } if (c != opRETURN) continue; else break; } } void ExecuteEvent(int i) { invc++; vcpush((quad) code); vcpush((quad) basevc); if (i>mapevents) err("VC event out of bounds (%d)",i); basevc=mapvc; code=(char *) (int) mapvc + (int) mapvctbl[i]; vcpush(-1); ExecuteVC(); basevc=(char *) vcpop(); code=(char *) vcpop(); invc--; } void ExecuteUserFunc(int i) { //lvars *ob=0; lvars temp; // save lvar memcpy(&temp, &lvar, sizeof(lvars)); vcpush((quad) code); vcpush((quad) basevc); if (i > numfuncs) err("VC event out of bounds"); basevc = sysvc; code = (char *)(sysvc + funcs[i].syscodeofs); vcpush(-1); memset(&lvar, 0, sizeof(lvar)); //ob = lvar; //lvar = (lvars *)valloc(sizeof(lvars)); //2640); //MSS_SET_BLOCK_LABEL(lvar, "lvar"); ExecuteVC(); basevc = (char *) vcpop(); code = (char *) vcpop(); //free(lvar); //lvar = ob; // restore lvar memcpy(&lvar, &temp, sizeof(lvars)); } void HookRetrace() { if (!hookretrace) return; if (hookretrace=USERFUNC_MARKER) ExecuteUserFunc(hookretrace-USERFUNC_MARKER); } void HookTimer() { if (!hooktimer) return; if (hooktimer=USERFUNC_MARKER) ExecuteUserFunc(hooktimer-USERFUNC_MARKER); } void HookKey(int script) { if (!script) return; if (script=USERFUNC_MARKER) ExecuteUserFunc(script-USERFUNC_MARKER); }