Free Hero Mesh

Check-in [c8eb0a9e48]
Login
This is a mirror of the main repository for Free Hero Mesh. New tickets and changes will not be accepted at this mirror.
Overview
Comment:Faster key bindings, and testing for key bindings
Downloads: Tarball | ZIP archive | SQL archive
Timelines: family | ancestors | descendants | both | trunk
Files: files | file ages | folders
SHA1: c8eb0a9e48179384fa609872f676061490be486a
User & Date: user on 2018-04-09 04:15:17
Other Links: manifest | tags
Context
2018-04-09
16:36
Add "FATAL" to fatal error messages check-in: e345d1a7d7 user: user tags: trunk
04:15
Faster key bindings, and testing for key bindings check-in: c8eb0a9e48 user: user tags: trunk
2018-04-08
23:31
Types, bug fixes, and test mode check-in: 3df78ec087 user: user tags: trunk
Changes

Added bindings.c version [4c842f9721].































































































































































































































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
#if 0
gcc -s -O2 -c -Wno-unused-result bindings.c `sdl-config --cflags`
exit
#endif

/*
  This program is part of Free Hero Mesh and is public domain.
*/

#define HEROMESH_BINDINGS
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "SDL.h"
#include "sqlite3.h"
#include "smallxrm.h"
#include "quarks.h"
#include "heromesh.h"

#define MOD_SHIFT 1
#define MOD_CTRL 2
#define MOD_ALT 4
#define MOD_META 8
#define MOD_NUMLOCK 14
typedef struct {
  UserCommand m[16];
} KeyBinding;

static KeyBinding*editor_bindings[SDLK_LAST];
static KeyBinding*game_bindings[SDLK_LAST];
static KeyBinding*editor_mouse_bindings[4];
static KeyBinding*game_mouse_bindings[4];
static int cur_modifiers,loose_modifiers;

static void set_binding(KeyBinding**pkb,int mod,const char*txt) {
  int i;
  KeyBinding*kb=*pkb;
  UserCommand*uc;
  if(!*txt) return;
  if(!kb) kb=*pkb=calloc(1,sizeof(KeyBinding));
  if(!kb) fatal("Allocation failed\n");
  uc=kb->m+mod;
  if(uc->cmd) return;
  switch(*txt) {
    case '^': // Miscellaneous
      uc->cmd='^';
      uc->n=txt[1];
      break;
    case '=': case '-': case '+': // Restart, rewind, advance
      uc->cmd=*txt;
      uc->n=strtol(txt+1,0,0);
      break;
    case '\'': // Input move
      uc->cmd='\'';
      for(i=1;i<256;i++) if(heromesh_key_names[i] && !strcmp(txt+1,heromesh_key_names[i])) {
        uc->n=i;
        return;
      }
      fatal("Error in key binding:  %s\nInvalid Hero Mesh key name\n",txt);
      break;
    case '!': // System command
      uc->cmd='!';
      uc->txt=txt+1;
      break;
    case 'A' ... 'Z': case 'a' ... 'z': // Execute SQL statement
      uc->cmd='s';
      if(i=sqlite3_prepare_v3(userdb,txt,-1,SQLITE_PREPARE_PERSISTENT,&uc->stmt,0)) fatal("Error in key binding:  %s\n%s\n",txt,sqlite3_errmsg(userdb));
      break;
    default:
      fatal("Error in key binding:  %s\nUnrecognized character\n",txt);
  }
}

#define BINDING_MODIFIER(a,b) \
  if(q==a && !(cur_modifiers&b)) { \
    cur_modifiers|=b; \
    xrm_enumerate(sub,cb_2,usr); \
    cur_modifiers&=~b; \
    if(loose) --loose_modifiers; \
    return 0; \
  }

