mirror of
https://github.com/EQEmu/Server.git
synced 2026-05-16 18:52:22 +00:00
Moved some around, more renames
This commit is contained in:
@@ -0,0 +1,19 @@
|
||||
CMAKE_MINIMUM_REQUIRED(VERSION 2.6)
|
||||
|
||||
PROJECT(PFSUtil)
|
||||
|
||||
IF(NOT CMAKE_BUILD_TYPE)
|
||||
SET(CMAKE_BUILD_TYPE "Debug")
|
||||
ENDIF(NOT CMAKE_BUILD_TYPE)
|
||||
|
||||
IF(WIN32)
|
||||
ADD_DEFINITIONS(/D _CRT_SECURE_NO_WARNINGS)
|
||||
ENDIF(WIN32)
|
||||
|
||||
SET(ZLIB_ROOT, "${CMAKE_CURRENT_SOURCE_DIR}/zlib")
|
||||
FIND_PACKAGE(ZLIB REQUIRED)
|
||||
INCLUDE_DIRECTORIES("${ZLIB_INCLUDE_DIRS}")
|
||||
|
||||
|
||||
ADD_SUBDIRECTORY(Common)
|
||||
ADD_SUBDIRECTORY(PFSList)
|
||||
@@ -0,0 +1,17 @@
|
||||
CMAKE_MINIMUM_REQUIRED(VERSION 2.6)
|
||||
|
||||
SET(common_sources
|
||||
Source/PFSArchive.cpp
|
||||
Source/Compression.cpp
|
||||
)
|
||||
|
||||
SET(common_headers
|
||||
Include/Archive.h
|
||||
Include/PFSArchive.h
|
||||
Include/PFSDataStructs.h
|
||||
Include/Compression.h
|
||||
)
|
||||
|
||||
INCLUDE_DIRECTORIES(Include)
|
||||
|
||||
ADD_LIBRARY(Common ${common_sources} ${common_headers})
|
||||
@@ -0,0 +1,20 @@
|
||||
#ifndef __AZONE_COMMON_ARCHIVE_H
|
||||
#define __AZONE_COMMON_ARCHIVE_H
|
||||
|
||||
#include <list>
|
||||
#include <string>
|
||||
#include <stdint.h>
|
||||
|
||||
class Archive {
|
||||
public:
|
||||
Archive() { }
|
||||
virtual ~Archive() { }
|
||||
|
||||
virtual bool Open(std::string filename) = 0;
|
||||
virtual bool Close() = 0;
|
||||
virtual bool Get(std::string filename, char** buffer, size_t& buffer_size) = 0;
|
||||
virtual bool Exists(std::string filename) = 0;
|
||||
virtual bool GetFiles(std::string ext, std::list<std::string>& files) = 0;
|
||||
};
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,9 @@
|
||||
#ifndef __AZONE_COMMON_COMPRESSION_H
|
||||
#define __AZONE_COMMON_COMPRESSION_H
|
||||
|
||||
#include <string>
|
||||
#include <zlib.h>
|
||||
|
||||
void decompress(const char* in, size_t in_len, char* out, size_t out_len);
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,35 @@
|
||||
#ifndef __AZONE_COMMON_PFSARCHIVE_H
|
||||
#define __AZONE_COMMON_PFSARCHIVE_H
|
||||
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <list>
|
||||
#include <vector>
|
||||
#ifdef WIN32
|
||||
#include <Winsock2.h>
|
||||
#else
|
||||
#include <arpa/inet.h>
|
||||
#endif
|
||||
#include "Archive.h"
|
||||
#include "PFSDataStructs.h"
|
||||
#include "Compression.h"
|
||||
|
||||
class PFSArchive : public Archive {
|
||||
public:
|
||||
PFSArchive();
|
||||
virtual ~PFSArchive();
|
||||
|
||||
virtual bool Open(std::string filename);
|
||||
virtual bool Close();
|
||||
virtual bool Get(std::string filename, char **buffer, size_t& buffer_size);
|
||||
virtual bool Exists(std::string filename);
|
||||
virtual bool GetFiles(std::string ext, std::list<std::string>& files);
|
||||
private:
|
||||
bool ReadIntoBuffer(std::string filename);
|
||||
std::vector<std::string> _filenames;
|
||||
std::vector<size_t> _files;
|
||||
char* _buffer;
|
||||
size_t _buffer_size;
|
||||
};
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,36 @@
|
||||
#ifndef __AZONE_COMMON_PFSDATASTRUCTS_H
|
||||
#define __AZONE_COMMON_PFSDATASTRUCTS_H
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
#pragma pack(1)
|
||||
|
||||
struct PFSHeader {
|
||||
uint32_t offset;
|
||||
char magic[4];
|
||||
uint32_t unknown;
|
||||
};
|
||||
|
||||
struct PFSDirectoryHeader {
|
||||
uint32_t count;
|
||||
};
|
||||
|
||||
struct PFSDirectory {
|
||||
uint32_t crc, offset, size;
|
||||
};
|
||||
|
||||
struct PFSDataBlock {
|
||||
uint32_t deflate_length, inflate_length;
|
||||
};
|
||||
|
||||
struct PFSFilenameHeader {
|
||||
uint32_t filename_count;
|
||||
};
|
||||
|
||||
struct PFSFilenameEntry {
|
||||
uint32_t filename_length;
|
||||
};
|
||||
|
||||
#pragma pack()
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,19 @@
|
||||
#include "Compression.h"
|
||||
|
||||
void decompress(const char* in, size_t in_len, char* out, size_t out_len) {
|
||||
int status;
|
||||
z_stream d_stream;
|
||||
|
||||
d_stream.zalloc = (alloc_func)0;
|
||||
d_stream.zfree = (free_func)0;
|
||||
d_stream.opaque = (voidpf)0;
|
||||
|
||||
d_stream.next_in = (Bytef*)in;
|
||||
d_stream.avail_in = in_len;
|
||||
d_stream.next_out = (Bytef*)out;
|
||||
d_stream.avail_out = out_len;
|
||||
|
||||
inflateInit(&d_stream);
|
||||
status = inflate(&d_stream, Z_NO_FLUSH);
|
||||
inflateEnd(&d_stream);
|
||||
}
|
||||
@@ -0,0 +1,220 @@
|
||||
#include "PFSArchive.h"
|
||||
|
||||
#define BufferRead(x, y) x = (y*)&_buffer[position]; position += sizeof(y);
|
||||
#define BufferReadLength(x, y) memcpy(x, &_buffer[position], y); position += y;
|
||||
#define MAX_FILENAME_SIZE 1024
|
||||
|
||||
PFSArchive::PFSArchive()
|
||||
:_buffer(NULL), _buffer_size(0)
|
||||
{
|
||||
}
|
||||
|
||||
PFSArchive::~PFSArchive() {
|
||||
Close();
|
||||
}
|
||||
|
||||
bool PFSArchive::Open(std::string filename)
|
||||
{
|
||||
if(!ReadIntoBuffer(filename)) {
|
||||
Close();
|
||||
return false;
|
||||
}
|
||||
|
||||
PFSHeader *header = NULL;
|
||||
PFSDirectoryHeader *directory_header = NULL;
|
||||
PFSDirectory *directory = NULL;
|
||||
PFSDataBlock *data_block = NULL;
|
||||
PFSFilenameHeader *filename_header = NULL;
|
||||
PFSFilenameEntry *filename_entry = NULL;
|
||||
size_t position = 0;
|
||||
|
||||
BufferRead(header, PFSHeader);
|
||||
|
||||
if(header->magic[0] != 'P' ||
|
||||
header->magic[1] != 'F' ||
|
||||
header->magic[2] != 'S' ||
|
||||
header->magic[3] != ' ')
|
||||
{
|
||||
Close();
|
||||
return false;
|
||||
}
|
||||
|
||||
position = header->offset;
|
||||
BufferRead(directory_header, PFSDirectoryHeader);
|
||||
|
||||
std::vector<uint32_t> offsets(directory_header->count, 0);
|
||||
_filenames.resize(directory_header->count);
|
||||
_files.resize(directory_header->count);
|
||||
|
||||
size_t i = 0;
|
||||
size_t j = 0;
|
||||
size_t running = 0;
|
||||
size_t temp_position = 0;
|
||||
size_t inflate = 0;
|
||||
char temp_buffer[32768];
|
||||
char temp_buffer2[32768];
|
||||
char temp_string[MAX_FILENAME_SIZE];
|
||||
for(; i < directory_header->count; ++i) {
|
||||
BufferRead(directory, PFSDirectory);
|
||||
if(directory->crc == ntohl(0xC90A5861)) {
|
||||
temp_position = position;
|
||||
position = directory->offset;
|
||||
memset(temp_buffer, 0, directory->size);
|
||||
inflate = 0;
|
||||
|
||||
while(inflate < directory->size) {
|
||||
BufferRead(data_block, PFSDataBlock);
|
||||
BufferReadLength(temp_buffer2, data_block->deflate_length);
|
||||
decompress(temp_buffer2, data_block->deflate_length, temp_buffer + inflate, data_block->inflate_length);
|
||||
inflate += data_block->inflate_length;
|
||||
}
|
||||
|
||||
position = temp_position;
|
||||
filename_header = (PFSFilenameHeader*)&temp_buffer[0];
|
||||
temp_position = sizeof(PFSFilenameHeader);
|
||||
|
||||
for(j = 0; j < filename_header->filename_count; ++j)
|
||||
{
|
||||
filename_entry = (PFSFilenameEntry*)&temp_buffer[temp_position];
|
||||
if(filename_entry->filename_length + 1 >= MAX_FILENAME_SIZE) {
|
||||
Close();
|
||||
return false;
|
||||
}
|
||||
temp_string[filename_entry->filename_length] = 0;
|
||||
memcpy(temp_string, &temp_buffer[temp_position + sizeof(PFSFilenameEntry)], filename_entry->filename_length);
|
||||
_filenames[j] = temp_string;
|
||||
temp_position += sizeof(PFSFilenameEntry) + filename_entry->filename_length;
|
||||
}
|
||||
} else {
|
||||
_files[running] = position - 12;
|
||||
offsets[running] = directory->offset;
|
||||
++running;
|
||||
}
|
||||
}
|
||||
|
||||
uint32_t temp = 0;
|
||||
for(i = directory_header->count - 2; i > 0; i--) {
|
||||
for(j = 0; j < i; j++) {
|
||||
if(offsets[j] > offsets[j + 1]) {
|
||||
temp = offsets[j];
|
||||
offsets[j] = offsets[j + 1];
|
||||
offsets[j + 1] = temp;
|
||||
temp = _files[j];
|
||||
_files[j] = _files[j + 1];
|
||||
_files[j + 1] = temp;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool PFSArchive::Close()
|
||||
{
|
||||
if(_buffer) {
|
||||
delete[] _buffer;
|
||||
_buffer = 0;
|
||||
_buffer_size = 0;
|
||||
_filenames.resize(0);
|
||||
_files.resize(0);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
//I would love to get rid of the allocations in the while loop below but sadly
|
||||
//I can't predict the size of data blocks well enough to be able to and feel
|
||||
//comfortable with it (I could however reduce the number of times I need to
|
||||
//reallocate with a little clever logic which i think I will do
|
||||
bool PFSArchive::Get(std::string filename, char **buffer, size_t& buffer_size) {
|
||||
size_t sz = _filenames.size();
|
||||
for(size_t index = 0; index < sz; ++index) {
|
||||
if(!_filenames[index].compare(filename)) {
|
||||
PFSDirectory* directory = NULL;
|
||||
PFSDataBlock* data_block = NULL;
|
||||
char *temp = NULL;
|
||||
|
||||
size_t position = _files[index];
|
||||
BufferRead(directory, PFSDirectory);
|
||||
position = directory->offset;
|
||||
|
||||
*buffer = new char[directory->size];
|
||||
buffer_size = directory->size;
|
||||
|
||||
size_t inflate = 0;
|
||||
while(inflate < directory->size) {
|
||||
BufferRead(data_block, PFSDataBlock);
|
||||
temp = new char[data_block->deflate_length];
|
||||
|
||||
memcpy(temp, &_buffer[position], data_block->deflate_length);
|
||||
position += data_block->deflate_length;
|
||||
|
||||
decompress(temp, data_block->deflate_length, *buffer + inflate, data_block->inflate_length);
|
||||
delete[] temp;
|
||||
inflate += data_block->inflate_length;
|
||||
}
|
||||
buffer_size = inflate;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
bool PFSArchive::Exists(std::string filename) {
|
||||
size_t count = _filenames.size();
|
||||
for(size_t i = 0; i < count; ++i) {
|
||||
if(!_filenames[i].compare(filename.c_str()))
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
bool PFSArchive::GetFiles(std::string ext, std::list<std::string>& files) {
|
||||
int elen = ext.length();
|
||||
bool all_files = !ext.compare("*");
|
||||
files.clear();
|
||||
|
||||
size_t count = _filenames.size();
|
||||
for(size_t i = 0; i < count; ++i) {
|
||||
int flen = _filenames[i].length();
|
||||
if(flen <= elen)
|
||||
continue;
|
||||
|
||||
if(!strcmp(_filenames[i].c_str() + (flen - elen), ext.c_str()) || all_files)
|
||||
files.push_back(_filenames[i]);
|
||||
}
|
||||
|
||||
return files.size() > 0;
|
||||
}
|
||||
|
||||
bool PFSArchive::ReadIntoBuffer(std::string filename) {
|
||||
FILE* f = fopen(filename.c_str(), "rb");
|
||||
if(!f) {
|
||||
return false;
|
||||
}
|
||||
|
||||
fseek(f, 0, SEEK_END);
|
||||
size_t total_size = ftell(f);
|
||||
rewind(f);
|
||||
|
||||
if(!total_size) {
|
||||
fclose(f);
|
||||
return false;
|
||||
}
|
||||
|
||||
if(_buffer) {
|
||||
delete[] _buffer;
|
||||
}
|
||||
|
||||
_buffer = new char[total_size];
|
||||
size_t bytes_read = fread(_buffer, 1, total_size, f);
|
||||
|
||||
if(bytes_read != total_size) {
|
||||
return false;
|
||||
}
|
||||
|
||||
_buffer_size = total_size;
|
||||
fclose(f);
|
||||
return true;
|
||||
}
|
||||
@@ -0,0 +1,23 @@
|
||||
CMAKE_MINIMUM_REQUIRED(VERSION 2.6)
|
||||
|
||||
SET(pfslist_sources
|
||||
Source/main.cpp
|
||||
)
|
||||
|
||||
SET(pfslist_headers
|
||||
)
|
||||
|
||||
INCLUDE_DIRECTORIES(Include
|
||||
../Common/Include
|
||||
)
|
||||
|
||||
ADD_EXECUTABLE(PFSList ${pfslist_sources} ${pfslist_headers})
|
||||
|
||||
TARGET_LINK_LIBRARIES(PFSList Common ${ZLIB_LIBRARY} "Ws2_32.lib")
|
||||
|
||||
IF(MSVC)
|
||||
ADD_DEFINITIONS(/D _CONSOLE)
|
||||
SET_TARGET_PROPERTIES(PFSList PROPERTIES LINK_FLAGS_RELEASE "/OPT:REF /OPT:ICF")
|
||||
ENDIF(MSVC)
|
||||
|
||||
SET(EXECUTABLE_OUTPUT_PATH ../Build/PFSList)
|
||||
@@ -0,0 +1,35 @@
|
||||
#include <stdio.h>
|
||||
#include <string>
|
||||
#include "PFSArchive.h"
|
||||
|
||||
int main(int argc, char **argv) {
|
||||
if(argc < 3) {
|
||||
printf("Usage: %s ext file1 [file2...]\n", argv[0]);
|
||||
return 1;
|
||||
}
|
||||
|
||||
for(int i = 2; i < argc; ++i) {
|
||||
PFSArchive archive;
|
||||
if(!archive.Open(argv[i])) {
|
||||
printf("Error: couldn't open %s\n", argv[i]);
|
||||
continue;
|
||||
}
|
||||
|
||||
std::list<std::string> files;
|
||||
if(!archive.GetFiles(argv[1], files)) {
|
||||
printf("Error: couldn't return the files with ext: %s\n", argv[1]);
|
||||
continue;
|
||||
}
|
||||
|
||||
printf("Files in %s:\n", argv[i]);
|
||||
std::list<std::string>::const_iterator iter = files.begin();
|
||||
while(iter != files.end()) {
|
||||
printf("%s\n", (*iter).c_str());
|
||||
iter++;
|
||||
}
|
||||
printf("\n");
|
||||
|
||||
archive.Close();
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
Reference in New Issue
Block a user