Index: exec.c ================================================================== --- exec.c +++ exec.c @@ -8,10 +8,11 @@ #include #include #include #include "sqlite3.h" #include "smallxrm.h" +#include "quarks.h" #include "heromesh.h" #include "instruc.h" #ifndef VSTACKSIZE #define VSTACKSIZE 0x400 @@ -26,10 +27,11 @@ Uint32 lastobj=VOIDLINK; Uint32 playfield[64*64]; Uint8 pfwidth,pfheight; Sint8 gameover,key_ignored; Uint8 generation_number_inc; +Uint32 move_number; typedef struct { Uint16 msg; Uint32 from; Value arg1,arg2,arg3; @@ -39,10 +41,11 @@ static const char*my_error; static MessageVars msgvars; static char lastimage_processing,changed; static Value vstack[VSTACKSIZE]; static int vstackptr; +static const char*traceprefix; #define Throw(x) (my_error=(x),longjmp(my_env,1)) #define StackReq(x,y) do{ if(vstackptr<(x)) Throw("Stack underflow"); if(vstackptr-(x)+(y)>=VSTACKSIZE) Throw("Stack overflow"); }while(0) #define Push(x) (vstack[vstackptr++]=(x)) #define Pop() (vstack[--vstackptr]) @@ -161,10 +164,31 @@ return v.u; } else { Throw("Cannot convert non-object to object"); } } + +static void trace_stack(Uint32 obj) { + Value t2=Pop(); + Value t1=Pop(); + Value t0=Pop(); + Object*o; + if(!main_options['t']) return; + if(!traceprefix) { + optionquery[1]=Q_tracePrefix; + traceprefix=xrm_get_resource(resourcedb,optionquery,optionquery,2); + if(!traceprefix) traceprefix=""; + } + printf("%sTrace : %d : %u %u",traceprefix,vstackptr,t0.t,t0.u); + if(t0.t>TY_MAXTYPE && t0.ugeneration==t0.t) { + o=objects[t0.u]; + printf(" [$%s %d %d]",classes[o->class]->name,o->x,o->y); + } + o=objects[obj]; + printf(" : %u %u [$%s %d %d]",o->generation,obj,classes[o->class]->name,o->x,o->y); + printf(" : %u %u : %u %u\n",t1.t,t1.u,t2.t,t2.u); +} // 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)) static void execute_program(Uint16*code,int ptr,Uint32 obj) { @@ -200,10 +224,11 @@ 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_NIP: StackReq(2,1); t1=Pop(); Pop(); Push(t1); break; case OP_RET: return; 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; default: Throw("Internal error: Unrecognized opcode"); } } @@ -263,9 +288,10 @@ gameover=0; changed=0; key_ignored=0; lastimage_processing=0; vstackptr=0; + move_number=0; if(generation_number<=TY_MAXTYPE) return "Too many generations of objects"; return 0; } Index: function.c ================================================================== --- function.c +++ function.c @@ -301,10 +301,15 @@ sqlite3_int64 a; if(sqlite3_value_type(*argv)==SQLITE_NULL) return; a=sqlite3_value_int64(*argv)&0xFFFFFFFF; sqlite3_result_int64(cxt,a-(a&0x80000000?0x100000000LL:0)); } + +static void fn_trace_on(sqlite3_context*cxt,int argc,sqlite3_value**argv) { + const char*v=sqlite3_user_data(cxt); + if(main_options['t']=*v) puts("[Tracing enabled]"); else puts("[Tracing disabled]"); +} static void fn_zero_extend(sqlite3_context*cxt,int argc,sqlite3_value**argv) { sqlite3_int64 a; if(sqlite3_value_type(*argv)==SQLITE_NULL) return; a=sqlite3_value_int64(*argv)&0xFFFFFFFF; @@ -940,12 +945,14 @@ sqlite3_create_function(userdb,"PICTURE_SIZE",0,SQLITE_UTF8|SQLITE_DETERMINISTIC,0,fn_picture_size,0,0); sqlite3_create_function(userdb,"READ_LUMP_AT",2,SQLITE_UTF8,0,fn_read_lump_at,0,0); sqlite3_create_function(userdb,"RESOURCE",-1,SQLITE_UTF8|SQLITE_DETERMINISTIC,0,fn_resource,0,0); sqlite3_create_function(userdb,"SIGN_EXTEND",1,SQLITE_UTF8|SQLITE_DETERMINISTIC,0,fn_sign_extend,0,0); sqlite3_create_function(userdb,"SOLUTION_CACHEID",0,SQLITE_UTF8|SQLITE_DETERMINISTIC,ptr1,fn_cacheid,0,0); + sqlite3_create_function(userdb,"TRACE_OFF",0,SQLITE_UTF8,"",fn_trace_on,0,0); + sqlite3_create_function(userdb,"TRACE_ON",0,SQLITE_UTF8,"\x01",fn_trace_on,0,0); sqlite3_create_function(userdb,"ZERO_EXTEND",1,SQLITE_UTF8|SQLITE_DETERMINISTIC,0,fn_zero_extend,0,0); sqlite3_create_module(userdb,"CLASSES",&vt_classes,"CREATE TABLE `CLASSES`(`ID` INTEGER PRIMARY KEY, `NAME` TEXT, `EDITORHELP` TEXT, `HELP` TEXT," "`INPUT` INT, `QUIZ` INT, `TRACEIN` INT, `TRACEOUT` INT, `GROUP` TEXT, `PLAYER` INT);"); sqlite3_create_module(userdb,"MESSAGES",&vt_messages,"CREATE TABLE `MESSAGES`(`ID` INTEGER PRIMARY KEY, `NAME` TEXT, `TRACE` INT);"); sqlite3_create_module(userdb,"OBJECTS",&vt_objects,"CREATE TABLE `OBJECTS`(`ID` INTEGER PRIMARY KEY, `CLASS` INT, `MISC1` INT, `MISC2` INT, `MISC3` INT," "`IMAGE` INT, `DIR` INT, `X` INT, `Y` INT, `UP` INT, `DOWN` INT, `DENSITY` INT HIDDEN);"); } Index: heromesh.h ================================================================== --- heromesh.h +++ heromesh.h @@ -192,10 +192,11 @@ extern Uint32 firstobj,lastobj; extern Uint32 playfield[64*64]; extern Uint8 pfwidth,pfheight; extern Sint8 gameover,key_ignored; extern Uint8 generation_number_inc; +extern Uint32 move_number; void pfunlink(Uint32 n); void pflink(Uint32 n); Uint32 objalloc(Uint16 c); void objtrash(Uint32 n);