Experimental reader prototype

Need optimization in further version
This commit is contained in:
JackCarterSmith 2022-09-21 21:13:00 +02:00
parent e15934f881
commit 10ad8b7d72
Signed by: JackCarterSmith
GPG Key ID: 832E52F4E23F8F24
7 changed files with 173 additions and 12 deletions

View File

@ -63,6 +63,10 @@ namespace RDI {
RDI_EXTERN std::string getSectionName( unsigned char id ); RDI_EXTERN std::string getSectionName( unsigned char id );
RDI_EXTERN unsigned int getSectionOffset( 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. * @brief Clean up global resources.
*/ */

View File

@ -29,13 +29,14 @@ FileEntry::~FileEntry() {}
DirectoryEntry::DirectoryEntry( std::string name ) { DirectoryEntry::DirectoryEntry( std::string name ) {
this->name = name; this->name = name;
this->fFlags.raw = 0; this->fFlags.raw = 0;
this->fFlags.sectionRootDir = 1; this->rootDir = true;
vSubFiles = new std::vector<DatEntry*>; vSubFiles = new std::vector<DatEntry*>;
} }
DirectoryEntry::DirectoryEntry( std::string name, DAT_FILE_FLAGS fFlags ) { DirectoryEntry::DirectoryEntry( std::string name, DAT_FILE_FLAGS fFlags ) {
this->name = name; this->name = name;
this->fFlags.raw = fFlags.raw; this->fFlags.raw = fFlags.raw;
this->rootDir = false;
vSubFiles = new std::vector<DatEntry*>; vSubFiles = new std::vector<DatEntry*>;
} }
@ -46,7 +47,11 @@ DirectoryEntry::DirectoryEntry( std::string name, DAT_FILE_FLAGS fFlags, DatEntr
AddEntry(hFileEntry); AddEntry(hFileEntry);
} }
DirectoryEntry::~DirectoryEntry() {} DirectoryEntry::~DirectoryEntry() {
for ( DatEntry* e : *vSubFiles )
delete e;
delete vSubFiles;
}
/*std::string DirectoryEntry::toString() { /*std::string DirectoryEntry::toString() {

View File

@ -20,12 +20,13 @@ namespace RDI {
typedef union u_file_flags { typedef union u_file_flags {
struct { struct {
// LSB
unsigned short unknown0:1; unsigned short unknown0:1;
unsigned short isFile:1; unsigned short isFile:1;
unsigned short unknown1:5; unsigned short unknown1:5;
unsigned short isDirectory:1; unsigned short isDirectory:1;
unsigned short unknown2:7; unsigned short unknown2:8;
unsigned short sectionRootDir:1; // MSB
}; };
unsigned short raw; unsigned short raw;
} DAT_FILE_FLAGS; } DAT_FILE_FLAGS;
@ -36,14 +37,18 @@ class DatEntry {
public: public:
virtual ~DatEntry() = 0; virtual ~DatEntry() = 0;
virtual bool isDirectory() = 0; virtual bool isDirectory() = 0;
virtual bool isRootDirectory() = 0;
//virtual std::string toString() = 0; //virtual std::string toString() = 0;
virtual unsigned int getSize() = 0; virtual unsigned int getSize() = 0;
std::string getName() { return name; };
protected: protected:
std::string name; std::string name;
DAT_FILE_FLAGS fFlags; DAT_FILE_FLAGS fFlags;
}; };
inline DatEntry::~DatEntry() {}
class FileEntry : public DatEntry { class FileEntry : public DatEntry {
public: public:
@ -54,6 +59,7 @@ public:
//std::string toString(); //std::string toString();
bool isDirectory() { return false; } bool isDirectory() { return false; }
bool isRootDirectory() { return false; }
unsigned int getSize() { return size; } unsigned int getSize() { return size; }
private: private:
@ -71,12 +77,15 @@ public:
void ClearLinkedFiles(); void ClearLinkedFiles();
void AddEntry( DatEntry* hFileEntry ); void AddEntry( DatEntry* hFileEntry );
std::vector<DatEntry*> getFiles() { return *vSubFiles; }
//std::string toString(); //std::string toString();
bool isDirectory() { return true; } bool isDirectory() { return true; }
bool isRootDirectory() { return rootDir; }
unsigned int getSize() { return vSubFiles->size(); } unsigned int getSize() { return vSubFiles->size(); }
private: private:
bool rootDir;
std::vector<DatEntry*> *vSubFiles; std::vector<DatEntry*> *vSubFiles;
}; };

View File

@ -13,9 +13,11 @@
#include <iostream> #include <iostream>
#include <string> #include <string>
#include <vector>
#include <fstream> #include <fstream>
#include "config.h" #include "config.h"
#include "RDat.h" #include "RDat.h"
#include "DatEntry.h"
#include "RDI.h" #include "RDI.h"
@ -36,6 +38,7 @@ void RDI::CreateRDatHandler( std::string roguePath ){
//return hRDat; //return hRDat;
} }
unsigned char RDI::getSectionCount() { unsigned char RDI::getSectionCount() {
if (hRDat == nullptr) return 0; if (hRDat == nullptr) return 0;
else return hRDat->getDataSectionCount(); else return hRDat->getDataSectionCount();
@ -51,6 +54,47 @@ unsigned int RDI::getSectionOffset( unsigned char id ) {
else return hRDat->getDataSectionOffset(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(){ void RDI::DestroyRDatHandler(){
if (hRDat) delete hRDat; if (hRDat) delete hRDat;
} }

View File

@ -50,6 +50,9 @@ RDat::RDat( string fPath ) {
} }
RDat::~RDat() { RDat::~RDat() {
for ( DirectoryEntry* de : *pFTRoot )
delete de;
delete pFTRoot;
free(rDatPtr); free(rDatPtr);
delete pDatSection; delete pDatSection;
} }
@ -129,15 +132,16 @@ RDI_RESULT RDat::ProcessFilesTree() {
MEMFILE pFileDescriptors = nullptr; MEMFILE pFileDescriptors = nullptr;
// Create new root files tree. One per data section. // 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++ ) { for ( i = 0; i < cDatSection; i++ ) {
curDir = new DirectoryEntry(pDatSection->at(i).name); curDir = new DirectoryEntry(pDatSection->at(i).name);
pFTRoot->push_back(curDir); pFTRoot->push_back(curDir);
// Recalculate files descriptor offset for current section. // Recalculate files descriptor offset for current section.
pFileDescriptors = rDatPtr + pDatSection->at(i).offset + pFileDescriptors = rDatPtr + pDatSection->at(i).offset +
((T_DAT_SECTION*)rDatPtr + pDatSection->at(i).offset)->file_headers_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; curEntriesCount = (((T_DAT_SECTION*)(rDatPtr + pDatSection->at(i).offset))->file_headers_size) / 32;
// Process arborescente in recursive method. // Process arborescente in recursive method.
ProcessDirectoryContents(curDir, pFileDescriptors, curEntriesCount, rDatPtr + pDatSection->at(i).offset); 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; if ( count == 0) return RDI_ERROR_PROCESS;
for ( i = 0; i < count; i++ ) { 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.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 // Test for file or directory
if (!curEntryFlags.isDirectory) { 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); pCurDir->AddEntry(newFile);
} else { } else {
newDir = new DirectoryEntry(tmpStr, curEntryFlags); newDir = new DirectoryEntry(tmpStr, curEntryFlags);
pCurDir->AddEntry(newDir); pCurDir->AddEntry(newDir);
ProcessDirectoryContents(newDir, ProcessDirectoryContents(newDir,
pDesc + i * sizeof(T_FILE_HEADER), pDesc + (i + 1) * sizeof(T_FILE_HEADER),
(((T_FILE_HEADER*)pCurDir)->dir_entries_size - sizeof(T_FILE_HEADER)) / 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); pSectionStart);
} }
} }
@ -180,4 +186,51 @@ RDI_RESULT RDat::ProcessDirectoryContents( DirectoryEntry* pCurDir, MEMFILE pDes
return RDI_OK; 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;
}
} }

View File

@ -39,6 +39,8 @@ public:
std::string getDataSectionName( unsigned char id ); std::string getDataSectionName( unsigned char id );
unsigned int getDataSectionOffset( unsigned char id ); unsigned int getDataSectionOffset( unsigned char id );
DatEntry *getElement( boost::filesystem::path virtualDirPath );
private: private:
std::string workingDir = "."; std::string workingDir = ".";
@ -59,6 +61,9 @@ private:
MEMFILE pSectionStart MEMFILE pSectionStart
); );
/* Tree manipulation/parse methods */
DatEntry *SearchSectionForEntry( DirectoryEntry *curDir, boost::filesystem::path virtualDirPath);
}; };
} /* namespace RDI */ } /* namespace RDI */

View File

@ -8,11 +8,17 @@
*/ */
#include <iostream> #include <iostream>
#include <string>
#include <boost/filesystem.hpp>
#include <RDI.h> #include <RDI.h>
void PrintVirtualDirectoryContents( boost::filesystem::path, std::string );
int main( int argc, char *argv[] ) { int main( int argc, char *argv[] ) {
unsigned int i; unsigned int i;
boost::filesystem::path pathBuilder;
std::string prefix;
printf("Using RDI lib v%s\n\n", RDI::getLibVersion().c_str()); printf("Using RDI lib v%s\n\n", RDI::getLibVersion().c_str());
//cout << "Using RDI lib v" << RDI::getLibVersion() << endl << endl; //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)); 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(); RDI::DestroyRDatHandler();
return 0; 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());
}
}
}