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 [8b747a8794]:

To Artifact [1d7efeafa0]:


37
38
39
40
41
42
43









44
45
46
47
48
49
50
static Uint8 replay_speed;
static Uint8 replay_time;
static Uint8 solved;
static Uint8 inserting,saved_inserting;
static sqlite3_stmt*autowin;
static size_t dum_size; // not used by Free Hero Mesh, but needed by some C library functions.










int encode_move(FILE*fp,MoveItem v) {
  // Encodes a single move and writes the encoded move to the file.
  // Returns the number of bytes of the encoded move.
  if(v>=8 && v<256) {
    fputc(v,fp);
    return 1;
  } else if(v>=0x8000 && v<=0x8FFF) {







>
>
>
>
>
>
>
>
>







37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
static Uint8 replay_speed;
static Uint8 replay_time;
static Uint8 solved;
static Uint8 inserting,saved_inserting;
static sqlite3_stmt*autowin;
static size_t dum_size; // not used by Free Hero Mesh, but needed by some C library functions.

typedef struct {
  char*data;
  size_t size;
  Uint16 mark,pos;
} SaveState;

static SaveState savestates[8];
static Uint8 has_savestates;

int encode_move(FILE*fp,MoveItem v) {
  // Encodes a single move and writes the encoded move to the file.
  // Returns the number of bytes of the encoded move.
  if(v>=8 && v<256) {
    fputc(v,fp);
    return 1;
  } else if(v>=0x8000 && v<=0x8FFF) {
330
331
332
333
334
335
336

337
338
339
340
341
342
343
  SDL_LockSurface(screen);
  draw_text(0,40,buf,0xF0,0xF1);
  SDL_UnlockSurface(screen);
  SDL_Flip(screen);
}

static void save_replay(void) {

  unsigned char*buf=0;
  size_t sz=0;
  FILE*fp;
  if(solution_replay || !replay_list || !replay_count) return;
  if(gameover==1) solved=1;
  fp=open_memstream((char**)&buf,&sz);
  if(!fp) fatal("Allocation failed\n");







>







339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
  SDL_LockSurface(screen);
  draw_text(0,40,buf,0xF0,0xF1);
  SDL_UnlockSurface(screen);
  SDL_Flip(screen);
}

static void save_replay(void) {
  int i;
  unsigned char*buf=0;
  size_t sz=0;
  FILE*fp;
  if(solution_replay || !replay_list || !replay_count) return;
  if(gameover==1) solved=1;
  fp=open_memstream((char**)&buf,&sz);
  if(!fp) fatal("Allocation failed\n");
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
385
386
387
388
389
      fputc(best_score>>24,fp);
    }
  }
  if(replay_mark) {
    fputc(0x42,fp);
    fputc(replay_mark,fp);
    fputc(replay_mark>>8,fp);












  }
  fclose(fp);
  if(!buf) fatal("Allocation failed\n");
  write_userstate(FIL_LEVEL,level_id,sz,buf);
  free(buf);
}

static void load_replay(void) {
  FILE*fp=0;
  unsigned char*buf=0;
  long sz;
  int i,j;
  free(replay_list);
  replay_list=0;
  replay_count=replay_mark=replay_size=0;
  free(best_list);
  best_list=0;









  if(solution_replay) {
    gameover_score=NO_SCORE;
    if(buf=read_lump(FIL_SOLUTION,level_id,&sz)) {
      fp=fmemopen(buf,sz,"r");
      if(!fp) fatal("Allocation failed\n");
      // Solution format: version (16-bits), flag (8-bits), score (32-bits), user name (null-terminated), timestamp (64-bits), move list
      if(sz>3) {







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

















>
>
>
>
>
>
>
>
>







369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
      fputc(best_score>>24,fp);
    }
  }
  if(replay_mark) {
    fputc(0x42,fp);
    fputc(replay_mark,fp);
    fputc(replay_mark>>8,fp);
  }
  if(has_savestates) for(i=0;i<8;i++) if(savestates[i].data) {
    fputc(i+0x30,fp);
    fputs(savestates[i].data,fp);
    fputc(0,fp);
    if(savestates[i].mark || savestates[i].pos) {
      fputc(i+0xB0,fp);
      fputc(savestates[i].mark,fp);
      fputc(savestates[i].mark>>8,fp);
      fputc(savestates[i].pos,fp);
      fputc(savestates[i].pos>>8,fp);
    }
  }
  fclose(fp);
  if(!buf) fatal("Allocation failed\n");
  write_userstate(FIL_LEVEL,level_id,sz,buf);
  free(buf);
}

static void load_replay(void) {
  FILE*fp=0;
  unsigned char*buf=0;
  long sz;
  int i,j;
  free(replay_list);
  replay_list=0;
  replay_count=replay_mark=replay_size=0;
  free(best_list);
  best_list=0;
  if(has_savestates) {
    for(i=0;i<8;i++) {
      free(savestates[i].data);
      savestates[i].data=0;
      savestates[i].size=0;
      savestates[i].mark=savestates[i].pos=0;
    }
    has_savestates=0;
  }
  if(solution_replay) {
    gameover_score=NO_SCORE;
    if(buf=read_lump(FIL_SOLUTION,level_id,&sz)) {
      fp=fmemopen(buf,sz,"r");
      if(!fp) fatal("Allocation failed\n");
      // Solution format: version (16-bits), flag (8-bits), score (32-bits), user name (null-terminated), timestamp (64-bits), move list
      if(sz>3) {
425
426
427
428
429
430
431





432
433
434
435
436
437
438
439
440
441
442
443
444
445
446






447
448
449
450
451
452
453
          if(replay_list) goto skip;
          decode_move_list(fp);
          break;
        case 0x02: // Best list
          if(best_list) goto skip;
          dum_size=0;
          getdelim(&best_list,&dum_size,0,fp);





          break;
        case 0x41: // Solved version
          i=fgetc(fp); i|=fgetc(fp)<<8;
          if(i==level_version) solved=1;
          break;
        case 0x42: // Mark
          replay_mark=fgetc(fp);
          replay_mark|=fgetc(fp)<<8;
          break;
        case 0x81: // Best score
          best_score=fgetc(fp);
          best_score|=fgetc(fp)<<8;
          best_score|=fgetc(fp)<<16;
          best_score|=fgetc(fp)<<24;
          break;






        default: skip:
          if(i<0x40) {
            while(fgetc(fp)>0);
          } else if(i<0x80) {
            fgetc(fp); fgetc(fp);
          } else if(i<0xC0) {
            for(i=0;i<4;i++) fgetc(fp);







>
>
>
>
>















>
>
>
>
>
>







456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
          if(replay_list) goto skip;
          decode_move_list(fp);
          break;
        case 0x02: // Best list
          if(best_list) goto skip;
          dum_size=0;
          getdelim(&best_list,&dum_size,0,fp);
          break;
        case 0x30 ... 0x37: // Save states
          if(savestates[i&7].data) goto skip;
          getdelim(&savestates[i&7].data,&savestates[i&7].size,0,fp);
          has_savestates=1;
          break;
        case 0x41: // Solved version
          i=fgetc(fp); i|=fgetc(fp)<<8;
          if(i==level_version) solved=1;
          break;
        case 0x42: // Mark
          replay_mark=fgetc(fp);
          replay_mark|=fgetc(fp)<<8;
          break;
        case 0x81: // Best score
          best_score=fgetc(fp);
          best_score|=fgetc(fp)<<8;
          best_score|=fgetc(fp)<<16;
          best_score|=fgetc(fp)<<24;
          break;
        case 0xB0 ... 0xB7: // Save states
          savestates[i&7].mark=fgetc(fp);
          savestates[i&7].mark|=fgetc(fp)<<8;
          savestates[i&7].pos=fgetc(fp);
          savestates[i&7].pos|=fgetc(fp)<<8;
          break;
        default: skip:
          if(i<0x40) {
            while(fgetc(fp)>0);
          } else if(i<0x80) {
            fgetc(fp); fgetc(fp);
          } else if(i<0xC0) {
            for(i=0;i<4;i++) fgetc(fp);
461
462
463
464
465
466
467







































468
469
470
471
472
473
474
        best_score=NO_SCORE;
      }
    }
  }
  if(fp) fclose(fp);
  free(buf);
}








































static void begin_level(int id) {
  const char*t;
  replay_time=0;
  if(replay_count) save_replay();
  inputs_count=0;
  replay_pos=0;







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







503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
        best_score=NO_SCORE;
      }
    }
  }
  if(fp) fclose(fp);
  free(buf);
}

static int exchange_state(int slot,int how) {
  // Return value is replay position of save state (-1 if error)
  // slot = 0 to 7
  // how = 'l' (load), 's' (save), 'x' (exchange)
  SaveState*ss=savestates+slot;
  SaveState v=*ss;
  FILE*fp;
  if(how!='s' && !v.data) {
    screen_message("Nonexisting save state");
    return -1;
  }
  if(how!='l') {
    if(ss->data) {
      if(how=='s') free(ss->data);
      ss->data=0;
      ss->size=0;
    }
    if(replay_count) {
      has_savestates=1;
      fp=open_memstream(&ss->data,&ss->size);
      if(!fp) fatal("Allocation failed\n");
      encode_move_list(fp);
      fputc(0,fp);
      fclose(fp);
    }
    ss->mark=replay_mark;
    ss->pos=replay_pos;
  }
  if(how!='s') {
    fp=fmemopen(v.data,v.size,"r");
    if(!fp) fatal("Allocation failed\n");
    decode_move_list(fp);
    fclose(fp);
    if(how=='x') free(v.data);
    replay_mark=v.mark;
  }
  return v.pos;
}

static void begin_level(int id) {
  const char*t;
  replay_time=0;
  if(replay_count) save_replay();
  inputs_count=0;
  replay_pos=0;
1365
1366
1367
1368
1369
1370
1371








1372
1373
1374
1375
1376
1377
1378
      return prev;
    case 'go': // Select level
      begin_level(number);
      return 1;
    case 'lo': // Locate me
      locate_me(number&63?:64,number/64?:64);
      return prev;








    case 'mi': // Move list import
      if(argc<2 || solution_replay) break;
      if(replay_pos) begin_level(level_id);
      do_import_moves(sqlite3_column_text(args,1));
      return 1;
    case 'ml': // Move list load
      if(argc<2 || solution_replay) break;







>
>
>
>
>
>
>
>







1446
1447
1448
1449
1450
1451
1452
1453
1454
1455
1456
1457
1458
1459
1460
1461
1462
1463
1464
1465
1466
1467
      return prev;
    case 'go': // Select level
      begin_level(number);
      return 1;
    case 'lo': // Locate me
      locate_me(number&63?:64,number/64?:64);
      return prev;
    case 'ls': // Load state
      if(solution_replay) {
        screen_message("You cannot load states during solution replay");
        return -3;
      }
      number=exchange_state(number&7,'l');
      if(number<0) return -3;
      goto restart;
    case 'mi': // Move list import
      if(argc<2 || solution_replay) break;
      if(replay_pos) begin_level(level_id);
      do_import_moves(sqlite3_column_text(args,1));
      return 1;
    case 'ml': // Move list load
      if(argc<2 || solution_replay) break;
1386
1387
1388
1389
1390
1391
1392











1393
1394
1395
1396
1397
1398
1399
    case 'rs': // Replay speed
      number+=replay_speed;
      // fall through
    case 'rS': // Replay speed (absolute)
      if(number<1) number=1; else if(number>255) number=255;
      replay_speed=number;
      return prev;











    case 'xy': // Coordinate input
      if(argc<3 || !has_xy_input) break;
      argc=sqlite3_column_int(args,1);
      number=sqlite3_column_int(args,2);
      if(argc<1 || argc>pfwidth || number<1 || number>pfheight) return 0;
      number=(number-1)|((argc-1)<<6)|0x8000;
      goto play;







>
>
>
>
>
>
>
>
>
>
>







1475
1476
1477
1478
1479
1480
1481
1482
1483
1484
1485
1486
1487
1488
1489
1490
1491
1492
1493
1494
1495
1496
1497
1498
1499
    case 'rs': // Replay speed
      number+=replay_speed;
      // fall through
    case 'rS': // Replay speed (absolute)
      if(number<1) number=1; else if(number>255) number=255;
      replay_speed=number;
      return prev;
    case 'ss': // Save state
      exchange_state(number&7,'s');
      return prev;
    case 'xs': // Exchange state
      if(solution_replay) {
        screen_message("You cannot load states during solution replay");
        return -3;
      }
      number=exchange_state(number&7,'x');
      if(number<0) return -3;
      goto restart;
    case 'xy': // Coordinate input
      if(argc<3 || !has_xy_input) break;
      argc=sqlite3_column_int(args,1);
      number=sqlite3_column_int(args,2);
      if(argc<1 || argc>pfwidth || number<1 || number>pfheight) return 0;
      number=(number-1)|((argc-1)<<6)|0x8000;
      goto play;