changeset 2480:c7a0913e1032

Various cleanups, integrate some changes/improvements from opendat project to packed.
author Matti Hamalainen <ccr@tnsp.org>
date Mon, 27 Apr 2020 21:37:15 +0300
parents c1cae47cd410
children f3d9cdb0a295
files tools/packed.c
diffstat 1 files changed, 153 insertions(+), 180 deletions(-) [+]
line wrap: on
line diff
--- a/tools/packed.c	Mon Apr 27 21:33:29 2020 +0300
+++ b/tools/packed.c	Mon Apr 27 21:37:15 2020 +0300
@@ -29,15 +29,14 @@
     PACK_EXTRACTED = 0x0001,
 };
 
-int    nsrcFilenames = 0, nexcFilenames = 0;
+
+size_t nsrcFilenames = 0, nexcFilenames = 0;
 char * srcFilenames[SET_MAX_FILES];
 char * excFilenames[SET_MAX_FILES];
 
 char * optPackFilename = NULL;
-BOOL   optDoCompress = TRUE;
 int    optCompressLevel = Z_BEST_COMPRESSION;
 int    optCommand = CMD_NONE;
-int    optDefResFlags = 0;
 
 
 static const DMOptArg cmdList[] =
@@ -57,9 +56,7 @@
     {  1,   0, "license"         , "Print out this program's license agreement", OPT_NONE },
     {  2, 'v', "verbose"         , "Be more verbose", OPT_NONE },
 
-    {  3, 'n', "nocompress"      , "No compression / decompression", OPT_NONE },
-    {  4, 'C', "level"           , "Set zlib compression level 1-9", OPT_ARGREQ },
-    {  5, 'f', "resflags"        , "Set default resource flags (-f 0xff)", OPT_ARGREQ },
+    {  4, 'C', "level"           , "Set zlib compression level 0-9", OPT_ARGREQ },
     {  6, 'x', "exclude"         , "Exclude name/glob pattern", OPT_ARGREQ },
 };
 
@@ -116,31 +113,15 @@
             dmVerbosity++;
             break;
 
-        case 3:
-            optDoCompress = FALSE;
-            break;
-
         case 4:
             optCompressLevel = atoi(optArg);
-            if (optCompressLevel < 1 || optCompressLevel > 9)
+            if (optCompressLevel < 0 || optCompressLevel > 9)
             {
-                dmErrorMsg("Invalid compression level argument '%s', must be 1 .. 9.\n", optArg);
+                dmErrorMsg("Invalid compression level argument '%s', must be 0 .. 9.\n", optArg);
                 return FALSE;
             }
             break;
 
