Reforge library structure - 3rd pass

Updated CMakeFile with MSVC options

Review Erso lib interface

Better tree display in RDIDebug tool


Change lib interface functions naming


Separate namespace for date file entries
This commit is contained in:
JackCarterSmith 2023-01-12 20:23:45 +01:00
parent 26629d56bc
commit 2da49b53ae
Signed by: JackCarterSmith
GPG Key ID: 832E52F4E23F8F24
15 changed files with 506 additions and 330 deletions

View File

@ -25,8 +25,13 @@ else() # Standalone project mode, should not be used for release.
endif() endif()
#set(RDI_LIB_NAME RDI${PROJECT_VERSION_MAJOR}${PROJECT_VERSION_MINOR}) #set(RDI_LIB_NAME RDI${PROJECT_VERSION_MAJOR}${PROJECT_VERSION_MINOR})
set(RDI_LIB_NAME RDI) set(RDI_LIB_NAME RDI)
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -Wall") if(NOT MSVC)
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wall") set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -Wall")
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wall -std=c++17 -static-libgcc -static-libstdc++")
else()
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} /Wall")
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} /Wall /std:c++17")
endif()
set(INSTALL_BIN_DIR "${CMAKE_INSTALL_PREFIX}/bin" CACHE PATH "Installation directory for executables") set(INSTALL_BIN_DIR "${CMAKE_INSTALL_PREFIX}/bin" CACHE PATH "Installation directory for executables")
set(INSTALL_LIB_DIR "${CMAKE_INSTALL_PREFIX}/lib" CACHE PATH "Installation directory for libraries") set(INSTALL_LIB_DIR "${CMAKE_INSTALL_PREFIX}/lib" CACHE PATH "Installation directory for libraries")
@ -176,11 +181,11 @@ if(BUILD_TOOLS)
endif() endif()
if(RDI_SHARED) if(RDI_SHARED)
target_link_libraries(rdi-debug-tools PRIVATE rdi-lib) target_link_libraries(rdi-debug-tools PRIVATE rdi-lib ${Boost_LIBRARIES})
target_link_libraries(erso-debug-tools PRIVATE rdi-lib) target_link_libraries(erso-debug-tools PRIVATE rdi-lib)
target_link_libraries(krennic-debug-tools PRIVATE rdi-lib) target_link_libraries(krennic-debug-tools PRIVATE rdi-lib)
elseif(RDI_STATIC) elseif(RDI_STATIC)
target_link_libraries(rdi-debug-tools PRIVATE rdi-libstatic) target_link_libraries(rdi-debug-tools PRIVATE rdi-libstatic ${Boost_LIBRARIES})
target_link_libraries(erso-debug-tools PRIVATE rdi-libstatic) target_link_libraries(erso-debug-tools PRIVATE rdi-libstatic)
target_link_libraries(krennic-debug-tools PRIVATE rdi-libstatic) target_link_libraries(krennic-debug-tools PRIVATE rdi-libstatic)
endif() endif()

View File