static void*cb_2(xrm_db*db,void*usr,int loose,xrm_quark q) {
  KeyBinding**kb=usr;
  const char*txt;
  xrm_db*sub=xrm_sub(db,loose,q);
  if(loose) ++loose_modifiers;
  BINDING_MODIFIER(Q_shift,MOD_SHIFT);
  BINDING_MODIFIER(Q_ctrl,MOD_CTRL);
  BINDING_MODIFIER(Q_alt,MOD_ALT);
  BINDING_MODIFIER(Q_meta,MOD_META);
  BINDING_MODIFIER(Q_numLock,MOD_NUMLOCK);
  if(txt=xrm_get(sub)) {
    if(usr==editor_mouse_bindings || usr==game_mouse_bindings) {
      switch(q) {
        case Q_left: kb+=SDL_BUTTON_LEFT; break;
        case Q_middle: kb+=SDL_BUTTON_MIDDLE; break;
        case Q_right: kb+=SDL_BUTTON_RIGHT; break;
        default: goto stop;
      }
    } else {
      if(q>=FirstKeyQuark && q<=LastKeyQuark) kb+=quark_to_key[q-FirstKeyQuark]; else goto stop;
    }
    set_binding(kb,cur_modifiers,txt);
    if(loose_modifiers) {
      int i;
      for(i=0;i<16;i++) if((i&cur_modifiers)==cur_modifiers && !kb[0]->m[i].cmd) kb[0]->m[i]=kb[0]->m[cur_modifiers];
    }
  }
stop:
  if(loose) --loose_modifiers;
  return 0;
}

static void*cb_1(xrm_db*db,void*usr) {
  xrm_enumerate(db,cb_2,usr);
  return 0;
}

void load_key_bindings(void) {
  fprintf(stderr,"Loading key bindings...\n");
  cur_modifiers=loose_modifiers=0;
  optionquery[1]=Q_editKey;
  xrm_search(resourcedb,optionquery,optionquery,2,cb_1,editor_bindings);
  optionquery[1]=Q_gameKey;
  xrm_search(resourcedb,optionquery,optionquery,2,cb_1,game_bindings);
  optionquery[1]=Q_editClick;
  xrm_search(resourcedb,optionquery,optionquery,2,cb_1,editor_mouse_bindings);
  optionquery[1]=Q_gameClick;
  xrm_search(resourcedb,optionquery,optionquery,2,cb_1,game_mouse_bindings);
  fprintf(stderr,"Done\n");
}

const UserCommand*find_key_binding(SDL_Event*ev,int editing) {
  KeyBinding*kb;
  static const UserCommand nul={cmd:0};
  SDLMod m;
  int i;
  if(ev->type==SDL_KEYDOWN) {
    m=ev->key.keysym.mod;
    if(ev->key.keysym.sym>=SDLK_LAST) return &nul;
    kb=(editing?editor_bindings:game_bindings)[ev->key.keysym.sym];
  } else if(ev->type==SDL_MOUSEBUTTONDOWN) {
    m=SDL_GetModState();
    if(ev->button.button>3) return &nul;
    kb=(editing?editor_mouse_bindings:game_mouse_bindings)[ev->button.button];
  } else {
    return &nul;
  }
  if(!kb) return &nul;
  i=0;
  if(m&KMOD_CTRL) i|=MOD_CTRL;
  if(m&KMOD_SHIFT) i|=MOD_SHIFT;
  if(m&KMOD_ALT) i|=MOD_ALT;
  if(m&KMOD_META) i|=MOD_META;
  if((m&KMOD_NUM) && kb->m[i|MOD_NUMLOCK].cmd) i|=MOD_NUMLOCK;
  return kb->m+i;
}

Modified heromesh.h from [0f695d01fc] to [25255b4793].

20
21
22
23
24
25
26




27
28
29
30
31
32
33
  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);







>
>
>
>







20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
  union {
    Sint32 s;
    Uint32 u;
  };
  Uint32 t; // Type 0-15, or a generation_number of an object
} Value;

extern const char*const standard_message_names[];
extern const char*const standard_sound_names[];
extern const char*const heromesh_key_names[256];

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);
78
79
80
81
82
83
84














} Class;

extern Class*classes[0x4000]; // 0 isn't used
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)






















>
>
>
>
>
>
>
>
>
>
>
>
>
>
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
} Class;

extern Class*classes[0x4000]; // 0 isn't used
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)

// == bindings ==

typedef struct {
  char cmd;
  union {
    int n;
    sqlite3_stmt*stmt;
    const char*txt;
  };
} UserCommand;

