Index: exec.c ================================================================== --- exec.c +++ exec.c @@ -11,17 +11,140 @@ #include "sqlite3.h" #include "smallxrm.h" #include "heromesh.h" Uint32 generation_number; -Object*objects; +Object**objects; Uint32 nobjects; Value globals[0x800]; +Uint32 firstobj=VOIDLINK; +Uint32 lastobj=VOIDLINK; +Uint32 playfield[64*64]; + +typedef struct { + Uint16 msg; + Uint32 from; + Value arg1,arg2,arg3; +} MessageVars; static jmp_buf my_env; -static int my_error; +static const char*my_error; +static MessageVars msgvars; +static char lastimage_processing; + +#define Throw(x) (my_error=(x),longjmp(my_env,1)) +#define StackReq(x,y) + +void pfunlink(Uint32 n) { + Object*o=objects[n]; + if(o->down==VOIDLINK) playfield[o->x+o->y*64-65]=o->up; + else objects[o->down]->up=o->up; + if(o->up!=VOIDLINK) objects[o->up]->down=o->down; + o->down=o->up=VOIDLINK; +} + +void pflink(Uint32 n) { + Object*o=objects[n]; + int p=o->x+o->y*64-65; + if(p<0) return; + if(playfield[p]==VOIDLINK) { + playfield[p]=n; + } else { + Sint32 d=o->density; + Uint32 m=playfield[p]; + Uint32 t=VOIDLINK; + while(m!=VOIDLINK && objects[m]->density>=d) t=m,m=objects[m]->up; + o->down=t; + o->up=m; + if(t!=VOIDLINK) objects[t]->up=n; else playfield[p]=n; + if(m!=VOIDLINK) objects[m]->down=n; + } +} + +#define OBJECT_ARRAY_BLOCK 256 +Uint32 objalloc(Uint16 c) { + // c must be a valid (nonzero) class number, and not a class with CF_GROUP, CF_NOCLASS1, or CF_NOCLASS2 flags. + Uint32 n; + Class*cl=classes[c]; + Object*o=calloc(1,sizeof(Object)+cl->uservars*sizeof(Value)); + if(!o) fatal("Allocation failed\n"); + o->class=c; + o->generation=generation_number; +#define C(x) o->x=cl->x; + C(height) C(weight) C(climb) C(density) C(volume) C(strength) C(arrivals) C(departures) C(temperature) + C(shape) C(shovable) C(oflags) + C(sharp[0]) C(sharp[1]) C(sharp[2]) C(sharp[3]) + C(hard[0]) C(hard[1]) C(hard[2]) C(hard[3]) +#undef C + o->misc4=NVALUE(cl->misc4); + o->misc5=NVALUE(cl->misc5); + o->misc6=NVALUE(cl->misc6); + o->misc7=NVALUE(cl->misc7); + if(nobjects) for(n=nobjects-1;;n--) { + if(!objects[n]) goto found; + if(!n) break; + } + if(nobjects>=0xFFFF0000L) fatal("Too many objects\n"); + objects=realloc(objects,(nobjects+OBJECT_ARRAY_BLOCK)*sizeof(Object*)); + if(!objects) fatal("Allocation failed\n"); + for(n=nobjects;nup=o->down=o->prev=o->next=VOIDLINK; + if(cl->nmsg || classes[0]->nmsg) { + o->prev=lastobj; + if(lastobj!=VOIDLINK) objects[lastobj]->next=n; + lastobj=n; + if(firstobj==VOIDLINK) firstobj=n; + } + objects[n]=o; + return n; +} + +static void execute_program(Uint16*code,int ptr,Uint32 obj) { + Object*o=objects[obj]; + if(StackProtection()) Throw("Call stack overflow"); + for(;;) switch(code[ptr++]) { + case OP_GOTO: ptr=code[ptr]; break; + case OP_CALLSUB: execute_program(code,code[ptr++],obj); break; + case OP_RET: return; + default: Throw("Internal error: Unrecognized opcode"); + } +} + +static Value send_message(Uint32 from,Uint32 to,Uint16 msg,Value arg1,Value arg2,Value arg3) { + MessageVars saved=msgvars; + Uint16 c=classes[objects[to]->class]; + Uint16 p=get_message_ptr(c,msg); + Uint16*code; + if(p==0xFFFF) { + p=get_message_ptr(0,msg); + if(!p) return NVALUE(0); + code=classes[0]->codes; + } else { + code=classes[c]->codes; + } + + msgvars={msg,from,arg1,arg2,arg3}; + execute_program(code,p,to); + msgvars=saved; + +} + +void annihilate(void) { + Uint32 i; + if(!objects) return; + for(i=0;igeneration) #define N_MESSAGES 23 extern const char*const standard_message_names[]; extern const char*const standard_sound_names[]; extern const char*const heromesh_key_names[256]; @@ -144,26 +145,37 @@ // == function == void init_sql_functions(sqlite3_int64*ptr0,sqlite3_int64*ptr1); // == exec == + +#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 typedef struct { Sint32 height,weight,climb,density,volume,strength,arrivals,departures,temperature; - Uint32 arrived,departed,arrived2,departed2,generation,up; + Uint32 arrived,departed,arrived2,departed2,generation; + Uint32 up,down,prev,next; // links to other objects Uint16 class,oflags; Uint16 sharp[4]; Uint16 hard[4]; Uint8 x,y,shape,shovable,image,dir; Value misc1,misc2,misc3,misc4,misc5,misc6,misc7; Value uservars[0]; } Object; extern Uint32 generation_number; -extern Object*objects; +extern Object**objects; extern Uint32 nobjects; extern Value globals[0x800]; +extern Uint32 firstobj,lastobj; +extern Uint32 playfield[64*64]; + +void pfunlink(Uint32 n); +void pflink(Uint32 n); +Uint32 objalloc(Uint16 c); +void annihilate(void); +const char*execute_turn(int key);