1 /*
2 * file cfg_demo.c - configuration data for recorded demos
3 *
4 * $Id: cfg_demo.c,v 1.11 2006/02/24 21:29:16 fzago Exp $
5 *
6 * Program XBLAST
7 * (C) by Oliver Vogel (e-mail: m.vogel@ndh.net)
8 *
9 * This program is free software; you can redistribute it and/or modify
10 * it under the terms of the GNU General Public License as published
11 * by the Free Software Foundation; either version 2; or (at your option)
12 * any later version
13 *
14 * This program is distributed in the hope that it will be entertaining,
15 * but WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILTY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General
17 * Public License for more details.
18 *
19 * You should have received a copy of the GNU General Public License along
20 * with this program; if not, write to the Free Software Foundation, Inc.
21 * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
22 */
23
24 #include "xblast.h"
25
26 /*
27 * global variables
28 */
29
30 /* current demo */
31 DBRoot *dbDemo = NULL;
32
33 /*
34 * local variables
35 */
36
37 /* list of all demos */
38 static DBRoot *dbList = NULL;
39 /* action keys for current demo */
40 static DBSection *frameSection = NULL;
41
42 /**********************
43 * managing all demos *
44 **********************/
45
46 /*
47 * initialize current demo and list
48 */
49 void
LoadDemoConfig(void)50 LoadDemoConfig (void)
51 {
52 /* create demo database for current demo */
53 dbDemo = DB_Create (DT_Demo, atomDemo);
54 assert (NULL != dbDemo);
55 /* load list of recorded demos */
56 dbList = DB_Create (DT_Config, atomDemo);
57 assert (NULL != dbDemo);
58 Dbg_Config ("loading list of demos\n");
59 if (DB_LoadDir (dbList, "demo", "dem", DT_Demo, atomTime, atomInfo, NULL, XBFalse)) {
60 SaveDemoConfig ();
61 }
62 else {
63 Dbg_Config ("no changes found\n");
64 }
65 } /* LoadDemoConfig */
66
67 /*
68 * store current list of demos in config
69 */
70 void
SaveDemoConfig(void)71 SaveDemoConfig (void)
72 {
73 /* list of demos database */
74 assert (dbList != NULL);
75 if (DB_Changed (dbList)) {
76 Dbg_Config ("saving list of demos\n");
77 DB_Store (dbList);
78 }
79 } /* SaveDemoConfig */
80
81 /*
82 * clear current demo and list
83 */
84 void
FinishDemoConfig(void)85 FinishDemoConfig (void)
86 {
87 /* remove single demo database */
88 assert (dbDemo != NULL);
89 DB_Delete (dbDemo);
90 dbDemo = NULL;
91 /* save and remove list of demos database */
92 SaveDemoConfig ();
93 DB_Delete (dbList);
94 dbList = NULL;
95 Dbg_Config ("demo config cleared\n");
96 } /* FinishDemoConfig */
97
98 /*
99 * compare to demo entries by time
100 */
101 static int
CompareDemoEntries(const void * a,const void * b)102 CompareDemoEntries (const void *a, const void *b)
103 {
104 assert (NULL != a);
105 assert (NULL != b);
106 return ((const CFGDemoEntry *) b)->time - ((const CFGDemoEntry *) a)->time;
107 } /* CompareDemoEntries */
108
109 /*
110 * create list with all demos available
111 */
112 CFGDemoEntry *
CreateDemoList(size_t * num)113 CreateDemoList (size_t * num)
114 {
115 CFGDemoEntry *list;
116 size_t i, j;
117 XBAtom atom;
118 const DBSection *section;
119
120 /* sanity check */
121 assert (NULL != dbList);
122 assert (NULL != num);
123 /* alloc data */
124 *num = DB_NumSections (dbList);
125 if (0 == *num) {
126 return NULL;
127 }
128 list = calloc (*num, sizeof (CFGDemoEntry));
129 /* build list */
130 for (i = 0, j = 0; i < *num; i++) {
131 atom = DB_IndexSection (dbList, i);
132 section = DB_GetSection (dbList, atom);
133 assert (NULL != section);
134 list[j].atom = atom;
135 (void)DB_GetEntryAtom (section, atomLevel, &list[j].level);
136 if (NULL == GetLevelNameByAtom (list[j].level)) {
137 continue;
138 }
139 (void)DB_GetEntryInt (section, atomNumPlayers, &list[j].numPlayers);
140 (void)DB_GetEntryTime (section, atomRecorded, &list[j].time);
141 j++;
142 }
143 *num = j;
144 /* sort it */
145 qsort (list, *num, sizeof (CFGDemoEntry), CompareDemoEntries);
146 return list;
147 } /* CreateDemoList */
148
149 /*****************************
150 * current demo from/to file *
151 *****************************/
152
153 /*
154 * load current demo from file
155 */
156 XBBool
LoadDemoFromFile(XBAtom atom)157 LoadDemoFromFile (XBAtom atom)
158 {
159 /* clear current demo */
160 assert (NULL != dbDemo);
161 DB_Delete (dbDemo);
162 /* create new demo */
163 dbDemo = DB_Create (DT_Demo, atom);
164 assert (NULL != dbDemo);
165 /* load and return success */
166 return DB_Load (dbDemo);
167 } /* LoadDemoFromFile */
168
169 /*
170 * store current demo in file
171 */
172 void
SaveCurrentDemo(const char * filename)173 SaveCurrentDemo (const char *filename)
174 {
175 /* set file name for output */
176 DB_SetAtom (dbDemo, GUI_StringToAtom (filename));
177 /* single demo */
178 assert (NULL != dbDemo);
179 DB_Store (dbDemo);
180 /* TODO: add file to demoList !!! */
181 } /* SaveCurrentDemo */
182
183 /***********************
184 * current demo config *
185 ***********************/
186
187 /*
188 * store config data for a demo in current database
189 */
190 void
StoreDemoConfig(const CFGDemoInfo * cfgDemo)191 StoreDemoConfig (const CFGDemoInfo * cfgDemo)
192 {
193 DBSection *section;
194 /* sanity checks */
195 assert (NULL != cfgDemo);
196 assert (NULL != dbDemo);
197 /* create empty section */
198 DB_DeleteSection (dbDemo, atomInfo);
199 section = DB_CreateSection (dbDemo, atomInfo);
200 assert (NULL != section);
201 /* store data */
202 (void)DB_CreateEntryInt (section, atomNumPlayers, cfgDemo->numPlayers);
203 (void)DB_CreateEntryInt (section, atomNumFrames, cfgDemo->numFrames);
204 (void)DB_CreateEntryAtom (section, atomLevel, cfgDemo->level);
205 (void)DB_CreateEntryInt (section, atomRandomSeed, cfgDemo->randomSeed);
206 (void)DB_CreateEntryTime (section, atomRecorded, cfgDemo->time);
207 (void)DB_CreateEntryInt (section, atomLives, cfgDemo->numLives);
208 (void)DB_CreateEntryInt (section, atomFrameRate, cfgDemo->frameRate);
209 (void)DB_CreateEntryBool (section, atomRandomPlayers, cfgDemo->randomPlayers);
210 (void)DB_CreateEntryInt (section, atomWinner, cfgDemo->winner);
211 } /* StoreDemoConfig */
212
213 /*
214 * get config data for current demo from database
215 */
216 XBBool
RetrieveDemoConfig(CFGDemoInfo * cfgDemo)217 RetrieveDemoConfig (CFGDemoInfo * cfgDemo)
218 {
219 const DBSection *section;
220 /* sanity checks */
221 assert (NULL != cfgDemo);
222 assert (NULL != dbDemo);
223 /* find section */
224 if (NULL == (section = DB_GetSection (dbDemo, atomInfo))) {
225 return XBFalse;
226 }
227 /* get data */
228 if (!DB_GetEntryInt (section, atomNumPlayers, &cfgDemo->numPlayers) ||
229 !DB_GetEntryInt (section, atomNumFrames, &cfgDemo->numFrames) ||
230 !DB_GetEntryAtom (section, atomLevel, &cfgDemo->level) ||
231 !DB_GetEntryInt (section, atomRandomSeed, &cfgDemo->randomSeed) ||
232 !DB_GetEntryTime (section, atomRecorded, &cfgDemo->time) ||
233 !DB_GetEntryInt (section, atomLives, &cfgDemo->numLives) ||
234 !DB_GetEntryInt (section, atomFrameRate, &cfgDemo->frameRate) ||
235 !DB_GetEntryBool (section, atomRandomPlayers, &cfgDemo->randomPlayers)) {
236 return XBFalse;
237 }
238 return XBTrue;
239 } /* RetrieveDemoConfig */
240
241 /****************************
242 * current demo: frame data *
243 ****************************/
244
245 /*
246 * store data for single frame in current demo database
247 */
248 void
StoreDemoFrame(int gameTime,int numPlayers,const unsigned char * buf)249 StoreDemoFrame (int gameTime, int numPlayers, const unsigned char *buf)
250 {
251 int i;
252 size_t len = 0;
253 char tmp[3 * MAX_PLAYER + 1] = "";
254 /* create frame section if needed */
255 if (NULL == frameSection) {
256 assert (NULL != dbDemo);
257 frameSection = DB_CreateSection (dbDemo, atomFrames);
258 assert (NULL != frameSection);
259 }
260 /* create the entry */
261 for (i = 0; i < numPlayers; i++) {
262 len += sprintf (tmp + len, "%02X ", (unsigned)buf[i]);
263 }
264 (void)DB_CreateEntryString (frameSection, GUI_IntToAtom (gameTime), tmp);
265 } /* StoreDemoFrame */
266
267 /*
268 * copy frames of current demo into a buffer
269 */
270 XBBool
RetrieveDemoFrames(int numPlayers,unsigned char (* buffer)[MAX_PLAYER])271 RetrieveDemoFrames (int numPlayers, unsigned char (*buffer)[MAX_PLAYER])
272 {
273 const DBSection *section;
274 size_t i, j, num;
275 int frame;
276 const char *s;
277 unsigned value;
278 /* sanity check */
279 assert (numPlayers <= MAX_PLAYER);
280 assert (buffer != NULL);
281 assert (dbDemo != NULL);
282 /* find frames section */
283 if (NULL == (section = DB_GetSection (dbDemo, atomFrames))) {
284 return XBFalse;
285 }
286 /* get number of entries */
287 num = DB_NumEntries (section);
288 /* loop through entries */
289 for (i = 0; i < num; i++) {
290 /* get indexed entry */
291 XBAtom atom = DB_IndexEntry (section, i);
292 assert (ATOM_INVALID != atom);
293 /* check for valid game time */
294 frame = GUI_AtomToInt (atom);
295 if (frame < 0 || frame >= GAME_TIME) {
296 return XBFalse;
297 }
298 /* get action string */
299 if (!DB_GetEntryString (section, atom, &s)) {
300 return XBFalse;
301 }
302 /* validate length */
303 if (strlen (s) < 2 * numPlayers) {
304 return XBFalse;
305 }
306 /* try to extract keys for each player */
307 for (j = 0; j < numPlayers; j++) {
308 if (1 != sscanf (s + 3 * j, "%x", &value)) {
309 return XBFalse;
310 }
311 /* store in buffer */
312 buffer[frame][j] = (unsigned char)value;
313 }
314 }
315 return XBTrue;
316 } /* RetrieveDemoFrames */
317
318 /*
319 * clear frame section of current database
320 */
321 void
DeleteDemoFrames(void)322 DeleteDemoFrames (void)
323 {
324 assert (NULL != dbDemo);
325 DB_DeleteSection (dbDemo, atomFrames);
326 frameSection = NULL;
327 } /* ClearDemoFrames */
328
329 /*
330 * end of file cfg_demo.c
331 */
332