void load_key_bindings(void);
const UserCommand*find_key_binding(SDL_Event*ev,int editing);

Modified main.c from [9c681f49a8] to [76acffeba5].

1
2
3
4
5
6
7
8
9
#if 0
gcc -s -O2 -o ~/bin/heromesh main.c picture.o smallxrm.o sqlite3.o `sdl-config --cflags --libs` -ldl -lpthread
exit
#endif

/*
  This program is part of Free Hero Mesh and is public domain.
*/


|







1
2
3
4
5
6
7
8
9
#if 0
gcc -s -O2 -o ~/bin/heromesh main.c picture.o bindings.o smallxrm.o sqlite3.o `sdl-config --cflags --libs` -ldl -lpthread
exit
#endif

/*
  This program is part of Free Hero Mesh and is public domain.
*/

17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
#include "sqlite3.h"
#include "smallxrm.h"
#include "names.h"
#include "quarks.h"
#include "cursorshapes.h"
#include "heromesh.h"

typedef struct {
  char cmd;
  union {
    int n;
    sqlite3_stmt*stmt;
    const char*txt;
  };
} UserCommand;

#define MOD_SHIFT 1
#define MOD_CTRL 2
#define MOD_ALT 4
#define MOD_META 8
#define MOD_NUMLOCK 14
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;"







<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<







17
18
19
20
21
22
23


















24
25
26
27
28
29
30
#include "sqlite3.h"
#include "smallxrm.h"
#include "names.h"
#include "quarks.h"
#include "cursorshapes.h"
#include "heromesh.h"



















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;"
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
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];

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);
}








<
<
<
<







39
40
41
42
43
44
45




46
47
48
49
50
51
52
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);
}

168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292

293
294

295
296
297
298
299
300
301
  s=malloc(256);
  if(!s) fatal("Allocation failed\n");
  if(fscanf(fp," %255s",s)!=1) fatal("Unable to scan name of class set\n");
  globalclassname=s;
  return !*s;
}

static void set_key_binding(KeyBinding**pkb,int mod,const char*txt) {
  int i;
  KeyBinding*kb=*pkb;
  UserCommand*uc;
  if(!*txt) return;
  if(!kb) kb=*pkb=calloc(1,sizeof(KeyBinding));
  uc=kb->m+mod;
  switch(*txt) {
    case '^': // Miscellaneous
      uc->cmd='^';
      uc->n=txt[1];
      break;
    case '=': case '-': case '+': // Restart, rewind, advance
      uc->cmd=*txt;
      uc->n=strtol(txt+1,0,0);
      break;
    case '\'': // Input move
      uc->cmd='\'';
      for(i=1;i<256;i++) if(heromesh_key_names[i] && !strcmp(txt+1,heromesh_key_names[i])) {
        uc->n=i;
        return;
      }
      fatal("Error in key binding:  %s\nInvalid Hero Mesh key name\n",txt);
      break;
    case '!': // System command
      uc->cmd='!';
      uc->txt=txt+1;
      break;
    case 'A' ... 'Z': case 'a' ... 'z': // Execute SQL statement
      uc->cmd='s';
      if(i=sqlite3_prepare_v3(userdb,txt+1,-1,SQLITE_PREPARE_PERSISTENT,&uc->stmt,0)) fatal("Error in key binding:  %s\n%s\n",txt,sqlite3_errmsg(userdb));
      break;
    default:
      fatal("Error in key binding:  %s\nUnrecognized character\n",txt);
  }
}

