Compare commits
36 Commits
Author | SHA1 | Date | |
---|---|---|---|
19c544441b | |||
94d2cb6e56 | |||
42de1f7dad | |||
e03f3436a6 | |||
0c8282ab5d | |||
d302d7ebd5 | |||
d6b94f8c79 | |||
49fa1278ad | |||
e2b5f4c841 | |||
4e8da870d9 | |||
3ffc546e1e | |||
6fa5719957 | |||
7c0088f311 | |||
56b4394f3b | |||
fd9f1a5979 | |||
f5c817b384 | |||
3b1b358363 | |||
151769a2d3 | |||
8ce721fd9c | |||
a6e16e7210 | |||
2b7bc30bcc | |||
93442c9e4e | |||
7e955457ca | |||
2517c3b265 | |||
df4c637b94 | |||
5716962abb | |||
9f98830fce | |||
84e0a0b904 | |||
58b120e7bf | |||
4f665d159b | |||
74d32a20f4 | |||
82dddcb5dc | |||
a536991daa | |||
337fa39535 | |||
a7e1fd65cf | |||
854dba8a26 |
4
.gitignore
vendored
4
.gitignore
vendored
@ -15,7 +15,8 @@
|
|||||||
# Precompiled Headers
|
# Precompiled Headers
|
||||||
*.gch
|
*.gch
|
||||||
*.pch
|
*.pch
|
||||||
src/config.h
|
RSPTextureLib/src/config.h
|
||||||
|
RSETexture/src/config.h
|
||||||
|
|
||||||
# Libraries
|
# Libraries
|
||||||
*.lib
|
*.lib
|
||||||
@ -74,3 +75,4 @@ install_manifest.txt
|
|||||||
compile_commands.json
|
compile_commands.json
|
||||||
CTestTestfile.cmake
|
CTestTestfile.cmake
|
||||||
_deps
|
_deps
|
||||||
|
CMakeUserPresets.json
|
||||||
|
142
CMakeLists.txt
142
CMakeLists.txt
@ -1,48 +1,94 @@
|
|||||||
# CMakeLists.txt
|
# CMakeLists.txt
|
||||||
|
|
||||||
# Written by JackCarterSmith, 2020
|
####################################################
|
||||||
# This code is released under the RSE license.
|
# Written by JackCarterSmith, 2022
|
||||||
|
# This code is released under the RSE license.
|
||||||
cmake_minimum_required(VERSION 3.1)
|
####################################################
|
||||||
cmake_policy(VERSION 3.1)
|
|
||||||
|
|
||||||
# define project
|
# CMake requirement and general configuration
|
||||||
project(rse-texture VERSION 1.0.1 DESCRIPTION "RogueSquadron Extractor - Texture" LANGUAGES C)
|
cmake_minimum_required(VERSION 3.15)
|
||||||
set(CMAKE_BUILD_TYPE Release)
|
cmake_policy(VERSION 3.15)
|
||||||
set(RSE_TEX_NAME RSE_Texture-${PROJECT_VERSION_MAJOR}.${PROJECT_VERSION_MINOR})
|
set(CMAKE_MODULE_PATH ${CMAKE_BINARY_DIR})
|
||||||
configure_file(${CMAKE_CURRENT_SOURCE_DIR}/src/config.h.in ${CMAKE_CURRENT_SOURCE_DIR}/src/config.h @ONLY)
|
if(DEFINED ENV{MS_COMPATIBLE})
|
||||||
|
set(CMAKE_GNUtoMS ON) # Enable compatibility level to exported libraries
|
||||||
include(CheckIncludeFile)
|
endif()
|
||||||
include(CheckCSourceCompiles)
|
|
||||||
|
|
||||||
# needed packages
|
# Project definition
|
||||||
|
if(DEFINED ENV{CI}) # Jenkins CI integration mode
|
||||||
find_package(ZLIB REQUIRED)
|
project(rse-texture VERSION $ENV{CI_VERSION}.$ENV{CI_BUILD_NUMBER} DESCRIPTION "RogueSquadron Extractor - Texture" LANGUAGES C)
|
||||||
include_directories(${ZLIB_INCLUDE_DIR})
|
set(RSE_TEXTURE_NAME $ENV{CI_OUTPUT_NAME})
|
||||||
find_package(PNG REQUIRED)
|
else() # Standalone project mode, should not be used for release.
|
||||||
include_directories(${PNG_INCLUDE_DIR})
|
project(rse-texture VERSION 2.1.0 DESCRIPTION "RogueSquadron Extractor - Texture" LANGUAGES C)
|
||||||
|
set(RSE_TEXTURE_NAME RSETexture)
|
||||||
# define src/headers files
|
endif()
|
||||||
|
set(RSP_TEXTURE_LIB_NAME RSPTexture${PROJECT_VERSION_MAJOR}${PROJECT_VERSION_MINOR})
|
||||||
FILE(GLOB RSE_TEX_SRCS src/*.c)
|
|
||||||
FILE(GLOB RSE_TEX_HRDS src/*.h)
|
set(INSTALL_BIN_DIR "${CMAKE_INSTALL_PREFIX}/bin" CACHE PATH "Installation directory for executables")
|
||||||
SOURCE_GROUP("Source Files" FILES ${RSE_TEX_SRCS})
|
set(INSTALL_LIB_DIR "${CMAKE_INSTALL_PREFIX}/lib" CACHE PATH "Installation directory for libraries")
|
||||||
SOURCE_GROUP("Header Files" FILES ${RSE_TEX_HRDS})
|
set(INSTALL_INC_DIR "${CMAKE_INSTALL_PREFIX}/include" CACHE PATH "Installation directory for headers")
|
||||||
|
|
||||||
# begin building RSE-Texture
|
# Compilation option
|
||||||
|
option(RSPTEXTURE_SHARED "Build shared lib" ON)
|
||||||
#include_directories(${CMAKE_CURRENT_SOURCE_DIR})
|
option(RSPTEXTURE_STATIC "Build static lib" ON)
|
||||||
add_executable(rse-texture ${RSE_TEX_SRCS} ${RSE_TEX_HRDS})
|
option(BUILD_TOOLS "Build lib tools" ON)
|
||||||
set_target_properties(rse-texture PROPERTIES OUTPUT_NAME ${RSE_TEX_NAME})
|
|
||||||
if(MSVC)
|
|
||||||
# msvc does not append 'lib' - do it here to have consistent name
|
# Push compile infos to source
|
||||||
set_target_properties(rse-texture PROPERTIES PREFIX "lib")
|
configure_file(${CMAKE_CURRENT_SOURCE_DIR}/config.h.in ${CMAKE_CURRENT_SOURCE_DIR}/RSPTextureLib/src/config.h @ONLY)
|
||||||
set_target_properties(rse-texture PROPERTIES IMPORT_PREFIX "lib")
|
#configure_file(${CMAKE_CURRENT_SOURCE_DIR}/config.h.in ${CMAKE_CURRENT_SOURCE_DIR}/RSETexture/src/config.h @ONLY)
|
||||||
endif()
|
|
||||||
target_link_libraries(rse-texture ${ZLIB_LIBRARIES} ${PNG_LIBRARIES})
|
|
||||||
|
# The project is divided in two parts:
|
||||||
# install executable
|
# - RSPTextureLib is the parser library for textures data, it's take HMT file as input and output extracted datas.
|
||||||
|
# It is intended to be used by others apps like rendering engine or others.
|
||||||
install(TARGETS rse-texture
|
# - RSETexture is the standalone application of the library, take HMT file in argument and output PNG file.
|
||||||
RUNTIME DESTINATION bin
|
# Artists or users can directly use this program to retrieve data in common datas format.
|
||||||
)
|
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(RSE_TEXTURE_TARGETS_LIST)
|
||||||
|
add_subdirectory(RSPTextureLib)
|
||||||
|
add_subdirectory(RSETexture)
|
||||||
|
if(RSPTEXTURE_SHARED)
|
||||||
|
list(APPEND RSE_TEXTURE_TARGETS_LIST rsp-texture-lib)
|
||||||
|
endif()
|
||||||
|
if(RSPTEXTURE_STATIC)
|
||||||
|
list(APPEND RSE_TEXTURE_TARGETS_LIST rsp-texture-libstatic)
|
||||||
|
endif()
|
||||||
|
if(NOT RSE_TEXTURE_TARGETS_LIST)
|
||||||
|
message(SEND_ERROR
|
||||||
|
"No library variant selected to build. "
|
||||||
|
"Please enable at least one of the following options: "
|
||||||
|
"RSPTEXTURE_STATIC, RSPTEXTURE_SHARED")
|
||||||
|
endif()
|
||||||
|
if(BUILD_TOOLS)
|
||||||
|
list(APPEND RSE_TEXTURE_TARGETS_LIST rse-texture)
|
||||||
|
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_PUBLIC_HRDS} DESTINATION ${INSTALL_INC_DIR})
|
||||||
|
|
||||||
|
# Install project artifacts
|
||||||
|
install(TARGETS ${RSE_TEXTURE_TARGETS_LIST}
|
||||||
|
RUNTIME DESTINATION ${INSTALL_BIN_DIR}
|
||||||
|
LIBRARY DESTINATION ${INSTALL_LIB_DIR}
|
||||||
|
ARCHIVE DESTINATION ${INSTALL_LIB_DIR}
|
||||||
|
)
|
||||||
|
74
Jenkinsfile
vendored
Normal file
74
Jenkinsfile
vendored
Normal file
@ -0,0 +1,74 @@
|
|||||||
|
pipeline {
|
||||||
|
agent any
|
||||||
|
options {
|
||||||
|
skipDefaultCheckout(true)
|
||||||
|
}
|
||||||
|
environment {
|
||||||
|
CI_OUTPUT_NAME = "RSETexture"
|
||||||
|
CI_VERSION = "2.1.0"
|
||||||
|
CI_BUILD_NUMBER = "$BUILD_NUMBER"
|
||||||
|
}
|
||||||
|
stages {
|
||||||
|
stage('Prepare') {
|
||||||
|
steps {
|
||||||
|
cleanWs()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
stage('Build') {
|
||||||
|
steps {
|
||||||
|
parallel(
|
||||||
|
linux: {
|
||||||
|
dir("linux") {
|
||||||
|
checkout([$class: 'GitSCM', branches: [[name: '**']], browser: [$class: 'GiteaBrowser', repoUrl: 'https://git.jcsmith.fr/JCS-Prod/RSE-Texture'], extensions: [], userRemoteConfigs: [[credentialsId: 'jenkins-ssh', url: 'ssh://git@git.jcsmith.fr:2322/JCS-Prod/RSE-Texture.git']]])
|
||||||
|
sh 'git submodule update --init --recursive'
|
||||||
|
sh 'conan install . -of build -s build_type=Release -o "&:tools=True" -pr:b=default -pr:h=default --build=missing'
|
||||||
|
cmakeBuild buildDir: 'build', cmakeArgs: '-DCMAKE_TOOLCHAIN_FILE=conan_toolchain.cmake -DRSPTEXTURE_SHARED=ON -DRSPTEXTURE_STATIC=OFF -DBUILD_TOOLS=ON -DCMAKE_POLICY_DEFAULT_CMP0091=NEW -DCMAKE_BUILD_TYPE=Release', installation: 'latest', steps: [[args: 'all']]
|
||||||
|
}
|
||||||
|
},
|
||||||
|
windows: {
|
||||||
|
dir("windows") {
|
||||||
|
checkout([$class: 'GitSCM', branches: [[name: '**']], browser: [$class: 'GiteaBrowser', repoUrl: 'https://git.jcsmith.fr/JCS-Prod/RSE-Terrain'], extensions: [], userRemoteConfigs: [[credentialsId: 'jenkins-ssh', url: 'ssh://git@git.jcsmith.fr:2322/JCS-Prod/RSE-Texture.git']]])
|
||||||
|
sh 'git submodule update --init --recursive'
|
||||||
|
sh 'conan install . -of build -s build_type=Release -o "&:tools=True" -pr:b=default -pr:h=windows --build=missing'
|
||||||
|
cmakeBuild buildDir: 'build', cmakeArgs: '-DCMAKE_TOOLCHAIN_FILE=conan_toolchain.cmake -DRSPTEXTURE_SHARED=ON -DRSPTEXTURE_STATIC=OFF -DBUILD_TOOLS=ON -DCMAKE_POLICY_DEFAULT_CMP0091=NEW -DCMAKE_BUILD_TYPE=Release -DCMAKE_SYSTEM_NAME=Windows -DCMAKE_C_COMPILER=x86_64-w64-mingw32-gcc -DCMAKE_RC_COMPILER=x86_64-w64-mingw32-windres', installation: 'latest', steps: [[args: 'all']]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
stage('Deploy') {
|
||||||
|
steps {
|
||||||
|
dir("zip_linux") {
|
||||||
|
sh 'cp -R ../linux/build/bin ../linux/build/lib ../linux/RSPTextureLib/include .'
|
||||||
|
}
|
||||||
|
dir("zip_win") {
|
||||||
|
sh 'cp -R ../windows/build/bin ../windows/build/lib ../windows/RSPTextureLib/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)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
*/
|
||||||
|
}
|
134
LICENSE-libpng
Normal file
134
LICENSE-libpng
Normal file
@ -0,0 +1,134 @@
|
|||||||
|
COPYRIGHT NOTICE, DISCLAIMER, and LICENSE
|
||||||
|
=========================================
|
||||||
|
|
||||||
|
PNG Reference Library License version 2
|
||||||
|
---------------------------------------
|
||||||
|
|
||||||
|
* Copyright (c) 1995-2019 The PNG Reference Library Authors.
|
||||||
|
* Copyright (c) 2018-2019 Cosmin Truta.
|
||||||
|
* Copyright (c) 2000-2002, 2004, 2006-2018 Glenn Randers-Pehrson.
|
||||||
|
* Copyright (c) 1996-1997 Andreas Dilger.
|
||||||
|
* Copyright (c) 1995-1996 Guy Eric Schalnat, Group 42, Inc.
|
||||||
|
|
||||||
|
The software is supplied "as is", without warranty of any kind,
|
||||||
|
express or implied, including, without limitation, the warranties
|
||||||
|
of merchantability, fitness for a particular purpose, title, and
|
||||||
|
non-infringement. In no event shall the Copyright owners, or
|
||||||
|
anyone distributing the software, be liable for any damages or
|
||||||
|
other liability, whether in contract, tort or otherwise, arising
|
||||||
|
from, out of, or in connection with the software, or the use or
|
||||||
|
other dealings in the software, even if advised of the possibility
|
||||||
|
of such damage.
|
||||||
|
|
||||||
|
Permission is hereby granted to use, copy, modify, and distribute
|
||||||
|
this software, or portions hereof, for any purpose, without fee,
|
||||||
|
subject to the following restrictions:
|
||||||
|
|
||||||
|
1. The origin of this software must not be misrepresented; you
|
||||||
|
must not claim that you wrote the original software. If you
|
||||||
|
use this software in a product, an acknowledgment in the product
|
||||||
|
documentation would be appreciated, but is not required.
|
||||||
|
|
||||||
|
2. Altered source versions must be plainly marked as such, and must
|
||||||
|
not be misrepresented as being the original software.
|
||||||
|
|
||||||
|
3. This Copyright notice may not be removed or altered from any
|
||||||
|
source or altered source distribution.
|
||||||
|
|
||||||
|
|
||||||
|
PNG Reference Library License version 1 (for libpng 0.5 through 1.6.35)
|
||||||
|
-----------------------------------------------------------------------
|
||||||
|
|
||||||
|
libpng versions 1.0.7, July 1, 2000, through 1.6.35, July 15, 2018 are
|
||||||
|
Copyright (c) 2000-2002, 2004, 2006-2018 Glenn Randers-Pehrson, are
|
||||||
|
derived from libpng-1.0.6, and are distributed according to the same
|
||||||
|
disclaimer and license as libpng-1.0.6 with the following individuals
|
||||||
|
added to the list of Contributing Authors:
|
||||||
|
|
||||||
|
Simon-Pierre Cadieux
|
||||||
|
Eric S. Raymond
|
||||||
|
Mans Rullgard
|
||||||
|
Cosmin Truta
|
||||||
|
Gilles Vollant
|
||||||
|
James Yu
|
||||||
|
Mandar Sahastrabuddhe
|
||||||
|
Google Inc.
|
||||||
|
Vadim Barkov
|
||||||
|
|
||||||
|
and with the following additions to the disclaimer:
|
||||||
|
|
||||||
|
There is no warranty against interference with your enjoyment of
|
||||||
|
the library or against infringement. There is no warranty that our
|
||||||
|
efforts or the library will fulfill any of your particular purposes
|
||||||
|
or needs. This library is provided with all faults, and the entire
|
||||||
|
risk of satisfactory quality, performance, accuracy, and effort is
|
||||||
|
with the user.
|
||||||
|
|
||||||
|
Some files in the "contrib" directory and some configure-generated
|
||||||
|
files that are distributed with libpng have other copyright owners, and
|
||||||
|
are released under other open source licenses.
|
||||||
|
|
||||||
|
libpng versions 0.97, January 1998, through 1.0.6, March 20, 2000, are
|
||||||
|
Copyright (c) 1998-2000 Glenn Randers-Pehrson, are derived from
|
||||||
|
libpng-0.96, and are distributed according to the same disclaimer and
|
||||||
|
license as libpng-0.96, with the following individuals added to the
|
||||||
|
list of Contributing Authors:
|
||||||
|
|
||||||
|
Tom Lane
|
||||||
|
Glenn Randers-Pehrson
|
||||||
|
Willem van Schaik
|
||||||
|
|
||||||
|
libpng versions 0.89, June 1996, through 0.96, May 1997, are
|
||||||
|
Copyright (c) 1996-1997 Andreas Dilger, are derived from libpng-0.88,
|
||||||
|
and are distributed according to the same disclaimer and license as
|
||||||
|
libpng-0.88, with the following individuals added to the list of
|
||||||
|
Contributing Authors:
|
||||||
|
|
||||||
|
John Bowler
|
||||||
|
Kevin Bracey
|
||||||
|
Sam Bushell
|
||||||
|
Magnus Holmgren
|
||||||
|
Greg Roelofs
|
||||||
|
Tom Tanner
|
||||||
|
|
||||||
|
Some files in the "scripts" directory have other copyright owners,
|
||||||
|
but are released under this license.
|
||||||
|
|
||||||
|
libpng versions 0.5, May 1995, through 0.88, January 1996, are
|
||||||
|
Copyright (c) 1995-1996 Guy Eric Schalnat, Group 42, Inc.
|
||||||
|
|
||||||
|
For the purposes of this copyright and license, "Contributing Authors"
|
||||||
|
is defined as the following set of individuals:
|
||||||
|
|
||||||
|
Andreas Dilger
|
||||||
|
Dave Martindale
|
||||||
|
Guy Eric Schalnat
|
||||||
|
Paul Schmidt
|
||||||
|
Tim Wegner
|
||||||
|
|
||||||
|
The PNG Reference Library is supplied "AS IS". The Contributing
|
||||||
|
Authors and Group 42, Inc. disclaim all warranties, expressed or
|
||||||
|
implied, including, without limitation, the warranties of
|
||||||
|
merchantability and of fitness for any purpose. The Contributing
|
||||||
|
Authors and Group 42, Inc. assume no liability for direct, indirect,
|
||||||
|
incidental, special, exemplary, or consequential damages, which may
|
||||||
|
result from the use of the PNG Reference Library, even if advised of
|
||||||
|
the possibility of such damage.
|
||||||
|
|
||||||
|
Permission is hereby granted to use, copy, modify, and distribute this
|
||||||
|
source code, or portions hereof, for any purpose, without fee, subject
|
||||||
|
to the following restrictions:
|
||||||
|
|
||||||
|
1. The origin of this source code must not be misrepresented.
|
||||||
|
|
||||||
|
2. Altered versions must be plainly marked as such and must not
|
||||||
|
be misrepresented as being the original source.
|
||||||
|
|
||||||
|
3. This Copyright notice may not be removed or altered from any
|
||||||
|
source or altered source distribution.
|
||||||
|
|
||||||
|
The Contributing Authors and Group 42, Inc. specifically permit,
|
||||||
|
without fee, and encourage the use of this source code as a component
|
||||||
|
to supporting the PNG file format in commercial products. If you use
|
||||||
|
this source code in a product, acknowledgment is not required but would
|
||||||
|
be appreciated.
|
55
README.md
55
README.md
@ -7,7 +7,7 @@ The collection consist of few independants modules, each of them deals with spec
|
|||||||
|
|
||||||
All modules are independants. This is the **'TEXTURE'** module.
|
All modules are independants. This is the **'TEXTURE'** module.
|
||||||
|
|
||||||
:exclamation: **Master branch is ugly for now and should not be used, please take only released versions.** :exclamation:
|
[](https://ci.jcsmith.fr/job/JCS-Prod/job/RSE-Texture/job/master/)
|
||||||
|
|
||||||
## TEXTURE MODULE
|
## TEXTURE MODULE
|
||||||
|
|
||||||
@ -20,36 +20,63 @@ This module can do:
|
|||||||
- Manage transparent textures,
|
- Manage transparent textures,
|
||||||
- Fixed some errored RGB color encoding.
|
- Fixed some errored RGB color encoding.
|
||||||
|
|
||||||
|
## TODO
|
||||||
|
|
||||||
|
- Discover all last unknowns fields, etc.
|
||||||
|
- Parse TEXT format for terrain module
|
||||||
|
|
||||||
### Using
|
### Using
|
||||||
|
|
||||||
`RSE-Texture_"version" [options] <hmt files...>` or you can simply drag&drop hmt files on it.
|
`RSETexture [options] <hmt files...>` or you can simply drag&drop hmt files on it.
|
||||||
|
|
||||||
Some textures samples can be found here (https://bit.ly/2DGjtng). A futur main program can extract all HMT files directly from DAT file.
|
A futur main program can extract all HMT files directly from DAT file.
|
||||||
|
Due to issue with copyrights, I can't provide samples... You need to extract HMT files yourself.
|
||||||
|
|
||||||
|
<img src="https://repo.jcsmith.fr/pictures/rse-texture.gif" width="620" height="400" />
|
||||||
|
|
||||||
### Options
|
### Options
|
||||||
|
|
||||||
- -h Print this message
|
- -h Print this message
|
||||||
- -v Activate verbose output
|
- -v,-vv Activate verbose/debug output mode respectively
|
||||||
- -no-subdir Extract textures directly inside current folder
|
- -no-subdir Extract textures directly inside current folder
|
||||||
|
|
||||||
### Dependencies
|
### Dependencies
|
||||||
|
|
||||||
Necessary libs (provided only in windows release) for running and for compiling.
|
Necessary libs (provided only in windows release) for running and for compiling.
|
||||||
|
|
||||||
- zlib (1.2.11)
|
- [zlib](https://www.zlib.net/) (1.3.1)
|
||||||
- libpng (1.6.37)
|
- [libpng](http://www.libpng.org/pub/png/libpng.html) (1.6.43)
|
||||||
|
|
||||||
### Compiling
|
### Compiling
|
||||||
|
|
||||||
You can compile on both Windows (MinGW) or native Linux system thanks to CMake, you only need to adjust your dependencies on Windows.
|
I've a preference for compiling libraries by hand, mainly for backward compatibility, but I recommend using Conan packages manager (https://conan.io) for simplicity (I've abandonned the support for conan v1 as it's now considered as deprecated).
|
||||||
zlib (zlib1g) and libpng16 distrib packages can be used on debian/ubuntu.
|
|
||||||
|
|
||||||
To compile, just clone and launch cmake:
|
|
||||||
|
|
||||||
```shell
|
```shell
|
||||||
cmake .
|
conan install . -of build -b missing -s build_type=Release -o tools=True -pr:b=default -pr:h=default
|
||||||
make
|
cmake --preset conan-release -G "Unix Makefiles"
|
||||||
make install
|
cmake --build --preset conan-release
|
||||||
```
|
```
|
||||||
|
|
||||||
On Windows system, you will probably need to specify the dependency flags for CMake.
|
If your CMake<3.23, you should use this command for generation instead of preset one:
|
||||||
|
|
||||||
|
`cmake . -S build -DCMAKE_TOOLCHAIN_FILE=conan_toolchain.cmake -DRSPTEXTURE_SHARED=ON -DRSPTEXTURE_STATIC=OFF -DBUILD_TOOLS=ON -DCMAKE_BUILD_TYPE=Release -G "Unix Makefiles"`
|
||||||
|
|
||||||
|
Beware to use the same release/debug configuration with CMake using Conan! Adjust CMake preset or Conan configuration if necessary.
|
||||||
|
|
||||||
|
On Windows environment, you can use MinGW `-G "MinGW Makefiles"` or Ninja `-G "Ninja"` as CMake generator.
|
||||||
|
|
||||||
|
### Compiling (options)
|
||||||
|
|
||||||
|
There are a few configurable build options:
|
||||||
|
|
||||||
|
- RSPTEXTURE_SHARED Enable the build of shared version of the library ("shared" conan option)
|
||||||
|
- RSPTEXTURE_STATIC Enable the build of static version of the library ("shared" conan option)
|
||||||
|
- BUILD_TOOLS Enable the build of the standalone tools (necessary to use the lib directly) ("tools" conan option)
|
||||||
|
|
||||||
|
### Compiling (old-way)
|
||||||
|
|
||||||
|
If you want to do it manually without Conan, you will probably need to specify the dependency flags for CMake. Ex:
|
||||||
|
|
||||||
|
`cmake.exe -D"ZLIB_INCLUDE_DIR=zlib/1.3.1/include" -D"ZLIB_LIBRARY=zlib/1.3.1/lib/libzlib.dll.a" -D"PNG_PNG_INCLUDE_DIR=libpng/1.6.43/include" -D"PNG_LIBRARY=libpng/1.6.43/lib/libpng.dll.a" -DRSPTEXTURE_SHARED=ON -DRSPTEXTURE_STATIC=OFF -DBUILD_TOOLS=ON . -G "MinGW Makefiles"`
|
||||||
|
|
||||||
|
I've tested cross-compilation too, but since I want to check that Conan is working properly at each release, I've integrated it into the Jenkins flow using Conan for the cross-abstraction.
|
||||||
|
50
RSETexture/CMakeLists.txt
Normal file
50
RSETexture/CMakeLists.txt
Normal file
@ -0,0 +1,50 @@
|
|||||||
|
# CMakeLists.txt
|
||||||
|
|
||||||
|
####################################################
|
||||||
|
# Written by JackCarterSmith, 2022
|
||||||
|
# This code is released under the RSE license.
|
||||||
|
####################################################
|
||||||
|
|
||||||
|
|
||||||
|
# General configuration
|
||||||
|
include(CheckIncludeFile)
|
||||||
|
include(CheckCSourceCompiles)
|
||||||
|
|
||||||
|
if(BUILD_TOOLS)
|
||||||
|
# Import needed packages and references their include path
|
||||||
|
find_package(PNG 1.6.40 REQUIRED)
|
||||||
|
include_directories(${PNG_INCLUDE_DIR})
|
||||||
|
|
||||||
|
|
||||||
|
# Define src/headers files
|
||||||
|
file(GLOB_RECURSE RSE_TEXTURE_SOURCES ./src/*.c)
|
||||||
|
source_group("Source Files" FILES ${RSE_TEXTURE_SOURCES})
|
||||||
|
|
||||||
|
|
||||||
|
# Building instructions for RSE-Texture
|
||||||
|
if(DEFINED ENV{CI})
|
||||||
|
set(CMAKE_BUILD_TYPE RELEASE)
|
||||||
|
endif()
|
||||||
|
|
||||||
|
|
||||||
|
# Declare standalone application
|
||||||
|
add_executable(rse-texture ${RSE_TEXTURE_SOURCES})
|
||||||
|
set_property(TARGET rse-texture PROPERTY C_STANDARD 90)
|
||||||
|
|
||||||
|
#target_include_directories(rse-texture PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/src)
|
||||||
|
set_target_properties(rse-texture PROPERTIES OUTPUT_NAME ${RSE_TEXTURE_NAME})
|
||||||
|
|
||||||
|
if(MSVC)
|
||||||
|
# msvc does not append 'lib' - do it here to have consistent name
|
||||||
|
set_target_properties(rse-texture PROPERTIES IMPORT_PREFIX "lib")
|
||||||
|
endif()
|
||||||
|
|
||||||
|
# Link externals libraries to the linker
|
||||||
|
if (TARGET PNG::PNG)
|
||||||
|
if(RSPTEXTURE_SHARED)
|
||||||
|
target_link_libraries(rse-texture PRIVATE rsp-texture-lib PNG::PNG)
|
||||||
|
elseif(RSPTEXTURE_STATIC)
|
||||||
|
target_link_libraries(rse-texture PRIVATE rsp-texture-libstatic PNG::PNG)
|
||||||
|
endif()
|
||||||
|
endif()
|
||||||
|
endif()
|
179
RSETexture/src/RSETexture.c
Normal file
179
RSETexture/src/RSETexture.c
Normal file
@ -0,0 +1,179 @@
|
|||||||
|
/**
|
||||||
|
* @file RSETexture.c
|
||||||
|
* @date 28/08/2022
|
||||||
|
* @author JackCarterSmith
|
||||||
|
* @copyright GPL-v3.0
|
||||||
|
* @brief HMT texture parser and export to PNG format.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <string.h>
|
||||||
|
#if defined(_WIN32)
|
||||||
|
#include <windows.h>
|
||||||
|
#else
|
||||||
|
#include <sys/types.h>
|
||||||
|
#include <sys/stat.h>
|
||||||
|
#endif
|
||||||
|
#include "options.h"
|
||||||
|
#include <RSPTexture.h>
|
||||||
|
#include <RSPTexture_errordefs.h>
|
||||||
|
#include "texture_export.h"
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Internal functions declarations
|
||||||
|
*/
|
||||||
|
|
||||||
|
static unsigned int mainProcess(int args_cnt, char* args_value[], T_PROG_OPTIONS* opt_ptr);
|
||||||
|
static void createSubDir(char *dirName);
|
||||||
|
static unsigned short checkInputArgs(T_PROG_OPTIONS* opt_ptr, int p_arg_nbr, char* p_args[]);
|
||||||
|
static void dispHelp();
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
* - MAIN -
|
||||||
|
*/
|
||||||
|
int main(int argc, char *argv[]) {
|
||||||
|
T_PROG_OPTIONS _opts;
|
||||||
|
unsigned char p;
|
||||||
|
|
||||||
|
// Hello world!
|
||||||
|
printf("\n*~[ Rogue Squadron Extractor (RSE) - RSPTextureLib v%s ]~*\n", RSPTexture_getVersion());
|
||||||
|
|
||||||
|
// Check for arguments
|
||||||
|
if (argc < 2) {
|
||||||
|
printf("\n[ERR] No input file/commands specified!\n");
|
||||||
|
dispHelp();
|
||||||
|
return RSPLIB_ERROR_ARGS_NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Create options for programs according to user's arguments.
|
||||||
|
p = checkInputArgs(&_opts, argc, argv);
|
||||||
|
if ( p == RSPLIB_ERROR_GENERIC ) return RSPLIB_SUCCESS;
|
||||||
|
else if ( p != RSPLIB_SUCCESS ) return p;
|
||||||
|
|
||||||
|
return mainProcess(argc, argv, &_opts);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Private functions definition
|
||||||
|
*/
|
||||||
|
|
||||||
|
static unsigned int mainProcess(int args_cnt, char* args_value[], T_PROG_OPTIONS* p_opts) {
|
||||||
|
unsigned short file_index;
|
||||||
|
RSPTEXTURE_PARAMETERS libParams;
|
||||||
|
T_RSPTEXTURE_HMT* hmtStruct = NULL;
|
||||||
|
unsigned int i;
|
||||||
|
|
||||||
|
libParams.raw = p_opts->raw & 0x7;
|
||||||
|
|
||||||
|
// Manage multiple inputs files
|
||||||
|
for ( file_index = p_opts->input_files_cnt; file_index < args_cnt; file_index++ )
|
||||||
|
{
|
||||||
|
printf("\n=============================================\n[INFO] - Parsing file: %s ...\n", args_value[file_index]);
|
||||||
|
|
||||||
|
// Allocate T_RSPTEXTURE_HMT structure to store extracted datas.
|
||||||
|
hmtStruct = calloc(1, sizeof(T_RSPTEXTURE_HMT));
|
||||||
|
if (hmtStruct) {
|
||||||
|
// Parse data from HMT file and put in T_RSPTEXTURE_HMT structure.
|
||||||
|
if (RSPTexture_processHMTFile(hmtStruct, args_value[file_index], libParams) != RSPLIB_SUCCESS) {
|
||||||
|
printf("[ERR] Failed to parse datas from %s\n", args_value[file_index]);
|
||||||
|
RSPTexture_freeHMT(hmtStruct);
|
||||||
|
return RSPLIB_ERROR_PROCESS;
|
||||||
|
}
|
||||||
|
} else return RSPLIB_ERROR_MEMORY;
|
||||||
|
|
||||||
|
// Create output folders structure.
|
||||||
|
if (p_opts->output_dir) createSubDir(args_value[file_index]);
|
||||||
|
|
||||||
|
// Export each texture as a PNG picture.
|
||||||
|
for ( i = 0; i < hmtStruct->textures_count; i++ ) {
|
||||||
|
switch (hmtStruct->textures[i].type) {
|
||||||
|
case 0:
|
||||||
|
case 1:
|
||||||
|
case 3:
|
||||||
|
case 4:
|
||||||
|
case 5:
|
||||||
|
if (exportPNGTexture(&(hmtStruct->textures[i]), args_value[file_index], p_opts) == RSPLIB_SUCCESS)
|
||||||
|
printf("[INFO] Successfully exported texture %s to PNG format.\n", hmtStruct->textures[i].name);
|
||||||
|
else
|
||||||
|
printf("[ERR] Failed to export texture %s to PNG format!\n", hmtStruct->textures[i].name);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
printf("[WARN] Can't export %s ! Image type %d not currently supported!\n", hmtStruct->textures[i].name, hmtStruct->textures[i].type);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
RSPTexture_freeHMT(hmtStruct);
|
||||||
|
}
|
||||||
|
|
||||||
|
return RSPLIB_SUCCESS;
|
||||||
|
}
|
||||||
|
|
||||||
|
static unsigned short checkInputArgs(T_PROG_OPTIONS* opt_ptr, int p_arg_nbr, char* p_args[]) {
|
||||||
|
char test[256];
|
||||||
|
int i;
|
||||||
|
|
||||||
|
// Set default options
|
||||||
|
opt_ptr->raw = 0;
|
||||||
|
opt_ptr->output_dir = 1;
|
||||||
|
|
||||||
|
if (p_arg_nbr > 1) {
|
||||||
|
for ( i = 1; i < p_arg_nbr; i++) {
|
||||||
|
strcpy(test, p_args[i]);
|
||||||
|
if (p_args[i][0] != '-') break;
|
||||||
|
if (strcmp(p_args[i], "-h") == 0) {
|
||||||
|
dispHelp();
|
||||||
|
return RSPLIB_ERROR_GENERIC;
|
||||||
|
} else if (strcmp(p_args[i], "-v") == 0) {
|
||||||
|
opt_ptr->verbose_mode = 1;
|
||||||
|
printf("[OPTN] Verbose enabled.\n");
|
||||||
|
} else if (strcmp(p_args[i], "-vv") == 0) {
|
||||||
|
opt_ptr->verbose_mode = 1;
|
||||||
|
opt_ptr->debug_mode = 1;
|
||||||
|
printf("[OPTN] Debug enabled.\n");
|
||||||
|
} else if (strcmp(p_args[i], "-vvv") == 0) {
|
||||||
|
opt_ptr->verbose_mode = 1;
|
||||||
|
opt_ptr->debug_mode = 1;
|
||||||
|
opt_ptr->god_mode = 1;
|
||||||
|
printf("[OPTN] God damn it!\n");
|
||||||
|
} else if (strcmp(p_args[i], "-no-subdir") == 0) {
|
||||||
|
opt_ptr->output_dir = 0;
|
||||||
|
printf("[OPTN] Export to current directory.\n");
|
||||||
|
} else {
|
||||||
|
printf("[ERR] Unknown option: %s\n", p_args[i]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
opt_ptr->input_files_cnt = i;
|
||||||
|
return RSPLIB_SUCCESS;
|
||||||
|
}
|
||||||
|
|
||||||
|
return RSPLIB_ERROR_ARGS_NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void createSubDir(char *dirName) {
|
||||||
|
if (dirName == NULL) return;
|
||||||
|
char _dir[1024];
|
||||||
|
|
||||||
|
snprintf(_dir, 1024, "%s-out", dirName);
|
||||||
|
|
||||||
|
#ifdef _WIN32
|
||||||
|
CreateDirectory(_dir, NULL);
|
||||||
|
#else
|
||||||
|
mkdir(_dir, 0755);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
static void dispHelp() {
|
||||||
|
printf("\n");
|
||||||
|
printf("Options:\n -h Print this message\n");
|
||||||
|
printf(" -v -vv Activate verbose console output\n");
|
||||||
|
printf(" -no-subdir Export models inside current folder\n");
|
||||||
|
printf("\n");
|
||||||
|
printf("Usage: RSETexture [options] <hmt_files...>\n");
|
||||||
|
printf("\n");
|
||||||
|
}
|
29
RSETexture/src/options.h
Normal file
29
RSETexture/src/options.h
Normal file
@ -0,0 +1,29 @@
|
|||||||
|
/**
|
||||||
|
* @file options.h
|
||||||
|
* @date 29/07/2022
|
||||||
|
* @author JackCarterSmith
|
||||||
|
* @copyright GPL-v3.0
|
||||||
|
* @brief Shared options structure definition and declaration.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef OPTIONS_H_
|
||||||
|
#define OPTIONS_H_
|
||||||
|
|
||||||
|
/// Options structure
|
||||||
|
typedef union u_prog_options {
|
||||||
|
struct {
|
||||||
|
unsigned char verbose_mode:1; //!< Output simple details about ID and other "light" things.
|
||||||
|
unsigned char debug_mode:1; //!< Output all values of faces, indices and vertices and others "heavy" things.
|
||||||
|
unsigned char god_mode:1; //!< Dev only. Output experimental values.
|
||||||
|
|
||||||
|
unsigned char output_dir:1; //!< Export extracted datas to a sub-directory.
|
||||||
|
|
||||||
|
unsigned short reserved0:12; //!< For future use.
|
||||||
|
|
||||||
|
unsigned short input_files_cnt; //!< Internal files counters.
|
||||||
|
};
|
||||||
|
unsigned int raw; //!< Raw options access for bit-masking or memory copy/compare.
|
||||||
|
} T_PROG_OPTIONS ;
|
||||||
|
|
||||||
|
#endif /* OPTIONS_H_ */
|
96
RSETexture/src/texture_export.c
Normal file
96
RSETexture/src/texture_export.c
Normal file
@ -0,0 +1,96 @@
|
|||||||
|
/**
|
||||||
|
* @file texture_export.c
|
||||||
|
* @date 29/08/2022
|
||||||
|
* @author JackCarterSmith
|
||||||
|
* @copyright GPL-v3.0
|
||||||
|
* @brief Export texture datas to PNG format.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include <png.h>
|
||||||
|
#include "options.h"
|
||||||
|
#include <RSPTexture_datatypes.h>
|
||||||
|
#include <RSPTexture_errordefs.h>
|
||||||
|
#include "texture_export.h"
|
||||||
|
|
||||||
|
|
||||||
|
static inline T_R8G8B8A8 *getPixelAt(const T_RSPTEXTURE_TEXTURE *tex, const unsigned int posX , const unsigned int posY) {
|
||||||
|
return tex->pixels + tex->width * posY + posX;
|
||||||
|
}
|
||||||
|
|
||||||
|
unsigned char exportPNGTexture(const T_RSPTEXTURE_TEXTURE* pTextureObj, const char* out_path, T_PROG_OPTIONS* p_opts) {
|
||||||
|
char export_path[1024];
|
||||||
|
FILE *_png_f = NULL;
|
||||||
|
png_structp png_ptr = NULL;
|
||||||
|
png_infop info_ptr = NULL;
|
||||||
|
size_t x,y;
|
||||||
|
png_byte **row_ptrs = NULL;
|
||||||
|
T_R8G8B8A8 *pixel = NULL;
|
||||||
|
//int pixel_size = 3;
|
||||||
|
//int depth = 8; //bit par color channel (RGB)
|
||||||
|
|
||||||
|
if (pTextureObj == NULL || out_path == NULL)
|
||||||
|
return RSPLIB_ERROR_ARGS_NULL;
|
||||||
|
|
||||||
|
#ifdef _WIN32
|
||||||
|
if (p_opts->output_dir)
|
||||||
|
snprintf(export_path, 1024, "%s-out\\%s.png", out_path, pTextureObj->name);
|
||||||
|
else
|
||||||
|
snprintf(export_path, 1024, "%s.png", pTextureObj->name);
|
||||||
|
#else
|
||||||
|
if (p_opts->output_dir)
|
||||||
|
snprintf(export_path, 1024, "%s-out/%s.png", out_path, pTextureObj->name);
|
||||||
|
else
|
||||||
|
snprintf(export_path, 1024, "%s.png", pTextureObj->name);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
// Open export file and add PNG header
|
||||||
|
_png_f = fopen(export_path, "wb");
|
||||||
|
if (_png_f == NULL) return RSPLIB_ERROR_MEMORY;
|
||||||
|
png_ptr = png_create_write_struct(PNG_LIBPNG_VER_STRING, NULL, NULL, NULL);
|
||||||
|
if (png_ptr == NULL) {
|
||||||
|
fclose(_png_f);
|
||||||
|
return RSPLIB_ERROR_MEMORY;
|
||||||
|
}
|
||||||
|
info_ptr = png_create_info_struct(png_ptr);
|
||||||
|
if (info_ptr == NULL) {
|
||||||
|
fclose(_png_f);
|
||||||
|
return RSPLIB_ERROR_MEMORY;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Set image attributes
|
||||||
|
png_set_IHDR(png_ptr, info_ptr, pTextureObj->width, pTextureObj->height, 8, PNG_COLOR_TYPE_RGBA, PNG_INTERLACE_NONE, PNG_COMPRESSION_TYPE_DEFAULT, PNG_FILTER_TYPE_DEFAULT);
|
||||||
|
|
||||||
|
// Store PNG datas in buffer
|
||||||
|
row_ptrs = png_malloc(png_ptr, pTextureObj->height * sizeof(png_byte *));
|
||||||
|
for ( y = 0; y < pTextureObj->height; y++ ) {
|
||||||
|
png_byte *row = png_malloc(png_ptr, pTextureObj->width * sizeof(T_R8G8B8A8));
|
||||||
|
row_ptrs[y] = row;
|
||||||
|
for ( x = 0; x < pTextureObj->width; x++ ) {
|
||||||
|
pixel = getPixelAt(pTextureObj, x , y);
|
||||||
|
*row++ = pixel->r;
|
||||||
|
*row++ = pixel->g;
|
||||||
|
*row++ = pixel->b;
|
||||||
|
*row++ = pixel->a;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Write pixels datas
|
||||||
|
png_init_io(png_ptr, _png_f);
|
||||||
|
png_set_rows(png_ptr, info_ptr, row_ptrs);
|
||||||
|
png_write_png(png_ptr, info_ptr, PNG_TRANSFORM_IDENTITY, NULL);
|
||||||
|
|
||||||
|
// Clean up
|
||||||
|
for ( y = 0; y < pTextureObj->height; y++ ) {
|
||||||
|
png_free(png_ptr, row_ptrs[y]);
|
||||||
|
}
|
||||||
|
png_free(png_ptr, row_ptrs);
|
||||||
|
png_destroy_write_struct(&png_ptr, &info_ptr);
|
||||||
|
|
||||||
|
fclose(_png_f);
|
||||||
|
|
||||||
|
return RSPLIB_SUCCESS;
|
||||||
|
}
|
15
RSETexture/src/texture_export.h
Normal file
15
RSETexture/src/texture_export.h
Normal file
@ -0,0 +1,15 @@
|
|||||||
|
/**
|
||||||
|
* @file texture_export.h
|
||||||
|
* @date 29/08/2022
|
||||||
|
* @author JackCarterSmith
|
||||||
|
* @copyright GPL-v3.0
|
||||||
|
* @brief Export texture datas to PNG format.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef TEXTURE_EXPORT_H_
|
||||||
|
#define TEXTURE_EXPORT_H_
|
||||||
|
|
||||||
|
unsigned char exportPNGTexture(const T_RSPTEXTURE_TEXTURE* pTextureObj, const char* out_path, T_PROG_OPTIONS* p_opts);
|
||||||
|
|
||||||
|
#endif /* TEXTURE_EXPORT_H_ */
|
102
RSPTextureLib/CMakeLists.txt
Normal file
102
RSPTextureLib/CMakeLists.txt
Normal file
@ -0,0 +1,102 @@
|
|||||||
|
# CMakeLists.txt
|
||||||
|
|
||||||
|
####################################################
|
||||||
|
# Written by JackCarterSmith, 2022
|
||||||
|
# This code is released under the RSE license.
|
||||||
|
####################################################
|
||||||
|
|
||||||
|
|
||||||
|
# General library configuration
|
||||||
|
if(DEFINED ENV{MS_COMPATIBLE})
|
||||||
|
set(CMAKE_GNUtoMS ON) # Enable compatibility level to exported libraries
|
||||||
|
endif()
|
||||||
|
|
||||||
|
include(CheckIncludeFile)
|
||||||
|
include(CheckCSourceCompiles)
|
||||||
|
|
||||||
|
|
||||||
|
# Define src/headers files
|
||||||
|
file(GLOB_RECURSE RSP_TEXTURE_SOURCES ./src/*.c)
|
||||||
|
source_group("Source Files" FILES ${RSP_TEXTURE_SOURCES})
|
||||||
|
file(GLOB RSP_PUBLIC_HRDS ./include/*.h)
|
||||||
|
set(RSP_PUBLIC_HRDS ${RSP_PUBLIC_HRDS} PARENT_SCOPE)
|
||||||
|
|
||||||
|
|
||||||
|
# Building instructions for RSP-Texture library
|
||||||
|
if(DEFINED ENV{CI})
|
||||||
|
set(CMAKE_BUILD_TYPE RELEASE)
|
||||||
|
endif()
|
||||||
|
|
||||||
|
|
||||||
|
# Declare the shared library instance
|
||||||
|
if(RSPTEXTURE_SHARED)
|
||||||
|
add_library(rsp-texture-lib SHARED ${RSP_TEXTURE_SOURCES})
|
||||||
|
set_property(TARGET rsp-texture-lib PROPERTY C_STANDARD 90)
|
||||||
|
set_target_properties(rsp-texture-lib PROPERTIES VERSION 2.1.0)
|
||||||
|
|
||||||
|
target_include_directories(rsp-texture-lib PUBLIC ${CMAKE_CURRENT_SOURCE_DIR}/include)
|
||||||
|
|
||||||
|
set_target_properties(rsp-texture-lib PROPERTIES OUTPUT_NAME "${RSP_TEXTURE_LIB_NAME}")
|
||||||
|
|
||||||
|
if(WIN32)
|
||||||
|
set_target_properties(rsp-texture-lib PROPERTIES DEFINE_SYMBOL RSPTEXTURE_DLL)
|
||||||
|
endif()
|
||||||
|
|
||||||
|
# msvc does not append 'lib' - do it here to have consistent name
|
||||||
|
if(MSVC)
|
||||||
|
set_target_properties(rsp-texture-lib PROPERTIES PREFIX "lib")
|
||||||
|
set_target_properties(rsp-texture-lib PROPERTIES IMPORT_PREFIX "lib")
|
||||||
|
endif()
|
||||||
|
endif()
|
||||||
|
|
||||||
|
|
||||||
|
# Declare the static library instance
|
||||||
|
if(RSPTEXTURE_STATIC)
|
||||||
|
add_library(rsp-texture-libstatic STATIC ${RSP_TEXTURE_SOURCES})
|
||||||
|
set_property(TARGET rsp-texture-libstatic PROPERTY C_STANDARD 90)
|
||||||
|
|
||||||
|
target_include_directories(rsp-texture-libstatic PUBLIC ${CMAKE_CURRENT_SOURCE_DIR}/include)
|
||||||
|
|
||||||
|
# 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(rsp-texture-libstatic PROPERTIES OUTPUT_NAME "${RSP_TEXTURE_LIB_NAME}")
|
||||||
|
set_target_properties(rsp-texture-libstatic PROPERTIES CLEAN_DIRECT_OUTPUT 1)
|
||||||
|
else()
|
||||||
|
set_target_properties(rsp-texture-libstatic PROPERTIES OUTPUT_NAME "${RSP_TEXTURE_LIB_NAME}_static")
|
||||||
|
set_target_properties(rsp-texture-libstatic PROPERTIES CLEAN_DIRECT_OUTPUT 1)
|
||||||
|
endif()
|
||||||
|
|
||||||
|
# MSVC does not append 'lib' - do it here to have consistent name
|
||||||
|
if(MSVC)
|
||||||
|
set_target_properties(rsp-texture-libstatic PROPERTIES PREFIX "lib")
|
||||||
|
endif()
|
||||||
|
endif()
|
||||||
|
|
||||||
|
|
||||||
|
include(${CMAKE_CURRENT_SOURCE_DIR}/../cmake/create_symlink.cmake)
|
||||||
|
|
||||||
|
# Install libraries with OS specific name fix
|
||||||
|
if(RSPTEXTURE_SHARED)
|
||||||
|
# Create a symlink for libRSPTexture.dll.a => libRSPTextureXX.dll.a on Cygwin/MinGW
|
||||||
|
if(CYGWIN OR MINGW)
|
||||||
|
create_lib_symlink(libRSPTexture${CMAKE_IMPORT_LIBRARY_SUFFIX} TARGET rsp-texture-lib)
|
||||||
|
install(FILES $<TARGET_LINKER_FILE_DIR:rsp-texture-lib>/libRSPTexture${CMAKE_IMPORT_LIBRARY_SUFFIX}
|
||||||
|
DESTINATION ${INSTALL_LIB_DIR})
|
||||||
|
endif()
|
||||||
|
|
||||||
|
if(NOT WIN32)
|
||||||
|
create_lib_symlink(libRSPTexture${CMAKE_SHARED_LIBRARY_SUFFIX} TARGET rsp-texture-lib)
|
||||||
|
install(FILES $<TARGET_LINKER_FILE_DIR:rsp-texture-lib>/libRSPTexture${CMAKE_SHARED_LIBRARY_SUFFIX}
|
||||||
|
DESTINATION ${INSTALL_LIB_DIR})
|
||||||
|
endif()
|
||||||
|
endif()
|
||||||
|
|
||||||
|
if(RSPTEXTURE_STATIC)
|
||||||
|
if(NOT WIN32 OR CYGWIN OR MINGW)
|
||||||
|
create_lib_symlink(libRSPTexture${CMAKE_STATIC_LIBRARY_SUFFIX} TARGET rsp-texture-libstatic)
|
||||||
|
install(FILES $<TARGET_LINKER_FILE_DIR:rsp-texture-libstatic>/libRSPTexture${CMAKE_STATIC_LIBRARY_SUFFIX}
|
||||||
|
DESTINATION ${INSTALL_LIB_DIR})
|
||||||
|
endif()
|
||||||
|
endif()
|
141
RSPTextureLib/include/RSPTexture.h
Normal file
141
RSPTextureLib/include/RSPTexture.h
Normal file
@ -0,0 +1,141 @@
|
|||||||
|
/**
|
||||||
|
* @file RSPTexture.h
|
||||||
|
* @date 14/09/2022
|
||||||
|
* @author JackCarterSmith
|
||||||
|
* @copyright GPL-v3.0
|
||||||
|
* @brief Rogue Squadron Parser texture library, used to decode HMT datas
|
||||||
|
* from original game file and access them through public interface.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "RSPTexture_datatypes.h"
|
||||||
|
|
||||||
|
#ifndef RSPTEXTURELIB_H_
|
||||||
|
#define RSPTEXTURELIB_H_
|
||||||
|
|
||||||
|
|
||||||
|
#if defined(_MSC_VER)
|
||||||
|
# define RSPTEXTURE_ABI_EXPORT __declspec(dllexport)
|
||||||
|
# define RSPTEXTURE_ABI_IMPORT __declspec(dllimport)
|
||||||
|
#elif __GNUC__ >= 4
|
||||||
|
# define RSPTEXTURE_ABI_EXPORT __attribute__ ((visibility("default")))
|
||||||
|
# define RSPTEXTURE_ABI_IMPORT __attribute__ ((visibility("default")))
|
||||||
|
#else
|
||||||
|
# define RSPTEXTURE_ABI_EXPORT
|
||||||
|
# define RSPTEXTURE_ABI_IMPORT
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if defined(RSPTEXTURE_DLL)
|
||||||
|
# if defined(WIN32)
|
||||||
|
# if defined(RSPTEXTURE_DLLBUILD)
|
||||||
|
# define RSPTEXTURE_EXTERN extern RSPTEXTURE_ABI_EXPORT
|
||||||
|
# else
|
||||||
|
# define RSPTEXTURE_EXTERN extern RSPTEXTURE_ABI_IMPORT
|
||||||
|
# endif
|
||||||
|
# endif
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifndef RSPTEXTURE_EXTERN
|
||||||
|
# define RSPTEXTURE_EXTERN extern
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
extern "C" {
|
||||||
|
#endif
|
||||||
|
|
||||||
|
///////////////////////////////////////////////////////////////////////////////
|
||||||
|
// Library's functions declaration
|
||||||
|
///////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Get the current library version.
|
||||||
|
* @return Char array of the version, escape char included.
|
||||||
|
*/
|
||||||
|
RSPTEXTURE_EXTERN char* RSPTexture_getVersion( void );
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Constructor for T_RSPTEXTURE_HMT struct
|
||||||
|
* @return Pointer to a new T_RSPTEXTURE_HMT struct.
|
||||||
|
*/
|
||||||
|
RSPTEXTURE_EXTERN T_RSPTEXTURE_HMT* RSPTexture_createHMT( void );
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Run texture parser for the specified file in file system.
|
||||||
|
* @details Texture library can process HMT file from file system. It's a easy
|
||||||
|
* approach using this library for debugging purpose.
|
||||||
|
*
|
||||||
|
* @param[out] hmtStruct HMT texture structure to be filled with parsed datas.
|
||||||
|
* @param[in] filePath Path to the HMT file in system.
|
||||||
|
* @param[in] params Parser options. See RSPTEXTURE_PARAMETERS.
|
||||||
|
*
|
||||||
|
* @return Error status, return RSPLIB_SUCCESS in nominal case.
|
||||||
|
*/
|
||||||
|
RSPTEXTURE_EXTERN unsigned short RSPTexture_processHMTFile(
|
||||||
|
T_RSPTEXTURE_HMT* hmtStruct, const char* const filePath,
|
||||||
|
const RSPTEXTURE_PARAMETERS params
|
||||||
|
);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Run texture parser for the specified file in memory.
|
||||||
|
* @details Texture library can process HMT file directly stored in RAM memory,
|
||||||
|
* you must load the file beforehand through a malloc/memcpy call.
|
||||||
|
* @warning No controls routines are implemented to verify file length!
|
||||||
|
*
|
||||||
|
* @param[out] hmtStruct HMT texture structure to be filled with parsed datas.
|
||||||
|
* @param[in] memFilePtr Pointer to the beginning of the file in memory.
|
||||||
|
* @param[in] memFileSize Size of the file in bytes.
|
||||||
|
* @param[in] params Parser options. See RSPTEXTURE_PARAMETERS.
|
||||||
|
*
|
||||||
|
* @return Error status, return RSPLIB_SUCCESS in nominal case.
|
||||||
|
*/
|
||||||
|
RSPTEXTURE_EXTERN unsigned short RSPTexture_processHMTFileMemory(
|
||||||
|
T_RSPTEXTURE_HMT* hmtStruct, const void* const memFilePtr, const long memFileSize,
|
||||||
|
const RSPTEXTURE_PARAMETERS params
|
||||||
|
);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Parse HMT materials for specific ID.
|
||||||
|
* @pre HMT structure should be processed with RSPTexture_processHMTFile()
|
||||||
|
* or RSPTexture_processHMTMemFile() before.
|
||||||
|
*
|
||||||
|
* @param[in] pHmt HMT texture structure to be analyzed.
|
||||||
|
* @param[in] mat_id ID of the material.
|
||||||
|
*
|
||||||
|
* @return Pointer to T_RSPTEXTURE_MATERIAL if found or NULL otherwise.
|
||||||
|
*/
|
||||||
|
RSPTEXTURE_EXTERN T_RSPTEXTURE_MATERIAL* RSPTexture_getMaterialFromID(
|
||||||
|
const T_RSPTEXTURE_HMT* pHmt, const unsigned short mat_id
|
||||||
|
);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Retrieve material name of a T_RSPTEXTURE_MATERIAL structure.
|
||||||
|
* @return '0' terminated name string (max: 16 chars).
|
||||||
|
*/
|
||||||
|
RSPTEXTURE_EXTERN char* RSPTexture_getMaterialName( const T_RSPTEXTURE_MATERIAL* mat );
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Retrieve opacity value from T_RSPTEXTURE_MATERIAL structure.
|
||||||
|
* @return Float opacity value.
|
||||||
|
* @warning Experimental method.
|
||||||
|
*/
|
||||||
|
RSPTEXTURE_EXTERN float RSPTexture_getMaterialOpacity( const T_RSPTEXTURE_MATERIAL* mat );
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Retrieve ambient light value from T_RSPTEXTURE_MATERIAL structure.
|
||||||
|
* @return Float ambient light value.
|
||||||
|
* @warning Experimental method.
|
||||||
|
*/
|
||||||
|
RSPTEXTURE_EXTERN float RSPTexture_getMaterialAmbient( const T_RSPTEXTURE_MATERIAL* mat );
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Clean HMT object and it's childrens from memory.
|
||||||
|
* @param[in] hmtStruct Pointer to data to be cleaned up.
|
||||||
|
*/
|
||||||
|
RSPTEXTURE_EXTERN void RSPTexture_freeHMT( T_RSPTEXTURE_HMT* hmtStruct );
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#endif /* RSPTEXTURELIB_H_ */
|
96
RSPTextureLib/include/RSPTexture_datatypes.h
Normal file
96
RSPTextureLib/include/RSPTexture_datatypes.h
Normal file
@ -0,0 +1,96 @@
|
|||||||
|
/**
|
||||||
|
* @file RSPTexture_datatypes.h
|
||||||
|
* @date 25/08/2022
|
||||||
|
* @author JackCarterSmith
|
||||||
|
* @copyright GPL-v3.0
|
||||||
|
* @brief RSP Texture workflow structures definitions
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef RSPTEXTURELIB_DATATYPES_H_
|
||||||
|
#define RSPTEXTURELIB_DATATYPES_H_
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
extern "C" {
|
||||||
|
#endif
|
||||||
|
|
||||||
|
///////////////////////////////////////////////////////////////////////////////
|
||||||
|
// Configuration structure
|
||||||
|
///////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
typedef union u_rsptexture_parameters {
|
||||||
|
struct {
|
||||||
|
unsigned char verbose_mode:1; //!< Output simple details about ID and other "light" things.
|
||||||
|
unsigned char debug_mode:1; //!< Output all values of faces, indices and vertices and others "heavy" things.
|
||||||
|
unsigned char god_mode:1; //!< Dev only. Output experimental values.
|
||||||
|
|
||||||
|
unsigned char reserved0:5; //!< For future use.
|
||||||
|
};
|
||||||
|
unsigned char raw; //!< Raw options access for bit-masking or memory copy/compare.
|
||||||
|
} RSPTEXTURE_PARAMETERS ;
|
||||||
|
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
// Lib's structure definitions
|
||||||
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
#ifndef MEMFILE_DEF
|
||||||
|
typedef char* MEMFILE;
|
||||||
|
#define MEMFILE_DEF
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifndef T_R8G8B8_DEF
|
||||||
|
typedef struct r8g8b8 { unsigned char r,g,b; } T_R8G8B8;
|
||||||
|
#define T_R8G8B8_DEF
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifndef T_R8G8B8A8_DEF
|
||||||
|
typedef struct r8g8b8a8 { unsigned char r,g,b,a; } T_R8G8B8A8;
|
||||||
|
#define T_R8G8B8A8_DEF
|
||||||
|
#endif
|
||||||
|
|
||||||
|
typedef enum e_mat_type {
|
||||||
|
RSPTEX_MAT_TYPE_TEXTURED = 1,
|
||||||
|
RSPTEX_MAT_TYPE_SOLID = 2
|
||||||
|
} RSPTEX_MAT_TYPE;
|
||||||
|
|
||||||
|
typedef unsigned char T_SAMPLE;
|
||||||
|
|
||||||
|
typedef struct rsptexture_texture {
|
||||||
|
unsigned char name[17]; // 16 + 1 string ending \0
|
||||||
|
unsigned short width;
|
||||||
|
unsigned short height;
|
||||||
|
|
||||||
|
unsigned char type;
|
||||||
|
unsigned char sample_bits;
|
||||||
|
unsigned int palette_entries;
|
||||||
|
T_R8G8B8A8 alpha_color;
|
||||||
|
|
||||||
|
T_R8G8B8A8* pixels;
|
||||||
|
} T_RSPTEXTURE_TEXTURE;
|
||||||
|
|
||||||
|
typedef struct rsptexture_material {
|
||||||
|
unsigned short id;
|
||||||
|
unsigned char name[17]; // 16 + 1 string ending \0
|
||||||
|
RSPTEX_MAT_TYPE type;
|
||||||
|
|
||||||
|
float opacity; //TODO: temporary, need to be defined
|
||||||
|
float ambient; //TODO: temporary, need to be defined
|
||||||
|
|
||||||
|
T_RSPTEXTURE_TEXTURE* texture;
|
||||||
|
} T_RSPTEXTURE_MATERIAL;
|
||||||
|
|
||||||
|
typedef struct rsptexture_hmt {
|
||||||
|
unsigned int materials_count;
|
||||||
|
unsigned int textures_count;
|
||||||
|
unsigned int texture_offset; //TODO: useless?
|
||||||
|
|
||||||
|
T_RSPTEXTURE_MATERIAL* materials;
|
||||||
|
T_RSPTEXTURE_TEXTURE* textures;
|
||||||
|
} T_RSPTEXTURE_HMT;
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#endif /* RSPTEXTURELIB_DATATYPES_H_ */
|
45
RSPTextureLib/include/RSPTexture_errordefs.h
Normal file
45
RSPTextureLib/include/RSPTexture_errordefs.h
Normal file
@ -0,0 +1,45 @@
|
|||||||
|
/**
|
||||||
|
* @file RSPTerrain_errordefs.h
|
||||||
|
* @date 22/08/2022
|
||||||
|
* @author JackCarterSmith
|
||||||
|
* @copyright GPL-v3.0
|
||||||
|
* @brief Errors type definition file. Used mostly by methods in this project.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <stdlib.h>
|
||||||
|
|
||||||
|
|
||||||
|
#ifndef RSPLIB_ERRORS_H_
|
||||||
|
#define RSPLIB_ERRORS_H_
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
extern "C" {
|
||||||
|
#endif
|
||||||
|
|
||||||
|
///////////////////////////////////////////////////////////////////////////////
|
||||||
|
// Errors types definitions
|
||||||
|
///////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
#ifndef NO_ERROR
|
||||||
|
#define NO_ERROR 0 // In case of dual declaration by GCC
|
||||||
|
#endif
|
||||||
|
#define RSPLIB_SUCCESS NO_ERROR //!< All is running good!
|
||||||
|
|
||||||
|
#define RSPLIB_ERROR_GENERIC 1 //!< Misuse of the program
|
||||||
|
#define RSPLIB_ERROR_MEMORY 2 //!< Memory de/allocation failure
|
||||||
|
#define RSPLIB_ERROR_IO 3 //!< File system access failure
|
||||||
|
#define RSPLIB_ERROR_PROCESS 4 //!< Internal processing failure
|
||||||
|
|
||||||
|
#define RSPLIB_ERROR_ARGS_NULL 16 //!< Method not NULL input expected
|
||||||
|
#define RSPLIB_ERROR_ARGS_RANGE 17 //!< Method input out of expected range
|
||||||
|
|
||||||
|
#define RSPLIB_ERROR_MOD_DISABLED 64 //!< A necessary module hasn't been activated during compilation time
|
||||||
|
|
||||||
|
#define RSPLIB_ERROR_REALITY_BRK -1 //!< This error can only appear in alternate reality
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#endif /* RSPLIB_ERRORS_H_ */
|
95
RSPTextureLib/src/RSPTexture.c
Normal file
95
RSPTextureLib/src/RSPTexture.c
Normal file
@ -0,0 +1,95 @@
|
|||||||
|
/**
|
||||||
|
* @file RSPTexture.c
|
||||||
|
* @date 14/09/2022
|
||||||
|
* @author JackCarterSmith
|
||||||
|
* @copyright GPL-v3.0
|
||||||
|
* @brief HMT textures datas parser and export to PNG format.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
#if defined(RSPTEXTURE_DLL)
|
||||||
|
# define RSPTEXTURE_DLLBUILD
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include "config.h"
|
||||||
|
#include "RSPTexture_errordefs.h"
|
||||||
|
#include "RSPTexture_datatypes.h"
|
||||||
|
#include "hmt_parser.h"
|
||||||
|
#include "RSPTexture.h"
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Libs interface
|
||||||
|
*/
|
||||||
|
inline char* RSPTexture_getVersion( void ) {
|
||||||
|
return PRG_VERSION;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* HMT parser
|
||||||
|
*/
|
||||||
|
T_RSPTEXTURE_HMT* RSPTexture_createHMT( void ) {
|
||||||
|
return calloc(1, sizeof(T_RSPTEXTURE_HMT));
|
||||||
|
}
|
||||||
|
|
||||||
|
unsigned short RSPTexture_processHMTFile( T_RSPTEXTURE_HMT* hmtStruct, const char* const filePath,
|
||||||
|
const RSPTEXTURE_PARAMETERS params ) {
|
||||||
|
|
||||||
|
if ( hmtStruct == NULL || filePath == NULL ) return RSPLIB_ERROR_ARGS_NULL;
|
||||||
|
|
||||||
|
return RSP_TextureLib_ParseHMTFile(filePath, hmtStruct, ¶ms);
|
||||||
|
}
|
||||||
|
|
||||||
|
unsigned short RSPTexture_processHMTFileMemory( T_RSPTEXTURE_HMT* hmtStruct, const void* const memFilePtr,
|
||||||
|
const long memFileSize, const RSPTEXTURE_PARAMETERS params ) {
|
||||||
|
|
||||||
|
if ( hmtStruct == NULL || memFilePtr == NULL ) return RSPLIB_ERROR_ARGS_NULL;
|
||||||
|
|
||||||
|
return RSP_TextureLib_ParseHMTMemFile((MEMFILE)memFilePtr, hmtStruct, ¶ms);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Material utilities
|
||||||
|
*/
|
||||||
|
T_RSPTEXTURE_MATERIAL* RSPTexture_getMaterialFromID( const T_RSPTEXTURE_HMT* pHmt, const unsigned short mat_id ) {
|
||||||
|
if ( pHmt == NULL ) return NULL;
|
||||||
|
if ( pHmt->materials == NULL ) return NULL;
|
||||||
|
|
||||||
|
return &(pHmt->materials[mat_id]);
|
||||||
|
}
|
||||||
|
|
||||||
|
inline char* RSPTexture_getMaterialName( const T_RSPTEXTURE_MATERIAL* mat ) {
|
||||||
|
if ( mat == NULL ) return NULL;
|
||||||
|
|
||||||
|
return (char*)mat->name;
|
||||||
|
}
|
||||||
|
|
||||||
|
inline float RSPTexture_getMaterialOpacity( const T_RSPTEXTURE_MATERIAL* mat ) {
|
||||||
|
if ( mat == NULL ) return 1.0;
|
||||||
|
|
||||||
|
return mat->opacity;
|
||||||
|
}
|
||||||
|
|
||||||
|
inline float RSPTexture_getMaterialAmbient( const T_RSPTEXTURE_MATERIAL* mat ) {
|
||||||
|
if ( mat == NULL ) return 1.0;
|
||||||
|
|
||||||
|
return mat->ambient;
|
||||||
|
}
|
||||||
|
|
||||||
|
void RSPTexture_freeHMT( T_RSPTEXTURE_HMT* hmtStruct ) {
|
||||||
|
unsigned int i;
|
||||||
|
|
||||||
|
if (hmtStruct == NULL) return;
|
||||||
|
|
||||||
|
if ((hmtStruct->textures_count > 0) && hmtStruct->textures) {
|
||||||
|
for ( i = 0; i < hmtStruct->textures_count; i++ )
|
||||||
|
if (hmtStruct->textures[i].pixels) free(hmtStruct->textures[i].pixels);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (hmtStruct->materials) free(hmtStruct->materials);
|
||||||
|
|
||||||
|
free(hmtStruct);
|
||||||
|
}
|
452
RSPTextureLib/src/hmt_parser.c
Normal file
452
RSPTextureLib/src/hmt_parser.c
Normal file
@ -0,0 +1,452 @@
|
|||||||
|
/**
|
||||||
|
* @file hmt_parser.c
|
||||||
|
* @date 26/08/2022
|
||||||
|
* @author JackCarterSmith
|
||||||
|
* @copyright GPL-v3.0
|
||||||
|
* @brief Process HMT file structure and extract its datas.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include "RSPTexture_errordefs.h"
|
||||||
|
#include "RSPTexture_datatypes.h"
|
||||||
|
#include "hmt_struct.h"
|
||||||
|
#include "hmt_parser.h"
|
||||||
|
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
// Private functions declarations
|
||||||
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
static unsigned short ExtractTextureHMT(T_RSPTEXTURE_HMT*, const MEMFILE, const RSPTEXTURE_PARAMETERS*);
|
||||||
|
static unsigned short ExtractMaterials(T_RSPTEXTURE_HMT*, const MEMFILE, const RSPTEXTURE_PARAMETERS*);
|
||||||
|
static unsigned short ExtractTextures(T_RSPTEXTURE_HMT*, const MEMFILE, const RSPTEXTURE_PARAMETERS*);
|
||||||
|
static unsigned short TranslatePixels(T_RSPTEXTURE_TEXTURE*, const T_SAMPLE*, const T_R8G8B8*);
|
||||||
|
static unsigned short isTransparentColor(const T_R8G8B8A8, const T_R8G8B8A8);
|
||||||
|
static void convert4bitsGreyTo32bitsRGBA(T_R8G8B8A8*, const T_SAMPLE*, const unsigned int, const T_R8G8B8A8);
|
||||||
|
static void convert4bitsTo32bitsRGBA(T_R8G8B8A8*, const T_SAMPLE*, const unsigned int, const T_R8G8B8*, const T_R8G8B8A8);
|
||||||
|
static void convert8bitsTo32bitsRGBA(T_R8G8B8A8*, const T_SAMPLE*, const unsigned int, const T_R8G8B8*, const T_R8G8B8A8);
|
||||||
|
static void useOddBytes(T_R8G8B8A8*, const T_SAMPLE*, const unsigned int);
|
||||||
|
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
// Public functions definition
|
||||||
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
unsigned short RSP_TextureLib_ParseHMTMemFile(const MEMFILE pMemFile, T_RSPTEXTURE_HMT* hmtStruct, const RSPTEXTURE_PARAMETERS* pParams) {
|
||||||
|
unsigned char err = RSPLIB_SUCCESS;
|
||||||
|
|
||||||
|
if (hmtStruct != NULL && pMemFile != NULL) {
|
||||||
|
// Do the magic!
|
||||||
|
err = ExtractTextureHMT(hmtStruct, pMemFile, pParams);
|
||||||
|
} else err = RSPLIB_ERROR_ARGS_NULL;
|
||||||
|
|
||||||
|
return err;
|
||||||
|
}
|
||||||
|
|
||||||
|
unsigned short RSP_TextureLib_ParseHMTFile(const char* fileName, T_RSPTEXTURE_HMT* hmtStruct, const RSPTEXTURE_PARAMETERS* pParams) {
|
||||||
|
unsigned char err = RSPLIB_SUCCESS;
|
||||||
|
long fileSize;
|
||||||
|
FILE* fStream = NULL;
|
||||||
|
MEMFILE memFile = NULL;
|
||||||
|
|
||||||
|
if (hmtStruct != NULL && fileName != NULL) {
|
||||||
|
// Open file
|
||||||
|
fStream = fopen(fileName, "rb");
|
||||||
|
|
||||||
|
if (fStream != NULL) {
|
||||||
|
// Determine file size in bytes
|
||||||
|
fseek(fStream, 0, SEEK_END);
|
||||||
|
fileSize = ftell(fStream);
|
||||||
|
fseek(fStream, 0, SEEK_SET);
|
||||||
|
if (pParams->verbose_mode) printf("[DBG] > Input file size: %ld bytes\n", fileSize);
|
||||||
|
|
||||||
|
memFile = malloc(fileSize + 1);
|
||||||
|
if (memFile != NULL) {
|
||||||
|
// Copy file in RAM
|
||||||
|
fread(memFile, fileSize, 1, fStream);
|
||||||
|
fclose(fStream);
|
||||||
|
|
||||||
|
// Do the magic!
|
||||||
|
err = ExtractTextureHMT(hmtStruct, memFile, pParams);
|
||||||
|
|
||||||
|
free(memFile);
|
||||||
|
|
||||||
|
} else {
|
||||||
|
fclose(fStream);
|
||||||
|
err = RSPLIB_ERROR_MEMORY;
|
||||||
|
if (pParams->verbose_mode) printf("[ERR] Can't allocate enough memory for file processing!\n");
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
err = RSPLIB_ERROR_IO;
|
||||||
|
if (pParams->verbose_mode) printf("[ERR] Input file %s not found!\n", fileName);
|
||||||
|
}
|
||||||
|
} else err = RSPLIB_ERROR_ARGS_NULL;
|
||||||
|
|
||||||
|
return err;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
// Private functions definition
|
||||||
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Extract datas from texture HMT in memory.
|
||||||
|
*
|
||||||
|
* @param[out] pHmtStruct Take T_RSPTEXTURE_HMT structure to fill with parsed datas.
|
||||||
|
* @param[in] pMemfile Pointer to an in-memory file location.
|
||||||
|
* @param[in] pParams Program option, used to tune parser features.
|
||||||
|
*
|
||||||
|
* @return Error code, RSPLIB_SUCCESS when no error.
|
||||||
|
*/
|
||||||
|
static unsigned short ExtractTextureHMT(T_RSPTEXTURE_HMT* pHmtStruct, const MEMFILE pMemfile, const RSPTEXTURE_PARAMETERS* pParams) {
|
||||||
|
unsigned short errorCode = RSPLIB_SUCCESS;
|
||||||
|
|
||||||
|
if (pHmtStruct == NULL || pMemfile == NULL) return RSPLIB_ERROR_ARGS_NULL;
|
||||||
|
|
||||||
|
// Get global infos
|
||||||
|
pHmtStruct->materials_count = ((T_HMTFILE_HEADER1 *)pMemfile)->materials_count;
|
||||||
|
pHmtStruct->texture_offset = ((T_HMTFILE_HEADER1 *)pMemfile)->textures_offset;
|
||||||
|
pHmtStruct->textures_count = ((T_HMTFILE_HEADER2 *)(pMemfile + pHmtStruct->texture_offset))->textures_count;
|
||||||
|
|
||||||
|
printf("[INFO] > Materials count: %d\n", pHmtStruct->materials_count);
|
||||||
|
printf("[INFO] > Textures count: %d\n", pHmtStruct->textures_count);
|
||||||
|
if (pParams->verbose_mode) printf("[DBG] > Texture offset: 0x%X\n", pHmtStruct->texture_offset);
|
||||||
|
printf("\n");
|
||||||
|
|
||||||
|
// Get textures if any
|
||||||
|
if (pHmtStruct->textures_count > 0)
|
||||||
|
errorCode |= ExtractTextures(pHmtStruct, pMemfile, pParams);
|
||||||
|
|
||||||
|
// Get materials if any and link them to texture
|
||||||
|
if (pHmtStruct->materials_count > 0)
|
||||||
|
errorCode |= ExtractMaterials(pHmtStruct, pMemfile, pParams);
|
||||||
|
|
||||||
|
|
||||||
|
return errorCode;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Retrieve materials datas from HMT file.
|
||||||
|
*
|
||||||
|
* @param[in|out] pHmt Take HMT structure to get the T_HMTFILE_MATERIAL buffer and header datas.
|
||||||
|
* @param[in] pMemfile Pointer to an in-memory file location.
|
||||||
|
* @param[in] pParams Program option, used to tune parser features.
|
||||||
|
*
|
||||||
|
* @return Error code, RSPLIB_SUCCESS when no error.
|
||||||
|
*/
|
||||||
|
static unsigned short ExtractMaterials(T_RSPTEXTURE_HMT* pHmt, const MEMFILE pMemfile, const RSPTEXTURE_PARAMETERS* pParams) {
|
||||||
|
unsigned int i;
|
||||||
|
|
||||||
|
if (pHmt == NULL || pMemfile == NULL) return RSPLIB_ERROR_ARGS_NULL;
|
||||||
|
|
||||||
|
pHmt->materials = (T_RSPTEXTURE_MATERIAL *)calloc(pHmt->materials_count, sizeof(T_RSPTEXTURE_MATERIAL));
|
||||||
|
if (pHmt->materials == NULL) return RSPLIB_ERROR_MEMORY;
|
||||||
|
|
||||||
|
for ( i = 0; i < pHmt->materials_count; i++ ) {
|
||||||
|
if (pParams->debug_mode) printf("\n-----------------------Begin of material #%d-------------------------\n", i);
|
||||||
|
|
||||||
|
// Get material name
|
||||||
|
//memcpy(pHmt->materials[i].name, ((T_HMTFILE_MATERIAL *)(pMemfile + sizeof(T_HMTFILE_MATERIAL) * (i + 1)))->name, 16);
|
||||||
|
snprintf((char *)pHmt->materials[i].name, 16, "%s", ((T_HMTFILE_MATERIAL *)(pMemfile +
|
||||||
|
sizeof(T_HMTFILE_HEADER1) + sizeof(T_HMTFILE_MATERIAL) * i))->name);
|
||||||
|
|
||||||
|
// Get material datas
|
||||||
|
pHmt->materials[i].type = ((T_HMTFILE_MATERIAL *)(pMemfile +
|
||||||
|
sizeof(T_HMTFILE_HEADER1) + sizeof(T_HMTFILE_MATERIAL) * i))->type;
|
||||||
|
pHmt->materials[i].id = ((T_HMTFILE_MATERIAL *)(pMemfile +
|
||||||
|
sizeof(T_HMTFILE_HEADER1) + sizeof(T_HMTFILE_MATERIAL) * i))->texture_index;
|
||||||
|
// If material is textured, the linked texture correspond to tex_index in textures array.
|
||||||
|
if (pHmt->materials[i].type == RSPTEX_MAT_TYPE_TEXTURED) pHmt->materials[i].texture = pHmt->textures + pHmt->materials[i].id;
|
||||||
|
else pHmt->materials[i].texture = NULL;
|
||||||
|
pHmt->materials[i].opacity = ((T_HMTFILE_MATERIAL *)(pMemfile +
|
||||||
|
sizeof(T_HMTFILE_HEADER1) + sizeof(T_HMTFILE_MATERIAL) * i))->reserved1;
|
||||||
|
pHmt->materials[i].ambient = ((T_HMTFILE_MATERIAL *)(pMemfile +
|
||||||
|
sizeof(T_HMTFILE_HEADER1) + sizeof(T_HMTFILE_MATERIAL) * i))->reserved0;
|
||||||
|
|
||||||
|
if (pParams->verbose_mode) {
|
||||||
|
printf("[INFO] > Material name: %s\n", pHmt->materials[i].name);
|
||||||
|
printf("[INFO] > Material type: %d\n", pHmt->materials[i].type);
|
||||||
|
printf("[INFO] > Material id: %d\n", pHmt->materials[i].id);
|
||||||
|
printf("[INFO] > Material text. index: %d\n", i);
|
||||||
|
if (pHmt->materials[i].type == RSPTEX_MAT_TYPE_TEXTURED)
|
||||||
|
printf("[INFO] > Linked texture name: %s (should correspond to material name)\n", pHmt->materials[i].texture->name);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Unassigned generic material datas :
|
||||||
|
* - Transparent
|
||||||
|
* - Ambient (global)
|
||||||
|
* - Diffuse (environnement)
|
||||||
|
* - Specular (self)
|
||||||
|
*/
|
||||||
|
if (pParams->debug_mode) {
|
||||||
|
printf("[DBG] > Material reserved0: %.8f\n", pHmt->materials[i].ambient);
|
||||||
|
printf("[DBG] > Material reserved1: %.8f\n", pHmt->materials[i].opacity);
|
||||||
|
printf("[DBG] > Material reserved2 (zero): 0x%X\n", ((T_HMTFILE_MATERIAL *)(pMemfile +
|
||||||
|
sizeof(T_HMTFILE_HEADER1) + sizeof(T_HMTFILE_MATERIAL) * i))->reserved2);
|
||||||
|
printf("[DBG] > Material reserved3 (0xA): 0x%X\n", ((T_HMTFILE_MATERIAL *)(pMemfile +
|
||||||
|
sizeof(T_HMTFILE_HEADER1) + sizeof(T_HMTFILE_MATERIAL) * i))->reserved3);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (pParams->debug_mode) printf("\n-----------------------End of material #%d---------------------------\n", i);
|
||||||
|
}
|
||||||
|
|
||||||
|
return RSPLIB_SUCCESS;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Retrieve textures datas from HMT file.
|
||||||
|
*
|
||||||
|
* @param[in|out] pHmt Take HMT structure to get the T_HMTFILE_TEXTURE_HEADER buffer and header datas.
|
||||||
|
* @param[in] pMemfile Pointer to an in-memory file location.
|
||||||
|
* @param[in] pParams Program option, used to tune parser features.
|
||||||
|
*
|
||||||
|
* @return Error code, RSPLIB_SUCCESS when no error.
|
||||||
|
*/
|
||||||
|
static unsigned short ExtractTextures(T_RSPTEXTURE_HMT* pHmt, const MEMFILE pMemfile, const RSPTEXTURE_PARAMETERS* pParams) {
|
||||||
|
T_R8G8B8* _palette = NULL;
|
||||||
|
T_SAMPLE* _samples = NULL;
|
||||||
|
unsigned int palette_offset, pixels_offset;
|
||||||
|
unsigned int i;
|
||||||
|
|
||||||
|
if (pHmt == NULL || pMemfile == NULL) return RSPLIB_ERROR_ARGS_NULL;
|
||||||
|
|
||||||
|
pHmt->textures = (T_RSPTEXTURE_TEXTURE *)calloc(pHmt->textures_count, sizeof(T_RSPTEXTURE_TEXTURE));
|
||||||
|
if (pHmt->textures == NULL) return RSPLIB_ERROR_MEMORY;
|
||||||
|
|
||||||
|
for ( i = 0; i < pHmt->textures_count; i++ ) {
|
||||||
|
if (pParams->debug_mode) printf("\n-----------------------Begin of texture #%d-------------------------\n", i);
|
||||||
|
_palette = NULL;
|
||||||
|
_samples = NULL;
|
||||||
|
|
||||||
|
// Get texture size infos
|
||||||
|
pHmt->textures[i].width = ((T_HMTFILE_TEXTURE_HEADER *)(pMemfile + pHmt->texture_offset +
|
||||||
|
sizeof(T_HMTFILE_HEADER2) + sizeof(T_HMTFILE_TEXTURE_HEADER) * i))->tex_width;
|
||||||
|
pHmt->textures[i].height = ((T_HMTFILE_TEXTURE_HEADER *)(pMemfile + pHmt->texture_offset +
|
||||||
|
sizeof(T_HMTFILE_HEADER2) + sizeof(T_HMTFILE_TEXTURE_HEADER) * i))->tex_height;
|
||||||
|
pHmt->textures[i].type = ((T_HMTFILE_TEXTURE_HEADER *)(pMemfile + pHmt->texture_offset +
|
||||||
|
sizeof(T_HMTFILE_HEADER2) + sizeof(T_HMTFILE_TEXTURE_HEADER) * i))->tex_format.type;
|
||||||
|
switch (pHmt->textures[i].type) {
|
||||||
|
case 0:
|
||||||
|
pHmt->textures[i].sample_bits = 4;
|
||||||
|
pHmt->textures[i].palette_entries = 16;
|
||||||
|
break;
|
||||||
|
case 1:
|
||||||
|
pHmt->textures[i].sample_bits = 8;
|
||||||
|
pHmt->textures[i].palette_entries = 256;
|
||||||
|
break;
|
||||||
|
case 2:
|
||||||
|
pHmt->textures[i].sample_bits = 16;
|
||||||
|
pHmt->textures[i].palette_entries = 0;
|
||||||
|
break;
|
||||||
|
case 3:
|
||||||
|
pHmt->textures[i].sample_bits = 32;
|
||||||
|
pHmt->textures[i].palette_entries = 0;
|
||||||
|
break;
|
||||||
|
case 4:
|
||||||
|
pHmt->textures[i].sample_bits = 4;
|
||||||
|
pHmt->textures[i].palette_entries = 0;
|
||||||
|
break;
|
||||||
|
case 5:
|
||||||
|
pHmt->textures[i].sample_bits = 8;
|
||||||
|
pHmt->textures[i].palette_entries = 0;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
pHmt->textures[i].sample_bits = 0;
|
||||||
|
pHmt->textures[i].palette_entries = 0;
|
||||||
|
}
|
||||||
|
memcpy(&pHmt->textures[i].alpha_color, &((T_HMTFILE_TEXTURE_HEADER *)(pMemfile + pHmt->texture_offset +
|
||||||
|
sizeof(T_HMTFILE_HEADER2) + sizeof(T_HMTFILE_TEXTURE_HEADER) * i))->tex_format.transparent_color, sizeof(T_R8G8B8A8));
|
||||||
|
|
||||||
|
// Get texture datas offsets
|
||||||
|
pixels_offset = ((T_HMTFILE_TEXTURE_HEADER *)(pMemfile + pHmt->texture_offset +
|
||||||
|
sizeof(T_HMTFILE_HEADER2) + sizeof(T_HMTFILE_TEXTURE_HEADER) * i))->pixels_offset;
|
||||||
|
palette_offset = ((T_HMTFILE_TEXTURE_HEADER *)(pMemfile + pHmt->texture_offset +
|
||||||
|
sizeof(T_HMTFILE_HEADER2) + sizeof(T_HMTFILE_TEXTURE_HEADER) * i))->palette_offset;
|
||||||
|
|
||||||
|
// Get texture name
|
||||||
|
//memcpy(pHmt->textures[i].name, pMemfile + ((T_HMTFILE_TEXTURE_HEADER *)(pMemfile + pHmt->texture_offset + sizeof(T_HMTFILE_TEXTURE_HEADER) * (i + 1)))->texname_offset, 16);
|
||||||
|
snprintf((char *)pHmt->textures[i].name, 16, "%s", pMemfile + ((T_HMTFILE_TEXTURE_HEADER *)(pMemfile + pHmt->texture_offset +
|
||||||
|
sizeof(T_HMTFILE_HEADER2) + sizeof(T_HMTFILE_TEXTURE_HEADER) * i))->texname_offset);
|
||||||
|
|
||||||
|
if (pParams->verbose_mode) {
|
||||||
|
printf("[INFO] > Texture name: %s\n", pHmt->textures[i].name);
|
||||||
|
printf("[INFO] > Texture size: %dx%d\n", pHmt->textures[i].width, pHmt->textures[i].height);
|
||||||
|
printf("[INFO] > Texture type: %d\n", pHmt->textures[i].type);
|
||||||
|
printf("[INFO] > Samplebits: %d\n", pHmt->textures[i].sample_bits);
|
||||||
|
printf("[INFO] > Palette entries: %d\n", pHmt->textures[i].palette_entries);
|
||||||
|
printf("[INFO] > Texture bits per sample: %d\n", ((T_HMTFILE_TEXTURE_HEADER *)(pMemfile + pHmt->texture_offset + sizeof(T_HMTFILE_HEADER2) + sizeof(T_HMTFILE_TEXTURE_HEADER) * i))->tex_format.sample_bitsize);
|
||||||
|
printf("[INFO] > Texture transparent color: %d %d %d %d\n", pHmt->textures[i].alpha_color.r, pHmt->textures[i].alpha_color.g, pHmt->textures[i].alpha_color.b, pHmt->textures[i].alpha_color.a);
|
||||||
|
}
|
||||||
|
if (pParams->debug_mode) {
|
||||||
|
printf("[DBG] > Texture unknown0: 0x%X\n", ((T_HMTFILE_TEXTURE_HEADER *)(pMemfile + pHmt->texture_offset + sizeof(T_HMTFILE_HEADER2) + sizeof(T_HMTFILE_TEXTURE_HEADER) * i))->tex_format.unknown0);
|
||||||
|
if (((T_HMTFILE_TEXTURE_HEADER *)(pMemfile + pHmt->texture_offset + sizeof(T_HMTFILE_HEADER2) + sizeof(T_HMTFILE_TEXTURE_HEADER) * i))->tex_format.reserved0 != 1)
|
||||||
|
printf("[DBG] > Texture: Always 1 different.\n");
|
||||||
|
printf("[DBG] > Texture palette offset: 0x%X\n", palette_offset);
|
||||||
|
printf("[DBG] > Texture pixels offset: 0x%X\n", pixels_offset);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Retrieve palette datas from HMT file
|
||||||
|
switch (pHmt->textures[i].palette_entries) {
|
||||||
|
case 16:
|
||||||
|
case 256:
|
||||||
|
_palette = (T_R8G8B8 *)realloc(_palette, sizeof(T_R8G8B8) * pHmt->textures[i].palette_entries);
|
||||||
|
if (_palette)
|
||||||
|
memcpy(_palette, pMemfile + palette_offset, sizeof(T_R8G8B8) * pHmt->textures[i].palette_entries);
|
||||||
|
else return RSPLIB_ERROR_MEMORY;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Retrieve samples from HMT file
|
||||||
|
//TODO: better approach?
|
||||||
|
_samples = (T_SAMPLE *)realloc(_samples, pHmt->textures[i].width * pHmt->textures[i].height * pHmt->textures[i].sample_bits / 8);
|
||||||
|
if (_samples) {
|
||||||
|
memcpy(_samples, pMemfile + pixels_offset, pHmt->textures[i].width * pHmt->textures[i].height * pHmt->textures[i].sample_bits / 8);
|
||||||
|
//if (pHmt->textures[i].type == 2) memcpy(pHmt->textures[i].samples, pMemfile + pHmt->textures[i].pixels_offset, pHmt->textures[i].width * pHmt->textures[i].height * pHmt->textures[i].sample_bits / (8 * 4)); //TODO: manage texture type 2
|
||||||
|
} else return RSPLIB_ERROR_MEMORY;
|
||||||
|
|
||||||
|
// Decode palette and samples to pixels datas
|
||||||
|
TranslatePixels(&(pHmt->textures[i]), _samples, _palette);
|
||||||
|
|
||||||
|
if (pParams->debug_mode) printf("\n-----------------------End of texture #%d---------------------------\n", i);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (_palette) free(_palette);
|
||||||
|
if (_samples) free(_samples);
|
||||||
|
|
||||||
|
return RSPLIB_SUCCESS;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Convert samples to pixels using palette and texture informations.
|
||||||
|
*
|
||||||
|
* @param[in|out] pTexture Take texture structure to get the pixels buffer and texture datas.
|
||||||
|
* @param[in] pSamples Pointer to samples buffer.
|
||||||
|
* @param[in] pPalette Pointer to palette buffer.
|
||||||
|
*
|
||||||
|
* @return Error code, RSPLIB_SUCCESS when no error.
|
||||||
|
*/
|
||||||
|
static unsigned short TranslatePixels(T_RSPTEXTURE_TEXTURE* pTexture, const T_SAMPLE* pSamples, const T_R8G8B8* pPalette) {
|
||||||
|
unsigned int size;
|
||||||
|
|
||||||
|
if (pTexture == NULL) return RSPLIB_ERROR_ARGS_NULL;
|
||||||
|
if (!(pTexture->type == 0 ||
|
||||||
|
pTexture->type == 1 ||
|
||||||
|
pTexture->type == 2 ||
|
||||||
|
pTexture->type == 3 ||
|
||||||
|
pTexture->type == 4 ||
|
||||||
|
pTexture->type == 5)) return RSPLIB_ERROR_PROCESS;
|
||||||
|
|
||||||
|
size = pTexture->height * pTexture->width;
|
||||||
|
|
||||||
|
switch (pTexture->sample_bits) {
|
||||||
|
case 32:
|
||||||
|
pTexture->pixels = (T_R8G8B8A8 *)calloc(size, sizeof(T_R8G8B8A8));
|
||||||
|
if (pTexture->pixels == NULL) printf("[ERR] A texture failed to assert pixels buffer!");
|
||||||
|
memcpy(pTexture->pixels, pSamples, size * sizeof(T_R8G8B8A8));
|
||||||
|
break;
|
||||||
|
case 4:
|
||||||
|
pTexture->pixels = (T_R8G8B8A8 *)calloc(size, sizeof(T_R8G8B8A8));
|
||||||
|
if (pTexture->pixels == NULL) printf("[ERR] A texture failed to assert pixels buffer!");
|
||||||
|
if (pTexture->palette_entries == 0) {
|
||||||
|
convert4bitsGreyTo32bitsRGBA(pTexture->pixels, pSamples, size, pTexture->alpha_color);
|
||||||
|
} else if (pTexture->palette_entries == 16) {
|
||||||
|
convert4bitsTo32bitsRGBA(pTexture->pixels, pSamples, size, pPalette, pTexture->alpha_color);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case 8:
|
||||||
|
if (pTexture->palette_entries == 0) {
|
||||||
|
pTexture->pixels = (T_R8G8B8A8 *)calloc(size, 1);
|
||||||
|
if (pTexture->pixels == NULL) printf("[ERR] A texture failed to assert pixels buffer!");
|
||||||
|
memcpy(pTexture->pixels, pSamples, size);
|
||||||
|
} else if (pTexture->palette_entries == 256) {
|
||||||
|
pTexture->pixels = (T_R8G8B8A8 *)calloc(size, sizeof(T_R8G8B8A8));
|
||||||
|
if (pTexture->pixels == NULL) printf("[ERR] A texture failed to assert pixels buffer!");
|
||||||
|
convert8bitsTo32bitsRGBA(pTexture->pixels, pSamples, size, pPalette, pTexture->alpha_color);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case 16:
|
||||||
|
pTexture->pixels = (T_R8G8B8A8 *)calloc(size, 1);
|
||||||
|
if (pTexture->pixels == NULL) printf("[ERR] A texture failed to assert pixels buffer!");
|
||||||
|
useOddBytes(pTexture->pixels, pSamples, size);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
return RSPLIB_SUCCESS;
|
||||||
|
}
|
||||||
|
|
||||||
|
static unsigned short isTransparentColor(const T_R8G8B8A8 testColor, const T_R8G8B8A8 transp_color) {
|
||||||
|
if (!(testColor.r == transp_color.r)) return 0;
|
||||||
|
if (!(testColor.g == transp_color.g)) return 0;
|
||||||
|
if (!(testColor.b == transp_color.b)) return 0;
|
||||||
|
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void convert4bitsGreyTo32bitsRGBA(T_R8G8B8A8* pPixels, const T_SAMPLE* pSamples, const unsigned int sampling, const T_R8G8B8A8 transp_color) {
|
||||||
|
unsigned int i;
|
||||||
|
T_SAMPLE p;
|
||||||
|
|
||||||
|
for ( i = 0; i < (sampling / 2); i++ ) {
|
||||||
|
p = pSamples[i];
|
||||||
|
|
||||||
|
pPixels[i * 2].r = div((p >> 4 & 0xF) * 256, 16).quot;
|
||||||
|
pPixels[i * 2].g = div((p >> 4 & 0xF) * 256, 16).quot;
|
||||||
|
pPixels[i * 2].b = div((p >> 4 & 0xF) * 256, 16).quot;
|
||||||
|
pPixels[i * 2].a = isTransparentColor(pPixels[i * 2], transp_color) ? 255 - transp_color.a : 255;
|
||||||
|
pPixels[i * 2 + 1].r = div((p & 0xF) * 256, 16).quot;
|
||||||
|
pPixels[i * 2 + 1].g = div((p & 0xF) * 256, 16).quot;
|
||||||
|
pPixels[i * 2 + 1].b = div((p & 0xF) * 256, 16).quot;
|
||||||
|
pPixels[i * 2 + 1].a = isTransparentColor(pPixels[i * 2 + 1], transp_color) ? 255 - transp_color.a : 255;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void convert4bitsTo32bitsRGBA(T_R8G8B8A8* pPixels, const T_SAMPLE* pSamples, const unsigned int sampling, const T_R8G8B8* pal, const T_R8G8B8A8 transp_color) {
|
||||||
|
unsigned int i;
|
||||||
|
T_SAMPLE p;
|
||||||
|
|
||||||
|
for ( i = 0; i < (sampling / 2); i++ ) {
|
||||||
|
p = pSamples[i];
|
||||||
|
|
||||||
|
pPixels[i * 2].r = pal[(p >> 4) & 0xF].r;
|
||||||
|
pPixels[i * 2].g = pal[(p >> 4) & 0xF].g;
|
||||||
|
pPixels[i * 2].b = pal[(p >> 4) & 0xF].b;
|
||||||
|
pPixels[i * 2].a = isTransparentColor(pPixels[i * 2], transp_color) ? 255 - transp_color.a : 255;
|
||||||
|
pPixels[i * 2 + 1].r = pal[p & 0xF].r;
|
||||||
|
pPixels[i * 2 + 1].g = pal[p & 0xF].g;
|
||||||
|
pPixels[i * 2 + 1].b = pal[p & 0xF].b;
|
||||||
|
pPixels[i * 2 + 1].a = isTransparentColor(pPixels[i * 2 + 1], transp_color) ? 255 - transp_color.a : 255;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void convert8bitsTo32bitsRGBA(T_R8G8B8A8* pPixels, const T_SAMPLE* pSamples, const unsigned int sampling, const T_R8G8B8* pal, const T_R8G8B8A8 transp_color) {
|
||||||
|
unsigned int i;
|
||||||
|
T_SAMPLE p;
|
||||||
|
|
||||||
|
for ( i = 0; i < sampling; i++ ) {
|
||||||
|
p = pSamples[i];
|
||||||
|
pPixels[i].r = pal[p].r;
|
||||||
|
pPixels[i].g = pal[p].g;
|
||||||
|
pPixels[i].b = pal[p].b;
|
||||||
|
pPixels[i].a = isTransparentColor(pPixels[i], transp_color) ? 255 - transp_color.a : 255;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void useOddBytes(T_R8G8B8A8* pPixels, const T_SAMPLE* pSamples, const unsigned int sampling) {
|
||||||
|
unsigned int i;
|
||||||
|
|
||||||
|
for ( i = 0; i < (sampling - 1); i++ ) {
|
||||||
|
//dst[i] = src[i*2+1]; //FIXME: Implement optimized byte shifting
|
||||||
|
//dst[i]._red = src[i*2+1];
|
||||||
|
//dst[i]._green = src[i*2+1];
|
||||||
|
//dst[i]._blue = src[i*2+1];
|
||||||
|
}
|
||||||
|
}
|
51
RSPTextureLib/src/hmt_parser.h
Normal file
51
RSPTextureLib/src/hmt_parser.h
Normal file
@ -0,0 +1,51 @@
|
|||||||
|
/**
|
||||||
|
* @file hmt_parser.h
|
||||||
|
* @date 26/08/2022
|
||||||
|
* @author JackCarterSmith
|
||||||
|
* @copyright GPL-v3.0
|
||||||
|
* @brief Process HMP file structure and extract its datas.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "RSPTexture_datatypes.h"
|
||||||
|
|
||||||
|
|
||||||
|
#ifndef RSPTEXTURELIB_HMT_PARSER_H_
|
||||||
|
#define RSPTEXTURELIB_HMT_PARSER_H_
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Process HMT file stored in memory.
|
||||||
|
* @details Parser will directly extract tiles count and information stored in
|
||||||
|
* HMT file and store them in T_RSPTEXTURE_HMT structure.
|
||||||
|
* @note Unmanaged mode
|
||||||
|
*
|
||||||
|
* @param[in] pMemFile Pointer to an in-memory HOB file location.
|
||||||
|
* @param[out] hmtStruct Allocated empty T_RSPTEXTURE_HMT structure instance to
|
||||||
|
* be filled with HMP datas.
|
||||||
|
* @param[in] pParams Parser options. See RSPTEXTURE_PARAMETERS.
|
||||||
|
*
|
||||||
|
* @return Processing error code, RSPLIB_SUCCESS if no error.
|
||||||
|
*/
|
||||||
|
unsigned short RSP_TextureLib_ParseHMTMemFile(const MEMFILE pMemFile,
|
||||||
|
T_RSPTEXTURE_HMT* hmtStruct, const RSPTEXTURE_PARAMETERS* pParams);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Process HMT file in file system.
|
||||||
|
* @details HMP file is dumped in memory before parsing in order to enhance
|
||||||
|
* performance during parser operation and in optic to protect data
|
||||||
|
* stored in the original file (read-only).
|
||||||
|
* Parser will extract tiles count and information stored in HMT file
|
||||||
|
* and store them in T_RSPTEXTURE_HMT structure.
|
||||||
|
* @note Managed mode
|
||||||
|
*
|
||||||
|
* @param[in] fileName String value of file name/path.
|
||||||
|
* @param[out] hmtStruct Allocated empty T_RSPTEXTURE_HMT structure instance to
|
||||||
|
* be filled with HMP datas.
|
||||||
|
* @param[in] pParams Parser options. See RSPTEXTURE_PARAMETERS.
|
||||||
|
*
|
||||||
|
* @return Processing error code, RSPLIB_SUCCESS if no error.
|
||||||
|
*/
|
||||||
|
unsigned short RSP_TextureLib_ParseHMTFile(const char* fileName,
|
||||||
|
T_RSPTEXTURE_HMT* hmtStruct, const RSPTEXTURE_PARAMETERS* pParams);
|
||||||
|
|
||||||
|
#endif /* RSPTEXTURELIB_HMT_PARSER_H_ */
|
135
RSPTextureLib/src/hmt_struct.h
Normal file
135
RSPTextureLib/src/hmt_struct.h
Normal file
@ -0,0 +1,135 @@
|
|||||||
|
/**
|
||||||
|
* @file hmt_struct.h
|
||||||
|
* @date 26/08/2022
|
||||||
|
* @author JackCarterSmith
|
||||||
|
* @copyright GPL-v3.0
|
||||||
|
* @brief HMT file mapping definition.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef RSPTEXTURELIB_HMT_STRUCT_H_
|
||||||
|
#define RSPTEXTURELIB_HMT_STRUCT_H_
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
* long = 64bits??? (8 Bytes)
|
||||||
|
* int = 32bits (4 Bytes)
|
||||||
|
* short = 16bits (2 Bytes)
|
||||||
|
* char = 8bits (1 Bytes)
|
||||||
|
*/
|
||||||
|
|
||||||
|
#if defined(_MSC_VER)
|
||||||
|
#define PACK
|
||||||
|
#elif defined(__GNUC__)
|
||||||
|
#define PACK __attribute__((packed))
|
||||||
|
#endif
|
||||||
|
|
||||||
|
///////////////////////////////////////////////////////////////////////////////
|
||||||
|
// 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 hmtfile_header1 {
|
||||||
|
unsigned int materials_count;
|
||||||
|
unsigned int textures_offset;
|
||||||
|
} T_HMTFILE_HEADER1;
|
||||||
|
|
||||||
|
typedef struct PACK hmtfile_header2 {
|
||||||
|
unsigned int textures_count;
|
||||||
|
} T_HMTFILE_HEADER2;
|
||||||
|
|
||||||
|
typedef struct PACK hmtfile_material {
|
||||||
|
unsigned short type; // 1 - Material with texture / 2 - Material without texture
|
||||||
|
unsigned short texture_index;
|
||||||
|
|
||||||
|
float reserved0; // misc. Diffuse? Transparent?
|
||||||
|
float reserved1; // Always 1.0f Ambient?
|
||||||
|
|
||||||
|
unsigned int reserved2; // Zero Specular?
|
||||||
|
unsigned int reserved3; // 0x0A
|
||||||
|
|
||||||
|
unsigned char name[16];
|
||||||
|
} T_HMTFILE_MATERIAL;
|
||||||
|
|
||||||
|
typedef struct PACK hmtfile_texture_format {
|
||||||
|
unsigned char reserved0; // Always 1 ?
|
||||||
|
unsigned char sample_bitsize;
|
||||||
|
unsigned char type;
|
||||||
|
/*
|
||||||
|
0 - palette 16x3B RGB, 4bit per pixel
|
||||||
|
1 - 256x3B palette RGB, 8bit per pixel
|
||||||
|
3 - RGBA 32bpp
|
||||||
|
4 - greyscale, 4bpp
|
||||||
|
5 - grayscale, 8bpp
|
||||||
|
*/
|
||||||
|
unsigned char unknown0; // 0x40 / 0x80
|
||||||
|
unsigned int transparent_color; //TODO: replace by T_PIXEL type
|
||||||
|
} T_HMTFILE_TEXTURE_FORMAT;
|
||||||
|
|
||||||
|
typedef struct PACK hmtfile_texture_header {
|
||||||
|
unsigned int pixels_offset;
|
||||||
|
|
||||||
|
unsigned int reserved0; // 28B zeros
|
||||||
|
unsigned int reserved1;
|
||||||
|
unsigned int reserved2;
|
||||||
|
unsigned int reserved3;
|
||||||
|
unsigned int reserved4;
|
||||||
|
unsigned int reserved5;
|
||||||
|
unsigned int reserved6;
|
||||||
|
|
||||||
|
unsigned int palette_offset; // 0 = no palette
|
||||||
|
unsigned int texname_offset;
|
||||||
|
|
||||||
|
unsigned short tex_width;
|
||||||
|
unsigned short tex_height;
|
||||||
|
|
||||||
|
T_HMTFILE_TEXTURE_FORMAT tex_format;
|
||||||
|
} T_HMTFILE_TEXTURE_HEADER;
|
||||||
|
|
||||||
|
typedef struct PACK hmtfile_image_attributes {
|
||||||
|
unsigned short width; // Must be increased to a multiple of 2 if odd.
|
||||||
|
unsigned short height;
|
||||||
|
|
||||||
|
unsigned char reserved0; // 0x01
|
||||||
|
|
||||||
|
unsigned char bit_per_pixel; // 0 - 4bits / 1 - 8bits
|
||||||
|
unsigned char subtype; // 3 - RGBA / 4 - greyscale / 5 - ov_rdir
|
||||||
|
unsigned char reserved1; // 0x80/128
|
||||||
|
} T_HMTFILE_IMAGE_ATTRIBUTES;
|
||||||
|
|
||||||
|
typedef struct PACK hmtfile_image {
|
||||||
|
unsigned int data_size;
|
||||||
|
unsigned int pixels_offset;
|
||||||
|
|
||||||
|
unsigned int reserved0; // 32B zeros
|
||||||
|
unsigned int reserved1;
|
||||||
|
unsigned int reserved2;
|
||||||
|
unsigned int reserved3;
|
||||||
|
unsigned int reserved4;
|
||||||
|
unsigned int reserved5;
|
||||||
|
unsigned int reserved6;
|
||||||
|
unsigned int reserved7;
|
||||||
|
|
||||||
|
unsigned int desc_offset;
|
||||||
|
|
||||||
|
T_HMTFILE_IMAGE_ATTRIBUTES attributes;
|
||||||
|
|
||||||
|
unsigned int transparent_color; //TODO: replace by T_PIXEL type
|
||||||
|
unsigned int unknown0;
|
||||||
|
} T_HMTFILE_IMAGE;
|
||||||
|
|
||||||
|
typedef struct PACK hmtfile_texture {
|
||||||
|
unsigned char name[16]; // Normally = material name
|
||||||
|
unsigned int RGB_palette; //TODO: to define
|
||||||
|
unsigned int pixels_samples; //TODO: to define
|
||||||
|
} T_HMTFILE_TEXTURE;
|
||||||
|
|
||||||
|
#if defined(_MSC_VER)
|
||||||
|
#pragma pack(pop)
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#endif /* RSPTEXTURELIB_HMT_STRUCT_H_ */
|
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()
|
126
conanfile.py
Normal file
126
conanfile.py
Normal file
@ -0,0 +1,126 @@
|
|||||||
|
import os
|
||||||
|
from conan import ConanFile
|
||||||
|
from conan.tools.cmake import CMakeToolchain, CMakeDeps, CMake
|
||||||
|
from conan.tools.files import copy
|
||||||
|
from conan.tools.scm import Git, Version
|
||||||
|
|
||||||
|
required_conan_version = ">=2.3"
|
||||||
|
|
||||||
|
class rse_texture(ConanFile):
|
||||||
|
name = "rsptexturelib"
|
||||||
|
package_type = "library"
|
||||||
|
version = "2.1.0"
|
||||||
|
revision_mode = "scm"
|
||||||
|
license = "GPL-3.0"
|
||||||
|
author = "JackCarterSmith <jackcartersmith@jcsmith.fr>"
|
||||||
|
url = "https://git.jcsmith.fr/JCS-Prod/RSE-Texture"
|
||||||
|
description = "Rogue Squadron 3D (PC) game textures files (HMT) extractor"
|
||||||
|
settings = "os", "compiler", "build_type", "arch"
|
||||||
|
generators = "CMakeDeps"
|
||||||
|
options = {
|
||||||
|
"shared": [True, False],
|
||||||
|
"tools": [True, False],
|
||||||
|
"fPIC": [True, False]
|
||||||
|
}
|
||||||
|
|
||||||
|
default_options = {
|
||||||
|
"shared": True,
|
||||||
|
"tools": False,
|
||||||
|
"fPIC": True
|
||||||
|
}
|
||||||
|
|
||||||
|
@property
|
||||||
|
def _is_msvc(self):
|
||||||
|
return str(self.settings.compiler) in ["Visual Studio", "msvc"]
|
||||||
|
|
||||||
|
#def validate(self):
|
||||||
|
# if self.settings.os == "Macos":
|
||||||
|
# raise ConanInvalidConfiguration("MacOS not supported")
|
||||||
|
|
||||||
|
def config_options(self):
|
||||||
|
if self.settings.os == "Windows":
|
||||||
|
del self.options.fPIC
|
||||||
|
|
||||||
|
def configure(self):
|
||||||
|
self.options["libpng"].shared = True
|
||||||
|
self.options["libpng"].sse = True
|
||||||
|
if self.options.shared:
|
||||||
|
self.options.rm_safe("fPIC")
|
||||||
|
|
||||||
|
def requirements(self):
|
||||||
|
if self.options.tools:
|
||||||
|
self.requires("zlib/1.3.1")
|
||||||
|
self.requires("libpng/1.6.43")
|
||||||
|
|
||||||
|
def source(self):
|
||||||
|
git = Git(self)
|
||||||
|
cargs = ['--single-branch', '--recursive', '--depth', '1', '--branch', 'v' + self.version]
|
||||||
|
git.clone(url="https://git.jcsmith.fr/JCS-Prod/RSE-Texture.git", target=".", args=cargs)
|
||||||
|
|
||||||
|
# def _patch(self):
|
||||||
|
# replace_in_file(self, os.path.join(self.source_folder, "RSPTextureLib", "CMakeLists.txt"),
|
||||||
|
# 'set_target_properties(rsp-texture-libstatic PROPERTIES OUTPUT_NAME "${RSP_TEXTURE_LIB_NAME}_static")',
|
||||||
|
# 'set_target_properties(rsp-texture-libstatic PROPERTIES OUTPUT_NAME "${RSP_TEXTURE_LIB_NAME}")')
|
||||||
|
|
||||||
|
def export_sources(self):
|
||||||
|
copy(self, "CMakeLists.txt", self.recipe_folder, self.export_sources_folder)
|
||||||
|
|
||||||
|
# def layout(self):
|
||||||
|
# cmake_layout(self, src_folder='.', build_folder='build')
|
||||||
|
|
||||||
|
def generate(self):
|
||||||
|
tc = CMakeToolchain(self)
|
||||||
|
tc.cache_variables["RSPTEXTURE_SHARED"] = self.options.shared
|
||||||
|
tc.cache_variables["RSPTEXTURE_STATIC"] = not self.options.shared
|
||||||
|
tc.cache_variables["BUILD_TOOLS"] = self.options.tools
|
||||||
|
#tc.cache_variables["BUILD_DEBUG"] = self.settings.build_type == "Debug"
|
||||||
|
tc.generate()
|
||||||
|
|
||||||
|
#cmdeps = CMakeDeps(self)
|
||||||
|
#cmpdeps.set_property("zlib", "cmake_find_mode", "both")
|
||||||
|
#cmpdeps.set_property("libpng", "cmake_find_mode", "both")
|
||||||
|
#if self.options.shared:
|
||||||
|
#cmdeps.configuration = "ReleaseShared"
|
||||||
|
#cmdeps.generate()
|
||||||
|
|
||||||
|
for dep in self.dependencies.values():
|
||||||
|
if len(dep.cpp_info.bindirs) > 0:
|
||||||
|
if self.settings.os == "Windows":
|
||||||
|
if self._is_msvc:
|
||||||
|
copy(self, "*.dll", dep.cpp_info.bindirs[0], os.path.join(self.build_folder, "bin", str(self.settings.build_type)))
|
||||||
|
else:
|
||||||
|
copy(self, "*.dll", dep.cpp_info.bindirs[0], os.path.join(self.build_folder, "bin"))
|
||||||
|
else:
|
||||||
|
copy(self, "*.so", dep.cpp_info.bindirs[0], os.path.join(self.build_folder, "bin"))
|
||||||
|
|
||||||
|
def build(self):
|
||||||
|
cmbuilder = CMake(self)
|
||||||
|
#self._patch()
|
||||||
|
cmbuilder.configure()
|
||||||
|
cmbuilder.build()
|
||||||
|
|
||||||
|
def package(self):
|
||||||
|
copy(self, "LICENSE", src=self.source_folder, dst=os.path.join(self.package_folder, "licenses"))
|
||||||
|
copy(self, pattern="*.h", src=os.path.join(self.source_folder, "include"), dst=os.path.join(self.package_folder, "include"))
|
||||||
|
copy(self, pattern="*.a", src=self.build_folder, dst=os.path.join(self.package_folder, "lib"), keep_path=False)
|
||||||
|
copy(self, pattern="*.so", src=self.build_folder, dst=os.path.join(self.package_folder, "lib"), keep_path=False)
|
||||||
|
copy(self, pattern="*.lib", src=self.build_folder, dst=os.path.join(self.package_folder, "lib"), keep_path=False)
|
||||||
|
copy(self, pattern="*.dll", src=self.build_folder, dst=os.path.join(self.package_folder, "bin"), keep_path=False)
|
||||||
|
|
||||||
|
def package_info(self):
|
||||||
|
self.cpp_info.set_property("cmake_file_name", "RSETexture")
|
||||||
|
self.cpp_info.set_property("cmake_target_name", "RSETexture")
|
||||||
|
self.cpp_info.set_property("cmake_module_target_name", "RSETexture::RSETexture")
|
||||||
|
self.cpp_info.set_property("cmake_find_mode", "both")
|
||||||
|
|
||||||
|
self.cpp_info.names["cmake_find_package"] = "RSETexture"
|
||||||
|
self.cpp_info.names["cmake_find_package_multi"] = "RSETexture"
|
||||||
|
|
||||||
|
self.cpp_info.includedirs = ["include"]
|
||||||
|
|
||||||
|
prefix = "lib" if self._is_msvc else ""
|
||||||
|
#suffix = "d" if self.settings.build_type == "Debug" else ""
|
||||||
|
suffix = ""
|
||||||
|
major_min_version = f"{Version(self.version).major}{Version(self.version).minor}"
|
||||||
|
|
||||||
|
self.cpp_info.libs = ["{}RSETexture{}{}".format(prefix, major_min_version, suffix)]
|
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_ */
|
File diff suppressed because it is too large
Load Diff
161
src/HMT_Parser.c
161
src/HMT_Parser.c
@ -1,161 +0,0 @@
|
|||||||
#include "HMT_Parser.h"
|
|
||||||
|
|
||||||
|
|
||||||
extern int _options; // Global options settings variable
|
|
||||||
|
|
||||||
HMT_FILE *parseHMTFile(FILE *hmt_src) {
|
|
||||||
int i;
|
|
||||||
HMT_FILE *_buff = NULL;
|
|
||||||
|
|
||||||
if (hmt_src == NULL) return NULL;
|
|
||||||
_buff = calloc(1, sizeof(HMT_FILE));
|
|
||||||
|
|
||||||
rewind(hmt_src); //Rewind file at the start
|
|
||||||
fread(&(_buff->material_count), 4, 1, hmt_src); // Extract first usefull datas
|
|
||||||
fread(&(_buff->texture_offset), 4, 1, hmt_src);
|
|
||||||
|
|
||||||
// Read materials
|
|
||||||
printf("[INFO] Materials detected: %d\n", _buff->material_count);
|
|
||||||
_buff->materials_list = calloc(_buff->material_count, sizeof(HMT_MATERIAL)); // Create a big list of materials entries
|
|
||||||
for (i=0; i<_buff->material_count; i++) {
|
|
||||||
// Extract materials datas
|
|
||||||
if (readMaterial(&(_buff->materials_list[i]), hmt_src) != 0) {
|
|
||||||
purgeHMTFromMemory(_buff);
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Read textures
|
|
||||||
fseek(hmt_src, _buff->texture_offset, SEEK_SET);
|
|
||||||
fread(&(_buff->texture_count), 4, 1, hmt_src);
|
|
||||||
printf("[INFO] Textures detected: %d\n\n", _buff->texture_count);
|
|
||||||
if (_buff->texture_count > 0) {
|
|
||||||
_buff->textures_list = calloc(_buff->texture_count, sizeof(HMT_TEXTURE)); // Create a big list of textures entries
|
|
||||||
for (i=0; i<_buff->texture_count; i++) {
|
|
||||||
// Extract textures datas
|
|
||||||
if (readTexture(&(_buff->textures_list[i]), hmt_src) != 0) {
|
|
||||||
purgeHMTFromMemory(_buff);
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return _buff;
|
|
||||||
}
|
|
||||||
|
|
||||||
int readMaterial(HMT_MATERIAL *mat, FILE *hmt_src) {
|
|
||||||
if (mat == NULL || hmt_src == NULL) return EXIT_FAILURE;
|
|
||||||
|
|
||||||
fread(mat, sizeof(HMT_MATERIAL), 1, hmt_src);
|
|
||||||
|
|
||||||
if (_options & 0x1) {
|
|
||||||
if (mat->zero != 0 || mat->hex_a != 0x0A) printf("\n Uncommon file detected!\n");
|
|
||||||
printf("Material type: %d\nTexture index: %d\n", mat->type_, mat->texture_index);
|
|
||||||
}
|
|
||||||
|
|
||||||
return EXIT_SUCCESS;
|
|
||||||
}
|
|
||||||
|
|
||||||
int readTexture(HMT_TEXTURE *tex, FILE *hmt_src) {
|
|
||||||
unsigned char u0,u1,bpp;
|
|
||||||
long pos;
|
|
||||||
RS_IMAGE_DESC desc;
|
|
||||||
|
|
||||||
fread(&(tex->data_offset), 4, 1, hmt_src);
|
|
||||||
fseek(hmt_src, 28, SEEK_CUR); // Skip zeros area
|
|
||||||
fread(&(tex->palette_offset), 4, 1, hmt_src);
|
|
||||||
fread(&(tex->textureName_offset), 4, 1, hmt_src);
|
|
||||||
fread(&(tex->width), 2, 1, hmt_src);
|
|
||||||
fread(&(tex->height), 2, 1, hmt_src);
|
|
||||||
|
|
||||||
fread(&u0, 1, 1, hmt_src);
|
|
||||||
fread(&bpp, 1, 1, hmt_src);
|
|
||||||
fread(&(tex->image.type_), 1, 1, hmt_src);
|
|
||||||
fread(&u1, 1, 1, hmt_src);
|
|
||||||
fread(&(tex->image.alpha_color._red), 1, 1, hmt_src);
|
|
||||||
fread(&(tex->image.alpha_color._green), 1, 1, hmt_src);
|
|
||||||
fread(&(tex->image.alpha_color._blue), 1, 1, hmt_src);
|
|
||||||
fread(&(tex->image.alpha_color._alpha), 1, 1, hmt_src);
|
|
||||||
|
|
||||||
pos = ftell(hmt_src);
|
|
||||||
fseek(hmt_src, tex->textureName_offset, SEEK_SET);
|
|
||||||
fread(&(tex->name), 16, 1, hmt_src);
|
|
||||||
fseek(hmt_src, pos, SEEK_SET);
|
|
||||||
|
|
||||||
desc = getImageDescFromType(tex->image.type_);
|
|
||||||
tex->image.paletteEntries = desc.palette_entries;
|
|
||||||
tex->image.sampleBits = desc.sample_bits;
|
|
||||||
tex->image.width = tex->width;
|
|
||||||
tex->image.height = tex->height;
|
|
||||||
|
|
||||||
if (_options & VERBOSE_ENABLED) {
|
|
||||||
printf("\n");
|
|
||||||
printf("Texture name: %s\n", tex->name);
|
|
||||||
printf("Size w: %ld h: %ld\n", tex->width, tex->height);
|
|
||||||
printf("Texture subtype: %d\n", tex->image.type_);
|
|
||||||
printf("Palette offset: %d\n", tex->palette_offset);
|
|
||||||
printf("Data offset: %d\n", tex->data_offset);
|
|
||||||
printf("Transparent color (RGB): %X %X %X\n", tex->image.alpha_color._red, tex->image.alpha_color._green, tex->image.alpha_color._blue);
|
|
||||||
printf("u0: %d u1: %d\n", u0, u1);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (tex->palette_offset > 0) {
|
|
||||||
if (_options & VERBOSE_ENABLED) printf("\nPalette entries: %d\n", tex->image.paletteEntries);
|
|
||||||
fseek(hmt_src, tex->palette_offset, SEEK_SET);
|
|
||||||
getPaletteFromFile(&(tex->image), hmt_src);
|
|
||||||
}
|
|
||||||
fseek(hmt_src, tex->data_offset, SEEK_SET);
|
|
||||||
getSamplesFromFile(&(tex->image), hmt_src);
|
|
||||||
decodePixels(&(tex->image));
|
|
||||||
|
|
||||||
fseek(hmt_src, pos, SEEK_SET);
|
|
||||||
|
|
||||||
return EXIT_SUCCESS;
|
|
||||||
}
|
|
||||||
|
|
||||||
int getPaletteFromFile(RS_IMAGE *img, FILE *f) {
|
|
||||||
int entries = img->paletteEntries;
|
|
||||||
|
|
||||||
switch (entries) {
|
|
||||||
case 16:
|
|
||||||
case 256:
|
|
||||||
fread(img->palette, sizeof(PIXEL), entries, f);
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
return EXIT_SUCCESS;
|
|
||||||
}
|
|
||||||
|
|
||||||
int getSamplesFromFile(RS_IMAGE *img, FILE *f) {
|
|
||||||
int sample_bits = img->sampleBits;
|
|
||||||
int size = div(img->width*img->height*sample_bits, 8).quot;
|
|
||||||
|
|
||||||
/*
|
|
||||||
if (f->_bufsize >= ftell(f)+size) { //TODO: Check C equivalent
|
|
||||||
printf("[ERR] WARNING! Please fix size/sample.");
|
|
||||||
return EXIT_FAILURE;
|
|
||||||
}
|
|
||||||
*/
|
|
||||||
|
|
||||||
img->samples = calloc(1, size);
|
|
||||||
fread(img->samples, size, 1, f);
|
|
||||||
if (img->type_ == 2) fread(img->samples, div(size, 4).quot, 1, f);
|
|
||||||
|
|
||||||
return EXIT_SUCCESS;
|
|
||||||
}
|
|
||||||
|
|
||||||
void purgeHMTFromMemory(HMT_FILE *_f) {
|
|
||||||
if (_f == NULL) return;
|
|
||||||
|
|
||||||
if (_f->textures_list != NULL) {
|
|
||||||
if (_f->textures_list->image.pixels != NULL) free(_f->textures_list->image.pixels);
|
|
||||||
if (_f->textures_list->image.samples != NULL) free(_f->textures_list->image.samples);
|
|
||||||
}
|
|
||||||
free(_f->textures_list);
|
|
||||||
|
|
||||||
if (_f->materials_list != NULL) free(_f->materials_list);
|
|
||||||
|
|
||||||
free(_f);
|
|
||||||
}
|
|
108
src/HMT_Parser.h
108
src/HMT_Parser.h
@ -1,108 +0,0 @@
|
|||||||
#ifndef HMT_PARSER_H_
|
|
||||||
#define HMT_PARSER_H_
|
|
||||||
|
|
||||||
#include <stdio.h>
|
|
||||||
#include <stdlib.h>
|
|
||||||
#include "options.h"
|
|
||||||
#include "RS_images.h"
|
|
||||||
|
|
||||||
/////////////////////////////
|
|
||||||
///// Define HMT types //////
|
|
||||||
/////////////////////////////
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief Material struct inside HMT file type
|
|
||||||
*
|
|
||||||
* Actual RE material struct:\n
|
|
||||||
* 4B material entry count MC\n
|
|
||||||
* 4B offset after material entries / offset to textures\n
|
|
||||||
* MC * material entry (36B)\n
|
|
||||||
* [\n
|
|
||||||
* 2B int material/texture type:\n
|
|
||||||
* 1 - material with texture\n
|
|
||||||
* 2 - material without texture\n
|
|
||||||
* 2B int texture index\n
|
|
||||||
* 4B float (scale factor?)\n
|
|
||||||
* 4B float (always 1.0)\n
|
|
||||||
* 4B int zero\n
|
|
||||||
* 4B int 0x0A\n
|
|
||||||
* 16B name\n
|
|
||||||
* ]\n
|
|
||||||
*
|
|
||||||
* @image html hmt_materialDef.png
|
|
||||||
*/
|
|
||||||
typedef struct HMTMaterial {
|
|
||||||
short type_; /**< Material type:\n 1 = Material with texture\n 2 = Material without texture */
|
|
||||||
short texture_index;
|
|
||||||
float unknow1,unknow2;
|
|
||||||
int zero;
|
|
||||||
int hex_a;
|
|
||||||
char name[16];
|
|
||||||
}HMT_MATERIAL;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief Texture struct inside HMT file type
|
|
||||||
*
|
|
||||||
* Actual RE texture struct:\n
|
|
||||||
* 4B int texcount Tc\n
|
|
||||||
* TC * texture entry 52B\n
|
|
||||||
* [\n
|
|
||||||
* 4B int pixel offset\n
|
|
||||||
* 28B zero\n
|
|
||||||
* 4B int palette offset, 0 = no palette\n
|
|
||||||
* 4B int texname offset\n
|
|
||||||
* 2B int width\n
|
|
||||||
* 2B int height\n
|
|
||||||
* 8B texture format [\n
|
|
||||||
* 1B int : always 1?\n
|
|
||||||
* 1B int : bits per sample?\n
|
|
||||||
* 1B int : subtype:\n
|
|
||||||
* -0 - palette 16x3B RGB, 4bit per pixel\n
|
|
||||||
* -1 - 256x3B palette RGB, 8bit per pixel\n
|
|
||||||
* -3 - RGBA 32bpp\n
|
|
||||||
* -4 - greyscale, 4bpp\n
|
|
||||||
* -5 - grayscale, 8bpp\n
|
|
||||||
* 1B int ? 0, 0x40, 0x80\n
|
|
||||||
* 4B RGBA transparent color?\n
|
|
||||||
* ]\n
|
|
||||||
* ]\n
|
|
||||||
*
|
|
||||||
* @image html hmt_textureDef.png
|
|
||||||
*/
|
|
||||||
typedef struct HMTTexture {
|
|
||||||
int data_offset;
|
|
||||||
int palette_offset;
|
|
||||||
int textureName_offset;
|
|
||||||
unsigned long width, height;
|
|
||||||
char name[16];
|
|
||||||
RS_IMAGE image;
|
|
||||||
}HMT_TEXTURE;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief Instance of HMTFile in memory
|
|
||||||
* This structure contain all parsed data for a single HMT file.
|
|
||||||
*/
|
|
||||||
typedef struct HMTFile {
|
|
||||||
int material_count; /**< Number of materials registered inside HMTFile instance. */
|
|
||||||
int texture_offset; /**< Address from which texture data begins. */
|
|
||||||
int texture_count; /**< Number of textures registered inside HMTFile instance. */
|
|
||||||
HMT_MATERIAL *materials_list; /**< Starting pointer of the materials list. Managed like an array and declared as a pointer */
|
|
||||||
HMT_TEXTURE *textures_list; /**< Starting pointer of the textures list. Managed like an array and declared as a pointer*/
|
|
||||||
}HMT_FILE;
|
|
||||||
|
|
||||||
|
|
||||||
/////////////////////////////
|
|
||||||
///// Declare functions /////
|
|
||||||
/////////////////////////////
|
|
||||||
HMT_FILE *parseHMTFile(FILE *hmt_src);
|
|
||||||
int readMaterial(HMT_MATERIAL *mat, FILE *hmt_src);
|
|
||||||
int readTexture(HMT_TEXTURE *tex, FILE *hmt_src);
|
|
||||||
HMT_MATERIAL *getMaterialFromIndex(int i);
|
|
||||||
HMT_MATERIAL *getMaterialFromName(char *matName);
|
|
||||||
HMT_TEXTURE *getTextureFromIndex(int i);
|
|
||||||
HMT_TEXTURE *getTextureFromMaterial(HMT_MATERIAL *mat);
|
|
||||||
int getPaletteFromFile(RS_IMAGE *img, FILE *f);
|
|
||||||
int getSamplesFromFile(RS_IMAGE *img, FILE *f);
|
|
||||||
void purgeHMTFromMemory(HMT_FILE *_f);
|
|
||||||
|
|
||||||
#endif
|
|
@ -1,74 +0,0 @@
|
|||||||
#include "Image_Exporter.h"
|
|
||||||
|
|
||||||
|
|
||||||
extern int _options; // Global options settings variable
|
|
||||||
|
|
||||||
int saveToPNG(RS_IMAGE *img, char *tex_path, char *hmt_fileName) {
|
|
||||||
if (tex_path == NULL || img == NULL) return EXIT_FAILURE;
|
|
||||||
char export_path[128];
|
|
||||||
FILE *_png_f = NULL;
|
|
||||||
png_structp png_ptr = NULL;
|
|
||||||
png_infop info_ptr = NULL;
|
|
||||||
size_t x,y;
|
|
||||||
png_byte **row_ptrs = NULL;
|
|
||||||
PIXEL_A *pixel = NULL;
|
|
||||||
//int pixel_size = 3;
|
|
||||||
//int depth = 8; //bit par color channel (RGB)
|
|
||||||
|
|
||||||
if (_options & OUTPUT_DIR) {
|
|
||||||
strcpy(export_path, hmt_fileName);
|
|
||||||
#ifdef _WIN32
|
|
||||||
strcat(export_path, "-out\\");
|
|
||||||
#else
|
|
||||||
strcat(export_path, "-out/");
|
|
||||||
#endif
|
|
||||||
strcat(export_path, tex_path);
|
|
||||||
} else {
|
|
||||||
strcpy(export_path, tex_path);
|
|
||||||
}
|
|
||||||
strcat(export_path, ".png");
|
|
||||||
_png_f = fopen(export_path, "wb");
|
|
||||||
if (_png_f == NULL) return EXIT_FAILURE;
|
|
||||||
png_ptr = png_create_write_struct(PNG_LIBPNG_VER_STRING, NULL, NULL, NULL);
|
|
||||||
if (png_ptr == NULL) {
|
|
||||||
fclose(_png_f);
|
|
||||||
return EXIT_FAILURE;
|
|
||||||
}
|
|
||||||
info_ptr = png_create_info_struct(png_ptr);
|
|
||||||
if (info_ptr == NULL) {
|
|
||||||
fclose(_png_f);
|
|
||||||
return EXIT_FAILURE;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Set image attributes
|
|
||||||
png_set_IHDR(png_ptr, info_ptr, img->width, img->height, 8, PNG_COLOR_TYPE_RGBA, PNG_INTERLACE_NONE, PNG_COMPRESSION_TYPE_DEFAULT, PNG_FILTER_TYPE_DEFAULT);
|
|
||||||
|
|
||||||
// Init PNG datas
|
|
||||||
row_ptrs = png_malloc(png_ptr, img->height * sizeof(png_byte *));
|
|
||||||
for (y=0; y<img->height; y++) {
|
|
||||||
png_byte *row = png_malloc(png_ptr, img->width*sizeof(PIXEL_A));
|
|
||||||
row_ptrs[y] = row;
|
|
||||||
for (x=0; x<img->width; x++) {
|
|
||||||
pixel = pixelAt(img, x , y);
|
|
||||||
if(pixel == NULL) return EXIT_FAILURE;
|
|
||||||
|
|
||||||
*row++ = pixel->_red;
|
|
||||||
*row++ = pixel->_green;
|
|
||||||
*row++ = pixel->_blue;
|
|
||||||
*row++ = pixel->_alpha;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
png_init_io(png_ptr, _png_f);
|
|
||||||
png_set_rows(png_ptr, info_ptr, row_ptrs);
|
|
||||||
png_write_png(png_ptr, info_ptr, PNG_TRANSFORM_IDENTITY, NULL);
|
|
||||||
|
|
||||||
for (y=0; y<img->height; y++) {
|
|
||||||
png_free(png_ptr, row_ptrs[y]);
|
|
||||||
}
|
|
||||||
png_free(png_ptr, row_ptrs);
|
|
||||||
png_destroy_write_struct(&png_ptr, &info_ptr);
|
|
||||||
fclose(_png_f);
|
|
||||||
|
|
||||||
return EXIT_SUCCESS;
|
|
||||||
}
|
|
@ -1,12 +0,0 @@
|
|||||||
#ifndef IMAGE_EXPORTER_H_
|
|
||||||
#define IMAGE_EXPORTER_H_
|
|
||||||
|
|
||||||
#include "options.h"
|
|
||||||
#include "RS_images.h"
|
|
||||||
#include <zlib.h>
|
|
||||||
#include <png.h>
|
|
||||||
|
|
||||||
|
|
||||||
int saveToPNG(RS_IMAGE *img, char *tex_name, char *hmt_fileName);
|
|
||||||
|
|
||||||
#endif
|
|
149
src/RS_images.c
149
src/RS_images.c
@ -1,149 +0,0 @@
|
|||||||
#include "RS_images.h"
|
|
||||||
|
|
||||||
|
|
||||||
//extern int _options; // Global options settings variable
|
|
||||||
|
|
||||||
void decodePixels(RS_IMAGE *img) {
|
|
||||||
int size;
|
|
||||||
|
|
||||||
//img->pixels = NULL;
|
|
||||||
if (!(img->type_ == 0 ||
|
|
||||||
img->type_ == 1 ||
|
|
||||||
img->type_ == 2 ||
|
|
||||||
img->type_ == 3 ||
|
|
||||||
img->type_ == 4 ||
|
|
||||||
img->type_ == 5)) return;
|
|
||||||
|
|
||||||
size = img->height * img->width;
|
|
||||||
switch (img->sampleBits) {
|
|
||||||
case 32:
|
|
||||||
img->pixels = calloc(1, size * sizeof(PIXEL_A));
|
|
||||||
memcpy(img->pixels, img->samples, size * sizeof(PIXEL_A));
|
|
||||||
break;
|
|
||||||
case 4:
|
|
||||||
img->pixels = calloc(1, size * sizeof(PIXEL_A));
|
|
||||||
if (img->paletteEntries == 0) {
|
|
||||||
convert4bitsGreyTo32bitsRGBA(img->samples, img->pixels, size, &(img->alpha_color));
|
|
||||||
} else if (img->paletteEntries == 16) {
|
|
||||||
convert4bitsTo32bitsRGBA(img->samples, img->pixels, size, img->palette, &(img->alpha_color));
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
case 8:
|
|
||||||
if (img->paletteEntries == 0) {
|
|
||||||
img->pixels = calloc(1, size);
|
|
||||||
memcpy(img->pixels, img->samples, size);
|
|
||||||
} else if (img->paletteEntries == 256) {
|
|
||||||
img->pixels = calloc(1, size * sizeof(PIXEL_A));
|
|
||||||
convert8bitsTo32bitsRGBA(img->samples, img->pixels, size, img->palette, &(img->alpha_color));
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
case 16:
|
|
||||||
img->pixels = calloc(1, size);
|
|
||||||
useOddBytes(img->samples, img->pixels, size);
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
int isTransparentColor(PIXEL_A *testColor, PIXEL_A *transp_color) {
|
|
||||||
if (transp_color == NULL || testColor == NULL) return -2;
|
|
||||||
|
|
||||||
if (!(testColor->_red == transp_color->_red)) return -1;
|
|
||||||
if (!(testColor->_green == transp_color->_green)) return -1;
|
|
||||||
if (!(testColor->_blue == transp_color->_blue)) return -1;
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
void convert4bitsGreyTo32bitsRGBA(unsigned char *samples_tab, PIXEL_A *pixels_tab, int sampling, PIXEL_A *transp_color) {
|
|
||||||
int i;
|
|
||||||
unsigned char v;
|
|
||||||
|
|
||||||
for(i=0; i<div(sampling,2).quot; i++) {
|
|
||||||
v = samples_tab[i];
|
|
||||||
pixels_tab[i*2]._red = div((v >> 4 & 0xF) * 256, 16).quot;
|
|
||||||
pixels_tab[i*2]._green = div((v >> 4 & 0xF) * 256, 16).quot;
|
|
||||||
pixels_tab[i*2]._blue = div((v >> 4 & 0xF) * 256, 16).quot;
|
|
||||||
if (isTransparentColor(&(pixels_tab[i*2]), transp_color) == 0) pixels_tab[i*2]._alpha = 0xFF - transp_color->_alpha; else pixels_tab[i*2]._alpha = 0xFF; // Test if color is a transparent color and adjust alpha layer
|
|
||||||
pixels_tab[i*2+1]._red = div((v & 0xF) * 256, 16).quot;
|
|
||||||
pixels_tab[i*2+1]._green = div((v & 0xF) * 256, 16).quot;
|
|
||||||
pixels_tab[i*2+1]._blue = div((v & 0xF) * 256, 16).quot;
|
|
||||||
if (isTransparentColor(&(pixels_tab[i*2+1]), transp_color) == 0) pixels_tab[i*2+1]._alpha = 0xFF - transp_color->_alpha; else pixels_tab[i*2+1]._alpha = 0xFF; // Test if color is a transparent color and adjust alpha layer
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void convert4bitsTo32bitsRGBA(unsigned char *samples_tab, PIXEL_A *pixels_tab, int size, PIXEL *pal, PIXEL_A *transp_color) {
|
|
||||||
int i,index;
|
|
||||||
|
|
||||||
for(i=0; i<div(size,2).quot; i++) {
|
|
||||||
index = samples_tab[i];
|
|
||||||
pixels_tab[i*2]._red = pal[(index >> 4) & 0xF]._red;
|
|
||||||
pixels_tab[i*2]._green = pal[(index >> 4) & 0xF]._green;
|
|
||||||
pixels_tab[i*2]._blue = pal[(index >> 4) & 0xF]._blue;
|
|
||||||
if (isTransparentColor(&(pixels_tab[i*2]), transp_color) == 0) pixels_tab[i*2]._alpha = 0xFF - transp_color->_alpha; else pixels_tab[i*2]._alpha = 0xFF; // Test if color is a transparent color and adjust alpha layer
|
|
||||||
pixels_tab[i*2+1]._red = pal[index & 0xF]._red;
|
|
||||||
pixels_tab[i*2+1]._green = pal[index & 0xF]._green;
|
|
||||||
pixels_tab[i*2+1]._blue = pal[index & 0xF]._blue;
|
|
||||||
if (isTransparentColor(&(pixels_tab[i*2+1]), transp_color) == 0) pixels_tab[i*2]._alpha = 0xFF - transp_color->_alpha; else pixels_tab[i*2+1]._alpha = 0xFF; // Test if color is a transparent color and adjust alpha layer
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void convert8bitsTo32bitsRGBA(unsigned char *samples_tab, PIXEL_A *pixels_tab, int size, PIXEL *pal, PIXEL_A *transp_color) {
|
|
||||||
int i,index;
|
|
||||||
|
|
||||||
for(i=0; i<size; i++) {
|
|
||||||
index = samples_tab[i];
|
|
||||||
pixels_tab[i]._red = pal[index]._red;
|
|
||||||
pixels_tab[i]._green = pal[index]._green;
|
|
||||||
pixels_tab[i]._blue = pal[index]._blue;
|
|
||||||
if (isTransparentColor(&(pixels_tab[i]), transp_color) == 0) pixels_tab[i]._alpha = 0xFF - transp_color->_alpha; else pixels_tab[i]._alpha = 0xFF; // Test if color is a transparent color and adjust alpha layer
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void useOddBytes(unsigned char *src, PIXEL_A *dst, int size) {
|
|
||||||
int i;
|
|
||||||
|
|
||||||
for(i=0; i<size; i++) {
|
|
||||||
//dst[i] = src[i*2+1];
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
PIXEL_A *pixelAt(RS_IMAGE *img, int posX , int posY) {
|
|
||||||
return img->pixels + img->width * posY + posX;
|
|
||||||
}
|
|
||||||
|
|
||||||
RS_IMAGE_DESC getImageDescFromType(unsigned char type) {
|
|
||||||
RS_IMAGE_DESC desc;
|
|
||||||
|
|
||||||
switch(type) {
|
|
||||||
case 0:
|
|
||||||
desc.palette_entries = 16;
|
|
||||||
desc.sample_bits = 4;
|
|
||||||
break;
|
|
||||||
case 1:
|
|
||||||
desc.palette_entries = 256;
|
|
||||||
desc.sample_bits = 8;
|
|
||||||
break;
|
|
||||||
case 2:
|
|
||||||
desc.palette_entries = 0;
|
|
||||||
desc.sample_bits = 16;
|
|
||||||
break;
|
|
||||||
case 3:
|
|
||||||
desc.palette_entries = 0;
|
|
||||||
desc.sample_bits = 32;
|
|
||||||
break;
|
|
||||||
case 4:
|
|
||||||
desc.palette_entries = 0;
|
|
||||||
desc.sample_bits = 4;
|
|
||||||
break;
|
|
||||||
case 5:
|
|
||||||
desc.palette_entries = 0;
|
|
||||||
desc.sample_bits = 8;
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
return desc;
|
|
||||||
}
|
|
@ -1,85 +0,0 @@
|
|||||||
#ifndef RS_IMAGES_H_
|
|
||||||
#define RS_IMAGES_H_
|
|
||||||
|
|
||||||
#include <stdio.h>
|
|
||||||
#include <stdlib.h>
|
|
||||||
#include <string.h>
|
|
||||||
//#include "options.h"
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief Constant contain the number of channel inside a PIXEL definition.
|
|
||||||
*/
|
|
||||||
#define PIXEL_MEMBERS_NBR 4
|
|
||||||
|
|
||||||
|
|
||||||
/////////////////////////////
|
|
||||||
///// Define new types //////
|
|
||||||
/////////////////////////////
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief RGBA pixel structure, used to store datas for implementation inside PNG files.
|
|
||||||
*/
|
|
||||||
typedef struct PixelRGBA {
|
|
||||||
unsigned char _red;
|
|
||||||
unsigned char _green;
|
|
||||||
unsigned char _blue;
|
|
||||||
unsigned char _alpha;
|
|
||||||
}PIXEL_A;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief RGB pixel structure, used to store datas for implementation inside PNG files, optimised version without alpha channel support.
|
|
||||||
*/
|
|
||||||
typedef struct PixelRGB {
|
|
||||||
unsigned char _red;
|
|
||||||
unsigned char _green;
|
|
||||||
unsigned char _blue;
|
|
||||||
}PIXEL;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief Image definition from Rogue Squadron HMT files
|
|
||||||
*/
|
|
||||||
typedef struct RSImage {
|
|
||||||
int data_size; /**< Image bytes size */
|
|
||||||
int width, height;
|
|
||||||
unsigned char type_; /**< Image type (0 = RBG/4bits per pixel, 1 = RBG/8bpp, 3 = RGBA/32bpp , 4 = grayscale/4bpp, 5 = grayscale/8bpp */
|
|
||||||
unsigned char sampleBits; /**< Bits per samble */
|
|
||||||
int paletteEntries;
|
|
||||||
PIXEL_A alpha_color;
|
|
||||||
PIXEL_A *pixels; /**< Image pixels list, managed like an array and declared as a pointer */
|
|
||||||
unsigned char *samples; /**< Image samples list managed like an array and declared as a pointer */
|
|
||||||
PIXEL palette[256]; /**< Image palette definition */ //TODO: Create union struct type instead
|
|
||||||
}RS_IMAGE;
|
|
||||||
|
|
||||||
typedef struct RSImage_desc {
|
|
||||||
int palette_entries;
|
|
||||||
int sample_bits;
|
|
||||||
}RS_IMAGE_DESC;
|
|
||||||
|
|
||||||
|
|
||||||
/////////////////////////////
|
|
||||||
///// Declare functions /////
|
|
||||||
/////////////////////////////
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief Conversion table for image type using RS_IMAGE_DESC.
|
|
||||||
* Return RS_IMAGE_DESC by providing image type as int\n
|
|
||||||
*
|
|
||||||
* Detailed conversion:\n\n
|
|
||||||
* Type 0 -> Palette entries: 16 ; Sample bits: 4\n
|
|
||||||
* Type 1 -> Palette entries: 256 ; Sample bits: 8\n
|
|
||||||
* Type 2 -> Palette entries: 0 ; Sample bits: 16\n
|
|
||||||
* Type 3 -> Palette entries: 0 ; Sample bits: 32\n
|
|
||||||
* Type 4 -> Palette entries: 0 ; Sample bits: 4\n
|
|
||||||
* Type 5 -> Palette entries: 0 ; Sample bits: 8\n
|
|
||||||
*/
|
|
||||||
RS_IMAGE_DESC getImageDescFromType(unsigned char type); //TODO: Optimise function
|
|
||||||
|
|
||||||
int isTransparentColor(PIXEL_A *testColor, PIXEL_A *transp_color);
|
|
||||||
void convert4bitsGreyTo32bitsRGBA(unsigned char *samples_tab, PIXEL_A *pixels_tab, int sampling, PIXEL_A *transp_color);
|
|
||||||
void convert4bitsTo32bitsRGBA(unsigned char *samples_tab, PIXEL_A *pixels_tab, int size, PIXEL *pal, PIXEL_A *transp_color);
|
|
||||||
void convert8bitsTo32bitsRGBA(unsigned char *samples_tab, PIXEL_A *pixels_tab, int size, PIXEL *pal, PIXEL_A *transp_color);
|
|
||||||
void useOddBytes(unsigned char *src, PIXEL_A *dst, int size);
|
|
||||||
void decodePixels(RS_IMAGE *img);
|
|
||||||
PIXEL_A *pixelAt(RS_IMAGE *img, int posX , int posY);
|
|
||||||
|
|
||||||
#endif
|
|
@ -1,130 +0,0 @@
|
|||||||
/*
|
|
||||||
================================================================================
|
|
||||||
Name : Texture-Extractor.c
|
|
||||||
Author : JackCarterSmith
|
|
||||||
License : GPL-v3.0
|
|
||||||
Description : DAT textures extractor to PNG format with enhanced function in C
|
|
||||||
================================================================================
|
|
||||||
*/
|
|
||||||
|
|
||||||
#include "Texture-Extractor.h"
|
|
||||||
|
|
||||||
|
|
||||||
extern int _options; // Global options settings variable
|
|
||||||
|
|
||||||
int main(int argc, char *argv[]) {
|
|
||||||
// Init buffer vars
|
|
||||||
HMT_FILE *hmt_fdatas = NULL;
|
|
||||||
int file_index;
|
|
||||||
|
|
||||||
printf("\n*** RogueSquadron Extractor (RSE) - TEXTURE module - v%s ***\n", VERSION);
|
|
||||||
|
|
||||||
// Check if filenames arguments exist
|
|
||||||
if (argc < 2) {
|
|
||||||
printf("\n[ERR] No input file/commands specified!\n");
|
|
||||||
dispHelp();
|
|
||||||
return EXIT_FAILURE; //TODO: implement own error codes system
|
|
||||||
}
|
|
||||||
_options = checkArgs(argv, argc); // Analyse program arguments
|
|
||||||
if (_options == -1) return EXIT_SUCCESS;
|
|
||||||
|
|
||||||
// Do the work
|
|
||||||
for (file_index=(_options >> 8) & 0xFF; file_index<argc; file_index++) { // Manage multiple inputs files
|
|
||||||
hmt_fdatas = extractDatasFromHMT(argv[file_index]);
|
|
||||||
if (hmt_fdatas == NULL) return EXIT_FAILURE;
|
|
||||||
if (exportTextures(hmt_fdatas, argv[file_index]) == EXIT_FAILURE) return EXIT_FAILURE;
|
|
||||||
purgeHMTFromMemory(hmt_fdatas); // Clean up memory (because I'm a good boy)
|
|
||||||
}
|
|
||||||
|
|
||||||
return EXIT_SUCCESS;
|
|
||||||
}
|
|
||||||
|
|
||||||
int checkArgs(char *args[], int arg_nbr) {
|
|
||||||
int _o = 0x0002; // Default options parameters
|
|
||||||
char test[256];
|
|
||||||
int i;
|
|
||||||
|
|
||||||
if (arg_nbr > 1) {
|
|
||||||
for (i=1; i<arg_nbr; i++) {
|
|
||||||
strcpy(test, args[i]);
|
|
||||||
if (args[i][0] != '-') break;
|
|
||||||
if (strcmp(args[i], "-h") == 0) {
|
|
||||||
dispHelp();
|
|
||||||
return -1;
|
|
||||||
} else if (strcmp(args[i], "-v") == 0) {
|
|
||||||
_o |= VERBOSE_ENABLED;
|
|
||||||
printf("[INFO] Verbose enabled.\n");
|
|
||||||
} else if (strcmp(args[i], "-no-subdir") == 0) {
|
|
||||||
_o &= ~OUTPUT_DIR;
|
|
||||||
printf("[INFO] Extract to current directory.\n");
|
|
||||||
} else {
|
|
||||||
printf("[INFO] Unknown option: %s\n", args[i]);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
_o = (i << 8) | (_o & 0x00FF);
|
|
||||||
}
|
|
||||||
|
|
||||||
return _o;
|
|
||||||
}
|
|
||||||
|
|
||||||
void createSubDir(char *dirName) {
|
|
||||||
if (dirName == NULL) return;
|
|
||||||
char _dir[50];
|
|
||||||
strcpy(_dir, dirName);
|
|
||||||
strcat(_dir, "-out");
|
|
||||||
|
|
||||||
#ifdef _WIN32
|
|
||||||
CreateDirectory(_dir, NULL);
|
|
||||||
#else
|
|
||||||
mkdir(_dir, 0755);
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
|
|
||||||
HMT_FILE *extractDatasFromHMT(char *hmt_filename) {
|
|
||||||
FILE *_hmtFile = NULL;
|
|
||||||
HMT_FILE *hmt_fdatas = NULL;
|
|
||||||
|
|
||||||
_hmtFile = fopen(hmt_filename, "rb");
|
|
||||||
if (_hmtFile != NULL) {
|
|
||||||
printf("\n[INFO] - Parsing file: %s\n", hmt_filename);
|
|
||||||
hmt_fdatas = parseHMTFile(_hmtFile);
|
|
||||||
if (hmt_fdatas == NULL) printf("[ERR] Failed to parse datas from %s\n", hmt_filename);
|
|
||||||
} else {
|
|
||||||
printf("[ERR] Input file %s not found!\n", hmt_filename);
|
|
||||||
}
|
|
||||||
fclose(_hmtFile);
|
|
||||||
|
|
||||||
return hmt_fdatas;
|
|
||||||
}
|
|
||||||
|
|
||||||
int exportTextures(HMT_FILE *hmt_f, char *filename) {
|
|
||||||
int i;
|
|
||||||
|
|
||||||
if(hmt_f->texture_count > 0) {
|
|
||||||
if (_options & OUTPUT_DIR) createSubDir(filename);
|
|
||||||
for (i=0; i<hmt_f->texture_count; i++) {
|
|
||||||
switch (hmt_f->textures_list[i].image.type_) {
|
|
||||||
case 0:
|
|
||||||
case 1:
|
|
||||||
case 3:
|
|
||||||
case 4:
|
|
||||||
case 5:
|
|
||||||
if (saveToPNG(&(hmt_f->textures_list[i].image), hmt_f->textures_list[i].name, filename)) return EXIT_FAILURE;
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
printf("[INFO] Image type %d not currently supported!\n", hmt_f->textures_list[i].image.type_);
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return EXIT_SUCCESS;
|
|
||||||
}
|
|
||||||
|
|
||||||
void dispHelp() {
|
|
||||||
printf("\n");
|
|
||||||
printf("Options:\n -h Print this message\n -v Activate verbose console output\n -no-subdir Extract textures inside current folder\n");
|
|
||||||
printf("\n");
|
|
||||||
printf("Usage: RSE-Texture_%s [options] <hmt files...>\n", VERSION);
|
|
||||||
printf("\n");
|
|
||||||
}
|
|
@ -1,26 +0,0 @@
|
|||||||
#ifndef TEXTURE_EXTRACTOR_H_
|
|
||||||
#define TEXTURE_EXTRACTOR_H_
|
|
||||||
|
|
||||||
#include <stdio.h>
|
|
||||||
#include <stdlib.h>
|
|
||||||
#include <string.h>
|
|
||||||
#if defined(_WIN32)
|
|
||||||
#include <windows.h>
|
|
||||||
#else
|
|
||||||
#include <sys/types.h>
|
|
||||||
#include <sys/stat.h>
|
|
||||||
#endif
|
|
||||||
#include "config.h"
|
|
||||||
#include "options.h"
|
|
||||||
#include "HMT_Parser.h"
|
|
||||||
#include "RS_images.h"
|
|
||||||
#include "Image_Exporter.h"
|
|
||||||
|
|
||||||
|
|
||||||
void createSubDir(char *dirName);
|
|
||||||
int checkArgs(char *args[], int arg_nbr);
|
|
||||||
HMT_FILE *extractDatasFromHMT(char* hmt_filename);
|
|
||||||
int exportTextures(HMT_FILE *hmt_f, char *filename);
|
|
||||||
void dispHelp();
|
|
||||||
|
|
||||||
#endif
|
|
@ -1 +0,0 @@
|
|||||||
#define VERSION "@PROJECT_VERSION@"
|
|
@ -1,9 +0,0 @@
|
|||||||
#ifndef OPTIONS_H_
|
|
||||||
#define OPTIONS_H_
|
|
||||||
|
|
||||||
#define VERBOSE_ENABLED 0x0001
|
|
||||||
#define OUTPUT_DIR 0x0002
|
|
||||||
|
|
||||||
int _options;
|
|
||||||
|
|
||||||
#endif
|
|
Loading…
x
Reference in New Issue
Block a user