Index: class.c ================================================================== --- class.c +++ class.c @@ -1055,11 +1055,11 @@ case OP_STRING: AddInst2(OP_STRING,pool_string(tokenstr)); break; default: if(Tokenf(TF_ABNORMAL)) ParseError("Invalid instruction token\n"); - if(compat && Tokenf(TF_COMPAT)) ++tokenv; + if(compat && Tokenf(TF_COMPAT) && Tokenf(TF_EQUAL)) ++tokenv; AddInstF(tokenv,tokent); } } else if(Tokenf(TF_FUNCTION)) { AddInst2(OP_FUNCTION,tokenv&0x3FFF); } else if(tokent==TF_OPEN) { Index: exec.c ================================================================== --- exec.c +++ exec.c @@ -156,17 +156,43 @@ if(o->next) objects[o->next]->prev=o->prev; free(o); objects[n]=0; generation_number_inc=1; } + +static Uint32 obj_above(Uint32 i) { + Object*o; + if(i==VOIDLINK) return VOIDLINK; + o=objects[i]; + i=o->up; + while(i!=VOIDLINK) { + o=objects[i]; + if(!(o->oflags&(OF_DESTROYED|OF_VISUALONLY))) return i; + i=o->up; + } + return VOIDLINK; +} + +static Uint32 obj_below(Uint32 i) { + Object*o; + if(i==VOIDLINK) return VOIDLINK; + o=objects[i]; + i=o->down; + while(i!=VOIDLINK) { + o=objects[i]; + if(!(o->oflags&(OF_DESTROYED|OF_VISUALONLY))) return i; + i=o->down; + } + return VOIDLINK; +} static Uint32 obj_class_at(Uint32 c,Uint32 x,Uint32 y) { Uint32 i; if(x<1 || x>pfwidth || y<1 || y>pfheight) return VOIDLINK; i=playfield[x+y*64-65]; while(i!=VOIDLINK) { - if(objects[i]->class==c && !(objects[i]->oflags&OF_DESTROYED) && !(objects[i]->dir&IOF_DEAD)) return i; + if(objects[i]->class==c && !(objects[i]->oflags&OF_DESTROYED)) return i; i=objects[i]->up; } return VOIDLINK; } @@ -187,11 +213,11 @@ return 0; } static Uint32 v_object(Value v) { if(v.t==TY_NUMBER) { - if(v.u) Throw("Cannot convert number to object"); + if(v.u) Throw("Cannot convert non-zero number to object"); return VOIDLINK; } else if(v.t>TY_MAXTYPE) { if(v.u>=nobjects || !objects[v.u]) Throw("Attempt to use a nonexistent object"); if(objects[v.u]->generation!=v.t) Throw("Attempt to use a nonexistent object"); return v.u; @@ -257,11 +283,11 @@ // Here is where the execution of a Free Hero Mesh bytecode subroutine is executed. #define NoIgnore() do{ changed=1; }while(0) #define GetVariableOf(a,b) (i=v_object(Pop()),i==VOIDLINK?NVALUE(0):b(objects[i]->a)) #define Numeric(a) do{ if((a).t!=TY_NUMBER) Throw("Type mismatch"); }while(0) -#define DivideBy(a) do { if(!(a).u) Throw("Division by zero"); }while(0) +#define DivideBy(a) do{ if(!(a).u) Throw("Division by zero"); }while(0) static void execute_program(Uint16*code,int ptr,Uint32 obj) { Uint32 i; Object*o=objects[obj]; Value t1,t2; static Value t3,t4,t5; @@ -305,17 +331,22 @@ case 0x3000 ... 0x37FF: NoIgnore(); StackReq(1,0); o->uservars[code[ptr-1]&0x7FF]=Pop(); break; case 0x3800 ... 0x38FF: NoIgnore(); StackReq(1,0); globals[code[ptr-1]&0x7FF]=Pop(); break; case 0x4000 ... 0x7FFF: StackReq(0,1); Push(CVALUE(code[ptr-1]-0x4000)); break; case 0x87E8 ... 0x87FF: StackReq(0,1); Push(NVALUE(1UL<<(code[ptr-1]&31))); break; case 0xC000 ... 0xFFFF: StackReq(0,1); Push(MVALUE((code[ptr-1]&0x3FFF)+256)); break; + case OP_ADD: StackReq(2,1); t2=Pop(); Numeric(t2); t1=Pop(); Numeric(t1); Push(NVALUE(t1.u+t2.u)); break; + case OP_BAND: StackReq(2,1); t2=Pop(); Numeric(t2); t1=Pop(); Numeric(t1); Push(NVALUE(t1.u&t2.u)); break; + case OP_BNOT: StackReq(1,1); t1=Pop(); Numeric(t1); Push(NVALUE(~t1.u)); break; + case OP_BOR: StackReq(2,1); t2=Pop(); Numeric(t2); t1=Pop(); Numeric(t1); Push(NVALUE(t1.u|t2.u)); break; case OP_BROADCAST: StackReq(4,1); t4=Pop(); t3=Pop(); t2=Pop(); t1=Pop(); Push(v_broadcast(obj,t1,t2,t3,t4,NVALUE(0),0)); break; case OP_BROADCAST_D: StackReq(4,0); t4=Pop(); t3=Pop(); t2=Pop(); t1=Pop(); v_broadcast(obj,t1,t2,t3,t4,NVALUE(0),0); break; case OP_BROADCASTCLASS: StackReq(3,1); t4=Pop(); t3=Pop(); t2=Pop(); Push(v_broadcast(obj,CVALUE(code[ptr++]),t2,t3,t4,NVALUE(0),0)); break; case OP_BROADCASTEX: StackReq(5,1); t5=Pop(); t4=Pop(); t3=Pop(); t2=Pop(); t1=Pop(); Push(v_broadcast(obj,t1,t2,t3,t4,t5,0)); break; case OP_BROADCASTEX_D: StackReq(5,0); t5=Pop(); t4=Pop(); t3=Pop(); t2=Pop(); t1=Pop(); v_broadcast(obj,t1,t2,t3,t4,t5,0); break; case OP_BROADCASTSUM: StackReq(4,1); t4=Pop(); t3=Pop(); t2=Pop(); t1=Pop(); Push(v_broadcast(obj,t1,t2,t3,t4,NVALUE(0),1)); break; case OP_BROADCASTSUMEX: StackReq(5,1); t5=Pop(); t4=Pop(); t3=Pop(); t2=Pop(); t1=Pop(); Push(v_broadcast(obj,t1,t2,t3,t4,t5,1)); break; + case OP_BXOR: StackReq(2,1); t2=Pop(); Numeric(t2); t1=Pop(); Numeric(t1); Push(NVALUE(t1.u^t2.u)); break; case OP_CALLSUB: execute_program(code,code[ptr++],obj); break; case OP_CLASS: StackReq(0,1); Push(CVALUE(o->class)); break; case OP_CLASS_C: StackReq(1,1); Push(GetVariableOf(class,CVALUE)); break; case OP_DIR: StackReq(0,1); Push(NVALUE(o->dir&7)); break; case OP_DISTANCE: StackReq(0,1); Push(NVALUE(o->distance)); break; @@ -340,12 +371,17 @@ case OP_LOC: StackReq(0,2); Push(NVALUE(o->x)); Push(NVALUE(o->y)); break; case OP_LOR: StackReq(2,1); t1=Pop(); t2=Pop(); if(v_bool(t1) || v_bool(t2)) Push(NVALUE(1)); else Push(NVALUE(0)); break; case OP_LOSELEVEL: gameover=-1; Throw(0); break; case OP_LT: StackReq(2,1); t2=Pop(); t1=Pop(); Push(NVALUE(v_unsigned_greater(t2,t1)?1:0)); break; case OP_LT_C: StackReq(2,1); t2=Pop(); t1=Pop(); Push(NVALUE(v_signed_greater(t2,t1)?1:0)); break; + case OP_LXOR: StackReq(2,1); t1=Pop(); t2=Pop(); if(v_bool(t1)?!v_bool(t2):v_bool(t2)) Push(NVALUE(1)); else Push(NVALUE(0)); break; case OP_NE: StackReq(2,1); t2=Pop(); t1=Pop(); Push(NVALUE(v_equal(t1,t2)?0:1)); break; case OP_NIP: StackReq(2,1); t1=Pop(); Pop(); Push(t1); break; + case OP_OBJABOVE: StackReq(0,1); i=obj_above(obj); Push(OVALUE(i)); break; + case OP_OBJABOVE_C: StackReq(1,1); i=obj_above(v_object(Pop())); Push(OVALUE(i)); break; + case OP_OBJBELOW: StackReq(0,1); i=obj_below(obj); Push(OVALUE(i)); break; + case OP_OBJBELOW_C: StackReq(1,1); i=obj_below(v_object(Pop())); Push(OVALUE(i)); break; case OP_OBJCLASSAT: StackReq(3,1); t3=Pop(); t2=Pop(); t1=Pop(); Push(v_obj_class_at(t1,t2,t3)); break; case OP_RET: return; case OP_SEND: StackReq(3,1); t4=Pop(); t3=Pop(); t2=Pop(); Push(v_send_self(obj,t2,t3,t4,NVALUE(0))); break; case OP_SEND_C: StackReq(4,1); t4=Pop(); t3=Pop(); t2=Pop(); t1=Pop(); Push(v_send_message(obj,t1,t2,t3,t4,NVALUE(0))); break; case OP_SEND_D: StackReq(3,0); t4=Pop(); t3=Pop(); t2=Pop(); v_send_self(obj,t2,t3,t4,NVALUE(0)); break; @@ -353,15 +389,26 @@ case OP_SENDEX: StackReq(4,1); t5=Pop(); t4=Pop(); t3=Pop(); t2=Pop(); Push(v_send_self(obj,t2,t3,t4,t5)); break; case OP_SENDEX_C: StackReq(5,1); t5=Pop(); t4=Pop(); t3=Pop(); t2=Pop(); t1=Pop(); Push(v_send_message(obj,t1,t2,t3,t4,t5)); break; case OP_SENDEX_D: StackReq(4,0); t5=Pop(); t4=Pop(); t3=Pop(); t2=Pop(); v_send_self(obj,t2,t3,t4,t5); break; case OP_SENDEX_CD: StackReq(5,0); t5=Pop(); t4=Pop(); t3=Pop(); t2=Pop(); t1=Pop(); v_send_message(obj,t1,t2,t3,t4,t5); break; case OP_SOUND: StackReq(2,0); t2=Pop(); t1=Pop(); break; // Sound not implemented at this time + case OP_SUB: StackReq(2,1); t2=Pop(); Numeric(t2); t1=Pop(); Numeric(t1); Push(NVALUE(t1.u-t2.u)); break; case OP_SWAP: StackReq(2,2); t1=Pop(); t2=Pop(); Push(t1); Push(t2); break; case OP_TRACE: StackReq(3,0); trace_stack(obj); break; case OP_WINLEVEL: key_ignored=0; gameover=1; Throw(0); break; case OP_XLOC: StackReq(0,1); Push(NVALUE(o->x)); break; case OP_YLOC: StackReq(0,1); Push(NVALUE(o->y)); break; +#define MiscVar(a,b) \ + case a: StackReq(0,1); Push(o->b); break; \ + case a+0x0800: StackReq(1,1); Push(GetVariableOf(b,)); break; \ + case a+0x1000: StackReq(1,0); objects[i]->b=Pop(); break; \ + case a+0x1001: StackReq(1,0); t1=Pop(); if(!t1.t) t1.u&=0xFFFF; objects[i]->b=t1; break; \ + case a+0x1800: StackReq(2,0); t1=Pop(); i=v_object(Pop()); if(i!=VOIDLINK) objects[i]->b=t1; break; \ + case a+0x1801: StackReq(2,0); t1=Pop(); if(!t1.t) t1.u&=0xFFFF; i=v_object(Pop()); if(i!=VOIDLINK) objects[i]->b=t1; break; + MiscVar(OP_MISC1,misc1) MiscVar(OP_MISC2,misc2) MiscVar(OP_MISC3,misc3) + MiscVar(OP_MISC4,misc4) MiscVar(OP_MISC5,misc5) MiscVar(OP_MISC6,misc6) MiscVar(OP_MISC7,misc7) +#undef MiscVar default: fprintf(stderr,"Unrecognized opcode 0x%04X at 0x%04X in $%s\n",code[ptr-1],ptr-1,classes[o->class]->name); Throw("Internal error: Unrecognized opcode"); } } static void trace_message(Uint32 obj) { Index: heromesh.h ================================================================== --- heromesh.h +++ heromesh.h @@ -169,11 +169,11 @@ #define VOIDLINK ((Uint32)(-1)) // The following "internal object flags" are part of the "dir" variable: #define IOF_DEAD 0x10 // object doesn't exist, except to continue an animation #define IOF_ANIM 0x20 // an animation is being displayed -// If the IOF_DEAD flag is set, then generation should also be set to zero. +// If the IOF_DEAD flag is set, then generation should also be set to zero, and OF_DESTROYED must be set, too. typedef struct { Sint32 height,weight,climb,density,volume,strength,arrivals,departures,temperature; Uint32 arrived,departed,arrived2,departed2,generation; Uint32 up,down,prev,next; // links to other objects Index: instruc.h ================================================================== --- instruc.h +++ instruc.h @@ -62,11 +62,11 @@ #define OP_CLASS_C 34859 #define OP_TEMPERATURE 32812 #define OP_TEMPERATURE_C 34860 #define OP_TEMPERATURE_E 36908 #define OP_TEMPERATURE_EC 38956 -#define OP_TEMPERATURE_EC16 34861 +#define OP_TEMPERATURE_EC16 38957 #define OP_TEMPERATURE_E16 36909 #define OP_SHAPE 32814 #define OP_SHAPE_C 34862 #define OP_SHAPE_E 36910 #define OP_SHAPE_EC 38958 @@ -84,53 +84,53 @@ #define OP_IMAGE_EC 38962 #define OP_INERTIA 32819 #define OP_INERTIA_C 34867 #define OP_INERTIA_E 36915 #define OP_INERTIA_EC 38963 -#define OP_INERTIA_EC16 34868 +#define OP_INERTIA_EC16 38964 #define OP_INERTIA_E16 36916 #define OP_DISTANCE 32821 #define OP_DISTANCE_C 34869 #define OP_DISTANCE_E 36917 #define OP_DISTANCE_EC 38965 -#define OP_DISTANCE_EC16 34870 +#define OP_DISTANCE_EC16 38966 #define OP_DISTANCE_E16 36918 #define OP_DENSITY 32823 #define OP_DENSITY_C 34871 #define OP_DENSITY_E 36919 #define OP_DENSITY_EC 38967 -#define OP_DENSITY_EC16 34872 +#define OP_DENSITY_EC16 38968 #define OP_DENSITY_E16 36920 #define OP_VOLUME 32825 #define OP_VOLUME_C 34873 #define OP_VOLUME_E 36921 #define OP_VOLUME_EC 38969 -#define OP_VOLUME_EC16 34874 +#define OP_VOLUME_EC16 38970 #define OP_VOLUME_E16 36922 #define OP_WEIGHT 32827 #define OP_WEIGHT_C 34875 #define OP_WEIGHT_E 36923 #define OP_WEIGHT_EC 38971 -#define OP_WEIGHT_EC16 34876 +#define OP_WEIGHT_EC16 38972 #define OP_WEIGHT_E16 36924 #define OP_HEIGHT 32829 #define OP_HEIGHT_C 34877 #define OP_HEIGHT_E 36925 #define OP_HEIGHT_EC 38973 -#define OP_HEIGHT_EC16 34878 +#define OP_HEIGHT_EC16 38974 #define OP_HEIGHT_E16 36926 #define OP_CLIMB 32831 #define OP_CLIMB_C 34879 #define OP_CLIMB_E 36927 #define OP_CLIMB_EC 38975 -#define OP_CLIMB_EC16 34880 +#define OP_CLIMB_EC16 38976 #define OP_CLIMB_E16 36928 #define OP_STRENGTH 32833 #define OP_STRENGTH_C 34881 #define OP_STRENGTH_E 36929 #define OP_STRENGTH_EC 38977 -#define OP_STRENGTH_EC16 34882 +#define OP_STRENGTH_EC16 38978 #define OP_STRENGTH_E16 36930 #define OP_HARD 32835 #define OP_HARD_C 34883 #define OP_HARD_E 36931 #define OP_HARD_EC 38979 @@ -148,47 +148,47 @@ #define OP_SHOVABLE_EC 38982 #define OP_MISC1 32839 #define OP_MISC1_C 34887 #define OP_MISC1_E 36935 #define OP_MISC1_EC 38983 -#define OP_MISC1_EC16 34888 +#define OP_MISC1_EC16 38984 #define OP_MISC1_E16 36936 #define OP_MISC2 32841 #define OP_MISC2_C 34889 #define OP_MISC2_E 36937 #define OP_MISC2_EC 38985 -#define OP_MISC2_EC16 34890 +#define OP_MISC2_EC16 38986 #define OP_MISC2_E16 36938 #define OP_MISC3 32843 #define OP_MISC3_C 34891 #define OP_MISC3_E 36939 #define OP_MISC3_EC 38987 -#define OP_MISC3_EC16 34892 +#define OP_MISC3_EC16 38988 #define OP_MISC3_E16 36940 #define OP_MISC4 32845 #define OP_MISC4_C 34893 #define OP_MISC4_E 36941 #define OP_MISC4_EC 38989 -#define OP_MISC4_EC16 34894 +#define OP_MISC4_EC16 38990 #define OP_MISC4_E16 36942 #define OP_MISC5 32847 #define OP_MISC5_C 34895 #define OP_MISC5_E 36943 #define OP_MISC5_EC 38991 -#define OP_MISC5_EC16 34896 +#define OP_MISC5_EC16 38992 #define OP_MISC5_E16 36944 #define OP_MISC6 32849 #define OP_MISC6_C 34897 #define OP_MISC6_E 36945 #define OP_MISC6_EC 38993 -#define OP_MISC6_EC16 34898 +#define OP_MISC6_EC16 38994 #define OP_MISC6_E16 36946 #define OP_MISC7 32851 #define OP_MISC7_C 34899 #define OP_MISC7_E 36947 #define OP_MISC7_EC 38995 -#define OP_MISC7_EC16 34900 +#define OP_MISC7_EC16 38996 #define OP_MISC7_E16 36948 #define OP_ARRIVED 32853 #define OP_ARRIVED_C 34901 #define OP_ARRIVED_E 36949 #define OP_ARRIVED_EC 38997 Index: instruc.js ================================================================== --- instruc.js +++ instruc.js @@ -37,11 +37,11 @@ console.log("#define OP_"+reg[2].toUpperCase()+" "+curnum); if(flags&1) console.log("#define OP_"+reg[2].toUpperCase()+"_C "+(curnum+0x0800)); if(flags&2) console.log("#define OP_"+reg[2].toUpperCase()+"_E "+(curnum+0x1000)); if(3==(flags&3)) console.log("#define OP_"+reg[2].toUpperCase()+"_EC "+(curnum+0x1800)); if(10==(flags&10)) { - if(flags&1) console.log("#define OP_"+reg[2].toUpperCase()+"_EC16 "+(curnum+0x0801)); + if(flags&1) console.log("#define OP_"+reg[2].toUpperCase()+"_EC16 "+(curnum+0x1801)); console.log("#define OP_"+reg[2].toUpperCase()+"_E16 "+(curnum+0x1001)); } if(flags&32) { console.log("#define OP_"+reg[2].toUpperCase()+"_D "+(curnum+0x2000)); if(flags&1) console.log("#define OP_"+reg[2].toUpperCase()+"_CD "+(curnum+0x2800));