#define SetKeyBinding(n,m) do { \
  optionquery[1]=Q_editKey; \
  if(s=xrm_get_resource(resourcedb,optionquery,optionquery,n)) set_key_binding(editor_bindings+quark_to_key[q-FirstKeyQuark],m,s); \
  optionquery[1]=Q_gameKey; \
  if(s=xrm_get_resource(resourcedb,optionquery,optionquery,n)) set_key_binding(game_bindings+quark_to_key[q-FirstKeyQuark],m,s); \
} while(0)
#define SetMouseBinding(o,n,m) do { \
  optionquery[1]=Q_editClick; \
  if(s=xrm_get_resource(resourcedb,optionquery,optionquery,n)) set_key_binding(editor_mouse_bindings+o,m,s); \
  optionquery[1]=Q_gameClick; \
  if(s=xrm_get_resource(resourcedb,optionquery,optionquery,n)) set_key_binding(game_mouse_bindings+o,m,s); \
} while(0)
static void load_key_bindings(void) {
  xrm_quark q;
  const char*s;
  for(q=FirstKeyQuark;q<=LastKeyQuark;q++) {
    optionquery[2]=optionquery[3]=optionquery[4]=q;
    SetKeyBinding(3,0);
    optionquery[2]=Q_shift;
    SetKeyBinding(4,MOD_SHIFT);
    optionquery[2]=Q_ctrl;
    SetKeyBinding(4,MOD_CTRL);
    optionquery[2]=Q_alt;
    SetKeyBinding(4,MOD_ALT);
    optionquery[2]=Q_meta;
    SetKeyBinding(4,MOD_META);
    optionquery[2]=Q_numLock;
    SetKeyBinding(4,MOD_NUMLOCK);
    optionquery[3]=Q_shift;
    SetKeyBinding(5,MOD_NUMLOCK|MOD_SHIFT);
#if 0
    optionquery[2]=Q_alt;
    SetKeyBinding(5,MOD_ALT|MOD_SHIFT);
    optionquery[2]=Q_ctrl;
    SetKeyBinding(5,MOD_CTRL|MOD_SHIFT);
    optionquery[2]=Q_meta;
    SetKeyBinding(5,MOD_META|MOD_SHIFT);
#endif
  }
  optionquery[2]=optionquery[3]=Q_left;
  SetMouseBinding(SDL_BUTTON_LEFT,3,0);
  optionquery[2]=Q_shift;
  SetMouseBinding(SDL_BUTTON_LEFT,4,MOD_SHIFT);
  optionquery[2]=Q_ctrl;
  SetMouseBinding(SDL_BUTTON_LEFT,4,MOD_CTRL);
  optionquery[2]=Q_alt;
  SetMouseBinding(SDL_BUTTON_LEFT,4,MOD_ALT);
  optionquery[2]=Q_meta;
  SetMouseBinding(SDL_BUTTON_LEFT,4,MOD_META);
  optionquery[2]=optionquery[3]=Q_middle;
  SetMouseBinding(SDL_BUTTON_MIDDLE,3,0);
  optionquery[2]=Q_shift;
  SetMouseBinding(SDL_BUTTON_MIDDLE,4,MOD_SHIFT);
  optionquery[2]=Q_ctrl;
  SetMouseBinding(SDL_BUTTON_MIDDLE,4,MOD_CTRL);
  optionquery[2]=Q_alt;
  SetMouseBinding(SDL_BUTTON_MIDDLE,4,MOD_ALT);
  optionquery[2]=Q_meta;
  SetMouseBinding(SDL_BUTTON_MIDDLE,4,MOD_META);
  optionquery[2]=optionquery[3]=Q_right;
  SetMouseBinding(SDL_BUTTON_RIGHT,3,0);
  optionquery[2]=Q_shift;
  SetMouseBinding(SDL_BUTTON_RIGHT,4,MOD_SHIFT);
  optionquery[2]=Q_ctrl;
  SetMouseBinding(SDL_BUTTON_RIGHT,4,MOD_CTRL);
  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;i<argc;i++) printf("|%s",argv[i]);
  putchar('\n');
  return 0;
}

