Index: heromesh.h ================================================================== --- heromesh.h +++ heromesh.h @@ -1,31 +1,55 @@ /* This file is part of Free Hero Mesh and is public domain. */ -// main.c +// == main == + +#define fatal(...) do{ fprintf(stderr,__VA_ARGS__); exit(1); }while(0) +#define boolxrm(a,b) (*a=='1'||*a=='y'||*a=='t'||*a=='Y'||*a=='T'?1:*a=='0'||*a=='n'||*a=='f'||*a=='N'||*a=='F'?0:b) + +#define TY_NUMBER 0 +#define TY_CLASS 1 +#define TY_MESSAGE 2 +#define TY_SOUND 3 +#define TY_USOUND 4 +#define TY_STRING 5 +#define TY_LEVELSTRING 6 +#define TY_MAXTYPE 15 + +typedef struct { + union { + Sint32 s; + Uint32 u; + }; + Uint32 t; // Type 0-15, or a generation_number of an object +} Value; extern sqlite3*userdb; extern xrm_db*resourcedb; extern const char*basefilename; extern xrm_quark optionquery[16]; +extern Uint32 generation_number; + +void set_cursor(int id); -// picture.c +// == picture == extern SDL_Surface*screen; extern Uint16 picture_size; void draw_picture(int x,int y,Uint16 img); void draw_text(int x,int y,const unsigned char*t,int bg,int fg); void load_pictures(void); -// class.c +// == class == #define CF_PLAYER 0x01 #define CF_INPUT 0x02 #define CF_COMPATIBLE 0x04 #define CF_QUIZ 0x08 +#define CF_GROUP 0x10 // this is a group of classes; you can't create an object of this class #define CF_NOCLASS1 0x40 // if only the name has been loaded so far, from the .class file #define CF_NOCLASS2 0x80 // if only the name has been loaded so far, from the CLASS.DEF lump #define OF_INVISIBLE 0x0001 #define OF_VISUALONLY 0x0002 @@ -38,23 +62,23 @@ #define OF_KEYCLEARED 0x0100 #define OF_DESTROYED 0x0200 typedef struct { const char*name; - const char*edithelp; - const char*gamehelp; - Uint16*codes; - Uint16*messages; // use 0xFFFF if no such message block - Uint16*images; // high bit is set if available to editor + const char*edithelp; // not present if CF_GROUP + const char*gamehelp; // not present if CF_GROUP + Uint16*codes; // if this is CF_GROUP, then instead a zero-terminated list of classes + Uint16*messages; // use 0xFFFF if no such message block; not present if CF_GROUP + Uint16*images; // high bit is set if available to editor; not present if CF_GROUP Sint32 height,weight,climb,density,volume,strength,arrivals,departures; Sint32 temperature,misc4,misc5,misc6,misc7; Uint16 uservars,oflags; Uint16 sharp[4]; Uint16 hard[4]; Uint8 cflags,shape,shovable; } Class; extern Class*classes[0x4000]; // 0 isn't used -extern const char*messages[0x4000]; -extern int max_animation; -extern Sint32 max_volume; +extern const char*messages[0x4000]; // index is 256 less than message number +extern int max_animation; // max steps in animation queue +extern Sint32 max_volume; // max total volume to allow moving diagonally (default 10000) Index: main.c ================================================================== --- main.c +++ main.c @@ -38,35 +38,36 @@ typedef struct { UserCommand m[16]; } KeyBinding; static const char schema[]= + "BEGIN;" "PRAGMA APPLICATION_ID(1296388936);" "PRAGMA RECURSIVE_TRIGGERS(1);" "CREATE TABLE IF NOT EXISTS `USERCACHEINDEX`(`ID` INTEGER PRIMARY KEY, `NAME` TEXT, `TIME` INT);" "CREATE TEMPORARY TABLE `PICTURES`(`ID` INTEGER PRIMARY KEY, `NAME` TEXT, `OFFSET` INT);" + "COMMIT;" ; sqlite3*userdb; xrm_db*resourcedb; const char*basefilename; xrm_quark optionquery[16]; +Uint32 generation_number; 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 KeyBinding*editor_bindings[SDLK_LAST]; static KeyBinding*game_bindings[SDLK_LAST]; static KeyBinding*editor_mouse_bindings[4]; static KeyBinding*game_mouse_bindings[4]; -#define fatal(...) do{ fprintf(stderr,__VA_ARGS__); exit(1); }while(0) -#define boolxrm(a,b) (*a=='1'||*a=='y'||*a=='t'||*a=='Y'||*a=='T'?1:*a=='0'||*a=='n'||*a=='f'||*a=='N'||*a=='F'?0:b) - 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); } @@ -131,11 +132,11 @@ optionquery[1]=Q_sqlInit; v=xrm_get_resource(resourcedb,optionquery,optionquery,2); if(v && sqlite3_exec(userdb,v,0,0,&s)) fatal("Failed to execute user-defined SQL statements (%s)\n",s?:"unknown error"); } -static void set_cursor(int id) { +void set_cursor(int id) { id>>=1; if(!cursor[id]) cursor[id]=SDL_CreateCursor((void*)cursorimg+(id<<6),(void*)cursorimg+(id<<6)+32,16,16,cursorhot[id]>>4,cursorhot[id]&15); SDL_SetCursor(cursor[id]); } @@ -276,28 +277,96 @@ optionquery[2]=Q_alt; SetMouseBinding(SDL_BUTTON_RIGHT,4,MOD_ALT); optionquery[2]=Q_meta; SetMouseBinding(SDL_BUTTON_RIGHT,4,MOD_META); } + +static int test_sql_callback(void*usr,int argc,char**argv,char**name) { + int i; + if(argc) printf("%s",*argv); + for(i=1;ioptind && argv[optind][0]=='-') { + int i; + const char*s=argv[optind++]; + if(s[1]=='-' && !s[2]) break; + for(i=1;s[i];i++) main_options[s[i]&127]=1; + } + if(argc<=optind) fatal("usage: %s [switches] [--] basename [options...]\n",argc?argv[0]:"heromesh"); if(xrm_init(realloc)) fatal("Failed to initialize resource manager\n"); if(xrm_init_quarks(global_quarks)) fatal("Failed to initialize resource manager\n"); resourcedb=xrm_create(); if(!resourcedb) fatal("Allocation of resource database failed\n"); - basefilename=argv[1]; - if(argc>2 && argv[1][0]=='=') { - globalclassname=argv[2]+1; - ++argv; --argc; + basefilename=argv[optind++]; + if(argc>optind && argv[1][0]=='=') { + globalclassname=argv[optind++]+1; } else if(find_globalclassname()) { globalclassname=strrchr(basefilename,'/'); globalclassname=globalclassname?globalclassname+1:basefilename; } load_options(); - if(argc>2) read_options(argc-2,argv+2); + if(argc>optind) read_options(argc-optind,argv+optind); *optionquery=xrm_make_quark(globalclassname,0)?:xrm_anyq; init_sql(); init_screen(); + load_pictures(); + if(main_options['T']) { + test_mode(); + return 0; + } return 0; } Index: picture.c ================================================================== --- picture.c +++ picture.c @@ -17,12 +17,10 @@ #include "smallxrm.h" #include "pcfont.h" #include "quarks.h" #include "heromesh.h" -#define fatal(...) do{ fprintf(stderr,__VA_ARGS__); exit(1); }while(0) - SDL_Surface*screen; Uint16 picture_size; static SDL_Surface*picts; static Uint8*curpic; @@ -102,17 +100,19 @@ if(x+8*len>screen->w) len=(screen->w-x)>>3; if(len<=0 || y+8>screen->h) return; pix+=y*pitch+x; while(*t) { f=fontdata+(*t<<3); + p=pix; for(yy=0;yy<8;yy++) { for(xx=0;xx<8;xx++) p[xx]=(*f<4 && !memcmp(".IMG",nam+i-4,4)) { j=1; if(n++==32768) fatal("Too many pictures\n"); sqlite3_reset(st); sqlite3_bind_int(st,1,n); - sqlite3_bind_text(st,2,nam,i,SQLITE_TRANSIENT); + sqlite3_bind_text(st,2,nam,i-4,SQLITE_TRANSIENT); sqlite3_bind_int64(st,3,ftell(fp)+4); while((i=sqlite3_step(st))==SQLITE_ROW); if(i!=SQLITE_DONE) fatal("SQL error (%d): %s\n",i,sqlite3_errmsg(userdb)); } else { j=0; @@ -321,6 +321,14 @@ case 'y': i|=SDL_ASYNCBLIT; break; } if(!(i&SDL_HWSURFACE)) i|=SDL_SWSURFACE; screen=SDL_SetVideoMode(w,h,8,i); if(!screen) fatal("Failed to initialize screen mode: %s\n",SDL_GetError()); + optionquery[1]=Q_keyRepeat; + if(v=xrm_get_resource(resourcedb,optionquery,optionquery,2)) { + w=strtol(v,(void*)&v,10); + h=strtol(v,0,10); + SDL_EnableKeyRepeat(w,h); + } else { + SDL_EnableKeyRepeat(SDL_DEFAULT_REPEAT_DELAY,SDL_DEFAULT_REPEAT_INTERVAL); + } } Index: quarks ================================================================== --- quarks +++ quarks @@ -202,6 +202,9 @@ sqlExtensions sqlMemStatus sqlSmallAllocations sqlCoveringIndexScan sqlPowerSafe + +! Miscellaneous +level Index: quarks.h ================================================================== --- quarks.h +++ quarks.h @@ -169,10 +169,11 @@ #define Q_sqlExtensions 170 #define Q_sqlMemStatus 171 #define Q_sqlSmallAllocations 172 #define Q_sqlCoveringIndexScan 173 #define Q_sqlPowerSafe 174 +#define Q_level 175 static const char*const global_quarks[]={ "screenWidth", "screenHeight", "palette", "popupColors", @@ -343,10 +344,11 @@ "sqlExtensions", "sqlMemStatus", "sqlSmallAllocations", "sqlCoveringIndexScan", "sqlPowerSafe", + "level", 0}; #ifdef HEROMESH_MAIN static const SDLKey quark_to_key[Q_undo+1-Q_backspace]={ SDLK_BACKSPACE, SDLK_TAB,