changeset 163:179ffe97599c

Implement support for the "new" MD5 format of SLDB.
author Matti Hamalainen <ccr@tnsp.org>
date Fri, 16 Feb 2018 22:07:19 +0200
parents 7359170fbb7f
children 9cc9ce46f4a0
files sidinfo.c sidlib.c sidlib.h
diffstat 3 files changed, 102 insertions(+), 66 deletions(-) [+]
line wrap: on
line diff
--- a/sidinfo.c	Fri Feb 16 21:24:28 2018 +0200
+++ b/sidinfo.c	Fri Feb 16 22:07:19 2018 +0200
@@ -14,7 +14,7 @@
 
 // Some constants
 #define SET_DEF_CHARSET   "utf-8"
-#define SET_SLDB_FILENAME "Songlengths.txt"
+#define SET_SLDB_FILENAME "Songlengths.md5"
 
 
 enum
@@ -94,7 +94,8 @@
 // Option variables
 char   *setHVSCPath = NULL,
        *setSLDBPath = NULL;
-BOOL	optParsable = FALSE,
+BOOL	setSLDBNewFormat = FALSE,
+        optParsable = FALSE,
         optNoNamePrefix = FALSE,
         optHexadecimal = FALSE,
         optOneLine = FALSE,
@@ -892,7 +893,7 @@
     }
 
     // Read PSID data
-    if (si_read_sid_file(inFile, &psid) != 0)
+    if (!si_read_sid_file(inFile, &psid, setSLDBNewFormat))
     {
         THERR("Error reading %s\n", filename);
         goto error;
@@ -1027,6 +1028,8 @@
             goto err;
         }
 
+        setSLDBNewFormat = th_strrcasecmp(setSLDBPath, ".md5") != NULL;
+
 err:
         th_io_close(inFile);
     }
--- a/sidlib.c	Fri Feb 16 21:24:28 2018 +0200
+++ b/sidlib.c	Fri Feb 16 22:07:19 2018 +0200
@@ -47,14 +47,12 @@
 }
 
 
