Free Hero Mesh

Check-in [016ea5365e]
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:Split picture reading codes into a separate file
Downloads: Tarball | ZIP archive
Timelines: family | ancestors | descendants | both | trunk
Files: files | file ages | folders
SHA1: 016ea5365e4ce59c21ddf976994712c1e1c73e9f
User & Date: user on 2018-04-02 18:22:32.465
Other Links: manifest | tags
Context
2018-04-02
23:54
Fix a mistake check-in: 1e31248216 user: user tags: trunk
18:22
Split picture reading codes into a separate file check-in: 016ea5365e user: user tags: trunk
2018-03-31
02:14
Add key bindings and some other stuff check-in: c1ad4ad8cc user: user tags: trunk
Changes
Added heromesh.h version [81301118dc].
Modified main.c from [ab2178c197] to [d2f05c125d].
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
#if 0
gcc -s -O2 -o ~/bin/heromesh main.c smallxrm.o sqlite3.o `sdl-config --cflags --libs` -ldl -lpthread
exit
#endif

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

#define _BSD_SOURCE

#include "SDL.h"
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include "sqlite3.h"
#include "smallxrm.h"
#include "names.h"
#include "quarks.h"
#include "cursorshapes.h"
#include "pcfont.h"

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

|








>










|







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
#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.
*/

#define _BSD_SOURCE
#define HEROMESH_MAIN
#include "SDL.h"
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#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;
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
static const char schema[]=
  "PRAGMA APPLICATION_ID(1296388936);"
  "PRAGMA RECURSIVE_TRIGGERS(1);"
  "CREATE TABLE IF NOT EXISTS `USERCACHEINDEX`(`ID` INTEGER PRIMARY KEY, `NAME` TEXT, `LVLTIME` INT, `SOLTIME` INT, `VERSION` INT);"
  "CREATE TEMPORARY TABLE `PICTURES`(`ID` INTEGER PRIMARY KEY, `NAME` TEXT, `OFFSET` INT);"
;

static sqlite3*userdb;
static SDL_Cursor*cursor[77];
static xrm_db*resourcedb;
static SDL_Surface*screen;
static const char*basefilename;


static const char*globalclassname;

static FILE*levelfp;
static FILE*solutionfp;
static xrm_quark optionquery[16];
static FILE*hamarc_fp;
static long hamarc_pos;
static Uint16 picture_size;
static SDL_Surface*picture_surface;
static KeyBinding*editor_bindings[SDLK_LAST];
static KeyBinding*game_bindings[SDLK_LAST];



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







|
<
|
<
|
>
>

>


<


<
<


>
>







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
static const char schema[]=
  "PRAGMA APPLICATION_ID(1296388936);"
  "PRAGMA RECURSIVE_TRIGGERS(1);"
  "CREATE TABLE IF NOT EXISTS `USERCACHEINDEX`(`ID` INTEGER PRIMARY KEY, `NAME` TEXT, `LVLTIME` INT, `SOLTIME` INT, `VERSION` INT);"
  "CREATE TEMPORARY TABLE `PICTURES`(`ID` INTEGER PRIMARY KEY, `NAME` TEXT, `OFFSET` INT);"
;

sqlite3*userdb;

xrm_db*resourcedb;

const char*basefilename;
xrm_quark optionquery[16];

static const char*globalclassname;
static SDL_Cursor*cursor[77];
static FILE*levelfp;
static FILE*solutionfp;

static FILE*hamarc_fp;
static long hamarc_pos;


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);
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
160
161
162
163
164
165
166
167
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
  }
  if(sqlite3_exec(userdb,schema,0,0,&s)) fatal("Failed to initialize database schema (%s)\n",s?:"unknown error");
  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 draw_picture(int x,int y,Uint16 img) {
  // To be called only when screen is unlocked!
  SDL_Rect src={(img&15)*picture_size,(img>>4)*picture_size,picture_size,picture_size};
  SDL_Rect dst={x,y,picture_size,picture_size};
  SDL_BlitSurface(picture_surface,&src,screen,&dst);
}

static void draw_text(int x,int y,const unsigned char*t,int bg,int fg) {
  // To be called only when screen is locked!
  int len=strlen(t);
  Uint8*pix=screen->pixels;
  Uint8*p;
  Uint16 pitch=screen->pitch;
  int xx,yy;
  const unsigned char*f;
  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);
    for(yy=0;yy<8;yy++) {
      for(xx=0;xx<8;xx++) p[xx]=(*f<<xx)&128?fg:bg;
      p+=pitch;
      ++f;
    }
    t++;
    if(!--len) return;
  }
}

