︙ | | | ︙ | |
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;
|
︙ | | | ︙ | |