Index: class.c ================================================================== --- class.c +++ class.c @@ -14,50 +14,65 @@ #include #include "sqlite3.h" #include "smallxrm.h" #include "heromesh.h" -#define TF_COMMA 0x0001 -#define TF_EQUAL 0x0002 -#define TF_ABNORMAL 0x0004 -#define TF_COMPAT 0x0008 -#define TF_DIR 0x0010 -#define TF_DROP 0x0020 -#define TF_NAME 0x0080 -#define TF_KEY 0x0100 -#define TF_OPEN 0x0400 -#define TF_CLOSE 0x0800 -#define TF_INT 0x1000 -#define TF_MACRO 0x4000 -#define TF_EOF 0x8000 +#define TF_COMMA 0x0001 // has a comma modifier +#define TF_EQUAL 0x0002 // has an equal sign modifier +#define TF_ABNORMAL 0x0004 // with TF_NAME, not directly an opcode +#define TF_COMPAT 0x0008 // add 1 to opcode in compatibility mode +#define TF_DIR 0x0010 // token is a direction +#define TF_DROP 0x0020 // add 0x2000 to opcode if followed by OP_DROP +#define TF_NAME 0x0080 // token is a name or opcode +#define TF_KEY 0x0100 // token is a Hero Mesh key name +#define TF_OPEN 0x0400 // token is ( +#define TF_CLOSE 0x0800 // token is ) +#define TF_INT 0x1000 // token is a number +#define TF_FUNCTION 0x2000 // token is a user function +#define TF_MACRO 0x4000 // token is a macro; never returned by nxttok() +#define TF_EOF 0x8000 // end of file typedef struct { const char*txt; Uint32 num; } Op_Names; #include "instruc.h" #define Tokenf(x) (tokent&(x)) Class*classes[0x4000]; const char*messages[0x4000]; +Uint16 functions[0x4000]; int max_animation=32; Sint32 max_volume=10000; + +#define HASH_SIZE 8888 +#define LOCAL_HASH_SIZE 5555 +typedef struct { + Uint16 id; + char*txt; +} Hash; static FILE*classfp; static Uint16 tokent; static Uint32 tokenv; static int linenum=1; static char tokenstr[0x2000]; static int undef_class=1; static int undef_message=0; +static int num_globals=0; +static int num_functions=0; +static Hash*glohash; #define ParseError(a,...) fatal("On line %d: " a,linenum,##__VA_ARGS__) static const unsigned char chkind[256]={ ['$']=1, ['!']=1, ['\'']=1, ['#']=1, ['@']=1, ['%']=1, ['&']=1, [':']=1, ['0'...'9']=2, ['-']=2, ['+']=2, ['A'...'Z']=3, ['a'...'z']=3, ['_']=3, ['?']=3, ['.']=3, ['*']=3, ['/']=3, }; + +#define MIN_VERSION 0 +#define MAX_VERSION 0 static void read_quoted_string(void) { int c,i,n; int isimg=0; for(i=0;i<0x1FFD;) { @@ -162,17 +177,33 @@ if(u==undef_message) ++undef_message; messages[u]=strdup(tokenstr); if(!messages[u]) fatal("Allocation failed\n"); return u; } + +static Uint16 look_hash(Hash*tbl,int size,Uint16 minv,Uint16 maxv,Uint16 newv,const char*err) { + int h,i,m; + for(h=i=0;tokenstr[i];i++) h=(13*h+tokenstr[i])%size; + m=h; + for(;;) { + if(tbl[h].id>=minv && tbl[h].id<=maxv && !strcmp(tokenstr,tbl[h].txt)) return tbl[h].id; + if(!tbl[h].id) { + if(newv>maxv) ParseError("Too many %s\n",err); + tbl[h].txt=strdup(tokenstr); + if(!tbl[h].txt) ParseError("Out of string space in hash table\n"); + tbl[h].id=newv; + return 0; + } + h=(h+1)%size; + if(h==m) ParseError("Hash table full\n"); + } +} #define ReturnToken(x,y) do{ tokent=x; tokenv=y; return; }while(0) static void nxttok(void) { - int c,i; - int fl=0; - int n=0; - int pr=0; + int c,i,fl,n,pr; + fl=n=pr=0; tokent=tokenv=0; *tokenstr=0; again: c=fgetc(classfp); while(c==' ' || c=='\t' || c=='\r' || c=='\n') { @@ -260,17 +291,17 @@ tokent=TF_NAME; tokenv=0x0400; break; case '%': if(fl&TF_COMMA) ParseError("Invalid use of , in token\n"); - tokent=TF_NAME|fl; + tokent=TF_NAME|TF_ABNORMAL|fl; tokenv=OP_LOCAL; break; case '@': if(fl&TF_COMMA) ParseError("Invalid use of , in token\n"); tokent=TF_NAME|fl; - + tokenv=look_hash(glohash,HASH_SIZE,0x2800,0x2FFF,num_globals+0x2800,"user global variables")?:(num_globals++)+0x2800; break; case '#': if(fl) ParseError("Invalid use of , and = in token\n"); tokent=TF_NAME; tokenv=look_message_name()+0xC000; @@ -278,11 +309,13 @@ case ':': tokent=TF_NAME|TF_ABNORMAL|fl; tokenv=OP_LABEL; break; case '&': - + if(fl) ParseError("Invalid use of , and = in token\n"); + tokent=TF_FUNCTION|TF_ABNORMAL; + tokenv=look_hash(glohash,HASH_SIZE,0x8000,0xBFFF,num_functions,"user functions")?:(num_functions++)+0x8000; break; case '\'': if(fl) ParseError("Invalid use of , and = in token\n"); tokent=TF_NAME|TF_KEY; for(i=8;i<256;i++) { @@ -296,8 +329,31 @@ } } void load_classes(void) { int i; + char*nam=sqlite3_mprintf("%s.class",basefilename); + if(!nam) fatal("Allocation failed\n"); + classfp=fopen(nam,"r"); + sqlite3_free(nam); + if(!classfp) fatal("Cannot open class file '%s': %m\n",nam); + glohash=calloc(HASH_SIZE,sizeof(Hash)); + if(!glohash) fatal("Allocation failed\n"); + if(main_options['L']) { + for(;;) { + nxttok(); + printf("** %5d %04X %08X \"",linenum,tokent,tokenv); + for(i=0;tokenstr[i];i++) { + if(tokenstr[i]<32 || tokenstr[i]>126) printf("<%02X>",tokenstr[i]&255); + else putchar(tokenstr[i]); + } + printf("\"\n"); + if(Tokenf(TF_EOF)) goto done; + } + } + done: + fclose(classfp); + for(i=0;icflags&CF_NOCLASS1)) fatal("Class $%s mentioned but not defined",classes[i]->name); } Index: heromesh.h ================================================================== --- heromesh.h +++ heromesh.h @@ -31,10 +31,11 @@ extern sqlite3*userdb; extern xrm_db*resourcedb; extern const char*basefilename; extern xrm_quark optionquery[16]; extern Uint32 generation_number; +extern char main_options[128]; void set_cursor(int id); // == picture == Index: instruc ================================================================== --- instruc +++ instruc @@ -157,11 +157,11 @@ ,=KeyCleared ,=UserSignal ,=VisualOnly ,=Stealthy ,=Moved -,IsPlayer +,Player ,Compatible Self Msg From =Arg1 @@ -170,10 +170,11 @@ MoveNumber Level Key ; Class definitions +-Input -Quiz -InPlace -DefaultImage -Help -EditorHelp Index: instruc.h ================================================================== --- instruc.h +++ instruc.h @@ -229,12 +229,12 @@ #define OP_STEALTHY_EC 39006 #define OP_MOVED 32863 #define OP_MOVED_C 34911 #define OP_MOVED_E 36959 #define OP_MOVED_EC 39007 -#define OP_ISPLAYER 32864 -#define OP_ISPLAYER_C 34912 +#define OP_PLAYER 32864 +#define OP_PLAYER_C 34912 #define OP_COMPATIBLE 32865 #define OP_COMPATIBLE_C 34913 #define OP_SELF 32866 #define OP_MSG 32867 #define OP_FROM 32868 @@ -245,111 +245,112 @@ #define OP_ARG3 32871 #define OP_ARG3_E 36967 #define OP_MOVENUMBER 32872 #define OP_LEVEL 32873 #define OP_KEY 32874 -#define OP_QUIZ 32875 -#define OP_INPLACE 32876 -#define OP_DEFAULTIMAGE 32877 -#define OP_HELP 32878 -#define OP_EDITORHELP 32879 -#define OP_SUBS 32880 -#define OP_ANIMATE 32881 -#define OP_ASSASSINATE 32882 -#define OP_ASSASSINATE_C 34930 -#define OP_BROADCAST 32883 -#define OP_BROADCAST_D 41075 -#define OP_BROADCASTCLASS 32884 -#define OP_BROADCASTEX 32885 -#define OP_BROADCASTEX_D 41077 -#define OP_BROADCASTSUM 32886 -#define OP_BROADCASTSUMEX 32887 -#define OP_CREATE 32888 -#define OP_CREATE_D 41080 -#define OP_DELINVENTORY 32889 -#define OP_DELTA 32890 -#define OP_DESTROY 32891 -#define OP_DESTROY_C 34939 -#define OP_DESTROY_D 41083 -#define OP_DESTROY_CD 43131 -#define OP_FLUSHCLASS 32892 -#define OP_FLUSHOBJ 32893 -#define OP_GETINVENTORY 32894 -#define OP_HEIGHTAT 32895 -#define OP_IGNOREKEY 32896 -#define OP_INTMOVE 32897 -#define OP_INTMOVE_C 34945 -#define OP_INTMOVE_D 41089 -#define OP_INTMOVE_CD 43137 -#define OP_JUMPTO 32898 -#define OP_JUMPTO_C 34946 -#define OP_LOC 32899 -#define OP_LOC_C 34947 -#define OP_LOCATEME 32900 -#define OP_LOSELEVEL 32901 -#define OP_MAXINVENTORY 32902 -#define OP_MOVE 32903 -#define OP_MOVE_C 34951 -#define OP_MOVE_D 41095 -#define OP_MOVE_CD 43143 -#define OP_MOVEPLUS 32904 -#define OP_MOVEPLUS_C 34952 -#define OP_MOVEPLUS_D 41096 -#define OP_MOVEPLUS_CD 43144 -#define OP_MOVETO 32905 -#define OP_MOVETO_C 34953 -#define OP_MOVETO_D 41097 -#define OP_MOVETO_CD 43145 -#define OP_NEWX 32906 -#define OP_NEWY 32907 -#define OP_OBJABOVE 32908 -#define OP_OBJABOVE_C 34956 -#define OP_OBJCLASSAT 32909 -#define OP_OBJBELOW 32910 -#define OP_OBJBELOW_C 34958 -#define OP_OBJDIR 32911 -#define OP_OBJDIR_C 34959 -#define OP_POPUP 32912 -#define OP_POPUPARGS 32913 -#define OP_QUEUETURN 32914 -#define OP_SEND 32915 -#define OP_SEND_C 34963 -#define OP_SEND_D 41107 -#define OP_SEND_CD 43155 -#define OP_SENDEX 32916 -#define OP_SENDEX_C 34964 -#define OP_SENDEX_D 41108 -#define OP_SENDEX_CD 43156 -#define OP_SETINVENTORY 32917 -#define OP_SOUND 32918 -#define OP_TRACE 32919 -#define OP_VOLUMEAT 32920 -#define OP_WINLEVEL 32921 -#define OP_XDIR 32922 -#define OP_XDIR_C 34970 -#define OP_YDIR 32923 -#define OP_YDIR_C 34971 -#define OP_FUNCTION 32924 -#define OP_LOCAL 32925 -#define OP_LABEL 32926 -#define OP_STRING 32927 +#define OP_INPUT 32875 +#define OP_QUIZ 32876 +#define OP_INPLACE 32877 +#define OP_DEFAULTIMAGE 32878 +#define OP_HELP 32879 +#define OP_EDITORHELP 32880 +#define OP_SUBS 32881 +#define OP_ANIMATE 32882 +#define OP_ASSASSINATE 32883 +#define OP_ASSASSINATE_C 34931 +#define OP_BROADCAST 32884 +#define OP_BROADCAST_D 41076 +#define OP_BROADCASTCLASS 32885 +#define OP_BROADCASTEX 32886 +#define OP_BROADCASTEX_D 41078 +#define OP_BROADCASTSUM 32887 +#define OP_BROADCASTSUMEX 32888 +#define OP_CREATE 32889 +#define OP_CREATE_D 41081 +#define OP_DELINVENTORY 32890 +#define OP_DELTA 32891 +#define OP_DESTROY 32892 +#define OP_DESTROY_C 34940 +#define OP_DESTROY_D 41084 +#define OP_DESTROY_CD 43132 +#define OP_FLUSHCLASS 32893 +#define OP_FLUSHOBJ 32894 +#define OP_GETINVENTORY 32895 +#define OP_HEIGHTAT 32896 +#define OP_IGNOREKEY 32897 +#define OP_INTMOVE 32898 +#define OP_INTMOVE_C 34946 +#define OP_INTMOVE_D 41090 +#define OP_INTMOVE_CD 43138 +#define OP_JUMPTO 32899 +#define OP_JUMPTO_C 34947 +#define OP_LOC 32900 +#define OP_LOC_C 34948 +#define OP_LOCATEME 32901 +#define OP_LOSELEVEL 32902 +#define OP_MAXINVENTORY 32903 +#define OP_MOVE 32904 +#define OP_MOVE_C 34952 +#define OP_MOVE_D 41096 +#define OP_MOVE_CD 43144 +#define OP_MOVEPLUS 32905 +#define OP_MOVEPLUS_C 34953 +#define OP_MOVEPLUS_D 41097 +#define OP_MOVEPLUS_CD 43145 +#define OP_MOVETO 32906 +#define OP_MOVETO_C 34954 +#define OP_MOVETO_D 41098 +#define OP_MOVETO_CD 43146 +#define OP_NEWX 32907 +#define OP_NEWY 32908 +#define OP_OBJABOVE 32909 +#define OP_OBJABOVE_C 34957 +#define OP_OBJCLASSAT 32910 +#define OP_OBJBELOW 32911 +#define OP_OBJBELOW_C 34959 +#define OP_OBJDIR 32912 +#define OP_OBJDIR_C 34960 +#define OP_POPUP 32913 +#define OP_POPUPARGS 32914 +#define OP_QUEUETURN 32915 +#define OP_SEND 32916 +#define OP_SEND_C 34964 +#define OP_SEND_D 41108 +#define OP_SEND_CD 43156 +#define OP_SENDEX 32917 +#define OP_SENDEX_C 34965 +#define OP_SENDEX_D 41109 +#define OP_SENDEX_CD 43157 +#define OP_SETINVENTORY 32918 +#define OP_SOUND 32919 +#define OP_TRACE 32920 +#define OP_VOLUMEAT 32921 +#define OP_WINLEVEL 32922 +#define OP_XDIR 32923 +#define OP_XDIR_C 34971 +#define OP_YDIR 32924 +#define OP_YDIR_C 34972 +#define OP_FUNCTION 32925 +#define OP_LOCAL 32926 +#define OP_LABEL 32927 +#define OP_STRING 32928 #ifdef HEROMESH_CLASS static const Op_Names op_names[]={ {"*",8486933}, {"+",8421395}, {"-",8421396}, {".",10518528}, {"/",8486934}, {"ANHH",8389394}, {"ARRIVED",8389124}, -{"Animate",8421489}, +{"Animate",8421490}, {"Arg1",8552549}, {"Arg2",8552550}, {"Arg3",8552551}, {"Arrivals",8618071}, {"Arrived",8618069}, -{"Assassinate",8487026}, +{"Assassinate",8487027}, {"B",9437196}, {"BANG",8389380}, {"BEDOINGNG",8389406}, {"BEEDEEP",8389404}, {"BEGIN_TURN",8389123}, @@ -357,14 +358,14 @@ {"BOUNCE",8389415}, {"BRRREEET",8389396}, {"BRRRT",8389395}, {"BUZZER",8389420}, {"BWEEP",8389397}, -{"Broadcast",10518643}, -{"BroadcastEx",10518645}, -{"BroadcastSum",8421494}, -{"BroadcastSumEx",8421495}, +{"Broadcast",10518644}, +{"BroadcastEx",10518646}, +{"BroadcastSum",8421495}, +{"BroadcastSumEx",8421496}, {"Busy",8618073}, {"CHEEP",8389393}, {"CHYEW",8389392}, {"CLEANUP",8389140}, {"CLICK",8389388}, @@ -373,61 +374,61 @@ {"CREATE",8389121}, {"CREATED",8389137}, {"Class",8486955}, {"Climb",9142335}, {"Compatible",8487009}, -{"Create",10518648}, +{"Create",10518649}, {"DEEP_POP",8389417}, {"DEPARTED",8389125}, {"DESTROY",8389122}, {"DESTROYED",8389136}, {"DINK",8389390}, {"DOOR",8389378}, {"DRLRLRINK",8389398}, {"DYUPE",8389413}, -{"DefaultImage",8683629}, -{"DelInventory",8421497}, -{"Delta",8421498}, +{"DefaultImage",8683630}, +{"DelInventory",8421498}, +{"Delta",8421499}, {"Density",9142327}, {"Departed",8618070}, {"Departures",8618072}, -{"Destroy",10584187}, +{"Destroy",10584188}, {"Dir",8618033}, {"Distance",9142325}, {"E",9437184}, {"END_TURN",8389139}, -{"EditorHelp",8683631}, +{"EditorHelp",8683632}, {"F",9437192}, {"FAROUT",8389421}, {"FFFFTT",8389399}, {"FLOATED",8389132}, {"FROG",8389383}, -{"FlushClass",8421500}, -{"FlushObj",8421501}, +{"FlushClass",8421501}, +{"FlushObj",8421502}, {"From",8421476}, {"GLASS",8389379}, {"GLISSANT",8389419}, -{"GetInventory",8421502}, +{"GetInventory",8421503}, {"HAWK",8389425}, {"HEARTBEAT",8389407}, {"HIT",8389134}, {"HITBY",8389135}, {"Hard",8618051}, {"Height",9142333}, -{"HeightAt",8421503}, -{"Help",8683630}, +{"HeightAt",8421504}, +{"Help",8683631}, {"INIT",8389120}, -{"IgnoreKey",8421504}, +{"IgnoreKey",8421505}, {"Image",8618034}, -{"InPlace",8683628}, +{"InPlace",8683629}, {"Inertia",9142323}, -{"IntMove",10584193}, +{"Input",8683627}, +{"IntMove",10584194}, {"Invisible",8618074}, -{"IsPlayer",8487008}, {"JAYAYAYNG",8389416}, {"JUMPED",8389128}, -{"JumpTo",8487042}, +{"JumpTo",8487043}, {"KEWEL",8389422}, {"KEY",8389129}, {"KLECK",8389387}, {"KLINKK",8389385}, {"Key",8421482}, @@ -437,49 +438,50 @@ {"LB",9437195}, {"LF",9437193}, {"LOCK",8389408}, {"LOOP",8388610}, {"Level",8421481}, -{"Loc",8487043}, -{"LocateMe",8421508}, -{"LoseLevel",8421509}, +{"Loc",8487044}, +{"LocateMe",8421509}, +{"LoseLevel",8421510}, {"MOVED",8389127}, {"MOVING",8389130}, -{"MaxInventory",8421510}, +{"MaxInventory",8421511}, {"Misc1",9142343}, {"Misc2",9142345}, {"Misc3",9142347}, {"Misc4",9142349}, {"Misc5",9142351}, {"Misc6",9142353}, {"Misc7",9142355}, -{"Move",10584199}, -{"Move+",10584200}, +{"Move",10584200}, +{"Move+",10584201}, {"MoveNumber",8421480}, -{"MoveTo",10584201}, +{"MoveTo",10584202}, {"Moved",8618079}, {"Msg",8421475}, {"N",9437186}, {"NE",9437185}, {"NW",9437187}, -{"NewX",8421514}, -{"NewY",8421515}, +{"NewX",8421515}, +{"NewY",8421516}, {"OLDPHONE",8389402}, {"ONCE",8388609}, {"OSC",8388616}, {"OSCLOOP",8388618}, -{"ObjAbove",8487052}, -{"ObjBelow",8487054}, -{"ObjClassAt",8421517}, -{"ObjDir",8487055}, +{"ObjAbove",8487053}, +{"ObjBelow",8487055}, +{"ObjClassAt",8421518}, +{"ObjDir",8487056}, {"PLAYERMOVING",8389133}, {"POSTINIT",8389138}, {"POUR",8389377}, {"POWER",8389386}, -{"PopUp",8421520}, -{"QueueTurn",8421522}, -{"Quiz",8683627}, +{"Player",8487008}, +{"PopUp",8421521}, +{"QueueTurn",8421523}, +{"Quiz",8683628}, {"R",9437198}, {"RATCHET1",8389418}, {"RATCHET2",8389412}, {"RATTLE",8389403}, {"RB",9437197}, @@ -488,46 +490,46 @@ {"SE",9437191}, {"SMALL_POP",8389389}, {"SPLASH",8389376}, {"STEAM",8389424}, {"STOP",8388608}, -{"SUBS",8683632}, +{"SUBS",8683633}, {"SUNK",8389131}, {"SW",9437189}, {"Self",8421474}, -{"Send",10584211}, -{"SendEx",10584212}, -{"SetInventory",8421525}, +{"Send",10584212}, +{"SendEx",10584213}, +{"SetInventory",8421526}, {"Shape",8618030}, {"ShapeDir",8618053}, {"Sharp",8618052}, {"Shovable",8618054}, -{"Sound",8421526}, +{"Sound",8421527}, {"Stealthy",8618078}, {"Strength",9142337}, {"TAHTASHH",8389409}, {"THMP_thmp",8389405}, {"THWIT",8389384}, {"TICK",8389391}, {"Temperature",9142316}, -{"Trace",8421527}, +{"Trace",8421528}, {"UH_OH",8389382}, {"UNCORK",8389414}, {"UNHH",8389381}, {"UserSignal",8618076}, {"VACUUM",8389411}, {"VisualOnly",8618077}, {"Volume",9142329}, -{"VolumeAt",8421528}, +{"VolumeAt",8421529}, {"W",9437188}, {"WAHOO",8389400}, {"WHACK",8389423}, {"Weight",9142331}, -{"WinLevel",8421529}, -{"XDir",8487066}, +{"WinLevel",8421530}, +{"XDir",8487067}, {"Xloc",8486959}, -{"YDir",8487067}, +{"YDir",8487068}, {"YEEHAW",8389401}, {"Yloc",8486960}, {"again",8683530}, {"band",8421403}, {"begin",8683529}, @@ -595,7 +597,7 @@ {"then",8683527}, {"tuck",8421380}, {"until",8683531}, {"while",8683532}, }; -#define N_OP_NAMES 262 +#define N_OP_NAMES 263 #endif Index: main.c ================================================================== --- main.c +++ main.c @@ -35,18 +35,18 @@ sqlite3*userdb; xrm_db*resourcedb; const char*basefilename; xrm_quark optionquery[16]; Uint32 generation_number; +char main_options[128]; static const char*globalclassname; static SDL_Cursor*cursor[77]; static FILE*levelfp; static FILE*solutionfp; static FILE*hamarc_fp; static long hamarc_pos; -static char main_options[128]; static void hamarc_begin(FILE*fp,const char*name) { while(*name) fputc(*name++,fp); fwrite("\0\0\0\0",1,5,hamarc_fp=fp); hamarc_pos=ftell(fp); @@ -285,8 +285,9 @@ load_pictures(); if(main_options['T']) { test_mode(); return 0; } + load_classes(); return 0; } Index: mbtofhm.c ================================================================== --- mbtofhm.c +++ mbtofhm.c @@ -416,11 +416,11 @@ static void class_codes(FILE*fp,const unsigned char*op,int ofs,const unsigned char*lbl,int nlbl,const unsigned char*subs,int nsubs,unsigned char*vars) { static const char*const stdvars[256]={ [0]="Class","Temperature","Shape", [4]="Xloc","Yloc","Dir","Image","Inertia","Misc1","Misc2","Misc3","Misc4","Misc5","Misc6","Misc7", [16]="Arrived","Departed","Arrivals","Departures", - [32]="Busy","Invisible","UserSignal","UserState","KeyCleared","IsPlayer","Destroyed","Stealthy","VisualOnly", + [32]="Busy","Invisible","UserSignal","UserState","KeyCleared","Player","Destroyed","Stealthy","VisualOnly", [48]="Msg","From","Arg1","Arg2", [64]="Density","Volume","Strength","Weight","Distance","Height","Climb", [72]="Hard","Hard","Hard","Hard","Sharp","Sharp","Sharp","Sharp","ShapeDir","ShapeDir","ShapeDir","ShapeDir", [84]="Shovable", };