update pak format
This commit is contained in:
parent
b34529a2a3
commit
32919ca13d
9 changed files with 324 additions and 73 deletions
|
|
@ -8,18 +8,49 @@
|
|||
#endif
|
||||
#include <stdio.h>
|
||||
|
||||
typedef struct kv {
|
||||
char* key;
|
||||
#include <GearSrc/Endian.h>
|
||||
#include <GearSrc/CRC.h>
|
||||
#include <GearSrc/String.h>
|
||||
|
||||
} kv_t;
|
||||
typedef struct file file_t;
|
||||
|
||||
struct file {
|
||||
char* name;
|
||||
int dir;
|
||||
int before;
|
||||
int after;
|
||||
unsigned char* data;
|
||||
file_t* parent;
|
||||
file_t** files;
|
||||
};
|
||||
|
||||
static FILE* out;
|
||||
static unsigned int total = 0;
|
||||
static unsigned int totalact = 0, totalcmp = 0;
|
||||
static file_t* root;
|
||||
static GSU32 seek = 0;
|
||||
|
||||
static void scan(const char* path, const char* pre);
|
||||
static file_t* new_file(file_t* parent, const char* name) {
|
||||
file_t* n = malloc(sizeof(*n));
|
||||
|
||||
static void pack(const char* fullpath, const char* path) {
|
||||
n->name = GSStringDuplicate(name);
|
||||
n->dir = 0;
|
||||
n->before = 0;
|
||||
n->after = 0;
|
||||
n->data = NULL;
|
||||
n->parent = parent;
|
||||
n->files = NULL;
|
||||
|
||||
if(parent != NULL) {
|
||||
arrput(parent->files, n);
|
||||
}
|
||||
|
||||
return n;
|
||||
}
|
||||
|
||||
static void scan(file_t* parent, const char* path, const char* pre);
|
||||
|
||||
static void pack(file_t* parent, const char* fullpath, const char* path, const char* name) {
|
||||
int m;
|
||||
FILE* f = fopen(fullpath, "rb");
|
||||
int insz;
|
||||
|
|
@ -44,40 +75,22 @@ static void pack(const char* fullpath, const char* path) {
|
|||
outsz = LZ4_compress_default(input, output, insz, m);
|
||||
|
||||
if(outsz > 0) {
|
||||
unsigned int sz;
|
||||
int i;
|
||||
char fn[128];
|
||||
|
||||
memset(fn, 0, 128);
|
||||
memcpy(fn, path, strlen(path));
|
||||
|
||||
fwrite(fn, 1, 128, out);
|
||||
|
||||
sz = insz;
|
||||
for(i = 0; i < 4; i++) {
|
||||
unsigned char n = (sz >> 24) & 0xff;
|
||||
|
||||
fwrite(&n, 1, 1, out);
|
||||
|
||||
sz = sz << 8;
|
||||
}
|
||||
|
||||
sz = outsz;
|
||||
for(i = 0; i < 4; i++) {
|
||||
unsigned char n = (sz >> 24) & 0xff;
|
||||
|
||||
fwrite(&n, 1, 1, out);
|
||||
|
||||
sz = sz << 8;
|
||||
}
|
||||
|
||||
fwrite(output, 1, outsz, out);
|
||||
file_t* n = new_file(parent, name);
|
||||
|
||||
printf("done (%8d -> %8d)\n", insz, outsz);
|
||||
|
||||
total++;
|
||||
totalact += insz;
|
||||
totalcmp += outsz;
|
||||
|
||||
free(input);
|
||||
|
||||
n->before = insz;
|
||||
n->after = outsz;
|
||||
n->data = output;
|
||||
|
||||
fclose(f);
|
||||
return;
|
||||
} else {
|
||||
printf("failed\n");
|
||||
}
|
||||
|
|
@ -104,7 +117,7 @@ static int is_dir(const char* path) {
|
|||
#endif
|
||||
}
|
||||
|
||||
static void found(const char* path, const char* pre, const char* input) {
|
||||
static void found(file_t* parent, const char* path, const char* pre, const char* input) {
|
||||
char* p = malloc(strlen(pre) + strlen(input) + 1 + 1);
|
||||
char* fp = malloc(strlen(path) + 1 + strlen(input) + 1);
|
||||
|
||||
|
|
@ -118,11 +131,15 @@ static void found(const char* path, const char* pre, const char* input) {
|
|||
strcat(fp, input);
|
||||
|
||||
if(is_dir(fp)) {
|
||||
file_t* d = new_file(parent, input);
|
||||
|
||||
d->dir = 1;
|
||||
|
||||
strcat(p, "/");
|
||||
|
||||
scan(fp, p);
|
||||
scan(d, fp, p);
|
||||
} else {
|
||||
pack(fp, p);
|
||||
pack(parent, fp, p, input);
|
||||
}
|
||||
|
||||
free(fp);
|
||||
|
|
@ -130,7 +147,7 @@ static void found(const char* path, const char* pre, const char* input) {
|
|||
free(p);
|
||||
}
|
||||
|
||||
static void scan(const char* path, const char* pre) {
|
||||
static void scan(file_t* parent, const char* path, const char* pre) {
|
||||
#ifdef _WIN32
|
||||
WIN32_FIND_DATA ffd;
|
||||
HANDLE hFind;
|
||||
|
|
@ -147,7 +164,7 @@ static void scan(const char* path, const char* pre) {
|
|||
|
||||
do {
|
||||
if(strcmp(ffd.cFileName, ".") != 0 && strcmp(ffd.cFileName, "..") != 0) {
|
||||
found(path, pre, ffd.cFileName);
|
||||
found(parent, path, pre, ffd.cFileName);
|
||||
}
|
||||
} while(FindNextFile(hFind, &ffd) != 0);
|
||||
FindClose(hFind);
|
||||
|
|
@ -157,7 +174,7 @@ static void scan(const char* path, const char* pre) {
|
|||
struct dirent* d;
|
||||
while((d = readdir(dir)) != NULL) {
|
||||
if(strcmp(d->d_name, "..") != 0 && strcmp(d->d_name, ".") != 0) {
|
||||
found(path, pre, d->d_name);
|
||||
found(parent, path, pre, d->d_name);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -166,6 +183,76 @@ static void scan(const char* path, const char* pre) {
|
|||
#endif
|
||||
}
|
||||
|
||||
static void recursive_write(file_t* parent) {
|
||||
int i;
|
||||
|
||||
if(parent->dir) {
|
||||
for(i = 0; i < arrlen(parent->files); i++) {
|
||||
recursive_write(parent->files[i]);
|
||||
}
|
||||
} else if(parent->data != NULL && parent->after > 0) {
|
||||
fwrite(parent->data, 1, parent->after, out);
|
||||
}
|
||||
}
|
||||
|
||||
static int total_size(file_t* parent, int level) {
|
||||
int sz = level == 0 ? 0 : (1 + 4 + 1 + strlen(parent->name) + 2 + 4);
|
||||
int i;
|
||||
|
||||
for(i = 0; i < arrlen(parent->files); i++) {
|
||||
if(parent->files[i]->dir) {
|
||||
sz += total_size(parent->files[i], level + 1);
|
||||
} else {
|
||||
sz += 1 + 4 + 1 + strlen(parent->files[i]->name) + 4 + 4 + 4;
|
||||
}
|
||||
}
|
||||
|
||||
return sz;
|
||||
}
|
||||
|
||||
static void recursive(file_t* parent) {
|
||||
int i;
|
||||
unsigned char c;
|
||||
GSU16 u16 = 0;
|
||||
GSU32 u32 = 0;
|
||||
GSU32 crc;
|
||||
|
||||
crc = GSCRC32(parent->name, strlen(parent->name));
|
||||
|
||||
c = parent->dir ? 1 : 0;
|
||||
fwrite(&c, 1, 1, out);
|
||||
|
||||
u32 = GSEndianSwapU32BE(crc);
|
||||
fwrite(&u32, 1, 4, out);
|
||||
|
||||
c = strlen(parent->name);
|
||||
fwrite(&c, 1, 1, out);
|
||||
fwrite(parent->name, 1, c, out);
|
||||
|
||||
if(parent->dir) {
|
||||
u16 = GSEndianSwapU16BE(arrlen(parent->files));
|
||||
fwrite(&u16, 1, 2, out);
|
||||
|
||||
u32 = GSEndianSwapU32BE(total_size(parent, 0));
|
||||
fwrite(&u32, 1, 4, out);
|
||||
|
||||
for(i = 0; i < arrlen(parent->files); i++) {
|
||||
recursive(parent->files[i]);
|
||||
}
|
||||
} else {
|
||||
u32 = GSEndianSwapU32BE(parent->before);
|
||||
fwrite(&u32, 1, 4, out);
|
||||
|
||||
u32 = GSEndianSwapU32BE(parent->after);
|
||||
fwrite(&u32, 1, 4, out);
|
||||
|
||||
u32 = GSEndianSwapU32BE(seek);
|
||||
fwrite(&u32, 1, 4, out);
|
||||
|
||||
seek += parent->after;
|
||||
}
|
||||
}
|
||||
|
||||
int main(int argc, char** argv) {
|
||||
unsigned char dat[128];
|
||||
|
||||
|
|
@ -179,21 +266,24 @@ int main(int argc, char** argv) {
|
|||
dat[3] = 'K';
|
||||
|
||||
fwrite(dat, 1, 4, out);
|
||||
|
||||
root = new_file(NULL, "");
|
||||
root->dir = 1;
|
||||
}
|
||||
if(argc == 2) {
|
||||
scan(".", "");
|
||||
scan(root, ".", "");
|
||||
} else if(argc > 2) {
|
||||
int i;
|
||||
|
||||
for(i = 1; i < argc; i++) scan(argv[i], "");
|
||||
for(i = 1; i < argc; i++) scan(root, argv[i], "");
|
||||
} else {
|
||||
printf("Usage: %s output [input]\n", argv[0]);
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
memset(dat, 0, 128);
|
||||
fwrite(dat, 1, 128, out);
|
||||
recursive(root);
|
||||
recursive_write(root);
|
||||
|
||||
printf("total %u files added, compressed %u -> %u bytes\n", total, totalact, totalcmp);
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue