Mercurial > hg > dmlib
diff packed.c @ 0:32250b436bca
Initial re-import.
author | Matti Hamalainen <ccr@tnsp.org> |
---|---|
date | Fri, 28 Sep 2012 01:54:23 +0300 |
parents | |
children | 7ad2c6b57932 |
line wrap: on
line diff
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/packed.c Fri Sep 28 01:54:23 2012 +0300 @@ -0,0 +1,451 @@ +/* + * PACKed - PACKfile EDitor + * Programmed and designed by Matti 'ccr' Hamalainen + * (C) Copyright 2011 Tecnic Software productions (TNSP) + */ +#include "dmlib.h" +#include "dmargs.h" +#include "dmpack.h" +#include "dmpackutil.h" +#include <errno.h> + +#define SET_MAX_FILES (4096) +#define SET_DEFAULT_PACK "data.pak" + +enum +{ + CMD_NONE = 0, + CMD_CREATE, + CMD_ADD, + CMD_LIST, + CMD_EXTRACT +} DCOMMAND; + +enum +{ + PACK_EXTRACTED = 0x0001, +}; + +int nsrcFilenames = 0; +char * srcFilenames[SET_MAX_FILES]; +char * optPackFilename = NULL; +BOOL optCompress = TRUE; +int optCommand = CMD_NONE; +int optDefResFlags = 0; + + +static DMOptArg optList[] = +{ + { 0, '?', "help", "Show this help", OPT_NONE }, + { 1, 'p', "pack", "Set pack filename (default: " SET_DEFAULT_PACK ")", OPT_ARGREQ }, + { 2, 'c', "create", "Create and add files to PACK", OPT_NONE }, + { 3, 'a', "add", "Add files to PACK", OPT_NONE }, + { 4, 'l', "list", "List files in PACK", OPT_NONE }, + { 5, 'e', "extract", "Extract files from PACK", OPT_NONE }, + { 6, 'n', "nocompress", "No compression", OPT_NONE }, + { 7, 'v', "verbose", "Increase verbosity", OPT_NONE }, + { 8, 'f', "resflags", "Set default resource flags (-f 0xff)", OPT_ARGREQ }, +}; + +static const int optListN = sizeof(optList) / sizeof(optList[0]); + + +void argShowHelp() +{ + dmPrintBanner(stdout, dmProgName, "[options] <packfile> [filename[s]]"); + dmArgsPrintHelp(stdout, optList, optListN); + fprintf(stdout, + "\n" + "Examples:\n" + "$ %s -p test.pak -l -- list files in test.pak\n" + "$ %s -a foobar.jpg -- add foobar.jpg in " SET_DEFAULT_PACK "\n" + "$ %s -x foobar.jpg -- extract foobar.jpg from " SET_DEFAULT_PACK "\n", + dmProgName, dmProgName, dmProgName); +} + + +BOOL argHandleOpt(const int optN, char *optArg, char *currArg) +{ + (void) optArg; + switch (optN) + { + case 0: + argShowHelp(); + exit(0); + break; + + case 1: + optPackFilename = optArg; + break; + case 2: + optCommand = CMD_CREATE; + break; + case 3: + optCommand = CMD_ADD; + break; + case 4: + optCommand = CMD_LIST; + break; + case 5: + optCommand = CMD_EXTRACT; + break; + + case 6: + optCompress = FALSE; + break; + + case 7: + dmVerbosity++; + break; + + case 8: + { + int i; + if (!dmGetIntVal(optArg, &i)) + { + dmError("Invalid flags value '%s'.\n", optArg); + return FALSE; + } + optDefResFlags = i; + } + break; + + default: + dmError("Unknown argument '%s'.\n", currArg); + return FALSE; + } + + return TRUE; +} + + +BOOL argHandleFile(char *currArg) +{ + if (nsrcFilenames < SET_MAX_FILES) + { + srcFilenames[nsrcFilenames] = currArg; + nsrcFilenames++; + } + else + { + dmError("Maximum number of input files (%i) exceeded!\n", + SET_MAX_FILES); + return FALSE; + } + return TRUE; +} + + +/* Compare a string to a pattern. Case-SENSITIVE version. + * The matching pattern can consist of any normal characters plus + * wildcards ? and *. "?" matches any character and "*" matches + * any number of characters. + */ +BOOL dm_strmatch(const char *str, const char *pattern) +{ + BOOL didMatch = TRUE, isAnyMode = FALSE, isEnd = FALSE; + const char *tmpPattern = NULL; + + // Check given pattern and string + if (str == NULL || pattern == NULL) + return FALSE; + + // Start comparision + do { + didMatch = FALSE; + switch (*pattern) + { + case '?': + // Any single character matches + if (*str) + { + didMatch = TRUE; + pattern++; + str++; + } + break; + + case '*': + didMatch = TRUE; + pattern++; + if (!*pattern) + isEnd = TRUE; + isAnyMode = TRUE; + tmpPattern = pattern; + break; + + case 0: + if (isAnyMode) + { + if (*str) + str++; + else + isEnd = TRUE; + } + else + { + if (*str) + { + if (tmpPattern) + { + isAnyMode = TRUE; + pattern = tmpPattern; + } + else + didMatch = FALSE; + } + else + isEnd = TRUE; + } + break; + default: + if (isAnyMode) + { + if (*pattern == *str) + { + isAnyMode = FALSE; + didMatch = TRUE; + } + else + { + if (*str) + { + didMatch = TRUE; + str++; + } + } + } + else + { + if (*pattern == *str) + { + didMatch = TRUE; + if (*pattern) + pattern++; + if (*str) + str++; + } + else + { + if (tmpPattern) + { + didMatch = TRUE; + isAnyMode = TRUE; + pattern = tmpPattern; + } + } + } + + if (!*str && !*pattern) + isEnd = TRUE; + break; + + } // switch + + } while (didMatch && !isEnd); + + return didMatch; +} + + +int dmAddFileToPack(DMPackFile *pack, const char *filename, int compression, int resFlags) +{ + DMPackEntry *node; + int res = dm_pack_add_file(pack, filename, compression, resFlags, &node); + + if (res != DMERR_OK) + { + dmPrint(1, "%-32s [ERROR:%i]\n", + filename, res); + } + else + { + dmPrint(1, "%-32s ['%s', s=%d, c=%d, o=%ld, f=0x%04x]\n", + filename, node->filename, + node->size, node->length, node->offset, + node->resFlags); + } + + return res; +} + + +int main(int argc, char *argv[]) +{ + int i, res = 0; + DMPackFile *pack = NULL; + + stderr = stdout; + + // Parse arguments + dmInitProg("packed", "Pack File Editor", "0.4", NULL, NULL); + dmVerbosity = 1; + + if (!dmArgsProcess(argc, argv, optList, optListN, + argHandleOpt, argHandleFile, TRUE)) + exit(1); + + // Check PACK filename + if (optPackFilename == NULL) + optPackFilename = SET_DEFAULT_PACK; + + if (optCommand == CMD_NONE) + { + argShowHelp(); + dmError("Nothing to do.\n"); + exit(0); + return 0; + } + + dmMsg(1, "Processing %s ...\n", optPackFilename); + + // Execute command + switch (optCommand) + { + case CMD_CREATE: + case CMD_ADD: + switch (optCommand) + { + case CMD_CREATE: + dmMsg(1, "Creating new PACK\n"); + res = dm_pack_create(optPackFilename, &pack); + break; + + case CMD_ADD: + dmMsg(1, "Opening existing PACK\n"); + res = dm_pack_open(optPackFilename, &pack, FALSE); + break; + } + + // Add files into PACK + if (res == DMERR_OK) + { + dmMsg(1, "Adding %d files...\n", nsrcFilenames); + + for (i = 0; i < nsrcFilenames; i++) + { + // Handle resource definition files + if (srcFilenames[i][0] == '@') + { + } + else + { + dmAddFileToPack(pack, srcFilenames[i], optCompress, optDefResFlags); + } + } + + dmMsg(1, "w=%i\n", dm_pack_write(pack)); + dmMsg(1, "c=%i\n", dm_pack_close(pack)); + } + else + { + dmError("Could not open packfile, error #%i: %s\n", res, + dmErrorStr(res)); + } + break; + + case CMD_LIST: + // List files in PACK + res = dm_pack_open(optPackFilename, &pack, TRUE); + if (res == DMERR_OK) + { + DMPackEntry *node; + for (i = 0, node = pack->entries; node; i++) + node = node->next; + dmMsg(1, "%d files total\n", i); + + for (node = pack->entries; node != NULL; node = node->next) + { + BOOL match; + + // Check for matches + if (nsrcFilenames > 0) + { + match = FALSE; + for (i = 0; i < nsrcFilenames && !match; i++) + { + match = dm_strmatch(node->filename, srcFilenames[i]); + } + } + else + match = TRUE; + + if (match) + { + // Print one entry + dmPrint(0, "Extracting: %-32s [siz=%d, cmp=%d, offs=0x%08x, flags=0x%04x]\n", + node->filename, node->size, node->length, + node->offset, node->resFlags); + } + } + + dmMsg(1, "c=%i\n", dm_pack_close(pack)); + } + else + dmError("Could not open packfile, error #%i: %s\n", res, + dmErrorStr(res)); + break; + + case CMD_EXTRACT: + // Extract files from PACK + res = dm_pack_open(optPackFilename, &pack, TRUE); + if (res == DMERR_OK) + { + DMPackEntry *node; + FILE *resFile = fopen(DMRES_RES_FILE, "w"); + if (resFile == NULL) + { + dmError("Could not create resource output file '%s' #%i: %s\n", + DMRES_RES_FILE, errno, strerror(errno)); + } + + for (node = pack->entries; node != NULL; node = node->next) + { + BOOL match; + + // Check for matches + if (nsrcFilenames > 0) + { + match = FALSE; + for (i = 0; (i < nsrcFilenames) && !match; i++) + { + match = dm_strmatch(node->filename, srcFilenames[i]); + } + } + else + match = TRUE; + + 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%08x, flags=0x%04x]\n", + node->filename, node->size, node->length, + node->offset, node->resFlags); + + dm_pack_extract_file(pack, node); + + if (resFile != NULL) + { + fprintf(resFile, + "%s|%04x", node->filename, node->resFlags); + } + } + } + + dmMsg(1, "c=%i\n", dm_pack_close(pack)); + + if (resFile != NULL) + fclose(resFile); + } + else + dmError("Could not open packfile, error #%i: %s\n", res, + dmErrorStr(res)); + break; + + } + + return 0; +}