The .fpk file use PRS compress method(a little change). This is the fpk tool:
Code:
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include <fcntl.h>
#include <sys/stat.h>
#include <dirent.h>
typedef unsigned int u32;
typedef unsigned short u16;
typedef unsigned char u8;
int endian=1;
u32 BE32(u32 data)
{
if(endian)
return ( (data<<24) | ((data<<8)&0x00ff0000) |
((data>>8)&0x0000ff00) | (data>>24) );
else
return data;
}
int blen;
int fbuf;
/* PRS get bit form lsb to msb, FPK get it form msb to lsb */
int get_bits(int n, char *sbuf, int *sptr)
{
int retv;
retv = 0;
while(n){
retv <<= 1;
if(blen==0){
fbuf = sbuf[*sptr];
//if(*sptr<256)
//{ printf("[%02x] ", fbuf&0xff); fflush(0); }
(*sptr)++;
blen = 8;
}
if(fbuf&0x80)
retv |= 1;
fbuf <<= 1;
blen --;
n --;
}
return retv;
}
int uncomp(char *dbuf, int dlen, char *sbuf, int slen)
{
int sptr;
int dptr;
int i, flag, len, pos;
blen = 0;
sptr = 0;
dptr = 0;
while(sptr<slen){
flag = get_bits(1, sbuf, &sptr);
if(flag==1){
//if(sptr<256)
//{ printf("%02x ", (u8)sbuf[sptr]); fflush(0); }
if(dptr<dlen)
dbuf[dptr++] = sbuf[sptr++];
}else{
flag = get_bits(1, sbuf, &sptr);
if(flag==0){
len = get_bits(2, sbuf, &sptr)+2;
pos = sbuf[sptr++]|0xffffff00;
}else{
pos = (sbuf[sptr++]<<8)|0xffff0000;
pos |= sbuf[sptr++]&0xff;
len = pos&0x07;
pos >>= 3;
if(len==0){
len = (sbuf[sptr++]&0xff)+1;
}else{
len += 2;
}
}
//if(sptr<256)
//{ printf("<%08x(%08x): %08x %d> \n", dptr, dlen, pos, len); fflush(0); }
pos += dptr;
for(i=0; i<len; i++){
if(dptr<dlen)
dbuf[dptr++] = dbuf[pos++];
}
}
}
return dptr;
}
void mkdir_p(char *dname)
{
char name[256];
char *p, *cp;
strcpy(name, dname);
cp = name;
while(1){
p = strchr(cp, '/');
if(p==NULL)
p = strchr(cp, '\\');
if(p==NULL)
break;
*p = 0;
//mkdir(name, 0777);
mkdir(name);
*p = '/';
cp = p+1;
};
}
int process_file(char *infname)
{
FILE *fp, *outfp;
char *fname, *dptr, *buf, *dbuf;
int i, fcnt, flen, dlen, offset;
char dname[256], tname[256], *p;
p = strchr(infname, '.');
if(p==NULL)
return -1;
if(strcmp(p+1, "fpk"))
return -1;
printf("process file %s ...\n", infname);
/* Open fpk file */
fp = fopen(infname, "rb");
if(fp==NULL){
printf("Can't open %s!\n", infname);
return -1;
}
/* Make directory */
strcpy(dname, infname);
p = strchr(dname, '.');
if(p)
*p = '_';
//mkdir(dname, 0777);
mkdir(dname);
fseek(fp, 0, SEEK_END);
flen = ftell(fp);
fseek(fp, 0, SEEK_SET);
buf = (char*)malloc(flen);
fread(buf, flen, 1, fp);
fclose(fp);
if(*(short*)(buf+0)==0){
endian = 1;
}else{
endian = 0;
}
fcnt = BE32(*(int*)(buf+4));
for(i=0; i<fcnt; i++){
dptr = buf+0x10+i*0x30;
fname = dptr;
flen = BE32(*(int*)(dptr+0x28));
offset = BE32(*(int*)(dptr+0x24));
dlen = BE32(*(int*)(dptr+0x2c));
printf("offset: %08x flen: %08x length: %08x file: %s\n", offset, flen, dlen, fname);
dbuf = malloc(dlen+256);
uncomp(dbuf, dlen, buf+offset, flen);
sprintf(tname, "%s/%s", dname, fname);
mkdir_p(tname);
outfp = fopen(tname, "wb");
if(outfp==NULL){
printf("Can't open output file %s !\n", tname);
}else{
fwrite(dbuf, dlen, 1, outfp);
fclose(outfp);
}
free(dbuf);
}
free(buf);
return 0;
}
////////////////////////////////////////////////////////////////////////////
int process_dir(char *dname)
{
DIR *pdir;
struct dirent *d;
struct stat statbuf;
char fname[256];
int i, ndir;
/* process file */
memset(&statbuf, 0, sizeof(statbuf));
stat(dname, &statbuf);
if((statbuf.st_mode&S_IFMT) != S_IFDIR){
return process_file(dname);
}
/* open directory */
pdir = opendir(dname);
if(pdir==NULL){
printf("Can't open directory <%s>\n", dname);
return -1;
}
/* get number of files in dircetory */
ndir = 0;
while((d=readdir(pdir))){
ndir++;
}
d = malloc(sizeof(struct dirent)*ndir);
/* read dirent first */
rewinddir(pdir);
for(i=0; i<ndir; i++){
memcpy(&d[i], readdir(pdir), sizeof(struct dirent));
}
/* process each files */
printf("Enter directory <%s> ...\n", dname);
for(i=0; i<ndir; i++){
if( d[i].d_name[0]=='.' &&( d[i].d_name[1] =='\0' || (d[i].d_name[1] == '.' && d[i].d_name[2] == '\0') ))
continue;
if(dname[0]=='.'){
sprintf(fname, "%s", d[i].d_name);
}else{
sprintf(fname, "%s/%s", dname, d[i].d_name);
}
process_dir(fname);
}
printf("Leave directory <%s> ...\n", dname);
free(d);
closedir(pdir);
return 0;
}
int main(int argc, char *argv[])
{
if(argc==1){
return process_dir(".");
}else{
return process_dir(argv[1]);
}
}