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()
#set(RDI_LIB_NAME RDI${PROJECT_VERSION_MAJOR}${PROJECT_VERSION_MINOR})
set(RDI_LIB_NAME RDI)
if(NOT MSVC)
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -Wall")
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_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_LIB_DIR "${CMAKE_INSTALL_PREFIX}/lib" CACHE PATH "Installation directory for libraries")
@ -176,11 +181,11 @@ if(BUILD_TOOLS)
endif()
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(krennic-debug-tools PRIVATE rdi-lib)
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(krennic-debug-tools PRIVATE rdi-libstatic)
endif()

View File

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

View File

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

View File

@ -48,7 +48,7 @@ namespace RDI {
* @brief Get the current library 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.
@ -56,26 +56,26 @@ namespace RDI {
* 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.
*/
RDI_EXTERN void Init( std::string roguePath );
RDI_EXTERN void RDI_Init( std::string roguePath );
/* Erso specific methods */
RDI_EXTERN unsigned char getSectionCount( void );
RDI_EXTERN std::string getSectionName( unsigned char id );
RDI_EXTERN unsigned int getSectionOffset( unsigned char id );
RDI_EXTERN unsigned char RDI_getSectionCount( void );
RDI_EXTERN std::string RDI_getSectionName( unsigned char id );
RDI_EXTERN unsigned int RDI_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 );
RDI_EXTERN unsigned int RDI_getDirectoryElementCount( std::string path );
RDI_EXTERN std::vector<std::string> RDI_getDirectoryElements( std::string path );
RDI_EXTERN bool RDI_isElementDirectory( std::string path );
/* Krennic specific methods */
RDI_EXTERN std::vector<std::string> getLevelsName( void );
RDI_EXTERN std::vector<std::string> getModelsName( void );
RDI_EXTERN std::vector<std::string> getMusicsName( void );
RDI_EXTERN std::vector<std::string> RDI_getLevelsName( void );
RDI_EXTERN std::vector<std::string> RDI_getModelsName( void );
RDI_EXTERN std::vector<std::string> RDI_getMusicsName( void );
/**
* @brief Clean up global resources.
*/
RDI_EXTERN void CleanUp( void );
RDI_EXTERN void RDI_CleanUp( void );
}
#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
* @date 24/09/2022
* @date 11/01/2023
* @author JackCarterSmith
* @copyright GPL-v3.0
* @brief Rogue DATA/BUNDLE file parser and interface.
@ -14,9 +14,8 @@
#include <boost/filesystem.hpp>
#include <RDI_Datatypes.h>
#include "files_mms/data_struct.h"
#include "DatFileEntry.hpp"
#include "Erso.hpp"
#include "ErsoEntry.hpp"
using std::string;
using std::ios;
@ -24,45 +23,78 @@ using std::vector;
using boost::filesystem::path;
using boost::filesystem::file_size;
using namespace RDI::DatFile;
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;
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.
errCode = DumpLegacyFiles();
errCode = DataFilesDumping();
if (errCode == RDI_ERROR_FILESYSTEM) {
std::cout << "Data files (DATA.DAT/DATA.HDR) not found! Interrupt." << std::endl;
return;
return errCode;
} else if (errCode == RDI_ERROR_MEMORY) {
std::cout << "Memory allocation or file access failed! Interrupt." << std::endl;
return;
return errCode;
}
// Process data file tree and filter file subtype into list.
ProcessFilesTree();
}
CreateDataFilesTree();
Erso::~Erso() {
for ( ErsoEntryDir* de : *pFTRoot )
delete de;
delete pFTRoot;
free(rDatPtr);
delete pDatSection;
return errCode;
}
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.
*
* @return Error status.
*/
RDI_RESULT Erso::DumpLegacyFiles() {
RDI_RESULT Erso::DataFilesDumping() {
unsigned int i;
path fp(workingDir);
MEMFILE pTmpFile;
@ -75,7 +107,7 @@ RDI_RESULT Erso::DumpLegacyFiles() {
// Open and parse data header file.
//if (boost::filesystem::exists(fp)) return RDI_ERROR_FILESYSTEM;
pTmpFile = MallocFile(fp);
pTmpFile = CreateMemFile(fp);
if (!pTmpFile) return RDI_ERROR_MEMORY;
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.
fp.replace_extension(".DAT");
//if (boost::filesystem::exists(fp)) return RDI_ERROR_FILESYSTEM;
rDatPtr = MallocFile(fp);
rDatPtr = CreateMemFile(fp);
if (!rDatPtr) return RDI_ERROR_MEMORY;
return RDI_OK;
@ -103,7 +135,7 @@ RDI_RESULT Erso::DumpLegacyFiles() {
*
* @return Start memory pointer of the file.
*/
MEMFILE Erso::MallocFile( path filePath ) {
MEMFILE Erso::CreateMemFile( path filePath ) {
const unsigned int size = file_size(filePath);
std::fstream rdf;
MEMFILE fPtr = NULL;
@ -123,16 +155,16 @@ MEMFILE Erso::MallocFile( path filePath ) {
*
* @return Error status.
*/
RDI_RESULT Erso::ProcessFilesTree() {
RDI_RESULT Erso::CreateDataFilesTree() {
unsigned int curEntriesCount = 0, i;
ErsoEntryDir* curDir = nullptr;
DatFileEntryDirectory* curDir = nullptr;
MEMFILE pFileDescriptors = nullptr;
// Create new root files tree. One per data section.
pFTRoot = new std::vector<ErsoEntryDir*>;
pFTRoot = new std::vector<DatFileEntryDirectory*>;
pFTRoot->clear();
for ( i = 0; i < cDatSection; i++ ) {
curDir = new ErsoEntryDir(pDatSection->at(i).name);
curDir = new DatFileEntryDirectory(pDatSection->at(i).name);
pFTRoot->push_back(curDir);
// Recalculate files descriptor offset for current section.
@ -141,18 +173,28 @@ RDI_RESULT Erso::ProcessFilesTree() {
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);
ProcessTreeDirectoryContents(curDir, pFileDescriptors, curEntriesCount, rDatPtr + pDatSection->at(i).offset);
}
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;
DAT_FILE_FLAGS curEntryFlags = {0};
ErsoEntryFile* newFile = nullptr;
ErsoEntryDir* newDir = nullptr;
DatFileEntryFile* newFile = nullptr;
DatFileEntryDirectory* newDir = nullptr;
std::string tmpStr;
if ( count == 0 ) return RDI_ERROR_PROCESS;
@ -165,17 +207,17 @@ RDI_RESULT Erso::ProcessDirectoryContents( ErsoEntryDir* pCurDir, MEMFILE pDesc,
// Test for file or directory
if (!curEntryFlags.isDirectory) {
newFile = new ErsoEntryFile(tmpStr, curEntryFlags,
newFile = new DatFileEntryFile(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 ErsoEntryDir(tmpStr, curEntryFlags);
newDir = new DatFileEntryDirectory(tmpStr, curEntryFlags);
pCurDir->AddEntry(newDir);
// 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);
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;
}
}
@ -183,11 +225,31 @@ RDI_RESULT Erso::ProcessDirectoryContents( ErsoEntryDir* pCurDir, MEMFILE pDesc,
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;
boost::filesystem::path newPath;
for ( ErsoEntry* de : *pFTRoot ) {
for ( DatFileEntry* de : *pFTRoot ) {
if (virtualDirPath.size() == 1 || virtualDirPath.begin() == --virtualDirPath.end()) {
if (de->getName() == virtualDirPath.filename().string())
return de;
@ -198,7 +260,7 @@ ErsoEntry *Erso::getElement( boost::filesystem::path virtualDirPath ) {
newPath.append(sp);
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;
}
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;
boost::filesystem::path newPath;
for ( ErsoEntry* e : curDir->getFiles() ) {
for ( DatFileEntry* e : curDir->getFiles() ) {
if (virtualDirPath.size() == 1 || virtualDirPath.begin() == --virtualDirPath.end()) {
if (e->getName() == virtualDirPath.filename().string())
return e;
@ -221,8 +291,8 @@ ErsoEntry *Erso::SearchSectionForEntry( ErsoEntryDir *curDir, boost::filesystem:
newPath.append(sp);
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
* @date 24/09/2022
* @date 11/01/2023
* @author JackCarterSmith
* @copyright GPL-v3.0
* @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 <vector>
#include "RDI_Datatypes.h"
#include "ErsoEntry.hpp"
#include "DatFileEntry.hpp"
#ifndef ERSO_HPP_
@ -31,20 +53,22 @@ struct dataSection {
class Erso final {
public:
Erso( std::string fPath );
Erso( std::string fPath, RDI_RESULT* outResult );
~Erso();
MEMFILE getRDat() {
return rDatPtr;
}
MEMFILE getRDat() const { return rDatPtr; }
/* Workspace management */
std::string getWorkingDirectory() { return workingDir; }
void setWorkingDirectory( std::string newPath ) { workingDir = newPath; }
RDI_RESULT setWorkingDirectory( std::string newPath );
unsigned char getDataSectionCount() { return cDatSection; }
std::string getDataSectionName( unsigned char id );
unsigned int getDataSectionOffset( unsigned char id );
/* Generals informations getters */
unsigned char getDataSectionCount() const { return cDatSection; }
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:
std::string workingDir = ".";
@ -53,21 +77,24 @@ private:
std::vector<struct dataSection> *pDatSection = nullptr;
MEMFILE rDatPtr = nullptr;
std::vector<ErsoEntryDir*> *pFTRoot = nullptr;
std::vector<DatFile::DatFileEntryDirectory*> *pFTRoot = nullptr;
/* File processing methods */
RDI_RESULT DumpLegacyFiles();
MEMFILE MallocFile( boost::filesystem::path filePath );
RDI_RESULT ProcessFilesTree();
RDI_RESULT ProcessDirectoryContents(
ErsoEntryDir* pCurDir,
RDI_RESULT Process();
RDI_RESULT DataFilesDumping();
MEMFILE CreateMemFile( boost::filesystem::path filePath );
RDI_RESULT CreateDataFilesTree();
RDI_RESULT ProcessTreeDirectoryContents(
DatFile::DatFileEntryDirectory* pCurDir,
MEMFILE pDesc,
const unsigned int count,
MEMFILE pSectionStart
);
void DisposeFile();
/* 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 "Krennic.hpp"
using namespace RDI::DatFile;
namespace RDI {
@ -33,12 +35,12 @@ Krennic::~Krennic() {}
void Krennic::BuildLevelList( Erso* pErso ) {
const static std::string legacyLvlPath = "data/level";
ErsoEntryDir* levelDir = nullptr;
DatFileEntryDirectory* levelDir = nullptr;
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) {
for ( ErsoEntry* fl : levelDir->getFiles() ) {
for ( DatFileEntry* fl : levelDir->getFiles() ) {
if (fl->isDirectory()) {
if (pErso->getElement(boost::filesystem::path(legacyLvlPath).append(fl->getName()).append("dat")) != nullptr) {
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/gnrc_stuff", "data2"
};
ErsoEntryDir* curModelDir = nullptr;
DatFileEntryDirectory* curModelDir = nullptr;
listModel.clear();
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) {
for ( ErsoEntry* fl : curModelDir->getFiles() ) {
for ( DatFileEntry* fl : curModelDir->getFiles() ) {
if (fl->getName().find("_HOB") != std::string::npos) {
listModel.push_back(path_it + "/" + fl->getName());
}
@ -76,12 +78,12 @@ void Krennic::BuildTextureList( Erso* pErso ) {
void Krennic::BuildMusicList( Erso* pErso ) {
const static std::string legacyMusicPath = "data/sound";
ErsoEntryDir* musicDir = nullptr;
DatFileEntryDirectory* musicDir = nullptr;
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) {
for ( ErsoEntry* fl : musicDir->getFiles() ) {
for ( DatFileEntry* fl : musicDir->getFiles() ) {
//TODO: MusyX-Class builder
if (fl->getName().find("_SNG") != std::string::npos) {

View File

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

View File

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

View File

@ -17,29 +17,49 @@
#include <fstream>
#include "config.h"
#include "Erso.hpp"
#include "ErsoEntry.hpp"
#include "DatFileEntry.hpp"
#include "Krennic.hpp"
#include "RDI.hpp"
using namespace RDI::DatFile;
/*
* Internal modules instance
*/
static RDI::Erso *hErsoModule = nullptr;
static RDI::Krennic *hKrennicModule = nullptr;
static RDI::Erso *ErsoModule = nullptr;
static RDI::Krennic *KrennicModule = nullptr;
/*
* Libs interface
*/
std::string RDI::getLibVersion() { return PRG_VERSION; }
std::string RDI::RDI_getLibVersion() { return PRG_VERSION; }
void RDI::Init( std::string roguePath ){
if (hErsoModule == nullptr) {
hErsoModule = new RDI::Erso(roguePath);
void RDI::RDI_Init( std::string roguePath ) {
#ifdef DEBUG
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() {
if (hErsoModule == nullptr) return 0;
else return hErsoModule->getDataSectionCount();
unsigned char RDI::RDI_getSectionCount() {
if (ErsoModule == nullptr) return 0;
else return ErsoModule->getDataSectionCount();
}
std::string RDI::getSectionName( unsigned char id ) {
if (hErsoModule == nullptr) return "";
else return hErsoModule->getDataSectionName(id);
std::string RDI::RDI_getSectionName( unsigned char id ) {
if (ErsoModule == nullptr) return "";
else return ErsoModule->getDataSectionName(id);
}
unsigned int RDI::getSectionOffset( unsigned char id ) {
if (hErsoModule == nullptr) return 0;
else return hErsoModule->getDataSectionOffset(id);
unsigned int RDI::RDI_getSectionOffset( unsigned char id ) {
if (ErsoModule == nullptr) return 0;
else return ErsoModule->getDataSectionOffset(id);
}
unsigned int RDI::getDirectoryElementCount( std::string path ) {
ErsoEntryDir* result = nullptr;
unsigned int RDI::RDI_getDirectoryElementCount( std::string path ) {
DatFileEntryDirectory* result = nullptr;
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;
else return result->getSize();
}
std::vector<std::string> RDI::getDirectoryElements( std::string path ) {
ErsoEntryDir* de = nullptr;
std::vector<std::string> RDI::RDI_getDirectoryElements( std::string path ) {
DatFileEntryDirectory* de = nullptr;
std::vector<std::string> elementsNameArray;
elementsNameArray.clear();
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()) {
for (ErsoEntry* de2 : de->getFiles())
for (DatFileEntry* de2 : de->getFiles())
elementsNameArray.push_back(de2->getName());
}
}
@ -92,31 +112,31 @@ std::vector<std::string> RDI::getDirectoryElements( std::string path ) {
return elementsNameArray;
}
bool RDI::isElementDirectory( std::string path ) {
ErsoEntry* result = nullptr;
bool RDI::RDI_isElementDirectory( std::string path ) {
DatFileEntry* result = nullptr;
if (path.empty()) return false;
result = hErsoModule->getElement(boost::filesystem::path(path));
result = ErsoModule->getElement(boost::filesystem::path(path));
if (result == nullptr) return false;
else return (result->isDirectory() || result->isRootDirectory());
}
std::vector<std::string> RDI::getLevelsName( void ) {
return hKrennicModule->getLevelsList();
std::vector<std::string> RDI::RDI_getLevelsName( void ) {
return KrennicModule->getLevelsList();
}
std::vector<std::string> RDI::getModelsName( void ) {
return hKrennicModule->getModelsList();
std::vector<std::string> RDI::RDI_getModelsName( void ) {
return KrennicModule->getModelsList();
}
std::vector<std::string> RDI::getMusicsName( void ) {
return hKrennicModule->getMusicsList();
std::vector<std::string> RDI::RDI_getMusicsName( void ) {
return KrennicModule->getMusicsList();
}
void RDI::CleanUp(){
if (hKrennicModule) delete hKrennicModule;
if (hErsoModule) delete hErsoModule;
void RDI::RDI_CleanUp(){
if (KrennicModule) delete KrennicModule;
if (ErsoModule) delete ErsoModule;
}

View File

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