Compare commits

..

36 Commits

Author SHA1 Message Date
19c544441b
Conan asspain
All checks were successful
JCS-Prod/RSE-Texture/pipeline/head This commit looks good
2024-09-22 15:39:05 +02:00
94d2cb6e56
Finalize package export
All checks were successful
JCS-Prod/RSE-Texture/pipeline/head This commit looks good
2024-09-22 13:01:07 +02:00
42de1f7dad
Jenkins script update
All checks were successful
JCS-Prod/RSE-Texture/pipeline/pr-master This commit looks good
JCS-Prod/RSE-Texture/pipeline/head This commit looks good
2024-09-22 12:35:28 +02:00
e03f3436a6
Final work on Conan v2 support 2024-09-22 11:41:42 +02:00
0c8282ab5d
Validated conan v2 migration
All checks were successful
JCS-Prod/RSE-Texture/pipeline/pr-master This commit looks good
JCS-Prod/RSE-Texture/pipeline/head This commit looks good
2024-05-19 10:08:10 +02:00
d302d7ebd5
Pre-migration of conan manager to v2 2023-09-29 16:03:50 +02:00
d6b94f8c79
Patched library garbage
All checks were successful
JCS-Prod/RSE-Texture/pipeline/pr-master This commit looks good
JCS-Prod/RSE-Texture/pipeline/head This commit looks good
2022-09-18 16:01:18 +02:00
49fa1278ad
DLL export patch
All checks were successful
JCS-Prod/RSE-Texture/pipeline/pr-master This commit looks good
JCS-Prod/RSE-Texture/pipeline/head This commit looks good
2022-09-14 19:59:20 +02:00
e2b5f4c841
Added conan package support
All checks were successful
JCS-Prod/RSE-Texture/pipeline/pr-master This commit looks good
JCS-Prod/RSE-Texture/pipeline/head This commit looks good
2022-09-14 19:15:32 +02:00
4e8da870d9
Reviewed material resolver
All checks were successful
JCS-Prod/RSE-Texture/pipeline/pr-master This commit looks good
JCS-Prod/RSE-Texture/pipeline/head This commit looks good
2022-09-04 13:19:23 +02:00
3ffc546e1e
Linked datas to export 2022-09-01 18:52:42 +02:00
6fa5719957
Prototype of dll material interface 2022-09-01 18:47:50 +02:00
7c0088f311
Fix memory leak in samples builder
All checks were successful
JCS-Prod/RSE-Texture/pipeline/pr-master This commit looks good
JCS-Prod/RSE-Texture/pipeline/head This commit looks good
2022-08-30 19:21:34 +02:00
56b4394f3b
Conan cross-build parameters fix
All checks were successful
JCS-Prod/RSE-Texture/pipeline/pr-master This commit looks good
JCS-Prod/RSE-Texture/pipeline/head This commit looks good
2022-08-30 11:19:41 +02:00
fd9f1a5979
Crosscompile patch
All checks were successful
JCS-Prod/RSE-Texture/pipeline/pr-master This commit looks good
JCS-Prod/RSE-Texture/pipeline/head This commit looks good
2022-08-29 22:46:31 +02:00
f5c817b384
Finish PNG export tool
Some checks failed
JCS-Prod/RSE-Texture/pipeline/pr-master There was a failure building this commit
2022-08-29 18:26:40 +02:00
3b1b358363
Imported old parser 2022-08-27 20:15:25 +02:00
151769a2d3
Begin new lib structure 2022-08-25 18:27:39 +02:00
8ce721fd9c
Added missing licenses
All checks were successful
JCS-Prod/RSE-Texture/pipeline/head This commit looks good
2022-07-14 20:13:16 +02:00
a6e16e7210
Update Jenkinsfile to allow fingerprint recording
All checks were successful
JCS-Prod/RSE-Texture/pipeline/head This commit looks good
2022-07-04 09:38:39 +02:00
2b7bc30bcc
Update 'README.md'
All checks were successful
JCS-Prod/RSE-Texture/pipeline/head This commit looks good
2022-04-10 14:40:23 +02:00
93442c9e4e
Update Jenkins to follow Conan support
All checks were successful
JCS-Prod/RSE-Texture/pipeline/head This commit looks good
2021-10-19 21:54:10 +02:00
7e955457ca
Merge branch 'develop' 2021-10-19 19:53:19 +02:00
2517c3b265
Updated Doxygen config and fix prefix lib glitch on MSVC 2021-10-19 19:53:08 +02:00
df4c637b94
Fix non recursive cmake building 2021-08-24 20:57:11 +02:00
5716962abb
Added Conan PM support 2021-08-22 21:28:30 +02:00
9f98830fce
Improved Jenkinsfile structure
All checks were successful
JCS-Prod/RSE-Texture/pipeline/head This commit looks good
2021-07-03 18:19:30 +02:00
84e0a0b904
Added jenkinsfile
All checks were successful
JCS-Prod/RSE-Texture/pipeline/head This commit looks good
2021-06-30 20:24:21 +02:00
58b120e7bf Cross-compiling prototype 2021-06-29 17:56:42 +02:00
4f665d159b
Update 'README.md' 2020-09-20 13:21:48 +00:00
74d32a20f4
Migrated hosting structure 2020-09-20 13:10:26 +00:00
82dddcb5dc
Detailed debug info, clear log 2020-09-10 16:29:34 +02:00
a536991daa
Adapt directory management on win platform 2020-09-10 13:27:04 +02:00
337fa39535
Implemented IO buffer control on win/unix system 2020-09-09 19:03:08 +02:00
a7e1fd65cf
Fixed extern variables def 2020-09-09 18:21:56 +02:00
854dba8a26
Added some gif to README and fixed bad version number 2020-09-09 03:12:46 +02:00
32 changed files with 4543 additions and 3310 deletions

