update pak format
This commit is contained in:
parent
b34529a2a3
commit
32919ca13d
9 changed files with 324 additions and 73 deletions
17
engine/include/GearSrc/CRC.h
Normal file
17
engine/include/GearSrc/CRC.h
Normal file
|
|
@ -0,0 +1,17 @@
|
||||||
|
#ifndef __GEARSRC_CRC_H__
|
||||||
|
#define __GEARSRC_CRC_H__
|
||||||
|
|
||||||
|
#include <GearSrc/MachDep.h>
|
||||||
|
#include <GearSrc/TypeDefs.h>
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
extern "C" {
|
||||||
|
#endif
|
||||||
|
|
||||||
|
GSDECL GSU32 GSCRC32(void* input, unsigned int len);
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
@ -12,6 +12,7 @@ extern "C" {
|
||||||
GSDECL GSFile GSFileOpen(GSEngine engine, const char* path);
|
GSDECL GSFile GSFileOpen(GSEngine engine, const char* path);
|
||||||
GSDECL int GSFileRead(GSFile file, void* out, int size);
|
GSDECL int GSFileRead(GSFile file, void* out, int size);
|
||||||
GSDECL void GSFileSeek(GSFile file, int pos);
|
GSDECL void GSFileSeek(GSFile file, int pos);
|
||||||
|
GSDECL void GSFileSeekFromCurrent(GSFile file, int pos);
|
||||||
GSDECL unsigned int GSFileSize(GSFile file);
|
GSDECL unsigned int GSFileSize(GSFile file);
|
||||||
GSDECL void GSFileClose(GSFile file);
|
GSDECL void GSFileClose(GSFile file);
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -15,5 +15,6 @@
|
||||||
#include <GearSrc/Resource.h>
|
#include <GearSrc/Resource.h>
|
||||||
#include <GearSrc/Endian.h>
|
#include <GearSrc/Endian.h>
|
||||||
#include <GearSrc/SkyBox.h>
|
#include <GearSrc/SkyBox.h>
|
||||||
|
#include <GearSrc/CRC.h>
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
|
||||||
|
|
@ -11,7 +11,8 @@ extern "C" {
|
||||||
enum GSLogLevel {
|
enum GSLogLevel {
|
||||||
GSLogInfo = 0,
|
GSLogInfo = 0,
|
||||||
GSLogWarn,
|
GSLogWarn,
|
||||||
GSLogError
|
GSLogError,
|
||||||
|
GSLogDebug
|
||||||
};
|
};
|
||||||
|
|
||||||
GSDECL void GSLog(int level, const char* fmt, ...);
|
GSDECL void GSLog(int level, const char* fmt, ...);
|
||||||
|
|
|
||||||
25
engine/src/crc.c
Normal file
25
engine/src/crc.c
Normal file
|
|
@ -0,0 +1,25 @@
|
||||||
|
/* crc32.c -- compute the CRC-32 of a data stream
|
||||||
|
* Copyright (C) 1995-1998 Mark Adler
|
||||||
|
* For conditions of distribution and use, see copyright notice in zlib.h
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <GearSrc/CRC.h>
|
||||||
|
|
||||||
|
GSU32 GSCRC32(void* input, unsigned int len) {
|
||||||
|
int i, j;
|
||||||
|
GSU32 byte, crc, mask;
|
||||||
|
unsigned char* message = input;
|
||||||
|
|
||||||
|
i = 0;
|
||||||
|
crc = 0xFFFFFFFF;
|
||||||
|
while(i < len) {
|
||||||
|
byte = message[i]; // Get next byte.
|
||||||
|
crc = crc ^ byte;
|
||||||
|
for(j = 7; j >= 0; j--) { // Do eight times.
|
||||||
|
mask = -(crc & 1);
|
||||||
|
crc = (crc >> 1) ^ (0xEDB88320 & mask);
|
||||||
|
}
|
||||||
|
i = i + 1;
|
||||||
|
}
|
||||||
|
return ~crc;
|
||||||
|
}
|
||||||
|
|
@ -30,8 +30,7 @@ GSFile GSFileOpen(GSEngine engine, const char* path) {
|
||||||
int i;
|
int i;
|
||||||
|
|
||||||
nam[0] = 0;
|
nam[0] = 0;
|
||||||
nam[1] = 0;
|
nam += 1;
|
||||||
nam += 2;
|
|
||||||
|
|
||||||
for(i = 0; i < shlen(engine->resource); i++) {
|
for(i = 0; i < shlen(engine->resource); i++) {
|
||||||
if(strcmp(engine->resource[i].key, s) == 0) {
|
if(strcmp(engine->resource[i].key, s) == 0) {
|
||||||
|
|
@ -78,6 +77,11 @@ void GSFileSeek(GSFile file, int pos) {
|
||||||
file->seek = pos;
|
file->seek = pos;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void GSFileSeekFromCurrent(GSFile file, int pos) {
|
||||||
|
if(file->fp != NULL) fseek(file->fp, pos, SEEK_CUR);
|
||||||
|
file->seek += pos;
|
||||||
|
}
|
||||||
|
|
||||||
unsigned int GSFileSize(GSFile file) {
|
unsigned int GSFileSize(GSFile file) {
|
||||||
return file->size;
|
return file->size;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -13,6 +13,8 @@ void GSLog(int level, const char* fmt, ...) {
|
||||||
fprintf(out, "WARN ");
|
fprintf(out, "WARN ");
|
||||||
} else if(level == GSLogError) {
|
} else if(level == GSLogError) {
|
||||||
fprintf(out, "ERROR");
|
fprintf(out, "ERROR");
|
||||||
|
} else if(level == GSLogDebug) {
|
||||||
|
fprintf(out, "DEBUG");
|
||||||
}
|
}
|
||||||
#else
|
#else
|
||||||
fprintf(out, "[\x1b[mGearSrc\x1b[m|");
|
fprintf(out, "[\x1b[mGearSrc\x1b[m|");
|
||||||
|
|
@ -23,6 +25,8 @@ void GSLog(int level, const char* fmt, ...) {
|
||||||
fprintf(out, "\x1b[1m\x1b[33mWARN\x1b[m ");
|
fprintf(out, "\x1b[1m\x1b[33mWARN\x1b[m ");
|
||||||
} else if(level == GSLogError) {
|
} else if(level == GSLogError) {
|
||||||
fprintf(out, "\x1b[1m\x1b[31mERROR\x1b[m");
|
fprintf(out, "\x1b[1m\x1b[31mERROR\x1b[m");
|
||||||
|
} else if(level == GSLogDebug) {
|
||||||
|
fprintf(out, "\x1b[1m\x1b[34mDEBUG\x1b[m");
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -3,9 +3,28 @@
|
||||||
#include <GearSrc/File.h>
|
#include <GearSrc/File.h>
|
||||||
#include <GearSrc/Log.h>
|
#include <GearSrc/Log.h>
|
||||||
#include <GearSrc/Endian.h>
|
#include <GearSrc/Endian.h>
|
||||||
|
#include <GearSrc/CRC.h>
|
||||||
|
#include <GearSrc/String.h>
|
||||||
|
|
||||||
#include <lz4.h>
|
#include <lz4.h>
|
||||||
|
|
||||||
|
/**
|
||||||
|
* signature: 0x7F PAK
|
||||||
|
*
|
||||||
|
* entry:
|
||||||
|
* 1 byte: type
|
||||||
|
* 4 bytes: name crc32
|
||||||
|
* 1 byte: name len
|
||||||
|
* n bytes: name
|
||||||
|
* if file {
|
||||||
|
* 4 bytes: actual size
|
||||||
|
* 4 bytes: compressed size
|
||||||
|
* 4 bytes: seek pos
|
||||||
|
* } else {
|
||||||
|
* 2 bytes: number of entries
|
||||||
|
* }
|
||||||
|
*/
|
||||||
|
|
||||||
static unsigned char res_sig[4] = {
|
static unsigned char res_sig[4] = {
|
||||||
0x7f,
|
0x7f,
|
||||||
'P',
|
'P',
|
||||||
|
|
@ -37,45 +56,134 @@ GSResource GSResourceOpen(GSEngine engine, const char* path) {
|
||||||
return resource;
|
return resource;
|
||||||
}
|
}
|
||||||
|
|
||||||
void* GSResourceGet(GSResource resource, const char* name, unsigned int* size) {
|
int find_entry(GSFile f, const char* name, int max, GSU32* totsz, GSU32* actsz, GSU32* cmpsz, GSU32* seekpos) {
|
||||||
char fn[129];
|
GSU32 crc = GSEndianSwapU32BE(GSCRC32((void*)name, strlen(name)));
|
||||||
|
int i;
|
||||||
|
|
||||||
fn[128] = 0;
|
for(i = 0; i < max; i++) {
|
||||||
|
unsigned char dir;
|
||||||
|
unsigned char len;
|
||||||
|
char* fn;
|
||||||
|
GSU32 t;
|
||||||
|
|
||||||
|
if(GSFileRead(f, &dir, 1) < 1) return -1;
|
||||||
|
if(GSFileRead(f, &t, 4) < 4) return -1;
|
||||||
|
if(GSFileRead(f, &len, 1) < 1) return -1;
|
||||||
|
|
||||||
|
fn = malloc(len + 1);
|
||||||
|
if(len > 0) {
|
||||||
|
if(GSFileRead(f, fn, len) < len) {
|
||||||
|
free(fn);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
fn[len] = 0;
|
||||||
|
|
||||||
|
if(dir) {
|
||||||
|
GSU16 n;
|
||||||
|
GSU32 tsz;
|
||||||
|
|
||||||
|
if(GSFileRead(f, &n, 2) < 2) {
|
||||||
|
free(fn);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(GSFileRead(f, &tsz, 4) < 4) {
|
||||||
|
free(fn);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
n = GSEndianSwapU16BE(n);
|
||||||
|
tsz = GSEndianSwapU32BE(tsz);
|
||||||
|
|
||||||
|
if(totsz != NULL) *totsz = tsz;
|
||||||
|
|
||||||
|
if(crc == t && strcmp(fn, name) == 0) {
|
||||||
|
GSLog(GSLogDebug, "Directory %s/ found", fn);
|
||||||
|
free(fn);
|
||||||
|
return n;
|
||||||
|
}
|
||||||
|
|
||||||
|
GSFileSeekFromCurrent(f, tsz);
|
||||||
|
} else {
|
||||||
|
if(GSFileRead(f, actsz, 4) < 4) {
|
||||||
|
free(fn);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(GSFileRead(f, cmpsz, 4) < 4) {
|
||||||
|
free(fn);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(GSFileRead(f, seekpos, 4) < 4) {
|
||||||
|
free(fn);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
*actsz = GSEndianSwapU32BE(*actsz);
|
||||||
|
*cmpsz = GSEndianSwapU32BE(*cmpsz);
|
||||||
|
*seekpos = GSEndianSwapU32BE(*seekpos);
|
||||||
|
|
||||||
|
if(crc == t && strcmp(fn, name) == 0) {
|
||||||
|
GSLog(GSLogDebug, "File %s found", fn);
|
||||||
|
free(fn);
|
||||||
|
return -2;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
free(fn);
|
||||||
|
}
|
||||||
|
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
void* GSResourceGet(GSResource resource, const char* name, unsigned int* size) {
|
||||||
|
char* p = GSStringDuplicate(name);
|
||||||
|
char* s = p;
|
||||||
|
char* f = s;
|
||||||
|
int m = 1;
|
||||||
|
GSU32 totsz;
|
||||||
|
GSU32 actsz;
|
||||||
|
GSU32 cmpsz;
|
||||||
|
GSU32 seekpos;
|
||||||
|
unsigned char* d = NULL;
|
||||||
|
|
||||||
GSFileSeek(resource->file, 4);
|
GSFileSeek(resource->file, 4);
|
||||||
|
|
||||||
while(!(GSFileRead(resource->file, fn, 128) < 128 || fn[0] == 0)) {
|
while(1) {
|
||||||
GSU32 actsz = 0;
|
s = strchr(s, '/');
|
||||||
GSU32 cmpsz = 0;
|
|
||||||
int i;
|
|
||||||
void* d;
|
|
||||||
|
|
||||||
if(GSFileRead(resource->file, &actsz, 4) < 4) return NULL;
|
if(s != NULL) s[0] = 0;
|
||||||
if(GSFileRead(resource->file, &cmpsz, 4) < 4) return NULL;
|
|
||||||
|
|
||||||
actsz = GSEndianSwapU32BE(actsz);
|
m = find_entry(resource->file, f, m, strlen(f) == 0 ? &totsz : NULL, &actsz, &cmpsz, &seekpos);
|
||||||
cmpsz = GSEndianSwapU32BE(cmpsz);
|
if(m == -1) break;
|
||||||
|
if(m == -2) {
|
||||||
|
unsigned char* cmp = malloc(cmpsz);
|
||||||
|
|
||||||
*size = actsz;
|
if(actsz > cmpsz * 255) actsz = cmpsz * 255;
|
||||||
|
|
||||||
d = malloc(cmpsz);
|
d = malloc(actsz);
|
||||||
if(GSFileRead(resource->file, d, cmpsz) < cmpsz) {
|
|
||||||
free(d);
|
GSFileSeek(resource->file, 4 + 1 + 4 + 1 + 2 + 4 + totsz + seekpos);
|
||||||
return NULL;
|
GSFileRead(resource->file, cmp, cmpsz);
|
||||||
|
|
||||||
|
LZ4_decompress_safe(cmp, d, cmpsz, actsz);
|
||||||
|
|
||||||
|
free(cmp);
|
||||||
|
|
||||||
|
*size = actsz;
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
if(strcmp(fn, name) == 0) {
|
|
||||||
unsigned char* r = malloc(actsz);
|
|
||||||
LZ4_decompress_safe(d, r, cmpsz, actsz);
|
|
||||||
|
|
||||||
free(d);
|
if(s == NULL) break;
|
||||||
|
s++;
|
||||||
return r;
|
f = s;
|
||||||
} else {
|
|
||||||
free(d);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return NULL;
|
free(p);
|
||||||
|
|
||||||
|
return d;
|
||||||
}
|
}
|
||||||
|
|
||||||
void GSResourceClose(GSResource resource) {
|
void GSResourceClose(GSResource resource) {
|
||||||
|
|
|
||||||
|
|
@ -8,18 +8,49 @@
|
||||||
#endif
|
#endif
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
|
|
||||||
typedef struct kv {
|
#include <GearSrc/Endian.h>
|
||||||
char* key;
|
#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 FILE* out;
|
||||||
static unsigned int total = 0;
|
static unsigned int total = 0;
|
||||||
static unsigned int totalact = 0, totalcmp = 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;
|
int m;
|
||||||
FILE* f = fopen(fullpath, "rb");
|
FILE* f = fopen(fullpath, "rb");
|
||||||
int insz;
|
int insz;
|
||||||
|
|
@ -44,40 +75,22 @@ static void pack(const char* fullpath, const char* path) {
|
||||||
outsz = LZ4_compress_default(input, output, insz, m);
|
outsz = LZ4_compress_default(input, output, insz, m);
|
||||||
|
|
||||||
if(outsz > 0) {
|
if(outsz > 0) {
|
||||||
unsigned int sz;
|
file_t* n = new_file(parent, name);
|
||||||
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);
|
|
||||||
|
|
||||||
printf("done (%8d -> %8d)\n", insz, outsz);
|
printf("done (%8d -> %8d)\n", insz, outsz);
|
||||||
|
|
||||||
total++;
|
total++;
|
||||||
totalact += insz;
|
totalact += insz;
|
||||||
totalcmp += outsz;
|
totalcmp += outsz;
|
||||||
|
|
||||||
|
free(input);
|
||||||
|
|
||||||
|
n->before = insz;
|
||||||
|
n->after = outsz;
|
||||||
|
n->data = output;
|
||||||
|
|
||||||
|
fclose(f);
|
||||||
|
return;
|
||||||
} else {
|
} else {
|
||||||
printf("failed\n");
|
printf("failed\n");
|
||||||
}
|
}
|
||||||
|
|
@ -104,7 +117,7 @@ static int is_dir(const char* path) {
|
||||||
#endif
|
#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* p = malloc(strlen(pre) + strlen(input) + 1 + 1);
|
||||||
char* fp = malloc(strlen(path) + 1 + strlen(input) + 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);
|
strcat(fp, input);
|
||||||
|
|
||||||
if(is_dir(fp)) {
|
if(is_dir(fp)) {
|
||||||
|
file_t* d = new_file(parent, input);
|
||||||
|
|
||||||
|
d->dir = 1;
|
||||||
|
|
||||||
strcat(p, "/");
|
strcat(p, "/");
|
||||||
|
|
||||||
scan(fp, p);
|
scan(d, fp, p);
|
||||||
} else {
|
} else {
|
||||||
pack(fp, p);
|
pack(parent, fp, p, input);
|
||||||
}
|
}
|
||||||
|
|
||||||
free(fp);
|
free(fp);
|
||||||
|
|
@ -130,7 +147,7 @@ static void found(const char* path, const char* pre, const char* input) {
|
||||||
free(p);
|
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
|
#ifdef _WIN32
|
||||||
WIN32_FIND_DATA ffd;
|
WIN32_FIND_DATA ffd;
|
||||||
HANDLE hFind;
|
HANDLE hFind;
|
||||||
|
|
@ -147,7 +164,7 @@ static void scan(const char* path, const char* pre) {
|
||||||
|
|
||||||
do {
|
do {
|
||||||
if(strcmp(ffd.cFileName, ".") != 0 && strcmp(ffd.cFileName, "..") != 0) {
|
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);
|
} while(FindNextFile(hFind, &ffd) != 0);
|
||||||
FindClose(hFind);
|
FindClose(hFind);
|
||||||
|
|
@ -157,7 +174,7 @@ static void scan(const char* path, const char* pre) {
|
||||||
struct dirent* d;
|
struct dirent* d;
|
||||||
while((d = readdir(dir)) != NULL) {
|
while((d = readdir(dir)) != NULL) {
|
||||||
if(strcmp(d->d_name, "..") != 0 && strcmp(d->d_name, ".") != 0) {
|
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
|
#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) {
|
int main(int argc, char** argv) {
|
||||||
unsigned char dat[128];
|
unsigned char dat[128];
|
||||||
|
|
||||||
|
|
@ -179,21 +266,24 @@ int main(int argc, char** argv) {
|
||||||
dat[3] = 'K';
|
dat[3] = 'K';
|
||||||
|
|
||||||
fwrite(dat, 1, 4, out);
|
fwrite(dat, 1, 4, out);
|
||||||
|
|
||||||
|
root = new_file(NULL, "");
|
||||||
|
root->dir = 1;
|
||||||
}
|
}
|
||||||
if(argc == 2) {
|
if(argc == 2) {
|
||||||
scan(".", "");
|
scan(root, ".", "");
|
||||||
} else if(argc > 2) {
|
} else if(argc > 2) {
|
||||||
int i;
|
int i;
|
||||||
|
|
||||||
for(i = 1; i < argc; i++) scan(argv[i], "");
|
for(i = 1; i < argc; i++) scan(root, argv[i], "");
|
||||||
} else {
|
} else {
|
||||||
printf("Usage: %s output [input]\n", argv[0]);
|
printf("Usage: %s output [input]\n", argv[0]);
|
||||||
|
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
memset(dat, 0, 128);
|
recursive(root);
|
||||||
fwrite(dat, 1, 128, out);
|
recursive_write(root);
|
||||||
|
|
||||||
printf("total %u files added, compressed %u -> %u bytes\n", total, totalact, totalcmp);
|
printf("total %u files added, compressed %u -> %u bytes\n", total, totalact, totalcmp);
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue