New binary replay format
This commit is contained in:
parent
db37e875d4
commit
ff3986c6cb
4 changed files with 219 additions and 271 deletions
|
@ -24,12 +24,12 @@ enum {
|
|||
};
|
||||
|
||||
typedef enum {
|
||||
Youmu,
|
||||
Youmu = 0,
|
||||
Marisa
|
||||
} Character;
|
||||
|
||||
typedef enum {
|
||||
YoumuOpposite,
|
||||
YoumuOpposite = 0,
|
||||
YoumuHoming,
|
||||
|
||||
MarisaLaser = YoumuOpposite,
|
||||
|
|
409
src/replay.c
409
src/replay.c
|
@ -14,39 +14,49 @@
|
|||
|
||||
#include "global.h"
|
||||
#include "paths/native.h"
|
||||
#include "taisei_err.h"
|
||||
|
||||
static uint8_t replay_magic_header[] = {
|
||||
0x68, 0x6f, 0x6e, 0x6f, 0xe2, 0x9d, 0xa4, 0x75, 0x6d, 0x69
|
||||
};
|
||||
|
||||
void replay_init(Replay *rpy) {
|
||||
memset(rpy, 0, sizeof(Replay));
|
||||
rpy->active = True;
|
||||
|
||||
rpy->playername = malloc(strlen(tconfig.strval[PLAYERNAME]) + 1);
|
||||
strcpy(rpy->playername, tconfig.strval[PLAYERNAME]);
|
||||
|
||||
printf("replay_init(): replay initialized for writting\n");
|
||||
}
|
||||
|
||||
ReplayStage* replay_init_stage(Replay *rpy, StageInfo *stage, int seed, Player *plr) {
|
||||
ReplayStage* replay_init_stage(Replay *rpy, StageInfo *stage, uint64_t seed, Player *plr) {
|
||||
ReplayStage *s;
|
||||
|
||||
rpy->stages = (ReplayStage*)realloc(rpy->stages, sizeof(ReplayStage) * (++rpy->stgcount));
|
||||
s = &(rpy->stages[rpy->stgcount-1]);
|
||||
memset(s, 0, sizeof(ReplayStage));
|
||||
|
||||
s->capacity = REPLAY_ALLOC_INITIAL;
|
||||
s->events = (ReplayEvent*)malloc(sizeof(ReplayEvent) * s->capacity);
|
||||
s->capacity = REPLAY_ALLOC_INITIAL;
|
||||
s->events = (ReplayEvent*)malloc(sizeof(ReplayEvent) * s->capacity);
|
||||
|
||||
s->stage = stage->id;
|
||||
s->seed = seed;
|
||||
s->diff = global.diff;
|
||||
s->points = global.points;
|
||||
|
||||
s->plr_pos = plr->pos;
|
||||
s->plr_focus = plr->focus;
|
||||
s->plr_fire = plr->fire;
|
||||
s->plr_char = plr->cha;
|
||||
s->plr_shot = plr->shot;
|
||||
s->plr_lifes = plr->lifes;
|
||||
s->plr_bombs = plr->bombs;
|
||||
s->plr_power = plr->power;
|
||||
s->plr_mflags = plr->moveflags;
|
||||
s->stage = stage->id;
|
||||
s->seed = seed;
|
||||
s->diff = global.diff;
|
||||
s->points = global.points;
|
||||
|
||||
s->plr_pos_x._double = creal(plr->pos);
|
||||
s->plr_pos_y._double = cimag(plr->pos);
|
||||
|
||||
s->plr_focus = plr->focus;
|
||||
s->plr_fire = plr->fire;
|
||||
s->plr_char = plr->cha;
|
||||
s->plr_shot = plr->shot;
|
||||
s->plr_lifes = plr->lifes;
|
||||
s->plr_bombs = plr->bombs;
|
||||
s->plr_power._double = plr->power;
|
||||
s->plr_moveflags = plr->moveflags;
|
||||
|
||||
printf("replay_init_stage(): created a new stage for writting\n");
|
||||
replay_select(rpy, rpy->stgcount-1);
|
||||
return s;
|
||||
|
@ -81,19 +91,19 @@ ReplayStage* replay_select(Replay *rpy, int stage) {
|
|||
return rpy->current;
|
||||
}
|
||||
|
||||
void replay_event(Replay *rpy, int type, int key) {
|
||||
void replay_event(Replay *rpy, uint8_t type, uint16_t key) {
|
||||
if(!rpy->active)
|
||||
return;
|
||||
|
||||
ReplayStage *s = rpy->current;
|
||||
ReplayEvent *e = &(s->events[s->ecount]);
|
||||
e->frame = global.frames;
|
||||
e->type = (char)type;
|
||||
e->key = (short)key;
|
||||
e->type = type;
|
||||
e->key = key;
|
||||
s->ecount++;
|
||||
|
||||
if(s->ecount >= s->capacity) {
|
||||
printf("Replay reached it's capacity of %d, reallocating\n", s->capacity);
|
||||
printf("Replay reached its capacity of %d, reallocating\n", s->capacity);
|
||||
s->capacity += REPLAY_ALLOC_ADDITIONAL;
|
||||
s->events = (ReplayEvent*)realloc(s->events, sizeof(ReplayEvent) * s->capacity);
|
||||
printf("The new capacity is %d\n", s->capacity);
|
||||
|
@ -103,219 +113,146 @@ void replay_event(Replay *rpy, int type, int key) {
|
|||
printf("The replay is OVER\n");
|
||||
}
|
||||
|
||||
void replay_write_separator(FILE *file) {
|
||||
fputs(":", file);
|
||||
void replay_write_string(SDL_RWops *file, char *str) {
|
||||
SDL_WriteLE16(file, strlen(str));
|
||||
SDL_RWwrite(file, str, 1, strlen(str));
|
||||
}
|
||||
|
||||
void replay_write_string(FILE *file, char *str) {
|
||||
fputs(str, file);
|
||||
replay_write_separator(file);
|
||||
}
|
||||
int replay_write_stage_event(ReplayEvent *evt, SDL_RWops *file) {
|
||||
SDL_WriteLE32(file, evt->frame);
|
||||
SDL_WriteU8(file, evt->type);
|
||||
SDL_WriteLE16(file, evt->key);
|
||||
|
||||
void replay_write_int(FILE *file, int val) {
|
||||
fprintf(file, "%d", val);
|
||||
replay_write_separator(file);
|
||||
}
|
||||
|
||||
void replay_write_double(FILE *file, double val) {
|
||||
fprintf(file, "%f", val);
|
||||
replay_write_separator(file);
|
||||
}
|
||||
|
||||
void replay_write_complex(FILE *file, complex val) {
|
||||
replay_write_double(file, creal(val));
|
||||
replay_write_double(file, cimag(val));
|
||||
}
|
||||
|
||||
int replay_write(Replay *rpy, FILE *file) {
|
||||
int i, j;
|
||||
|
||||
// header
|
||||
replay_write_int(file, REPLAY_MAGICNUMBER);
|
||||
replay_write_string(file, tconfig.strval[PLAYERNAME]);
|
||||
replay_write_string(file, "Get out of here, you nasty cheater!");
|
||||
replay_write_int(file, rpy->stgcount);
|
||||
|
||||
for(j = 0; j < rpy->stgcount; ++j) {
|
||||
ReplayStage *stg = &(rpy->stages[j]);
|
||||
|
||||
// initial game settings
|
||||
replay_write_int(file, stg->stage);
|
||||
replay_write_int(file, stg->seed);
|
||||
replay_write_int(file, stg->diff);
|
||||
replay_write_int(file, stg->points);
|
||||
|
||||
// initial player settings
|
||||
replay_write_int(file, stg->plr_char);
|
||||
replay_write_int(file, stg->plr_shot);
|
||||
replay_write_complex(file, stg->plr_pos);
|
||||
replay_write_int(file, stg->plr_focus);
|
||||
replay_write_int(file, stg->plr_fire);
|
||||
replay_write_double(file, stg->plr_power);
|
||||
replay_write_int(file, stg->plr_lifes);
|
||||
replay_write_int(file, stg->plr_bombs);
|
||||
replay_write_int(file, stg->plr_mflags);
|
||||
|
||||
// events
|
||||
replay_write_int(file, stg->ecount);
|
||||
|
||||
for(i = 0; i < stg->ecount; ++i) {
|
||||
ReplayEvent *e = &(stg->events[i]);
|
||||
replay_write_int(file, e->frame);
|
||||
replay_write_int(file, e->type);
|
||||
replay_write_int(file, e->key);
|
||||
}
|
||||
}
|
||||
|
||||
return True;
|
||||
}
|
||||
|
||||
// read order
|
||||
enum {
|
||||
// header
|
||||
RPY_H_MAGIC = 0,
|
||||
RPY_H_META1,
|
||||
RPY_H_META2,
|
||||
RPY_H_STAGECOUNT,
|
||||
|
||||
// initial game settings
|
||||
RPY_G_STAGE,
|
||||
RPY_G_SEED,
|
||||
RPY_G_DIFF,
|
||||
RPY_G_PTS,
|
||||
|
||||
// initial player settings
|
||||
RPY_P_CHAR,
|
||||
RPY_P_SHOT,
|
||||
RPY_P_POSREAL,
|
||||
RPY_P_POSIMAG,
|
||||
RPY_P_FOCUS,
|
||||
RPY_P_FIRE,
|
||||
RPY_P_POWER,
|
||||
RPY_P_LIFES,
|
||||
RPY_P_BOMBS,
|
||||
RPY_P_MFLAGS,
|
||||
|
||||
// events
|
||||
RPY_E_COUNT,
|
||||
RPY_E_FRAME,
|
||||
RPY_E_TYPE,
|
||||
RPY_E_KEY
|
||||
};
|
||||
int replay_write_stage(ReplayStage *stg, SDL_RWops *file) {
|
||||
int i;
|
||||
|
||||
#define INTOF(s) ((int)strtol(s, NULL, 10))
|
||||
#define FLOATOF(s) ((float)strtod(s, NULL))
|
||||
SDL_WriteLE32(file, stg->stage);
|
||||
SDL_WriteLE32(file, stg->seed);
|
||||
SDL_WriteU8(file, stg->diff);
|
||||
SDL_WriteLE32(file, stg->points);
|
||||
SDL_WriteU8(file, stg->plr_char);
|
||||
SDL_WriteU8(file, stg->plr_shot);
|
||||
SDL_WriteLE64(file, stg->plr_pos_x._int);
|
||||
SDL_WriteLE64(file, stg->plr_pos_y._int);
|
||||
SDL_WriteU8(file, stg->plr_focus);
|
||||
SDL_WriteU8(file, stg->plr_fire);
|
||||
SDL_WriteLE64(file, stg->plr_power._int);
|
||||
SDL_WriteU8(file, stg->plr_lifes);
|
||||
SDL_WriteU8(file, stg->plr_bombs);
|
||||
SDL_WriteU8(file, stg->plr_moveflags);
|
||||
SDL_WriteLE32(file, stg->ecount);
|
||||
|
||||
int replay_read(Replay *rpy, FILE *file) {
|
||||
int readstate = RPY_H_MAGIC;
|
||||
int bufidx = 0, eidx = 0;
|
||||
char buf[REPLAY_READ_MAXSTRLEN], c;
|
||||
ReplayStage *s;
|
||||
int stgnum = 0;
|
||||
memset(rpy, 0, sizeof(Replay));
|
||||
|
||||
while((c = fgetc(file)) != EOF) {
|
||||
if(c == ':') {
|
||||
buf[bufidx] = 0;
|
||||
bufidx = 0;
|
||||
|
||||
switch(readstate) {
|
||||
case RPY_H_MAGIC: {
|
||||
int magic = INTOF(buf);
|
||||
if(magic != REPLAY_MAGICNUMBER) {
|
||||
printf("replay_read(): invalid magic number: %d\n", magic);
|
||||
replay_destroy(rpy);
|
||||
return False;
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
case RPY_H_META1:
|
||||
stralloc(&rpy->playername, buf);
|
||||
printf("replay_read(): replay META1 is: %s\n", buf);
|
||||
break;
|
||||
|
||||
case RPY_H_META2: // skip
|
||||
break;
|
||||
|
||||
case RPY_H_STAGECOUNT:
|
||||
rpy->stgcount = INTOF(buf);
|
||||
if(rpy->stgcount <= 0) {
|
||||
printf("replay_read(): insane stage count: %i\n", rpy->stgcount);
|
||||
replay_destroy(rpy);
|
||||
return False;
|
||||
}
|
||||
rpy->stages = (ReplayStage*)malloc(sizeof(ReplayStage) * rpy->stgcount);
|
||||
s = &(rpy->stages[0]);
|
||||
memset(s, 0, sizeof(ReplayStage));
|
||||
break;
|
||||
|
||||
case RPY_G_STAGE: s->stage = INTOF(buf); break;
|
||||
case RPY_G_SEED: s->seed = INTOF(buf); break;
|
||||
case RPY_G_DIFF: s->diff = INTOF(buf); break;
|
||||
case RPY_G_PTS: s->points = INTOF(buf); break;
|
||||
|
||||
case RPY_P_CHAR: s->plr_char = INTOF(buf); break;
|
||||
case RPY_P_SHOT: s->plr_shot = INTOF(buf); break;
|
||||
case RPY_P_POSREAL: s->plr_pos = FLOATOF(buf); break;
|
||||
case RPY_P_POSIMAG: s->plr_pos += FLOATOF(buf) * I;break;
|
||||
case RPY_P_FOCUS: s->plr_focus = INTOF(buf); break;
|
||||
case RPY_P_FIRE: s->plr_fire = INTOF(buf); break;
|
||||
case RPY_P_POWER: s->plr_power = FLOATOF(buf); break;
|
||||
case RPY_P_LIFES: s->plr_lifes = INTOF(buf); break;
|
||||
case RPY_P_BOMBS: s->plr_bombs = INTOF(buf); break;
|
||||
case RPY_P_MFLAGS: s->plr_mflags = INTOF(buf); break;
|
||||
|
||||
case RPY_E_COUNT:
|
||||
s->capacity = s->ecount = INTOF(buf);
|
||||
if(s->capacity <= 0) {
|
||||
printf("replay_read(): insane capacity in stage %i: %i\n", stgnum, s->capacity);
|
||||
replay_destroy(rpy);
|
||||
return False;
|
||||
}
|
||||
s->events = (ReplayEvent*)malloc(sizeof(ReplayEvent) * s->capacity);
|
||||
break;
|
||||
|
||||
case RPY_E_FRAME: s->events[eidx].frame = INTOF(buf); break;
|
||||
case RPY_E_TYPE: s->events[eidx].type = INTOF(buf); break;
|
||||
case RPY_E_KEY:
|
||||
s->events[eidx].key = INTOF(buf);
|
||||
eidx++;
|
||||
|
||||
if(eidx == s->capacity) {
|
||||
if((++stgnum) >= rpy->stgcount)
|
||||
return True;
|
||||
s = &(rpy->stages[stgnum]);
|
||||
readstate = RPY_G_STAGE;
|
||||
eidx = 0;
|
||||
continue;
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
if(readstate == RPY_E_KEY)
|
||||
readstate = RPY_E_FRAME;
|
||||
else
|
||||
++readstate;
|
||||
} else {
|
||||
buf[bufidx++] = c;
|
||||
if(bufidx >= REPLAY_READ_MAXSTRLEN) {
|
||||
printf("replay_read(): item is too long\n");
|
||||
replay_destroy(rpy);
|
||||
return False;
|
||||
}
|
||||
for(i = 0; i < stg->ecount; ++i) {
|
||||
if(!replay_write_stage_event(&stg->events[i], file)) {
|
||||
return False;
|
||||
}
|
||||
}
|
||||
|
||||
printf("replay_read(): replay isn't properly terminated\n");
|
||||
replay_destroy(rpy);
|
||||
return False;
|
||||
|
||||
return True;
|
||||
}
|
||||
|
||||
#undef FLOATOF
|
||||
#undef INTOF
|
||||
int replay_write(Replay *rpy, SDL_RWops *file) {
|
||||
uint8_t *u8_p;
|
||||
int i;
|
||||
|
||||
for(u8_p = replay_magic_header; *u8_p; ++u8_p) {
|
||||
SDL_WriteU8(file, *u8_p);
|
||||
}
|
||||
|
||||
SDL_WriteLE16(file, REPLAY_STRUCT_VERSION);
|
||||
replay_write_string(file, rpy->playername);
|
||||
SDL_WriteLE32(file, rpy->stgcount);
|
||||
|
||||
for(i = 0; i < rpy->stgcount; ++i) {
|
||||
if(!replay_write_stage(&rpy->stages[i], file)) {
|
||||
return False;
|
||||
}
|
||||
}
|
||||
|
||||
return True;
|
||||
}
|
||||
|
||||
void replay_read_string(SDL_RWops *file, char **ptr) {
|
||||
size_t len = SDL_ReadLE16(file);
|
||||
|
||||
*ptr = malloc(len + 1);
|
||||
memset(*ptr, 0, len + 1);
|
||||
|
||||
SDL_RWread(file, *ptr, 1, len);
|
||||
}
|
||||
|
||||
int replay_read(Replay *rpy, SDL_RWops *file) {
|
||||
uint8_t *u8_p;
|
||||
int i, j;
|
||||
|
||||
memset(rpy, 0, sizeof(Replay));
|
||||
|
||||
for(u8_p = replay_magic_header; *u8_p; ++u8_p) {
|
||||
SDL_WriteU8(file, *u8_p);
|
||||
if(SDL_ReadU8(file) != *u8_p) {
|
||||
warnx("replay_read(): incorrect header");
|
||||
return False;
|
||||
}
|
||||
}
|
||||
|
||||
if(SDL_ReadLE16(file) != REPLAY_STRUCT_VERSION) {
|
||||
warnx("replay_read(): incorrect version");
|
||||
return False;
|
||||
}
|
||||
|
||||
replay_read_string(file, &rpy->playername);
|
||||
|
||||
rpy->stgcount = SDL_ReadLE32(file);
|
||||
|
||||
if(!rpy->stgcount) {
|
||||
warnx("replay_read(): no stages in replay");
|
||||
return False;
|
||||
}
|
||||
|
||||
rpy->stages = malloc(sizeof(ReplayStage) * rpy->stgcount);
|
||||
memset(rpy->stages, 0, sizeof(ReplayStage) * rpy->stgcount);
|
||||
|
||||
for(i = 0; i < rpy->stgcount; ++i) {
|
||||
ReplayStage *stg = &rpy->stages[i];
|
||||
|
||||
stg->stage = SDL_ReadLE32(file);
|
||||
stg->seed = SDL_ReadLE32(file);
|
||||
stg->diff = SDL_ReadU8(file);
|
||||
stg->points = SDL_ReadLE32(file);
|
||||
stg->plr_char = SDL_ReadU8(file);
|
||||
stg->plr_shot = SDL_ReadU8(file);
|
||||
stg->plr_pos_x._int = SDL_ReadLE64(file);
|
||||
stg->plr_pos_y._int = SDL_ReadLE64(file);
|
||||
stg->plr_focus = SDL_ReadU8(file);
|
||||
stg->plr_fire = SDL_ReadU8(file);
|
||||
stg->plr_power._int = SDL_ReadLE64(file);
|
||||
stg->plr_lifes = SDL_ReadU8(file);
|
||||
stg->plr_bombs = SDL_ReadU8(file);
|
||||
stg->plr_moveflags = SDL_ReadU8(file);
|
||||
stg->ecount = SDL_ReadLE32(file);
|
||||
|
||||
if(!stg->ecount) {
|
||||
warnx("replay_read(): no events in stage");
|
||||
return False;
|
||||
}
|
||||
|
||||
stg->events = malloc(sizeof(ReplayEvent) * stg->ecount);
|
||||
memset(stg->events, 0, sizeof(ReplayEvent) * stg->ecount);
|
||||
|
||||
for(j = 0; j < stg->ecount; ++j) {
|
||||
ReplayEvent *evt = &stg->events[j];
|
||||
|
||||
evt->frame = SDL_ReadLE32(file);
|
||||
evt->type = SDL_ReadU8(file);
|
||||
evt->key = SDL_ReadLE16(file);
|
||||
}
|
||||
}
|
||||
|
||||
return True;
|
||||
}
|
||||
|
||||
char* replay_getpath(char *name, int ext) {
|
||||
char *p = (char*)malloc(strlen(get_replays_path()) + strlen(name) + strlen(REPLAY_EXTENSION) + 3);
|
||||
|
@ -330,18 +267,16 @@ int replay_save(Replay *rpy, char *name) {
|
|||
char *p = replay_getpath(name, !strendswith(name, REPLAY_EXTENSION));
|
||||
printf("replay_save(): saving %s\n", p);
|
||||
|
||||
FILE *fp = fopen(p, "w");
|
||||
|
||||
SDL_RWops *file = SDL_RWFromFile(p, "wb");
|
||||
free(p);
|
||||
|
||||
if(!fp) {
|
||||
printf("replay_save(): fopen() failed\n");
|
||||
if(!file) {
|
||||
warnx("replay_save(): SDL_RWFromFile() failed: %s\n", SDL_GetError());
|
||||
return False;
|
||||
}
|
||||
|
||||
int result = replay_write(rpy, fp);
|
||||
fflush(fp);
|
||||
fclose(fp);
|
||||
int result = replay_write(rpy, file);
|
||||
SDL_RWclose(file);
|
||||
return result;
|
||||
}
|
||||
|
||||
|
@ -349,17 +284,21 @@ int replay_load(Replay *rpy, char *name) {
|
|||
char *p = replay_getpath(name, !strendswith(name, REPLAY_EXTENSION));
|
||||
printf("replay_load(): loading %s\n", p);
|
||||
|
||||
FILE *fp = fopen(p, "r");
|
||||
|
||||
SDL_RWops *file = SDL_RWFromFile(p, "rb");
|
||||
free(p);
|
||||
|
||||
if(!fp) {
|
||||
printf("replay_load(): fopen() failed\n");
|
||||
if(!file) {
|
||||
warnx("replay_save(): SDL_RWFromFile() failed: %s\n", SDL_GetError());
|
||||
return False;
|
||||
}
|
||||
|
||||
int result = replay_read(rpy, fp);
|
||||
fclose(fp);
|
||||
int result = replay_read(rpy, file);
|
||||
|
||||
if(!result) {
|
||||
replay_destroy(rpy);
|
||||
}
|
||||
|
||||
SDL_RWclose(file);
|
||||
return result;
|
||||
}
|
||||
|
||||
|
|
65
src/replay.h
65
src/replay.h
|
@ -12,33 +12,47 @@
|
|||
#include "stage.h"
|
||||
#include "player.h"
|
||||
|
||||
#define REPLAY_ALLOC_INITIAL 1000
|
||||
#define REPLAY_ALLOC_ADDITIONAL 500
|
||||
#define REPLAY_EXTENSION "tsr"
|
||||
#define REPLAY_STRUCT_VERSION 0
|
||||
#define REPLAY_MAX_NAME_LENGTH 128
|
||||
|
||||
typedef union float64_u {
|
||||
// ASSUMPTION: the "double" type is an IEEE 754 binary64
|
||||
|
||||
double _double;
|
||||
uint64_t _int;
|
||||
} float64_u;
|
||||
|
||||
typedef struct ReplayEvent {
|
||||
int frame;
|
||||
char type;
|
||||
short key;
|
||||
uint32_t frame;
|
||||
uint8_t type;
|
||||
uint16_t key;
|
||||
} ReplayEvent;
|
||||
|
||||
typedef struct ReplayStage {
|
||||
// initial game settings
|
||||
int stage;
|
||||
int seed; // this also happens to be the game initiation time - and we use this property, don't break it please
|
||||
int diff;
|
||||
int points;
|
||||
uint32_t stage;
|
||||
uint32_t seed; // this also happens to be the game initiation time - and we use this property, don't break it please
|
||||
uint8_t diff;
|
||||
uint32_t points;
|
||||
|
||||
// initial player settings
|
||||
Character plr_char;
|
||||
ShotMode plr_shot;
|
||||
complex plr_pos;
|
||||
short plr_focus;
|
||||
short plr_fire;
|
||||
float plr_power;
|
||||
int plr_lifes;
|
||||
int plr_bombs;
|
||||
int plr_mflags;
|
||||
uint8_t plr_char;
|
||||
uint8_t plr_shot;
|
||||
float64_u plr_pos_x;
|
||||
float64_u plr_pos_y;
|
||||
uint8_t plr_focus;
|
||||
uint8_t plr_fire;
|
||||
float64_u plr_power;
|
||||
uint8_t plr_lifes;
|
||||
uint8_t plr_bombs;
|
||||
uint8_t plr_moveflags;
|
||||
|
||||
// events
|
||||
ReplayEvent *events;
|
||||
int ecount;
|
||||
uint32_t ecount;
|
||||
|
||||
// The fields below should not be stored
|
||||
int capacity;
|
||||
|
@ -47,11 +61,12 @@ typedef struct ReplayStage {
|
|||
|
||||
typedef struct Replay {
|
||||
// metadata
|
||||
// uint16_t version;
|
||||
char *playername;
|
||||
|
||||
// stages (NOTE FOR FUTURE: stages do not represent stage runs in particular, they can and should be used to store stuff like spell practice runs, too)
|
||||
ReplayStage *stages;
|
||||
int stgcount;
|
||||
uint32_t stgcount;
|
||||
|
||||
// The fields below should not be stored
|
||||
int active;
|
||||
|
@ -65,24 +80,18 @@ enum {
|
|||
};
|
||||
|
||||
void replay_init(Replay *rpy);
|
||||
ReplayStage* replay_init_stage(Replay *rpy, StageInfo *stage, int seed, Player *plr);
|
||||
ReplayStage* replay_init_stage(Replay *rpy, StageInfo *stage, uint64_t seed, Player *plr);
|
||||
void replay_destroy(Replay *rpy);
|
||||
void replay_destroy_stage(ReplayStage *stage);
|
||||
ReplayStage* replay_select(Replay *rpy, int stage);
|
||||
void replay_event(Replay *rpy, int type, int key);
|
||||
void replay_event(Replay *rpy, uint8_t type, uint16_t key);
|
||||
|
||||
int replay_write(Replay *rpy, FILE *file);
|
||||
int replay_read(Replay *rpy, FILE *file);
|
||||
int replay_write(Replay *rpy, SDL_RWops *file);
|
||||
int replay_read(Replay *rpy, SDL_RWops *file);
|
||||
|
||||
char* replay_getpath(char *name, int ext); // must be freed
|
||||
int replay_save(Replay *rpy, char *name);
|
||||
int replay_load(Replay *rpy, char *name);
|
||||
void replay_copy(Replay *dst, Replay *src);
|
||||
|
||||
#define REPLAY_ALLOC_INITIAL 1000
|
||||
#define REPLAY_ALLOC_ADDITIONAL 500
|
||||
#define REPLAY_MAGICNUMBER 1337
|
||||
#define REPLAY_EXTENSION "tsr"
|
||||
#define REPLAY_READ_MAXSTRLEN 128
|
||||
|
||||
#endif
|
||||
|
|
12
src/stage.c
12
src/stage.c
|
@ -459,7 +459,7 @@ void stage_loop(StageInfo* info, StageRule start, StageRule end, StageRule draw,
|
|||
return;
|
||||
}
|
||||
|
||||
int seed = time(0);
|
||||
uint32_t seed = (uint32_t)time(0);
|
||||
tsrand_switch(&global.rand_game);
|
||||
tsrand_seed_p(&global.rand_game, seed);
|
||||
stage_start();
|
||||
|
@ -467,26 +467,26 @@ void stage_loop(StageInfo* info, StageRule start, StageRule end, StageRule draw,
|
|||
if(global.replaymode == REPLAY_RECORD) {
|
||||
if(global.replay.active)
|
||||
replay_init_stage(&global.replay, info, seed, &global.plr);
|
||||
printf("Random seed: %d\n", seed);
|
||||
printf("Random seed: %u\n", seed);
|
||||
} else {
|
||||
ReplayStage *stg = global.replay.current;
|
||||
printf("REPLAY_PLAY mode: %d events, stage: \"%s\"\n", stg->ecount, stage_get(stg->stage)->title);
|
||||
|
||||
tsrand_seed_p(&global.rand_game, stg->seed);
|
||||
printf("Random seed: %d\n", stg->seed);
|
||||
printf("Random seed: %u\n", stg->seed);
|
||||
|
||||
global.diff = stg->diff;
|
||||
global.points = stg->points;
|
||||
|
||||
global.plr.shot = stg->plr_shot;
|
||||
global.plr.cha = stg->plr_char;
|
||||
global.plr.pos = stg->plr_pos;
|
||||
global.plr.pos = stg->plr_pos_x._double + I * stg->plr_pos_y._double;
|
||||
global.plr.focus = stg->plr_focus;
|
||||
global.plr.fire = stg->plr_fire;
|
||||
global.plr.lifes = stg->plr_lifes;
|
||||
global.plr.bombs = stg->plr_bombs;
|
||||
global.plr.power = stg->plr_power;
|
||||
global.plr.moveflags = stg->plr_mflags;
|
||||
global.plr.power = stg->plr_power._double;
|
||||
global.plr.moveflags = stg->plr_moveflags;
|
||||
|
||||
stg->playpos = 0;
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue