Experimental reader prototype
Need optimization in further version
This commit is contained in:
parent
e15934f881
commit
10ad8b7d72
@ -63,6 +63,10 @@ namespace RDI {
|
||||
RDI_EXTERN std::string getSectionName( unsigned char id );
|
||||
RDI_EXTERN unsigned int getSectionOffset( unsigned char id );
|
||||
|
||||
RDI_EXTERN unsigned int getDirectoryElementCount( std::string path );
|
||||
RDI_EXTERN std::vector<std::string> getDirectoryElements( std::string path );
|
||||
RDI_EXTERN bool isElementDirectory( std::string path );
|
||||
|
||||
/**
|
||||
* @brief Clean up global resources.
|
||||
*/
|
||||
|
@ -29,13 +29,14 @@ FileEntry::~FileEntry() {}
|
||||
DirectoryEntry::DirectoryEntry( std::string name ) {
|
||||
this->name = name;
|
||||
this->fFlags.raw = 0;
|
||||
this->fFlags.sectionRootDir = 1;
|
||||
this->rootDir = true;
|
||||
vSubFiles = new std::vector<DatEntry*>;
|
||||
}
|
||||
|
||||
DirectoryEntry::DirectoryEntry( std::string name, DAT_FILE_FLAGS fFlags ) {
|
||||
this->name = name;
|
||||
this->fFlags.raw = fFlags.raw;
|
||||
this->rootDir = false;
|
||||
vSubFiles = new std::vector<DatEntry*>;
|
||||
}
|
||||
|
||||
@ -46,7 +47,11 @@ DirectoryEntry::DirectoryEntry( std::string name, DAT_FILE_FLAGS fFlags, DatEntr
|
||||
AddEntry(hFileEntry);
|
||||
}
|
||||
|
||||
DirectoryEntry::~DirectoryEntry() {}
|
||||
DirectoryEntry::~DirectoryEntry() {
|
||||
for ( DatEntry* e : *vSubFiles )
|
||||
delete e;
|
||||
delete vSubFiles;
|
||||
}
|
||||
|
||||
/*std::string DirectoryEntry::toString() {
|
||||
|
||||
|
@ -20,12 +20,13 @@ namespace RDI {
|
||||
|
||||
typedef union u_file_flags {
|
||||
struct {
|
||||
// LSB
|
||||
unsigned short unknown0:1;
|
||||
unsigned short isFile:1;
|
||||
unsigned short unknown1:5;
|
||||
unsigned short isDirectory:1;
|
||||
unsigned short unknown2:7;
|
||||
unsigned short sectionRootDir:1;
|
||||
unsigned short unknown2:8;
|
||||
// MSB
|
||||
};
|
||||
unsigned short raw;
|
||||
} DAT_FILE_FLAGS;
|
||||
@ -36,14 +37,18 @@ class DatEntry {
|
||||
public:
|
||||
virtual ~DatEntry() = 0;
|
||||
virtual bool isDirectory() = 0;
|
||||
virtual bool isRootDirectory() = 0;
|
||||
//virtual std::string toString() = 0;
|
||||
virtual unsigned int getSize() = 0;
|
||||
|
||||
std::string getName() { return name; };
|
||||
|
||||
protected:
|
||||
std::string name;
|
||||
DAT_FILE_FLAGS fFlags;
|
||||
};
|
||||
|
||||
inline DatEntry::~DatEntry() {}
|
||||
|
||||
class FileEntry : public DatEntry {
|
||||
public:
|
||||
@ -54,6 +59,7 @@ public:
|
||||
|
||||
//std::string toString();
|
||||
bool isDirectory() { return false; }
|
||||
bool isRootDirectory() { return false; }
|
||||
unsigned int getSize() { return size; }
|
||||
|
||||
private:
|
||||
@ -71,12 +77,15 @@ public:
|
||||
|
||||
void ClearLinkedFiles();
|
||||
void AddEntry( DatEntry* hFileEntry );
|
||||
std::vector<DatEntry*> getFiles() { return *vSubFiles; }
|
||||
|
||||
//std::string toString();
|
||||
bool isDirectory() { return true; }
|
||||
bool isRootDirectory() { return rootDir; }
|
||||
unsigned int getSize() { return vSubFiles->size(); }
|
||||
|
||||
private:
|
||||
bool rootDir;
|
||||
std::vector<DatEntry*> *vSubFiles;
|
||||
};
|
||||
|
||||
|
44
src/RDI.cpp
44
src/RDI.cpp
@ -13,9 +13,11 @@
|
||||
|
||||
#include <iostream>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
#include <fstream>
|
||||
#include "config.h"
|
||||
#include "RDat.h"
|
||||
#include "DatEntry.h"
|
||||
#include "RDI.h"
|
||||
|
||||
|
||||
@ -36,6 +38,7 @@ void RDI::CreateRDatHandler( std::string roguePath ){
|
||||
//return hRDat;
|
||||
}
|
||||
|
||||
|
||||
unsigned char RDI::getSectionCount() {
|
||||
if (hRDat == nullptr) return 0;
|
||||
else return hRDat->getDataSectionCount();
|
||||
@ -51,6 +54,47 @@ unsigned int RDI::getSectionOffset( unsigned char id ) {
|
||||
else return hRDat->getDataSectionOffset(id);
|
||||
}
|
||||
|
||||
|
||||
unsigned int RDI::getDirectoryElementCount( std::string path ) {
|
||||
DirectoryEntry* result = nullptr;
|
||||
|
||||
if (path.empty()) return 0;
|
||||
|
||||
result = dynamic_cast<DirectoryEntry *>(hRDat->getElement(boost::filesystem::path(path)));
|
||||
|
||||
if (result == nullptr) return 0;
|
||||
else return result->getSize();
|
||||
}
|
||||
|
||||
std::vector<std::string> RDI::getDirectoryElements( std::string path ) {
|
||||
DirectoryEntry* de = nullptr;
|
||||
std::vector<std::string> elementsNameArray;
|
||||
elementsNameArray.clear();
|
||||
|
||||
if (!path.empty()) {
|
||||
de = dynamic_cast<DirectoryEntry *>(hRDat->getElement(boost::filesystem::path(path)));
|
||||
|
||||
if (de != nullptr && de->isDirectory()) {
|
||||
for (DatEntry* de2 : de->getFiles())
|
||||
elementsNameArray.push_back(de2->getName());
|
||||
}
|
||||
}
|
||||
|
||||
return elementsNameArray;
|
||||
}
|
||||
|
||||
bool RDI::isElementDirectory( std::string path ) {
|
||||
DatEntry* result = nullptr;
|
||||
|
||||
if (path.empty()) return false;
|
||||
|
||||
result = hRDat->getElement(boost::filesystem::path(path));
|
||||
|
||||
if (result == nullptr) return false;
|
||||
else return (result->isDirectory() || result->isRootDirectory());
|
||||
}
|
||||
|
||||
|
||||
void RDI::DestroyRDatHandler(){
|
||||
if (hRDat) delete hRDat;
|
||||
}
|
||||
|
69
src/RDat.cpp
69
src/RDat.cpp
@ -50,6 +50,9 @@ RDat::RDat( string fPath ) {
|
||||
}
|
||||
|
||||
RDat::~RDat() {
|
||||
for ( DirectoryEntry* de : *pFTRoot )
|
||||
delete de;
|
||||
delete pFTRoot;
|
||||
free(rDatPtr);
|
||||
delete pDatSection;
|
||||
}
|
||||
@ -129,15 +132,16 @@ RDI_RESULT RDat::ProcessFilesTree() {
|
||||
MEMFILE pFileDescriptors = nullptr;
|
||||
|
||||
// Create new root files tree. One per data section.
|
||||
pFTRoot = new std::vector<DirectoryEntry*>(cDatSection);
|
||||
pFTRoot = new std::vector<DirectoryEntry*>;
|
||||
pFTRoot->clear();
|
||||
for ( i = 0; i < cDatSection; i++ ) {
|
||||
curDir = new DirectoryEntry(pDatSection->at(i).name);
|
||||
pFTRoot->push_back(curDir);
|
||||
|
||||
// Recalculate files descriptor offset for current section.
|
||||
pFileDescriptors = rDatPtr + pDatSection->at(i).offset +
|
||||
((T_DAT_SECTION*)rDatPtr + pDatSection->at(i).offset)->file_headers_offset;
|
||||
curEntriesCount = (((T_DAT_SECTION*)rDatPtr + pDatSection->at(i).offset)->file_headers_size) / 32;
|
||||
((T_DAT_SECTION*)(rDatPtr + pDatSection->at(i).offset))->file_headers_offset;
|
||||
curEntriesCount = (((T_DAT_SECTION*)(rDatPtr + pDatSection->at(i).offset))->file_headers_size) / 32;
|
||||
|
||||
// Process arborescente in recursive method.
|
||||
ProcessDirectoryContents(curDir, pFileDescriptors, curEntriesCount, rDatPtr + pDatSection->at(i).offset);
|
||||
@ -157,22 +161,24 @@ RDI_RESULT RDat::ProcessDirectoryContents( DirectoryEntry* pCurDir, MEMFILE pDes
|
||||
if ( count == 0) return RDI_ERROR_PROCESS;
|
||||
|
||||
for ( i = 0; i < count; i++ ) {
|
||||
curEntryFlags.raw = ((T_FILE_HEADER*)pDesc)->flags;
|
||||
curEntryFlags.raw = ((T_FILE_HEADER*)(pDesc + i * sizeof(T_FILE_HEADER)))->flags;
|
||||
|
||||
tmpStr.clear();
|
||||
tmpStr.append(((T_FILE_HEADER*)pDesc)->name);
|
||||
tmpStr.append(((T_FILE_HEADER*)(pDesc + i * sizeof(T_FILE_HEADER)))->name);
|
||||
|
||||
// Test for file or directory
|
||||
if (!curEntryFlags.isDirectory) {
|
||||
newFile = new FileEntry(tmpStr, curEntryFlags, ((T_FILE_HEADER*)pDesc)->datas_size, pSectionStart + ((T_FILE_HEADER*)pDesc)->datas_offset);
|
||||
newFile = new FileEntry(tmpStr, curEntryFlags,
|
||||
((T_FILE_HEADER*)(pDesc + i * sizeof(T_FILE_HEADER)))->datas_size,
|
||||
pSectionStart + ((T_FILE_HEADER*)(pDesc + i * sizeof(T_FILE_HEADER)))->datas_offset);
|
||||
pCurDir->AddEntry(newFile);
|
||||
} else {
|
||||
newDir = new DirectoryEntry(tmpStr, curEntryFlags);
|
||||
pCurDir->AddEntry(newDir);
|
||||
|
||||
ProcessDirectoryContents(newDir,
|
||||
pDesc + i * sizeof(T_FILE_HEADER),
|
||||
(((T_FILE_HEADER*)pCurDir)->dir_entries_size - sizeof(T_FILE_HEADER)) / sizeof(T_FILE_HEADER),
|
||||
pDesc + (i + 1) * sizeof(T_FILE_HEADER),
|
||||
(((T_FILE_HEADER*)(pDesc + i * sizeof(T_FILE_HEADER)))->dir_entries_size - sizeof(T_FILE_HEADER)) / sizeof(T_FILE_HEADER),
|
||||
pSectionStart);
|
||||
}
|
||||
}
|
||||
@ -180,4 +186,51 @@ RDI_RESULT RDat::ProcessDirectoryContents( DirectoryEntry* pCurDir, MEMFILE pDes
|
||||
return RDI_OK;
|
||||
}
|
||||
|
||||
DatEntry *RDat::getElement( boost::filesystem::path virtualDirPath ) {
|
||||
bool skip = false;
|
||||
boost::filesystem::path newPath;
|
||||
|
||||
for ( DatEntry* de : *pFTRoot ) {
|
||||
if (virtualDirPath.size() == 1 || virtualDirPath.begin() == --virtualDirPath.end()) {
|
||||
if (de->getName() == virtualDirPath.filename().string())
|
||||
return de;
|
||||
} else {
|
||||
if (de->getName() == virtualDirPath.begin()->string()) {
|
||||
for (auto& sp : virtualDirPath) {
|
||||
if (skip)
|
||||
newPath.append(sp);
|
||||
skip = true;
|
||||
}
|
||||
return SearchSectionForEntry(dynamic_cast<DirectoryEntry *>(de), newPath);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
DatEntry *RDat::SearchSectionForEntry( DirectoryEntry *curDir, boost::filesystem::path virtualDirPath ) {
|
||||
bool skip = false;
|
||||
boost::filesystem::path newPath;
|
||||
|
||||
for ( DatEntry* e : curDir->getFiles() ) {
|
||||
if (virtualDirPath.size() == 1 || virtualDirPath.begin() == --virtualDirPath.end()) {
|
||||
if (e->getName() == virtualDirPath.filename().string())
|
||||
return e;
|
||||
} else {
|
||||
if (e->isDirectory() && (e->getName() == virtualDirPath.begin()->string())) {
|
||||
for (auto& sp : virtualDirPath) {
|
||||
if (skip)
|
||||
newPath.append(sp);
|
||||
skip = true;
|
||||
}
|
||||
//TODO: add safety when trying to access inside a file
|
||||
return SearchSectionForEntry(dynamic_cast<DirectoryEntry *>(e), newPath);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -39,6 +39,8 @@ public:
|
||||
std::string getDataSectionName( unsigned char id );
|
||||
unsigned int getDataSectionOffset( unsigned char id );
|
||||
|
||||
DatEntry *getElement( boost::filesystem::path virtualDirPath );
|
||||
|
||||
private:
|
||||
std::string workingDir = ".";
|
||||
|
||||
@ -59,6 +61,9 @@ private:
|
||||
MEMFILE pSectionStart
|
||||
);
|
||||
|
||||
/* Tree manipulation/parse methods */
|
||||
DatEntry *SearchSectionForEntry( DirectoryEntry *curDir, boost::filesystem::path virtualDirPath);
|
||||
|
||||
};
|
||||
|
||||
} /* namespace RDI */
|
||||
|
@ -8,11 +8,17 @@
|
||||
*/
|
||||
|
||||
#include <iostream>
|
||||
#include <string>
|
||||
#include <boost/filesystem.hpp>
|
||||
#include <RDI.h>
|
||||
|
||||
|
||||
void PrintVirtualDirectoryContents( boost::filesystem::path, std::string );
|
||||
|
||||
int main( int argc, char *argv[] ) {
|
||||
unsigned int i;
|
||||
boost::filesystem::path pathBuilder;
|
||||
std::string prefix;
|
||||
|
||||
printf("Using RDI lib v%s\n\n", RDI::getLibVersion().c_str());
|
||||
//cout << "Using RDI lib v" << RDI::getLibVersion() << endl << endl;
|
||||
@ -28,7 +34,42 @@ int main( int argc, char *argv[] ) {
|
||||
printf(" -Section %d offset: 0x%X\n", i, RDI::getSectionOffset(i));
|
||||
}
|
||||
|
||||
//prefix.append("\t");
|
||||
prefix.append(" ");
|
||||
printf("\nSections files root:\n");
|
||||
for ( i = 0; i < RDI::getSectionCount(); i++ ) {
|
||||
printf("%s:\n", RDI::getSectionName(i).c_str()); // Print root trees
|
||||
|
||||
pathBuilder.clear();
|
||||
pathBuilder.concat(RDI::getSectionName(i));
|
||||
|
||||
PrintVirtualDirectoryContents(pathBuilder, prefix);
|
||||
}
|
||||
|
||||
RDI::DestroyRDatHandler();
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
void PrintVirtualDirectoryContents( boost::filesystem::path path, std::string outPrefix ) {
|
||||
auto curDirElementsName = RDI::getDirectoryElements(path.string());
|
||||
auto newPath = boost::filesystem::path(path);
|
||||
auto newOutPrefix = std::string(outPrefix);
|
||||
|
||||
for ( std::string eName : curDirElementsName ) {
|
||||
newPath.clear();
|
||||
newPath.concat(path);
|
||||
newOutPrefix.clear();
|
||||
newOutPrefix.append(outPrefix);
|
||||
|
||||
newPath.append(eName);
|
||||
if (RDI::isElementDirectory(newPath.string())) {
|
||||
printf("%s%s:\n", outPrefix.c_str(), eName.c_str());
|
||||
//newOutPrefix.append("\t");
|
||||
newOutPrefix.append(" ");
|
||||
PrintVirtualDirectoryContents(newPath, newOutPrefix);
|
||||
} else {
|
||||
printf("%s%s\n", newOutPrefix.c_str(), eName.c_str());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user