static void test_mode(void) {
  Uint32 n=0;

  SDL_Event ev;
  char buf[32];

  set_cursor(XC_tcross);
  SDL_LockSurface(screen);
  draw_text(0,0,"Hello, World!",0xF0,0xFF);
  SDL_UnlockSurface(screen);
  SDL_Flip(screen);
  while(SDL_WaitEvent(&ev)) switch(ev.type) {
    case SDL_KEYDOWN:







<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<










>


>







146
147
148
149
150
151
152












































































































153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
  s=malloc(256);
  if(!s) fatal("Allocation failed\n");
  if(fscanf(fp," %255s",s)!=1) fatal("Unable to scan name of class set\n");
  globalclassname=s;
  return !*s;
}













































































































static int test_sql_callback(void*usr,int argc,char**argv,char**name) {
  int i;
  if(argc) printf("%s",*argv);
  for(i=1;i<argc;i++) printf("|%s",argv[i]);
  putchar('\n');
  return 0;
}

static void test_mode(void) {
  Uint32 n=0;
  SDLKey k;
  SDL_Event ev;
  char buf[32];
  const UserCommand*uc;
  set_cursor(XC_tcross);
  SDL_LockSurface(screen);
  draw_text(0,0,"Hello, World!",0xF0,0xFF);
  SDL_UnlockSurface(screen);
  SDL_Flip(screen);
  while(SDL_WaitEvent(&ev)) switch(ev.type) {
    case SDL_KEYDOWN:
314
315
316
317
318
319
320






321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337


























338




339


340
341

342
343
344
345
346
347
348
          snprintf(buf,30,"%u",n);
          SDL_WM_SetCaption(buf,buf);
          break;
        case SDLK_c:
          SDL_FillRect(screen,0,n);
          SDL_Flip(screen);
          break;






        case SDLK_p:
          sqlite3_exec(userdb,"SELECT * FROM `PICTURES`;",test_sql_callback,0,0);
          break;
        case SDLK_q:
          exit(0);
          break;
      }
      break;
    case SDL_MOUSEBUTTONDOWN:
      draw_picture(ev.button.x,ev.button.y,n);
      SDL_Flip(screen);
      break;
    case SDL_QUIT:
      exit(0);
      break;
  }
  fatal("An error occurred waiting for events.\n");


























}







int main(int argc,char**argv) {
  int optind=1;

  while(argc>optind && 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");







>
>
>
>
>
>

















>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
|
>
>
>
>
|
>
>


>







186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
          snprintf(buf,30,"%u",n);
          SDL_WM_SetCaption(buf,buf);
          break;
        case SDLK_c:
          SDL_FillRect(screen,0,n);
          SDL_Flip(screen);
          break;
        case SDLK_e:
          n=1;
          goto keytest;
        case SDLK_g:
          n=0;
          goto keytest;
        case SDLK_p:
          sqlite3_exec(userdb,"SELECT * FROM `PICTURES`;",test_sql_callback,0,0);
          break;
        case SDLK_q:
          exit(0);
          break;
      }
      break;
    case SDL_MOUSEBUTTONDOWN:
      draw_picture(ev.button.x,ev.button.y,n);
      SDL_Flip(screen);
      break;
    case SDL_QUIT:
      exit(0);
      break;
  }
  fatal("An error occurred waiting for events.\n");
keytest:
  SDL_FillRect(screen,0,0xF0);
  SDL_LockSurface(screen);
  draw_text(1,5,n?"Edit Key":"Game Key",0xF1,0xF7);
  SDL_UnlockSurface(screen);
  SDL_EnableUNICODE(1);
  SDL_Flip(screen);
  set_cursor(XC_arrow);
  while(SDL_WaitEvent(&ev)) switch(ev.type) {
    case SDL_KEYDOWN:
      printf("[%d %d %d %d] ",ev.key.keysym.scancode,ev.key.keysym.sym,ev.key.keysym.mod,ev.key.keysym.unicode);
      goto bindingtest;
    case SDL_MOUSEBUTTONDOWN:
      printf("[%d %d %d] ",ev.button.x,ev.button.y,ev.button.button);
    bindingtest:
      uc=find_key_binding(&ev,n);
      switch(uc->cmd) {
        case 0: printf("<Unbound>\n"); break;
        case '^': printf("<Misc> %c\n",uc->n); break;
        case '=': printf("<Reset> %d\n",uc->n); break;
        case '-': printf("<Rewind> %d\n",uc->n); break;
        case '+': printf("<Advance> %d\n",uc->n); break;
        case '\'': printf("<Play> %s (%d)\n",heromesh_key_names[uc->n],uc->n); break;
        case '!': printf("<System> %s",uc->txt); break;
        case 's': printf("<SQL> %s",sqlite3_sql(uc->stmt)); break;
        default: printf("<Unknown>\n");
      }
      break;
    case SDL_QUIT:
      exit(0);
      break;
  }
}

