rewrote replay_write and replay_read to use a text-based format
This commit is contained in:
parent
65a69e4974
commit
6afad43f83
3 changed files with 160 additions and 84 deletions
|
@ -50,7 +50,7 @@ troll:
|
|||
void start_replay(void *arg) {
|
||||
char p[1337];
|
||||
snprintf(p, 1337, "%s/test.%s", get_config_path(), REPLAY_EXTENSION);
|
||||
FILE *fp = fopen(p, "rb");
|
||||
FILE *fp = fopen(p, "r");
|
||||
printf("%s\n", p);
|
||||
replay_read(&global.replay, fp);
|
||||
fclose(fp);
|
||||
|
|
241
src/replay.c
241
src/replay.c
|
@ -69,106 +69,181 @@ void replay_event(Replay *rpy, int type, int key) {
|
|||
|
||||
char p[1337];
|
||||
snprintf(p, 1337, "%s/test.%s", get_config_path(), REPLAY_EXTENSION);
|
||||
FILE *fp = fopen(p, "wb");
|
||||
FILE *fp = fopen(p, "w");
|
||||
replay_write(rpy, fp);
|
||||
fflush(fp);
|
||||
fclose(fp);
|
||||
}
|
||||
}
|
||||
|
||||
#define WRITE(type, value, count) if(fwrite(value, sizeof(type), count, file) != (count)) { \
|
||||
printf("replay_write(): fwrite failed at (%s)(%s)\n", #type, #value); \
|
||||
return False; \
|
||||
void replay_write_separator(FILE *file) {
|
||||
fputs(":", file);
|
||||
}
|
||||
|
||||
int replay_write(Replay *rpy, FILE* file) {
|
||||
char *head = "Taisei replay file";
|
||||
short headlen = strlen(head);
|
||||
short magic = REPLAY_MAGICNUMBER;
|
||||
char replays = 1;
|
||||
void replay_write_string(FILE *file, char *str) {
|
||||
fputs(str, file);
|
||||
replay_write_separator(file);
|
||||
}
|
||||
|
||||
void replay_write_int(FILE *file, int val) {
|
||||
fprintf(file, "%d", val);
|
||||
replay_write_separator(file);
|
||||
}
|
||||
|
||||
void replay_write_char(FILE *file, char val) {
|
||||
fprintf(file, "%c", 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;
|
||||
|
||||
// replay header
|
||||
WRITE(short, &magic, 1)
|
||||
WRITE(short, &headlen, 1)
|
||||
WRITE(char, head, headlen)
|
||||
// header
|
||||
replay_write_int(file, REPLAY_MAGICNUMBER);
|
||||
replay_write_string(file, "Taisei replay file");
|
||||
replay_write_string(file, "This file is not for your eyes, move on");
|
||||
replay_write_int(file, 1);
|
||||
|
||||
// amount of replays (stages) stored in this file (may be used later)
|
||||
WRITE(char, &replays, 1)
|
||||
|
||||
// initial game settigs
|
||||
WRITE(int, &rpy->stage, 1)
|
||||
WRITE(int, &rpy->seed, 1)
|
||||
WRITE(int, &rpy->stage, 1)
|
||||
WRITE(int, &rpy->diff, 1)
|
||||
WRITE(int, &rpy->points, 1)
|
||||
// initial game settings
|
||||
replay_write_int(file, rpy->stage);
|
||||
replay_write_int(file, rpy->seed);
|
||||
replay_write_int(file, rpy->diff);
|
||||
replay_write_int(file, rpy->points);
|
||||
|
||||
// initial player settings
|
||||
WRITE(Character, &rpy->plr_char, 1)
|
||||
WRITE(ShotMode, &rpy->plr_shot, 1)
|
||||
WRITE(complex, &rpy->plr_pos, 1)
|
||||
WRITE(float, &rpy->plr_power, 1)
|
||||
WRITE(int, &rpy->plr_lifes, 1)
|
||||
WRITE(int, &rpy->plr_bombs, 1)
|
||||
replay_write_int(file, rpy->plr_char);
|
||||
replay_write_int(file, rpy->plr_shot);
|
||||
replay_write_complex(file, rpy->plr_pos);
|
||||
replay_write_double(file, rpy->plr_power);
|
||||
replay_write_int(file, rpy->plr_lifes);
|
||||
replay_write_int(file, rpy->plr_bombs);
|
||||
|
||||
// events
|
||||
WRITE(int, &rpy->ecount, 1)
|
||||
WRITE(ReplayEvent, rpy->events, rpy->ecount)
|
||||
replay_write_int(file, rpy->ecount);
|
||||
|
||||
return True;
|
||||
}
|
||||
|
||||
#define READ(type, ptr, count) if(fread(ptr, sizeof(type), count, file) != (count)) { \
|
||||
printf("replay_read(): fread failed at (%s)(%s)\n", #type, #ptr); \
|
||||
return False; \
|
||||
} else printf("replay_read(): (%s)(%s)\n", #type, #ptr);
|
||||
|
||||
int replay_read(Replay *rpy, FILE* file) {
|
||||
char *head;
|
||||
short headlen;
|
||||
short magic;
|
||||
char replays;
|
||||
|
||||
printf("replay_read()\n");
|
||||
|
||||
// replay header
|
||||
READ(short, &magic, 1)
|
||||
|
||||
if(magic != REPLAY_MAGICNUMBER) {
|
||||
printf("replay_read(): invalid magic number (got %d, expected %d).\n", magic, REPLAY_MAGICNUMBER);
|
||||
return False;
|
||||
for(i = 0; i < rpy->ecount; ++i) {
|
||||
ReplayEvent *e = &(rpy->events[i]);
|
||||
replay_write_int(file, e->frame);
|
||||
|
||||
// trollface.tsr
|
||||
replay_write_char(file, e->type);
|
||||
replay_write_char(file, e->key);
|
||||
}
|
||||
|
||||
READ(short, &headlen, 1)
|
||||
head = (char*)malloc(headlen+1);
|
||||
READ(char, head, headlen)
|
||||
printf("replay_read(): %s\n", head);
|
||||
|
||||
// amount of replays (stages) stored in this file (may be used later)
|
||||
READ(char, &replays, 1)
|
||||
|
||||
// initial game settigs
|
||||
READ(int, &rpy->stage, 1)
|
||||
READ(int, &rpy->seed, 1)
|
||||
READ(int, &rpy->stage, 1)
|
||||
READ(int, &rpy->diff, 1)
|
||||
READ(int, &rpy->points, 1)
|
||||
|
||||
// initial player settings
|
||||
READ(Character, &rpy->plr_char, 1)
|
||||
READ(ShotMode, &rpy->plr_shot, 1)
|
||||
READ(complex, &rpy->plr_pos, 1)
|
||||
READ(float, &rpy->plr_power, 1)
|
||||
READ(int, &rpy->plr_lifes, 1)
|
||||
READ(int, &rpy->plr_bombs, 1)
|
||||
|
||||
// events
|
||||
READ(int, &rpy->ecount, 1)
|
||||
rpy->capacity = rpy->ecount;
|
||||
rpy->events = (ReplayEvent*)malloc(sizeof(ReplayEvent) * rpy->capacity);
|
||||
READ(ReplayEvent, rpy->events, rpy->ecount)
|
||||
|
||||
return True;
|
||||
}
|
||||
|
||||
#undef WRITE
|
||||
#undef READ
|
||||
// read order
|
||||
enum {
|
||||
// header
|
||||
RPY_H_MAGIC = 0,
|
||||
RPY_H_META1,
|
||||
RPY_H_META2,
|
||||
RPY_H_REPLAYCOUNT,
|
||||
|
||||
// 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_POWER,
|
||||
RPY_P_LIFES,
|
||||
RPY_P_BOMBS,
|
||||
|
||||
// events
|
||||
RPY_E_COUNT,
|
||||
RPY_E_FRAME,
|
||||
RPY_E_TYPE,
|
||||
RPY_E_KEY
|
||||
};
|
||||
|
||||
#define INTOF(s) ((int)strtol(s, NULL, 10))
|
||||
#define FLOATOF(s) ((float)strtod(s, NULL))
|
||||
|
||||
int replay_read(Replay *rpy, FILE *file) {
|
||||
int readstate = RPY_H_MAGIC;
|
||||
int bufidx = 0, eidx = 0;
|
||||
char buf[REPLAY_READ_MAXSTRLEN], c;
|
||||
|
||||
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);
|
||||
return False;
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
case RPY_H_META1:
|
||||
printf("replay_read(): %s\n", buf);
|
||||
break;
|
||||
|
||||
case RPY_H_META2: case RPY_H_REPLAYCOUNT: // skip
|
||||
break;
|
||||
|
||||
case RPY_G_STAGE: rpy->stage = INTOF(buf); break;
|
||||
case RPY_G_SEED: rpy->seed = INTOF(buf); break;
|
||||
case RPY_G_DIFF: rpy->diff = INTOF(buf); break;
|
||||
case RPY_G_PTS: rpy->points = INTOF(buf); break;
|
||||
|
||||
case RPY_P_CHAR: rpy->plr_char = INTOF(buf); break;
|
||||
case RPY_P_SHOT: rpy->plr_shot = INTOF(buf); break;
|
||||
case RPY_P_POSREAL: rpy->plr_pos = INTOF(buf); break;
|
||||
case RPY_P_POSIMAG: rpy->plr_pos += INTOF(buf) * I; break;
|
||||
case RPY_P_POWER: rpy->plr_power = FLOATOF(buf); break;
|
||||
case RPY_P_LIFES: rpy->plr_lifes = INTOF(buf); break;
|
||||
case RPY_P_BOMBS: rpy->plr_bombs = INTOF(buf); break;
|
||||
|
||||
case RPY_E_COUNT:
|
||||
rpy->capacity = rpy->ecount = INTOF(buf);
|
||||
rpy->events = (ReplayEvent*)malloc(sizeof(ReplayEvent) * rpy->capacity);
|
||||
break;
|
||||
|
||||
case RPY_E_FRAME: rpy->events[eidx].frame = INTOF(buf); break;
|
||||
case RPY_E_TYPE: rpy->events[eidx].type = buf[0]; break;
|
||||
case RPY_E_KEY: rpy->events[eidx].key = buf[0]; eidx++; break;
|
||||
}
|
||||
|
||||
if(rpy->capacity && eidx == rpy->capacity)
|
||||
return True;
|
||||
|
||||
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");
|
||||
return False;
|
||||
}
|
||||
}
|
||||
|
||||
return False;
|
||||
}
|
||||
|
||||
#undef FLOATOF
|
||||
#undef INTOF
|
||||
|
|
|
@ -57,5 +57,6 @@ int replay_read(Replay *rpy, FILE *file);
|
|||
#define REPLAY_ALLOC_ADDITIONAL 100
|
||||
#define REPLAY_MAGICNUMBER 1337
|
||||
#define REPLAY_EXTENSION "tsr"
|
||||
#define REPLAY_READ_MAXSTRLEN 128
|
||||
|
||||
#endif
|
||||
|
|
Loading…
Reference in a new issue