@ -16,11 +16,13 @@
namespace RDI { namespace RDI {
class ErsoEntryFile; namespace DatFile {
class DatFileEntryFile;
}
class GenericFile { class GenericFile {
public: public:
GenericFile( ErsoEntryFile& hDat ); GenericFile( DatFile::DatFileEntryFile &hDat );
virtual ~GenericFile(); virtual ~GenericFile();
MEMFILE get() { return pMemLoc; } MEMFILE get() { return pMemLoc; }

View File

@ -17,7 +17,7 @@ namespace RDI {
class HMT : public GenericFile { class HMT : public GenericFile {
public: public:
HMT( ErsoEntryFile& hDat ); HMT( DatFile::DatFileEntryFile &hDat );
virtual ~HMT(); virtual ~HMT();
}; };

View File

@ -48,7 +48,7 @@ namespace RDI {
* @brief Get the current library version. * @brief Get the current library version.
* @return String of the version. * @return String of the version.
*/ */
RDI_EXTERN std::string getLibVersion( void ); RDI_EXTERN std::string RDI_getLibVersion( void );
/** /**
* @brief Allocate memory and create default structure to access datas. * @brief Allocate memory and create default structure to access datas.
@ -56,26 +56,26 @@ namespace RDI {
* If file can be opened, it's mapped in memory and process files list. * If file can be opened, it's mapped in memory and process files list.
* @param[in] roguePath Path to DATA.DAT and DATA.HDR location. * @param[in] roguePath Path to DATA.DAT and DATA.HDR location.
*/ */
RDI_EXTERN void Init( std::string roguePath ); RDI_EXTERN void RDI_Init( std::string roguePath );
/* Erso specific methods */ /* Erso specific methods */
RDI_EXTERN unsigned char getSectionCount( void ); RDI_EXTERN unsigned char RDI_getSectionCount( void );
RDI_EXTERN std::string getSectionName( unsigned char id ); RDI_EXTERN std::string RDI_getSectionName( unsigned char id );
RDI_EXTERN unsigned int getSectionOffset( unsigned char id ); RDI_EXTERN unsigned int RDI_getSectionOffset( unsigned char id );
RDI_EXTERN unsigned int getDirectoryElementCount( std::string path ); RDI_EXTERN unsigned int RDI_getDirectoryElementCount( std::string path );
RDI_EXTERN std::vector<std::string> getDirectoryElements( std::string path ); RDI_EXTERN std::vector<std::string> RDI_getDirectoryElements( std::string path );
RDI_EXTERN bool isElementDirectory( std::string path ); RDI_EXTERN bool RDI_isElementDirectory( std::string path );
/* Krennic specific methods */ /* Krennic specific methods */
RDI_EXTERN std::vector<std::string> getLevelsName( void ); RDI_EXTERN std::vector<std::string> RDI_getLevelsName( void );
RDI_EXTERN std::vector<std::string> getModelsName( void ); RDI_EXTERN std::vector<std::string> RDI_getModelsName( void );
RDI_EXTERN std::vector<std::string> getMusicsName( void ); RDI_EXTERN std::vector<std::string> RDI_getMusicsName( void );
/** /**
* @brief Clean up global resources. * @brief Clean up global resources.
*/ */
RDI_EXTERN void CleanUp( void ); RDI_EXTERN void RDI_CleanUp( void );
} }
#endif /* RDI_HPP_ */ #endif /* RDI_HPP_ */

72
src/DatFileEntry.cpp Normal file
View File

@ -0,0 +1,72 @@
/**
* @file DatFileEntry.cpp
* @date 12/01/2023
* @author JackCarterSmith
* @copyright GPL-v3.0
* @brief Data file entry descriptor objects helper class.
*
*/
#include <RDI_Datatypes.h>
#include <vector>
#include <string>
#include "DatFileEntry.hpp"
using std::string;
using std::vector;
namespace RDI {
namespace DatFile {
DatFileEntryFile::DatFileEntryFile( string name, DAT_FILE_FLAGS fFlags, unsigned int size, MEMFILE fPtr ) {
this->name = name;
this->size = size;
this->fFlags.raw = fFlags.raw;
this->fileMemPtr = fPtr;
}
DatFileEntryFile::~DatFileEntryFile() {}
DatFileEntryDirectory::DatFileEntryDirectory( string name ) {
this->name = name;
this->fFlags.raw = 0;
this->rootDir = true;
vSubFiles = new vector<DatFileEntry*>;
}
DatFileEntryDirectory::DatFileEntryDirectory( string name, DAT_FILE_FLAGS fFlags ) {
this->name = name;
this->fFlags.raw = fFlags.raw;
this->rootDir = false;
vSubFiles = new vector<DatFileEntry*>;
}
DatFileEntryDirectory::DatFileEntryDirectory( string name, DAT_FILE_FLAGS fFlags, DatFileEntry* hFileEntry ) {
this->name = name;
this->fFlags.raw = fFlags.raw;
vSubFiles = new vector<DatFileEntry*>;
AddEntry(hFileEntry);
}
DatFileEntryDirectory::~DatFileEntryDirectory() {
for ( DatFileEntry* e : *vSubFiles )
delete e;
delete vSubFiles;
}
/*std::string DirectoryEntry::toString() {
}*/
void DatFileEntryDirectory::ClearLinkedFiles() {
vSubFiles->clear();
}
void DatFileEntryDirectory::AddEntry( DatFileEntry* hFileEntry ) {
vSubFiles->push_back(hFileEntry);
}
}
}

101
src/DatFileEntry.hpp Normal file
View File

@ -0,0 +1,101 @@
/**
* @file DatFileEntry.hpp
* @date 12/01/2023
* @author JackCarterSmith
* @copyright GPL-v3.0
* @brief Data file entry descriptor objects helper class.
*
* DATA and BUNDLE file store in different location file's header and
* file's data. This helper class it's used to provide a more convenient
* access to the corresponding file inside memory (after Erso module's
* initialization).
*
*/
#include <RDI_Datatypes.h>
#include <vector>
#include <string>
#ifndef ERSOENTRY_HPP_
#define ERSOENTRY_HPP_
namespace RDI {
namespace DatFile {
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:8;
// MSB
};
unsigned short raw;
} DAT_FILE_FLAGS;
class DatFileEntry {
public:
virtual ~DatFileEntry() = 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 DatFileEntry::~DatFileEntry() {}
class DatFileEntryFile : public DatFileEntry {
public:
DatFileEntryFile( std::string name, DAT_FILE_FLAGS fFlags, unsigned int size, MEMFILE fPtr );
~DatFileEntryFile();
MEMFILE getDatas() { return fileMemPtr; }
//std::string toString();
bool isDirectory() { return false; }
bool isRootDirectory() { return false; }
unsigned int getSize() { return size; } // In bytes
private:
MEMFILE fileMemPtr;
unsigned int size;
};
class DatFileEntryDirectory : public DatFileEntry {
public:
DatFileEntryDirectory( std::string name );
DatFileEntryDirectory( std::string name, DAT_FILE_FLAGS fFlags );
DatFileEntryDirectory( std::string name, DAT_FILE_FLAGS fFlags, DatFileEntry* hFileEntry );
~DatFileEntryDirectory();
void ClearLinkedFiles();
void AddEntry( DatFileEntry* hFileEntry );
std::vector<DatFileEntry*> getFiles() { return *vSubFiles; }
//std::string toString();
bool isDirectory() { return true; }
bool isRootDirectory() { return rootDir; }
unsigned int getSize() { return vSubFiles->size(); } // In number of elements
private:
bool rootDir;
std::vector<DatFileEntry*> *vSubFiles;
};
}
}
#endif /* ERSOENTRY_HPP_ */

View File

@ -1,6 +1,6 @@
/** /**
* @file Erso.cpp * @file Erso.cpp
* @date 24/09/2022 * @date 11/01/2023
* @author JackCarterSmith * @author JackCarterSmith
* @copyright GPL-v3.0 * @copyright GPL-v3.0
* @brief Rogue DATA/BUNDLE file parser and interface. * @brief Rogue DATA/BUNDLE file parser and interface.
@ -14,9 +14,8 @@
#include <boost/filesystem.hpp> #include <boost/filesystem.hpp>
#include <RDI_Datatypes.h> #include <RDI_Datatypes.h>
#include "files_mms/data_struct.h" #include "files_mms/data_struct.h"
#include "DatFileEntry.hpp"
#include "Erso.hpp" #include "Erso.hpp"
#include "ErsoEntry.hpp"
using std::string; using std::string;
using std::ios; using std::ios;
@ -24,45 +23,78 @@ using std::vector;
using boost::filesystem::path; using boost::filesystem::path;
using boost::filesystem::file_size; using boost::filesystem::file_size;
using namespace RDI::DatFile;
namespace RDI { namespace RDI {
Erso::Erso( string fPath ) { Erso::Erso( string fPath ) : workingDir(fPath)
{
Process();
}
Erso::Erso( string fPath, RDI_RESULT* outResult ) :
workingDir(fPath)
{
if (outResult) *outResult = Process();
else Process();
}
Erso::~Erso()
{
DisposeFile();
}
string Erso::getDataSectionName( unsigned char id ) const { return pDatSection->at(id).name; }
unsigned int Erso::getDataSectionOffset( unsigned char id ) const { return pDatSection->at(id).offset; }
/**
* Change the current working directory.
* This action will reconstruct files tree, all previous file entries became invalid.
*
* @param newPath New working directory path
*
* @return Error status.
*/
RDI_RESULT Erso::setWorkingDirectory( std::string newPath ) {
RDI_RESULT errCode = RDI_OK; RDI_RESULT errCode = RDI_OK;
this->workingDir = fPath; DisposeFile();
this->workingDir = newPath;
Process();
return errCode;
}
/* ------------------------------------------------------------------------------------------------------------- */
RDI_RESULT Erso::Process() {
RDI_RESULT errCode = RDI_OK;
// Process header file and dump data file in memory. // Process header file and dump data file in memory.
errCode = DumpLegacyFiles(); errCode = DataFilesDumping();
if (errCode == RDI_ERROR_FILESYSTEM) { if (errCode == RDI_ERROR_FILESYSTEM) {
std::cout << "Data files (DATA.DAT/DATA.HDR) not found! Interrupt." << std::endl; std::cout << "Data files (DATA.DAT/DATA.HDR) not found! Interrupt." << std::endl;
return; return errCode;
} else if (errCode == RDI_ERROR_MEMORY) { } else if (errCode == RDI_ERROR_MEMORY) {
std::cout << "Memory allocation or file access failed! Interrupt." << std::endl; std::cout << "Memory allocation or file access failed! Interrupt." << std::endl;
return; return errCode;
} }
// Process data file tree and filter file subtype into list. // Process data file tree and filter file subtype into list.
ProcessFilesTree(); CreateDataFilesTree();
}
Erso::~Erso() { return errCode;
for ( ErsoEntryDir* de : *pFTRoot )
delete de;
delete pFTRoot;
free(rDatPtr);
delete pDatSection;
} }
string Erso::getDataSectionName( unsigned char id ) { return pDatSection->at(id).name; }
unsigned int Erso::getDataSectionOffset( unsigned char id ) { return pDatSection->at(id).offset; }
/** /**
* Helper function to search for legacy DATA.DAT/HDR and dump it in memory. * Helper function to search for legacy DATA.DAT/HDR and dump it in memory.
* *
* @return Error status. * @return Error status.
*/ */
RDI_RESULT Erso::DumpLegacyFiles() { RDI_RESULT Erso::DataFilesDumping() {
unsigned int i; unsigned int i;
path fp(workingDir); path fp(workingDir);
MEMFILE pTmpFile; MEMFILE pTmpFile;
@ -75,7 +107,7 @@ RDI_RESULT Erso::DumpLegacyFiles() {
// Open and parse data header file. // Open and parse data header file.
//if (boost::filesystem::exists(fp)) return RDI_ERROR_FILESYSTEM; //if (boost::filesystem::exists(fp)) return RDI_ERROR_FILESYSTEM;
pTmpFile = MallocFile(fp); pTmpFile = CreateMemFile(fp);
if (!pTmpFile) return RDI_ERROR_MEMORY; if (!pTmpFile) return RDI_ERROR_MEMORY;
cDatSection = file_size(fp) / sizeof(T_HDR_ENTRY); cDatSection = file_size(fp) / sizeof(T_HDR_ENTRY);
@ -91,7 +123,7 @@ RDI_RESULT Erso::DumpLegacyFiles() {
// Dump data file and store it's pointer into class member. // Dump data file and store it's pointer into class member.
fp.replace_extension(".DAT"); fp.replace_extension(".DAT");
//if (boost::filesystem::exists(fp)) return RDI_ERROR_FILESYSTEM; //if (boost::filesystem::exists(fp)) return RDI_ERROR_FILESYSTEM;
rDatPtr = MallocFile(fp); rDatPtr = CreateMemFile(fp);
if (!rDatPtr) return RDI_ERROR_MEMORY; if (!rDatPtr) return RDI_ERROR_MEMORY;
return RDI_OK; return RDI_OK;
@ -103,7 +135,7 @@ RDI_RESULT Erso::DumpLegacyFiles() {
* *
* @return Start memory pointer of the file. * @return Start memory pointer of the file.
*/ */
MEMFILE Erso::MallocFile( path filePath ) { MEMFILE Erso::CreateMemFile( path filePath ) {
const unsigned int size = file_size(filePath); const unsigned int size = file_size(filePath);
std::fstream rdf; std::fstream rdf;
MEMFILE fPtr = NULL; MEMFILE fPtr = NULL;
@ -123,16 +155,16 @@ MEMFILE Erso::MallocFile( path filePath ) {
* *
* @return Error status. * @return Error status.
*/ */
RDI_RESULT Erso::ProcessFilesTree() { RDI_RESULT Erso::CreateDataFilesTree() {
unsigned int curEntriesCount = 0, i; unsigned int curEntriesCount = 0, i;
ErsoEntryDir* curDir = nullptr; DatFileEntryDirectory* curDir = nullptr;
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<ErsoEntryDir*>; pFTRoot = new std::vector<DatFileEntryDirectory*>;
pFTRoot->clear(); pFTRoot->clear();
for ( i = 0; i < cDatSection; i++ ) { for ( i = 0; i < cDatSection; i++ ) {
curDir = new ErsoEntryDir(pDatSection->at(i).name); curDir = new DatFileEntryDirectory(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.
@ -141,21 +173,31 @@ RDI_RESULT Erso::ProcessFilesTree() {
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); ProcessTreeDirectoryContents(curDir, pFileDescriptors, curEntriesCount, rDatPtr + pDatSection->at(i).offset);
} }
return RDI_OK; return RDI_OK;
} }
RDI_RESULT Erso::ProcessDirectoryContents( ErsoEntryDir* pCurDir, MEMFILE pDesc, const unsigned int count, MEMFILE pSectionStart ) { /**
* Recursive function to process all sub-directory from a specific DatFileEntryDirectory root.
*
* @param pCurDir Root/current DatFileEntryDirectory from which the function begin to dig into
* @param pDesc MEMFILE pointer to the first entry of directory to be parsed
* @param count Number of elements in the pCurDir directory
* @param pSectionStart MEMFILE pointer to the beginning of parsed file
*
* @return Error status.
*/
RDI_RESULT Erso::ProcessTreeDirectoryContents( DatFileEntryDirectory* pCurDir, MEMFILE pDesc, const unsigned int count, MEMFILE pSectionStart ) {
unsigned int i, newDRECnt; unsigned int i, newDRECnt;
DAT_FILE_FLAGS curEntryFlags = {0}; DAT_FILE_FLAGS curEntryFlags = {0};
ErsoEntryFile* newFile = nullptr; DatFileEntryFile* newFile = nullptr;
ErsoEntryDir* newDir = nullptr; DatFileEntryDirectory* newDir = nullptr;
std::string tmpStr; std::string tmpStr;
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 + i * sizeof(T_FILE_HEADER)))->flags; curEntryFlags.raw = ((T_FILE_HEADER*)(pDesc + i * sizeof(T_FILE_HEADER)))->flags;
@ -165,17 +207,17 @@ RDI_RESULT Erso::ProcessDirectoryContents( ErsoEntryDir* pCurDir, MEMFILE pDesc,
// Test for file or directory // Test for file or directory
if (!curEntryFlags.isDirectory) { if (!curEntryFlags.isDirectory) {
newFile = new ErsoEntryFile(tmpStr, curEntryFlags, newFile = new DatFileEntryFile(tmpStr, curEntryFlags,
((T_FILE_HEADER*)(pDesc + i * sizeof(T_FILE_HEADER)))->datas_size, ((T_FILE_HEADER*)(pDesc + i * sizeof(T_FILE_HEADER)))->datas_size,
pSectionStart + ((T_FILE_HEADER*)(pDesc + i * sizeof(T_FILE_HEADER)))->datas_offset); pSectionStart + ((T_FILE_HEADER*)(pDesc + i * sizeof(T_FILE_HEADER)))->datas_offset);
pCurDir->AddEntry(newFile); pCurDir->AddEntry(newFile);
} else { } else {
newDir = new ErsoEntryDir(tmpStr, curEntryFlags); newDir = new DatFileEntryDirectory(tmpStr, curEntryFlags);
pCurDir->AddEntry(newDir); pCurDir->AddEntry(newDir);
// Keep entries count in new directory to jump over after processing it. // Keep entries count in new directory to jump over after processing it.
newDRECnt = (((T_FILE_HEADER*)(pDesc + i * sizeof(T_FILE_HEADER)))->dir_entries_size - sizeof(T_FILE_HEADER)) / sizeof(T_FILE_HEADER); newDRECnt = (((T_FILE_HEADER*)(pDesc + i * sizeof(T_FILE_HEADER)))->dir_entries_size - sizeof(T_FILE_HEADER)) / sizeof(T_FILE_HEADER);
ProcessDirectoryContents(newDir, pDesc + (i + 1) * sizeof(T_FILE_HEADER), newDRECnt, pSectionStart); ProcessTreeDirectoryContents(newDir, pDesc + (i + 1) * sizeof(T_FILE_HEADER), newDRECnt, pSectionStart);
if (newDRECnt <= count) i += newDRECnt; if (newDRECnt <= count) i += newDRECnt;
} }
} }
@ -183,11 +225,31 @@ RDI_RESULT Erso::ProcessDirectoryContents( ErsoEntryDir* pCurDir, MEMFILE pDesc,
return RDI_OK; return RDI_OK;
} }
ErsoEntry *Erso::getElement( boost::filesystem::path virtualDirPath ) { /**
* Free all allocated resources for files tree and MemFile
*/
void Erso::DisposeFile() {
for ( DatFileEntryDirectory* de : *pFTRoot )
delete de;
delete pFTRoot;
free(rDatPtr);
delete pDatSection;
}
/* ------------------------------------------------------------------------------------------------------------- */
/**
* Get DatFileEntry reference from virtual path
*
* @param virtualDirPath Path to the virtual resource
*
* @return Reference to the resource from specified input path
*/
DatFileEntry *Erso::getElement( boost::filesystem::path virtualDirPath ) {
bool skip = false; bool skip = false;
boost::filesystem::path newPath; boost::filesystem::path newPath;
for ( ErsoEntry* de : *pFTRoot ) { for ( DatFileEntry* de : *pFTRoot ) {
if (virtualDirPath.size() == 1 || virtualDirPath.begin() == --virtualDirPath.end()) { if (virtualDirPath.size() == 1 || virtualDirPath.begin() == --virtualDirPath.end()) {
if (de->getName() == virtualDirPath.filename().string()) if (de->getName() == virtualDirPath.filename().string())
return de; return de;
@ -198,7 +260,7 @@ ErsoEntry *Erso::getElement( boost::filesystem::path virtualDirPath ) {
newPath.append(sp); newPath.append(sp);
skip = true; skip = true;
} }
return SearchSectionForEntry(dynamic_cast<ErsoEntryDir *>(de), newPath); return SearchSectionForEntry(dynamic_cast<DatFileEntryDirectory *>(de), newPath);
} }
} }
} }
@ -206,11 +268,19 @@ ErsoEntry *Erso::getElement( boost::filesystem::path virtualDirPath ) {
return nullptr; return nullptr;
} }
ErsoEntry *Erso::SearchSectionForEntry( ErsoEntryDir *curDir, boost::filesystem::path virtualDirPath ) { /**
* Browse inside virtual path to the final object from specific root DatFileEntryDirectory.
*
* @param curDir Origin of browsing
* @param virtualDirPath Requested file path
*
* @return Reference to the file resource
*/
DatFileEntry *Erso::SearchSectionForEntry( DatFileEntryDirectory *curDir, boost::filesystem::path virtualDirPath ) {
bool skip = false; bool skip = false;
boost::filesystem::path newPath; boost::filesystem::path newPath;
for ( ErsoEntry* e : curDir->getFiles() ) { for ( DatFileEntry* e : curDir->getFiles() ) {
if (virtualDirPath.size() == 1 || virtualDirPath.begin() == --virtualDirPath.end()) { if (virtualDirPath.size() == 1 || virtualDirPath.begin() == --virtualDirPath.end()) {
if (e->getName() == virtualDirPath.filename().string()) if (e->getName() == virtualDirPath.filename().string())
return e; return e;
@ -221,8 +291,8 @@ ErsoEntry *Erso::SearchSectionForEntry( ErsoEntryDir *curDir, boost::filesystem:
newPath.append(sp); newPath.append(sp);
skip = true; skip = true;
} }
//TODO: add safety when trying to access inside a file
return SearchSectionForEntry(dynamic_cast<ErsoEntryDir *>(e), newPath); return SearchSectionForEntry(dynamic_cast<DatFileEntryDirectory *>(e), newPath);
} }
} }
} }

View File

@ -1,16 +1,38 @@
/** /**
* @file Erso.hpp * @file Erso.hpp
* @date 24/09/2022 * @date 11/01/2023
* @author JackCarterSmith * @author JackCarterSmith
* @copyright GPL-v3.0 * @copyright GPL-v3.0
* @brief Rogue DATA/BUNDLE file parser and interface. * @brief Rogue DATA/BUNDLE file parser and interface.
* @warning This module should be initialized before every others modules call of RDI library.
*
* Erso is the first module of the RDI library, it's use research work of
* <rogue_dev_team>, dpethes and myself to parse legacy data files of Rogue
* game.
* Currently compatible legacy files are :
* - DATA.DAT/HDR: as primary elements package containing all levels, sound,
* textures, etc.
* - BUNDLE.000: as title menu resources like pictures, buttons and cursor
* textures, menu sounds, menu macro-scripting.
* - BUNDLE.001: not known for now.
*
* This module should be initialized before every others modules call of RDI
* library.
*
* Standard usage:
* - Create a single Erso object with the folder path of datas files as input
* argument.
* - All supported data files will be parsed and a virtual tree view will be
* created.
* - The virtual tree view can be browse using appropriate 'get' functions.
* *
*/ */
#include <boost/filesystem.hpp> #include <boost/filesystem.hpp>
#include <vector> #include <vector>
#include "RDI_Datatypes.h" #include "RDI_Datatypes.h"
#include "ErsoEntry.hpp"
#include "DatFileEntry.hpp"
#ifndef ERSO_HPP_ #ifndef ERSO_HPP_
@ -31,20 +53,22 @@ struct dataSection {
class Erso final { class Erso final {
public: public:
Erso( std::string fPath ); Erso( std::string fPath );
Erso( std::string fPath, RDI_RESULT* outResult );
~Erso(); ~Erso();
MEMFILE getRDat() { MEMFILE getRDat() const { return rDatPtr; }
return rDatPtr;
}
/* Workspace management */
std::string getWorkingDirectory() { return workingDir; } std::string getWorkingDirectory() { return workingDir; }
void setWorkingDirectory( std::string newPath ) { workingDir = newPath; } RDI_RESULT setWorkingDirectory( std::string newPath );
unsigned char getDataSectionCount() { return cDatSection; } /* Generals informations getters */
std::string getDataSectionName( unsigned char id ); unsigned char getDataSectionCount() const { return cDatSection; }
unsigned int getDataSectionOffset( unsigned char id ); std::string getDataSectionName( unsigned char id ) const;
unsigned int getDataSectionOffset( unsigned char id ) const;
ErsoEntry *getElement( boost::filesystem::path virtualDirPath ); /* Tree manipulation/parse methods */
DatFile::DatFileEntry *getElement( boost::filesystem::path virtualDirPath );
private: private:
std::string workingDir = "."; std::string workingDir = ".";
@ -53,21 +77,24 @@ private:
std::vector<struct dataSection> *pDatSection = nullptr; std::vector<struct dataSection> *pDatSection = nullptr;
MEMFILE rDatPtr = nullptr; MEMFILE rDatPtr = nullptr;
std::vector<ErsoEntryDir*> *pFTRoot = nullptr; std::vector<DatFile::DatFileEntryDirectory*> *pFTRoot = nullptr;
/* File processing methods */ /* File processing methods */
RDI_RESULT DumpLegacyFiles(); RDI_RESULT Process();
MEMFILE MallocFile( boost::filesystem::path filePath ); RDI_RESULT DataFilesDumping();
RDI_RESULT ProcessFilesTree(); MEMFILE CreateMemFile( boost::filesystem::path filePath );
RDI_RESULT ProcessDirectoryContents( RDI_RESULT CreateDataFilesTree();
ErsoEntryDir* pCurDir, RDI_RESULT ProcessTreeDirectoryContents(
DatFile::DatFileEntryDirectory* pCurDir,
MEMFILE pDesc, MEMFILE pDesc,
const unsigned int count, const unsigned int count,
MEMFILE pSectionStart MEMFILE pSectionStart
); );
void DisposeFile();
/* Tree manipulation/parse methods */ /* Tree manipulation/parse methods */
ErsoEntry *SearchSectionForEntry( ErsoEntryDir *curDir, boost::filesystem::path virtualDirPath); DatFile::DatFileEntry *SearchSectionForEntry( DatFile::DatFileEntryDirectory *curDir, boost::filesystem::path virtualDirPath);
}; };

View File

@ -1,68 +0,0 @@
/**
* @file ErsoDatEntry.cpp
* @date 24/09/2022
* @author JackCarterSmith
* @copyright GPL-v3.0
* @brief Data file entry descriptor class.
*
*/
#include "ErsoEntry.hpp"
namespace RDI {
ErsoEntryFile::ErsoEntryFile( std::string name, DAT_FILE_FLAGS fFlags, unsigned int size, MEMFILE fPtr ) {
this->name = name;
this->size = size;
this->fFlags.raw = fFlags.raw;
this->fileMemPtr = fPtr;
}
ErsoEntryFile::~ErsoEntryFile() {}
/*std::string FileEntry::toString() {
}*/
ErsoEntryDir::ErsoEntryDir( std::string name ) {
this->name = name;
this->fFlags.raw = 0;
this->rootDir = true;
vSubFiles = new std::vector<ErsoEntry*>;
}
ErsoEntryDir::ErsoEntryDir( std::string name, DAT_FILE_FLAGS fFlags ) {
this->name = name;
this->fFlags.raw = fFlags.raw;
this->rootDir = false;
vSubFiles = new std::vector<ErsoEntry*>;
}
ErsoEntryDir::ErsoEntryDir( std::string name, DAT_FILE_FLAGS fFlags, ErsoEntry* hFileEntry ) {
this->name = name;
this->fFlags.raw = fFlags.raw;
vSubFiles = new std::vector<ErsoEntry*>;
AddEntry(hFileEntry);
}
ErsoEntryDir::~ErsoEntryDir() {
for ( ErsoEntry* e : *vSubFiles )
delete e;
delete vSubFiles;
}
/*std::string DirectoryEntry::toString() {
}*/
void ErsoEntryDir::ClearLinkedFiles() {
vSubFiles->clear();
}
void ErsoEntryDir::AddEntry( ErsoEntry* hFileEntry ) {
vSubFiles->push_back(hFileEntry);
}
}

View File

@ -1,94 +0,0 @@
/**
* @file ErsoEntry.hpp
* @date 24/09/2022
* @author JackCarterSmith
* @copyright GPL-v3.0
* @brief Data file entry descriptor class.
*
*/
#include <RDI_Datatypes.h>
#include <vector>
#include <string>
#ifndef ERSOENTRY_HPP_
#define ERSOENTRY_HPP_
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:8;
// MSB
};
unsigned short raw;
} DAT_FILE_FLAGS;
class ErsoEntry {
public:
virtual ~ErsoEntry() = 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 ErsoEntry::~ErsoEntry() {}
class ErsoEntryFile : public ErsoEntry {
public:
ErsoEntryFile( std::string name, DAT_FILE_FLAGS fFlags, unsigned int size, MEMFILE fPtr );
~ErsoEntryFile();
MEMFILE getDatas() { return fileMemPtr; }
//std::string toString();
bool isDirectory() { return false; }
bool isRootDirectory() { return false; }
unsigned int getSize() { return size; }
private:
MEMFILE fileMemPtr;
unsigned int size;
};
class ErsoEntryDir : public ErsoEntry {
public:
ErsoEntryDir( std::string name );
ErsoEntryDir( std::string name, DAT_FILE_FLAGS fFlags );
ErsoEntryDir( std::string name, DAT_FILE_FLAGS fFlags, ErsoEntry* hFileEntry );
~ErsoEntryDir();
void ClearLinkedFiles();
void AddEntry( ErsoEntry* hFileEntry );
std::vector<ErsoEntry*> 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<ErsoEntry*> *vSubFiles;
};
}
#endif /* ERSODATENTRY_HPP_ */

View File

@ -17,6 +17,8 @@
#include "Erso.hpp" #include "Erso.hpp"
#include "Krennic.hpp" #include "Krennic.hpp"
using namespace RDI::DatFile;
namespace RDI { namespace RDI {
@ -33,12 +35,12 @@ Krennic::~Krennic() {}
void Krennic::BuildLevelList( Erso* pErso ) { void Krennic::BuildLevelList( Erso* pErso ) {
const static std::string legacyLvlPath = "data/level"; const static std::string legacyLvlPath = "data/level";
ErsoEntryDir* levelDir = nullptr; DatFileEntryDirectory* levelDir = nullptr;
listLevel.clear(); listLevel.clear();
levelDir = dynamic_cast<ErsoEntryDir*>(pErso->getElement(boost::filesystem::path(legacyLvlPath))); levelDir = dynamic_cast<DatFileEntryDirectory*>(pErso->getElement(boost::filesystem::path(legacyLvlPath)));
if (levelDir != nullptr) { if (levelDir != nullptr) {
for ( ErsoEntry* fl : levelDir->getFiles() ) { for ( DatFileEntry* fl : levelDir->getFiles() ) {
if (fl->isDirectory()) { if (fl->isDirectory()) {
if (pErso->getElement(boost::filesystem::path(legacyLvlPath).append(fl->getName()).append("dat")) != nullptr) { if (pErso->getElement(boost::filesystem::path(legacyLvlPath).append(fl->getName()).append("dat")) != nullptr) {
listLevel.push_back(legacyLvlPath + "/" + fl->getName()); listLevel.push_back(legacyLvlPath + "/" + fl->getName());
@ -55,13 +57,13 @@ void Krennic::BuildModelList( Erso* pErso ) {
"data/pl_crafts", "data/reb_stuff", "data/imp_stuff", "data/pl_crafts", "data/reb_stuff", "data/imp_stuff",
"data/gnrc_stuff", "data2" "data/gnrc_stuff", "data2"
}; };
ErsoEntryDir* curModelDir = nullptr; DatFileEntryDirectory* curModelDir = nullptr;
listModel.clear(); listModel.clear();
for ( std::string path_it : legacyModelPath ) { for ( std::string path_it : legacyModelPath ) {
curModelDir = dynamic_cast<ErsoEntryDir*>(pErso->getElement(boost::filesystem::path(path_it))); curModelDir = dynamic_cast<DatFileEntryDirectory*>(pErso->getElement(boost::filesystem::path(path_it)));
if (curModelDir != nullptr) { if (curModelDir != nullptr) {
for ( ErsoEntry* fl : curModelDir->getFiles() ) { for ( DatFileEntry* fl : curModelDir->getFiles() ) {
if (fl->getName().find("_HOB") != std::string::npos) { if (fl->getName().find("_HOB") != std::string::npos) {
listModel.push_back(path_it + "/" + fl->getName()); listModel.push_back(path_it + "/" + fl->getName());
} }
@ -76,12 +78,12 @@ void Krennic::BuildTextureList( Erso* pErso ) {
void Krennic::BuildMusicList( Erso* pErso ) { void Krennic::BuildMusicList( Erso* pErso ) {
const static std::string legacyMusicPath = "data/sound"; const static std::string legacyMusicPath = "data/sound";
ErsoEntryDir* musicDir = nullptr; DatFileEntryDirectory* musicDir = nullptr;
listMusic.clear(); listMusic.clear();
musicDir = dynamic_cast<ErsoEntryDir*>(pErso->getElement(boost::filesystem::path(legacyMusicPath))); musicDir = dynamic_cast<DatFileEntryDirectory*>(pErso->getElement(boost::filesystem::path(legacyMusicPath)));
if (musicDir != nullptr) { if (musicDir != nullptr) {
for ( ErsoEntry* fl : musicDir->getFiles() ) { for ( DatFileEntry* fl : musicDir->getFiles() ) {
//TODO: MusyX-Class builder //TODO: MusyX-Class builder
if (fl->getName().find("_SNG") != std::string::npos) { if (fl->getName().find("_SNG") != std::string::npos) {

View File

@ -8,12 +8,15 @@
*/ */
#include <string> #include <string>
#include "DatFileEntry.hpp"
#include <FileHandler/Generic.h> #include <FileHandler/Generic.h>
#include "ErsoEntry.hpp"
using namespace RDI::DatFile;
namespace RDI { namespace RDI {
GenericFile::GenericFile( ErsoEntryFile& hDat ) { GenericFile::GenericFile( DatFile::DatFileEntryFile &hDat ) {
this->size = hDat.getSize(); this->size = hDat.getSize();
this->fileName = hDat.getName(); this->fileName = hDat.getName();
this->fileExtension = ""; this->fileExtension = "";

View File

@ -10,10 +10,12 @@
#include <FileHandler/Generic.h> #include <FileHandler/Generic.h>
#include <FileHandler/HMT.h> #include <FileHandler/HMT.h>
using namespace RDI::DatFile;
namespace RDI { namespace RDI {
HMT::HMT( ErsoEntryFile& hDat ): GenericFile( hDat ) { HMT::HMT( DatFile::DatFileEntryFile &hDat ): GenericFile( hDat ) {
this->fileExtension = "hmt"; this->fileExtension = "hmt";
} }

View File

@ -17,29 +17,49 @@
#include <fstream> #include <fstream>
#include "config.h" #include "config.h"
#include "Erso.hpp" #include "Erso.hpp"
#include "ErsoEntry.hpp" #include "DatFileEntry.hpp"
#include "Krennic.hpp" #include "Krennic.hpp"
#include "RDI.hpp" #include "RDI.hpp"
using namespace RDI::DatFile;
/* /*
* Internal modules instance * Internal modules instance
*/ */
static RDI::Erso *hErsoModule = nullptr; static RDI::Erso *ErsoModule = nullptr;
static RDI::Krennic *hKrennicModule = nullptr; static RDI::Krennic *KrennicModule = nullptr;
/* /*
* Libs interface * Libs interface
*/ */
std::string RDI::getLibVersion() { return PRG_VERSION; } std::string RDI::RDI_getLibVersion() { return PRG_VERSION; }
void RDI::Init( std::string roguePath ){ void RDI::RDI_Init( std::string roguePath ) {
if (hErsoModule == nullptr) { #ifdef DEBUG
hErsoModule = new RDI::Erso(roguePath); std::cout << std::endl << "Running RDI v" << RDI_getLibVersion() << std::endl;
std::cout << "> RSPModelLib v" << "N/A" << std::endl;
std::cout << "> RSPTerrainLib v" << "N/A" << std::endl;
std::cout << "> RSPTextureLib v" << "N/A" << std::endl;
#endif
// Create new instance of Erso module
// Load and extract datas files from DATA.DAT
if (ErsoModule == nullptr) {
#ifdef DEBUG
std::cout << "[RDI][DBG] Loading Erso module..." << std::endl;
#endif
ErsoModule = new RDI::Erso(roguePath);
} }
if (hErsoModule != nullptr && hKrennicModule == nullptr) {
hKrennicModule = new RDI::Krennic(hErsoModule); // Create new instance of Krennic module
// Process datas from Erso and build new dataset to be used outside this library
if (ErsoModule != nullptr && KrennicModule == nullptr) {
#ifdef DEBUG
std::cout << "[RDI][DBG] Loading Krennic module..." << std::endl;
#endif
KrennicModule = new RDI::Krennic(ErsoModule);
} }
} }
@ -48,43 +68,43 @@ void RDI::Init( std::string roguePath ){
unsigned char RDI::getSectionCount() { unsigned char RDI::RDI_getSectionCount() {
if (hErsoModule == nullptr) return 0; if (ErsoModule == nullptr) return 0;
else return hErsoModule->getDataSectionCount(); else return ErsoModule->getDataSectionCount();
} }
std::string RDI::getSectionName( unsigned char id ) { std::string RDI::RDI_getSectionName( unsigned char id ) {
if (hErsoModule == nullptr) return ""; if (ErsoModule == nullptr) return "";
else return hErsoModule->getDataSectionName(id); else return ErsoModule->getDataSectionName(id);
} }
unsigned int RDI::getSectionOffset( unsigned char id ) { unsigned int RDI::RDI_getSectionOffset( unsigned char id ) {
if (hErsoModule == nullptr) return 0; if (ErsoModule == nullptr) return 0;
else return hErsoModule->getDataSectionOffset(id); else return ErsoModule->getDataSectionOffset(id);
} }
unsigned int RDI::getDirectoryElementCount( std::string path ) { unsigned int RDI::RDI_getDirectoryElementCount( std::string path ) {
ErsoEntryDir* result = nullptr; DatFileEntryDirectory* result = nullptr;
if (path.empty()) return 0; if (path.empty()) return 0;
result = dynamic_cast<ErsoEntryDir *>(hErsoModule->getElement(boost::filesystem::path(path))); result = dynamic_cast<DatFileEntryDirectory *>(ErsoModule->getElement(boost::filesystem::path(path)));
if (result == nullptr) return 0; if (result == nullptr) return 0;
else return result->getSize(); else return result->getSize();
} }
std::vector<std::string> RDI::getDirectoryElements( std::string path ) { std::vector<std::string> RDI::RDI_getDirectoryElements( std::string path ) {
ErsoEntryDir* de = nullptr; DatFileEntryDirectory* de = nullptr;
std::vector<std::string> elementsNameArray; std::vector<std::string> elementsNameArray;
elementsNameArray.clear(); elementsNameArray.clear();
if (!path.empty()) { if (!path.empty()) {
de = dynamic_cast<ErsoEntryDir *>(hErsoModule->getElement(boost::filesystem::path(path))); de = dynamic_cast<DatFileEntryDirectory *>(ErsoModule->getElement(boost::filesystem::path(path)));
if (de != nullptr && de->isDirectory()) { if (de != nullptr && de->isDirectory()) {
for (ErsoEntry* de2 : de->getFiles()) for (DatFileEntry* de2 : de->getFiles())
elementsNameArray.push_back(de2->getName()); elementsNameArray.push_back(de2->getName());
} }
} }
@ -92,31 +112,31 @@ std::vector<std::string> RDI::getDirectoryElements( std::string path ) {
return elementsNameArray; return elementsNameArray;
} }
bool RDI::isElementDirectory( std::string path ) { bool RDI::RDI_isElementDirectory( std::string path ) {
ErsoEntry* result = nullptr; DatFileEntry* result = nullptr;
if (path.empty()) return false; if (path.empty()) return false;
result = hErsoModule->getElement(boost::filesystem::path(path)); result = ErsoModule->getElement(boost::filesystem::path(path));
if (result == nullptr) return false; if (result == nullptr) return false;
else return (result->isDirectory() || result->isRootDirectory()); else return (result->isDirectory() || result->isRootDirectory());
} }
std::vector<std::string> RDI::getLevelsName( void ) { std::vector<std::string> RDI::RDI_getLevelsName( void ) {
return hKrennicModule->getLevelsList(); return KrennicModule->getLevelsList();
} }
std::vector<std::string> RDI::getModelsName( void ) { std::vector<std::string> RDI::RDI_getModelsName( void ) {
return hKrennicModule->getModelsList(); return KrennicModule->getModelsList();
} }
std::vector<std::string> RDI::getMusicsName( void ) { std::vector<std::string> RDI::RDI_getMusicsName( void ) {
return hKrennicModule->getMusicsList(); return KrennicModule->getMusicsList();
} }
void RDI::CleanUp(){ void RDI::RDI_CleanUp(){
if (hKrennicModule) delete hKrennicModule; if (KrennicModule) delete KrennicModule;
if (hErsoModule) delete hErsoModule; if (ErsoModule) delete ErsoModule;
} }

View File

@ -1,6 +1,6 @@
/** /**
* @file RDIdebug.cpp * @file RDIDebug.cpp
* @date 17/09/2022 * @date 12/01/2023
* @author JackCarterSmith * @author JackCarterSmith
* @copyright GPL-v3.0 * @copyright GPL-v3.0
* @brief Debug app to test functions of RDI library. * @brief Debug app to test functions of RDI library.
@ -12,74 +12,108 @@
#include <boost/filesystem.hpp> #include <boost/filesystem.hpp>
#include <RDI.hpp> #include <RDI.hpp>
#ifdef _WIN32
#include <windows.h>
#endif
void PrintVirtualDirectoryContents( boost::filesystem::path, std::string ); using namespace boost::filesystem;
using namespace std;
void PrintVirtualDirectoryContents( path, string, bool );
int main( int argc, char *argv[] ) { int main( int argc, char *argv[] ) {
unsigned int i; unsigned int i;
boost::filesystem::path pathBuilder; path pathBuilder;
std::string prefix; string prefix;
bool use_unicode = true;
printf("Using RDI lib v%s\n\n", RDI::getLibVersion().c_str()); #ifdef _WIN32
//cout << "Using RDI lib v" << RDI::getLibVersion() << endl << endl; SetConsoleOutputCP(CP_UTF8);
#endif
if ( argc > 1 ) cout << "Using RDI lib v" << RDI::RDI_getLibVersion() << endl << endl;
RDI::Init(argv[1]);
else
RDI::Init(".");
printf("> Section found: %d\n", RDI::getSectionCount()); // Initialize RDI (Erso and Krennic module) with folder provided in program
for ( i = 0; i < RDI::getSectionCount(); i++ ) { // argument, or the current directory by default
printf(" -Section %d name: %s\n", i, RDI::getSectionName(i).c_str()); if ( argc > 2 ) {
printf(" -Section %d offset: 0x%X\n", i, RDI::getSectionOffset(i)); use_unicode = atoi(argv[2]);
RDI::RDI_Init(argv[1]);
} else if (argc > 1) {
RDI::RDI_Init(argv[1]);
} else {
RDI::RDI_Init(".");
} }
//prefix.append("\t"); // Print details about legacy DATA.DAT file
prefix.append(" "); cout << "> Section found: " << RDI::RDI_getSectionCount() << endl;
printf("\nSections files root:\n"); for ( i = 0; i < RDI::RDI_getSectionCount(); i++ ) {
for ( i = 0; i < RDI::getSectionCount(); i++ ) { cout << " -Section " << i << " name: " << RDI::RDI_getSectionName(i) << endl;
printf("%s:\n", RDI::getSectionName(i).c_str()); // Print root trees cout << " -Section " << i << " offset: 0x" << hex << uppercase << RDI::RDI_getSectionOffset(i) << endl;
}
// Print DATA.DAT tree view with unicode "style"
cout << endl << "DATA.DAT files tree view:" << endl;
for ( i = 0; i < RDI::RDI_getSectionCount(); i++ ) {
cout << RDI::RDI_getSectionName(i) << ":" << endl;
pathBuilder.clear(); pathBuilder.clear();
pathBuilder.concat(RDI::getSectionName(i)); pathBuilder.concat(RDI::RDI_getSectionName(i));
PrintVirtualDirectoryContents(pathBuilder, prefix); PrintVirtualDirectoryContents(pathBuilder, prefix, use_unicode);
} }
for ( std::string lname : RDI::getLevelsName() ) { // Print game elements Krennic module found
printf("Level found: %s\n", lname.c_str()); cout << endl << "Legacy files processing result:";
cout << endl << "> Levels found:" << endl;
for ( std::string lname : RDI::RDI_getLevelsName() ) {
cout << " " << lname << endl;
} }
for ( std::string mdname : RDI::getModelsName() ) { cout << endl << "> Models found:" << endl;
printf("Model found: %s\n", mdname.c_str()); for ( std::string mdname : RDI::RDI_getModelsName() ) {
cout << " " << mdname << endl;
} }
for ( std::string mname : RDI::getMusicsName() ) { cout << endl << "> Musics found:" << endl;
printf("Music found: %s\n", mname.c_str()); for ( std::string mname : RDI::RDI_getMusicsName() ) {
cout << " " << mname << endl;
} }
RDI::CleanUp(); // Release RDI library
RDI::RDI_CleanUp();
return 0; return 0;
} }
void PrintVirtualDirectoryContents( boost::filesystem::path path, std::string outPrefix ) { void PrintVirtualDirectoryContents( path p, string outPrefix, bool unicode ) {
auto curDirElementsName = RDI::getDirectoryElements(path.string()); auto curDirElementsName = RDI::RDI_getDirectoryElements(p.string());
auto newPath = boost::filesystem::path(path); auto newPath = path(p);
auto newOutPrefix = std::string(outPrefix); auto newOutPrefix = string(outPrefix);
for ( std::string eName : curDirElementsName ) { for ( string eName : curDirElementsName ) {
newPath.clear(); newPath.clear();
newPath.concat(path); newPath.concat(p);
newOutPrefix.clear(); newOutPrefix.clear();
newOutPrefix.append(outPrefix); newOutPrefix.append(outPrefix);
newPath.append(eName); newPath.append(eName);
if (RDI::isElementDirectory(newPath.string())) { if (RDI::RDI_isElementDirectory(newPath.string())) {
printf("%s%s:\n", outPrefix.c_str(), eName.c_str()); if (unicode) {
//newOutPrefix.append("\t"); cout << outPrefix << "\u251C " << eName << endl;
newOutPrefix.append(" "); newOutPrefix.append("\u2502 ");
PrintVirtualDirectoryContents(newPath, newOutPrefix); } else {
cout << outPrefix << "\\ " << eName << endl;
newOutPrefix.append("| ");
}
PrintVirtualDirectoryContents(newPath, newOutPrefix, unicode);
} else { } else {
printf("%s%s\n", newOutPrefix.c_str(), eName.c_str()); if (unicode) {
if (*--curDirElementsName.end() == eName)
cout << newOutPrefix << "\u2514 " << eName << endl;
else
cout << newOutPrefix << "\u251C " << eName << endl;
} else {
cout << newOutPrefix << "+ " << eName << endl;
}
} }
} }
} }