RDI first prototype release #1
1
.gitignore
vendored
1
.gitignore
vendored
@ -428,6 +428,7 @@ FodyWeavers.xsd
|
|||||||
# ---> C
|
# ---> C
|
||||||
# Prerequisites
|
# Prerequisites
|
||||||
*.d
|
*.d
|
||||||
|
src/config.h
|
||||||
|
|
||||||
# Object files
|
# Object files
|
||||||
*.o
|
*.o
|
||||||
|
197
CMakeLists.txt
Normal file
197
CMakeLists.txt
Normal file
@ -0,0 +1,197 @@
|
|||||||
|
# CMakeLists.txt
|
||||||
|
|
||||||
|
####################################################
|
||||||
|
# Written by JackCarterSmith, 2022
|
||||||
|
# This code is released under the RDI license.
|
||||||
|
####################################################
|
||||||
|
|
||||||
|
|
||||||
|
# CMake requirement and general configuration
|
||||||
|
cmake_minimum_required(VERSION 3.12)
|
||||||
|
cmake_policy(VERSION 3.12)
|
||||||
|
set(CMAKE_MODULE_PATH ${CMAKE_BINARY_DIR})
|
||||||
|
if(DEFINED ENV{MS_COMPATIBLE})
|
||||||
|
set(CMAKE_GNUtoMS ON) # Enable compatibility level to exported libraries
|
||||||
|
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)
|
||||||
|
set(RDI_NAME $ENV{CI_OUTPUT_NAME})
|
||||||
|
else() # Standalone project mode, should not be used for release.
|
||||||
|
project(rdi VERSION 1.0.0 DESCRIPTION "Rogue Data Interface" LANGUAGES C CXX)
|
||||||
|
set(RDI_NAME RDI)
|
||||||
|
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")
|
||||||
|
|
||||||
|
set(INSTALL_BIN_DIR "${CMAKE_INSTALL_PREFIX}/bin" CACHE PATH "Installation directory for executables")
|
||||||
|
set(INSTALL_LIB_DIR "${CMAKE_INSTALL_PREFIX}/lib" CACHE PATH "Installation directory for libraries")
|
||||||
|
set(INSTALL_INC_DIR "${CMAKE_INSTALL_PREFIX}/include" CACHE PATH "Installation directory for headers")
|
||||||
|
|
||||||
|
# Compilation option
|
||||||
|
option(RDI_SHARED "Build shared lib" ON)
|
||||||
|
option(RDI_STATIC "Build static lib" ON)
|
||||||
|
option(BUILD_TOOLS "Build lib tools" ON)
|
||||||
|
|
||||||
|
|
||||||
|
# Push compile infos to source
|
||||||
|
configure_file(${CMAKE_CURRENT_SOURCE_DIR}/config.h.in ${CMAKE_CURRENT_SOURCE_DIR}/src/config.h @ONLY)
|
||||||
|
|
||||||
|
|
||||||
|
# The project is divided in two parts:
|
||||||
|
# - RDI library to interface with RS3D data files. On windows system, it's can use registry to find RS3D install folder.
|
||||||
|
# - Some testing and debugging tools (WIP)
|
||||||
|
set(CMAKE_RUNTIME_OUTPUT_DIRECTORY ${PROJECT_BINARY_DIR}/bin)
|
||||||
|
set(CMAKE_LIBRARY_OUTPUT_DIRECTORY ${PROJECT_BINARY_DIR}/lib)
|
||||||
|
set(CMAKE_ARCHIVE_OUTPUT_DIRECTORY ${PROJECT_BINARY_DIR}/lib)
|
||||||
|
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)
|
||||||
|
|
||||||
|
|
||||||
|
# Building instructions for RSP-Texture library
|
||||||
|
if(DEFINED ENV{CI})
|
||||||
|
set(CMAKE_BUILD_TYPE RELEASE)
|
||||||
|
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 CXX_STANDARD 17)
|
||||||
|
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}")
|
||||||
|
|
||||||
|
target_link_libraries(rdi-lib PRIVATE
|
||||||
|
${RSPModel_LIBRARIES}
|
||||||
|
${RSPTerrain_LIBRARIES}
|
||||||
|
${RSPTexture_LIBRARIES}
|
||||||
|
${Boost_LIBRARIES}
|
||||||
|
)
|
||||||
|
|
||||||
|
if(WIN32)
|
||||||
|
# remove lib prefix on windows system when building dll file
|
||||||
|
set_target_properties(rdi-lib PROPERTIES PREFIX "")
|
||||||
|
set_target_properties(rdi-lib PROPERTIES DEFINE_SYMBOL RDI_DLL)
|
||||||
|
endif()
|
||||||
|
|
||||||
|
list(APPEND RDI_TARGETS_LIST rdi-lib)
|
||||||
|
|
||||||
|
# msvc does not append 'lib' - do it here to have consistent name
|
||||||
|
if(MSVC)
|
||||||
|
# only for import library, not the shared one
|
||||||
|
set_target_properties(rdi-lib PROPERTIES IMPORT_PREFIX "lib")
|
||||||
|
endif()
|
||||||
|
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 CXX_STANDARD 17)
|
||||||
|
|
||||||
|
target_include_directories(rdi-libstatic PUBLIC ${CMAKE_CURRENT_SOURCE_DIR}/include)
|
||||||
|
|
||||||
|
target_link_libraries(rdi-libstatic PRIVATE
|
||||||
|
${RSPModel_LIBRARIES}
|
||||||
|
${RSPTerrain_LIBRARIES}
|
||||||
|
${RSPTexture_LIBRARIES}
|
||||||
|
${Boost_LIBRARIES}
|
||||||
|
)
|
||||||
|
|
||||||
|
list(APPEND RDI_TARGETS_LIST rdi-libstatic)
|
||||||
|
|
||||||
|
# MSVC doesn't use a different file extension for shared vs. static
|
||||||
|
# libs. We are able to change OUTPUT_NAME to remove the _static
|
||||||
|
# for all other platforms.
|
||||||
|
if(NOT MSVC)
|
||||||
|
set_target_properties(rdi-libstatic PROPERTIES OUTPUT_NAME "${RDI_LIB_NAME}")
|
||||||
|
set_target_properties(rdi-libstatic PROPERTIES CLEAN_DIRECT_OUTPUT 1)
|
||||||
|
else()
|
||||||
|
set_target_properties(rdi-libstatic PROPERTIES OUTPUT_NAME "${RDI_LIB_NAME}_static")
|
||||||
|
set_target_properties(rdi-libstatic PROPERTIES CLEAN_DIRECT_OUTPUT 1)
|
||||||
|
endif()
|
||||||
|
|
||||||
|
# MSVC does not append 'lib' - do it here to have consistent name
|
||||||
|
if(MSVC)
|
||||||
|
set_target_properties(rdi-libstatic PROPERTIES PREFIX "lib")
|
||||||
|
endif()
|
||||||
|
endif()
|
||||||
|
|
||||||
|
if(NOT RDI_TARGETS_LIST)
|
||||||
|
message(SEND_ERROR
|
||||||
|
"No library variant selected to build. "
|
||||||
|
"Please enable at least one of the following options: "
|
||||||
|
"RDI_STATIC, RDI_SHARED")
|
||||||
|
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})
|
||||||
|
|
||||||
|
add_executable(rdi-debug-tools ${RDI_TOOLS_SOURCES})
|
||||||
|
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)
|
||||||
|
|
||||||
|
|
||||||
|
if(MSVC)
|
||||||
|
# msvc does not append 'lib' - do it here to have consistent name
|
||||||
|
set_target_properties(rdi-debug-tools PROPERTIES IMPORT_PREFIX "lib")
|
||||||
|
endif()
|
||||||
|
|
||||||
|
if(RDI_SHARED)
|
||||||
|
target_link_libraries(rdi-debug-tools PRIVATE rdi-lib)
|
||||||
|
elseif(RDI_STATIC)
|
||||||
|
target_link_libraries(rdi-debug-tools PRIVATE rdi-libstatic)
|
||||||
|
endif()
|
||||||
|
endif()
|
||||||
|
|
||||||
|
|
||||||
|
# GPG signature custom command
|
||||||
|
#add_custom_command(
|
||||||
|
# OUTPUT ""
|
||||||
|
# COMMAND gpg --batch --detach-sign
|
||||||
|
# -o ${RSE_MOD_NAME}_${CI_SYS_TARGET}.gpg
|
||||||
|
# ${RSE_MOD_NAME}
|
||||||
|
# DEPENDS ${RSE_MOD_NAME}
|
||||||
|
# VERBATIM
|
||||||
|
#)
|
||||||
|
|
||||||
|
|
||||||
|
# Install dependancies
|
||||||
|
#install(FILES ${PROJECT_BINARY_DIR}/bin/libpng16.dll
|
||||||
|
# DESTINATION ${INSTALL_BIN_DIR})
|
||||||
|
|
||||||
|
# Install library includes
|
||||||
|
install(FILES ${RSP_LIB_PUBLIC_HRDS} DESTINATION ${INSTALL_INC_DIR})
|
||||||
|
|
||||||
|
# Install project artifacts
|
||||||
|
install(TARGETS ${RDI_TARGETS_LIST}
|
||||||
|
RUNTIME DESTINATION ${INSTALL_BIN_DIR}
|
||||||
|
LIBRARY DESTINATION ${INSTALL_LIB_DIR}
|
||||||
|
ARCHIVE DESTINATION ${INSTALL_LIB_DIR}
|
||||||
|
)
|
79
Jenkinsfile
vendored
Normal file
79
Jenkinsfile
vendored
Normal file
@ -0,0 +1,79 @@
|
|||||||
|
pipeline {
|
||||||
|
agent any
|
||||||
|
options {
|
||||||
|
skipDefaultCheckout(true)
|
||||||
|
}
|
||||||
|
environment {
|
||||||
|
CI_OUTPUT_NAME = "RDI"
|
||||||
|
CI_VERSION = "1.0.0"
|
||||||
|
CI_BUILD_NUMBER = "$BUILD_NUMBER"
|
||||||
|
}
|
||||||
|
stages {
|
||||||
|
stage('Prepare') {
|
||||||
|
steps {
|
||||||
|
cleanWs()
|
||||||
|
rtConanClient(id: "conan", userHome: "/home/jackcartersmith")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
stage('Build') {
|
||||||
|
steps {
|
||||||
|
parallel(
|
||||||
|
linux: {
|
||||||
|
dir("linux") {
|
||||||
|
checkout([$class: 'GitSCM', branches: [[name: '**']], browser: [$class: 'GiteaBrowser', repoUrl: 'https://git.jcsmith.fr/JCS-Prod/RDI'], extensions: [], userRemoteConfigs: [[credentialsId: 'jenkins-ssh', url: 'ssh://git@git.jcsmith.fr:2322/JCS-Prod/RDI.git']]])
|
||||||
|
sh 'git submodule update --init --recursive'
|
||||||
|
dir("build") {
|
||||||
|
rtConanRun(clientId: "conan", command: "install .. --build=missing")
|
||||||
|
}
|
||||||
|
cmakeBuild buildDir: 'build', installation: 'latest', steps: [[args: 'all']]
|
||||||
|
}
|
||||||
|
},
|
||||||
|
windows: {
|
||||||
|
dir("windows") {
|
||||||
|
checkout([$class: 'GitSCM', branches: [[name: '**']], browser: [$class: 'GiteaBrowser', repoUrl: 'https://git.jcsmith.fr/JCS-Prod/RDI'], extensions: [], userRemoteConfigs: [[credentialsId: 'jenkins-ssh', url: 'ssh://git@git.jcsmith.fr:2322/JCS-Prod/RDI.git']]])
|
||||||
|
sh 'git submodule update --init --recursive'
|
||||||
|
dir("build") {
|
||||||
|
rtConanRun(clientId: "conan", command: "install .. -pr:b=default -pr:h=windows --build=missing")
|
||||||
|
}
|
||||||
|
cmakeBuild buildDir: 'build', cmakeArgs: '-DGNU_HOST=x86_64-w64-mingw32 -DCMAKE_TOOLCHAIN_FILE=./cmake/mingw_cross_toolchain.cmake', installation: 'latest', steps: [[args: 'all']]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
stage('Deploy') {
|
||||||
|
steps {
|
||||||
|
dir("zip_linux") {
|
||||||
|
sh 'cp -R ../linux/build/bin ../linux/build/lib ../linux/include .'
|
||||||
|
}
|
||||||
|
dir("zip_win") {
|
||||||
|
sh 'cp -R ../windows/build/bin ../windows/build/lib ../windows/include .'
|
||||||
|
}
|
||||||
|
zip archive: false, dir: 'zip_linux', exclude: '', glob: '', zipFile: 'linux_x64.zip'
|
||||||
|
sh 'mv linux_x64.zip ${CI_OUTPUT_NAME}_${CI_VERSION}.${BUILD_NUMBER}_Linux_x86_64.zip'
|
||||||
|
zip archive: false, dir: 'zip_win', exclude: '', glob: '', zipFile: 'mingw64.zip'
|
||||||
|
sh 'mv mingw64.zip ${CI_OUTPUT_NAME}_${CI_VERSION}.${BUILD_NUMBER}_mingw64.zip'
|
||||||
|
archiveArtifacts(artifacts: '*.zip')
|
||||||
|
fingerprint(targets: '*.zip')
|
||||||
|
}
|
||||||
|
}
|
||||||
|
stage('Sign') {
|
||||||
|
steps {
|
||||||
|
sh 'gpg --batch --detach-sign -o ${CI_OUTPUT_NAME}_${CI_VERSION}.${BUILD_NUMBER}_Linux_x86_64.zip.gpg ${CI_OUTPUT_NAME}_${CI_VERSION}.${BUILD_NUMBER}_Linux_x86_64.zip'
|
||||||
|
sh 'gpg --batch --detach-sign -o ${CI_OUTPUT_NAME}_${CI_VERSION}.${BUILD_NUMBER}_mingw64.zip.gpg ${CI_OUTPUT_NAME}_${CI_VERSION}.${BUILD_NUMBER}_mingw64.zip'
|
||||||
|
archiveArtifacts(artifacts: '*.gpg')
|
||||||
|
fingerprint(targets: '*.gpg')
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
/*
|
||||||
|
post {
|
||||||
|
always {
|
||||||
|
cleanWs(cleanWhenNotBuilt: false,
|
||||||
|
deleteDirs: true,
|
||||||
|
disableDeferredWipeout: true,
|
||||||
|
notFailBuild: true)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
*/
|
||||||
|
}
|
@ -1,3 +1,3 @@
|
|||||||
# RDI
|
# Rogue Data Interface (RDI)
|
||||||
|
|
||||||
This is the Rogue Data Interface, a library to make link between old data file from "Rogue Squadron 3D" and new Direct3D/OpenGL components.
|
A library to make link between old data file from "Rogue Squadron 3D" and new Direct3D/OpenGL components.
|
87
cmake/create_symlink.cmake
Normal file
87
cmake/create_symlink.cmake
Normal file
@ -0,0 +1,87 @@
|
|||||||
|
# Set a variable with CMake code which:
|
||||||
|
# Creates a symlink from src to dest (if possible) or alternatively
|
||||||
|
# copies if different.
|
||||||
|
include(CMakeParseArguments)
|
||||||
|
|
||||||
|
function(create_symlink DEST_FILE)
|
||||||
|
|
||||||
|
cmake_parse_arguments(S "" "FILE;TARGET" "" ${ARGN})
|
||||||
|
|
||||||
|
if(NOT S_TARGET AND NOT S_FILE)
|
||||||
|
message(FATAL_ERROR "create_symlink: Missing TARGET or FILE argument")
|
||||||
|
endif()
|
||||||
|
|
||||||
|
if(S_TARGET AND S_FILE)
|
||||||
|
message(FATAL_ERROR "create_symlink: Both source file ${S_FILE} and build target ${S_TARGET} arguments are present; can only have one.")
|
||||||
|
endif()
|
||||||
|
|
||||||
|
if(S_FILE)
|
||||||
|
# If we don't need to symlink something that's coming from a build target,
|
||||||
|
# we can go ahead and symlink/copy at configure time.
|
||||||
|
if(CMAKE_HOST_WIN32 AND NOT CYGWIN)
|
||||||
|
execute_process(
|
||||||
|
COMMAND "${CMAKE_COMMAND}" -E copy_if_different ${S_FILE} ${DEST_FILE}
|
||||||
|
WORKING_DIRECTORY "${CMAKE_CURRENT_BINARY_DIR}")
|
||||||
|
else()
|
||||||
|
execute_process(
|
||||||
|
COMMAND ${CMAKE_COMMAND} -E create_symlink ${S_FILE} ${DEST_FILE}
|
||||||
|
WORKING_DIRECTORY "${CMAKE_CURRENT_BINARY_DIR}")
|
||||||
|
endif()
|
||||||
|
endif()
|
||||||
|
|
||||||
|
if(S_TARGET)
|
||||||
|
# We need to use generator expressions, which can be a bit tricky, so for
|
||||||
|
# simplicity make the symlink a POST_BUILD step and use the TARGET
|
||||||
|
# signature of add_custom_command.
|
||||||
|
if(CMAKE_HOST_WIN32 AND NOT CYGWIN)
|
||||||
|
add_custom_command(TARGET ${S_TARGET} POST_BUILD
|
||||||
|
COMMAND "${CMAKE_COMMAND}" -E copy_if_different $<TARGET_LINKER_FILE_NAME:${S_TARGET}> $<TARGET_LINKER_FILE_DIR:${S_TARGET}>/${DEST_FILE})
|
||||||
|
else()
|
||||||
|
add_custom_command(TARGET ${S_TARGET} POST_BUILD
|
||||||
|
COMMAND "${CMAKE_COMMAND}" -E create_symlink $<TARGET_LINKER_FILE_NAME:${S_TARGET}> $<TARGET_LINKER_FILE_DIR:${S_TARGET}>/${DEST_FILE})
|
||||||
|
endif()
|
||||||
|
endif()
|
||||||
|
|
||||||
|
endfunction()
|
||||||
|
|
||||||
|
|
||||||
|
function(create_lib_symlink DEST_FILE)
|
||||||
|
|
||||||
|
cmake_parse_arguments(S "" "FILE;TARGET" "" ${ARGN})
|
||||||
|
|
||||||
|
if(NOT S_TARGET AND NOT S_FILE)
|
||||||
|
message(FATAL_ERROR "create_symlink: Missing TARGET or FILE argument")
|
||||||
|
endif()
|
||||||
|
|
||||||
|
if(S_TARGET AND S_FILE)
|
||||||
|
message(FATAL_ERROR "create_symlink: Both source file ${S_FILE} and build target ${S_TARGET} arguments are present; can only have one.")
|
||||||
|
endif()
|
||||||
|
|
||||||
|
if(S_FILE)
|
||||||
|
# If we don't need to symlink something that's coming from a build target,
|
||||||
|
# we can go ahead and symlink/copy at configure time.
|
||||||
|
if(CMAKE_HOST_WIN32 AND NOT CYGWIN)
|
||||||
|
execute_process(
|
||||||
|
COMMAND "${CMAKE_COMMAND}" -E copy_if_different ${S_FILE} ${DEST_FILE}
|
||||||
|
WORKING_DIRECTORY "${CMAKE_LIBRARY_OUTPUT_DIRECTORY}")
|
||||||
|
else()
|
||||||
|
execute_process(
|
||||||
|
COMMAND ${CMAKE_COMMAND} -E create_symlink ${S_FILE} ${DEST_FILE}
|
||||||
|
WORKING_DIRECTORY "${CMAKE_LIBRARY_OUTPUT_DIRECTORY}")
|
||||||
|
endif()
|
||||||
|
endif()
|
||||||
|
|
||||||
|
if(S_TARGET)
|
||||||
|
# We need to use generator expressions, which can be a bit tricky, so for
|
||||||
|
# simplicity make the symlink a POST_BUILD step and use the TARGET
|
||||||
|
# signature of add_custom_command.
|
||||||
|
if(CMAKE_HOST_WIN32 AND NOT CYGWIN)
|
||||||
|
add_custom_command(TARGET ${S_TARGET} POST_BUILD
|
||||||
|
COMMAND "${CMAKE_COMMAND}" -E copy_if_different ${CMAKE_LIBRARY_OUTPUT_DIRECTORY}/$<TARGET_LINKER_FILE_NAME:${S_TARGET}> $<TARGET_LINKER_FILE_DIR:${S_TARGET}>/${DEST_FILE})
|
||||||
|
else()
|
||||||
|
add_custom_command(TARGET ${S_TARGET} POST_BUILD
|
||||||
|
COMMAND "${CMAKE_COMMAND}" -E create_symlink ${CMAKE_LIBRARY_OUTPUT_DIRECTORY}/$<TARGET_LINKER_FILE_NAME:${S_TARGET}> $<TARGET_LINKER_FILE_DIR:${S_TARGET}>/${DEST_FILE})
|
||||||
|
endif()
|
||||||
|
endif()
|
||||||
|
|
||||||
|
endfunction()
|
8
cmake/mingw_cross_toolchain.cmake
Normal file
8
cmake/mingw_cross_toolchain.cmake
Normal file
@ -0,0 +1,8 @@
|
|||||||
|
SET(CMAKE_SYSTEM_NAME Windows)
|
||||||
|
IF("${GNU_HOST}" STREQUAL "")
|
||||||
|
SET(GNU_HOST i586-mingw32msvc)
|
||||||
|
ENDIF()
|
||||||
|
# Prefix detection only works with compiler id "GNU"
|
||||||
|
SET(CMAKE_C_COMPILER ${GNU_HOST}-gcc)
|
||||||
|
# CMake doesn't automatically look for prefixed 'windres', do it manually:
|
||||||
|
SET(CMAKE_RC_COMPILER ${GNU_HOST}-windres)
|
17
conanfile.txt
Normal file
17
conanfile.txt
Normal file
@ -0,0 +1,17 @@
|
|||||||
|
[requires]
|
||||||
|
rspmodellib/2.2.0
|
||||||
|
rspterrainlib/2.0.4
|
||||||
|
rsptexturelib/2.1.0
|
||||||
|
boost/1.80.0
|
||||||
|
|
||||||
|
[generators]
|
||||||
|
cmake
|
||||||
|
cmake_find_package
|
||||||
|
|
||||||
|
[options]
|
||||||
|
boost:zlib=False
|
||||||
|
boost:bzip2=False
|
||||||
|
boost:without_test=True
|
||||||
|
|
||||||
|
[imports]
|
||||||
|
bin, *.dll -> ./bin
|
6
config.h.in
Normal file
6
config.h.in
Normal file
@ -0,0 +1,6 @@
|
|||||||
|
#ifndef CONFIG_H_
|
||||||
|
#define CONFIG_H_
|
||||||
|
|
||||||
|
#define PRG_VERSION "@PROJECT_VERSION@"
|
||||||
|
|
||||||
|
#endif /* CONFIG_H_ */
|
2492
doc/Doxyfile
Normal file
2492
doc/Doxyfile
Normal file
File diff suppressed because it is too large
Load Diff
77
include/RDI.h
Normal file
77
include/RDI.h
Normal file
@ -0,0 +1,77 @@
|
|||||||
|
/**
|
||||||
|
* @file RDI.h
|
||||||
|
* @date 15/09/2022
|
||||||
|
* @author JackCarterSmith
|
||||||
|
* @copyright GPL-v3.0
|
||||||
|
* @brief Rogue Data Interface library main entry file.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "RDI_Datatypes.h"
|
||||||
|
|
||||||
|
|
||||||
|
#ifndef RDI_H_
|
||||||
|
#define RDI_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 {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Get the current library version.
|
||||||
|
* @return String of the version.
|
||||||
|
*/
|
||||||
|
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.
|
||||||
|
*
|
||||||
|
* @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 unsigned char getSectionCount( void );
|
||||||
|
RDI_EXTERN std::string getSectionName( unsigned char id );
|
||||||
|
RDI_EXTERN unsigned int getSectionOffset( unsigned char id );
|
||||||
|
|
||||||
|
RDI_EXTERN unsigned int getDirectoryElementCount( std::string path );
|
||||||
|
RDI_EXTERN std::vector<std::string> getDirectoryElements( std::string path );
|
||||||
|
RDI_EXTERN bool isElementDirectory( std::string path );
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Clean up global resources.
|
||||||
|
*/
|
||||||
|
RDI_EXTERN void DestroyRDatHandler( void );
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif /* RDI_H_ */
|
30
include/RDI_Datatypes.h
Normal file
30
include/RDI_Datatypes.h
Normal file
@ -0,0 +1,30 @@
|
|||||||
|
/**
|
||||||
|
* @file RDI_Datatypes.h
|
||||||
|
* @date 20/09/2022
|
||||||
|
* @author JackCarterSmith
|
||||||
|
* @copyright GPL-v3.0
|
||||||
|
* @brief Rogue Data Interface library variables type definitions.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef RDI_DATATYPES_H_
|
||||||
|
#define RDI_DATATYPES_H_
|
||||||
|
|
||||||
|
namespace RDI {
|
||||||
|
|
||||||
|
typedef char* MEMFILE;
|
||||||
|
|
||||||
|
typedef enum e_rdi_result {
|
||||||
|
RDI_OK,
|
||||||
|
|
||||||
|
RDI_ERROR_GENERIC,
|
||||||
|
RDI_ERROR_PROCESS,
|
||||||
|
RDI_ERROR_MEMORY,
|
||||||
|
RDI_ERROR_FILESYSTEM,
|
||||||
|
|
||||||
|
RDI_ERROR_UNEXPECTED
|
||||||
|
} RDI_RESULT;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif /* RDI_DATATYPES_H_ */
|
68
src/DatEntry.cpp
Normal file
68
src/DatEntry.cpp
Normal file
@ -0,0 +1,68 @@
|
|||||||
|
/**
|
||||||
|
* @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<DatEntry*>;
|
||||||
|
}
|
||||||
|
|
||||||
|
DirectoryEntry::DirectoryEntry( std::string name, DAT_FILE_FLAGS fFlags ) {
|
||||||
|
this->name = name;
|
||||||
|
this->fFlags.raw = fFlags.raw;
|
||||||
|
this->rootDir = false;
|
||||||
|
vSubFiles = new std::vector<DatEntry*>;
|
||||||
|
}
|
||||||
|
|
||||||
|
DirectoryEntry::DirectoryEntry( std::string name, DAT_FILE_FLAGS fFlags, DatEntry* hFileEntry ) {
|
||||||
|
this->name = name;
|
||||||
|
this->fFlags.raw = fFlags.raw;
|
||||||
|
vSubFiles = new std::vector<DatEntry*>;
|
||||||
|
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);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
94
src/DatEntry.h
Normal file
94
src/DatEntry.h
Normal file
@ -0,0 +1,94 @@
|
|||||||
|
/**
|
||||||
|
* @file DatEntry.h
|
||||||
|
* @date 20/09/2022
|
||||||
|
* @author JackCarterSmith
|
||||||
|
* @copyright GPL-v3.0
|
||||||
|
* @brief Data file entry descriptor class.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "RDI_Datatypes.h"
|
||||||
|
#include <vector>
|
||||||
|
#include <string>
|
||||||
|
|
||||||
|
|
||||||
|
#ifndef DATENTRY_H_
|
||||||
|
#define DATENTRY_H_
|
||||||
|
|
||||||
|
|
||||||
|
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 DatEntry {
|
||||||
|
public:
|
||||||
|
virtual ~DatEntry() = 0;
|
||||||
|
virtual bool isDirectory() = 0;
|
||||||
|
virtual bool isRootDirectory() = 0;
|
||||||
|
//virtual std::string toString() = 0;
|
||||||
|
virtual unsigned int getSize() = 0;
|
||||||
|
|
||||||
|
std::string getName() { return name; };
|
||||||
|
|
||||||
|
protected:
|
||||||
|
std::string name;
|
||||||
|
DAT_FILE_FLAGS fFlags;
|
||||||
|
};
|
||||||
|
|
||||||
|
inline DatEntry::~DatEntry() {}
|
||||||
|
|
||||||
|
class FileEntry : public DatEntry {
|
||||||
|
public:
|
||||||
|
FileEntry( std::string name, DAT_FILE_FLAGS fFlags, unsigned int size, MEMFILE fPtr );
|
||||||
|
~FileEntry();
|
||||||
|
|
||||||
|
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 DirectoryEntry : public DatEntry {
|
||||||
|
public:
|
||||||
|
DirectoryEntry( std::string name );
|
||||||
|
DirectoryEntry( std::string name, DAT_FILE_FLAGS fFlags );
|
||||||
|
DirectoryEntry( std::string name, DAT_FILE_FLAGS fFlags, DatEntry* hFileEntry );
|
||||||
|
~DirectoryEntry();
|
||||||
|
|
||||||
|
void ClearLinkedFiles();
|
||||||
|
void AddEntry( DatEntry* hFileEntry );
|
||||||
|
std::vector<DatEntry*> getFiles() { return *vSubFiles; }
|
||||||
|
|
||||||
|
//std::string toString();
|
||||||
|
bool isDirectory() { return true; }
|
||||||
|
bool isRootDirectory() { return rootDir; }
|
||||||
|
unsigned int getSize() { return vSubFiles->size(); }
|
||||||
|
|
||||||
|
private:
|
||||||
|
bool rootDir;
|
||||||
|
std::vector<DatEntry*> *vSubFiles;
|
||||||
|
};
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif /* DATENTRY_H_ */
|
100
src/RDI.cpp
Normal file
100
src/RDI.cpp
Normal file
@ -0,0 +1,100 @@
|
|||||||
|
/**
|
||||||
|
* @file RDI.cpp
|
||||||
|
* @date 15/09/2022
|
||||||
|
* @author JackCarterSmith
|
||||||
|
* @copyright GPL-v3.0
|
||||||
|
* @brief Rogue Data Interface library main entry file.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
#if defined(RDI_DLL)
|
||||||
|
# define RDI_DLLBUILD
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#include <iostream>
|
||||||
|
#include <string>
|
||||||
|
#include <vector>
|
||||||
|
#include <fstream>
|
||||||
|
#include "config.h"
|
||||||
|
#include "RDat.h"
|
||||||
|
#include "DatEntry.h"
|
||||||
|
#include "RDI.h"
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Internal variable
|
||||||
|
*/
|
||||||
|
static RDI::RDat *hRDat = nullptr;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Libs interface
|
||||||
|
*/
|
||||||
|
|
||||||
|
std::string RDI::getLibVersion() { return PRG_VERSION; }
|
||||||
|
|
||||||
|
void RDI::CreateRDatHandler( std::string roguePath ){
|
||||||
|
if (hRDat == nullptr) hRDat = new RDI::RDat(roguePath);
|
||||||
|
|
||||||
|
//return hRDat;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
unsigned char RDI::getSectionCount() {
|
||||||
|
if (hRDat == nullptr) return 0;
|
||||||
|
else return hRDat->getDataSectionCount();
|
||||||
|
}
|
||||||
|
|
||||||
|
std::string RDI::getSectionName( unsigned char id ) {
|
||||||
|
if (hRDat == nullptr) return "";
|
||||||
|
else return hRDat->getDataSectionName(id);
|
||||||
|
}
|
||||||
|
|
||||||
|
unsigned int RDI::getSectionOffset( unsigned char id ) {
|
||||||
|
if (hRDat == nullptr) return 0;
|
||||||
|
else return hRDat->getDataSectionOffset(id);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
unsigned int RDI::getDirectoryElementCount( std::string path ) {
|
||||||
|
DirectoryEntry* result = nullptr;
|
||||||
|
|
||||||
|
if (path.empty()) return 0;
|
||||||
|
|
||||||
|
result = dynamic_cast<DirectoryEntry *>(hRDat->getElement(boost::filesystem::path(path)));
|
||||||
|
|
||||||
|
if (result == nullptr) return 0;
|
||||||
|
else return result->getSize();
|
||||||
|
}
|
||||||
|
|
||||||
|
std::vector<std::string> RDI::getDirectoryElements( std::string path ) {
|
||||||
|
DirectoryEntry* de = nullptr;
|
||||||
|
std::vector<std::string> elementsNameArray;
|
||||||
|
elementsNameArray.clear();
|
||||||
|
|
||||||
|
if (!path.empty()) {
|
||||||
|
de = dynamic_cast<DirectoryEntry *>(hRDat->getElement(boost::filesystem::path(path)));
|
||||||
|
|
||||||
|
if (de != nullptr && de->isDirectory()) {
|
||||||
|
for (DatEntry* de2 : de->getFiles())
|
||||||
|
elementsNameArray.push_back(de2->getName());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return elementsNameArray;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool RDI::isElementDirectory( std::string path ) {
|
||||||
|
DatEntry* result = nullptr;
|
||||||
|
|
||||||
|
if (path.empty()) return false;
|
||||||
|
|
||||||
|
result = hRDat->getElement(boost::filesystem::path(path));
|
||||||
|
|
||||||
|
if (result == nullptr) return false;
|
||||||
|
else return (result->isDirectory() || result->isRootDirectory());
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void RDI::DestroyRDatHandler(){
|
||||||
|
if (hRDat) delete hRDat;
|
||||||
|
}
|
236
src/RDat.cpp
Normal file
236
src/RDat.cpp
Normal file
@ -0,0 +1,236 @@
|
|||||||
|
/**
|
||||||
|
* @file RDat.cpp
|
||||||
|
* @date 20/09/2022
|
||||||
|
* @author JackCarterSmith
|
||||||
|
* @copyright GPL-v3.0
|
||||||
|
* @brief Rogue Dat file class interface.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <iostream>
|
||||||
|
#include <fstream>
|
||||||
|
#include <vector>
|
||||||
|
#include <boost/filesystem.hpp>
|
||||||
|
#include <RSPModel.h>
|
||||||
|
#include <RSPTerrain.h>
|
||||||
|
#include <RSPTexture.h>
|
||||||
|
#include <RDI_Datatypes.h>
|
||||||
|
#include "DatEntry.h"
|
||||||
|
#include "data_struct.h"
|
||||||
|
#include "RDat.h"
|
||||||
|
|
||||||
|
|
||||||
|
using std::string;
|
||||||
|
using std::ios;
|
||||||
|
using std::vector;
|
||||||
|
using boost::filesystem::path;
|
||||||
|
using boost::filesystem::file_size;
|
||||||
|
|
||||||
|
|
||||||
|
namespace RDI {
|
||||||
|
|
||||||
|
RDat::RDat( string fPath ) {
|
||||||
|
RDI_RESULT errCode = RDI_OK;
|
||||||
|
|
||||||
|
this->workingDir = fPath;
|
||||||
|
|
||||||
|
// Process header file and dump data file in memory.
|
||||||
|
errCode = DumpLegacyFiles();
|
||||||
|
if (errCode == RDI_ERROR_FILESYSTEM) {
|
||||||
|
std::cout << "Data files (DATA.DAT/DATA.HDR) not found! Interrupt." << std::endl;
|
||||||
|
return;
|
||||||
|
} else if (errCode == RDI_ERROR_MEMORY) {
|
||||||
|
std::cout << "Memory allocation or file access failed! Interrupt." << std::endl;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Process data file tree and filter file subtype into list.
|
||||||
|
ProcessFilesTree();
|
||||||
|
}
|
||||||
|
|
||||||
|
RDat::~RDat() {
|
||||||
|
for ( DirectoryEntry* 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; }
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Helper function to search for legacy DATA.DAT/HDR and dump it in memory.
|
||||||
|
*
|
||||||
|
* @return Error status.
|
||||||
|
*/
|
||||||
|
RDI_RESULT RDat::DumpLegacyFiles() {
|
||||||
|
unsigned int i;
|
||||||
|
path fp(workingDir);
|
||||||
|
MEMFILE pTmpFile;
|
||||||
|
|
||||||
|
// If input as a directory, assume it's contain DATA.DAT/HDR.
|
||||||
|
if (boost::filesystem::is_directory(fp)) fp.append("DATA.HDR");
|
||||||
|
|
||||||
|
// If file specified in input is the "datas" file, process the header (HDR) before.
|
||||||
|
if (fp.extension() == ".DAT") fp.replace_extension(".HDR");
|
||||||
|
|
||||||
|
// Open and parse data header file.
|
||||||
|
//if (boost::filesystem::exists(fp)) return RDI_ERROR_FILESYSTEM;
|
||||||
|
pTmpFile = MallocFile(fp);
|
||||||
|
if (!pTmpFile) return RDI_ERROR_MEMORY;
|
||||||
|
|
||||||
|
cDatSection = file_size(fp) / sizeof(T_HDR_ENTRY);
|
||||||
|
pDatSection = new vector<struct dataSection>(cDatSection);
|
||||||
|
for ( i = 0; i < pDatSection->size(); i++ ) {
|
||||||
|
// Store header infos into structure to make easier access later.
|
||||||
|
pDatSection->at(i).name.append(((T_HDR_ENTRY*)(pTmpFile + i * sizeof(T_HDR_ENTRY)))->section_name);
|
||||||
|
pDatSection->at(i).offset = ((T_HDR_ENTRY*)(pTmpFile + i * sizeof(T_HDR_ENTRY)))->section_offset;
|
||||||
|
}
|
||||||
|
|
||||||
|
free(pTmpFile);
|
||||||
|
|
||||||
|
// 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);
|
||||||
|
if (!rDatPtr) return RDI_ERROR_MEMORY;
|
||||||
|
|
||||||
|
return RDI_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Dump file into to newly allocated memory.
|
||||||
|
* @param filePath File path.
|
||||||
|
*
|
||||||
|
* @return Start memory pointer of the file.
|
||||||
|
*/
|
||||||
|
MEMFILE RDat::MallocFile( path filePath ) {
|
||||||
|
const unsigned int size = file_size(filePath);
|
||||||
|
std::fstream rdf;
|
||||||
|
MEMFILE fPtr = NULL;
|
||||||
|
|
||||||
|
rdf.open(filePath.string(), ios::in | ios::binary);
|
||||||
|
if (rdf.is_open()) {
|
||||||
|
fPtr = (MEMFILE)malloc(size);
|
||||||
|
rdf.read(fPtr, size);
|
||||||
|
rdf.close();
|
||||||
|
}
|
||||||
|
|
||||||
|
return fPtr;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Helper function to process files content for further use in this library.
|
||||||
|
*
|
||||||
|
* @return Error status.
|
||||||
|
*/
|
||||||
|
RDI_RESULT RDat::ProcessFilesTree() {
|
||||||
|
unsigned int curEntriesCount = 0, i;
|
||||||
|
DirectoryEntry* curDir = nullptr;
|
||||||
|
MEMFILE pFileDescriptors = nullptr;
|
||||||
|
|
||||||
|
// Create new root files tree. One per data section.
|
||||||
|
pFTRoot = new std::vector<DirectoryEntry*>;
|
||||||
|
pFTRoot->clear();
|
||||||
|
for ( i = 0; i < cDatSection; i++ ) {
|
||||||
|
curDir = new DirectoryEntry(pDatSection->at(i).name);
|
||||||
|
pFTRoot->push_back(curDir);
|
||||||
|
|
||||||
|
// Recalculate files descriptor offset for current section.
|
||||||
|
pFileDescriptors = rDatPtr + pDatSection->at(i).offset +
|
||||||
|
((T_DAT_SECTION*)(rDatPtr + pDatSection->at(i).offset))->file_headers_offset;
|
||||||
|
curEntriesCount = (((T_DAT_SECTION*)(rDatPtr + pDatSection->at(i).offset))->file_headers_size) / 32;
|
||||||
|
|
||||||
|
// Process arborescente in recursive method.
|
||||||
|
ProcessDirectoryContents(curDir, pFileDescriptors, curEntriesCount, rDatPtr + pDatSection->at(i).offset);
|
||||||
|
}
|
||||||
|
|
||||||
|
return RDI_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
RDI_RESULT RDat::ProcessDirectoryContents( DirectoryEntry* pCurDir, MEMFILE pDesc, const unsigned int count, MEMFILE pSectionStart ) {
|
||||||
|
unsigned int i, newDRECnt;
|
||||||
|
DAT_FILE_FLAGS curEntryFlags = {0};
|
||||||
|
|
||||||
|
FileEntry* newFile = nullptr;
|
||||||
|
DirectoryEntry* newDir = nullptr;
|
||||||
|
std::string tmpStr;
|
||||||
|
|
||||||
|
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;
|
||||||
|
|
||||||
|
tmpStr.clear();
|
||||||
|
tmpStr.append(((T_FILE_HEADER*)(pDesc + i * sizeof(T_FILE_HEADER)))->name);
|
||||||
|
|
||||||
|
// Test for file or directory
|
||||||
|
if (!curEntryFlags.isDirectory) {
|
||||||
|
newFile = new FileEntry(tmpStr, curEntryFlags,
|
||||||
|
((T_FILE_HEADER*)(pDesc + i * sizeof(T_FILE_HEADER)))->datas_size,
|
||||||
|
pSectionStart + ((T_FILE_HEADER*)(pDesc + i * sizeof(T_FILE_HEADER)))->datas_offset);
|
||||||
|
pCurDir->AddEntry(newFile);
|
||||||
|
} else {
|
||||||
|
newDir = new DirectoryEntry(tmpStr, curEntryFlags);
|
||||||
|
pCurDir->AddEntry(newDir);
|
||||||
|
|
||||||
|
// 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);
|
||||||
|
if (newDRECnt <= count) i += newDRECnt;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return RDI_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
DatEntry *RDat::getElement( boost::filesystem::path virtualDirPath ) {
|
||||||
|
bool skip = false;
|
||||||
|
boost::filesystem::path newPath;
|
||||||
|
|
||||||
|
for ( DatEntry* de : *pFTRoot ) {
|
||||||
|
if (virtualDirPath.size() == 1 || virtualDirPath.begin() == --virtualDirPath.end()) {
|
||||||
|
if (de->getName() == virtualDirPath.filename().string())
|
||||||
|
return de;
|
||||||
|
} else {
|
||||||
|
if (de->getName() == virtualDirPath.begin()->string()) {
|
||||||
|
for (auto& sp : virtualDirPath) {
|
||||||
|
if (skip)
|
||||||
|
newPath.append(sp);
|
||||||
|
skip = true;
|
||||||
|
}
|
||||||
|
return SearchSectionForEntry(dynamic_cast<DirectoryEntry *>(de), newPath);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
DatEntry *RDat::SearchSectionForEntry( DirectoryEntry *curDir, boost::filesystem::path virtualDirPath ) {
|
||||||
|
bool skip = false;
|
||||||
|
boost::filesystem::path newPath;
|
||||||
|
|
||||||
|
for ( DatEntry* e : curDir->getFiles() ) {
|
||||||
|
if (virtualDirPath.size() == 1 || virtualDirPath.begin() == --virtualDirPath.end()) {
|
||||||
|
if (e->getName() == virtualDirPath.filename().string())
|
||||||
|
return e;
|
||||||
|
} else {
|
||||||
|
if (e->isDirectory() && (e->getName() == virtualDirPath.begin()->string())) {
|
||||||
|
for (auto& sp : virtualDirPath) {
|
||||||
|
if (skip)
|
||||||
|
newPath.append(sp);
|
||||||
|
skip = true;
|
||||||
|
}
|
||||||
|
//TODO: add safety when trying to access inside a file
|
||||||
|
return SearchSectionForEntry(dynamic_cast<DirectoryEntry *>(e), newPath);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
71
src/RDat.h
Normal file
71
src/RDat.h
Normal file
@ -0,0 +1,71 @@
|
|||||||
|
/**
|
||||||
|
* @file RDat.h
|
||||||
|
* @date 15/09/2022
|
||||||
|
* @author JackCarterSmith
|
||||||
|
* @copyright GPL-v3.0
|
||||||
|
* @brief Rogue Dat file class interface.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <boost/filesystem.hpp>
|
||||||
|
#include <vector>
|
||||||
|
#include "DatEntry.h"
|
||||||
|
#include "RDI_Datatypes.h"
|
||||||
|
|
||||||
|
|
||||||
|
#ifndef RDAT_H_
|
||||||
|
#define RDAT_H_
|
||||||
|
|
||||||
|
namespace RDI {
|
||||||
|
|
||||||
|
struct dataSection {
|
||||||
|
std::string name = "";
|
||||||
|
unsigned int offset = 0;
|
||||||
|
};
|
||||||
|
|
||||||
|
class RDat final {
|
||||||
|
public:
|
||||||
|
RDat( std::string fPath );
|
||||||
|
~RDat();
|
||||||
|
|
||||||
|
MEMFILE getRDat() {
|
||||||
|
return rDatPtr;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::string getWorkingDirectory() { return workingDir; }
|
||||||
|
void setWorkingDirectory( std::string newPath ) { workingDir = newPath; }
|
||||||
|
|
||||||
|
unsigned char getDataSectionCount() { return cDatSection; }
|
||||||
|
std::string getDataSectionName( unsigned char id );
|
||||||
|
unsigned int getDataSectionOffset( unsigned char id );
|
||||||
|
|
||||||
|
DatEntry *getElement( boost::filesystem::path virtualDirPath );
|
||||||
|
|
||||||
|
private:
|
||||||
|
std::string workingDir = ".";
|
||||||
|
|
||||||
|
unsigned char cDatSection = 0;
|
||||||
|
std::vector<struct dataSection> *pDatSection = nullptr;
|
||||||
|
MEMFILE rDatPtr = nullptr;
|
||||||
|
|
||||||
|
std::vector<DirectoryEntry*> *pFTRoot = nullptr;
|
||||||
|
|
||||||
|
/* File processing methods */
|
||||||
|
RDI_RESULT DumpLegacyFiles();
|
||||||
|
MEMFILE MallocFile( boost::filesystem::path filePath );
|
||||||
|
RDI_RESULT ProcessFilesTree();
|
||||||
|
RDI_RESULT ProcessDirectoryContents(
|
||||||
|
DirectoryEntry* pCurDir,
|
||||||
|
MEMFILE pDesc,
|
||||||
|
const unsigned int count,
|
||||||
|
MEMFILE pSectionStart
|
||||||
|
);
|
||||||
|
|
||||||
|
/* Tree manipulation/parse methods */
|
||||||
|
DatEntry *SearchSectionForEntry( DirectoryEntry *curDir, boost::filesystem::path virtualDirPath);
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
} /* namespace RDI */
|
||||||
|
|
||||||
|
#endif /* RDAT_H_ */
|
49
src/bundle_struct.h
Normal file
49
src/bundle_struct.h
Normal file
@ -0,0 +1,49 @@
|
|||||||
|
/**
|
||||||
|
* @file bundle_struct.h
|
||||||
|
* @date 16/09/2022
|
||||||
|
* @author JackCarterSmith
|
||||||
|
* @copyright GPL-v3.0
|
||||||
|
* @brief Bundle (000/001) file mapping definition.
|
||||||
|
*
|
||||||
|
* @todo Should not be used for now, bundle files contains game menu elements. May be for graph assets?
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef BUNDLE_STRUCT_H_
|
||||||
|
#define BUNDLE_STRUCT_H_
|
||||||
|
|
||||||
|
#ifndef PACK
|
||||||
|
# if defined(_MSC_VER)
|
||||||
|
# define PACK
|
||||||
|
# elif defined(__GNUC__)
|
||||||
|
# define PACK __attribute__((packed))
|
||||||
|
# endif
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
namespace RDI {
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////////////////
|
||||||
|
// Declaration of Memory Mapped Structure
|
||||||
|
// Caution: the place of variable is important for correct mapping!
|
||||||
|
////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
#if defined(_MSC_VER)
|
||||||
|
#pragma pack(push, 1)
|
||||||
|
#endif
|
||||||
|
|
||||||
|
typedef struct PACK file_header {
|
||||||
|
unsigned int datas_offset;
|
||||||
|
} T_FILE_HEADER;
|
||||||
|
|
||||||
|
typedef struct PACK dat_section {
|
||||||
|
unsigned int file_headers_offset;
|
||||||
|
} T_DAT_SECTION;
|
||||||
|
|
||||||
|
#if defined(_MSC_VER)
|
||||||
|
#pragma pack(pop)
|
||||||
|
#endif
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif /* BUNDLE_STRUCT_H_ */
|
73
src/data_struct.h
Normal file
73
src/data_struct.h
Normal file
@ -0,0 +1,73 @@
|
|||||||
|
/**
|
||||||
|
* @file data_struct.h
|
||||||
|
* @date 16/09/2022
|
||||||
|
* @author JackCarterSmith
|
||||||
|
* @copyright GPL-v3.0
|
||||||
|
* @brief Data file mapping definition.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef DATA_STRUCT_H_
|
||||||
|
#define DATA_STRUCT_H_
|
||||||
|
|
||||||
|
#ifndef PACK
|
||||||
|
# if defined(_MSC_VER)
|
||||||
|
# define PACK
|
||||||
|
# elif defined(__GNUC__)
|
||||||
|
# define PACK __attribute__((packed))
|
||||||
|
# endif
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
namespace RDI {
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////////////////
|
||||||
|
// Declaration of Memory Mapped Structure
|
||||||
|
// Caution: the place of variable is important for correct mapping!
|
||||||
|
////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
#if defined(_MSC_VER)
|
||||||
|
#pragma pack(push, 1)
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/*
|
||||||
|
* DATA.DAT content type
|
||||||
|
* +---------------+-------------------------------------------+
|
||||||
|
* | T_DAT_SECTION | T_FILE_HEADER (file_headers_size x bytes) |
|
||||||
|
* +---------------+-------------------------------------------+
|
||||||
|
*/
|
||||||
|
typedef struct PACK file_header {
|
||||||
|
unsigned int datas_offset; // From the start of section
|
||||||
|
unsigned int datas_size; // If file is directory, equal to sum of it's file.
|
||||||
|
unsigned int reserved0; // 0xFFFFFFFF
|
||||||
|
unsigned short flags;
|
||||||
|
unsigned short dir_entries_size; // If directory = sum of files entry size + itself, 0 if standard file.
|
||||||
|
char name[16]; // File extension is UPPERCASE, separated of file name by '_'.
|
||||||
|
} T_FILE_HEADER;
|
||||||
|
|
||||||
|
typedef struct PACK dat_section {
|
||||||
|
unsigned int file_headers_offset; // From the start of section
|
||||||
|
unsigned int file_headers_size;
|
||||||
|
unsigned char files_datas; // Should be used as start pointer for memcpy.
|
||||||
|
} T_DAT_SECTION;
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
* DATA.HDR content type
|
||||||
|
* Entries are in a row, test for EOF.
|
||||||
|
*/
|
||||||
|
typedef struct PACK hdr_entry {
|
||||||
|
char section_name[16];
|
||||||
|
unsigned int reserved0; // 12B of zeros
|
||||||
|
unsigned int reserved1;
|
||||||
|
unsigned int reserved2;
|
||||||
|
unsigned int section_offset;
|
||||||
|
} T_HDR_ENTRY;
|
||||||
|
|
||||||
|
#if defined(_MSC_VER)
|
||||||
|
#pragma pack(pop)
|
||||||
|
#endif
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif /* DATA_STRUCT_H_ */
|
23
src/datfiles/HMT.cpp
Normal file
23
src/datfiles/HMT.cpp
Normal file
@ -0,0 +1,23 @@
|
|||||||
|
/**
|
||||||
|
* @file HMT.cpp
|
||||||
|
* @date 15/09/2022
|
||||||
|
* @author JackCarterSmith
|
||||||
|
* @copyright GPL-v3.0
|
||||||
|
* @brief HMT file object class.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "HMT.h"
|
||||||
|
|
||||||
|
namespace RDI {
|
||||||
|
|
||||||
|
HMT::HMT() {
|
||||||
|
// TODO Auto-generated constructor stub
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
HMT::~HMT() {
|
||||||
|
// TODO Auto-generated destructor stub
|
||||||
|
}
|
||||||
|
|
||||||
|
} /* namespace RDI */
|
23
src/datfiles/HMT.h
Normal file
23
src/datfiles/HMT.h
Normal file
@ -0,0 +1,23 @@
|
|||||||
|
/**
|
||||||
|
* @file HMT.h
|
||||||
|
* @date 15/09/2022
|
||||||
|
* @author JackCarterSmith
|
||||||
|
* @copyright GPL-v3.0
|
||||||
|
* @brief HMT file object class.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef SRC_DATFILES_HMT_H_
|
||||||
|
#define SRC_DATFILES_HMT_H_
|
||||||
|
|
||||||
|
namespace RDI {
|
||||||
|
|
||||||
|
class HMT {
|
||||||
|
public:
|
||||||
|
HMT();
|
||||||
|
virtual ~HMT();
|
||||||
|
};
|
||||||
|
|
||||||
|
} /* namespace RDI */
|
||||||
|
|
||||||
|
#endif /* SRC_DATFILES_HMT_H_ */
|
75
tools/RDIdebug.cpp
Normal file
75
tools/RDIdebug.cpp
Normal file
@ -0,0 +1,75 @@
|
|||||||
|
/**
|
||||||
|
* @file RDIdebug.cpp
|
||||||
|
* @date 17/09/2022
|
||||||
|
* @author JackCarterSmith
|
||||||
|
* @copyright GPL-v3.0
|
||||||
|
* @brief Debug app to test functions of RDI library.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <iostream>
|
||||||
|
#include <string>
|
||||||
|
#include <boost/filesystem.hpp>
|
||||||
|
#include <RDI.h>
|
||||||
|
|
||||||
|
|
||||||
|
void PrintVirtualDirectoryContents( boost::filesystem::path, std::string );
|
||||||
|
|
||||||
|
int main( int argc, char *argv[] ) {
|
||||||
|
unsigned int i;
|
||||||
|
boost::filesystem::path pathBuilder;
|
||||||
|
std::string prefix;
|
||||||
|
|
||||||
|
printf("Using RDI lib v%s\n\n", RDI::getLibVersion().c_str());
|
||||||
|
//cout << "Using RDI lib v" << RDI::getLibVersion() << endl << endl;
|
||||||
|
|
||||||
|
if ( argc > 1 )
|
||||||
|
RDI::CreateRDatHandler(argv[1]);
|
||||||
|
else
|
||||||
|
RDI::CreateRDatHandler(".");
|
||||||
|
|
||||||
|
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));
|
||||||
|
}
|
||||||
|
|
||||||
|
//prefix.append("\t");
|
||||||
|
prefix.append(" ");
|
||||||
|
printf("\nSections files root:\n");
|
||||||
|
for ( i = 0; i < RDI::getSectionCount(); i++ ) {
|
||||||
|
printf("%s:\n", RDI::getSectionName(i).c_str()); // Print root trees
|
||||||
|
|
||||||
|
pathBuilder.clear();
|
||||||
|
pathBuilder.concat(RDI::getSectionName(i));
|
||||||
|
|
||||||
|
PrintVirtualDirectoryContents(pathBuilder, prefix);
|
||||||
|
}
|
||||||
|
|
||||||
|
RDI::DestroyRDatHandler();
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
void PrintVirtualDirectoryContents( boost::filesystem::path path, std::string outPrefix ) {
|
||||||
|
auto curDirElementsName = RDI::getDirectoryElements(path.string());
|
||||||
|
auto newPath = boost::filesystem::path(path);
|
||||||
|
auto newOutPrefix = std::string(outPrefix);
|
||||||
|
|
||||||
|
for ( std::string eName : curDirElementsName ) {
|
||||||
|
newPath.clear();
|
||||||
|
newPath.concat(path);
|
||||||
|
newOutPrefix.clear();
|
||||||
|
newOutPrefix.append(outPrefix);
|
||||||
|
|
||||||
|
newPath.append(eName);
|
||||||
|
if (RDI::isElementDirectory(newPath.string())) {
|
||||||
|
printf("%s%s:\n", outPrefix.c_str(), eName.c_str());
|
||||||
|
//newOutPrefix.append("\t");
|
||||||
|
newOutPrefix.append(" ");
|
||||||
|
PrintVirtualDirectoryContents(newPath, newOutPrefix);
|
||||||
|
} else {
|
||||||
|
printf("%s%s\n", newOutPrefix.c_str(), eName.c_str());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
Loading…
x
Reference in New Issue
Block a user