-int si_read_sid_file(th_ioctx *ctx, PSIDHeader **ppsid)
+static BOOL si_read_hash_data(th_ioctx *ctx, PSIDHeader *psid,
+    th_md5state_t *state, BOOL first)
 {
-    PSIDHeader *psid = NULL;
-    th_md5state_t state;
-    uint8_t tmp8, *data = NULL;
-    int index, ret = -1;
+    uint8_t *data = NULL;
+    BOOL ret = FALSE;
     size_t read;
-    BOOL first;
 
     if ((data = (uint8_t *) th_malloc(PSID_BUFFER_SIZE)) == NULL)
     {
@@ -64,6 +62,52 @@
         goto error;
     }
 
+    psid->dataSize = 0;
+    do
+    {
+        read = thfread(data, sizeof(uint8_t), PSID_BUFFER_SIZE, ctx);
+        psid->dataSize += read;
+
+        // If load address is 0 in header and we have the first block, grab it
+        if (first && psid->loadAddress == 0)
+        {
+            if (read < 4)
+            {
+                th_io_error(ctx, THERR_FREAD,
+                    "Error reading song data, unexpectedly small file.\n");
+                goto error;
+            }
+
+            // Grab the load address
+            psid->loadAddress = TH_LE16_TO_NATIVE(*(uint16_t *) data);
+
+            // .. do not include the load address to the hash
+            th_md5_append(state, &data[2], read - 2);
+            first = FALSE;
+        }
+        else
+        if (read > 0)
+        {
+            // Append data "as is"
+            th_md5_append(state, data, read);
+        }
+    } while (read > 0 && !thfeof(ctx));
+
+    ret = TRUE;
+
+error:
+    th_free(data);
+    return ret;
+}
+
+
+BOOL si_read_sid_file(th_ioctx *ctx, PSIDHeader **ppsid, const BOOL newSLDB)
+{
+    PSIDHeader *psid = NULL;
+    th_md5state_t state;
+    BOOL ret = FALSE;
+    off_t hdrStart, hdrEnd;
+
     if ((psid = *ppsid = th_malloc0(sizeof(PSIDHeader))) == NULL)
     {
         th_io_error(ctx, THERR_MALLOC,
@@ -71,6 +115,8 @@
         goto error;
     }
 
+    hdrStart = thftell(ctx);
+
     // Read PSID header in
     if (!thfread_str(ctx, (uint8_t *) psid->magic, PSID_MAGIC_LEN) ||
         !thfread_be16(ctx, &psid->version) ||
@@ -128,79 +174,66 @@
         }
     }
 
+    hdrEnd = thftell(ctx);
+
     // Initialize MD5-hash calculation
     th_md5_init(&state);
 
-    // Process actual data
-    psid->dataSize = 0;
-    first = TRUE;
-    do
+    if (newSLDB)
+    {
+        // New Songlengths.md5 style hash calculation:
+        // We just hash the whole file, so seek back to beginning ..
+        thfseek(ctx, hdrStart, SEEK_SET);
+
+        if (!si_read_hash_data(ctx, psid, &state, FALSE))
+            goto error;
+
+        psid->dataSize -= hdrEnd - hdrStart;
+    }
+    else
     {
-        read = thfread(data, sizeof(uint8_t), PSID_BUFFER_SIZE, ctx);
-        psid->dataSize += read;
+        // "Old" Songlengths.txt style MD5 hash calculation
+        // We need to separately hash data etc.
+        if (!si_read_hash_data(ctx, psid, &state, TRUE))
+            goto error;
 
-        // If load address is 0 in header and we have the first block, grab it
-        if (first && psid->loadAddress == 0)
+        // Append header data to hash
+        th_md5_append_le16(&state, psid->initAddress);
+        th_md5_append_le16(&state, psid->playAddress);
+        th_md5_append_le16(&state, psid->nSongs);
+
+        // Append song speed data to hash
+        uint8_t tmp8 = psid->isRSID ? 60 : 0;
+        for (int index = 0; index < psid->nSongs && index < 32; index++)
         {
-            if (read < 4)
-            {
-                th_io_error(ctx, THERR_FREAD,
-                    "Error reading song data, unexpectedly small file.\n");
-                goto error;
-            }
-
-            // Grab the load address
-            psid->loadAddress = TH_LE16_TO_NATIVE(*(uint16_t *) data);
+            if (psid->isRSID)
+                tmp8 = 60;
+            else
+                tmp8 = (psid->speed & (1 << index)) ? 60 : 0;
 
-            // .. do not include the load address to the hash
-            th_md5_append(&state, &data[2], read - 2);
-            first = FALSE;
-        }
-        else
-        if (read > 0)
-        {
-            // Append data "as is"
-            th_md5_append(&state, data, read);
+            th_md5_append(&state, &tmp8, sizeof(tmp8));
         }
-    } while (read > 0 && !thfeof(ctx));
 
-    // Append header data to hash
-    th_md5_append_le16(&state, psid->initAddress);
-    th_md5_append_le16(&state, psid->playAddress);
-    th_md5_append_le16(&state, psid->nSongs);
+        // Rest of songs (more than 32)
+        for (int index = 32; index < psid->nSongs; index++)
+            th_md5_append(&state, &tmp8, sizeof(tmp8));
 
-    // Append song speed data to hash
-    tmp8 = psid->isRSID ? 60 : 0;
-    for (index = 0; index < psid->nSongs && index < 32; index++)
-    {
-        if (psid->isRSID)
-            tmp8 = 60;
-        else
-            tmp8 = (psid->speed & (1 << index)) ? 60 : 0;
-
-        th_md5_append(&state, &tmp8, sizeof(tmp8));
-    }
-
-    // Rest of songs (more than 32)
-    for (index = 32; index < psid->nSongs; index++)
-        th_md5_append(&state, &tmp8, sizeof(tmp8));
-
-    // PSIDv2NG specific
-    if (psid->version >= 2)
-    {
-        // REFER TO SIDPLAY HEADERS FOR MORE INFORMATION
-        tmp8 = (psid->flags >> 2) & 3;
-        if (tmp8 == 2)
-            th_md5_append(&state, &tmp8, sizeof(tmp8));
+        // PSIDv2NG specific
+        if (psid->version >= 2)
+        {
+            // REFER TO SIDPLAY HEADERS FOR MORE INFORMATION
+            tmp8 = (psid->flags >> 2) & 3;
+            if (tmp8 == 2)
+                th_md5_append(&state, &tmp8, sizeof(tmp8));
+        }
     }
 
     // Calculate the hash
     th_md5_finish(&state, psid->hash);
-    ret = 0;
+    ret = TRUE;
 
 error:
     // Free buffer
-    th_free(data);
     return ret;
 }
 
--- a/sidlib.h	Fri Feb 16 21:24:28 2018 +0200
+++ b/sidlib.h	Fri Feb 16 22:07:19 2018 +0200
@@ -92,7 +92,7 @@
 //
 // Functions
 //
-int             si_read_sid_file(th_ioctx *ctx, PSIDHeader **ppsid);
+BOOL            si_read_sid_file(th_ioctx *ctx, PSIDHeader **ppsid, const BOOL newSLDB);
 void            si_free_sid_file(PSIDHeader *psid);
 
 const char *    si_get_sid_clock_str(const int flags);