#include "pak_pack.h" bool pakUnpack(uint8_t *buffer, char *outputPath) { MyPakHeader myHeader; if (!pakParseHeader(buffer, &myHeader)) { return false; } PakFile *files = pakGetFiles(buffer); if (files == NULL) { return false; } char fileNameBuf[FILENAME_MAX]; memset(fileNameBuf, 0, FILENAME_MAX); char pathBuf[PATH_MAX + 2]; memset(pathBuf, 0, PATH_MAX); #ifdef _WIN32 CreateDirectory(outputPath, NULL); #else mkdir(outputPath, 0777); #endif char *pakIndexStr = calloc(PAK_BUFFER_BLOCK_SIZE, sizeof(char)); if (pakIndexStr == NULL) { free(files); return false; } uint32_t offset = 0; uint32_t length = PAK_BUFFER_BLOCK_SIZE; offset += sprintf(pakIndexStr + offset, PAK_INDEX_GLOBAL_TAG "\r\nversion=%u\r\n", myHeader.version); offset += sprintf(pakIndexStr + offset, "encoding=%u\r\n\r\n" PAK_INDEX_RES_TAG "\r\n", myHeader.encoding); for (uint32_t i = 0; i < myHeader.resource_count; i++) { sprintf(fileNameBuf, "%u%s", files[i].id, pakGetFileType(files[i])); offset += sprintf(pakIndexStr + offset, "%u=%s\r\n", files[i].id, fileNameBuf); if (length - offset < PAK_BUFFER_MIN_FREE_SIZE) { pakIndexStr = realloc(pakIndexStr, length + PAK_BUFFER_BLOCK_SIZE); length += PAK_BUFFER_BLOCK_SIZE; } sprintf(pathBuf, "%s/%s", outputPath, fileNameBuf); writeFile(pathBuf, files[i]); } PakAlias *aliasBuf = NULL; if (myHeader.alias_count > 0) { offset += sprintf(pakIndexStr + offset, "\r\n" PAK_INDEX_ALIAS_TAG "\r\n"); aliasBuf = (PakAlias *)(buffer + myHeader.size + (myHeader.resource_count + 1) * PAK_ENTRY_SIZE); } for (unsigned int i = 0; i < myHeader.alias_count; i++) { offset += sprintf(pakIndexStr + offset, "%u=%u\r\n", aliasBuf->resource_id, aliasBuf->entry_index); aliasBuf++; if (length - offset < PAK_BUFFER_MIN_FREE_SIZE) { pakIndexStr = realloc(pakIndexStr, length + PAK_BUFFER_BLOCK_SIZE); length += PAK_BUFFER_BLOCK_SIZE; } } PakFile pakIndexBuf; // puts(pakIndexStr); pakIndexBuf.buffer = pakIndexStr; pakIndexBuf.size = offset; sprintf(pathBuf, "%s/pak_index.ini", outputPath); writeFile(pathBuf, pakIndexBuf); freeFile(pakIndexBuf); free(files); return true; } uint32_t countChar(const char *string, uint32_t length, char toCount) { uint32_t count = 0; for (uint32_t i = 0; i < length; i++) { if (string[i] == toCount) count++; } return count; } PakFile pakPack(PakFile pakIndex, char *path) { // TODO MyPakHeader myHeader; memset(&myHeader, 0, sizeof(myHeader)); char *pakIndexBuf = pakIndex.buffer; PakFile pakFile = NULL_File; PakFile *resFiles = NULL; PakAlias *pakAlias = NULL; uint32_t count = 0; uint32_t offset = sizeof(PAK_INDEX_GLOBAL_TAG) - 1; sscanf(pakIndexBuf + offset, " version=%u%n", &myHeader.version, &count); if (count == 0) { goto PAK_PACK_END; } offset += count; #pragma GCC diagnostic push #pragma GCC diagnostic ignored "-Wformat" #pragma GCC diagnostic ignored "-Wformat-extra-args" sscanf(pakIndexBuf + offset, " encoding=%hhu%n", &myHeader.encoding, &count); #pragma GCC diagnostic pop // printf("version=%u\nencoding=%u\n", myHeader.version, // myHeader.encoding); if (myHeader.version == 5) { myHeader.size = PAK_HEADER_SIZE_V5; } else if (myHeader.version == 4) { myHeader.size = PAK_HEADER_SIZE_V4; } else { puts(PAK_ERROR_UNKNOWN_VER); goto PAK_PACK_END; } char *pakIndexEnd = pakIndexBuf + pakIndex.size - 1; char *pakEntryIndex = strstr(pakIndexBuf, PAK_INDEX_RES_TAG) + sizeof(PAK_INDEX_RES_TAG) - 1; char *pakAliasIndex = strstr(pakIndexBuf, PAK_INDEX_ALIAS_TAG); if (myHeader.version == 4 || pakAliasIndex == NULL) { myHeader.alias_count = 0; pakAliasIndex = pakIndexEnd; } else { pakAliasIndex += sizeof(PAK_INDEX_ALIAS_TAG) - 1; myHeader.alias_count = (uint16_t) countChar(pakAliasIndex, pakIndexEnd - pakAliasIndex, '='); } myHeader.resource_count = countChar(pakEntryIndex, pakAliasIndex - pakEntryIndex, '='); // printf("resource_count=%u\nalias_count=%u\n", myHeader.resource_count, // myHeader.alias_count); char fileNameBuf[FILENAME_MAX]; memset(fileNameBuf, 0, FILENAME_MAX); char pathBuf[PATH_MAX]; memset(pathBuf, 0, PATH_MAX); resFiles = calloc(myHeader.resource_count, sizeof(PakFile)); if (resFiles == NULL) { goto PAK_PACK_END; } offset = 0; for (uint32_t i = 0; i < myHeader.resource_count; i++) { uint32_t id = 0; sscanf(pakEntryIndex + offset, " %u=%s%n ", &id, fileNameBuf, &count); if (count == 0 || sprintf(pathBuf, "%s%s", path, fileNameBuf) == 0) { puts(PAK_ERROR_BROKEN_INDEX); myHeader.resource_count = i; goto PAK_PACK_END; } offset += count; resFiles[i] = readFile(pathBuf); if (resFiles[i].buffer == NULL) { puts(PAK_ERROR_BROKEN_INDEX); myHeader.resource_count = i; goto PAK_PACK_END; } resFiles[i].id = (uint16_t) id; // printf("id=%u\tfile_name=%s\tpath=%s\tsize=%u\n",id, // fileNameBuf, pathBuf, resFiles[i].size); } if (myHeader.alias_count > 0) { offset = 0; pakAlias = calloc(myHeader.alias_count, sizeof(PakAlias)); if (pakAlias == NULL) { goto PAK_PACK_END; } for (uint32_t i = 0; i < myHeader.alias_count; i++) { sscanf(pakAliasIndex + offset, " %hu=%hu%n ", &pakAlias[i].resource_id, &pakAlias[i].entry_index, &count); if (count == 0) { puts(PAK_ERROR_BROKEN_INDEX); goto PAK_PACK_END; } offset += count; // printf("resource_id=%hu\tentry_index=%hu\n",pakAlias[i].resource_id, // pakAlias[i].entry_index); } } pakFile = pakPackFiles(&myHeader, resFiles, pakAlias); printf("\nresource_count=%u\nalias_count=%u\n", myHeader.resource_count, myHeader.alias_count); printf("version=%u\nencoding=%u\n", myHeader.version, myHeader.encoding); printf("\npak size: %u\n", pakFile.size); PAK_PACK_END: if (resFiles != NULL) { for (uint32_t i = 0; i < myHeader.resource_count; i++) { if (resFiles[i].buffer != NULL) free(resFiles[i].buffer); } free(resFiles); } if (pakAlias != NULL) free(pakAlias); return pakFile; }