int main(int argc,char**argv) {
  int optind=1;
  fprintf(stderr,"FREE HERO MESH\n");
  while(argc>optind && 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");
357
358
359
360
361
362
363

364
365
366
367
368
369
370
371
372
    globalclassname=strrchr(basefilename,'/');
    globalclassname=globalclassname?globalclassname+1:basefilename;
  }
  load_options();
  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;
}







>









268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
    globalclassname=strrchr(basefilename,'/');
    globalclassname=globalclassname?globalclassname+1:basefilename;
  }
  load_options();
  if(argc>optind) read_options(argc-optind,argv+optind);
  *optionquery=xrm_make_quark(globalclassname,0)?:xrm_anyq;
  init_sql();
  load_key_bindings();
  init_screen();
  load_pictures();
  if(main_options['T']) {
    test_mode();
    return 0;
  }
  
  return 0;
}

Modified names.h from [1e2e8b5b84] to [dbba9433ad].

16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
#define MSG_HIT 14
#define MSG_HITBY 15
#define MSG_DESTROYED 16
#define MSG_CREATED 17
#define MSG_POSTINIT 18
#define MSG_END_TURN 19
#define MSG_CLEANUP 20
static const char*const standard_message_names[]={
 "INIT",
 "CREATE",
 "DESTROY",
 "BEGIN_TURN",
 "ARRIVED",
 "DEPARTED",
 "LASTIMAGE",







|







16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
#define MSG_HIT 14
#define MSG_HITBY 15
#define MSG_DESTROYED 16
#define MSG_CREATED 17
#define MSG_POSTINIT 18
#define MSG_END_TURN 19
#define MSG_CLEANUP 20
const char*const standard_message_names[]={
 "INIT",
 "CREATE",
 "DESTROY",
 "BEGIN_TURN",
 "ARRIVED",
 "DEPARTED",
 "LASTIMAGE",
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
#define SND_GLISSANT 43
#define SND_BUZZER 44
#define SND_FAROUT 45
#define SND_KEWEL 46
#define SND_WHACK 47
#define SND_STEAM 48
#define SND_HAWK 49
static const char*const standard_sound_names[]={
 "SPLASH",
 "POUR",
 "DOOR",
 "GLASS",
 "BANG",
 "UNHH",
 "UH_OH",







|







89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
#define SND_GLISSANT 43
#define SND_BUZZER 44
#define SND_FAROUT 45
#define SND_KEWEL 46
#define SND_WHACK 47
#define SND_STEAM 48
#define SND_HAWK 49
const char*const standard_sound_names[]={
 "SPLASH",
 "POUR",
 "DOOR",
 "GLASS",
 "BANG",
 "UNHH",
 "UH_OH",
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
 "BUZZER",
 "FAROUT",
 "KEWEL",
 "WHACK",
 "STEAM",
 "HAWK",
};
static const char*const heromesh_key_names[256]={
 [8]="BACK",
 [9]="TAB",
 [12]="CENTER",
 [13]="ENTER",
 [16]="SHIFT",
 [17]="CTRL",
 [19]="BREAK",







|







141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
 "BUZZER",
 "FAROUT",
 "KEWEL",
 "WHACK",
 "STEAM",
 "HAWK",
};
const char*const heromesh_key_names[256]={
 [8]="BACK",
 [9]="TAB",
 [12]="CENTER",
 [13]="ENTER",
 [16]="SHIFT",
 [17]="CTRL",
 [19]="BREAK",

Modified names.js from [3fa560a1f1] to [1a4970b05a].

133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
  heromesh_key_names[y]=z;
});
[..."ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789"].forEach(x=>{
  heromesh_key_names[x.charCodeAt()]=x;
});
console.log("// Auto-generated! Do not modify directly!");
standard_message_names.forEach(([a,b,c])=>console.log("#define MSG_"+c+" "+b));
console.log("static const char*const standard_message_names[]={");
standard_message_names.forEach(([a,b,c])=>console.log(" \""+c+"\","));
console.log("};");
standard_sound_names.forEach((x,y)=>console.log("#define SND_"+x+" "+y));
console.log("static const char*const standard_sound_names[]={");
standard_sound_names.forEach(x=>console.log(" \""+x+"\","));
console.log("};");
console.log("static const char*const heromesh_key_names[256]={");
Object.keys(heromesh_key_names).forEach(x=>console.log(" ["+x+"]=\""+heromesh_key_names[x]+"\","));
console.log("};");







|



|


|


133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
  heromesh_key_names[y]=z;
});
[..."ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789"].forEach(x=>{
  heromesh_key_names[x.charCodeAt()]=x;
});
console.log("// Auto-generated! Do not modify directly!");
standard_message_names.forEach(([a,b,c])=>console.log("#define MSG_"+c+" "+b));
console.log("const char*const standard_message_names[]={");
standard_message_names.forEach(([a,b,c])=>console.log(" \""+c+"\","));
console.log("};");
standard_sound_names.forEach((x,y)=>console.log("#define SND_"+x+" "+y));
console.log("const char*const standard_sound_names[]={");
standard_sound_names.forEach(x=>console.log(" \""+x+"\","));
console.log("};");
console.log("const char*const heromesh_key_names[256]={");
Object.keys(heromesh_key_names).forEach(x=>console.log(" ["+x+"]=\""+heromesh_key_names[x]+"\","));
console.log("};");