4
.gitignore vendored
View File

@ -15,7 +15,8 @@
# Precompiled Headers
*.gch
*.pch
src/config.h
RSPTextureLib/src/config.h
RSETexture/src/config.h
# Libraries
*.lib
@ -74,3 +75,4 @@ install_manifest.txt
compile_commands.json
CTestTestfile.cmake
_deps
CMakeUserPresets.json

View File

@ -1,48 +1,94 @@
# CMakeLists.txt
# Written by JackCarterSmith, 2020
# This code is released under the RSE license.
cmake_minimum_required(VERSION 3.1)
cmake_policy(VERSION 3.1)
# define project
project(rse-texture VERSION 1.0.1 DESCRIPTION "RogueSquadron Extractor - Texture" LANGUAGES C)
set(CMAKE_BUILD_TYPE Release)
set(RSE_TEX_NAME RSE_Texture-${PROJECT_VERSION_MAJOR}.${PROJECT_VERSION_MINOR})
configure_file(${CMAKE_CURRENT_SOURCE_DIR}/src/config.h.in ${CMAKE_CURRENT_SOURCE_DIR}/src/config.h @ONLY)
include(CheckIncludeFile)
include(CheckCSourceCompiles)
# needed packages
find_package(ZLIB REQUIRED)
include_directories(${ZLIB_INCLUDE_DIR})
find_package(PNG REQUIRED)
include_directories(${PNG_INCLUDE_DIR})
# define src/headers files
FILE(GLOB RSE_TEX_SRCS src/*.c)
FILE(GLOB RSE_TEX_HRDS src/*.h)
SOURCE_GROUP("Source Files" FILES ${RSE_TEX_SRCS})
SOURCE_GROUP("Header Files" FILES ${RSE_TEX_HRDS})
# begin building RSE-Texture
#include_directories(${CMAKE_CURRENT_SOURCE_DIR})
add_executable(rse-texture ${RSE_TEX_SRCS} ${RSE_TEX_HRDS})
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
set_target_properties(rse-texture PROPERTIES PREFIX "lib")
set_target_properties(rse-texture PROPERTIES IMPORT_PREFIX "lib")
endif()
target_link_libraries(rse-texture ${ZLIB_LIBRARIES} ${PNG_LIBRARIES})
# install executable
install(TARGETS rse-texture
RUNTIME DESTINATION bin
)
# CMakeLists.txt
####################################################
# Written by JackCarterSmith, 2022
# This code is released under the RSE license.
####################################################
# CMake requirement and general configuration
cmake_minimum_required(VERSION 3.15)
cmake_policy(VERSION 3.15)
set(CMAKE_MODULE_PATH ${CMAKE_BINARY_DIR})
if(DEFINED ENV{MS_COMPATIBLE})
set(CMAKE_GNUtoMS ON) # Enable compatibility level to exported libraries
endif()
# Project definition
if(DEFINED ENV{CI}) # Jenkins CI integration mode
project(rse-texture VERSION $ENV{CI_VERSION}.$ENV{CI_BUILD_NUMBER} DESCRIPTION "RogueSquadron Extractor - Texture" LANGUAGES C)
set(RSE_TEXTURE_NAME $ENV{CI_OUTPUT_NAME})
else() # Standalone project mode, should not be used for release.
project(rse-texture VERSION 2.1.0 DESCRIPTION "RogueSquadron Extractor - Texture" LANGUAGES C)
set(RSE_TEXTURE_NAME RSETexture)
endif()
set(RSP_TEXTURE_LIB_NAME RSPTexture${PROJECT_VERSION_MAJOR}${PROJECT_VERSION_MINOR})
set(INSTALL_BIN_DIR "${CMAKE_INSTALL_PREFIX}/bin" CACHE PATH "Installation directory for executables")
set(INSTALL_LIB_DIR "${CMAKE_INSTALL_PREFIX}/lib" CACHE PATH "Installation directory for libraries")
set(INSTALL_INC_DIR "${CMAKE_INSTALL_PREFIX}/include" CACHE PATH "Installation directory for headers")
# Compilation option
option(RSPTEXTURE_SHARED "Build shared lib" ON)
option(RSPTEXTURE_STATIC "Build static lib" ON)
option(BUILD_TOOLS "Build lib tools" ON)
# Push compile infos to source
configure_file(${CMAKE_CURRENT_SOURCE_DIR}/config.h.in ${CMAKE_CURRENT_SOURCE_DIR}/RSPTextureLib/src/config.h @ONLY)
#configure_file(${CMAKE_CURRENT_SOURCE_DIR}/config.h.in ${CMAKE_CURRENT_SOURCE_DIR}/RSETexture/src/config.h @ONLY)
# The project is divided in two parts:
# - 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.
# - RSETexture is the standalone application of the library, take HMT file in argument and output PNG file.
# 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
View 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
View 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.

View File

@ -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.
:exclamation: **Master branch is ugly for now and should not be used, please take only released versions.** :exclamation:
[![Build Status](https://ci.jcsmith.fr/job/JCS-Prod/job/RSE-Texture/job/master/badge/icon)](https://ci.jcsmith.fr/job/JCS-Prod/job/RSE-Texture/job/master/)
## TEXTURE MODULE
@ -20,36 +20,63 @@ This module can do:
- Manage transparent textures,
- Fixed some errored RGB color encoding.
## TODO
- Discover all last unknowns fields, etc.
- Parse TEXT format for terrain module
### 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
- -h Print this message
- -v Activate verbose output
- -v,-vv Activate verbose/debug output mode respectively
- -no-subdir Extract textures directly inside current folder
### Dependencies
Necessary libs (provided only in windows release) for running and for compiling.
- zlib (1.2.11)
- libpng (1.6.37)
- [zlib](https://www.zlib.net/) (1.3.1)
- [libpng](http://www.libpng.org/pub/png/libpng.html) (1.6.43)
### Compiling
You can compile on both Windows (MinGW) or native Linux system thanks to CMake, you only need to adjust your dependencies on Windows.
zlib (zlib1g) and libpng16 distrib packages can be used on debian/ubuntu.
To compile, just clone and launch cmake:
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).
```shell
cmake .
make
make install
conan install . -of build -b missing -s build_type=Release -o tools=True -pr:b=default -pr:h=default
cmake --preset conan-release -G "Unix Makefiles"
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
View 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
View 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
View 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_ */

View 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;
}

View 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_ */

View 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()

View 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_ */

View 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_ */

View 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_ */

View 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, &params);
}
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, &params);
}
/*
* 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);
}

View 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];
}
}

View 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_ */

View 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_ */

View 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
View 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
View 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

View File

@ -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);
}

View File

@ -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

View File

@ -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;
}

View File

@ -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

View File

@ -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;
}

View File

@ -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

View File

@ -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");
}

View File

@ -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

View File

@ -1 +0,0 @@
#define VERSION "@PROJECT_VERSION@"

View File

@ -1,9 +0,0 @@
#ifndef OPTIONS_H_
#define OPTIONS_H_
#define VERBOSE_ENABLED 0x0001
#define OUTPUT_DIR 0x0002
int _options;
#endif