static Uint16 decide_picture_size(int nwantsize,const Uint8*wantsize,const Uint16*havesize) {
  int i,j;
  if(!nwantsize) fatal("Unable to determine what picture size is wanted\n");
  for(i=0;i<nwantsize;i++) if(havesize[j=wantsize[i]]) return j;
  for(i=0;i<nwantsize;i++) for(j=2;j<wantsize[i];j++) if(wantsize[i]%j==0 && havesize[wantsize[i]/j]) return wantsize[i];
  for(i=*wantsize;i;i--) for(j=1;j<i;j++) if(i%j==0 && havesize[i/j]) return i;
  fatal("Unable to determine what picture size is wanted\n");
}

static void load_pictures(void) {
  sqlite3_stmt*st=0;
  FILE*fp;
  Uint8 wantsize[32];
  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);
  if(v) while(nwantsize<32) {
    i=j=0;
    sscanf(v," %d %n",&i,&j);
    if(!j) break;
    if(i<2 || i>255) fatal("Invalid picture size %d\n",i);
    wantsize[nwantsize++]=i;
    v+=j;
  }
  sqlite3_exec(userdb,"BEGIN;",0,0,0);
  if(sqlite3_prepare(userdb,"INSERT INTO `PICTURES`(`ID`,`NAME`,`OFFSET`) VALUES(?1,?2,?3);",-1,&st,0))
   fatal("Unable to prepare SQL statement while loading pictures: %s\n",sqlite3_errmsg(userdb));
  nam=malloc(256);
  if(!nam) fatal("Allocation failed\n");
  n=0;
  memset(havesize,0,256*sizeof(Uint16));
  while(!feof(fp)) {
    i=0;
    while(j=fgetc(fp)) {
      if(j==EOF) goto nomore1;
      if(i<255) nam[i++]=j;
    }
    nam[i]=0;
    if(i>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_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;
    }
    i=fgetc(fp)<<16;
    i|=fgetc(fp)<<24;
    i|=fgetc(fp)<<0;
    i|=fgetc(fp)<<8;
    if(j) {
      i-=j=fgetc(fp)&15;
      while(j--) ++havesize[fgetc(fp)&255];
      fseek(fp,i-1,SEEK_CUR);
    } else {
      fseek(fp,i,SEEK_CUR);
    }
  }
nomore1:
  if(!n) fatal("Cannot find any pictures in this puzzle set\n");
  free(nam);
  sqlite3_finalize(st);
  rewind(fp);
  for(i=0;i<256;i++) havesize[i]=(havesize[i]==n)?1:0;
  picture_size=decide_picture_size(nwantsize,wantsize,havesize);
  
  fclose(fp);
  sqlite3_exec(userdb,"COMMIT;",0,0,0);
}

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

static void load_options(void) {







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







129
130
131
132
133
134
135



















































































































136
137
138
139
140
141
142
  }
  if(sqlite3_exec(userdb,schema,0,0,&s)) fatal("Failed to initialize database schema (%s)\n",s?:"unknown error");
  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) {
  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]);
}

static void load_options(void) {
324
325
326
327
328
329
330






331
332
333
334
335
336
337

#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)






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;







>
>
>
>
>
>







210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229

#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;
351
352
353
354
355
356
357






























358
359
360
361
362
363
364
    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
  }






























}

int main(int argc,char**argv) {
  if(argc<2) fatal("usage: %s 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();







>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>







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

int main(int argc,char**argv) {
  if(argc<2) fatal("usage: %s 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();
Added picture.c version [55b874cfd0].
Modified quarks.h from [a748b92e70] to [6487272797].
341
342
343
344
345
346
347


348
349
350
351
352
353
354
355
  "solutionTimestamp",
  "sqlInit",
  "sqlExtensions",
  "sqlMemStatus",
  "sqlSmallAllocations",
  "sqlCoveringIndexScan",
  "sqlPowerSafe",


0}; static const SDLKey quark_to_key[Q_undo+1-Q_backspace]={
SDLK_BACKSPACE,
SDLK_TAB,
SDLK_CLEAR,
SDLK_RETURN,
SDLK_PAUSE,
SDLK_ESCAPE,
SDLK_SPACE,







>
>
|







341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
  "solutionTimestamp",
  "sqlInit",
  "sqlExtensions",
  "sqlMemStatus",
  "sqlSmallAllocations",
  "sqlCoveringIndexScan",
  "sqlPowerSafe",
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,
SDLK_SPACE,
479
480
481
482
483
484
485

SDLK_POWER,
SDLK_EURO,
SDLK_COMPOSE,
SDLK_UNDO,
};
#define FirstKeyQuark Q_backspace
#define LastKeyQuark Q_undo








>
481
482
483
484
485
486
487
488
SDLK_POWER,
SDLK_EURO,
SDLK_COMPOSE,
SDLK_UNDO,
};
#define FirstKeyQuark Q_backspace
#define LastKeyQuark Q_undo
#endif
Modified quarks.js from [fa428bd705] to [4d5623fa73].
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}; static 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");






|

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