Modified picture.c from [2526d2ec5f] to [b1d6c4cbe4].

211
212
213
214
215
216
217

218
219
220
221
222
223
224
  Uint8 nwantsize=0;
  Uint8 altImage;
  Uint16 havesize[256];
  char*nam=sqlite3_mprintf("%s.xclass",basefilename);
  const char*v;
  int i,j,n;
  if(!nam) fatal("Allocation failed\n");

  fp=fopen(nam,"r");
  if(!fp) fatal("Failed to open xclass file (%m)\n");
  sqlite3_free(nam);
  optionquery[1]=Q_altImage;
  altImage=strtol(xrm_get_resource(resourcedb,optionquery,optionquery,2)?:"0",0,10);
  optionquery[1]=Q_imageSize;
  v=xrm_get_resource(resourcedb,optionquery,optionquery,2);







>







211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
  Uint8 nwantsize=0;
  Uint8 altImage;
  Uint16 havesize[256];
  char*nam=sqlite3_mprintf("%s.xclass",basefilename);
  const char*v;
  int i,j,n;
  if(!nam) fatal("Allocation failed\n");
  fprintf(stderr,"Loading pictures...\n");
  fp=fopen(nam,"r");
  if(!fp) fatal("Failed to open xclass file (%m)\n");
  sqlite3_free(nam);
  optionquery[1]=Q_altImage;
  altImage=strtol(xrm_get_resource(resourcedb,optionquery,optionquery,2)?:"0",0,10);
  optionquery[1]=Q_imageSize;
  v=xrm_get_resource(resourcedb,optionquery,optionquery,2);
293
294
295
296
297
298
299

300
301
302
303
304
305
306
    fseek(fp,sqlite3_column_int64(st,1),SEEK_SET);
    load_one_picture(fp,sqlite3_column_int(st,0),altImage);
  }
  sqlite3_finalize(st);
  fclose(fp);
  sqlite3_exec(userdb,"COMMIT;",0,0,0);
  SDL_SetColorKey(picts,SDL_SRCCOLORKEY|SDL_RLEACCEL,0);

}

void init_screen(void) {
  const char*v;
  int w,h,i;
  optionquery[1]=Q_screenWidth;
  w=strtol(xrm_get_resource(resourcedb,optionquery,optionquery,2)?:"800",0,10);







>







294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
    fseek(fp,sqlite3_column_int64(st,1),SEEK_SET);
    load_one_picture(fp,sqlite3_column_int(st,0),altImage);
  }
  sqlite3_finalize(st);
  fclose(fp);
  sqlite3_exec(userdb,"COMMIT;",0,0,0);
  SDL_SetColorKey(picts,SDL_SRCCOLORKEY|SDL_RLEACCEL,0);
  fprintf(stderr,"Done\n");
}

