2 * Copyright (C) 2003 Robert Kooima
4 * NEVERBALL is free software; you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License as published
6 * by the Free Software Foundation; either version 2 of the License,
7 * or (at your option) any later version.
9 * This program is distributed in the hope that it will be useful, but
10 * WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 * General Public License for more details.
32 /*---------------------------------------------------------------------------*/
34 #define MAGIC 0x4E425250
38 static char name
[MAXDEMO
][MAXNAM
];
39 static char shot
[MAXDEMO
][PATHMAX
];
40 static short score
[MAXDEMO
];
41 static short clock
[MAXDEMO
];
44 /*---------------------------------------------------------------------------*/
55 /* Scan the user directory for files. */
57 if ((h
= FindFirstFile(config_user("*"), &d
)) != INVALID_HANDLE_VALUE
)
60 if ((fp
= fopen(config_user(d
.cFileName
), FMODE_RB
)))
65 /* Note the name and screen shot of each replay file. */
71 if (magic
== MAGIC
&& t
)
73 fread(shot
[count
], 1, PATHMAX
, fp
);
76 strncpy(name
[count
], d
.cFileName
, MAXNAM
);
81 while (count
< MAXDEMO
&& FindNextFile(h
, &d
));
99 /* Scan the user directory for files. */
101 if ((dp
= opendir(config_user(""))))
103 while (count
< MAXDEMO
&& (ent
= readdir(dp
)))
104 if ((fp
= fopen(config_user(ent
->d_name
), FMODE_RB
)))
109 /* Note the name and screen shot of each replay file. */
111 get_int (fp
, &magic
);
115 if (magic
== MAGIC
&& t
)
117 fread(shot
[count
], 1, PATHMAX
, fp
);
120 strncpy(name
[count
], ent
->d_name
, MAXNAM
);
132 const char *demo_pick(void)
136 return (n
> 0) ? name
[(rand() >> 4) % n
] : NULL
;
139 const char *demo_name(int i
)
141 return (0 <= i
&& i
< count
) ? name
[i
] : NULL
;
144 const char *demo_shot(int i
)
146 return (0 <= i
&& i
< count
) ? shot
[i
] : NULL
;
149 int demo_coins(int i
)
151 return (0 <= i
&& i
< count
) ? score
[i
] : 0;
154 int demo_clock(int i
)
156 return (0 <= i
&& i
< count
) ? clock
[i
] : 0;
159 /*---------------------------------------------------------------------------*/
161 int demo_exists(char *name
)
165 if ((fp
= fopen(config_user(name
), "r")))
173 void demo_unique(char *name
)
177 /* Generate a unique name for a new replay save. */
179 for (i
= 1; i
< 100; i
++)
181 sprintf(name
, "replay%02d", i
);
183 if (!demo_exists(name
))
188 /*---------------------------------------------------------------------------*/
190 int demo_play_init(const char *name
,
196 int t
, int g
, int s
, int c
, int b
)
206 /* Initialize the replay file. Write the header. */
208 if (name
&& (demo_fp
= fopen(config_user(name
), FMODE_WB
)))
210 put_int(demo_fp
, &magic
);
212 put_short(demo_fp
, &zero
);
213 put_short(demo_fp
, &zero
);
215 fwrite(shot
, 1, PATHMAX
, demo_fp
);
216 fwrite(file
, 1, PATHMAX
, demo_fp
);
217 fwrite(back
, 1, PATHMAX
, demo_fp
);
218 fwrite(grad
, 1, PATHMAX
, demo_fp
);
219 fwrite(song
, 1, PATHMAX
, demo_fp
);
221 put_short(demo_fp
, &st
);
222 put_short(demo_fp
, &sg
);
223 put_short(demo_fp
, &ss
);
224 put_short(demo_fp
, &sc
);
225 put_short(demo_fp
, &sb
);
227 audio_music_fade_to(2.0f
, song
);
229 return game_init(file
, back
, grad
, t
, (g
== 0));
234 void demo_play_step(float dt
)
238 put_float(demo_fp
, &dt
);
239 put_game_state(demo_fp
);
243 void demo_play_stat(int coins
, int clock
)
250 /* Update the demo header using the final score and time. */
252 fseek(demo_fp
, 4, SEEK_SET
);
254 put_short(demo_fp
, &t
);
255 put_short(demo_fp
, &c
);
257 fseek(demo_fp
, 0, SEEK_END
);
261 void demo_play_stop(const char *name
)
271 /* Rename the temporary replay file to its given name. */
275 strncpy(src
, config_user(USER_REPLAY_FILE
), PATHMAX
);
276 strncpy(dst
, config_user(name
), PATHMAX
);
283 /*---------------------------------------------------------------------------*/
285 static char demo_replay_name
[MAXSTR
];
287 int demo_replay_init(const char *name
, int *s
, int *c
, int *b
, int *g
)
303 if ((demo_fp
= fopen(config_user(name
), FMODE_RB
)))
305 strncpy(demo_replay_name
, name
, MAXSTR
);
307 get_int(demo_fp
, &magic
);
311 get_short(demo_fp
, &zero
);
312 get_short(demo_fp
, &zero
);
314 fread(shot
, 1, PATHMAX
, demo_fp
);
315 fread(file
, 1, PATHMAX
, demo_fp
);
316 fread(back
, 1, PATHMAX
, demo_fp
);
317 fread(grad
, 1, PATHMAX
, demo_fp
);
318 fread(song
, 1, PATHMAX
, demo_fp
);
320 get_short(demo_fp
, &st
);
321 get_short(demo_fp
, &sg
);
322 get_short(demo_fp
, &ss
);
323 get_short(demo_fp
, &sc
);
324 get_short(demo_fp
, &sb
);
326 if (g
) *g
= (int) sg
;
327 if (s
) *s
= (int) ss
;
328 if (c
) *c
= (int) sc
;
329 if (b
) *b
= (int) sb
;
333 audio_music_fade_to(0.5f
, song
);
334 return game_init(file
, back
, grad
, st
, (*g
== 0));
337 return game_init(file
, back
, grad
, st
, 1);
344 int demo_replay_step(float *dt
)
346 const float g
[3] = { 0.0f
, -9.8f
, 0.0f
};
350 get_float(demo_fp
, dt
);
352 if (feof(demo_fp
) == 0)
354 /* Play out current game state for particles, clock, etc. */
356 game_step(g
, *dt
, 1);
358 /* Load real current game state from file. */
360 if (get_game_state(demo_fp
))
367 void demo_replay_stop(int d
)
374 if (d
) unlink(config_user(demo_replay_name
));
378 /*---------------------------------------------------------------------------*/