Mercurial > hg > xmms-sid
comparison src/xs_length.c @ 955:3c2efa18c422
Change semantics of xs_fread_be{32,16}() functions to match xs_fread_str()
and xs_fread_byte() and change the PSID/RSID file parsing for SLDB MD5
calculation to use them. Also, fix the parser so that PSID/RSID v3 files are
supported correctly.
author | Matti Hamalainen <ccr@tnsp.org> |
---|---|
date | Tue, 20 Nov 2012 21:28:39 +0200 |
parents | ad97fd1524be |
children | 5e0a05c84694 |
comparison
equal
deleted
inserted
replaced
954:a5b118c853f5 | 955:3c2efa18c422 |
---|---|
368 } psidv2_header_t; | 368 } psidv2_header_t; |
369 | 369 |
370 | 370 |
371 static gint xs_get_sid_hash(const gchar *filename, xs_md5hash_t hash) | 371 static gint xs_get_sid_hash(const gchar *filename, xs_md5hash_t hash) |
372 { | 372 { |
373 XSFile *inFile; | 373 XSFile *inFile = NULL; |
374 xs_md5state_t inState; | 374 xs_md5state_t inState; |
375 psidv1_header_t psidH; | 375 psidv1_header_t psidH; |
376 psidv2_header_t psidH2; | 376 psidv2_header_t psidH2; |
377 guint8 *songData; | 377 guint8 *songData = NULL; |
378 guint8 ib8[2], i8; | 378 guint8 ib8[2], i8; |
379 gint index, result; | 379 gint index, result; |
380 | 380 |
381 /* Try to open the file */ | 381 /* Try to open the file */ |
382 if ((inFile = xs_fopen(filename, "rb")) == NULL) | 382 if ((inFile = xs_fopen(filename, "rb")) == NULL) |
383 return -1; | 383 goto error; |
384 | 384 |
385 /* Read PSID header in */ | 385 /* Read PSID header in */ |
386 xs_fread(psidH.magicID, sizeof(psidH.magicID), 1, inFile); | 386 if (!xs_fread_str(inFile, psidH.magicID, sizeof(psidH.magicID)) || |
387 if (strncmp(psidH.magicID, "PSID", 4) && | 387 !xs_fread_be16(inFile, &psidH.version) || |
388 strncmp(psidH.magicID, "RSID", 4)) | 388 !xs_fread_be16(inFile, &psidH.dataOffset) || |
389 { | 389 !xs_fread_be16(inFile, &psidH.loadAddress) || |
390 xs_fclose(inFile); | 390 !xs_fread_be16(inFile, &psidH.initAddress) || |
391 xs_error("Not a PSID or RSID file '%s'\n", filename); | 391 !xs_fread_be16(inFile, &psidH.playAddress) || |
392 return -2; | 392 !xs_fread_be16(inFile, &psidH.nSongs) || |
393 } | 393 !xs_fread_be16(inFile, &psidH.startSong) || |
394 | 394 !xs_fread_be32(inFile, &psidH.speed)) |
395 psidH.version = xs_fread_be16(inFile); | 395 { |
396 psidH.dataOffset = xs_fread_be16(inFile); | 396 xs_error("Could not read PSID/RSID header from '%s'\n", filename); |
397 psidH.loadAddress = xs_fread_be16(inFile); | 397 goto error; |
398 psidH.initAddress = xs_fread_be16(inFile); | 398 } |
399 psidH.playAddress = xs_fread_be16(inFile); | 399 |
400 psidH.nSongs = xs_fread_be16(inFile); | 400 if ((strncmp(psidH.magicID, "PSID", 4) && |
401 psidH.startSong = xs_fread_be16(inFile); | 401 strncmp(psidH.magicID, "RSID", 4)) || |
402 psidH.speed = xs_fread_be32(inFile); | 402 psidH.version < 1 || psidH.version > 3) |
403 | 403 { |
404 xs_fread(psidH.sidName, sizeof(gchar), sizeof(psidH.sidName), inFile); | 404 xs_error("Not a supported PSID or RSID file '%s'\n", filename); |
405 xs_fread(psidH.sidAuthor, sizeof(gchar), sizeof(psidH.sidAuthor), inFile); | 405 goto error; |
406 xs_fread(psidH.sidCopyright, sizeof(gchar), sizeof(psidH.sidCopyright), inFile); | 406 } |
407 | 407 |
408 if (xs_feof(inFile) || xs_ferror(inFile)) | 408 if (!xs_fread_str(inFile, psidH.sidName, sizeof(psidH.sidName)) || |
409 { | 409 !xs_fread_str(inFile, psidH.sidAuthor, sizeof(psidH.sidAuthor)) || |
410 xs_fclose(inFile); | 410 !xs_fread_str(inFile, psidH.sidCopyright, sizeof(psidH.sidCopyright))) |
411 { | |
411 xs_error("Error reading SID file header from '%s'\n", filename); | 412 xs_error("Error reading SID file header from '%s'\n", filename); |
412 return -4; | 413 goto error; |
413 } | 414 } |
414 | 415 |
415 /* Check if we need to load PSIDv2NG header ... */ | 416 /* Check if we need to load PSIDv2NG header ... */ |
416 psidH2.flags = 0; /* Just silence a stupid gcc warning */ | 417 psidH2.flags = 0; /* Just silence a stupid gcc warning */ |
417 | 418 |
418 if (psidH.version == 2) | 419 if (psidH.version == 2 || psidH.version == 3) |
419 { | 420 { |
420 /* Yes, we need to */ | 421 /* Yes, we need to */ |
421 psidH2.flags = xs_fread_be16(inFile); | 422 if (!xs_fread_be16(inFile, &psidH2.flags) || |
422 psidH2.startPage = xs_fgetc(inFile); | 423 !xs_fread_byte(inFile, &psidH2.startPage) || |
423 psidH2.pageLength = xs_fgetc(inFile); | 424 !xs_fread_byte(inFile, &psidH2.startPage) || |
424 psidH2.reserved = xs_fread_be16(inFile); | 425 !xs_fread_be16(inFile, &psidH2.reserved)) |
426 { | |
427 xs_error("Error reading PSID/RSID v2+ extra header data from '%s'\n", | |
428 filename); | |
429 goto error; | |
430 } | |
425 } | 431 } |
426 | 432 |
427 /* Allocate buffer */ | 433 /* Allocate buffer */ |
428 songData = (guint8 *) g_malloc(XS_SIDBUF_SIZE * sizeof(guint8)); | 434 if ((songData = (guint8 *) g_malloc(XS_SIDBUF_SIZE)) == NULL) |
429 if (!songData) | 435 { |
430 { | |
431 xs_fclose(inFile); | |
432 xs_error("Error allocating temp data buffer for file '%s'\n", filename); | 436 xs_error("Error allocating temp data buffer for file '%s'\n", filename); |
433 return -3; | 437 goto error; |
434 } | 438 } |
435 | 439 |
436 /* Read data to buffer */ | 440 /* Read data to buffer */ |
437 result = xs_fread(songData, sizeof(guint8), XS_SIDBUF_SIZE, inFile); | 441 result = xs_fread(songData, sizeof(guint8), XS_SIDBUF_SIZE, inFile); |
438 xs_fclose(inFile); | 442 xs_fclose(inFile); |
477 /* Rest of songs (more than 32) */ | 481 /* Rest of songs (more than 32) */ |
478 for (index = 32; index < psidH.nSongs; index++) | 482 for (index = 32; index < psidH.nSongs; index++) |
479 xs_md5_append(&inState, &i8, sizeof(i8)); | 483 xs_md5_append(&inState, &i8, sizeof(i8)); |
480 | 484 |
481 /* PSIDv2NG specific */ | 485 /* PSIDv2NG specific */ |
482 if (psidH.version == 2) | 486 if (psidH.version == 2 || psidH.version == 3) |
483 { | 487 { |
484 /* SEE SIDPLAY HEADERS FOR INFO */ | 488 /* SEE SIDPLAY HEADERS FOR INFO */ |
485 i8 = (psidH2.flags >> 2) & 3; | 489 i8 = (psidH2.flags >> 2) & 3; |
486 if (i8 == 2) | 490 if (i8 == 2) |
487 xs_md5_append(&inState, &i8, sizeof(i8)); | 491 xs_md5_append(&inState, &i8, sizeof(i8)); |
489 | 493 |
490 /* Calculate the hash */ | 494 /* Calculate the hash */ |
491 xs_md5_finish(&inState, hash); | 495 xs_md5_finish(&inState, hash); |
492 | 496 |
493 return 0; | 497 return 0; |
498 | |
499 error: | |
500 if (inFile != NULL) | |
501 xs_fclose(inFile); | |
502 g_free(songData); | |
503 return -1; | |
494 } | 504 } |
495 | 505 |
496 | 506 |
497 /* Get node from db index via binary search | 507 /* Get node from db index via binary search |
498 */ | 508 */ |