-        case 5:
-            {
-                unsigned int tmpUI;
-                if (!dmGetIntVal(optArg, &tmpUI, NULL))
-                {
-                    dmErrorMsg("Invalid flags value '%s'.\n", optArg);
-                    return FALSE;
-                }
-                optDefResFlags = tmpUI;
-            }
-            break;
-
         case 6:
             if (nexcFilenames < SET_MAX_FILES)
             {
@@ -206,25 +187,25 @@
 
 DMPackEntry *dmPackEntryCopy(const DMPackEntry *src)
 {
-    DMPackEntry *node = dmPackEntryNew();
-    if (node == NULL)
+    DMPackEntry *entry = dmPackEntryNew();
+    if (entry == NULL)
         return NULL;
 
-    strncpy(node->filename, src->filename, DMRES_NAME_LEN);
-    node->filename[DMRES_NAME_LEN] = 0;
+    strncpy(entry->filename, src->filename, DMRES_NAME_LEN);
+    entry->filename[DMRES_NAME_LEN] = 0;
 
-    node->size     = src->size;
-    node->offset   = src->offset;
-    node->csize    = src->csize;
-    node->flags    = src->flags;
+    entry->size     = src->size;
+    entry->offset   = src->offset;
+    entry->csize    = src->csize;
+    entry->flags    = src->flags;
 
-    return node;
+    return entry;
 }
 
 
 int dmPackWrite(DMPackFile * pack)
 {
-    DMPackEntry *node;
+    DMPackEntry *entry;
     DMPackFileHeader hdr;
 
     if (pack == NULL)
@@ -241,10 +222,10 @@
         sizeof(hdr.ident) + sizeof(hdr.version) +
         sizeof(hdr.dirEntries) + sizeof(hdr.dirOffset);
 
-    for (node = pack->entries; node != NULL; node = node->next)
+    for (entry = pack->entries; entry != NULL; entry = entry->next)
     {
         hdr.dirEntries++;
-        hdr.dirOffset += node->csize;
+        hdr.dirOffset += entry->csize;
     }
 
     dmMsg(1, "%d entries in PACK, dir at offset 0x%08" DM_PRIx64 ".\n",
@@ -264,14 +245,14 @@
     if (fseeko(pack->file, hdr.dirOffset, SEEK_SET) != 0)
         return DMERR_FSEEK;
 
-    for (node = pack->entries; node != NULL; node = node->next)
+    for (entry = pack->entries; entry != NULL; entry = entry->next)
     {
         // Write one entry
-        if (!dm_fwrite_str(pack->file, node->filename, DMRES_NAME_LEN) ||
-            !dm_fwrite_le64(pack->file, node->offset) ||
-            !dm_fwrite_le32(pack->file, node->csize) ||
-            !dm_fwrite_le32(pack->file, node->size) ||
-            !dm_fwrite_le32(pack->file, node->flags))
+        if (!dm_fwrite_str(pack->file, entry->filename, DMRES_NAME_LEN) ||
+            !dm_fwrite_le64(pack->file, entry->offset) ||
+            !dm_fwrite_le32(pack->file, entry->csize) ||
+            !dm_fwrite_le32(pack->file, entry->size) ||
+            !dm_fwrite_le32(pack->file, entry->flags))
             return DMERR_FWRITE;
     }
 
@@ -282,8 +263,7 @@
 int dmPackCreate(const char *filename, DMPackFile ** pack)
 {
     // Allocate packfile-structure
-    *pack = (DMPackFile *) dmMalloc0(sizeof(DMPackFile));
-    if (*pack == NULL)
+    if ((*pack = (DMPackFile *) dmMalloc0(sizeof(DMPackFile))) == NULL)
         return DMERR_MALLOC;
 
     // Open the file
@@ -302,12 +282,11 @@
 
 
 int dmPackAddFile(DMPackFile * pack, const char *filename,
-    const Uint32 flags, const BOOL compress, int level,
-    DMPackEntry ** ppEntry)
+    const int level, DMPackEntry ** ppEntry)
 {
     Uint64 startOffs, outSize;
     Uint8 *inBuffer = NULL, *outBuffer = NULL;
-    DMPackEntry entry, *node;
+    DMPackEntry rentry, *pentry;
     FILE *inFile = NULL;
     int ret = DMERR_OK;
     BOOL zinit = FALSE;
@@ -324,9 +303,9 @@
     // Compute starting offset
     outSize = 0;
     startOffs = sizeof(DMPackFileHeader);
-    for (node = pack->entries; node != NULL; node = node->next)
+    for (pentry = pack->entries; pentry != NULL; pentry = pentry->next)
     {
-        startOffs += node->csize;
+        startOffs += pentry->csize;
     }
 
     // Seek to the position
@@ -346,7 +325,7 @@
     }
 
     // Read (and possibly compress) the data
-    if (compress)
+    if (level > 0)
     {
         int zret;
 
@@ -400,15 +379,15 @@
     }
 
     // Create directory entry
-    strncpy(entry.filename, filename, DMRES_NAME_LEN);
-    entry.filename[DMRES_NAME_LEN] = 0;
-    entry.offset = startOffs;
-    entry.size   = zstr.total_in;
-    entry.csize  = outSize;
-    entry.flags  = flags | (compress ? DMF_COMPRESSED : 0);
+    strncpy(rentry.filename, filename, DMRES_NAME_LEN);
+    rentry.filename[DMRES_NAME_LEN] = 0;
+    rentry.offset = startOffs;
+    rentry.size   = zstr.total_in;
+    rentry.csize  = outSize;
+    rentry.flags  = level > 0 ? DMF_COMPRESSED : 0;
 
     // Add directory entry
-    if ((*ppEntry = dmPackEntryCopy(&entry)) == NULL)
+    if ((*ppEntry = dmPackEntryCopy(&rentry)) == NULL)
     {
         ret = DMERR_MALLOC;
         goto out;
@@ -430,10 +409,7 @@
 }
 
 
-/*
- * EXTRACT a file from the PACK
- */
-int dmPackExtractFile(DMPackFile *pack, DMPackEntry * entry, BOOL decompress)
+int dmPackExtractFile(DMPackFile *pack, DMPackEntry * entry, const BOOL decompress)
 {
     z_stream zstr;
     FILE *outFile = NULL;
@@ -465,7 +441,7 @@
     }
 
     // Read and uncompress the data, if needed
-    if (decompress || (entry->flags & DMF_COMPRESSED) == 0)
+    if (decompress && (entry->flags & DMF_COMPRESSED))
     {
         // Initialize compression streams
         memset(&zstr, 0, sizeof(zstr));
@@ -492,23 +468,25 @@
         remaining   -= zstr.avail_in;
         zstr.next_in = inBuffer;
 
-        if (!decompress)
+        if (zinit)
         {
-            if (fwrite(inBuffer, sizeof(Uint8), zstr.avail_in, outFile) != zstr.avail_in)
+            while (zstr.avail_in > 0 && zret == Z_OK)
             {
-                ret = DMERR_FWRITE;
-                goto out;
+                zstr.next_out  = outBuffer;
+                zstr.avail_out = SET_TMPBUF_SIZE;
+                zstr.total_out = 0;
+                zret = inflate(&zstr, Z_FULL_FLUSH);
+                if (zstr.total_out > 0 &&
+                    fwrite(outBuffer, sizeof(Uint8), zstr.total_out, outFile) != zstr.total_out)
+                {
+                    ret = DMERR_FWRITE;
+                    goto out;
+                }
             }
         }
         else
-        while (zstr.avail_in > 0 && zret == Z_OK)
         {
-            zstr.next_out  = outBuffer;
-            zstr.avail_out = SET_TMPBUF_SIZE;
-            zstr.total_out = 0;
-            zret = inflate(&zstr, Z_FULL_FLUSH);
-            if (zstr.total_out > 0 &&
-                fwrite(outBuffer, sizeof(Uint8), zstr.total_out, outFile) != zstr.total_out)
+            if (fwrite(inBuffer, sizeof(Uint8), zstr.avail_in, outFile) != zstr.avail_in)
             {
                 ret = DMERR_FWRITE;
                 goto out;
@@ -643,11 +621,11 @@
 }
 
 
-BOOL dmCheckExcluded(const char *filename)
+BOOL dmMatchList(char **list, const size_t nlist, const char *str)
 {
-    for (int i = 0; i < nexcFilenames; i++)
+    for (size_t i = 0; i < nlist; i++)
     {
-        if (dmStrMatch(filename, excFilenames[i]))
+        if (dmStrMatch(str, list[i]))
             return TRUE;
     }
     return FALSE;
@@ -658,6 +636,7 @@
 {
     int res = 0;
     DMPackFile *pack = NULL;
+    DMPackEntry *entry = NULL;
 
     // Parse arguments
     dmInitProg("packed", "TNSP Pack File Editor", "0.7", NULL, NULL);
@@ -667,16 +646,16 @@
         argHandleOpt, argHandleNonOpt, OPTH_BAILOUT))
         exit(1);
 
-    if (optCommand == CMD_NONE)
+    if (optCommand == CMD_NONE || argc < 2)
     {
         argShowHelp();
-        goto error;
+        goto out;
     }
 
     if (optPackFilename == NULL)
     {
         dmErrorMsg("No PACK file specified.\n");
-        goto error;
+        goto out;
     }
 
     dmMsg(1, "Processing PACK '%s' ...\n", optPackFilename);
@@ -699,146 +678,140 @@
             break;
         }
 
-        // Add files into PACK
-        if (res == DMERR_OK)
+        if (res != DMERR_OK)
         {
-            dmMsg(1, "Adding files...\n");
+            dmErrorMsg("Could not open PACK file: %s\n",
+                dmErrorStr(res));
+            goto out;
+        }
 
-            for (int i = 0; i < nsrcFilenames; i++)
-            if (!dmCheckExcluded(srcFilenames[i]))
-            {
-                DMPackEntry *node = NULL;
-                int res = dmPackAddFile(pack, srcFilenames[i],
-                    optDefResFlags, optDoCompress,
-                    optCompressLevel, &node);
+        // Add files into PACK
+        dmMsg(1, "Adding files...\n");
+
+        for (size_t i = 0; i < nsrcFilenames; i++)
+        if (!dmMatchList(excFilenames, nexcFilenames, srcFilenames[i]))
+        {
+            res = dmPackAddFile(pack, srcFilenames[i], optCompressLevel, &entry);
 
-                if (res != DMERR_OK)
-                {
-                    dmPrint(1, "%-32s [ERROR:%d]\n",
-                        srcFilenames[i], res);
-                }
-                else
-                {
-                    dmPrint(1, "%-32s ['%s', s=%d, c=%d, o=%" DM_PRId64 ", f=0x%04x]\n",
-                        srcFilenames[i], node->filename,
-                        node->size, node->csize, node->offset, node->flags);
-                }
+            if (res != DMERR_OK)
+            {
+                dmPrint(1, "%-32s [ERROR:%d]\n",
+                    srcFilenames[i], res);
             }
-
-            dmMsg(2, "w=%d\n", dmPackWrite(pack));
-            dmMsg(2, "c=%d\n", dmPackClose(pack));
+            else
+            {
+                dmPrint(1, "%-32s ['%s', s=%d, c=%d, o=%" DM_PRId64 ", f=0x%04x]\n",
+                    srcFilenames[i], entry->filename,
+                    entry->size, entry->csize, entry->offset,
+                    entry->flags);
+            }
         }
-        else
-        {
-            dmErrorMsg("Could not open packfile, error #%d: %s\n", res,
-                  dmErrorStr(res));
-        }
+
+        dmMsg(2, "w=%d\n", dmPackWrite(pack));
         break;
 
     case CMD_LIST:
         // List files in PACK
-        res = dmPackOpen(optPackFilename, &pack, TRUE);
-        if (res == DMERR_OK)
+        if ((res = dmPackOpen(optPackFilename, &pack, TRUE)) != DMERR_OK)
+        {
+            dmErrorMsg("Could not open PACK file: %s\n",
+                dmErrorStr(res));
+            goto out;
+        }
+        else
         {
-            DMPackEntry *node;
-            int i;
-            for (i = 0, node = pack->entries; node; i++)
-                node = node->next;
+            size_t ntotal = 0, nshown = 0,
+                totalSize = 0, totalCSize = 0;
+
+            // Print the list header
+            int hlen = printf(
+                "%-32s | %10s | %10s | %10s | %s\n",
+                "Name", "Size", "CSize", "Offset", "Flags");
 
-            dmMsg(1, "%d files total\n", i);
+            for (int n = 0; n < hlen; n++)
+                fputc('-', stdout);
 
-            dmPrint(0, "%-32s | %8s | %8s | %8s | %s\n",
-                "Name", "Size", "CSize", "Offset", "ResFlags");
+            fputs("\n", stdout);
 
-            for (node = pack->entries; node != NULL; node = node->next)
+            // Print all the matching entries
+            for (entry = pack->entries; entry != NULL; entry = entry->next)
             {
                 BOOL match;
 
-                // Check for matches in specified filenames/patterns
                 if (nsrcFilenames > 0)
-                {
-                    match = FALSE;
-                    for (int i = 0; i < nsrcFilenames && !match; i++)
-                        match = dmStrMatch(node->filename, srcFilenames[i]);
-                }
+                    // Check for matches in specified filenames/patterns
+                    match = dmMatchList(srcFilenames, nsrcFilenames, entry->filename);
                 else
-                // No filenames specified, everything shown
+                    // No filenames specified, everything shown
                     match = TRUE;
 
-                if (match)
+                if (match && !dmMatchList(excFilenames, nexcFilenames, entry->filename))
                 {
-                    dmPrint(0, "%-32s | %8d | %8d | %08" DM_PRIx64 " | %04x\n",
-                        node->filename, node->size, node->csize,
-                        node->offset, node->flags);
+                    printf("%-32s | %10d | %10d | %010" DM_PRIx64 " | %04x\n",
+                        entry->filename, entry->size, entry->csize,
+                        entry->offset, entry->flags);
+
+                    nshown++;
+                    totalSize += entry->size;
+                    totalCSize += entry->csize;
                 }
+
+                ntotal++;
             }
 
-            dmMsg(2, "c=%d\n", dmPackClose(pack));
+            for (int n = 0; n < hlen; n++)
+                fputc('-', stdout);
+
+            printf(
+                "\n"
+                "%-32s | %10" DM_PRIu_SIZE_T " | %10" DM_PRIu_SIZE_T " |\n"
+                "Listed %" DM_PRIu_SIZE_T " of %" DM_PRIu_SIZE_T " files total.\n",
+                "Totals",
+                totalSize, totalCSize,
+                nshown, ntotal);
         }
-        else
-            dmErrorMsg("Could not open packfile, error #%d: %s\n", res,
-                  dmErrorStr(res));
         break;
 
     case CMD_EXTRACT:
         // Extract files from PACK
-        res = dmPackOpen(optPackFilename, &pack, TRUE);
-        if (res == DMERR_OK)
+        if ((res = dmPackOpen(optPackFilename, &pack, TRUE)) != DMERR_OK)
+        {
+            dmErrorMsg("Could not open PACK file: %s\n",
+                dmErrorStr(res));
+            goto out;
+        }
+
+        for (entry = pack->entries; entry != NULL; entry = entry->next)
         {
-            DMPackEntry *node;
-            FILE *resFile = fopen(DMRES_RES_FILE, "w");
-            if (resFile == NULL)
+            BOOL match;
+
+            // Check for matches
+            if (nsrcFilenames > 0)
             {
-                int err = dmGetErrno();
-                dmErrorMsg("Could not create resource output file '%s' #%d: %s\n",
-                    DMRES_RES_FILE, err, dmErrorStr(err));
+                match = !dmMatchList(excFilenames, nexcFilenames, entry->filename) &&
+                    dmMatchList(srcFilenames, nsrcFilenames, entry->filename);
+            }
+            else
+            {
+                match = !dmMatchList(excFilenames, nexcFilenames, entry->filename);
             }
 
-            for (node = pack->entries; node != NULL; node = node->next)
+            if (match && (entry->privFlags & PACK_EXTRACTED) == 0)
             {
-                BOOL match;
-
-                // Check for matches
-                if (nsrcFilenames > 0)
-                {
-                    match = FALSE;
-                    for (int i = 0; i < nsrcFilenames && !match; i++)
-                    {
-                        if (dmStrMatch(node->filename, srcFilenames[i]) &&
-                            !dmCheckExcluded(node->filename))
-                            match = TRUE;
-                    }
-                }
-                else
-                {
-                    match = !dmCheckExcluded(node->filename);
-                }
+                // Print one entry
+                dmPrint(0, "Extracting: %-32s [siz=%d, cmp=%d, offs=0x%08" DM_PRIx64 ", flags=0x%04x]\n",
+                        entry->filename, entry->size, entry->csize,
+                        entry->offset, entry->flags);
 
-                if (match && (node->privFlags & PACK_EXTRACTED) == 0)
-                {
-                    // Mark as done
-                    node->privFlags |= PACK_EXTRACTED;
-
-                    // Print one entry
-                    dmPrint(0, "Extracting: %-32s [siz=%d, cmp=%d, offs=0x%08" DM_PRIx64 ", flags=0x%04x]\n",
-                            node->filename, node->size, node->csize,
-                            node->offset, node->flags);
-
-                    dmPackExtractFile(pack, node, optDoCompress);
-                }
+                if ((res = dmPackExtractFile(pack, entry, optCompressLevel > 0)) == DMERR_OK)
+                    entry->privFlags |= PACK_EXTRACTED;
             }
-
-            dmMsg(2, "c=%d\n", dmPackClose(pack));
-
-            if (resFile != NULL)
-                fclose(resFile);
         }
-        else
-            dmErrorMsg("Could not open packfile, error #%d: %s\n", res,
-                  dmErrorStr(res));
         break;
     }
 
-error:
+out:
+    dmPackClose(pack);
+
     return 0;
 }