Mercurial > hg > dmlib
view packed.c @ 120:a4830b62ff5d
Increase delay here a bit.
author | Matti Hamalainen <ccr@tnsp.org> |
---|---|
date | Thu, 04 Oct 2012 03:43:43 +0300 |
parents | b56ce9981d79 |
children | 3dc35ce354f7 |
line wrap: on
line source
/* * 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 "dmres.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] [-p <packfilename>] [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; #ifndef __WIN32 stderr = stdout; #endif // 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); dmPrint(0, "%-32s | %8s | %8s | %8s | %s\n", "Name", "Size", "CSize", "Offset", "ResFlags"); 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) { char flags[16]; dmres_flags_to_symbolic(flags, sizeof(flags), node->resFlags); dmPrint(0, "%-32s | %8d | %8d | %08x | %s\n", node->filename, node->size, node->length, node->offset, flags); } } 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; }