Free Hero Mesh

Diff
Login
This is a mirror of the main repository for Free Hero Mesh. New tickets and changes will not be accepted at this mirror.

Differences From Artifact [aa26680e3f]:

To Artifact [dee2ab208b]:


12
13
14
15
16
17
18












19
20
21
22
23
24
25
26



















































27
28
29
30
31
32
33
#include "heromesh.h"

typedef struct {
  struct sqlite3_vtab_cursor;
  sqlite3_int64 rowid;
  char unique,eof;
} Cursor;













static void fn_basename(sqlite3_context*cxt,int argc,sqlite3_value**argv) {
  sqlite3_result_text(cxt,basefilename,-1,SQLITE_STATIC);
}

static void fn_cacheid(sqlite3_context*cxt,int argc,sqlite3_value**argv) {
  sqlite3_result_int64(cxt,*(sqlite3_int64*)sqlite3_user_data(cxt));
}




















































static void fn_modstate(sqlite3_context*cxt,int argc,sqlite3_value**argv) {
  sqlite3_result_int(cxt,SDL_GetModState());
}

static void fn_picture_size(sqlite3_context*cxt,int argc,sqlite3_value**argv) {
  sqlite3_result_int(cxt,picture_size);







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








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







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
#include "heromesh.h"

typedef struct {
  struct sqlite3_vtab_cursor;
  sqlite3_int64 rowid;
  char unique,eof;
} Cursor;

static void find_first_usable_image(const Class*cl,sqlite3_context*cxt) {
  int i;
  if(cl->cflags&CF_GROUP) return;
  if(!cl->images) return;
  for(i=0;i<cl->nimages;i++) {
    if(cl->images[i]&0x8000) {
      sqlite3_result_int(cxt,i);
      return;
    }
  }
}

static void fn_basename(sqlite3_context*cxt,int argc,sqlite3_value**argv) {
  sqlite3_result_text(cxt,basefilename,-1,SQLITE_STATIC);
}

static void fn_cacheid(sqlite3_context*cxt,int argc,sqlite3_value**argv) {
  sqlite3_result_int64(cxt,*(sqlite3_int64*)sqlite3_user_data(cxt));
}

static void fn_class_data(sqlite3_context*cxt,int argc,sqlite3_value**argv) {
  int id=sqlite3_value_int(argv[0]);
  Class*cl;
  if(id<0 || id>=0x4000 || !classes[id]) return;
  cl=classes[id];
  switch(sqlite3_value_int(argv[1])&255) {
    case 0: sqlite3_result_int(cxt,id); break;
    case 1: sqlite3_result_int64(cxt,cl->temperature); break;
    case 2: sqlite3_result_int(cxt,cl->shape); break;
    case 7: find_first_usable_image(cl,cxt); break;
    case 12: sqlite3_result_int64(cxt,cl->misc4&0xFFFFFFFFULL); break;
    case 13: sqlite3_result_int64(cxt,cl->misc5&0xFFFFFFFFULL); break;
    case 14: sqlite3_result_int64(cxt,cl->misc6&0xFFFFFFFFULL); break;
    case 15: sqlite3_result_int64(cxt,cl->misc7&0xFFFFFFFFULL); break;
    case 18: sqlite3_result_int64(cxt,cl->arrivals); break;
    case 19: sqlite3_result_int64(cxt,cl->departures); break;
    case 32: sqlite3_result_int(cxt,cl->oflags&OF_BUSY?1:0); break;
    case 33: sqlite3_result_int(cxt,cl->oflags&OF_INVISIBLE?1:0); break;
    case 34: sqlite3_result_int(cxt,cl->oflags&OF_USERSIGNAL?1:0); break;
    case 35: sqlite3_result_int(cxt,cl->oflags&OF_USERSTATE?1:0); break;
    case 36: sqlite3_result_int(cxt,cl->oflags&OF_KEYCLEARED?1:0); break;
    case 37: sqlite3_result_int(cxt,cl->cflags&CF_PLAYER?1:0); break;
    case 38: sqlite3_result_int(cxt,cl->oflags&OF_DESTROYED?1:0); break;
    case 39: sqlite3_result_int(cxt,cl->oflags&OF_STEALTHY?1:0); break;
    case 40: sqlite3_result_int(cxt,cl->oflags&OF_VISUALONLY?1:0); break;
    case 64: sqlite3_result_int64(cxt,cl->density); break;
    case 65: sqlite3_result_int64(cxt,cl->volume); break;
    case 66: sqlite3_result_int64(cxt,cl->strength); break;
    case 67: sqlite3_result_int64(cxt,cl->weight); break;
    case 69: sqlite3_result_int64(cxt,cl->height); break;
    case 70: sqlite3_result_int64(cxt,cl->climb); break;
    case 72: sqlite3_result_int(cxt,cl->hard[0]); break;
    case 73: sqlite3_result_int(cxt,cl->hard[1]); break;
    case 74: sqlite3_result_int(cxt,cl->hard[2]); break;
    case 75: sqlite3_result_int(cxt,cl->hard[3]); break;
    case 76: sqlite3_result_int(cxt,cl->sharp[0]); break;
    case 77: sqlite3_result_int(cxt,cl->sharp[1]); break;
    case 78: sqlite3_result_int(cxt,cl->sharp[2]); break;
    case 79: sqlite3_result_int(cxt,cl->sharp[3]); break;
    case 80: sqlite3_result_int(cxt,(cl->shape>>0)&3); break;
    case 81: sqlite3_result_int(cxt,(cl->shape>>2)&3); break;
    case 82: sqlite3_result_int(cxt,(cl->shape>>4)&3); break;
    case 83: sqlite3_result_int(cxt,(cl->shape>>6)&3); break;
    case 84: sqlite3_result_int(cxt,cl->shovable); break;
    case 128: sqlite3_result_double(cxt,cl->volume/(double)max_volume); break;
    case 129: sqlite3_result_int(cxt,cl->uservars); break;
    case 130: sqlite3_result_int(cxt,cl->collisionLayers); break;
    case 132: sqlite3_result_int(cxt,cl->cflags&CF_COMPATIBLE?1:0); break;
  }
}

static void fn_modstate(sqlite3_context*cxt,int argc,sqlite3_value**argv) {
  sqlite3_result_int(cxt,SDL_GetModState());
}

static void fn_picture_size(sqlite3_context*cxt,int argc,sqlite3_value**argv) {
  sqlite3_result_int(cxt,picture_size);
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
static int vt0_eof(sqlite3_vtab_cursor*pcur) {
  Cursor*cur=(void*)pcur;
  return cur->eof;
}

static int vt0_index(sqlite3_vtab*vt,sqlite3_index_info*info) {
  int i;
  if(info->nOrderBy==1 && info->aOrderBy->iColumn==-1 && !info->aOrderBy->desc) info->orderByConsumed=1;
  for(i=0;i<info->nConstraint;i++) {
    if(info->aConstraint[i].iColumn==-1 && info->aConstraint[i].op==SQLITE_INDEX_CONSTRAINT_EQ && info->aConstraint[i].usable) {
      info->aConstraintUsage[i].argvIndex=1;
      info->aConstraintUsage[i].omit=1;
      info->idxFlags=SQLITE_INDEX_SCAN_UNIQUE;
      break;
    }
  }
  return SQLITE_OK;







|

|







151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
static int vt0_eof(sqlite3_vtab_cursor*pcur) {
  Cursor*cur=(void*)pcur;
  return cur->eof;
}

static int vt0_index(sqlite3_vtab*vt,sqlite3_index_info*info) {
  int i;
  if(info->nOrderBy==1 && (info->aOrderBy->iColumn==-1 || !info->aOrderBy->iColumn) && !info->aOrderBy->desc) info->orderByConsumed=1;
  for(i=0;i<info->nConstraint;i++) {
    if((info->aConstraint[i].iColumn==-1 || !info->aConstraint[i].iColumn) && info->aConstraint[i].op==SQLITE_INDEX_CONSTRAINT_EQ && info->aConstraint[i].usable) {
      info->aConstraintUsage[i].argvIndex=1;
      info->aConstraintUsage[i].omit=1;
      info->idxFlags=SQLITE_INDEX_SCAN_UNIQUE;
      break;
    }
  }
  return SQLITE_OK;
197
198
199
200
201
202
203
204







































































































205
206

207
208
209
210
211
212
213


214
215

Module(vt_messages,
  .xColumn=vt1_messages_column,
  .xFilter=vt1_messages_filter,
  .xNext=vt1_messages_next,
  .xUpdate=vt1_messages_update,
);








































































































void init_sql_functions(sqlite3_int64*ptr0,sqlite3_int64*ptr1) {
  sqlite3_create_function(userdb,"BASENAME",0,SQLITE_UTF8|SQLITE_DETERMINISTIC,0,fn_basename,0,0);

  sqlite3_create_function(userdb,"LEVEL_CACHEID",0,SQLITE_UTF8|SQLITE_DETERMINISTIC,ptr0,fn_cacheid,0,0);
  sqlite3_create_function(userdb,"MODSTATE",0,SQLITE_UTF8,0,fn_modstate,0,0);
  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_module(userdb,"MESSAGES",&vt_messages,"CREATE TABLE `MESSAGES`(`ID` INTEGER PRIMARY KEY, `NAME` TEXT, `TRACE` INT);");
}








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


>







>
>


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
302
303
304
305
306
307
308
309
310
311
312
313
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
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384

Module(vt_messages,
  .xColumn=vt1_messages_column,
  .xFilter=vt1_messages_filter,
  .xNext=vt1_messages_next,
  .xUpdate=vt1_messages_update,
);

static int vt1_classes_column(sqlite3_vtab_cursor*pcur,sqlite3_context*cxt,int n) {
  Cursor*cur=(void*)pcur;
  switch(n) {
    case 0: // ID
      sqlite3_result_int64(cxt,cur->rowid);
      break;
    case 1: // NAME
      if(sqlite3_vtab_nochange(cxt)) return SQLITE_OK;
      sqlite3_result_text(cxt,classes[cur->rowid]->name,-1,0);
      break;
    case 2: // EDITORHELP
      if(sqlite3_vtab_nochange(cxt)) return SQLITE_OK;
      sqlite3_result_text(cxt,classes[cur->rowid]->edithelp,-1,0);
      break;
    case 3: // HELP
      if(sqlite3_vtab_nochange(cxt)) return SQLITE_OK;
      sqlite3_result_text(cxt,classes[cur->rowid]->gamehelp,-1,0);
      break;
    case 4: // INPUT
      sqlite3_result_int(cxt,classes[cur->rowid]->cflags&CF_INPUT?1:0);
      break;
    case 5: // QUIZ
      sqlite3_result_int(cxt,classes[cur->rowid]->cflags&CF_QUIZ?1:0);
      break;
    case 6: // TRACEIN
      sqlite3_result_int(cxt,classes[cur->rowid]->oflags&OF_TRACEIN?1:0);
      break;
    case 7: // TRACEOUT
      sqlite3_result_int(cxt,classes[cur->rowid]->oflags&OF_TRACEOUT?1:0);
      break;
    case 8: // GROUP
      if(sqlite3_vtab_nochange(cxt)) return SQLITE_OK;
      if(classes[cur->rowid]->cflags&CF_GROUP) {
        char*s=sqlite3_mprintf(" ");
        if(!s) return SQLITE_NOMEM;
        for(n=0;classes[cur->rowid]->codes[n];n++) {
          s=sqlite3_mprintf("%z%s ",s,classes[classes[cur->rowid]->codes[n]]->name);
          if(!s) return SQLITE_NOMEM;
        }
        sqlite3_result_text(cxt,s,-1,sqlite3_free);
      } else {
        sqlite3_result_null(cxt);
      }
      break;
    case 9: // PLAYER
      sqlite3_result_int(cxt,classes[cur->rowid]->cflags&CF_PLAYER?1:0);
      break;
  }
  return SQLITE_OK;
}

static int vt1_classes_filter(sqlite3_vtab_cursor*pcur,int idxNum,const char*idxStr,int argc,sqlite3_value**argv) {
  Cursor*cur=(void*)pcur;
  cur->eof=0;
  if(argc) {
    cur->rowid=sqlite3_value_int64(*argv);
    cur->unique=1;
    if(cur->rowid<=0 || cur->rowid>=0x4000 || !classes[cur->rowid] || classes[cur->rowid]->cflags&CF_NOCLASS2) cur->eof=1;
  } else {
    cur->unique=0;
    cur->rowid=1;
    while(cur->rowid<0x4000 && (!classes[cur->rowid] || classes[cur->rowid]->cflags&CF_NOCLASS2)) ++cur->rowid;
    if(cur->rowid>=0x4000) cur->eof=1;
  }
  return SQLITE_OK;
}

static int vt1_classes_next(sqlite3_vtab_cursor*pcur) {
  Cursor*cur=(void*)pcur;
  if(cur->unique) {
    cur->eof=1;
  } else {
    ++cur->rowid;
    while(cur->rowid<0x4000 && (!classes[cur->rowid] || classes[cur->rowid]->cflags&CF_NOCLASS2)) ++cur->rowid;
    if(cur->rowid>=0x4000) cur->eof=1;
  }
  return SQLITE_OK;
}

static int vt1_classes_update(sqlite3_vtab*vt,int argc,sqlite3_value**argv,sqlite3_int64*rowid) {
  sqlite3_int64 id;
  int v[3];
  if(argc!=5 || sqlite3_value_type(*argv)!=SQLITE_INTEGER) return SQLITE_CONSTRAINT_VTAB;
  id=sqlite3_value_int64(*argv);
  if(id!=sqlite3_value_int64(argv[1])) return SQLITE_CONSTRAINT_VTAB;
  if(id<=0 || id>=0x4000 || !classes[id]) return SQLITE_INTERNAL;
  v[0]=sqlite3_value_int(argv[5]);
  v[1]=sqlite3_value_int(argv[6]);
  v[2]=sqlite3_value_int(argv[7]);
  if((v[0]|v[1]|v[2])&~1) return SQLITE_CONSTRAINT_CHECK;
  if(v[0]) classes[id]->cflags|=CF_QUIZ; else classes[id]->cflags&=~CF_QUIZ;
  classes[id]->oflags&=~(OF_TRACEIN|OF_TRACEOUT);
  classes[id]->oflags|=(v[1]?OF_TRACEIN:0)|(v[2]?OF_TRACEOUT:0);
  return SQLITE_OK;
}

Module(vt_classes,
  .xColumn=vt1_classes_column,
  .xFilter=vt1_classes_filter,
  .xNext=vt1_classes_next,
  .xUpdate=vt1_classes_update,
);

void init_sql_functions(sqlite3_int64*ptr0,sqlite3_int64*ptr1) {
  sqlite3_create_function(userdb,"BASENAME",0,SQLITE_UTF8|SQLITE_DETERMINISTIC,0,fn_basename,0,0);
  sqlite3_create_function(userdb,"CLASS_DATA",2,SQLITE_UTF8|SQLITE_DETERMINISTIC,0,fn_class_data,0,0);
  sqlite3_create_function(userdb,"LEVEL_CACHEID",0,SQLITE_UTF8|SQLITE_DETERMINISTIC,ptr0,fn_cacheid,0,0);
  sqlite3_create_function(userdb,"MODSTATE",0,SQLITE_UTF8,0,fn_modstate,0,0);
  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_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);");
}