From e07d86153595747dc40eeb6accfcd67a9d631708 Mon Sep 17 00:00:00 2001 From: JackCarterSmith Date: Thu, 22 Sep 2022 22:09:23 +0200 Subject: [PATCH 1/9] Add legacy interface --- src/LegacyExplorer.cpp | 31 +++++++++++++++++++++++++++++++ src/LegacyExplorer.h | 26 ++++++++++++++++++++++++++ src/RDat.cpp | 3 --- 3 files changed, 57 insertions(+), 3 deletions(-) create mode 100644 src/LegacyExplorer.cpp create mode 100644 src/LegacyExplorer.h diff --git a/src/LegacyExplorer.cpp b/src/LegacyExplorer.cpp new file mode 100644 index 0000000..ed37682 --- /dev/null +++ b/src/LegacyExplorer.cpp @@ -0,0 +1,31 @@ +/** + * @file LegacyExplorer.cpp + * @date 22/09/2022 + * @author JackCarterSmith + * @copyright GPL-v3.0 + * @brief Main game resources interface. + * + * Complete class would take legacy RDat files tree and extract levels, objects, + * textures, animations, etc. adapted datas for OpenGL/Direct3D application. + * + */ + +#include +#include +#include +#include "RDat.h" +#include "LegacyExplorer.h" + + +namespace RDI { + +LegacyExplorer::LegacyExplorer( RDat& pRDat ) { + // TODO Auto-generated constructor stub + +} + +LegacyExplorer::~LegacyExplorer() { + // TODO Auto-generated destructor stub +} + +} diff --git a/src/LegacyExplorer.h b/src/LegacyExplorer.h new file mode 100644 index 0000000..553cfb6 --- /dev/null +++ b/src/LegacyExplorer.h @@ -0,0 +1,26 @@ +/** + * @file LegacyExplorer.h + * @date 22/09/2022 + * @author JackCarterSmith + * @copyright GPL-v3.0 + * @brief Main game resources interface. + * + * Complete class would take legacy RDat files tree and extract levels, objects, + * textures, animations, etc. adapted datas for OpenGL/Direct3D application. + * + */ + +#ifndef LEGACYEXPLORER_H_ +#define LEGACYEXPLORER_H_ + +namespace RDI { + +class LegacyExplorer final { +public: + LegacyExplorer( RDat& pRDat ); + ~LegacyExplorer(); +}; + +} + +#endif /* LEGACYEXPLORER_H_ */ diff --git a/src/RDat.cpp b/src/RDat.cpp index 2ac2ab2..0ab3197 100644 --- a/src/RDat.cpp +++ b/src/RDat.cpp @@ -12,9 +12,6 @@ #include #include #include -#include -#include -#include #include #include "DatEntry.h" #include "data_struct.h" -- 2.39.5 From 5764d27ef4dc4c4f4725dfd935a94efa960e8bc6 Mon Sep 17 00:00:00 2001 From: JackCarterSmith Date: Sat, 24 Sep 2022 13:44:07 +0200 Subject: [PATCH 2/9] Basic assets lists constructor General datas/lists structure should be reviewed --- include/RDI.h | 7 ++++ src/LegacyExplorer.cpp | 75 ++++++++++++++++++++++++++++++++++-- src/LegacyExplorer.h | 58 +++++++++++++++++++++++++++- src/RDI.cpp | 24 ++++++++++++ src/datfiles/GenericFile.cpp | 25 ++++++++++++ src/datfiles/GenericFile.h | 34 ++++++++++++++++ src/datfiles/HMT.cpp | 13 +++---- src/datfiles/HMT.h | 15 +++++--- tools/RDIdebug.cpp | 11 ++++++ 9 files changed, 244 insertions(+), 18 deletions(-) create mode 100644 src/datfiles/GenericFile.cpp create mode 100644 src/datfiles/GenericFile.h diff --git a/include/RDI.h b/include/RDI.h index 4746737..cdb1d81 100644 --- a/include/RDI.h +++ b/include/RDI.h @@ -58,6 +58,7 @@ namespace RDI { * @return Handler of RogueData file, should be used with other function of this lib. */ RDI_EXTERN void CreateRDatHandler( std::string roguePath ); + RDI_EXTERN void CreateLegacyHandler( void ); RDI_EXTERN unsigned char getSectionCount( void ); RDI_EXTERN std::string getSectionName( unsigned char id ); @@ -67,10 +68,16 @@ namespace RDI { RDI_EXTERN std::vector getDirectoryElements( std::string path ); RDI_EXTERN bool isElementDirectory( std::string path ); + + RDI_EXTERN std::vector getLevelsName( void ); + RDI_EXTERN std::vector getModelsName( void ); + RDI_EXTERN std::vector getMusicsName( void ); + /** * @brief Clean up global resources. */ RDI_EXTERN void DestroyRDatHandler( void ); + RDI_EXTERN void DestroyLegacyHandler( void ); } diff --git a/src/LegacyExplorer.cpp b/src/LegacyExplorer.cpp index ed37682..7fb56bc 100644 --- a/src/LegacyExplorer.cpp +++ b/src/LegacyExplorer.cpp @@ -13,19 +13,86 @@ #include #include #include +#include #include "RDat.h" #include "LegacyExplorer.h" namespace RDI { -LegacyExplorer::LegacyExplorer( RDat& pRDat ) { - // TODO Auto-generated constructor stub +LegacyExplorer::LegacyExplorer( RDat* pRDat ) { + BuildLevelList(pRDat); + BuildModelList(pRDat); + BuildTextureList(pRDat); + BuildMusicList(pRDat); + BuildSampleList(pRDat); +} + +LegacyExplorer::~LegacyExplorer() {} + + +void LegacyExplorer::BuildLevelList( RDat* pRDat ) { + const static std::string legacyLvlPath = "data/level"; + DirectoryEntry* levelDir = nullptr; + + listLevel.clear(); + levelDir = dynamic_cast(pRDat->getElement(boost::filesystem::path(legacyLvlPath))); + if (levelDir != nullptr) { + for ( DatEntry* fl : levelDir->getFiles() ) { + if (fl->isDirectory()) { + if (pRDat->getElement(boost::filesystem::path(legacyLvlPath).append(fl->getName()).append("dat")) != nullptr) { + listLevel.push_back(legacyLvlPath + "/" + fl->getName()); + } + } + } + } + + //TODO: LvlClass builder +} + +void LegacyExplorer::BuildModelList( RDat* pRDat ) { + const static std::vector legacyModelPath = { + "data/pl_crafts", "data/reb_stuff", "data/imp_stuff", + "data/gnrc_stuff", "data2" + }; + DirectoryEntry* curModelDir = nullptr; + + listModel.clear(); + for ( std::string path_it : legacyModelPath ) { + curModelDir = dynamic_cast(pRDat->getElement(boost::filesystem::path(path_it))); + if (curModelDir != nullptr) { + for ( DatEntry* fl : curModelDir->getFiles() ) { + if (fl->getName().find("_HOB") != std::string::npos) { + listModel.push_back(path_it + "/" + fl->getName()); + } + } + } + } +} + +void LegacyExplorer::BuildTextureList( RDat* pRDat ) { } -LegacyExplorer::~LegacyExplorer() { - // TODO Auto-generated destructor stub +void LegacyExplorer::BuildMusicList( RDat* pRDat ) { + const static std::string legacyMusicPath = "data/sound"; + DirectoryEntry* musicDir = nullptr; + + listMusic.clear(); + musicDir = dynamic_cast(pRDat->getElement(boost::filesystem::path(legacyMusicPath))); + if (musicDir != nullptr) { + for ( DatEntry* fl : musicDir->getFiles() ) { + //TODO: MusyX-Class builder + + if (fl->getName().find("_SNG") != std::string::npos) { + listMusic.push_back(legacyMusicPath + "/" + fl->getName()); + } + } + } +} + +void LegacyExplorer::BuildSampleList( RDat* pRDat ) { + } } diff --git a/src/LegacyExplorer.h b/src/LegacyExplorer.h index 553cfb6..0dde00d 100644 --- a/src/LegacyExplorer.h +++ b/src/LegacyExplorer.h @@ -10,6 +10,14 @@ * */ +#include +#include +#include +#include "RDat.h" +#include "datfiles/GenericFile.h" +#include "datfiles/HMT.h" + + #ifndef LEGACYEXPLORER_H_ #define LEGACYEXPLORER_H_ @@ -17,8 +25,56 @@ namespace RDI { class LegacyExplorer final { public: - LegacyExplorer( RDat& pRDat ); + LegacyExplorer( RDat* pRDat ); ~LegacyExplorer(); + + /** + * Retrieve know list of legacy game files type. + * @return Array of filtered elements. + */ + ///@{ + std::vector getLevelsList() { return listLevel; } + std::vector getModelsList() { return listModel; } + std::vector getTexturesList() { return listTexture; } + std::vector getMusicsList() { return listMusic; } + std::vector getSamplesList() { return listSample; } + ///@} + + /** + * Obtain the class interface for datas in specified file type. + * @param name Name of the file, should be in list. + * @return File type class handler. + */ + ///@{ + void* getLevel( std::string name ); + void* getModel( std::string name ); + HMT *getTexture( std::string name ); + void* getMusic( std::string name ); + void* getSample( std::string name ); + ///@} + + /** + * @brief Retrieve default file instance. + * @details Unknown file type can be wrapped in dummy class to access raw + * content without parsing or other type of processing. + * + * @param[in] vPath Virtual path to the file. + * @return Generic file type class handler. + */ + GenericFile *getFile( boost::filesystem::path vPath ); + +private: + std::vector listLevel; + std::vector listModel; + std::vector listTexture; + std::vector listMusic; + std::vector listSample; + + void BuildLevelList( RDat* pRDat ); + void BuildModelList( RDat* pRDat ); + void BuildTextureList( RDat* pRDat ); + void BuildMusicList( RDat* pRDat ); + void BuildSampleList( RDat* pRDat ); }; } diff --git a/src/RDI.cpp b/src/RDI.cpp index 93fe10a..1e62b1d 100644 --- a/src/RDI.cpp +++ b/src/RDI.cpp @@ -18,6 +18,7 @@ #include "config.h" #include "RDat.h" #include "DatEntry.h" +#include "LegacyExplorer.h" #include "RDI.h" @@ -25,6 +26,7 @@ * Internal variable */ static RDI::RDat *hRDat = nullptr; +static RDI::LegacyExplorer *hLegacyExp = nullptr; /* * Libs interface @@ -38,6 +40,12 @@ void RDI::CreateRDatHandler( std::string roguePath ){ //return hRDat; } +void RDI::CreateLegacyHandler( void ){ + if (hRDat != nullptr) hLegacyExp = new RDI::LegacyExplorer(hRDat); + + //return hLegacyExp; +} + unsigned char RDI::getSectionCount() { if (hRDat == nullptr) return 0; @@ -95,6 +103,22 @@ bool RDI::isElementDirectory( std::string path ) { } +std::vector RDI::getLevelsName( void ) { + return hLegacyExp->getLevelsList(); +} + +std::vector RDI::getModelsName( void ) { + return hLegacyExp->getModelsList(); +} + +std::vector RDI::getMusicsName( void ) { + return hLegacyExp->getMusicsList(); +} + void RDI::DestroyRDatHandler(){ if (hRDat) delete hRDat; } + +void RDI::DestroyLegacyHandler(){ + if (hLegacyExp) delete hLegacyExp; +} diff --git a/src/datfiles/GenericFile.cpp b/src/datfiles/GenericFile.cpp new file mode 100644 index 0000000..5cbf8bd --- /dev/null +++ b/src/datfiles/GenericFile.cpp @@ -0,0 +1,25 @@ +/** + * @file GenericFile.cpp + * @date 23/09/2022 + * @author JackCarterSmith + * @copyright GPL-v3.0 + * @brief Generic file object class. + * + */ + +#include +#include "../DatEntry.h" +#include "GenericFile.h" + +namespace RDI { + +GenericFile::GenericFile( FileEntry& hDat ) { + this->size = hDat.getSize(); + this->fileName = hDat.getName(); + this->fileExtension = ""; + this->pMemLoc = hDat.getDatas(); +} + +GenericFile::~GenericFile() {} + +} diff --git a/src/datfiles/GenericFile.h b/src/datfiles/GenericFile.h new file mode 100644 index 0000000..1475e6d --- /dev/null +++ b/src/datfiles/GenericFile.h @@ -0,0 +1,34 @@ +/** + * @file GenericFile.h + * @date 23/09/2022 + * @author JackCarterSmith + * @copyright GPL-v3.0 + * @brief Generic file object class. + * + */ + +#include +#include "../DatEntry.h" + + +#ifndef GENERICFILE_H_ +#define GENERICFILE_H_ + +namespace RDI { + +class GenericFile { +public: + GenericFile( FileEntry& hDat ); + virtual ~GenericFile(); + + MEMFILE get() { return pMemLoc; } + +protected: + unsigned long size; + std::string fileName, fileExtension; + MEMFILE pMemLoc = nullptr; +}; + +} + +#endif /* GENERICFILE_H_ */ diff --git a/src/datfiles/HMT.cpp b/src/datfiles/HMT.cpp index 77ed7eb..5bc0586 100644 --- a/src/datfiles/HMT.cpp +++ b/src/datfiles/HMT.cpp @@ -7,17 +7,16 @@ * */ +#include "GenericFile.h" #include "HMT.h" + namespace RDI { -HMT::HMT() { - // TODO Auto-generated constructor stub - +HMT::HMT( FileEntry& hDat ): GenericFile( hDat ) { + this->fileExtension = "hmt"; } -HMT::~HMT() { - // TODO Auto-generated destructor stub -} +HMT::~HMT() {} -} /* namespace RDI */ +} diff --git a/src/datfiles/HMT.h b/src/datfiles/HMT.h index c6c8cb7..e4d108e 100644 --- a/src/datfiles/HMT.h +++ b/src/datfiles/HMT.h @@ -7,17 +7,20 @@ * */ -#ifndef SRC_DATFILES_HMT_H_ -#define SRC_DATFILES_HMT_H_ +#include "GenericFile.h" + + +#ifndef HMT_H_ +#define HMT_H_ namespace RDI { -class HMT { +class HMT : public GenericFile { public: - HMT(); + HMT( FileEntry& hDat ); virtual ~HMT(); }; -} /* namespace RDI */ +} -#endif /* SRC_DATFILES_HMT_H_ */ +#endif /* HMT_H_ */ diff --git a/tools/RDIdebug.cpp b/tools/RDIdebug.cpp index 61a7e30..6887aca 100644 --- a/tools/RDIdebug.cpp +++ b/tools/RDIdebug.cpp @@ -46,6 +46,17 @@ int main( int argc, char *argv[] ) { PrintVirtualDirectoryContents(pathBuilder, prefix); } + RDI::CreateLegacyHandler(); + for ( std::string lname : RDI::getLevelsName() ) { + printf("Level found: %s\n", lname.c_str()); + } + for ( std::string mdname : RDI::getModelsName() ) { + printf("Model found: %s\n", mdname.c_str()); + } + for ( std::string mname : RDI::getMusicsName() ) { + printf("Music found: %s\n", mname.c_str()); + } + RDI::DestroyRDatHandler(); return 0; -- 2.39.5 From c33ee14f368e393de94126410beaac9be3cfd3b6 Mon Sep 17 00:00:00 2001 From: JackCarterSmith Date: Thu, 29 Sep 2022 09:47:13 +0200 Subject: [PATCH 3/9] Cmake findpackage linux fix --- CMakeLists.txt | 23 +++++++++++------------ 1 file changed, 11 insertions(+), 12 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 2f61fb5..937abdf 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -15,18 +15,6 @@ if(DEFINED ENV{MS_COMPATIBLE}) endif() -# Import needed packages and references their include path -find_package(RSPModel 2.2 REQUIRED) -include_directories(${RSPModel_INCLUDE_DIR}) -find_package(RSPTerrain 2.0 REQUIRED) -include_directories(${RSPTerrain_INCLUDE_DIR}) -find_package(RSPTexture 2.1 REQUIRED) -include_directories(${RSPTexture_INCLUDE_DIR}) -find_package(Boost 1.80.0 EXACT REQUIRED) -include_directories(${Boost_INCLUDE_DIR}) -add_definitions(-DBOOST_ALL_NO_LIB) - - # Project definition if(DEFINED ENV{CI}) # Jenkins CI integration mode project(rdi VERSION $ENV{CI_VERSION}.$ENV{CI_BUILD_NUMBER} DESCRIPTION "Rogue Data Interface" LANGUAGES C CXX) @@ -49,6 +37,17 @@ option(RDI_SHARED "Build shared lib" ON) option(RDI_STATIC "Build static lib" ON) option(BUILD_TOOLS "Build lib tools" ON) +# Import needed packages and references their include path +find_package(RSPModel 2.2 REQUIRED) +include_directories(${RSPModel_INCLUDE_DIR}) +find_package(RSPTerrain 2.0 REQUIRED) +include_directories(${RSPTerrain_INCLUDE_DIR}) +find_package(RSPTexture 2.1 REQUIRED) +include_directories(${RSPTexture_INCLUDE_DIR}) +find_package(Boost 1.80.0 EXACT REQUIRED) +include_directories(${Boost_INCLUDE_DIR}) +add_definitions(-DBOOST_ALL_NO_LIB) + # Push compile infos to source configure_file(${CMAKE_CURRENT_SOURCE_DIR}/config.h.in ${CMAKE_CURRENT_SOURCE_DIR}/src/config.h @ONLY) -- 2.39.5 From b21372d1b9bcb0e57c64ffab8eaed51b8b079821 Mon Sep 17 00:00:00 2001 From: JackCarterSmith Date: Sat, 24 Sep 2022 15:28:16 +0200 Subject: [PATCH 4/9] Reforge library structure - 1st pass --- CMakeLists.txt | 25 ++++- .../FileHandler/Generic.h | 6 +- {src/datfiles => include/FileHandler}/HMT.h | 4 +- include/{RDI.h => RDI.hpp} | 12 ++- src/DatEntry.cpp | 68 ------------- src/{RDat.cpp => Erso.cpp} | 56 +++++------ src/{RDat.h => Erso.hpp} | 33 ++++--- src/ErsoEntry.cpp | 68 +++++++++++++ src/{DatEntry.h => ErsoEntry.hpp} | 40 ++++---- src/Krennic.cpp | 98 +++++++++++++++++++ src/{LegacyExplorer.h => Krennic.hpp} | 36 +++---- ...ericFile.cpp => KrennicHandlerGeneric.cpp} | 6 +- .../HMT.cpp => KrennicHandlerHMT.cpp} | 6 +- src/LegacyExplorer.cpp | 98 ------------------- src/RDI.cpp | 60 ++++++------ src/{ => files_mms}/bundle_struct.h | 0 src/{ => files_mms}/data_struct.h | 0 tools/ErsoDebug.cpp | 16 +++ tools/KrennicDebug.cpp | 16 +++ tools/RDIdebug.cpp | 2 +- 20 files changed, 354 insertions(+), 296 deletions(-) rename src/datfiles/GenericFile.h => include/FileHandler/Generic.h (83%) rename {src/datfiles => include/FileHandler}/HMT.h (81%) rename include/{RDI.h => RDI.hpp} (93%) delete mode 100644 src/DatEntry.cpp rename src/{RDat.cpp => Erso.cpp} (80%) rename src/{RDat.h => Erso.hpp} (63%) create mode 100644 src/ErsoEntry.cpp rename src/{DatEntry.h => ErsoEntry.hpp} (60%) create mode 100644 src/Krennic.cpp rename src/{LegacyExplorer.h => Krennic.hpp} (73%) rename src/{datfiles/GenericFile.cpp => KrennicHandlerGeneric.cpp} (76%) rename src/{datfiles/HMT.cpp => KrennicHandlerHMT.cpp} (63%) delete mode 100644 src/LegacyExplorer.cpp rename src/{ => files_mms}/bundle_struct.h (100%) rename src/{ => files_mms}/data_struct.h (100%) create mode 100644 tools/ErsoDebug.cpp create mode 100644 tools/KrennicDebug.cpp diff --git a/CMakeLists.txt b/CMakeLists.txt index 937abdf..d8497ae 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -64,7 +64,7 @@ unset(RDI_TARGETS_LIST) # Define src/headers files file(GLOB_RECURSE RDI_LIB_SOURCES ./src/*.cpp ./src/*.c) source_group("Source Files" FILES ${RDI_LIB_SOURCES}) -file(GLOB RSP_LIB_PUBLIC_HRDS ./include/*.h) +file(GLOB_RECURSE RSP_LIB_PUBLIC_HRDS ./include/*.hpp ./include/*.h) # Building instructions for RSP-Texture library @@ -148,24 +148,41 @@ endif() if(BUILD_TOOLS) # Add lib debug tool to buildchain - file(GLOB_RECURSE RDI_TOOLS_SOURCES ./tools/*.cpp ./tools/*.c) - source_group("Tools src files" FILES ${RDI_TOOLS_SOURCES}) + #file(GLOB_RECURSE RDI_TOOLS_SOURCES ./tools/*.cpp ./tools/*.c) + #source_group("Tools src files" FILES ${RDI_TOOLS_SOURCES}) - add_executable(rdi-debug-tools ${RDI_TOOLS_SOURCES}) + #add_executable(rdi-debug-tools ${RDI_TOOLS_SOURCES}) + add_executable(rdi-debug-tools ./tools/RDIDebug.cpp) set_property(TARGET rdi-debug-tools PROPERTY C_STANDARD 90) set_target_properties(rdi-debug-tools PROPERTIES OUTPUT_NAME "RDI-debug") list(APPEND RDI_TARGETS_LIST rdi-debug-tools) + add_executable(erso-debug-tools ./tools/ErsoDebug.cpp) + set_property(TARGET erso-debug-tools PROPERTY C_STANDARD 90) + set_target_properties(erso-debug-tools PROPERTIES OUTPUT_NAME "Erso-debug") + list(APPEND RDI_TARGETS_LIST erso-debug-tools) + + add_executable(krennic-debug-tools ./tools/KrennicDebug.cpp) + set_property(TARGET krennic-debug-tools PROPERTY C_STANDARD 90) + set_target_properties(krennic-debug-tools PROPERTIES OUTPUT_NAME "Krennic-debug") + list(APPEND RDI_TARGETS_LIST krennic-debug-tools) + if(MSVC) # msvc does not append 'lib' - do it here to have consistent name set_target_properties(rdi-debug-tools PROPERTIES IMPORT_PREFIX "lib") + set_target_properties(erso-debug-tools PROPERTIES IMPORT_PREFIX "lib") + set_target_properties(krennic-debug-tools PROPERTIES IMPORT_PREFIX "lib") endif() if(RDI_SHARED) target_link_libraries(rdi-debug-tools PRIVATE rdi-lib) + 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(erso-debug-tools PRIVATE rdi-libstatic) + target_link_libraries(krennic-debug-tools PRIVATE rdi-libstatic) endif() endif() diff --git a/src/datfiles/GenericFile.h b/include/FileHandler/Generic.h similarity index 83% rename from src/datfiles/GenericFile.h rename to include/FileHandler/Generic.h index 1475e6d..bd2f152 100644 --- a/src/datfiles/GenericFile.h +++ b/include/FileHandler/Generic.h @@ -7,8 +7,8 @@ * */ +#include "../RDI_Datatypes.h" #include -#include "../DatEntry.h" #ifndef GENERICFILE_H_ @@ -16,9 +16,11 @@ namespace RDI { +class ErsoEntryFile; + class GenericFile { public: - GenericFile( FileEntry& hDat ); + GenericFile( ErsoEntryFile& hDat ); virtual ~GenericFile(); MEMFILE get() { return pMemLoc; } diff --git a/src/datfiles/HMT.h b/include/FileHandler/HMT.h similarity index 81% rename from src/datfiles/HMT.h rename to include/FileHandler/HMT.h index e4d108e..cc0e59c 100644 --- a/src/datfiles/HMT.h +++ b/include/FileHandler/HMT.h @@ -7,7 +7,7 @@ * */ -#include "GenericFile.h" +#include #ifndef HMT_H_ @@ -17,7 +17,7 @@ namespace RDI { class HMT : public GenericFile { public: - HMT( FileEntry& hDat ); + HMT( ErsoEntryFile& hDat ); virtual ~HMT(); }; diff --git a/include/RDI.h b/include/RDI.hpp similarity index 93% rename from include/RDI.h rename to include/RDI.hpp index cdb1d81..0399849 100644 --- a/include/RDI.h +++ b/include/RDI.hpp @@ -1,17 +1,19 @@ /** - * @file RDI.h - * @date 15/09/2022 + * @file RDI.hpp + * @date 24/09/2022 * @author JackCarterSmith * @copyright GPL-v3.0 * @brief Rogue Data Interface library main entry file. * */ +#include +#include #include "RDI_Datatypes.h" -#ifndef RDI_H_ -#define RDI_H_ +#ifndef RDI_HPP_ +#define RDI_HPP_ #if defined(_MSC_VER) @@ -81,4 +83,4 @@ namespace RDI { } -#endif /* RDI_H_ */ +#endif /* RDI_HPP_ */ diff --git a/src/DatEntry.cpp b/src/DatEntry.cpp deleted file mode 100644 index 354c21a..0000000 --- a/src/DatEntry.cpp +++ /dev/null @@ -1,68 +0,0 @@ -/** - * @file DatEntry.cpp - * @date 20/09/2022 - * @author JackCarterSmith - * @copyright GPL-v3.0 - * @brief Data file entry descriptor class. - * - */ - -#include "DatEntry.h" - - -namespace RDI { - -FileEntry::FileEntry( 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; -} - -FileEntry::~FileEntry() {} - -/*std::string FileEntry::toString() { - -}*/ - - -DirectoryEntry::DirectoryEntry( std::string name ) { - this->name = name; - this->fFlags.raw = 0; - this->rootDir = true; - vSubFiles = new std::vector; -} - -DirectoryEntry::DirectoryEntry( std::string name, DAT_FILE_FLAGS fFlags ) { - this->name = name; - this->fFlags.raw = fFlags.raw; - this->rootDir = false; - vSubFiles = new std::vector; -} - -DirectoryEntry::DirectoryEntry( std::string name, DAT_FILE_FLAGS fFlags, DatEntry* hFileEntry ) { - this->name = name; - this->fFlags.raw = fFlags.raw; - vSubFiles = new std::vector; - AddEntry(hFileEntry); -} - -DirectoryEntry::~DirectoryEntry() { - for ( DatEntry* e : *vSubFiles ) - delete e; - delete vSubFiles; -} - -/*std::string DirectoryEntry::toString() { - -}*/ - -void DirectoryEntry::ClearLinkedFiles() { - vSubFiles->clear(); -} - -void DirectoryEntry::AddEntry( DatEntry* hFileEntry ) { - vSubFiles->push_back(hFileEntry); -} - -} diff --git a/src/RDat.cpp b/src/Erso.cpp similarity index 80% rename from src/RDat.cpp rename to src/Erso.cpp index 0ab3197..dd53823 100644 --- a/src/RDat.cpp +++ b/src/Erso.cpp @@ -1,9 +1,9 @@ /** - * @file RDat.cpp - * @date 20/09/2022 + * @file Erso.cpp + * @date 24/09/2022 * @author JackCarterSmith * @copyright GPL-v3.0 - * @brief Rogue Dat file class interface. + * @brief Rogue DATA/BUNDLE file parser and interface. * */ @@ -13,9 +13,9 @@ #include #include #include -#include "DatEntry.h" -#include "data_struct.h" -#include "RDat.h" +#include "files_mms/data_struct.h" +#include "Erso.hpp" +#include "ErsoEntry.hpp" using std::string; @@ -27,7 +27,7 @@ using boost::filesystem::file_size; namespace RDI { -RDat::RDat( string fPath ) { +Erso::Erso( string fPath ) { RDI_RESULT errCode = RDI_OK; this->workingDir = fPath; @@ -46,23 +46,23 @@ RDat::RDat( string fPath ) { ProcessFilesTree(); } -RDat::~RDat() { - for ( DirectoryEntry* de : *pFTRoot ) +Erso::~Erso() { + for ( ErsoEntryDir* de : *pFTRoot ) delete de; delete pFTRoot; free(rDatPtr); delete pDatSection; } -string RDat::getDataSectionName( unsigned char id ) { return pDatSection->at(id).name; } -unsigned int RDat::getDataSectionOffset( unsigned char id ) { return pDatSection->at(id).offset; } +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 RDat::DumpLegacyFiles() { +RDI_RESULT Erso::DumpLegacyFiles() { unsigned int i; path fp(workingDir); MEMFILE pTmpFile; @@ -103,7 +103,7 @@ RDI_RESULT RDat::DumpLegacyFiles() { * * @return Start memory pointer of the file. */ -MEMFILE RDat::MallocFile( path filePath ) { +MEMFILE Erso::MallocFile( path filePath ) { const unsigned int size = file_size(filePath); std::fstream rdf; MEMFILE fPtr = NULL; @@ -123,16 +123,16 @@ MEMFILE RDat::MallocFile( path filePath ) { * * @return Error status. */ -RDI_RESULT RDat::ProcessFilesTree() { +RDI_RESULT Erso::ProcessFilesTree() { unsigned int curEntriesCount = 0, i; - DirectoryEntry* curDir = nullptr; + ErsoEntryDir* curDir = nullptr; MEMFILE pFileDescriptors = nullptr; // Create new root files tree. One per data section. - pFTRoot = new std::vector; + pFTRoot = new std::vector; pFTRoot->clear(); for ( i = 0; i < cDatSection; i++ ) { - curDir = new DirectoryEntry(pDatSection->at(i).name); + curDir = new ErsoEntryDir(pDatSection->at(i).name); pFTRoot->push_back(curDir); // Recalculate files descriptor offset for current section. @@ -147,12 +147,12 @@ RDI_RESULT RDat::ProcessFilesTree() { return RDI_OK; } -RDI_RESULT RDat::ProcessDirectoryContents( DirectoryEntry* pCurDir, MEMFILE pDesc, const unsigned int count, MEMFILE pSectionStart ) { +RDI_RESULT Erso::ProcessDirectoryContents( ErsoEntryDir* pCurDir, MEMFILE pDesc, const unsigned int count, MEMFILE pSectionStart ) { unsigned int i, newDRECnt; DAT_FILE_FLAGS curEntryFlags = {0}; - FileEntry* newFile = nullptr; - DirectoryEntry* newDir = nullptr; + ErsoEntryFile* newFile = nullptr; + ErsoEntryDir* newDir = nullptr; std::string tmpStr; if ( count == 0) return RDI_ERROR_PROCESS; @@ -165,12 +165,12 @@ RDI_RESULT RDat::ProcessDirectoryContents( DirectoryEntry* pCurDir, MEMFILE pDes // Test for file or directory if (!curEntryFlags.isDirectory) { - newFile = new FileEntry(tmpStr, curEntryFlags, + newFile = new ErsoEntryFile(tmpStr, curEntryFlags, ((T_FILE_HEADER*)(pDesc + i * sizeof(T_FILE_HEADER)))->datas_size, pSectionStart + ((T_FILE_HEADER*)(pDesc + i * sizeof(T_FILE_HEADER)))->datas_offset); pCurDir->AddEntry(newFile); } else { - newDir = new DirectoryEntry(tmpStr, curEntryFlags); + newDir = new ErsoEntryDir(tmpStr, curEntryFlags); pCurDir->AddEntry(newDir); // Keep entries count in new directory to jump over after processing it. @@ -183,11 +183,11 @@ RDI_RESULT RDat::ProcessDirectoryContents( DirectoryEntry* pCurDir, MEMFILE pDes return RDI_OK; } -DatEntry *RDat::getElement( boost::filesystem::path virtualDirPath ) { +ErsoEntry *Erso::getElement( boost::filesystem::path virtualDirPath ) { bool skip = false; boost::filesystem::path newPath; - for ( DatEntry* de : *pFTRoot ) { + for ( ErsoEntry* de : *pFTRoot ) { if (virtualDirPath.size() == 1 || virtualDirPath.begin() == --virtualDirPath.end()) { if (de->getName() == virtualDirPath.filename().string()) return de; @@ -198,7 +198,7 @@ DatEntry *RDat::getElement( boost::filesystem::path virtualDirPath ) { newPath.append(sp); skip = true; } - return SearchSectionForEntry(dynamic_cast(de), newPath); + return SearchSectionForEntry(dynamic_cast(de), newPath); } } } @@ -206,11 +206,11 @@ DatEntry *RDat::getElement( boost::filesystem::path virtualDirPath ) { return nullptr; } -DatEntry *RDat::SearchSectionForEntry( DirectoryEntry *curDir, boost::filesystem::path virtualDirPath ) { +ErsoEntry *Erso::SearchSectionForEntry( ErsoEntryDir *curDir, boost::filesystem::path virtualDirPath ) { bool skip = false; boost::filesystem::path newPath; - for ( DatEntry* e : curDir->getFiles() ) { + for ( ErsoEntry* e : curDir->getFiles() ) { if (virtualDirPath.size() == 1 || virtualDirPath.begin() == --virtualDirPath.end()) { if (e->getName() == virtualDirPath.filename().string()) return e; @@ -222,7 +222,7 @@ DatEntry *RDat::SearchSectionForEntry( DirectoryEntry *curDir, boost::filesystem skip = true; } //TODO: add safety when trying to access inside a file - return SearchSectionForEntry(dynamic_cast(e), newPath); + return SearchSectionForEntry(dynamic_cast(e), newPath); } } } diff --git a/src/RDat.h b/src/Erso.hpp similarity index 63% rename from src/RDat.h rename to src/Erso.hpp index 1c1d476..d39f7cc 100644 --- a/src/RDat.h +++ b/src/Erso.hpp @@ -1,20 +1,20 @@ /** - * @file RDat.h - * @date 15/09/2022 + * @file Erso.hpp + * @date 24/09/2022 * @author JackCarterSmith * @copyright GPL-v3.0 - * @brief Rogue Dat file class interface. + * @brief Rogue DATA/BUNDLE file parser and interface. * */ #include #include -#include "DatEntry.h" #include "RDI_Datatypes.h" +#include "ErsoEntry.hpp" -#ifndef RDAT_H_ -#define RDAT_H_ +#ifndef ERSO_HPP_ +#define ERSO_HPP_ namespace RDI { @@ -23,10 +23,15 @@ struct dataSection { unsigned int offset = 0; }; -class RDat final { +/** + * Erso is class codename of the DATA/BUNDLE file parser of RDI library. + * + * @pre RDI should construct Erso class before doing anything on datas. + */ +class Erso final { public: - RDat( std::string fPath ); - ~RDat(); + Erso( std::string fPath ); + ~Erso(); MEMFILE getRDat() { return rDatPtr; @@ -39,7 +44,7 @@ public: std::string getDataSectionName( unsigned char id ); unsigned int getDataSectionOffset( unsigned char id ); - DatEntry *getElement( boost::filesystem::path virtualDirPath ); + ErsoEntry *getElement( boost::filesystem::path virtualDirPath ); private: std::string workingDir = "."; @@ -48,24 +53,24 @@ private: std::vector *pDatSection = nullptr; MEMFILE rDatPtr = nullptr; - std::vector *pFTRoot = nullptr; + std::vector *pFTRoot = nullptr; /* File processing methods */ RDI_RESULT DumpLegacyFiles(); MEMFILE MallocFile( boost::filesystem::path filePath ); RDI_RESULT ProcessFilesTree(); RDI_RESULT ProcessDirectoryContents( - DirectoryEntry* pCurDir, + ErsoEntryDir* pCurDir, MEMFILE pDesc, const unsigned int count, MEMFILE pSectionStart ); /* Tree manipulation/parse methods */ - DatEntry *SearchSectionForEntry( DirectoryEntry *curDir, boost::filesystem::path virtualDirPath); + ErsoEntry *SearchSectionForEntry( ErsoEntryDir *curDir, boost::filesystem::path virtualDirPath); }; } /* namespace RDI */ -#endif /* RDAT_H_ */ +#endif /* ERSO_HPP_ */ diff --git a/src/ErsoEntry.cpp b/src/ErsoEntry.cpp new file mode 100644 index 0000000..52ff513 --- /dev/null +++ b/src/ErsoEntry.cpp @@ -0,0 +1,68 @@ +/** + * @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; +} + +ErsoEntryDir::ErsoEntryDir( std::string name, DAT_FILE_FLAGS fFlags ) { + this->name = name; + this->fFlags.raw = fFlags.raw; + this->rootDir = false; + vSubFiles = new std::vector; +} + +ErsoEntryDir::ErsoEntryDir( std::string name, DAT_FILE_FLAGS fFlags, ErsoEntry* hFileEntry ) { + this->name = name; + this->fFlags.raw = fFlags.raw; + vSubFiles = new std::vector; + 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); +} + +} diff --git a/src/DatEntry.h b/src/ErsoEntry.hpp similarity index 60% rename from src/DatEntry.h rename to src/ErsoEntry.hpp index 119ed75..5c6ac88 100644 --- a/src/DatEntry.h +++ b/src/ErsoEntry.hpp @@ -1,19 +1,19 @@ /** - * @file DatEntry.h - * @date 20/09/2022 + * @file ErsoEntry.hpp + * @date 24/09/2022 * @author JackCarterSmith * @copyright GPL-v3.0 * @brief Data file entry descriptor class. * */ -#include "RDI_Datatypes.h" +#include #include #include -#ifndef DATENTRY_H_ -#define DATENTRY_H_ +#ifndef ERSOENTRY_HPP_ +#define ERSOENTRY_HPP_ namespace RDI { @@ -33,9 +33,9 @@ typedef union u_file_flags { -class DatEntry { +class ErsoEntry { public: - virtual ~DatEntry() = 0; + virtual ~ErsoEntry() = 0; virtual bool isDirectory() = 0; virtual bool isRootDirectory() = 0; //virtual std::string toString() = 0; @@ -48,12 +48,12 @@ protected: DAT_FILE_FLAGS fFlags; }; -inline DatEntry::~DatEntry() {} +inline ErsoEntry::~ErsoEntry() {} -class FileEntry : public DatEntry { +class ErsoEntryFile : public ErsoEntry { public: - FileEntry( std::string name, DAT_FILE_FLAGS fFlags, unsigned int size, MEMFILE fPtr ); - ~FileEntry(); + ErsoEntryFile( std::string name, DAT_FILE_FLAGS fFlags, unsigned int size, MEMFILE fPtr ); + ~ErsoEntryFile(); MEMFILE getDatas() { return fileMemPtr; } @@ -68,16 +68,16 @@ private: }; -class DirectoryEntry : public DatEntry { +class ErsoEntryDir : public ErsoEntry { public: - DirectoryEntry( std::string name ); - DirectoryEntry( std::string name, DAT_FILE_FLAGS fFlags ); - DirectoryEntry( std::string name, DAT_FILE_FLAGS fFlags, DatEntry* hFileEntry ); - ~DirectoryEntry(); + 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( DatEntry* hFileEntry ); - std::vector getFiles() { return *vSubFiles; } + void AddEntry( ErsoEntry* hFileEntry ); + std::vector getFiles() { return *vSubFiles; } //std::string toString(); bool isDirectory() { return true; } @@ -86,9 +86,9 @@ public: private: bool rootDir; - std::vector *vSubFiles; + std::vector *vSubFiles; }; } -#endif /* DATENTRY_H_ */ +#endif /* ERSODATENTRY_HPP_ */ diff --git a/src/Krennic.cpp b/src/Krennic.cpp new file mode 100644 index 0000000..5a447e2 --- /dev/null +++ b/src/Krennic.cpp @@ -0,0 +1,98 @@ +/** + * @file Krennic.cpp + * @date 24/09/2022 + * @author JackCarterSmith + * @copyright GPL-v3.0 + * @brief Main game assets parser and interface. + * + * Complete class would take Erso legacy files tree and extract levels, objects, + * textures, animations, etc. adapted datas for OpenGL/Direct3D application. + * + */ + +#include +#include +#include +#include +#include "Erso.hpp" +#include "Krennic.hpp" + + +namespace RDI { + +Krennic::Krennic( Erso* pErso ) { + BuildLevelList(pErso); + BuildModelList(pErso); + BuildTextureList(pErso); + BuildMusicList(pErso); + BuildSampleList(pErso); +} + +Krennic::~Krennic() {} + + +void Krennic::BuildLevelList( Erso* pErso ) { + const static std::string legacyLvlPath = "data/level"; + ErsoEntryDir* levelDir = nullptr; + + listLevel.clear(); + levelDir = dynamic_cast(pErso->getElement(boost::filesystem::path(legacyLvlPath))); + if (levelDir != nullptr) { + for ( ErsoEntry* 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()); + } + } + } + } + + //TODO: LvlClass builder +} + +void Krennic::BuildModelList( Erso* pErso ) { + const static std::vector legacyModelPath = { + "data/pl_crafts", "data/reb_stuff", "data/imp_stuff", + "data/gnrc_stuff", "data2" + }; + ErsoEntryDir* curModelDir = nullptr; + + listModel.clear(); + for ( std::string path_it : legacyModelPath ) { + curModelDir = dynamic_cast(pErso->getElement(boost::filesystem::path(path_it))); + if (curModelDir != nullptr) { + for ( ErsoEntry* fl : curModelDir->getFiles() ) { + if (fl->getName().find("_HOB") != std::string::npos) { + listModel.push_back(path_it + "/" + fl->getName()); + } + } + } + } +} + +void Krennic::BuildTextureList( Erso* pErso ) { + +} + +void Krennic::BuildMusicList( Erso* pErso ) { + const static std::string legacyMusicPath = "data/sound"; + ErsoEntryDir* musicDir = nullptr; + + listMusic.clear(); + musicDir = dynamic_cast(pErso->getElement(boost::filesystem::path(legacyMusicPath))); + if (musicDir != nullptr) { + for ( ErsoEntry* fl : musicDir->getFiles() ) { + //TODO: MusyX-Class builder + + if (fl->getName().find("_SNG") != std::string::npos) { + listMusic.push_back(legacyMusicPath + "/" + fl->getName()); + } + } + } +} + +void Krennic::BuildSampleList( Erso* pErso ) { + +} + +} diff --git a/src/LegacyExplorer.h b/src/Krennic.hpp similarity index 73% rename from src/LegacyExplorer.h rename to src/Krennic.hpp index 0dde00d..ee74fb8 100644 --- a/src/LegacyExplorer.h +++ b/src/Krennic.hpp @@ -1,11 +1,11 @@ /** - * @file LegacyExplorer.h - * @date 22/09/2022 + * @file Krennic.hpp + * @date 24/09/2022 * @author JackCarterSmith * @copyright GPL-v3.0 - * @brief Main game resources interface. + * @brief Main game assets parser and interface. * - * Complete class would take legacy RDat files tree and extract levels, objects, + * Complete class would take Erso legacy files tree and extract levels, objects, * textures, animations, etc. adapted datas for OpenGL/Direct3D application. * */ @@ -13,20 +13,20 @@ #include #include #include -#include "RDat.h" -#include "datfiles/GenericFile.h" -#include "datfiles/HMT.h" +#include +#include +#include "Erso.hpp" -#ifndef LEGACYEXPLORER_H_ -#define LEGACYEXPLORER_H_ +#ifndef KRENNIC_HPP_ +#define KRENNIC_HPP_ namespace RDI { -class LegacyExplorer final { +class Krennic final { public: - LegacyExplorer( RDat* pRDat ); - ~LegacyExplorer(); + Krennic( Erso* pErso ); + ~Krennic(); /** * Retrieve know list of legacy game files type. @@ -70,13 +70,13 @@ private: std::vector listMusic; std::vector listSample; - void BuildLevelList( RDat* pRDat ); - void BuildModelList( RDat* pRDat ); - void BuildTextureList( RDat* pRDat ); - void BuildMusicList( RDat* pRDat ); - void BuildSampleList( RDat* pRDat ); + void BuildLevelList( Erso* pErso ); + void BuildModelList( Erso* pErso ); + void BuildTextureList( Erso* pErso ); + void BuildMusicList( Erso* pErso ); + void BuildSampleList( Erso* pErso ); }; } -#endif /* LEGACYEXPLORER_H_ */ +#endif /* KRENNIC_HPP_ */ diff --git a/src/datfiles/GenericFile.cpp b/src/KrennicHandlerGeneric.cpp similarity index 76% rename from src/datfiles/GenericFile.cpp rename to src/KrennicHandlerGeneric.cpp index 5cbf8bd..54bf350 100644 --- a/src/datfiles/GenericFile.cpp +++ b/src/KrennicHandlerGeneric.cpp @@ -8,12 +8,12 @@ */ #include -#include "../DatEntry.h" -#include "GenericFile.h" +#include +#include "ErsoEntry.hpp" namespace RDI { -GenericFile::GenericFile( FileEntry& hDat ) { +GenericFile::GenericFile( ErsoEntryFile& hDat ) { this->size = hDat.getSize(); this->fileName = hDat.getName(); this->fileExtension = ""; diff --git a/src/datfiles/HMT.cpp b/src/KrennicHandlerHMT.cpp similarity index 63% rename from src/datfiles/HMT.cpp rename to src/KrennicHandlerHMT.cpp index 5bc0586..66baf43 100644 --- a/src/datfiles/HMT.cpp +++ b/src/KrennicHandlerHMT.cpp @@ -7,13 +7,13 @@ * */ -#include "GenericFile.h" -#include "HMT.h" +#include +#include namespace RDI { -HMT::HMT( FileEntry& hDat ): GenericFile( hDat ) { +HMT::HMT( ErsoEntryFile& hDat ): GenericFile( hDat ) { this->fileExtension = "hmt"; } diff --git a/src/LegacyExplorer.cpp b/src/LegacyExplorer.cpp deleted file mode 100644 index 7fb56bc..0000000 --- a/src/LegacyExplorer.cpp +++ /dev/null @@ -1,98 +0,0 @@ -/** - * @file LegacyExplorer.cpp - * @date 22/09/2022 - * @author JackCarterSmith - * @copyright GPL-v3.0 - * @brief Main game resources interface. - * - * Complete class would take legacy RDat files tree and extract levels, objects, - * textures, animations, etc. adapted datas for OpenGL/Direct3D application. - * - */ - -#include -#include -#include -#include -#include "RDat.h" -#include "LegacyExplorer.h" - - -namespace RDI { - -LegacyExplorer::LegacyExplorer( RDat* pRDat ) { - BuildLevelList(pRDat); - BuildModelList(pRDat); - BuildTextureList(pRDat); - BuildMusicList(pRDat); - BuildSampleList(pRDat); -} - -LegacyExplorer::~LegacyExplorer() {} - - -void LegacyExplorer::BuildLevelList( RDat* pRDat ) { - const static std::string legacyLvlPath = "data/level"; - DirectoryEntry* levelDir = nullptr; - - listLevel.clear(); - levelDir = dynamic_cast(pRDat->getElement(boost::filesystem::path(legacyLvlPath))); - if (levelDir != nullptr) { - for ( DatEntry* fl : levelDir->getFiles() ) { - if (fl->isDirectory()) { - if (pRDat->getElement(boost::filesystem::path(legacyLvlPath).append(fl->getName()).append("dat")) != nullptr) { - listLevel.push_back(legacyLvlPath + "/" + fl->getName()); - } - } - } - } - - //TODO: LvlClass builder -} - -void LegacyExplorer::BuildModelList( RDat* pRDat ) { - const static std::vector legacyModelPath = { - "data/pl_crafts", "data/reb_stuff", "data/imp_stuff", - "data/gnrc_stuff", "data2" - }; - DirectoryEntry* curModelDir = nullptr; - - listModel.clear(); - for ( std::string path_it : legacyModelPath ) { - curModelDir = dynamic_cast(pRDat->getElement(boost::filesystem::path(path_it))); - if (curModelDir != nullptr) { - for ( DatEntry* fl : curModelDir->getFiles() ) { - if (fl->getName().find("_HOB") != std::string::npos) { - listModel.push_back(path_it + "/" + fl->getName()); - } - } - } - } -} - -void LegacyExplorer::BuildTextureList( RDat* pRDat ) { - -} - -void LegacyExplorer::BuildMusicList( RDat* pRDat ) { - const static std::string legacyMusicPath = "data/sound"; - DirectoryEntry* musicDir = nullptr; - - listMusic.clear(); - musicDir = dynamic_cast(pRDat->getElement(boost::filesystem::path(legacyMusicPath))); - if (musicDir != nullptr) { - for ( DatEntry* fl : musicDir->getFiles() ) { - //TODO: MusyX-Class builder - - if (fl->getName().find("_SNG") != std::string::npos) { - listMusic.push_back(legacyMusicPath + "/" + fl->getName()); - } - } - } -} - -void LegacyExplorer::BuildSampleList( RDat* pRDat ) { - -} - -} diff --git a/src/RDI.cpp b/src/RDI.cpp index 1e62b1d..caa4b26 100644 --- a/src/RDI.cpp +++ b/src/RDI.cpp @@ -1,9 +1,9 @@ /** * @file RDI.cpp - * @date 15/09/2022 + * @date 24/09/2022 * @author JackCarterSmith * @copyright GPL-v3.0 - * @brief Rogue Data Interface library main entry file. + * @brief Rogue Data Interface library main entry abstraction file. * */ @@ -16,17 +16,17 @@ #include #include #include "config.h" -#include "RDat.h" -#include "DatEntry.h" -#include "LegacyExplorer.h" -#include "RDI.h" +#include "Erso.hpp" +#include "ErsoEntry.hpp" +#include "Krennic.hpp" +#include "RDI.hpp" /* * Internal variable */ -static RDI::RDat *hRDat = nullptr; -static RDI::LegacyExplorer *hLegacyExp = nullptr; +static RDI::Erso *hErsoModule = nullptr; +static RDI::Krennic *hKrennicModule = nullptr; /* * Libs interface @@ -35,55 +35,55 @@ static RDI::LegacyExplorer *hLegacyExp = nullptr; std::string RDI::getLibVersion() { return PRG_VERSION; } void RDI::CreateRDatHandler( std::string roguePath ){ - if (hRDat == nullptr) hRDat = new RDI::RDat(roguePath); + if (hErsoModule == nullptr) hErsoModule = new RDI::Erso(roguePath); - //return hRDat; + //return hErsoModule; } void RDI::CreateLegacyHandler( void ){ - if (hRDat != nullptr) hLegacyExp = new RDI::LegacyExplorer(hRDat); + if (hErsoModule != nullptr) hKrennicModule = new RDI::Krennic(hErsoModule); - //return hLegacyExp; + //return hKrennicModule; } unsigned char RDI::getSectionCount() { - if (hRDat == nullptr) return 0; - else return hRDat->getDataSectionCount(); + if (hErsoModule == nullptr) return 0; + else return hErsoModule->getDataSectionCount(); } std::string RDI::getSectionName( unsigned char id ) { - if (hRDat == nullptr) return ""; - else return hRDat->getDataSectionName(id); + if (hErsoModule == nullptr) return ""; + else return hErsoModule->getDataSectionName(id); } unsigned int RDI::getSectionOffset( unsigned char id ) { - if (hRDat == nullptr) return 0; - else return hRDat->getDataSectionOffset(id); + if (hErsoModule == nullptr) return 0; + else return hErsoModule->getDataSectionOffset(id); } unsigned int RDI::getDirectoryElementCount( std::string path ) { - DirectoryEntry* result = nullptr; + ErsoEntryDir* result = nullptr; if (path.empty()) return 0; - result = dynamic_cast(hRDat->getElement(boost::filesystem::path(path))); + result = dynamic_cast(hErsoModule->getElement(boost::filesystem::path(path))); if (result == nullptr) return 0; else return result->getSize(); } std::vector RDI::getDirectoryElements( std::string path ) { - DirectoryEntry* de = nullptr; + ErsoEntryDir* de = nullptr; std::vector elementsNameArray; elementsNameArray.clear(); if (!path.empty()) { - de = dynamic_cast(hRDat->getElement(boost::filesystem::path(path))); + de = dynamic_cast(hErsoModule->getElement(boost::filesystem::path(path))); if (de != nullptr && de->isDirectory()) { - for (DatEntry* de2 : de->getFiles()) + for (ErsoEntry* de2 : de->getFiles()) elementsNameArray.push_back(de2->getName()); } } @@ -92,11 +92,11 @@ std::vector RDI::getDirectoryElements( std::string path ) { } bool RDI::isElementDirectory( std::string path ) { - DatEntry* result = nullptr; + ErsoEntry* result = nullptr; if (path.empty()) return false; - result = hRDat->getElement(boost::filesystem::path(path)); + result = hErsoModule->getElement(boost::filesystem::path(path)); if (result == nullptr) return false; else return (result->isDirectory() || result->isRootDirectory()); @@ -104,21 +104,21 @@ bool RDI::isElementDirectory( std::string path ) { std::vector RDI::getLevelsName( void ) { - return hLegacyExp->getLevelsList(); + return hKrennicModule->getLevelsList(); } std::vector RDI::getModelsName( void ) { - return hLegacyExp->getModelsList(); + return hKrennicModule->getModelsList(); } std::vector RDI::getMusicsName( void ) { - return hLegacyExp->getMusicsList(); + return hKrennicModule->getMusicsList(); } void RDI::DestroyRDatHandler(){ - if (hRDat) delete hRDat; + if (hErsoModule) delete hErsoModule; } void RDI::DestroyLegacyHandler(){ - if (hLegacyExp) delete hLegacyExp; + if (hKrennicModule) delete hKrennicModule; } diff --git a/src/bundle_struct.h b/src/files_mms/bundle_struct.h similarity index 100% rename from src/bundle_struct.h rename to src/files_mms/bundle_struct.h diff --git a/src/data_struct.h b/src/files_mms/data_struct.h similarity index 100% rename from src/data_struct.h rename to src/files_mms/data_struct.h diff --git a/tools/ErsoDebug.cpp b/tools/ErsoDebug.cpp new file mode 100644 index 0000000..4cb30bd --- /dev/null +++ b/tools/ErsoDebug.cpp @@ -0,0 +1,16 @@ +/** + * @file ErsoDebug.cpp + * @date 24/09/2022 + * @author JackCarterSmith + * @copyright GPL-v3.0 + * @brief Debug app to test Erso module of RDI library. + * + */ + +#include + + +int main( int argc, char *argv[] ) { + + return 0; +} diff --git a/tools/KrennicDebug.cpp b/tools/KrennicDebug.cpp new file mode 100644 index 0000000..1e2812f --- /dev/null +++ b/tools/KrennicDebug.cpp @@ -0,0 +1,16 @@ +/** + * @file KrennicDebug.cpp + * @date 24/09/2022 + * @author JackCarterSmith + * @copyright GPL-v3.0 + * @brief Debug app to test Krennic module of RDI library. + * + */ + +#include + + +int main( int argc, char *argv[] ) { + + return 0; +} diff --git a/tools/RDIdebug.cpp b/tools/RDIdebug.cpp index 6887aca..dd0100e 100644 --- a/tools/RDIdebug.cpp +++ b/tools/RDIdebug.cpp @@ -10,7 +10,7 @@ #include #include #include -#include +#include void PrintVirtualDirectoryContents( boost::filesystem::path, std::string ); -- 2.39.5 From 26629d56bcf66af5b810942ec5055280eb540a8d Mon Sep 17 00:00:00 2001 From: JackCarterSmith Date: Sun, 25 Sep 2022 22:14:54 +0200 Subject: [PATCH 5/9] Reforge library structure - 2nd pass --- include/RDI.hpp | 19 +++++++------------ src/RDI.cpp | 28 +++++++++++++--------------- tools/{RDIdebug.cpp => RDIDebug.cpp} | 7 +++---- 3 files changed, 23 insertions(+), 31 deletions(-) rename tools/{RDIdebug.cpp => RDIDebug.cpp} (94%) diff --git a/include/RDI.hpp b/include/RDI.hpp index 0399849..15d3a48 100644 --- a/include/RDI.hpp +++ b/include/RDI.hpp @@ -51,17 +51,14 @@ namespace RDI { RDI_EXTERN std::string getLibVersion( void ); /** - * @brief Create a new Rogue Data file instance. - * @details Try to open DATA.DAT file at location specified by roguePath. - * If file can be opened, it's mapped in memory and process files list. - * + * @brief Allocate memory and create default structure to access datas. + * @details Try to open DATA.DAT file at location specified by roguePath. + * 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. - * - * @return Handler of RogueData file, should be used with other function of this lib. */ - RDI_EXTERN void CreateRDatHandler( std::string roguePath ); - RDI_EXTERN void CreateLegacyHandler( void ); + RDI_EXTERN void 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 ); @@ -70,7 +67,7 @@ namespace RDI { RDI_EXTERN std::vector getDirectoryElements( std::string path ); RDI_EXTERN bool isElementDirectory( std::string path ); - + /* Krennic specific methods */ RDI_EXTERN std::vector getLevelsName( void ); RDI_EXTERN std::vector getModelsName( void ); RDI_EXTERN std::vector getMusicsName( void ); @@ -78,9 +75,7 @@ namespace RDI { /** * @brief Clean up global resources. */ - RDI_EXTERN void DestroyRDatHandler( void ); - RDI_EXTERN void DestroyLegacyHandler( void ); - + RDI_EXTERN void CleanUp( void ); } #endif /* RDI_HPP_ */ diff --git a/src/RDI.cpp b/src/RDI.cpp index caa4b26..b4a4a7d 100644 --- a/src/RDI.cpp +++ b/src/RDI.cpp @@ -23,28 +23,29 @@ /* - * Internal variable + * Internal modules instance */ static RDI::Erso *hErsoModule = nullptr; static RDI::Krennic *hKrennicModule = nullptr; + /* * Libs interface */ - std::string RDI::getLibVersion() { return PRG_VERSION; } -void RDI::CreateRDatHandler( std::string roguePath ){ - if (hErsoModule == nullptr) hErsoModule = new RDI::Erso(roguePath); - - //return hErsoModule; +void RDI::Init( std::string roguePath ){ + if (hErsoModule == nullptr) { + hErsoModule = new RDI::Erso(roguePath); + } + if (hErsoModule != nullptr && hKrennicModule == nullptr) { + hKrennicModule = new RDI::Krennic(hErsoModule); + } } -void RDI::CreateLegacyHandler( void ){ - if (hErsoModule != nullptr) hKrennicModule = new RDI::Krennic(hErsoModule); - //return hKrennicModule; -} + + unsigned char RDI::getSectionCount() { @@ -115,10 +116,7 @@ std::vector RDI::getMusicsName( void ) { return hKrennicModule->getMusicsList(); } -void RDI::DestroyRDatHandler(){ +void RDI::CleanUp(){ + if (hKrennicModule) delete hKrennicModule; if (hErsoModule) delete hErsoModule; } - -void RDI::DestroyLegacyHandler(){ - if (hKrennicModule) delete hKrennicModule; -} diff --git a/tools/RDIdebug.cpp b/tools/RDIDebug.cpp similarity index 94% rename from tools/RDIdebug.cpp rename to tools/RDIDebug.cpp index dd0100e..542f53f 100644 --- a/tools/RDIdebug.cpp +++ b/tools/RDIDebug.cpp @@ -24,9 +24,9 @@ int main( int argc, char *argv[] ) { //cout << "Using RDI lib v" << RDI::getLibVersion() << endl << endl; if ( argc > 1 ) - RDI::CreateRDatHandler(argv[1]); + RDI::Init(argv[1]); else - RDI::CreateRDatHandler("."); + RDI::Init("."); printf("> Section found: %d\n", RDI::getSectionCount()); for ( i = 0; i < RDI::getSectionCount(); i++ ) { @@ -46,7 +46,6 @@ int main( int argc, char *argv[] ) { PrintVirtualDirectoryContents(pathBuilder, prefix); } - RDI::CreateLegacyHandler(); for ( std::string lname : RDI::getLevelsName() ) { printf("Level found: %s\n", lname.c_str()); } @@ -57,7 +56,7 @@ int main( int argc, char *argv[] ) { printf("Music found: %s\n", mname.c_str()); } - RDI::DestroyRDatHandler(); + RDI::CleanUp(); return 0; } -- 2.39.5 From 2da49b53ae7e3beb073e38f23ce743708e743dcb Mon Sep 17 00:00:00 2001 From: JackCarterSmith Date: Thu, 12 Jan 2023 20:23:45 +0100 Subject: [PATCH 6/9] 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 --- CMakeLists.txt | 13 ++- include/FileHandler/Generic.h | 6 +- include/FileHandler/HMT.h | 2 +- include/RDI.hpp | 24 +++--- src/DatFileEntry.cpp | 72 ++++++++++++++++ src/DatFileEntry.hpp | 101 ++++++++++++++++++++++ src/Erso.cpp | 154 ++++++++++++++++++++++++---------- src/Erso.hpp | 61 ++++++++++---- src/ErsoEntry.cpp | 68 --------------- src/ErsoEntry.hpp | 94 --------------------- src/Krennic.cpp | 20 +++-- src/KrennicHandlerGeneric.cpp | 7 +- src/KrennicHandlerHMT.cpp | 4 +- src/RDI.cpp | 94 +++++++++++++-------- tools/RDIDebug.cpp | 116 ++++++++++++++++--------- 15 files changed, 506 insertions(+), 330 deletions(-) create mode 100644 src/DatFileEntry.cpp create mode 100644 src/DatFileEntry.hpp delete mode 100644 src/ErsoEntry.cpp delete mode 100644 src/ErsoEntry.hpp diff --git a/CMakeLists.txt b/CMakeLists.txt index d8497ae..4bf1e10 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -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) -set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -Wall") -set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wall") +if(NOT MSVC) + 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_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() diff --git a/include/FileHandler/Generic.h b/include/FileHandler/Generic.h index bd2f152..bb1b1b9 100644 --- a/include/FileHandler/Generic.h +++ b/include/FileHandler/Generic.h @@ -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; } diff --git a/include/FileHandler/HMT.h b/include/FileHandler/HMT.h index cc0e59c..5c266a6 100644 --- a/include/FileHandler/HMT.h +++ b/include/FileHandler/HMT.h @@ -17,7 +17,7 @@ namespace RDI { class HMT : public GenericFile { public: - HMT( ErsoEntryFile& hDat ); + HMT( DatFile::DatFileEntryFile &hDat ); virtual ~HMT(); }; diff --git a/include/RDI.hpp b/include/RDI.hpp index 15d3a48..b8e7c9d 100644 --- a/include/RDI.hpp +++ b/include/RDI.hpp @@ -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 getDirectoryElements( std::string path ); - RDI_EXTERN bool isElementDirectory( std::string path ); + RDI_EXTERN unsigned int RDI_getDirectoryElementCount( std::string path ); + RDI_EXTERN std::vector RDI_getDirectoryElements( std::string path ); + RDI_EXTERN bool RDI_isElementDirectory( std::string path ); /* Krennic specific methods */ - RDI_EXTERN std::vector getLevelsName( void ); - RDI_EXTERN std::vector getModelsName( void ); - RDI_EXTERN std::vector getMusicsName( void ); + RDI_EXTERN std::vector RDI_getLevelsName( void ); + RDI_EXTERN std::vector RDI_getModelsName( void ); + RDI_EXTERN std::vector RDI_getMusicsName( void ); /** * @brief Clean up global resources. */ - RDI_EXTERN void CleanUp( void ); + RDI_EXTERN void RDI_CleanUp( void ); } #endif /* RDI_HPP_ */ diff --git a/src/DatFileEntry.cpp b/src/DatFileEntry.cpp new file mode 100644 index 0000000..9018c17 --- /dev/null +++ b/src/DatFileEntry.cpp @@ -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 +#include +#include +#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; +} + +DatFileEntryDirectory::DatFileEntryDirectory( string name, DAT_FILE_FLAGS fFlags ) { + this->name = name; + this->fFlags.raw = fFlags.raw; + this->rootDir = false; + vSubFiles = new vector; +} + +DatFileEntryDirectory::DatFileEntryDirectory( string name, DAT_FILE_FLAGS fFlags, DatFileEntry* hFileEntry ) { + this->name = name; + this->fFlags.raw = fFlags.raw; + vSubFiles = new vector; + 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); +} + +} +} diff --git a/src/DatFileEntry.hpp b/src/DatFileEntry.hpp new file mode 100644 index 0000000..dad0775 --- /dev/null +++ b/src/DatFileEntry.hpp @@ -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 +#include +#include + + +#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 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 *vSubFiles; +}; + +} +} + +#endif /* ERSOENTRY_HPP_ */ diff --git a/src/Erso.cpp b/src/Erso.cpp index dd53823..0c3c348 100644 --- a/src/Erso.cpp +++ b/src/Erso.cpp @@ -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 #include #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; + pFTRoot = new std::vector; 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,21 +173,31 @@ 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; + if ( count == 0 ) return RDI_ERROR_PROCESS; for ( i = 0; i < count; i++ ) { 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 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(de), newPath); + return SearchSectionForEntry(dynamic_cast(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(e), newPath); + + return SearchSectionForEntry(dynamic_cast(e), newPath); } } } diff --git a/src/Erso.hpp b/src/Erso.hpp index d39f7cc..7c5ad21 100644 --- a/src/Erso.hpp +++ b/src/Erso.hpp @@ -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 + * , 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 #include #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 *pDatSection = nullptr; MEMFILE rDatPtr = nullptr; - std::vector *pFTRoot = nullptr; + std::vector *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); }; diff --git a/src/ErsoEntry.cpp b/src/ErsoEntry.cpp deleted file mode 100644 index 52ff513..0000000 --- a/src/ErsoEntry.cpp +++ /dev/null @@ -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; -} - -ErsoEntryDir::ErsoEntryDir( std::string name, DAT_FILE_FLAGS fFlags ) { - this->name = name; - this->fFlags.raw = fFlags.raw; - this->rootDir = false; - vSubFiles = new std::vector; -} - -ErsoEntryDir::ErsoEntryDir( std::string name, DAT_FILE_FLAGS fFlags, ErsoEntry* hFileEntry ) { - this->name = name; - this->fFlags.raw = fFlags.raw; - vSubFiles = new std::vector; - 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); -} - -} diff --git a/src/ErsoEntry.hpp b/src/ErsoEntry.hpp deleted file mode 100644 index 5c6ac88..0000000 --- a/src/ErsoEntry.hpp +++ /dev/null @@ -1,94 +0,0 @@ -/** - * @file ErsoEntry.hpp - * @date 24/09/2022 - * @author JackCarterSmith - * @copyright GPL-v3.0 - * @brief Data file entry descriptor class. - * - */ - -#include -#include -#include - - -#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 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 *vSubFiles; -}; - -} - -#endif /* ERSODATENTRY_HPP_ */ diff --git a/src/Krennic.cpp b/src/Krennic.cpp index 5a447e2..2bd7a57 100644 --- a/src/Krennic.cpp +++ b/src/Krennic.cpp @@ -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(pErso->getElement(boost::filesystem::path(legacyLvlPath))); + levelDir = dynamic_cast(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(pErso->getElement(boost::filesystem::path(path_it))); + curModelDir = dynamic_cast(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(pErso->getElement(boost::filesystem::path(legacyMusicPath))); + musicDir = dynamic_cast(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) { diff --git a/src/KrennicHandlerGeneric.cpp b/src/KrennicHandlerGeneric.cpp index 54bf350..679bf3d 100644 --- a/src/KrennicHandlerGeneric.cpp +++ b/src/KrennicHandlerGeneric.cpp @@ -8,12 +8,15 @@ */ #include +#include "DatFileEntry.hpp" #include -#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 = ""; diff --git a/src/KrennicHandlerHMT.cpp b/src/KrennicHandlerHMT.cpp index 66baf43..95c82d7 100644 --- a/src/KrennicHandlerHMT.cpp +++ b/src/KrennicHandlerHMT.cpp @@ -10,10 +10,12 @@ #include #include +using namespace RDI::DatFile; + namespace RDI { -HMT::HMT( ErsoEntryFile& hDat ): GenericFile( hDat ) { +HMT::HMT( DatFile::DatFileEntryFile &hDat ): GenericFile( hDat ) { this->fileExtension = "hmt"; } diff --git a/src/RDI.cpp b/src/RDI.cpp index b4a4a7d..984e23e 100644 --- a/src/RDI.cpp +++ b/src/RDI.cpp @@ -17,29 +17,49 @@ #include #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(hErsoModule->getElement(boost::filesystem::path(path))); + result = dynamic_cast(ErsoModule->getElement(boost::filesystem::path(path))); if (result == nullptr) return 0; else return result->getSize(); } -std::vector RDI::getDirectoryElements( std::string path ) { - ErsoEntryDir* de = nullptr; +std::vector RDI::RDI_getDirectoryElements( std::string path ) { + DatFileEntryDirectory* de = nullptr; std::vector elementsNameArray; elementsNameArray.clear(); if (!path.empty()) { - de = dynamic_cast(hErsoModule->getElement(boost::filesystem::path(path))); + de = dynamic_cast(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 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 RDI::getLevelsName( void ) { - return hKrennicModule->getLevelsList(); +std::vector RDI::RDI_getLevelsName( void ) { + return KrennicModule->getLevelsList(); } -std::vector RDI::getModelsName( void ) { - return hKrennicModule->getModelsList(); +std::vector RDI::RDI_getModelsName( void ) { + return KrennicModule->getModelsList(); } -std::vector RDI::getMusicsName( void ) { - return hKrennicModule->getMusicsList(); +std::vector 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; } diff --git a/tools/RDIDebug.cpp b/tools/RDIDebug.cpp index 542f53f..b6bd02e 100644 --- a/tools/RDIDebug.cpp +++ b/tools/RDIDebug.cpp @@ -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 #include +#ifdef _WIN32 +#include +#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 { + cout << outPrefix << "\\ " << eName << endl; + newOutPrefix.append("| "); + } + PrintVirtualDirectoryContents(newPath, newOutPrefix, unicode); } 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; + } } } } -- 2.39.5 From 4a0b0df410ed66742dc4640903e4055c2ba576b3 Mon Sep 17 00:00:00 2001 From: JackCarterSmith Date: Sun, 15 Jan 2023 17:04:34 +0100 Subject: [PATCH 7/9] Reforge library structure - final pass Rework files lister DatEntries class got new path member Play with vectors concatenation Harmonize configuration --- include/RDI.hpp | 1 + src/DatFileEntry.cpp | 29 ++++--------- src/DatFileEntry.hpp | 23 +++++++---- src/Erso.cpp | 69 +++++++++++++++++++++++++++---- src/Erso.hpp | 6 ++- src/Krennic.cpp | 97 ++++++++++++++++++++++++++++---------------- src/Krennic.hpp | 10 ++--- src/RDI.cpp | 4 ++ tools/RDIDebug.cpp | 12 ++++-- 9 files changed, 167 insertions(+), 84 deletions(-) diff --git a/include/RDI.hpp b/include/RDI.hpp index b8e7c9d..28e02bd 100644 --- a/include/RDI.hpp +++ b/include/RDI.hpp @@ -70,6 +70,7 @@ namespace RDI { /* Krennic specific methods */ RDI_EXTERN std::vector RDI_getLevelsName( void ); RDI_EXTERN std::vector RDI_getModelsName( void ); + RDI_EXTERN std::vector RDI_getTexturesName( void ); RDI_EXTERN std::vector RDI_getMusicsName( void ); /** diff --git a/src/DatFileEntry.cpp b/src/DatFileEntry.cpp index 9018c17..e979532 100644 --- a/src/DatFileEntry.cpp +++ b/src/DatFileEntry.cpp @@ -19,33 +19,24 @@ 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( string name, string path, DAT_FILE_FLAGS fFlags, unsigned int size, MEMFILE fPtr ) + : DatFileEntry::DatFileEntry(name, path, fFlags), size(size), fileMemPtr(fPtr) {} DatFileEntryFile::~DatFileEntryFile() {} -DatFileEntryDirectory::DatFileEntryDirectory( string name ) { - this->name = name; - this->fFlags.raw = 0; - this->rootDir = true; +DatFileEntryDirectory::DatFileEntryDirectory( string name, string path ) + : DatFileEntry::DatFileEntry(name, path), rootDir(true) { vSubFiles = new vector; } -DatFileEntryDirectory::DatFileEntryDirectory( string name, DAT_FILE_FLAGS fFlags ) { - this->name = name; - this->fFlags.raw = fFlags.raw; - this->rootDir = false; +DatFileEntryDirectory::DatFileEntryDirectory( string name, string path, DAT_FILE_FLAGS fFlags ) + : DatFileEntry::DatFileEntry(name, path, fFlags), rootDir(false) { vSubFiles = new vector; } -DatFileEntryDirectory::DatFileEntryDirectory( string name, DAT_FILE_FLAGS fFlags, DatFileEntry* hFileEntry ) { - this->name = name; - this->fFlags.raw = fFlags.raw; +DatFileEntryDirectory::DatFileEntryDirectory( string name, string path, DAT_FILE_FLAGS fFlags, DatFileEntry* hFileEntry ) + : DatFileEntry::DatFileEntry(name, path, fFlags), rootDir(false) { vSubFiles = new vector; AddEntry(hFileEntry); } @@ -56,10 +47,6 @@ DatFileEntryDirectory::~DatFileEntryDirectory() { delete vSubFiles; } -/*std::string DirectoryEntry::toString() { - -}*/ - void DatFileEntryDirectory::ClearLinkedFiles() { vSubFiles->clear(); } diff --git a/src/DatFileEntry.hpp b/src/DatFileEntry.hpp index dad0775..f6f8447 100644 --- a/src/DatFileEntry.hpp +++ b/src/DatFileEntry.hpp @@ -44,13 +44,20 @@ 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; }; + std::string getName() { return name; } + std::string getPath() { return virtualAbsPath; } protected: + DatFileEntry( std::string name, std::string path ) : name(name), virtualAbsPath(path) { + this->fFlags.raw = 0; + } + DatFileEntry( std::string name, std::string path, DAT_FILE_FLAGS fFlags ) + : name(name), virtualAbsPath(path), fFlags(fFlags) {} + std::string name; + std::string virtualAbsPath; DAT_FILE_FLAGS fFlags; }; @@ -58,34 +65,32 @@ inline DatFileEntry::~DatFileEntry() {} class DatFileEntryFile : public DatFileEntry { public: - DatFileEntryFile( std::string name, DAT_FILE_FLAGS fFlags, unsigned int size, MEMFILE fPtr ); + DatFileEntryFile( std::string name, std::string path, 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; + MEMFILE fileMemPtr; }; 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( std::string name, std::string path ); + DatFileEntryDirectory( std::string name, std::string path, DAT_FILE_FLAGS fFlags ); + DatFileEntryDirectory( std::string name, std::string path, DAT_FILE_FLAGS fFlags, DatFileEntry* hFileEntry ); ~DatFileEntryDirectory(); void ClearLinkedFiles(); void AddEntry( DatFileEntry* hFileEntry ); std::vector getFiles() { return *vSubFiles; } - //std::string toString(); bool isDirectory() { return true; } bool isRootDirectory() { return rootDir; } unsigned int getSize() { return vSubFiles->size(); } // In number of elements diff --git a/src/Erso.cpp b/src/Erso.cpp index 0c3c348..9b59ea3 100644 --- a/src/Erso.cpp +++ b/src/Erso.cpp @@ -164,7 +164,7 @@ RDI_RESULT Erso::CreateDataFilesTree() { pFTRoot = new std::vector; pFTRoot->clear(); for ( i = 0; i < cDatSection; i++ ) { - curDir = new DatFileEntryDirectory(pDatSection->at(i).name); + curDir = new DatFileEntryDirectory(pDatSection->at(i).name, pDatSection->at(i).name); pFTRoot->push_back(curDir); // Recalculate files descriptor offset for current section. @@ -207,12 +207,12 @@ RDI_RESULT Erso::ProcessTreeDirectoryContents( DatFileEntryDirectory* pCurDir, M // Test for file or directory if (!curEntryFlags.isDirectory) { - newFile = new DatFileEntryFile(tmpStr, curEntryFlags, + newFile = new DatFileEntryFile(tmpStr, pCurDir->getPath() + "/" + 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 DatFileEntryDirectory(tmpStr, curEntryFlags); + newDir = new DatFileEntryDirectory(tmpStr, pCurDir->getPath() + "/" + tmpStr, curEntryFlags); pCurDir->AddEntry(newDir); // Keep entries count in new directory to jump over after processing it. @@ -245,9 +245,9 @@ void Erso::DisposeFile() { * * @return Reference to the resource from specified input path */ -DatFileEntry *Erso::getElement( boost::filesystem::path virtualDirPath ) { +DatFileEntry *Erso::getElement( path virtualDirPath ) { bool skip = false; - boost::filesystem::path newPath; + path newPath; for ( DatFileEntry* de : *pFTRoot ) { if (virtualDirPath.size() == 1 || virtualDirPath.begin() == --virtualDirPath.end()) { @@ -260,7 +260,7 @@ DatFileEntry *Erso::getElement( boost::filesystem::path virtualDirPath ) { newPath.append(sp); skip = true; } - return SearchSectionForEntry(dynamic_cast(de), newPath); + return SearchEntryPath(dynamic_cast(de), newPath); } } } @@ -268,6 +268,32 @@ DatFileEntry *Erso::getElement( boost::filesystem::path virtualDirPath ) { return nullptr; } +/** + * Get a list of files corresponding to the specified pattern. + * + * @param virtualDirPath Origin of browsing + * @param pattern Search filename pattern + * @param recursive Do the search inside subfolders + * + * @return List of references to the files corresponding to pattern + */ +vector Erso::getElements( path virtualDirPath, string pattern, bool recursive ) { + vector result; + DatFileEntryDirectory* curDir = dynamic_cast(getElement(virtualDirPath)); + + if (recursive) { + auto recursFileList = SearchEntriesPattern(curDir, pattern); + result.insert(result.end(), recursFileList.begin(), recursFileList.end()); + } else { + for ( DatFileEntry* e : curDir->getFiles() ) { + if (e->getName().find(pattern) != string::npos) //TODO: Replace using RegEx search + result.push_back(e); + } + } + + return result; +} + /** * Browse inside virtual path to the final object from specific root DatFileEntryDirectory. * @@ -276,9 +302,9 @@ DatFileEntry *Erso::getElement( boost::filesystem::path virtualDirPath ) { * * @return Reference to the file resource */ -DatFileEntry *Erso::SearchSectionForEntry( DatFileEntryDirectory *curDir, boost::filesystem::path virtualDirPath ) { +DatFileEntry* Erso::SearchEntryPath( DatFileEntryDirectory* curDir, path virtualDirPath ) { bool skip = false; - boost::filesystem::path newPath; + path newPath; for ( DatFileEntry* e : curDir->getFiles() ) { if (virtualDirPath.size() == 1 || virtualDirPath.begin() == --virtualDirPath.end()) { @@ -292,7 +318,7 @@ DatFileEntry *Erso::SearchSectionForEntry( DatFileEntryDirectory *curDir, boost: skip = true; } - return SearchSectionForEntry(dynamic_cast(e), newPath); + return SearchEntryPath(dynamic_cast(e), newPath); } } } @@ -300,4 +326,29 @@ DatFileEntry *Erso::SearchSectionForEntry( DatFileEntryDirectory *curDir, boost: return nullptr; } +/** + * Browse inside virtual path to find specific pattern and add it reference to the list in input. + * + * @param upDir Origin of browsing + * @param pattern Search filename pattern + * + * @return Vector list of DatFileEntry + */ +vector Erso::SearchEntriesPattern( DatFileEntryDirectory* upDir, string pattern ) { + vector subDatEntries; + + for ( DatFileEntry* e : upDir->getFiles() ) + if (e->getName().find(pattern) != string::npos) //TODO: Replace using RegEx search + subDatEntries.push_back(e); + + for ( DatFileEntry* e : upDir->getFiles() ) { + if (e->isDirectory()) { + auto recursFileList = SearchEntriesPattern(dynamic_cast(e), pattern); + subDatEntries.insert(subDatEntries.end(), recursFileList.begin(), recursFileList.end()); + } + } + + return subDatEntries; +} + } diff --git a/src/Erso.hpp b/src/Erso.hpp index 7c5ad21..b49943c 100644 --- a/src/Erso.hpp +++ b/src/Erso.hpp @@ -68,7 +68,8 @@ public: unsigned int getDataSectionOffset( unsigned char id ) const; /* Tree manipulation/parse methods */ - DatFile::DatFileEntry *getElement( boost::filesystem::path virtualDirPath ); + DatFile::DatFileEntry* getElement( boost::filesystem::path virtualDirPath ); + std::vector getElements( boost::filesystem::path virtualDirPath, std::string pattern, bool recursive ); private: std::string workingDir = "."; @@ -94,7 +95,8 @@ private: void DisposeFile(); /* Tree manipulation/parse methods */ - DatFile::DatFileEntry *SearchSectionForEntry( DatFile::DatFileEntryDirectory *curDir, boost::filesystem::path virtualDirPath); + DatFile::DatFileEntry* SearchEntryPath( DatFile::DatFileEntryDirectory *curDir, boost::filesystem::path virtualDirPath); + std::vector SearchEntriesPattern(DatFile::DatFileEntryDirectory *upDir, std::string pattern); }; diff --git a/src/Krennic.cpp b/src/Krennic.cpp index 2bd7a57..d5533ad 100644 --- a/src/Krennic.cpp +++ b/src/Krennic.cpp @@ -17,11 +17,28 @@ #include "Erso.hpp" #include "Krennic.hpp" +using std::string; +using std::vector; + using namespace RDI::DatFile; namespace RDI { +struct PathDescriptor { + PathDescriptor(string p, bool r) noexcept + : path(p), isRecursive(r) {} + + PathDescriptor(const PathDescriptor&) = default; + PathDescriptor& operator=(const PathDescriptor&) = default; + + PathDescriptor(PathDescriptor&&) = default; + PathDescriptor& operator=(PathDescriptor&&) = default; + + string path; + bool isRecursive; +}; + Krennic::Krennic( Erso* pErso ) { BuildLevelList(pErso); BuildModelList(pErso); @@ -34,61 +51,73 @@ Krennic::~Krennic() {} void Krennic::BuildLevelList( Erso* pErso ) { - const static std::string legacyLvlPath = "data/level"; - DatFileEntryDirectory* levelDir = nullptr; + const static vector legacyLvlPath = { + PathDescriptor("data/level", true) + }; listLevel.clear(); - levelDir = dynamic_cast(pErso->getElement(boost::filesystem::path(legacyLvlPath))); - if (levelDir != nullptr) { - 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()); - } - } + for (PathDescriptor legacyLvlSubpath : legacyLvlPath) { + for (DatFileEntry* file : pErso->getElements(boost::filesystem::path(legacyLvlSubpath.path), "dat", legacyLvlSubpath.isRecursive)) { + //TODO: level-class builder + listLevel.push_back(file->getPath()); } } - - //TODO: LvlClass builder } void Krennic::BuildModelList( Erso* pErso ) { - const static std::vector legacyModelPath = { - "data/pl_crafts", "data/reb_stuff", "data/imp_stuff", - "data/gnrc_stuff", "data2" - }; - DatFileEntryDirectory* curModelDir = nullptr; + const static vector legacyModelPath = { + PathDescriptor("data", false), + PathDescriptor("data/pl_crafts", false), + PathDescriptor("data/reb_stuff", false), + PathDescriptor("data/imp_stuff", false), + PathDescriptor("data/gnrc_stuff", false), + PathDescriptor("data/level", true), + PathDescriptor("data/frontend", true), + PathDescriptor("data/dbg", false), + PathDescriptor("data2", false) + }; listModel.clear(); - for ( std::string path_it : legacyModelPath ) { - curModelDir = dynamic_cast(pErso->getElement(boost::filesystem::path(path_it))); - if (curModelDir != nullptr) { - for ( DatFileEntry* fl : curModelDir->getFiles() ) { - if (fl->getName().find("_HOB") != std::string::npos) { - listModel.push_back(path_it + "/" + fl->getName()); - } - } + for (PathDescriptor legacyModelSubpath : legacyModelPath) { + for (DatFileEntry* file : pErso->getElements(boost::filesystem::path(legacyModelSubpath.path), "_HOB", legacyModelSubpath.isRecursive)) { + //TODO: model-class builder + listModel.push_back(file->getPath()); } } } void Krennic::BuildTextureList( Erso* pErso ) { + const static vector legacyTexturePath = { + PathDescriptor("data", false), + PathDescriptor("data/pl_crafts", false), + PathDescriptor("data/reb_stuff", false), + PathDescriptor("data/imp_stuff", false), + PathDescriptor("data/gnrc_stuff", false), + PathDescriptor("data/level", true), + PathDescriptor("data/frontend", true), + PathDescriptor("data/dbg", false), + PathDescriptor("data2", false) + }; + listTexture.clear(); + for (PathDescriptor legacyTextureSubpath : legacyTexturePath) { + for (DatFileEntry* file : pErso->getElements(boost::filesystem::path(legacyTextureSubpath.path), "_HMT", legacyTextureSubpath.isRecursive)) { + //TODO: texture-class builder + listTexture.push_back(file->getPath()); + } + } } void Krennic::BuildMusicList( Erso* pErso ) { - const static std::string legacyMusicPath = "data/sound"; - DatFileEntryDirectory* musicDir = nullptr; + const static vector legacyLvlPath = { + PathDescriptor("data/sound", false) + }; listMusic.clear(); - musicDir = dynamic_cast(pErso->getElement(boost::filesystem::path(legacyMusicPath))); - if (musicDir != nullptr) { - for ( DatFileEntry* fl : musicDir->getFiles() ) { + for (PathDescriptor legacyMusicSubpath : legacyLvlPath) { + for (DatFileEntry* file : pErso->getElements(boost::filesystem::path(legacyMusicSubpath.path), "_SNG", legacyMusicSubpath.isRecursive)) { //TODO: MusyX-Class builder - - if (fl->getName().find("_SNG") != std::string::npos) { - listMusic.push_back(legacyMusicPath + "/" + fl->getName()); - } + listMusic.push_back(file->getPath()); } } } diff --git a/src/Krennic.hpp b/src/Krennic.hpp index ee74fb8..8b45d3d 100644 --- a/src/Krennic.hpp +++ b/src/Krennic.hpp @@ -46,11 +46,11 @@ public: * @return File type class handler. */ ///@{ - void* getLevel( std::string name ); - void* getModel( std::string name ); - HMT *getTexture( std::string name ); - void* getMusic( std::string name ); - void* getSample( std::string name ); + void* getLevel( std::string name ); + void* getModel( std::string name ); + HMT* getTexture( std::string name ); + void* getMusic( std::string name ); + void* getSample( std::string name ); ///@} /** diff --git a/src/RDI.cpp b/src/RDI.cpp index 984e23e..5940992 100644 --- a/src/RDI.cpp +++ b/src/RDI.cpp @@ -132,6 +132,10 @@ std::vector RDI::RDI_getModelsName( void ) { return KrennicModule->getModelsList(); } +std::vector RDI::RDI_getTexturesName( void ) { + return KrennicModule->getTexturesList(); +} + std::vector RDI::RDI_getMusicsName( void ) { return KrennicModule->getMusicsList(); } diff --git a/tools/RDIDebug.cpp b/tools/RDIDebug.cpp index b6bd02e..621c743 100644 --- a/tools/RDIDebug.cpp +++ b/tools/RDIDebug.cpp @@ -49,7 +49,7 @@ int main( int argc, char *argv[] ) { 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; + cout << " -Section " << i << " offset: 0x" << hex << uppercase << RDI::RDI_getSectionOffset(i) << dec << endl; } // Print DATA.DAT tree view with unicode "style" @@ -65,15 +65,19 @@ int main( int argc, char *argv[] ) { // Print game elements Krennic module found cout << endl << "Legacy files processing result:"; - cout << endl << "> Levels found:" << endl; + cout << endl << "> Levels found: " << RDI::RDI_getLevelsName().size() << endl; for ( std::string lname : RDI::RDI_getLevelsName() ) { cout << " " << lname << endl; } - cout << endl << "> Models found:" << endl; + cout << endl << "> Models found: " << RDI::RDI_getModelsName().size() << endl; for ( std::string mdname : RDI::RDI_getModelsName() ) { cout << " " << mdname << endl; } - cout << endl << "> Musics found:" << endl; + cout << endl << "> Textures found: " << RDI::RDI_getTexturesName().size() << endl; + for ( std::string txname : RDI::RDI_getTexturesName() ) { + cout << " " << txname << endl; + } + cout << endl << "> Musics found: " << RDI::RDI_getMusicsName().size() << endl; for ( std::string mname : RDI::RDI_getMusicsName() ) { cout << " " << mname << endl; } -- 2.39.5 From 05b3c1e88a233aed92ea41937ecc26a2c2f3fa9b Mon Sep 17 00:00:00 2001 From: JackCarterSmith Date: Thu, 2 Feb 2023 19:45:59 +0100 Subject: [PATCH 8/9] HOB file management HOB file handler prototype Mesh building should be moved to RSPModel lib Tree rendering unicode chars fix Updated version detection HOB file handler Debug HOB handler Pointer probably deallocated, need to check it Fix HOB loader and disposer Using HOB instance instead of static methods Review DLL support for MSVC build Vertices values calculation fix Added export obj method to debug tool Missed levels name separation Cleaned model processing Multithreading branch reported to later --- CMakeLists.txt | 43 ++++-- conanfile.txt | 4 +- include/FileHandler/Generic.h | 29 +++- include/FileHandler/HMT.h | 2 +- include/FileHandler/HOB.h | 120 +++++++++++++++ include/RDI.hpp | 31 ++-- src/Erso.hpp | 3 +- src/Krennic.cpp | 122 ++++++++++++--- src/Krennic.hpp | 43 +++--- src/KrennicHandlerGeneric.cpp | 13 +- src/KrennicHandlerHMT.cpp | 2 +- src/KrennicHandlerHOB.cpp | 189 ++++++++++++++++++++++++ src/RDI.cpp | 48 +++--- tools/RDIDebug.cpp | 269 ++++++++++++++++++++++++++++------ 14 files changed, 779 insertions(+), 139 deletions(-) create mode 100644 include/FileHandler/HOB.h create mode 100644 src/KrennicHandlerHOB.cpp diff --git a/CMakeLists.txt b/CMakeLists.txt index 4bf1e10..df8c2fa 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -7,8 +7,8 @@ # CMake requirement and general configuration -cmake_minimum_required(VERSION 3.12) -cmake_policy(VERSION 3.12) +cmake_minimum_required(VERSION 3.15) +cmake_policy(VERSION 3.15) set(CMAKE_MODULE_PATH ${CMAKE_BINARY_DIR}) if(DEFINED ENV{MS_COMPATIBLE}) set(CMAKE_GNUtoMS ON) # Enable compatibility level to exported libraries @@ -27,10 +27,10 @@ endif() set(RDI_LIB_NAME RDI) if(NOT MSVC) set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -Wall") - set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wall -std=c++17 -static-libgcc -static-libstdc++") + set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wall") else() set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} /Wall") - set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} /Wall /std:c++17") + set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} /Wall") endif() set(INSTALL_BIN_DIR "${CMAKE_INSTALL_PREFIX}/bin" CACHE PATH "Installation directory for executables") @@ -43,13 +43,13 @@ option(RDI_STATIC "Build static lib" ON) option(BUILD_TOOLS "Build lib tools" ON) # Import needed packages and references their include path -find_package(RSPModel 2.2 REQUIRED) +find_package(RSPModel 2.3 REQUIRED) include_directories(${RSPModel_INCLUDE_DIR}) find_package(RSPTerrain 2.0 REQUIRED) include_directories(${RSPTerrain_INCLUDE_DIR}) find_package(RSPTexture 2.1 REQUIRED) include_directories(${RSPTexture_INCLUDE_DIR}) -find_package(Boost 1.80.0 EXACT REQUIRED) +find_package(Boost 1.81.0 REQUIRED) include_directories(${Boost_INCLUDE_DIR}) add_definitions(-DBOOST_ALL_NO_LIB) @@ -80,14 +80,22 @@ endif() # Declare the shared library instance if(RDI_SHARED) add_library(rdi-lib SHARED ${RDI_LIB_SOURCES}) - set_property(TARGET rdi-lib PROPERTY C_STANDARD 90) + set_property(TARGET rdi-lib PROPERTY C_STANDARD 17) set_property(TARGET rdi-lib PROPERTY CXX_STANDARD 17) + set_property(TARGET rdi-lib PROPERTY MSVC_RUNTIME_LIBRARY "MultiThreaded$<$:Debug>DLL") set_target_properties(rdi-lib PROPERTIES VERSION 1.0.0) target_include_directories(rdi-lib PUBLIC ${CMAKE_CURRENT_SOURCE_DIR}/include) set_target_properties(rdi-lib PROPERTIES OUTPUT_NAME "${RDI_LIB_NAME}") + # As GNU-GCC have different runtime lib, we statically link them for this type of build + if (NOT MSVC) + target_link_libraries(rdi-lib PRIVATE + -static-libgcc + -static-libstdc++ + ) + endif() target_link_libraries(rdi-lib PRIVATE ${RSPModel_LIBRARIES} ${RSPTerrain_LIBRARIES} @@ -113,11 +121,20 @@ endif() # Declare the static library instance if(RDI_STATIC) add_library(rdi-libstatic STATIC ${RDI_LIB_SOURCES}) - set_property(TARGET rdi-libstatic PROPERTY C_STANDARD 90) + set_property(TARGET rdi-libstatic PROPERTY C_STANDARD 17) set_property(TARGET rdi-libstatic PROPERTY CXX_STANDARD 17) + set_property(TARGET rdi-libstatic PROPERTY MSVC_RUNTIME_LIBRARY "MultiThreaded$<$:Debug>DLL") + set_target_properties(rdi-libstatic PROPERTIES VERSION 1.0.0) target_include_directories(rdi-libstatic PUBLIC ${CMAKE_CURRENT_SOURCE_DIR}/include) + # As GNU-GCC have different runtime lib, we statically link them for this type of build + if (NOT MSVC) + target_link_libraries(rdi-libstatic PRIVATE + -static-libgcc + -static-libstdc++ + ) + endif() target_link_libraries(rdi-libstatic PRIVATE ${RSPModel_LIBRARIES} ${RSPTerrain_LIBRARIES} @@ -158,17 +175,20 @@ if(BUILD_TOOLS) #add_executable(rdi-debug-tools ${RDI_TOOLS_SOURCES}) add_executable(rdi-debug-tools ./tools/RDIDebug.cpp) - set_property(TARGET rdi-debug-tools PROPERTY C_STANDARD 90) + set_property(TARGET rdi-debug-tools PROPERTY C_STANDARD 17) + set_property(TARGET rdi-debug-tools PROPERTY CXX_STANDARD 17) set_target_properties(rdi-debug-tools PROPERTIES OUTPUT_NAME "RDI-debug") list(APPEND RDI_TARGETS_LIST rdi-debug-tools) add_executable(erso-debug-tools ./tools/ErsoDebug.cpp) - set_property(TARGET erso-debug-tools PROPERTY C_STANDARD 90) + set_property(TARGET erso-debug-tools PROPERTY C_STANDARD 17) + set_property(TARGET erso-debug-tools PROPERTY CXX_STANDARD 17) set_target_properties(erso-debug-tools PROPERTIES OUTPUT_NAME "Erso-debug") list(APPEND RDI_TARGETS_LIST erso-debug-tools) add_executable(krennic-debug-tools ./tools/KrennicDebug.cpp) - set_property(TARGET krennic-debug-tools PROPERTY C_STANDARD 90) + set_property(TARGET krennic-debug-tools PROPERTY C_STANDARD 17) + set_property(TARGET krennic-debug-tools PROPERTY CXX_STANDARD 17) set_target_properties(krennic-debug-tools PROPERTIES OUTPUT_NAME "Krennic-debug") list(APPEND RDI_TARGETS_LIST krennic-debug-tools) @@ -180,6 +200,7 @@ if(BUILD_TOOLS) set_target_properties(krennic-debug-tools PROPERTIES IMPORT_PREFIX "lib") endif() + # Static libgcc and libstdc++ already linked in library if(RDI_SHARED) target_link_libraries(rdi-debug-tools PRIVATE rdi-lib ${Boost_LIBRARIES}) target_link_libraries(erso-debug-tools PRIVATE rdi-lib) diff --git a/conanfile.txt b/conanfile.txt index 1f3d10b..e12cdf7 100644 --- a/conanfile.txt +++ b/conanfile.txt @@ -1,8 +1,8 @@ [requires] -rspmodellib/2.2.0 +rspmodellib/2.3.0 rspterrainlib/2.0.4 rsptexturelib/2.1.0 -boost/1.80.0 +boost/1.81.0 [generators] cmake diff --git a/include/FileHandler/Generic.h b/include/FileHandler/Generic.h index bb1b1b9..59916bc 100644 --- a/include/FileHandler/Generic.h +++ b/include/FileHandler/Generic.h @@ -1,6 +1,6 @@ /** * @file GenericFile.h - * @date 23/09/2022 + * @date 01/02/2023 * @author JackCarterSmith * @copyright GPL-v3.0 * @brief Generic file object class. @@ -22,15 +22,38 @@ namespace DatFile { class GenericFile { public: - GenericFile( DatFile::DatFileEntryFile &hDat ); + // Default constructor + // Set the default class members and link against correct MEMFILE + GenericFile( DatFile::DatFileEntryFile* hDat ); virtual ~GenericFile(); + GenericFile(const GenericFile&) = default; + GenericFile& operator=(const GenericFile&) = default; + + GenericFile(GenericFile&&) = default; + GenericFile& operator=(GenericFile&&) = default; + + // Primary datas parsing/loading function + // This function must be called to load datas in memory and access to others function + void Load(); + bool isLoaded() const { return loaded; } + + // Free memory of object datas + // Should be called after using it + void Dispose(); + + std::string getFileName() const { return fileName; } + std::string getFullPath() const { return fullFilePath; } + std::string getFileExtension() const { return fileExtension; } MEMFILE get() { return pMemLoc; } protected: unsigned long size; - std::string fileName, fileExtension; + std::string fileName, fullFilePath, fileExtension; MEMFILE pMemLoc = nullptr; + +private: + bool loaded = false; }; } diff --git a/include/FileHandler/HMT.h b/include/FileHandler/HMT.h index 5c266a6..c0c41bc 100644 --- a/include/FileHandler/HMT.h +++ b/include/FileHandler/HMT.h @@ -17,7 +17,7 @@ namespace RDI { class HMT : public GenericFile { public: - HMT( DatFile::DatFileEntryFile &hDat ); + HMT( DatFile::DatFileEntryFile* hDat ); virtual ~HMT(); }; diff --git a/include/FileHandler/HOB.h b/include/FileHandler/HOB.h new file mode 100644 index 0000000..48f9ff2 --- /dev/null +++ b/include/FileHandler/HOB.h @@ -0,0 +1,120 @@ +/** + * @file HOB.h + * @date 31/01/2023 + * @author JackCarterSmith + * @copyright GPL-v3.0 + * @brief HOB file object class. + * + * Rogue data files use a specific (and size optimized) storage method of model. + * HOB handler parse these datas and store them in a more GPU-frienly BOOST-Lib + * type. + * + */ + +#include +#include +#include +#include +#include + + +#ifndef HOB_H_ +#define HOB_H_ + +#if defined(_MSC_VER) +# define RDI_ABI_EXPORT __declspec(dllexport) +# define RDI_ABI_IMPORT __declspec(dllimport) +#elif __GNUC__ >= 4 +# define RDI_ABI_EXPORT __attribute__ ((visibility("default"))) +# define RDI_ABI_IMPORT __attribute__ ((visibility("default"))) +#else +# define RDI_ABI_EXPORT +# define RDI_ABI_IMPORT +#endif + +#if defined(RDI_DLL) +# if defined(WIN32) +# if defined(RDI_DLLBUILD) +# define RDI_EXTERN RDI_ABI_EXPORT +# else +# define RDI_EXTERN RDI_ABI_IMPORT +# endif +# endif +#endif + +#ifndef RDI_EXTERN +# define RDI_EXTERN +#endif + +namespace RDI { + +class HOB final : public GenericFile { +public: + /* + struct Vertex { + Vertex() noexcept = default; + Vertex(float x, float y, float z) noexcept + : x(x),y(y),z(z) {} + Vertex(std::array vArray) noexcept + : x(vArray[0]),y(vArray[1]),z(vArray[2]) {} + + Vertex(const Vertex&) = default; + Vertex& operator=(const Vertex&) = default; + + Vertex(Vertex&&) = default; + Vertex& operator=(Vertex&&) = default; + + float x = 0.0f, y = 0.0f, z = 0.0f; + }; + */ + + struct Mesh { + // Empty vertices mesh should be considered as root/main mesh struct. + std::vector*> vertices; + std::vector indices; + + // Transform matrix not used for now, equal to identity matrix. + boost::qvm::mat transform; + //Material material; + + // Submesh are divided by material/texture + std::vector subMeshs; + }; + + /* -------------------------------------------------------------------------- */ + HOB( DatFile::DatFileEntryFile* hDat ); + ~HOB(); + + HOB(const HOB&) = default; + HOB& operator=(const HOB&) = default; + + HOB(HOB&&) = default; + HOB& operator=(HOB&&) = default; + + // Mandatory function from base class + RDI_EXTERN void Load(); + RDI_EXTERN void Dispose(); + + /* -------------------------------------------------------------------------- */ + RDI_EXTERN unsigned int getObjectCount() const; + RDI_EXTERN std::string* getObjectName( unsigned short index ) const; + + RDI_EXTERN HOB::Mesh* getMeshFromObject( unsigned short index ) const; + RDI_EXTERN HOB::Mesh* getMeshFromObject( std::string name ) const; + + //ObjectMaterials getMaterialFromObject( unsigned short index, unsigned short materialIndex ); + //ObjectMaterials getMaterialFromObject( std::string name, unsigned short materialIndex ); + //std::vector getMaterialsFromObject( unsigned short index ); + //std::vector getMaterialsFromObject( std::string name ); + + +private: + void* hobInstance = nullptr; + unsigned int objCnt = 0; + std::unordered_map objectMeshList; // Each object mesh ordered by index + +}; + +} + +#endif /* HOB_H_ */ diff --git a/include/RDI.hpp b/include/RDI.hpp index 28e02bd..a6a8368 100644 --- a/include/RDI.hpp +++ b/include/RDI.hpp @@ -1,6 +1,6 @@ /** * @file RDI.hpp - * @date 24/09/2022 + * @date 22/01/2023 * @author JackCarterSmith * @copyright GPL-v3.0 * @brief Rogue Data Interface library main entry file. @@ -10,6 +10,7 @@ #include #include #include "RDI_Datatypes.h" +#include "FileHandler/HOB.h" #ifndef RDI_HPP_ @@ -48,7 +49,7 @@ namespace RDI { * @brief Get the current library version. * @return String of the version. */ - RDI_EXTERN std::string RDI_getLibVersion( void ); + RDI_EXTERN const std::string RDI_getLibVersion( void ) noexcept; /** * @brief Allocate memory and create default structure to access datas. @@ -58,20 +59,26 @@ namespace RDI { */ RDI_EXTERN void RDI_Init( std::string roguePath ); + /* -------------------------------------------------------------------------- */ /* Erso specific methods */ - 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 const unsigned char RDI_getSectionCount( void ); + RDI_EXTERN const std::string RDI_getSectionName( unsigned char id ); + RDI_EXTERN const unsigned int RDI_getSectionOffset( unsigned char id ); - RDI_EXTERN unsigned int RDI_getDirectoryElementCount( std::string path ); - RDI_EXTERN std::vector RDI_getDirectoryElements( std::string path ); - RDI_EXTERN bool RDI_isElementDirectory( std::string path ); + RDI_EXTERN const unsigned int RDI_getDirectoryElementCount( std::string path ); + RDI_EXTERN const std::vector RDI_getDirectoryElements( std::string path ); + RDI_EXTERN const bool RDI_isElementDirectory( std::string path ); + + /* -------------------------------------------------------------------------- */ /* Krennic specific methods */ - RDI_EXTERN std::vector RDI_getLevelsName( void ); - RDI_EXTERN std::vector RDI_getModelsName( void ); - RDI_EXTERN std::vector RDI_getTexturesName( void ); - RDI_EXTERN std::vector RDI_getMusicsName( void ); + RDI_EXTERN const std::vector RDI_getLevelsName( void ); + RDI_EXTERN const std::vector RDI_getModelsName( void ); + RDI_EXTERN const std::vector RDI_getTexturesName( void ); + RDI_EXTERN const std::vector RDI_getMusicsName( void ); + + RDI_EXTERN HOB* RDI_getModel( std::string modelName ); + /** * @brief Clean up global resources. diff --git a/src/Erso.hpp b/src/Erso.hpp index b49943c..fdb11e8 100644 --- a/src/Erso.hpp +++ b/src/Erso.hpp @@ -59,13 +59,14 @@ public: MEMFILE getRDat() const { return rDatPtr; } /* Workspace management */ - std::string getWorkingDirectory() { return workingDir; } + std::string getWorkingDirectory() const { return workingDir; } RDI_RESULT setWorkingDirectory( std::string newPath ); /* Generals informations getters */ unsigned char getDataSectionCount() const { return cDatSection; } std::string getDataSectionName( unsigned char id ) const; unsigned int getDataSectionOffset( unsigned char id ) const; + bool isUpdatedVersion() const { return (cDatSection > 2); } /* Tree manipulation/parse methods */ DatFile::DatFileEntry* getElement( boost::filesystem::path virtualDirPath ); diff --git a/src/Krennic.cpp b/src/Krennic.cpp index d5533ad..9704ba5 100644 --- a/src/Krennic.cpp +++ b/src/Krennic.cpp @@ -1,6 +1,6 @@ /** * @file Krennic.cpp - * @date 24/09/2022 + * @date 18/09/2023 * @author JackCarterSmith * @copyright GPL-v3.0 * @brief Main game assets parser and interface. @@ -10,15 +10,22 @@ * */ +#include +#include +#include #include #include #include #include +#include +#include +#include #include "Erso.hpp" #include "Krennic.hpp" using std::string; using std::vector; +using std::array; using namespace RDI::DatFile; @@ -40,32 +47,32 @@ struct PathDescriptor { }; Krennic::Krennic( Erso* pErso ) { - BuildLevelList(pErso); - BuildModelList(pErso); - BuildTextureList(pErso); - BuildMusicList(pErso); - BuildSampleList(pErso); + BuildLevelFileList(pErso); + BuildModelFileList(pErso); + BuildTextureFileList(pErso); + BuildMusicFileList(pErso); + BuildSampleFileList(pErso); } Krennic::~Krennic() {} -void Krennic::BuildLevelList( Erso* pErso ) { - const static vector legacyLvlPath = { +void Krennic::BuildLevelFileList( Erso* pErso ) { + const static array legacyLvlPath = { PathDescriptor("data/level", true) }; - listLevel.clear(); + listLevelsName.clear(); for (PathDescriptor legacyLvlSubpath : legacyLvlPath) { for (DatFileEntry* file : pErso->getElements(boost::filesystem::path(legacyLvlSubpath.path), "dat", legacyLvlSubpath.isRecursive)) { //TODO: level-class builder - listLevel.push_back(file->getPath()); + listLevelsName.push_back(file->getPath()); } } } -void Krennic::BuildModelList( Erso* pErso ) { - const static vector legacyModelPath = { +void Krennic::BuildModelFileList( Erso* pErso ) { + const static array legacyModelPath = { PathDescriptor("data", false), PathDescriptor("data/pl_crafts", false), PathDescriptor("data/reb_stuff", false), @@ -74,20 +81,36 @@ void Krennic::BuildModelList( Erso* pErso ) { PathDescriptor("data/level", true), PathDescriptor("data/frontend", true), PathDescriptor("data/dbg", false), + PathDescriptor("dbg_data", false) + }; + // Update version game legacy assets paths + const static array legacyModelPath2= { PathDescriptor("data2", false) }; - listModel.clear(); + listModels.clear(); + listModelsName.clear(); for (PathDescriptor legacyModelSubpath : legacyModelPath) { for (DatFileEntry* file : pErso->getElements(boost::filesystem::path(legacyModelSubpath.path), "_HOB", legacyModelSubpath.isRecursive)) { - //TODO: model-class builder - listModel.push_back(file->getPath()); + auto hobObj = new HOB(dynamic_cast(file)); + listModels.push_back(hobObj); + listModelsName.push_back(file->getPath()); + } + } + if (pErso->isUpdatedVersion()) { + for (PathDescriptor legacyModelSubpath2 : legacyModelPath2) { + for (DatFileEntry* file : pErso->getElements(boost::filesystem::path(legacyModelSubpath2.path), "_HOB", legacyModelSubpath2.isRecursive)) { + auto hobObj = new HOB(dynamic_cast(file)); + listModels.push_back(hobObj); + listModelsName.push_back(file->getPath()); + } } } } -void Krennic::BuildTextureList( Erso* pErso ) { - const static vector legacyTexturePath = { +void Krennic::BuildTextureFileList( Erso* pErso ) { + // Base game legacy assets paths + const static array legacyTexturePath = { PathDescriptor("data", false), PathDescriptor("data/pl_crafts", false), PathDescriptor("data/reb_stuff", false), @@ -96,34 +119,85 @@ void Krennic::BuildTextureList( Erso* pErso ) { PathDescriptor("data/level", true), PathDescriptor("data/frontend", true), PathDescriptor("data/dbg", false), + PathDescriptor("dbg_data", false) + }; + // Update version game legacy assets paths + const static array legacyTexturePath2= { PathDescriptor("data2", false) }; - listTexture.clear(); + listTexturesName.clear(); for (PathDescriptor legacyTextureSubpath : legacyTexturePath) { for (DatFileEntry* file : pErso->getElements(boost::filesystem::path(legacyTextureSubpath.path), "_HMT", legacyTextureSubpath.isRecursive)) { //TODO: texture-class builder - listTexture.push_back(file->getPath()); + listTexturesName.push_back(file->getPath()); + } + } + if (pErso->isUpdatedVersion()) { + for (PathDescriptor legacyTextureSubpath2 : legacyTexturePath2) { + for (DatFileEntry* file : pErso->getElements(boost::filesystem::path(legacyTextureSubpath2.path), "_HMT", legacyTextureSubpath2.isRecursive)) { + //TODO: texture-class builder + listTexturesName.push_back(file->getPath()); + } } } } -void Krennic::BuildMusicList( Erso* pErso ) { - const static vector legacyLvlPath = { +void Krennic::BuildMusicFileList( Erso* pErso ) { + const static array legacyLvlPath = { PathDescriptor("data/sound", false) }; - listMusic.clear(); + listMusicsName.clear(); for (PathDescriptor legacyMusicSubpath : legacyLvlPath) { for (DatFileEntry* file : pErso->getElements(boost::filesystem::path(legacyMusicSubpath.path), "_SNG", legacyMusicSubpath.isRecursive)) { //TODO: MusyX-Class builder - listMusic.push_back(file->getPath()); + listMusicsName.push_back(file->getPath()); } } } -void Krennic::BuildSampleList( Erso* pErso ) { +void Krennic::BuildSampleFileList( Erso* pErso ) { } +//void* Krennic::getLevel( std::string name ) {} + +HOB* Krennic::getModel( string name ) { + unsigned int i = 0; + + for (string fileName : listModelsName) { + if (fileName.find(name) != string::npos) { + return listModels.at(i); + } + i++; + } + + throw std::invalid_argument("Krennic can't found the requested model."); +} + +//HMT* Krennic::getTexture( std::string name ) {} + +//void* Krennic::getMusic( std::string name ) {} + +//void* Krennic::getSample( std::string name ) {} + + +void Krennic::DisposeLevels() {} + +void Krennic::DisposeModels() { + for (HOB* hobObj : listModels) { + if (hobObj->isLoaded()) + hobObj->Dispose(); + + delete hobObj; + } +} + +void Krennic::DisposeTextures() {} + +void Krennic::DisposeMusics() {} + +void Krennic::DisposeSamples() {} + } diff --git a/src/Krennic.hpp b/src/Krennic.hpp index 8b45d3d..20743a2 100644 --- a/src/Krennic.hpp +++ b/src/Krennic.hpp @@ -1,6 +1,6 @@ /** * @file Krennic.hpp - * @date 24/09/2022 + * @date 18/01/2023 * @author JackCarterSmith * @copyright GPL-v3.0 * @brief Main game assets parser and interface. @@ -15,6 +15,7 @@ #include #include #include +#include #include "Erso.hpp" @@ -33,11 +34,11 @@ public: * @return Array of filtered elements. */ ///@{ - std::vector getLevelsList() { return listLevel; } - std::vector getModelsList() { return listModel; } - std::vector getTexturesList() { return listTexture; } - std::vector getMusicsList() { return listMusic; } - std::vector getSamplesList() { return listSample; } + std::vector getLevelsList() { return listLevelsName; } + std::vector getModelsList() { return listModelsName; } + std::vector getTexturesList() { return listTexturesName; } + std::vector getMusicsList() { return listMusicsName; } + std::vector getSamplesList() { return listSamplesName; } ///@} /** @@ -47,7 +48,7 @@ public: */ ///@{ void* getLevel( std::string name ); - void* getModel( std::string name ); + HOB* getModel( std::string name ); HMT* getTexture( std::string name ); void* getMusic( std::string name ); void* getSample( std::string name ); @@ -64,17 +65,25 @@ public: GenericFile *getFile( boost::filesystem::path vPath ); private: - std::vector listLevel; - std::vector listModel; - std::vector listTexture; - std::vector listMusic; - std::vector listSample; + std::vector listModels; - void BuildLevelList( Erso* pErso ); - void BuildModelList( Erso* pErso ); - void BuildTextureList( Erso* pErso ); - void BuildMusicList( Erso* pErso ); - void BuildSampleList( Erso* pErso ); + std::vector listLevelsName; + std::vector listModelsName; + std::vector listTexturesName; + std::vector listMusicsName; + std::vector listSamplesName; + + void BuildLevelFileList( Erso* pErso ); + void BuildModelFileList( Erso* pErso ); + void BuildTextureFileList( Erso* pErso ); + void BuildMusicFileList( Erso* pErso ); + void BuildSampleFileList( Erso* pErso ); + + void DisposeLevels(); + void DisposeModels(); + void DisposeTextures(); + void DisposeMusics(); + void DisposeSamples(); }; } diff --git a/src/KrennicHandlerGeneric.cpp b/src/KrennicHandlerGeneric.cpp index 679bf3d..5b31aa2 100644 --- a/src/KrennicHandlerGeneric.cpp +++ b/src/KrennicHandlerGeneric.cpp @@ -1,6 +1,6 @@ /** * @file GenericFile.cpp - * @date 23/09/2022 + * @date 01/02/2023 * @author JackCarterSmith * @copyright GPL-v3.0 * @brief Generic file object class. @@ -16,13 +16,12 @@ using namespace RDI::DatFile; namespace RDI { -GenericFile::GenericFile( DatFile::DatFileEntryFile &hDat ) { - this->size = hDat.getSize(); - this->fileName = hDat.getName(); - this->fileExtension = ""; - this->pMemLoc = hDat.getDatas(); -} +GenericFile::GenericFile( DatFile::DatFileEntryFile* hDat ) + : size(hDat->getSize()), fileName(hDat->getName()), fullFilePath(hDat->getPath()), pMemLoc(hDat->getDatas()) {} GenericFile::~GenericFile() {} +void GenericFile::Load() { this->loaded = true; } +void GenericFile::Dispose() { this->loaded = false; } + } diff --git a/src/KrennicHandlerHMT.cpp b/src/KrennicHandlerHMT.cpp index 95c82d7..885e10f 100644 --- a/src/KrennicHandlerHMT.cpp +++ b/src/KrennicHandlerHMT.cpp @@ -15,7 +15,7 @@ using namespace RDI::DatFile; namespace RDI { -HMT::HMT( DatFile::DatFileEntryFile &hDat ): GenericFile( hDat ) { +HMT::HMT( DatFile::DatFileEntryFile* hDat ): GenericFile( hDat ) { this->fileExtension = "hmt"; } diff --git a/src/KrennicHandlerHOB.cpp b/src/KrennicHandlerHOB.cpp new file mode 100644 index 0000000..ba9f959 --- /dev/null +++ b/src/KrennicHandlerHOB.cpp @@ -0,0 +1,189 @@ +/** + * @file KrennicHandlerHOB.cpp + * @date 19/01/2023 + * @author JackCarterSmith + * @copyright GPL-v3.0 + * @brief HOB file object class. + * + */ + +#include +#include +#include +#include +#include +#include "DatFileEntry.hpp" +#include +#include + +using std::runtime_error; +using std::out_of_range; +using std::invalid_argument; +using std::string; +using namespace RDI::DatFile; +using namespace boost::qvm; + + +namespace RDI { + +HOB::Mesh* BuildObjectMesh( const T_RSPMODEL_OBJECT* hobPtr ); +HOB::Mesh* FillMesh( const T_RSPMODEL_OBJ_PARTS* objPtr ); + + +/* -------------------------------------------------------------------------- */ +HOB::HOB( DatFileEntryFile* hDat ) + : GenericFile(hDat) { + this->fileExtension = "hob"; +} + +HOB::~HOB() { + Dispose(); +} + + +/* -------------------------------------------------------------------------- */ +void HOB::Load() { + unsigned int i; + RSPMODEL_PARAMETERS rspParams; + unsigned short result = RSPLIB_SUCCESS; + + if (this->isLoaded()) return; + + this->hobInstance = new T_RSPMODEL_HOB{}; + auto hobInstancePtr = static_cast(this->hobInstance); + rspParams.raw = 0; + result = RSPModel_processHOBFileMemory(hobInstancePtr, this->pMemLoc, this->size, rspParams); + if (result != RSPLIB_SUCCESS) { + RSPModel_freeHOB(static_cast(this->hobInstance)); + delete static_cast(this->hobInstance); + + if (result == RSPLIB_ERROR_GENERIC) + throw out_of_range("HOB handler tried to process empty file."); + else + throw runtime_error("HOB handler processing failed with error: " + std::to_string(result)); + } + + this->objCnt = hobInstancePtr->obj_count; + this->objectMeshList.clear(); + for ( i = 0; i < this->objCnt; i++ ) + this->objectMeshList[string(hobInstancePtr->objects[i].name)] = BuildObjectMesh(hobInstancePtr->objects + i); + + RSPModel_freeHOB(static_cast(this->hobInstance)); + + // Must be called last to set loaded state + GenericFile::Load(); +} + +void HOB::Dispose() { + if (!this->isLoaded()) return; + + for ( const auto& [objName, objMesh] : this->objectMeshList ) { + for ( auto v : objMesh->vertices) + delete v; + + for ( auto sm : objMesh->subMeshs) + delete sm; + + delete objMesh; + } + + this->objectMeshList.clear(); + delete static_cast(this->hobInstance); + + // Must be called last to unset loaded state + GenericFile::Dispose(); +} + + +/* -------------------------------------------------------------------------- */ +unsigned int HOB::getObjectCount() const { + if (this->isLoaded()) + return this->objCnt; + + return RSPModel_getHOBFileMemObjCount(this->pMemLoc); +} + +std::string* HOB::getObjectName( unsigned short index ) const { + if (!this->isLoaded()) + throw runtime_error("HOB handler has not been loaded prior to function calling."); + + if (index >= this->objCnt) + throw out_of_range("HOB handler object index out of range!"); + + auto entry = objectMeshList.begin(); + std::advance(entry, index); + return new string(entry->first); +} + +HOB::Mesh* HOB::getMeshFromObject( unsigned short index ) const { + if (!this->isLoaded()) + throw runtime_error("HOB handler has not been loaded prior to function calling."); + + if (index >= this->objCnt) + throw out_of_range("HOB handler object index out of range!"); + + auto entry = objectMeshList.begin(); + std::advance(entry, index); + return entry->second; +} + +HOB::Mesh* HOB::getMeshFromObject( string name ) const { + if (!this->isLoaded()) + throw runtime_error("HOB handler has not been loaded prior to function calling."); + + for ( const auto& [objName, objMesh] : this->objectMeshList ) + if (objName == name) return objMesh; + + throw invalid_argument("HOB handler can't find requested object name."); +} + + +/* -------------------------------------------------------------------------- */ +HOB::Mesh* BuildObjectMesh( const T_RSPMODEL_OBJECT* hobPtr ) { + unsigned int i; + auto meshObj = new HOB::Mesh(); + + meshObj->indices.clear(); + meshObj->vertices.clear(); + meshObj->subMeshs.clear(); + + meshObj->transform = identity_mat(); + for (i = 0; i < hobPtr->object_part_count; i++) + meshObj->subMeshs.push_back(FillMesh(hobPtr->object_parts + i)); + + return meshObj; +} + +HOB::Mesh* FillMesh( const T_RSPMODEL_OBJ_PARTS* objPtr ) { + unsigned int i; + auto meshObj = new HOB::Mesh(); + + meshObj->indices.clear(); + meshObj->vertices.clear(); + meshObj->subMeshs.clear(); + + //meshObj->transform = mat(); + meshObj->transform = identity_mat(); + for (i = 0; i < objPtr->vertex_count; i++) { + auto v = new vec(); + v->a[0] = static_cast(-(objPtr->vertices[i].x)) / 1024.0; + v->a[1] = static_cast(-(objPtr->vertices[i].y)) / 1024.0; + v->a[2] = static_cast((objPtr->vertices[i].z)) / 1024.0; + meshObj->vertices.push_back(v); + } + for (i = 0; i < objPtr->face_count; i++) { + meshObj->indices.push_back(static_cast(objPtr->faces[i].indices[0])); + meshObj->indices.push_back(static_cast(objPtr->faces[i].indices[1])); + meshObj->indices.push_back(static_cast(objPtr->faces[i].indices[2])); + + if (objPtr->faces[i].flags_bits.fIsQuad) { + meshObj->indices.push_back(static_cast(objPtr->faces[i].indices[2])); + meshObj->indices.push_back(static_cast(objPtr->faces[i].indices[3])); + meshObj->indices.push_back(static_cast(objPtr->faces[i].indices[0])); + } + } + + return meshObj; +} + +} diff --git a/src/RDI.cpp b/src/RDI.cpp index 5940992..5f138e8 100644 --- a/src/RDI.cpp +++ b/src/RDI.cpp @@ -1,6 +1,6 @@ /** * @file RDI.cpp - * @date 24/09/2022 + * @date 22/01/2023 * @author JackCarterSmith * @copyright GPL-v3.0 * @brief Rogue Data Interface library main entry abstraction file. @@ -15,10 +15,13 @@ #include #include #include +#include +#include // Only for version getting, no processing. #include "config.h" #include "Erso.hpp" #include "DatFileEntry.hpp" #include "Krennic.hpp" +#include #include "RDI.hpp" using namespace RDI::DatFile; @@ -34,12 +37,12 @@ static RDI::Krennic *KrennicModule = nullptr; /* * Libs interface */ -std::string RDI::RDI_getLibVersion() { return PRG_VERSION; } +const std::string RDI::RDI_getLibVersion() noexcept { return PRG_VERSION; } 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; +#ifndef NDEBUG + std::cout << std::endl << "Running RDI v" << std::string(RDI::RDI_getLibVersion()) << std::endl; + std::cout << "> RSPModelLib v" << std::string(RSPModel_getVersion()) << std::endl; std::cout << "> RSPTerrainLib v" << "N/A" << std::endl; std::cout << "> RSPTextureLib v" << "N/A" << std::endl; #endif @@ -47,7 +50,7 @@ void RDI::RDI_Init( std::string roguePath ) { // Create new instance of Erso module // Load and extract datas files from DATA.DAT if (ErsoModule == nullptr) { -#ifdef DEBUG +#ifndef NDEBUG std::cout << "[RDI][DBG] Loading Erso module..." << std::endl; #endif ErsoModule = new RDI::Erso(roguePath); @@ -56,7 +59,7 @@ void RDI::RDI_Init( std::string roguePath ) { // 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 +#ifndef NDEBUG std::cout << "[RDI][DBG] Loading Krennic module..." << std::endl; #endif KrennicModule = new RDI::Krennic(ErsoModule); @@ -68,23 +71,23 @@ void RDI::RDI_Init( std::string roguePath ) { -unsigned char RDI::RDI_getSectionCount() { +const unsigned char RDI::RDI_getSectionCount() { if (ErsoModule == nullptr) return 0; else return ErsoModule->getDataSectionCount(); } -std::string RDI::RDI_getSectionName( unsigned char id ) { +const std::string RDI::RDI_getSectionName( unsigned char id ) { if (ErsoModule == nullptr) return ""; else return ErsoModule->getDataSectionName(id); } -unsigned int RDI::RDI_getSectionOffset( unsigned char id ) { +const unsigned int RDI::RDI_getSectionOffset( unsigned char id ) { if (ErsoModule == nullptr) return 0; else return ErsoModule->getDataSectionOffset(id); } -unsigned int RDI::RDI_getDirectoryElementCount( std::string path ) { +const unsigned int RDI::RDI_getDirectoryElementCount( std::string path ) { DatFileEntryDirectory* result = nullptr; if (path.empty()) return 0; @@ -95,7 +98,7 @@ unsigned int RDI::RDI_getDirectoryElementCount( std::string path ) { else return result->getSize(); } -std::vector RDI::RDI_getDirectoryElements( std::string path ) { +const std::vector RDI::RDI_getDirectoryElements( std::string path ) { DatFileEntryDirectory* de = nullptr; std::vector elementsNameArray; elementsNameArray.clear(); @@ -112,7 +115,7 @@ std::vector RDI::RDI_getDirectoryElements( std::string path ) { return elementsNameArray; } -bool RDI::RDI_isElementDirectory( std::string path ) { +const bool RDI::RDI_isElementDirectory( std::string path ) { DatFileEntry* result = nullptr; if (path.empty()) return false; @@ -124,22 +127,33 @@ bool RDI::RDI_isElementDirectory( std::string path ) { } -std::vector RDI::RDI_getLevelsName( void ) { +/* -------------------------------------------------------------------------- */ +const std::vector RDI::RDI_getLevelsName( void ) { return KrennicModule->getLevelsList(); } -std::vector RDI::RDI_getModelsName( void ) { +const std::vector RDI::RDI_getModelsName( void ) { return KrennicModule->getModelsList(); } -std::vector RDI::RDI_getTexturesName( void ) { +const std::vector RDI::RDI_getTexturesName( void ) { return KrennicModule->getTexturesList(); } -std::vector RDI::RDI_getMusicsName( void ) { +const std::vector RDI::RDI_getMusicsName( void ) { return KrennicModule->getMusicsList(); } +RDI::HOB* RDI::RDI_getModel( std::string modelName ) { + try { + return KrennicModule->getModel(modelName); + } + catch (std::invalid_argument const &ex) { // Can't find model, incorrect name? + throw std::invalid_argument(ex); + } +} + +/* -------------------------------------------------------------------------- */ void RDI::RDI_CleanUp(){ if (KrennicModule) delete KrennicModule; if (ErsoModule) delete ErsoModule; diff --git a/tools/RDIDebug.cpp b/tools/RDIDebug.cpp index 621c743..826417d 100644 --- a/tools/RDIDebug.cpp +++ b/tools/RDIDebug.cpp @@ -1,6 +1,6 @@ /** * @file RDIDebug.cpp - * @date 12/01/2023 + * @date 01/02/2023 * @author JackCarterSmith * @copyright GPL-v3.0 * @brief Debug app to test functions of RDI library. @@ -8,31 +8,249 @@ */ #include +#include #include +#include +#include +#include +#ifdef USE_MULTITHREADING +#include +#include +#endif #include #include #ifdef _WIN32 #include +#else +#include #endif using namespace boost::filesystem; using namespace std; -void PrintVirtualDirectoryContents( path, string, bool ); +static vector modelCollection; + +static void PrintVirtualDirectoryContents( path p, bool unicode, string outPrefix = "" ) { + auto curDirElementsName = RDI::RDI_getDirectoryElements(p.string()); + auto newPath = path(p); + auto newOutPrefix = string(outPrefix); + + for ( string eName : curDirElementsName ) { + newPath.clear(); + newPath.concat(p); + newOutPrefix.clear(); + newOutPrefix.append(outPrefix); + + newPath.append(eName); + if (RDI::RDI_isElementDirectory(newPath.string())) { + if (unicode) { + if (*--curDirElementsName.end() == eName) { + cout << outPrefix << "\u2514 " << eName << endl; + newOutPrefix.append(" "); + } else { + cout << outPrefix << "\u251C " << eName << endl; + newOutPrefix.append("\u2502 "); + } + } else { + if (*--curDirElementsName.end() == eName) { + cout << outPrefix << "\\ " << eName << endl; + newOutPrefix.append(" "); + } else { + cout << outPrefix << "\\ " << eName << endl; + newOutPrefix.append("| "); + } + } + PrintVirtualDirectoryContents(newPath, unicode, newOutPrefix); + } else { + if (unicode) { + if (*--curDirElementsName.end() == eName) + cout << newOutPrefix << "\u2514 " << eName << endl; + else + cout << newOutPrefix << "\u251C " << eName << endl; + } else { + cout << newOutPrefix << "+ " << eName << endl; + } + } + } +} + +static void PrintModel( const RDI::HOB::Mesh* mesh, string prefix = "" ) { + if (mesh == nullptr) + return; + + string newPrefix = string(prefix); + + for ( auto submesh : mesh->subMeshs ) { + for ( auto v : submesh->vertices ) + cout << "[ " << v->a[0] << "; " << v->a[1] << "; " << v->a[2] << " ]" << endl; + + newPrefix.append(" "); + PrintModel(submesh, newPrefix); + } +} + +static void GenerateModelOBJ( const RDI::HOB::Mesh* mesh, const string outFolder, const string* name ) { + if (mesh == nullptr || name == nullptr || outFolder.empty()) + return; + + unsigned long i, i_offset = 0; + + ofstream objFile(".\\objOut\\" + outFolder + "\\" + (*name) + ".obj"); + + for ( auto submesh : mesh->subMeshs ) { + for ( auto v : submesh->vertices ) { + objFile << "v " << v->a[0] << " " << v->a[1] << " " << v->a[2] << endl; + } + objFile << endl; + for ( i = 0; i < submesh->indices.size(); i += 3 ) { + objFile << "f " << submesh->indices[i]+i_offset+1; + objFile << " " << submesh->indices[i+1]+i_offset+1; + objFile << " " << submesh->indices[i+2]+i_offset+1 << endl; + } + objFile << endl; + + i_offset += submesh->vertices.size(); + } + + objFile.close(); +} + +#ifdef USE_MULTITHREADING +static void GenerateModelOBJThreaded() { + unsigned int i, successCnt; + deque process; + const unsigned int maxThreads = thread::hardware_concurrency(); + + if (modelCollection.empty()) + return; + +#ifdef _WIN32 + CreateDirectory(".\\objOut", NULL); +#else + mkdir("./objOut"); +#endif + + for ( RDI::HOB* hobFile : modelCollection ) { + successCnt = 0; + cout << " Processing " << hobFile->getFullPath() << "..." << endl; + if (hobFile->isLoaded() && (hobFile->getObjectCount() > 0)) { + + string parentPath = path(hobFile->getFullPath()).parent_path().filename().string(); + replace(parentPath.begin(), parentPath.end(), '/', '\\'); + +#ifdef _WIN32 + CreateDirectory((".\\objOut\\" + parentPath).c_str(), NULL); +#else + mkdir(("./objOut/" + parentPath).c_str()); +#endif + + // Create initial threads for files processing + for ( i = 0; i < maxThreads; i++ ) { + if (i >= hobFile->getObjectCount()) + break; + + process.push_back(new thread( + GenerateModelOBJ, + hobFile->getMeshFromObject(i), + parentPath, + hobFile->getObjectName(i) + )); + } + + // Loop until all threads finished and no more file should be processed + while (true) { + process.front()->join(); + //delete process.front(); + process.pop_front(); + ++successCnt; + + if (successCnt >= hobFile->getObjectCount()) + break; + + process.push_back(new thread( + GenerateModelOBJ, + hobFile->getMeshFromObject(successCnt), + parentPath, + hobFile->getObjectName(successCnt) + )); + } + } + } +} +#endif + +static void ProcessModels() { + unsigned int i,invalid = 0; + + // Build models collection + modelCollection.clear(); + for ( string mdname : RDI::RDI_getModelsName() ) { + auto filePath = path(mdname); + modelCollection.push_back(RDI::RDI_getModel(filePath.string())); + } + + // Try to load models using low-level library + for ( RDI::HOB* hobFile : modelCollection ) { + try { + hobFile->Load(); + for ( i = 0; i < hobFile->getObjectCount(); i++ ) { + if (hobFile->getMeshFromObject(i)->subMeshs.empty()) { + cout << "Memory allocation failure!" << endl; + invalid++; + } + } + } catch (out_of_range const &ex) { + //cout << "Empty object" << endl; + } + } + cout << "Number of invalid memory allocation: " << invalid << endl; + + // Launch threaded OBJ file building + //GenerateModelOBJThreaded(); + //PrintModel(meshCollection.back()); +#ifdef _WIN32 + CreateDirectory(".\\objOut", NULL); +#else + mkdir("./objOut"); +#endif + + for ( RDI::HOB* hobFile : modelCollection ) { + if (hobFile->getObjectCount()) { + string parentPath = path(hobFile->getFullPath()).parent_path().filename().string(); + replace(parentPath.begin(), parentPath.end(), '/', '\\'); + +#ifdef _WIN32 + CreateDirectory((".\\objOut\\" + parentPath).c_str(), NULL); +#else + mkdir(("./objOut/" + parentPath).c_str()); +#endif + + for ( i = 0; i < hobFile->getObjectCount(); i++ ) { + cout << " Processing " << hobFile->getFullPath() << "..." << endl; + GenerateModelOBJ(hobFile->getMeshFromObject(i), parentPath, hobFile->getObjectName(i)); + } + } + } + + // Unload models + for ( RDI::HOB* hobFile : modelCollection ) { + hobFile->Dispose(); + modelCollection.clear(); + } +} int main( int argc, char *argv[] ) { unsigned int i; path pathBuilder; - string prefix; bool use_unicode = true; #ifdef _WIN32 SetConsoleOutputCP(CP_UTF8); #endif - cout << "Using RDI lib v" << RDI::RDI_getLibVersion() << endl << endl; + cout << "RDIDebug tool - using RDI lib v" << RDI::RDI_getLibVersion() << endl << endl; // Initialize RDI (Erso and Krennic module) with folder provided in program // argument, or the current directory by default @@ -46,7 +264,8 @@ int main( int argc, char *argv[] ) { } // Print details about legacy DATA.DAT file - cout << "> Section found: " << RDI::RDI_getSectionCount() << endl; + //cout << "> Section found: " << RDI::RDI_getSectionCount() << endl; + printf("> Section found: %d\n", RDI::RDI_getSectionCount()); 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) << dec << endl; @@ -60,7 +279,7 @@ int main( int argc, char *argv[] ) { pathBuilder.clear(); pathBuilder.concat(RDI::RDI_getSectionName(i)); - PrintVirtualDirectoryContents(pathBuilder, prefix, use_unicode); + PrintVirtualDirectoryContents(pathBuilder, use_unicode); } // Print game elements Krennic module found @@ -70,9 +289,7 @@ int main( int argc, char *argv[] ) { cout << " " << lname << endl; } cout << endl << "> Models found: " << RDI::RDI_getModelsName().size() << endl; - for ( std::string mdname : RDI::RDI_getModelsName() ) { - cout << " " << mdname << endl; - } + ProcessModels(); cout << endl << "> Textures found: " << RDI::RDI_getTexturesName().size() << endl; for ( std::string txname : RDI::RDI_getTexturesName() ) { cout << " " << txname << endl; @@ -87,37 +304,3 @@ int main( int argc, char *argv[] ) { return 0; } - -void PrintVirtualDirectoryContents( path p, string outPrefix, bool unicode ) { - auto curDirElementsName = RDI::RDI_getDirectoryElements(p.string()); - auto newPath = path(p); - auto newOutPrefix = string(outPrefix); - - for ( string eName : curDirElementsName ) { - newPath.clear(); - newPath.concat(p); - newOutPrefix.clear(); - newOutPrefix.append(outPrefix); - - newPath.append(eName); - if (RDI::RDI_isElementDirectory(newPath.string())) { - if (unicode) { - cout << outPrefix << "\u251C " << eName << endl; - newOutPrefix.append("\u2502 "); - } else { - 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; - } - } - } -} -- 2.39.5 From 7181d65a6e9fba8e63d279bbea5452a7c4b6c476 Mon Sep 17 00:00:00 2001 From: JackCarterSmith Date: Fri, 3 Feb 2023 17:35:28 +0100 Subject: [PATCH 9/9] Using C++17 filesystem directories + Print processing to time to log --- tools/RDIDebug.cpp | 32 +++++++++++++++++--------------- 1 file changed, 17 insertions(+), 15 deletions(-) diff --git a/tools/RDIDebug.cpp b/tools/RDIDebug.cpp index 826417d..298a684 100644 --- a/tools/RDIDebug.cpp +++ b/tools/RDIDebug.cpp @@ -7,8 +7,13 @@ * */ +#if __cplusplus < 201703L +#error "This code run on C++17 or upper." +#endif + #include #include +#include #include #include #include @@ -17,13 +22,12 @@ #include #include #endif +#include #include #include #ifdef _WIN32 #include -#else -#include #endif using namespace boost::filesystem; @@ -210,26 +214,18 @@ static void ProcessModels() { // Launch threaded OBJ file building //GenerateModelOBJThreaded(); //PrintModel(meshCollection.back()); -#ifdef _WIN32 - CreateDirectory(".\\objOut", NULL); -#else - mkdir("./objOut"); -#endif for ( RDI::HOB* hobFile : modelCollection ) { - if (hobFile->getObjectCount()) { - string parentPath = path(hobFile->getFullPath()).parent_path().filename().string(); + if (hobFile->isLoaded() && hobFile->getObjectCount()) { + string parentPath = path(hobFile->getFullPath()).string(); replace(parentPath.begin(), parentPath.end(), '/', '\\'); -#ifdef _WIN32 - CreateDirectory((".\\objOut\\" + parentPath).c_str(), NULL); -#else - mkdir(("./objOut/" + parentPath).c_str()); -#endif + filesystem::create_directories(".\\objOut\\" + hobFile->getFullPath()); for ( i = 0; i < hobFile->getObjectCount(); i++ ) { - cout << " Processing " << hobFile->getFullPath() << "..." << endl; + cout << hobFile->getFullPath() << "/" << *(hobFile->getObjectName(i)) << "..."; GenerateModelOBJ(hobFile->getMeshFromObject(i), parentPath, hobFile->getObjectName(i)); + cout << " OK" << endl; } } } @@ -288,12 +284,18 @@ int main( int argc, char *argv[] ) { for ( std::string lname : RDI::RDI_getLevelsName() ) { cout << " " << lname << endl; } + cout << endl << "> Models found: " << RDI::RDI_getModelsName().size() << endl; + auto t_start = chrono::high_resolution_clock::now(); ProcessModels(); + auto t_end = chrono::high_resolution_clock::now(); + cout << "Models processing in " << chrono::duration_cast(t_end - t_start).count() << "s" << endl; + cout << endl << "> Textures found: " << RDI::RDI_getTexturesName().size() << endl; for ( std::string txname : RDI::RDI_getTexturesName() ) { cout << " " << txname << endl; } + cout << endl << "> Musics found: " << RDI::RDI_getMusicsName().size() << endl; for ( std::string mname : RDI::RDI_getMusicsName() ) { cout << " " << mname << endl; -- 2.39.5