comparison src/xs_length.c @ 660:b0743dc9165d

Change tabs to 4 spaces, everywhere.
author Matti Hamalainen <ccr@tnsp.org>
date Wed, 02 Apr 2008 22:10:05 +0300
parents acaba070cf49
children 9321ffa2ea7e
comparison
equal deleted inserted replaced
659:04ea91a61225 660:b0743dc9165d
30 30
31 /* Free memory allocated for given SLDB node 31 /* Free memory allocated for given SLDB node
32 */ 32 */
33 static void xs_sldb_node_free(sldb_node_t *node) 33 static void xs_sldb_node_free(sldb_node_t *node)
34 { 34 {
35 if (node) { 35 if (node) {
36 /* Nothing much to do here ... */ 36 /* Nothing much to do here ... */
37 g_free(node->lengths); 37 g_free(node->lengths);
38 g_free(node); 38 g_free(node);
39 } 39 }
40 } 40 }
41 41
42 42
43 /* Insert given node to db linked list 43 /* Insert given node to db linked list
44 */ 44 */
45 static void xs_sldb_node_insert(xs_sldb_t *db, sldb_node_t *node) 45 static void xs_sldb_node_insert(xs_sldb_t *db, sldb_node_t *node)
46 { 46 {
47 assert(db); 47 assert(db);
48 48
49 if (db->nodes) { 49 if (db->nodes) {
50 /* The first node's prev points to last node */ 50 /* The first node's prev points to last node */
51 LPREV = db->nodes->prev; /* New node's prev = Previous last node */ 51 LPREV = db->nodes->prev; /* New node's prev = Previous last node */
52 db->nodes->prev->next = node; /* Previous last node's next = New node */ 52 db->nodes->prev->next = node; /* Previous last node's next = New node */
53 db->nodes->prev = node; /* New last node = New node */ 53 db->nodes->prev = node; /* New last node = New node */
54 LNEXT = NULL; /* But next is NULL! */ 54 LNEXT = NULL; /* But next is NULL! */
55 } else { 55 } else {
56 db->nodes = node; /* First node ... */ 56 db->nodes = node; /* First node ... */
57 LPREV = node; /* ... it's also last */ 57 LPREV = node; /* ... it's also last */
58 LNEXT = NULL; /* But next is NULL! */ 58 LNEXT = NULL; /* But next is NULL! */
59 } 59 }
60 } 60 }
61 61
62 62
63 /* Parse a time-entry in SLDB format 63 /* Parse a time-entry in SLDB format
64 */ 64 */
65 static gint xs_sldb_gettime(gchar *str, size_t *pos) 65 static gint xs_sldb_gettime(gchar *str, size_t *pos)
66 { 66 {
67 gint result, tmp; 67 gint result, tmp;
68 68
69 /* Check if it starts with a digit */ 69 /* Check if it starts with a digit */
70 if (isdigit(str[*pos])) { 70 if (isdigit(str[*pos])) {
71 /* Get minutes-field */ 71 /* Get minutes-field */
72 result = 0; 72 result = 0;
73 while (isdigit(str[*pos])) 73 while (isdigit(str[*pos]))
74 result = (result * 10) + (str[(*pos)++] - '0'); 74 result = (result * 10) + (str[(*pos)++] - '0');
75 75
76 result *= 60; 76 result *= 60;
77 77
78 /* Check the field separator char */ 78 /* Check the field separator char */
79 if (str[*pos] == ':') { 79 if (str[*pos] == ':') {
80 /* Get seconds-field */ 80 /* Get seconds-field */
81 (*pos)++; 81 (*pos)++;
82 tmp = 0; 82 tmp = 0;
83 while (isdigit(str[*pos])) { 83 while (isdigit(str[*pos])) {
84 tmp = (tmp * 10) + (str[(*pos)++] - '0'); 84 tmp = (tmp * 10) + (str[(*pos)++] - '0');
85 } 85 }
86 86
87 result += tmp; 87 result += tmp;
88 } else 88 } else
89 result = -2; 89 result = -2;
90 } else 90 } else
91 result = -1; 91 result = -1;
92 92
93 /* Ignore and skip the possible attributes */ 93 /* Ignore and skip the possible attributes */
94 while (str[*pos] && !isspace(str[*pos])) 94 while (str[*pos] && !isspace(str[*pos]))
95 (*pos)++; 95 (*pos)++;
96 96
97 return result; 97 return result;
98 } 98 }
99 99
100 100
101 /* Parse one SLDB definition line, return SLDB node 101 /* Parse one SLDB definition line, return SLDB node
102 */ 102 */
103 sldb_node_t * xs_sldb_read_entry(gchar *inLine) 103 sldb_node_t * xs_sldb_read_entry(gchar *inLine)
104 { 104 {
105 size_t linePos; 105 size_t linePos;
106 gint i; 106 gint i;
107 gboolean isOK; 107 gboolean isOK;
108 sldb_node_t *tmnode; 108 sldb_node_t *tmnode;
109 109
110 /* Allocate new node */ 110 /* Allocate new node */
111 tmnode = (sldb_node_t *) g_malloc0(sizeof(sldb_node_t)); 111 tmnode = (sldb_node_t *) g_malloc0(sizeof(sldb_node_t));
112 if (!tmnode) { 112 if (!tmnode) {
113 xs_error("Error allocating new node. Fatal error.\n"); 113 xs_error("Error allocating new node. Fatal error.\n");
114 return NULL; 114 return NULL;
115 } 115 }
116 116
117 /* Get hash value */ 117 /* Get hash value */
118 linePos = 0; 118 linePos = 0;
119 for (i = 0; i < XS_MD5HASH_LENGTH; i++, linePos += 2) { 119 for (i = 0; i < XS_MD5HASH_LENGTH; i++, linePos += 2) {
120 gint tmpu; 120 gint tmpu;
121 sscanf(&inLine[linePos], "%2x", &tmpu); 121 sscanf(&inLine[linePos], "%2x", &tmpu);
122 tmnode->md5Hash[i] = tmpu; 122 tmnode->md5Hash[i] = tmpu;
123 } 123 }
124 124
125 /* Get playtimes */ 125 /* Get playtimes */
126 if (inLine[linePos] != 0) { 126 if (inLine[linePos] != 0) {
127 if (inLine[linePos] != '=') { 127 if (inLine[linePos] != '=') {
128 xs_error("'=' expected on column #%d.\n", linePos); 128 xs_error("'=' expected on column #%d.\n", linePos);
129 xs_sldb_node_free(tmnode); 129 xs_sldb_node_free(tmnode);
130 return NULL; 130 return NULL;
131 } else { 131 } else {
132 size_t tmpLen, savePos; 132 size_t tmpLen, savePos;
133 133
134 /* First playtime is after '=' */ 134 /* First playtime is after '=' */
135 savePos = ++linePos; 135 savePos = ++linePos;
136 tmpLen = strlen(inLine); 136 tmpLen = strlen(inLine);
137 137
138 /* Get number of sub-tune lengths */ 138 /* Get number of sub-tune lengths */
139 isOK = TRUE; 139 isOK = TRUE;
140 while ((linePos < tmpLen) && isOK) { 140 while ((linePos < tmpLen) && isOK) {
141 xs_findnext(inLine, &linePos); 141 xs_findnext(inLine, &linePos);
142 142
143 if (xs_sldb_gettime(inLine, &linePos) >= 0) 143 if (xs_sldb_gettime(inLine, &linePos) >= 0)
144 tmnode->nlengths++; 144 tmnode->nlengths++;
145 else 145 else
146 isOK = FALSE; 146 isOK = FALSE;
147 } 147 }
148 148
149 /* Allocate memory for lengths */ 149 /* Allocate memory for lengths */
150 if (tmnode->nlengths > 0) { 150 if (tmnode->nlengths > 0) {
151 tmnode->lengths = (gint *) g_malloc0(tmnode->nlengths * sizeof(gint)); 151 tmnode->lengths = (gint *) g_malloc0(tmnode->nlengths * sizeof(gint));
152 if (!tmnode->lengths) { 152 if (!tmnode->lengths) {
153 xs_error("Could not allocate memory for node.\n"); 153 xs_error("Could not allocate memory for node.\n");
154 xs_sldb_node_free(tmnode); 154 xs_sldb_node_free(tmnode);
155 return NULL; 155 return NULL;
156 } 156 }
157 } else { 157 } else {
158 xs_sldb_node_free(tmnode); 158 xs_sldb_node_free(tmnode);
159 return NULL; 159 return NULL;
160 } 160 }
161 161
162 /* Read lengths in */ 162 /* Read lengths in */
163 i = 0; 163 i = 0;
164 linePos = savePos; 164 linePos = savePos;
165 isOK = TRUE; 165 isOK = TRUE;
166 while ((linePos < tmpLen) && (i < tmnode->nlengths) && isOK) { 166 while ((linePos < tmpLen) && (i < tmnode->nlengths) && isOK) {
167 gint l; 167 gint l;
168 168
169 xs_findnext(inLine, &linePos); 169 xs_findnext(inLine, &linePos);
170 170
171 l = xs_sldb_gettime(inLine, &linePos); 171 l = xs_sldb_gettime(inLine, &linePos);
172 if (l >= 0) 172 if (l >= 0)
173 tmnode->lengths[i] = l; 173 tmnode->lengths[i] = l;
174 else 174 else
175 isOK = FALSE; 175 isOK = FALSE;
176 176
177 i++; 177 i++;
178 } 178 }
179 179
180 if (!isOK) { 180 if (!isOK) {
181 xs_sldb_node_free(tmnode); 181 xs_sldb_node_free(tmnode);
182 return NULL; 182 return NULL;
183 } else 183 } else
184 return tmnode; 184 return tmnode;
185 } 185 }
186 } 186 }
187 187
188 return NULL; 188 return NULL;
189 } 189 }
190 190
191 191
192 /* Read database to memory 192 /* Read database to memory
193 */ 193 */
194 gint xs_sldb_read(xs_sldb_t *db, const gchar *dbFilename) 194 gint xs_sldb_read(xs_sldb_t *db, const gchar *dbFilename)
195 { 195 {
196 FILE *inFile; 196 FILE *inFile;
197 gchar inLine[XS_BUF_SIZE]; 197 gchar inLine[XS_BUF_SIZE];
198 size_t lineNum; 198 size_t lineNum;
199 sldb_node_t *tmnode; 199 sldb_node_t *tmnode;
200 assert(db); 200 assert(db);
201 201
202 /* Try to open the file */ 202 /* Try to open the file */
203 if ((inFile = fopen(dbFilename, "ra")) == NULL) { 203 if ((inFile = fopen(dbFilename, "ra")) == NULL) {
204 xs_error("Could not open SongLengthDB '%s'\n", dbFilename); 204 xs_error("Could not open SongLengthDB '%s'\n", dbFilename);
205 return -1; 205 return -1;
206 } 206 }
207 207
208 /* Read and parse the data */ 208 /* Read and parse the data */
209 lineNum = 0; 209 lineNum = 0;
210 210
211 while (fgets(inLine, XS_BUF_SIZE, inFile) != NULL) { 211 while (fgets(inLine, XS_BUF_SIZE, inFile) != NULL) {
212 size_t linePos = 0; 212 size_t linePos = 0;
213 lineNum++; 213 lineNum++;
214 214
215 xs_findnext(inLine, &linePos); 215 xs_findnext(inLine, &linePos);
216 216
217 /* Check if it is datafield */ 217 /* Check if it is datafield */
218 if (isxdigit(inLine[linePos])) { 218 if (isxdigit(inLine[linePos])) {
219 /* Check the length of the hash */ 219 /* Check the length of the hash */
220 gint hashLen; 220 gint hashLen;
221 for (hashLen = 0; inLine[linePos] && isxdigit(inLine[linePos]); hashLen++, linePos++); 221 for (hashLen = 0; inLine[linePos] && isxdigit(inLine[linePos]); hashLen++, linePos++);
222 222
223 if (hashLen != XS_MD5HASH_LENGTH_CH) { 223 if (hashLen != XS_MD5HASH_LENGTH_CH) {
224 xs_error("Invalid MD5-hash in SongLengthDB file '%s' line #%d!\n", 224 xs_error("Invalid MD5-hash in SongLengthDB file '%s' line #%d!\n",
225 dbFilename, lineNum); 225 dbFilename, lineNum);
226 } else { 226 } else {
227 /* Parse and add node to db */ 227 /* Parse and add node to db */
228 if ((tmnode = xs_sldb_read_entry(inLine)) != NULL) { 228 if ((tmnode = xs_sldb_read_entry(inLine)) != NULL) {
229 xs_sldb_node_insert(db, tmnode); 229 xs_sldb_node_insert(db, tmnode);
230 } else { 230 } else {
231 xs_error("Invalid entry in SongLengthDB file '%s' line #%d!\n", 231 xs_error("Invalid entry in SongLengthDB file '%s' line #%d!\n",
232 dbFilename, lineNum); 232 dbFilename, lineNum);
233 } 233 }
234 } 234 }
235 } else if ((inLine[linePos] != ';') && (inLine[linePos] != '[') && (inLine[linePos] != 0)) { 235 } else if ((inLine[linePos] != ';') && (inLine[linePos] != '[') && (inLine[linePos] != 0)) {
236 xs_error("Invalid line in SongLengthDB file '%s' line #%d\n", 236 xs_error("Invalid line in SongLengthDB file '%s' line #%d\n",
237 dbFilename, lineNum); 237 dbFilename, lineNum);
238 } 238 }
239 239
240 } 240 }
241 241
242 /* Close the file */ 242 /* Close the file */
243 fclose(inFile); 243 fclose(inFile);
244 244
245 return 0; 245 return 0;
246 } 246 }
247 247
248 248
249 /* Compare two given MD5-hashes. 249 /* Compare two given MD5-hashes.
250 * Return: 0 if equal 250 * Return: 0 if equal
251 * negative if testHash1 < testHash2 251 * negative if testHash1 < testHash2
252 * positive if testHash1 > testHash2 252 * positive if testHash1 > testHash2
253 */ 253 */
254 static gint xs_sldb_cmphash(xs_md5hash_t testHash1, xs_md5hash_t testHash2) 254 static gint xs_sldb_cmphash(xs_md5hash_t testHash1, xs_md5hash_t testHash2)
255 { 255 {
256 gint i, d; 256 gint i, d;
257 257
258 /* Compute difference of hashes */ 258 /* Compute difference of hashes */
259 for (i = 0, d = 0; (i < XS_MD5HASH_LENGTH) && !d; i++) 259 for (i = 0, d = 0; (i < XS_MD5HASH_LENGTH) && !d; i++)
260 d = (testHash1[i] - testHash2[i]); 260 d = (testHash1[i] - testHash2[i]);
261 261
262 return d; 262 return d;
263 } 263 }
264 264
265 265
266 /* Compare two nodes 266 /* Compare two nodes
267 */ 267 */
268 static gint xs_sldb_cmp(const void *node1, const void *node2) 268 static gint xs_sldb_cmp(const void *node1, const void *node2)
269 { 269 {
270 /* We assume here that we never ever get NULL-pointers or similar */ 270 /* We assume here that we never ever get NULL-pointers or similar */
271 return xs_sldb_cmphash( 271 return xs_sldb_cmphash(
272 (*(sldb_node_t **) node1)->md5Hash, 272 (*(sldb_node_t **) node1)->md5Hash,
273 (*(sldb_node_t **) node2)->md5Hash); 273 (*(sldb_node_t **) node2)->md5Hash);
274 } 274 }
275 275
276 276
277 /* (Re)create index 277 /* (Re)create index
278 */ 278 */
279 gint xs_sldb_index(xs_sldb_t * db) 279 gint xs_sldb_index(xs_sldb_t * db)
280 { 280 {
281 sldb_node_t *pCurr; 281 sldb_node_t *pCurr;
282 size_t i; 282 size_t i;
283 assert(db); 283 assert(db);
284 284
285 /* Free old index */ 285 /* Free old index */
286 if (db->pindex) { 286 if (db->pindex) {
287 g_free(db->pindex); 287 g_free(db->pindex);
288 db->pindex = NULL; 288 db->pindex = NULL;
289 } 289 }
290 290
291 /* Get size of db */ 291 /* Get size of db */
292 pCurr = db->nodes; 292 pCurr = db->nodes;
293 db->n = 0; 293 db->n = 0;
294 while (pCurr) { 294 while (pCurr) {
295 db->n++; 295 db->n++;
296 pCurr = pCurr->next; 296 pCurr = pCurr->next;
297 } 297 }
298 298
299 /* Check number of nodes */ 299 /* Check number of nodes */
300 if (db->n > 0) { 300 if (db->n > 0) {
301 /* Allocate memory for index-table */ 301 /* Allocate memory for index-table */
302 db->pindex = (sldb_node_t **) g_malloc(sizeof(sldb_node_t *) * db->n); 302 db->pindex = (sldb_node_t **) g_malloc(sizeof(sldb_node_t *) * db->n);
303 if (!db->pindex) 303 if (!db->pindex)
304 return -1; 304 return -1;
305 305
306 /* Get node-pointers to table */ 306 /* Get node-pointers to table */
307 i = 0; 307 i = 0;
308 pCurr = db->nodes; 308 pCurr = db->nodes;
309 while (pCurr && (i < db->n)) { 309 while (pCurr && (i < db->n)) {
310 db->pindex[i++] = pCurr; 310 db->pindex[i++] = pCurr;
311 pCurr = pCurr->next; 311 pCurr = pCurr->next;
312 } 312 }
313 313
314 /* Sort the indexes */ 314 /* Sort the indexes */
315 qsort(db->pindex, db->n, sizeof(sldb_node_t *), xs_sldb_cmp); 315 qsort(db->pindex, db->n, sizeof(sldb_node_t *), xs_sldb_cmp);
316 } 316 }
317 317
318 return 0; 318 return 0;
319 } 319 }
320 320
321 321
322 /* Free a given song-length database 322 /* Free a given song-length database
323 */ 323 */
324 void xs_sldb_free(xs_sldb_t * db) 324 void xs_sldb_free(xs_sldb_t * db)
325 { 325 {
326 sldb_node_t *pCurr, *next; 326 sldb_node_t *pCurr, *next;
327 327
328 if (!db) 328 if (!db)
329 return; 329 return;
330 330
331 /* Free the memory allocated for nodes */ 331 /* Free the memory allocated for nodes */
332 pCurr = db->nodes; 332 pCurr = db->nodes;
333 while (pCurr) { 333 while (pCurr) {
334 next = pCurr->next; 334 next = pCurr->next;
335 xs_sldb_node_free(pCurr); 335 xs_sldb_node_free(pCurr);
336 pCurr = next; 336 pCurr = next;
337 } 337 }
338 338
339 db->nodes = NULL; 339 db->nodes = NULL;
340 340
341 /* Free memory allocated for index */ 341 /* Free memory allocated for index */
342 if (db->pindex) { 342 if (db->pindex) {
343 g_free(db->pindex); 343 g_free(db->pindex);
344 db->pindex = NULL; 344 db->pindex = NULL;
345 } 345 }
346 346
347 /* Free structure */ 347 /* Free structure */
348 db->n = 0; 348 db->n = 0;
349 g_free(db); 349 g_free(db);
350 } 350 }
351 351
352 352
353 /* Compute md5hash of given SID-file 353 /* Compute md5hash of given SID-file
354 */ 354 */
355 typedef struct { 355 typedef struct {
356 gchar magicID[4]; /* "PSID" / "RSID" magic identifier */ 356 gchar magicID[4]; /* "PSID" / "RSID" magic identifier */
357 guint16 version, /* Version number */ 357 guint16 version, /* Version number */
358 dataOffset, /* Start of actual c64 data in file */ 358 dataOffset, /* Start of actual c64 data in file */
359 loadAddress, /* Loading address */ 359 loadAddress, /* Loading address */
360 initAddress, /* Initialization address */ 360 initAddress, /* Initialization address */
361 playAddress, /* Play one frame */ 361 playAddress, /* Play one frame */
362 nSongs, /* Number of subsongs */ 362 nSongs, /* Number of subsongs */
363 startSong; /* Default starting song */ 363 startSong; /* Default starting song */
364 guint32 speed; /* Speed */ 364 guint32 speed; /* Speed */
365 gchar sidName[32]; /* Descriptive text-fields, ASCIIZ */ 365 gchar sidName[32]; /* Descriptive text-fields, ASCIIZ */
366 gchar sidAuthor[32]; 366 gchar sidAuthor[32];
367 gchar sidCopyright[32]; 367 gchar sidCopyright[32];
368 } psidv1_header_t; 368 } psidv1_header_t;
369 369
370 370
371 typedef struct { 371 typedef struct {
372 guint16 flags; /* Flags */ 372 guint16 flags; /* Flags */
373 guint8 startPage, pageLength; 373 guint8 startPage, pageLength;
374 guint16 reserved; 374 guint16 reserved;
375 } psidv2_header_t; 375 } psidv2_header_t;
376 376
377 377
378 static gint xs_get_sid_hash(const gchar *filename, xs_md5hash_t hash) 378 static gint xs_get_sid_hash(const gchar *filename, xs_md5hash_t hash)
379 { 379 {
380 xs_file_t *inFile; 380 xs_file_t *inFile;
381 xs_md5state_t inState; 381 xs_md5state_t inState;
382 psidv1_header_t psidH; 382 psidv1_header_t psidH;
383 psidv2_header_t psidH2; 383 psidv2_header_t psidH2;
384 guint8 *songData; 384 guint8 *songData;
385 guint8 ib8[2], i8; 385 guint8 ib8[2], i8;
386 gint index, result; 386 gint index, result;
387 387
388 /* Try to open the file */ 388 /* Try to open the file */
389 if ((inFile = xs_fopen(filename, "rb")) == NULL) 389 if ((inFile = xs_fopen(filename, "rb")) == NULL)
390 return -1; 390 return -1;
391 391
392 /* Read PSID header in */ 392 /* Read PSID header in */
393 xs_fread(psidH.magicID, sizeof(psidH.magicID), 1, inFile); 393 xs_fread(psidH.magicID, sizeof(psidH.magicID), 1, inFile);
394 if (strncmp(psidH.magicID, "PSID", 4) && strncmp(psidH.magicID, "RSID", 4)) { 394 if (strncmp(psidH.magicID, "PSID", 4) && strncmp(psidH.magicID, "RSID", 4)) {
395 xs_fclose(inFile); 395 xs_fclose(inFile);
396 xs_error("Not a PSID or RSID file '%s'\n", filename); 396 xs_error("Not a PSID or RSID file '%s'\n", filename);
397 return -2; 397 return -2;
398 } 398 }
399 399
400 psidH.version = xs_fread_be16(inFile); 400 psidH.version = xs_fread_be16(inFile);
401 psidH.dataOffset = xs_fread_be16(inFile); 401 psidH.dataOffset = xs_fread_be16(inFile);
402 psidH.loadAddress = xs_fread_be16(inFile); 402 psidH.loadAddress = xs_fread_be16(inFile);
403 psidH.initAddress = xs_fread_be16(inFile); 403 psidH.initAddress = xs_fread_be16(inFile);
404 psidH.playAddress = xs_fread_be16(inFile); 404 psidH.playAddress = xs_fread_be16(inFile);
405 psidH.nSongs = xs_fread_be16(inFile); 405 psidH.nSongs = xs_fread_be16(inFile);
406 psidH.startSong = xs_fread_be16(inFile); 406 psidH.startSong = xs_fread_be16(inFile);
407 psidH.speed = xs_fread_be32(inFile); 407 psidH.speed = xs_fread_be32(inFile);
408 408
409 xs_fread(psidH.sidName, sizeof(gchar), sizeof(psidH.sidName), inFile); 409 xs_fread(psidH.sidName, sizeof(gchar), sizeof(psidH.sidName), inFile);
410 xs_fread(psidH.sidAuthor, sizeof(gchar), sizeof(psidH.sidAuthor), inFile); 410 xs_fread(psidH.sidAuthor, sizeof(gchar), sizeof(psidH.sidAuthor), inFile);
411 xs_fread(psidH.sidCopyright, sizeof(gchar), sizeof(psidH.sidCopyright), inFile); 411 xs_fread(psidH.sidCopyright, sizeof(gchar), sizeof(psidH.sidCopyright), inFile);
412 412
413 if (xs_feof(inFile) || xs_ferror(inFile)) { 413 if (xs_feof(inFile) || xs_ferror(inFile)) {
414 xs_fclose(inFile); 414 xs_fclose(inFile);
415 xs_error("Error reading SID file header from '%s'\n", filename); 415 xs_error("Error reading SID file header from '%s'\n", filename);
416 return -4; 416 return -4;
417 } 417 }
418 418
419 /* Check if we need to load PSIDv2NG header ... */ 419 /* Check if we need to load PSIDv2NG header ... */
420 psidH2.flags = 0; /* Just silence a stupid gcc warning */ 420 psidH2.flags = 0; /* Just silence a stupid gcc warning */
421 421
422 if (psidH.version == 2) { 422 if (psidH.version == 2) {
423 /* Yes, we need to */ 423 /* Yes, we need to */
424 psidH2.flags = xs_fread_be16(inFile); 424 psidH2.flags = xs_fread_be16(inFile);
425 psidH2.startPage = xs_fgetc(inFile); 425 psidH2.startPage = xs_fgetc(inFile);
426 psidH2.pageLength = xs_fgetc(inFile); 426 psidH2.pageLength = xs_fgetc(inFile);
427 psidH2.reserved = xs_fread_be16(inFile); 427 psidH2.reserved = xs_fread_be16(inFile);
428 } 428 }
429 429
430 /* Allocate buffer */ 430 /* Allocate buffer */
431 songData = (guint8 *) g_malloc(XS_SIDBUF_SIZE * sizeof(guint8)); 431 songData = (guint8 *) g_malloc(XS_SIDBUF_SIZE * sizeof(guint8));
432 if (!songData) { 432 if (!songData) {
433 xs_fclose(inFile); 433 xs_fclose(inFile);
434 xs_error("Error allocating temp data buffer for file '%s'\n", filename); 434 xs_error("Error allocating temp data buffer for file '%s'\n", filename);
435 return -3; 435 return -3;
436 } 436 }
437 437
438 /* Read data to buffer */ 438 /* Read data to buffer */
439 result = xs_fread(songData, sizeof(guint8), XS_SIDBUF_SIZE, inFile); 439 result = xs_fread(songData, sizeof(guint8), XS_SIDBUF_SIZE, inFile);
440 xs_fclose(inFile); 440 xs_fclose(inFile);
441 441
442 /* Initialize and start MD5-hash calculation */ 442 /* Initialize and start MD5-hash calculation */
443 xs_md5_init(&inState); 443 xs_md5_init(&inState);
444 444
445 if (psidH.loadAddress == 0) { 445 if (psidH.loadAddress == 0) {
446 /* Strip load address (2 first bytes) */ 446 /* Strip load address (2 first bytes) */
447 xs_md5_append(&inState, &songData[2], result - 2); 447 xs_md5_append(&inState, &songData[2], result - 2);
448 } else { 448 } else {
449 /* Append "as is" */ 449 /* Append "as is" */
450 xs_md5_append(&inState, songData, result); 450 xs_md5_append(&inState, songData, result);
451 } 451 }
452 452
453 /* Free buffer */ 453 /* Free buffer */
454 g_free(songData); 454 g_free(songData);
455 455
456 /* Append header data to hash */ 456 /* Append header data to hash */
457 #define XSADDHASH(QDATAB) do { \ 457 #define XSADDHASH(QDATAB) do { \
458 ib8[0] = (QDATAB & 0xff); \ 458 ib8[0] = (QDATAB & 0xff); \
459 ib8[1] = (QDATAB >> 8); \ 459 ib8[1] = (QDATAB >> 8); \
460 xs_md5_append(&inState, (guint8 *) &ib8, sizeof(ib8)); \ 460 xs_md5_append(&inState, (guint8 *) &ib8, sizeof(ib8)); \
461 } while (0) 461 } while (0)
462 462
463 XSADDHASH(psidH.initAddress); 463 XSADDHASH(psidH.initAddress);
464 XSADDHASH(psidH.playAddress); 464 XSADDHASH(psidH.playAddress);
465 XSADDHASH(psidH.nSongs); 465 XSADDHASH(psidH.nSongs);
466 #undef XSADDHASH 466 #undef XSADDHASH
467 467
468 /* Append song speed data to hash */ 468 /* Append song speed data to hash */
469 i8 = 0; 469 i8 = 0;
470 for (index = 0; (index < psidH.nSongs) && (index < 32); index++) { 470 for (index = 0; (index < psidH.nSongs) && (index < 32); index++) {
471 i8 = (psidH.speed & (1 << index)) ? 60 : 0; 471 i8 = (psidH.speed & (1 << index)) ? 60 : 0;
472 xs_md5_append(&inState, &i8, sizeof(i8)); 472 xs_md5_append(&inState, &i8, sizeof(i8));
473 } 473 }
474 474
475 /* Rest of songs (more than 32) */ 475 /* Rest of songs (more than 32) */
476 for (index = 32; index < psidH.nSongs; index++) { 476 for (index = 32; index < psidH.nSongs; index++) {
477 xs_md5_append(&inState, &i8, sizeof(i8)); 477 xs_md5_append(&inState, &i8, sizeof(i8));
478 } 478 }
479 479
480 /* PSIDv2NG specific */ 480 /* PSIDv2NG specific */
481 if (psidH.version == 2) { 481 if (psidH.version == 2) {
482 /* SEE SIDPLAY HEADERS FOR INFO */ 482 /* SEE SIDPLAY HEADERS FOR INFO */
483 i8 = (psidH2.flags >> 2) & 3; 483 i8 = (psidH2.flags >> 2) & 3;
484 if (i8 == 2) 484 if (i8 == 2)
485 xs_md5_append(&inState, &i8, sizeof(i8)); 485 xs_md5_append(&inState, &i8, sizeof(i8));
486 } 486 }
487 487
488 /* Calculate the hash */ 488 /* Calculate the hash */
489 xs_md5_finish(&inState, hash); 489 xs_md5_finish(&inState, hash);
490 490
491 return 0; 491 return 0;
492 } 492 }
493 493
494 494
495 /* Get node from db index via binary search 495 /* Get node from db index via binary search
496 */ 496 */
497 sldb_node_t *xs_sldb_get(xs_sldb_t *db, const gchar *filename) 497 sldb_node_t *xs_sldb_get(xs_sldb_t *db, const gchar *filename)
498 { 498 {
499 sldb_node_t keyItem, *key, **item; 499 sldb_node_t keyItem, *key, **item;
500 500
501 /* Check the database pointers */ 501 /* Check the database pointers */
502 if (!db || !db->nodes || !db->pindex) 502 if (!db || !db->nodes || !db->pindex)
503 return NULL; 503 return NULL;
504 504
505 /* Get the hash and then look up from db */ 505 /* Get the hash and then look up from db */
506 if (xs_get_sid_hash(filename, keyItem.md5Hash) == 0) { 506 if (xs_get_sid_hash(filename, keyItem.md5Hash) == 0) {
507 key = &keyItem; 507 key = &keyItem;
508 item = bsearch(&key, db->pindex, db->n, 508 item = bsearch(&key, db->pindex, db->n,
509 sizeof(db->pindex[0]), xs_sldb_cmp); 509 sizeof(db->pindex[0]), xs_sldb_cmp);
510 510
511 if (item) 511 if (item)
512 return *item; 512 return *item;
513 else 513 else
514 return NULL; 514 return NULL;
515 } else 515 } else
516 return NULL; 516 return NULL;
517 } 517 }
518 518
519 519