void init_screen(void) {
  const char*v;
  int w,h,i;
  optionquery[1]=Q_screenWidth;
  w=strtol(xrm_get_resource(resourcedb,optionquery,optionquery,2)?:"800",0,10);

Modified quarks.h from [16698ee816] to [93fb52c37c].

344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
  "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,
SDLK_CLEAR,
SDLK_RETURN,
SDLK_PAUSE,
SDLK_ESCAPE,







|







344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
  "sqlExtensions",
  "sqlMemStatus",
  "sqlSmallAllocations",
  "sqlCoveringIndexScan",
  "sqlPowerSafe",
  "level",
0};
#ifdef HEROMESH_BINDINGS
static const SDLKey quark_to_key[Q_undo+1-Q_backspace]={
SDLK_BACKSPACE,
SDLK_TAB,
SDLK_CLEAR,
SDLK_RETURN,
SDLK_PAUSE,
SDLK_ESCAPE,

Modified quarks.js from [4d5623fa73] to [a3dad95697].

1
2
3
4
5
6
7
8
9
"use strict";
const fs=require("fs");
const quarks=fs.readFileSync("quarks","ascii").split("\n").map(x=>x.trim()).filter(x=>x&&x[0]!="!");
quarks.forEach((x,y)=>console.log("#define Q_"+x+" "+(y+2)));
console.log("static const char*const global_quarks[]={");
quarks.forEach(x=>console.log("  \""+x+"\","));
console.log("0};\n#ifdef HEROMESH_MAIN\nstatic const SDLKey quark_to_key[Q_undo+1-Q_backspace]={");
quarks.slice(quarks.indexOf("backspace"),quarks.indexOf("undo")+1).forEach(x=>console.log("SDLK_"+x[x.length==1?"toLowerCase":"toUpperCase"]()+","));
console.log("};\n#define FirstKeyQuark Q_backspace\n#define LastKeyQuark Q_undo\n#endif");






|


1
2
3
4
5
6
7
8
9
"use strict";
const fs=require("fs");
const quarks=fs.readFileSync("quarks","ascii").split("\n").map(x=>x.trim()).filter(x=>x&&x[0]!="!");
quarks.forEach((x,y)=>console.log("#define Q_"+x+" "+(y+2)));
console.log("static const char*const global_quarks[]={");
quarks.forEach(x=>console.log("  \""+x+"\","));
console.log("0};\n#ifdef HEROMESH_BINDINGS\nstatic const SDLKey quark_to_key[Q_undo+1-Q_backspace]={");
quarks.slice(quarks.indexOf("backspace"),quarks.indexOf("undo")+1).forEach(x=>console.log("SDLK_"+x[x.length==1?"toLowerCase":"toUpperCase"]()+","));
console.log("};\n#define FirstKeyQuark Q_backspace\n#define LastKeyQuark Q_undo\n#endif");

Modified smallxrm.c from [4ef0f077c3] to [b4352f885e].

101
102
103
104
105
106
107
108
109

110
111
112
113
114
115
116
  my_realloc(db,0);
}

void*xrm_enumerate(xrm_db*db,void*(*cb)(xrm_db*,void*,int,xrm_quark),void*usr) {
  int i;
  void*r;
  if(!db) return 0;
  for(i=0;i<db->l.n;i++) if(r=cb(db,usr,1,db->l.p[i].k)) return r;
  for(i=0;i<db->t.n;i++) if(r=cb(db,usr,0,db->t.p[i].k)) return r;

  return 0;
}

const char*xrm_get(xrm_db*db) {
  return db?db->v:0;
}








<

>







101
102
103
104
105
106
107

108
109
110
111
112
113
114
115
116
  my_realloc(db,0);
}

void*xrm_enumerate(xrm_db*db,void*(*cb)(xrm_db*,void*,int,xrm_quark),void*usr) {
  int i;
  void*r;
  if(!db) return 0;

  for(i=0;i<db->t.n;i++) if(r=cb(db,usr,0,db->t.p[i].k)) return r;
  for(i=0;i<db->l.n;i++) if(r=cb(db,usr,1,db->l.p[i].k)) return r;
  return 0;
}

const char*xrm_get(xrm_db*db) {
  return db?db->v:0;
}