Initial commit for 2S2H

Co-authored-by: Louis <35883445+louist103@users.noreply.github.com>
Co-authored-by: Nicholas Estelami <NEstelami@users.noreply.github.com>
Co-authored-by: Random06457 <28494085+Random06457@users.noreply.github.com>
This commit is contained in:
Garrett Cox 2024-01-05 10:15:41 -06:00
parent ea8c7de686
commit 2332f63f5a
435 changed files with 24779 additions and 6151 deletions

23
.clang-format Normal file
View File

@ -0,0 +1,23 @@
IndentWidth: 4
Language: Cpp
UseTab: Never
ColumnLimit: 120
PointerAlignment: Left
BreakBeforeBraces: Attach
SpaceAfterCStyleCast: false
Cpp11BracedListStyle: false
IndentCaseLabels: true
BinPackArguments: true
BinPackParameters: true
AlignAfterOpenBracket: Align
AlignOperands: true
BreakBeforeTernaryOperators: true
BreakBeforeBinaryOperators: None
AllowShortBlocksOnASingleLine: true
AllowShortIfStatementsOnASingleLine: false
AllowShortLoopsOnASingleLine: false
AllowShortCaseLabelsOnASingleLine: false
AllowShortFunctionsOnASingleLine: false
AlignEscapedNewlines: Left
AlignTrailingComments: true
SortIncludes: false

9
.clang-tidy Normal file
View File

@ -0,0 +1,9 @@
Checks: '-*,readability-braces-around-statements,readability-inconsistent-declaration-parameter-name'
WarningsAsErrors: ''
HeaderFilterRegex: '(src|include)\/.*\.h$'
FormatStyle: 'file'
CheckOptions:
# Require argument names to match exactly (instead of allowing a name to be a prefix/suffix of another)
# Note: 'true' is expected by clang-tidy 12+ but '1' is used for compatibility with older versions
- key: readability-inconsistent-declaration-parameter-name.Strict
value: 1

2
.gitattributes vendored Normal file
View File

@ -0,0 +1,2 @@
# Auto detect text files and perform LF normalization
* text=auto

56
.gitignore vendored Normal file
View File

@ -0,0 +1,56 @@
*.otr
.vscode
*.swp
logs
*.nix
shipofharkinian.json
.envrc
imgui.ini
mm/libultraship/extern/Debug/ImGui.lib
mm/libultraship/extern/Debug/StrHash64.lib
mm/libultraship/extern/Debug/tinyxml2.lib
mm/libultraship/extern/ImGui.dir/Debug/ImGui.lib.recipe
mm/libultraship/extern/ImGui.dir/Debug/ImGui.tlog/CL.command.1.tlog
mm/libultraship/extern/ImGui.dir/Debug/ImGui.tlog/CL.read.1.tlog
mm/libultraship/extern/ImGui.dir/Debug/ImGui.tlog/CL.write.1.tlog
mm/libultraship/extern/ImGui.dir/Debug/ImGui.tlog/CustomBuild.command.1.tlog
mm/libultraship/extern/ImGui.dir/Debug/ImGui.tlog/CustomBuild.read.1.tlog
mm/libultraship/extern/ImGui.dir/Debug/ImGui.tlog/CustomBuild.write.1.tlog
mm/libultraship/extern/ImGui.dir/Debug/ImGui.tlog/ImGui.lastbuildstate
mm/libultraship/extern/ImGui.dir/Debug/ImGui.tlog/Lib-link.read.1.tlog
mm/libultraship/extern/StrHash64.dir/Debug/StrHash64.tlog/CL.command.1.tlog
mm/libultraship/extern/StrHash64.dir/Debug/StrHash64.tlog/CL.read.1.tlog
mm/libultraship/extern/StrHash64.dir/Debug/StrHash64.tlog/CL.write.1.tlog
mm/libultraship/extern/StrHash64.dir/Debug/StrHash64.tlog/CustomBuild.command.1.tlog
mm/libultraship/extern/StrHash64.dir/Debug/StrHash64.tlog/CustomBuild.read.1.tlog
mm/libultraship/extern/StrHash64.dir/Debug/StrHash64.tlog/CustomBuild.write.1.tlog
mm/libultraship/extern/StrHash64.dir/Debug/StrHash64.tlog/Lib-link.read.1.tlog
mm/libultraship/extern/StrHash64.dir/Debug/StrHash64.tlog/Lib-link.write.1.tlog
mm/libultraship/extern/StrHash64.dir/Debug/StrHash64.tlog/Lib.command.1.tlog
/buildmm
/Debug/libultraship.lib
/Debug
/build*
/Release
.vs/*

9
.gitmodules vendored Normal file
View File

@ -0,0 +1,9 @@
[submodule "libultraship"]
path = libultraship
url = git@github.com:louist103/libultraship.git
[submodule "OTRExporter"]
path = OTRExporter
url = git@github.com:louist103/OTRExporter.git
[submodule "ZAPDTR"]
path = ZAPDTR
url = git@github.com:louist103/ZAPDTR.git

65
CMake/Default.cmake Normal file
View File

@ -0,0 +1,65 @@
################################################################################
# Command for variable_watch. This command issues error message, if a variable
# is changed. If variable PROPERTY_READER_GUARD_DISABLED is TRUE nothing happens
# variable_watch(<variable> property_reader_guard)
################################################################################
function(property_reader_guard VARIABLE ACCESS VALUE CURRENT_LIST_FILE STACK)
if("${PROPERTY_READER_GUARD_DISABLED}")
return()
endif()
if("${ACCESS}" STREQUAL "MODIFIED_ACCESS")
message(FATAL_ERROR
" Variable ${VARIABLE} is not supposed to be changed.\n"
" It is used only for reading target property ${VARIABLE}.\n"
" Use\n"
" set_target_properties(\"<target>\" PROPERTIES \"${VARIABLE}\" \"<value>\")\n"
" or\n"
" set_target_properties(\"<target>\" PROPERTIES \"${VARIABLE}_<CONFIG>\" \"<value>\")\n"
" instead.\n")
endif()
endfunction()
################################################################################
# Create variable <name> with generator expression that expands to value of
# target property <name>_<CONFIG>. If property is empty or not set then property
# <name> is used instead. Variable <name> has watcher property_reader_guard that
# doesn't allow to edit it.
# create_property_reader(<name>)
# Input:
# name - Name of watched property and output variable
################################################################################
function(create_property_reader NAME)
set(PROPERTY_READER_GUARD_DISABLED TRUE)
set(CONFIG_VALUE "$<TARGET_GENEX_EVAL:${PROPS_TARGET},$<TARGET_PROPERTY:${PROPS_TARGET},${NAME}_$<UPPER_CASE:$<CONFIG>>>>")
set(IS_CONFIG_VALUE_EMPTY "$<STREQUAL:${CONFIG_VALUE},>")
set(GENERAL_VALUE "$<TARGET_GENEX_EVAL:${PROPS_TARGET},$<TARGET_PROPERTY:${PROPS_TARGET},${NAME}>>")
set("${NAME}" "$<IF:${IS_CONFIG_VALUE_EMPTY},${GENERAL_VALUE},${CONFIG_VALUE}>" PARENT_SCOPE)
variable_watch("${NAME}" property_reader_guard)
endfunction()
################################################################################
# Set property $<name>_${PROPS_CONFIG_U} of ${PROPS_TARGET} to <value>
# set_config_specific_property(<name> <value>)
# Input:
# name - Prefix of property name
# value - New value
################################################################################
function(set_config_specific_property NAME VALUE)
set_target_properties("${PROPS_TARGET}" PROPERTIES "${NAME}_${PROPS_CONFIG_U}" "${VALUE}")
endfunction()
################################################################################
create_property_reader("TARGET_NAME")
create_property_reader("OUTPUT_DIRECTORY")
set_config_specific_property("TARGET_NAME" "${PROPS_TARGET}")
set_config_specific_property("OUTPUT_NAME" "${TARGET_NAME}")
set_config_specific_property("ARCHIVE_OUTPUT_NAME" "${TARGET_NAME}")
set_config_specific_property("LIBRARY_OUTPUT_NAME" "${TARGET_NAME}")
set_config_specific_property("RUNTIME_OUTPUT_NAME" "${TARGET_NAME}")
set_config_specific_property("ARCHIVE_OUTPUT_DIRECTORY" "${OUTPUT_DIRECTORY}")
set_config_specific_property("LIBRARY_OUTPUT_DIRECTORY" "${OUTPUT_DIRECTORY}")
set_config_specific_property("RUNTIME_OUTPUT_DIRECTORY" "${OUTPUT_DIRECTORY}")

12
CMake/DefaultCXX.cmake Normal file
View File

@ -0,0 +1,12 @@
include("${CMAKE_CURRENT_LIST_DIR}/Default.cmake")
set_config_specific_property("OUTPUT_DIRECTORY" "${CMAKE_SOURCE_DIR}$<$<NOT:$<STREQUAL:${CMAKE_VS_PLATFORM_NAME},Win32>>:/${CMAKE_VS_PLATFORM_NAME}>/${PROPS_CONFIG}")
if(MSVC)
create_property_reader("DEFAULT_CXX_EXCEPTION_HANDLING")
create_property_reader("DEFAULT_CXX_DEBUG_INFORMATION_FORMAT")
set_target_properties("${PROPS_TARGET}" PROPERTIES MSVC_RUNTIME_LIBRARY "MultiThreaded$<$<CONFIG:Debug>:Debug>DLL")
set_config_specific_property("DEFAULT_CXX_EXCEPTION_HANDLING" "/EHsc")
set_config_specific_property("DEFAULT_CXX_DEBUG_INFORMATION_FORMAT" "/Zi")
endif()

30
CMake/Packaging-2.cmake Normal file
View File

@ -0,0 +1,30 @@
set(CPACK_ARCHIVE_COMPONENT_INSTALL ON)
set(CPACK_COMPONENT_INCLUDE_TOPLEVEL_DIRECTORY 0)
set(CPACK_COMPONENTS_ALL "ship" "extractor" "appimage")
if (NOT CPACK_GENERATOR STREQUAL "External")
list(REMOVE_ITEM CPACK_COMPONENTS_ALL "appimage")
endif()
if (CPACK_GENERATOR MATCHES "DEB|RPM")
# https://unix.stackexchange.com/a/11552/254512
set(CPACK_PACKAGING_INSTALL_PREFIX "/opt/ship/bin")#/${CMAKE_PROJECT_VERSION}")
set(CPACK_COMPONENT_INCLUDE_TOPLEVEL_DIRECTORY 0)
elseif (CPACK_GENERATOR MATCHES "ZIP")
set(CPACK_PACKAGING_INSTALL_PREFIX "")
endif()
if (CPACK_GENERATOR MATCHES "External")
set(CPACK_ARCHIVE_COMPONENT_INSTALL ON)
SET(CPACK_MONOLITHIC_INSTALL 1)
set(CPACK_PACKAGING_INSTALL_PREFIX "/usr/bin")
endif()
if (CPACK_GENERATOR MATCHES "Bundle")
set(CPACK_BUNDLE_NAME "soh")
set(CPACK_BUNDLE_PLIST "macosx/Info.plist")
set(CPACK_BUNDLE_ICON "macosx/soh.icns")
set(CPACK_BUNDLE_STARTUP_COMMAND "../soh/macosx/soh-macos.sh")
set(CPACK_BUNDLE_APPLE_CERT_APP "-")
endif()

90
CMake/Packaging.cmake Normal file
View File

@ -0,0 +1,90 @@
# these are cache variables, so they could be overwritten with -D,
set(CPACK_PACKAGE_NAME "${PROJECT_NAME}"
CACHE STRING "The resulting package name"
)
set(CPACK_PACKAGE_DESCRIPTION_SUMMARY "Simple C++ application"
CACHE STRING "Package description for the package metadata"
)
set(CPACK_PACKAGE_VENDOR "Some Company")
set(CPACK_VERBATIM_VARIABLES YES)
set(CPACK_PACKAGE_INSTALL_DIRECTORY ${CPACK_PACKAGE_NAME})
SET(CPACK_OUTPUT_FILE_PREFIX "${CMAKE_SOURCE_DIR}/_packages")
set(CPACK_PACKAGE_VERSION_MAJOR ${PROJECT_VERSION_MAJOR})
set(CPACK_PACKAGE_VERSION_MINOR ${PROJECT_VERSION_MINOR})
set(CPACK_PACKAGE_VERSION_PATCH ${PROJECT_VERSION_PATCH})
set(CPACK_PACKAGE_VERSION "${CPACK_PACKAGE_VERSION_MAJOR}.${CPACK_PACKAGE_VERSION_MINOR}.${CPACK_PACKAGE_VERSION_PATCH}")
set(CPACK_PACKAGE_CONTACT "YOUR@E-MAIL.net")
set(CPACK_DEBIAN_PACKAGE_MAINTAINER "YOUR NAME")
#set(CPACK_RESOURCE_FILE_LICENSE "${CMAKE_CURRENT_SOURCE_DIR}/LICENSE")
set(CPACK_RESOURCE_FILE_README "${CMAKE_SOURCE_DIR}/README.md")
if (CMAKE_SYSTEM_NAME STREQUAL "Linux")
set(CPACK_SYSTEM_NAME ${LSB_RELEASE_CODENAME_SHORT})
# package name for deb
# if set, then instead of some-application-0.9.2-Linux.deb
# you'll get some-application_0.9.2_amd64.deb (note the underscores too)
#set(CPACK_DEBIAN_FILE_NAME DEB-DEFAULT)
execute_process(COMMAND dpkg --print-architecture OUTPUT_VARIABLE ARCHITECTURE OUTPUT_STRIP_TRAILING_WHITESPACE)
set( CPACK_DEBIAN_FILE_NAME ${CPACK_PACKAGE_NAME}-${CPACK_PACKAGE_VERSION}-${CPACK_SYSTEM_NAME}-${ARCHITECTURE}.deb )
# if you want every group to have its own package,
# although the same happens if this is not sent (so it defaults to ONE_PER_GROUP)
# and CPACK_DEB_COMPONENT_INSTALL is set to YES
set(CPACK_COMPONENTS_GROUPING ALL_COMPONENTS_IN_ONE)#ONE_PER_GROUP)
# without this you won't be able to pack only specified component
set(CPACK_DEB_COMPONENT_INSTALL YES)
set(CPACK_EXTERNAL_ENABLE_STAGING YES)
set(CPACK_EXTERNAL_PACKAGE_SCRIPT "${PROJECT_BINARY_DIR}/appimage-generate.cmake")
file(GENERATE
OUTPUT "${PROJECT_BINARY_DIR}/appimage-generate.cmake"
CONTENT [[
include(CMakePrintHelpers)
cmake_print_variables(CPACK_TEMPORARY_DIRECTORY)
cmake_print_variables(CPACK_TOPLEVEL_DIRECTORY)
cmake_print_variables(CPACK_PACKAGE_DIRECTORY)
cmake_print_variables(CPACK_PACKAGE_FILE_NAME)
find_program(LINUXDEPLOY_EXECUTABLE
NAMES linuxdeploy linuxdeploy-x86_64.AppImage
PATHS ${CPACK_PACKAGE_DIRECTORY}/linuxdeploy)
if (NOT LINUXDEPLOY_EXECUTABLE)
message(STATUS "Downloading linuxdeploy")
set(LINUXDEPLOY_EXECUTABLE ${CPACK_PACKAGE_DIRECTORY}/linuxdeploy/linuxdeploy)
file(DOWNLOAD
https://github.com/linuxdeploy/linuxdeploy/releases/download/continuous/linuxdeploy-x86_64.AppImage
${LINUXDEPLOY_EXECUTABLE}
INACTIVITY_TIMEOUT 10
LOG ${CPACK_PACKAGE_DIRECTORY}/linuxdeploy/download.log
STATUS LINUXDEPLOY_DOWNLOAD)
execute_process(COMMAND chmod +x ${LINUXDEPLOY_EXECUTABLE} COMMAND_ECHO STDOUT)
endif()
execute_process(
COMMAND
${CMAKE_COMMAND} -E env
OUTPUT=${CPACK_PACKAGE_FILE_NAME}.appimage
VERSION=$<IF:$<BOOL:${CPACK_PACKAGE_VERSION}>,${CPACK_PACKAGE_VERSION},0.1.0>
${LINUXDEPLOY_EXECUTABLE}
--appimage-extract-and-run
--appdir=${CPACK_TEMPORARY_DIRECTORY}
--executable=$<TARGET_FILE:soh>
$<$<BOOL:$<TARGET_PROPERTY:soh,APPIMAGE_DESKTOP_FILE>>:--desktop-file=$<TARGET_PROPERTY:soh,APPIMAGE_DESKTOP_FILE>>
$<$<BOOL:$<TARGET_PROPERTY:soh,APPIMAGE_ICON_FILE>>:--icon-file=$<TARGET_PROPERTY:soh,APPIMAGE_ICON_FILE>>
--output=appimage
# --verbosity=2
)
]])
endif()
include(CPack)

248
CMake/Utils.cmake Normal file
View File

@ -0,0 +1,248 @@
# utils file for projects came from visual studio solution with cmake-converter.
################################################################################
# Wrap each token of the command with condition
################################################################################
cmake_policy(PUSH)
cmake_policy(SET CMP0054 NEW)
macro(prepare_commands)
unset(TOKEN_ROLE)
unset(COMMANDS)
foreach(TOKEN ${ARG_COMMANDS})
if("${TOKEN}" STREQUAL "COMMAND")
set(TOKEN_ROLE "KEYWORD")
elseif("${TOKEN_ROLE}" STREQUAL "KEYWORD")
set(TOKEN_ROLE "CONDITION")
elseif("${TOKEN_ROLE}" STREQUAL "CONDITION")
set(TOKEN_ROLE "COMMAND")
elseif("${TOKEN_ROLE}" STREQUAL "COMMAND")
set(TOKEN_ROLE "ARG")
endif()
if("${TOKEN_ROLE}" STREQUAL "KEYWORD")
list(APPEND COMMANDS "${TOKEN}")
elseif("${TOKEN_ROLE}" STREQUAL "CONDITION")
set(CONDITION ${TOKEN})
elseif("${TOKEN_ROLE}" STREQUAL "COMMAND")
list(APPEND COMMANDS "$<$<NOT:${CONDITION}>:${DUMMY}>$<${CONDITION}:${TOKEN}>")
elseif("${TOKEN_ROLE}" STREQUAL "ARG")
list(APPEND COMMANDS "$<${CONDITION}:${TOKEN}>")
endif()
endforeach()
endmacro()
cmake_policy(POP)
################################################################################
# Transform all the tokens to absolute paths
################################################################################
macro(prepare_output)
unset(OUTPUT)
foreach(TOKEN ${ARG_OUTPUT})
if(IS_ABSOLUTE ${TOKEN})
list(APPEND OUTPUT "${TOKEN}")
else()
list(APPEND OUTPUT "${CMAKE_CURRENT_SOURCE_DIR}/${TOKEN}")
endif()
endforeach()
endmacro()
################################################################################
# Parse add_custom_command_if args.
#
# Input:
# PRE_BUILD - Pre build event option
# PRE_LINK - Pre link event option
# POST_BUILD - Post build event option
# TARGET - Target
# OUTPUT - List of output files
# DEPENDS - List of files on which the command depends
# COMMANDS - List of commands(COMMAND condition1 commannd1 args1 COMMAND
# condition2 commannd2 args2 ...)
# Output:
# OUTPUT - Output files
# DEPENDS - Files on which the command depends
# COMMENT - Comment
# PRE_BUILD - TRUE/FALSE
# PRE_LINK - TRUE/FALSE
# POST_BUILD - TRUE/FALSE
# TARGET - Target name
# COMMANDS - Prepared commands(every token is wrapped in CONDITION)
# NAME - Unique name for custom target
# STEP - PRE_BUILD/PRE_LINK/POST_BUILD
################################################################################
function(add_custom_command_if_parse_arguments)
cmake_parse_arguments("ARG" "PRE_BUILD;PRE_LINK;POST_BUILD" "TARGET;COMMENT" "DEPENDS;OUTPUT;COMMANDS" ${ARGN})
if(WIN32)
set(DUMMY "cd.")
elseif(UNIX)
set(DUMMY "true")
endif()
prepare_commands()
prepare_output()
set(DEPENDS "${ARG_DEPENDS}")
set(COMMENT "${ARG_COMMENT}")
set(PRE_BUILD "${ARG_PRE_BUILD}")
set(PRE_LINK "${ARG_PRE_LINK}")
set(POST_BUILD "${ARG_POST_BUILD}")
set(TARGET "${ARG_TARGET}")
if(PRE_BUILD)
set(STEP "PRE_BUILD")
elseif(PRE_LINK)
set(STEP "PRE_LINK")
elseif(POST_BUILD)
set(STEP "POST_BUILD")
endif()
set(NAME "${TARGET}_${STEP}")
set(OUTPUT "${OUTPUT}" PARENT_SCOPE)
set(DEPENDS "${DEPENDS}" PARENT_SCOPE)
set(COMMENT "${COMMENT}" PARENT_SCOPE)
set(PRE_BUILD "${PRE_BUILD}" PARENT_SCOPE)
set(PRE_LINK "${PRE_LINK}" PARENT_SCOPE)
set(POST_BUILD "${POST_BUILD}" PARENT_SCOPE)
set(TARGET "${TARGET}" PARENT_SCOPE)
set(COMMANDS "${COMMANDS}" PARENT_SCOPE)
set(STEP "${STEP}" PARENT_SCOPE)
set(NAME "${NAME}" PARENT_SCOPE)
endfunction()
################################################################################
# Add conditional custom command
#
# Generating Files
# The first signature is for adding a custom command to produce an output:
# add_custom_command_if(
# <OUTPUT output1 [output2 ...]>
# <COMMANDS>
# <COMMAND condition command1 [args1...]>
# [COMMAND condition command2 [args2...]]
# [DEPENDS [depends...]]
# [COMMENT comment]
#
# Build Events
# add_custom_command_if(
# <TARGET target>
# <PRE_BUILD | PRE_LINK | POST_BUILD>
# <COMMAND condition command1 [args1...]>
# [COMMAND condition command2 [args2...]]
# [COMMENT comment]
#
# Input:
# output - Output files the command is expected to produce
# condition - Generator expression for wrapping the command
# command - Command-line(s) to execute at build time.
# args - Command`s args
# depends - Files on which the command depends
# comment - Display the given message before the commands are executed at
# build time.
# PRE_BUILD - Run before any other rules are executed within the target
# PRE_LINK - Run after sources have been compiled but before linking the
# binary
# POST_BUILD - Run after all other rules within the target have been
# executed
################################################################################
function(add_custom_command_if)
add_custom_command_if_parse_arguments(${ARGN})
if(OUTPUT AND TARGET)
message(FATAL_ERROR "Wrong syntax. A TARGET and OUTPUT can not both be specified.")
endif()
if(OUTPUT)
add_custom_command(OUTPUT ${OUTPUT}
${COMMANDS}
DEPENDS ${DEPENDS}
WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}
COMMENT ${COMMENT})
elseif(TARGET)
if(PRE_BUILD AND NOT ${CMAKE_GENERATOR} MATCHES "Visual Studio")
add_custom_target(
${NAME}
${COMMANDS}
WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}
COMMENT ${COMMENT})
add_dependencies(${TARGET} ${NAME})
else()
add_custom_command(
TARGET ${TARGET}
${STEP}
${COMMANDS}
WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}
COMMENT ${COMMENT})
endif()
else()
message(FATAL_ERROR "Wrong syntax. A TARGET or OUTPUT must be specified.")
endif()
endfunction()
################################################################################
# Use props file for a target and configs
# use_props(<target> <configs...> <props_file>)
# Inside <props_file> there are following variables:
# PROPS_TARGET - <target>
# PROPS_CONFIG - One of <configs...>
# PROPS_CONFIG_U - Uppercase PROPS_CONFIG
# Input:
# target - Target to apply props file
# configs - Build configurations to apply props file
# props_file - CMake script
################################################################################
macro(use_props TARGET CONFIGS PROPS_FILE)
set(PROPS_TARGET "${TARGET}")
foreach(PROPS_CONFIG ${CONFIGS})
string(TOUPPER "${PROPS_CONFIG}" PROPS_CONFIG_U)
get_filename_component(ABSOLUTE_PROPS_FILE "${PROPS_FILE}" ABSOLUTE BASE_DIR "${CMAKE_CURRENT_LIST_DIR}")
if(EXISTS "${ABSOLUTE_PROPS_FILE}")
include("${ABSOLUTE_PROPS_FILE}")
else()
message(WARNING "Corresponding cmake file from props \"${ABSOLUTE_PROPS_FILE}\" doesn't exist")
endif()
endforeach()
endmacro()
################################################################################
# Add compile options to source file
# source_file_compile_options(<source_file> [compile_options...])
# Input:
# source_file - Source file
# compile_options - Options to add to COMPILE_FLAGS property
################################################################################
function(source_file_compile_options SOURCE_FILE)
if("${ARGC}" LESS_EQUAL "1")
return()
endif()
get_source_file_property(COMPILE_OPTIONS "${SOURCE_FILE}" COMPILE_OPTIONS)
if(COMPILE_OPTIONS)
list(APPEND COMPILE_OPTIONS ${ARGN})
else()
set(COMPILE_OPTIONS "${ARGN}")
endif()
set_source_files_properties("${SOURCE_FILE}" PROPERTIES COMPILE_OPTIONS "${COMPILE_OPTIONS}")
endfunction()
################################################################################
# Default properties of visual studio projects
################################################################################
set(DEFAULT_CXX_PROPS "${CMAKE_CURRENT_LIST_DIR}/DefaultCXX.cmake")
function(get_linux_lsb_release_information)
find_program(LSB_RELEASE_EXEC lsb_release)
if(NOT LSB_RELEASE_EXEC)
message(FATAL_ERROR "Could not detect lsb_release executable, can not gather required information")
endif()
execute_process(COMMAND "${LSB_RELEASE_EXEC}" --short --id OUTPUT_VARIABLE LSB_RELEASE_ID_SHORT OUTPUT_STRIP_TRAILING_WHITESPACE)
execute_process(COMMAND "${LSB_RELEASE_EXEC}" --short --release OUTPUT_VARIABLE LSB_RELEASE_VERSION_SHORT OUTPUT_STRIP_TRAILING_WHITESPACE)
execute_process(COMMAND "${LSB_RELEASE_EXEC}" --short --codename OUTPUT_VARIABLE LSB_RELEASE_CODENAME_SHORT OUTPUT_STRIP_TRAILING_WHITESPACE)
set(LSB_RELEASE_ID_SHORT "${LSB_RELEASE_ID_SHORT}" PARENT_SCOPE)
set(LSB_RELEASE_VERSION_SHORT "${LSB_RELEASE_VERSION_SHORT}" PARENT_SCOPE)
set(LSB_RELEASE_CODENAME_SHORT "${LSB_RELEASE_CODENAME_SHORT}" PARENT_SCOPE)
endfunction()

191
CMake/automate-vcpkg.cmake Normal file
View File

@ -0,0 +1,191 @@
#------------------------------------------------------------------------------------------------------------
#
# Automate-VCPKG by Andre Taulien
# ===============================
#
# Project Repository: https://github.com/REGoth-project/Automate-VCPKG
# License ..........: MIT, see end of file.
#
# Based on: https://github.com/sutambe/cpptruths/blob/vcpkg_cmake_blog/cpp0x/vcpkg_test/CMakeLists.txt
#
#
# While [Vcpkg](https://github.com/microsoft/vcpkg) on it's own is awesome, it does add
# a little bit of complexity to getting a project to build. Even more if the one trying
# to compile your application is not too fond of the commandline. Additionally, CMake
# commands tend to get rather long with the toolchain path.
#
# To keep things simple for new users who just want to get the project to build, this
# script offers a solution.
#
# Lets assume your main `CMakelists.txt` looks something like this:
#
# cmake_minimum_required (VERSION 3.12.0)
# project (MyProject)
#
# add_executable(MyExecutable main.c)
#
# To integrate Vcpkg into that `CMakelists.txt`, simple put the following lines before the
# call to `project(MyProject)`:
#
# include(cmake/automate-vcpkg.cmake)
#
# vcpkg_bootstrap()
# vcpkg_install_packages(libsquish physfs)
#
# The call to `vcpkg_bootstrap()` will clone the official Vcpkg repository and bootstrap it.
# If it detected an existing environment variable defining a valid `VCPKG_ROOT`, it will
# update the existing installation of Vcpkg.
#
# Arguments to `vcpkg_install_packages()` are the packages you want to install using Vcpkg.
#
# If you want to keep the possibility for users to chose their own copy of Vcpkg, you can
# simply not run the code snippet mentioned above, something like this will work:
#
# option(SKIP_AUTOMATE_VCPKG "When ON, you will need to built the packages
# required by MyProject on your own or supply your own vcpkg toolchain.")
#
# if (NOT SKIP_AUTOMATE_VCPKG)
# include(cmake/automate-vcpkg.cmake)
#
# vcpkg_bootstrap()
# vcpkg_install_packages(libsquish physfs)
# endif()
#
# Then, the user has to supply the packages on their own, be it through Vcpkg or manually
# specifying their locations.
#------------------------------------------------------------------------------------------------------------
cmake_minimum_required (VERSION 3.12)
if(WIN32)
set(VCPKG_FALLBACK_ROOT ${CMAKE_CURRENT_BINARY_DIR}/vcpkg CACHE STRING "vcpkg configuration directory to use if vcpkg was not installed on the system before")
else()
set(VCPKG_FALLBACK_ROOT ${CMAKE_CURRENT_BINARY_DIR}/.vcpkg CACHE STRING "vcpkg configuration directory to use if vcpkg was not installed on the system before")
endif()
# On Windows, Vcpkg defaults to x86, even on x64 systems. If we're
# doing a 64-bit build, we need to fix that.
if (WIN32)
# Since the compiler checks haven't run yet, we need to figure
# out the value of CMAKE_SIZEOF_VOID_P ourselfs
include(CheckTypeSize)
enable_language(C)
check_type_size("void*" SIZEOF_VOID_P BUILTIN_TYPES_ONLY)
if (SIZEOF_VOID_P EQUAL 8)
message(STATUS "Using Vcpkg triplet 'x64-windows'")
set(VCPKG_TRIPLET x64-windows)
endif()
endif()
if(NOT DEFINED VCPKG_ROOT)
if(NOT DEFINED ENV{VCPKG_ROOT})
set(VCPKG_ROOT ${VCPKG_FALLBACK_ROOT})
else()
set(VCPKG_ROOT $ENV{VCPKG_ROOT})
endif()
endif()
# Installs a new copy of Vcpkg or updates an existing one
macro(vcpkg_bootstrap)
_install_or_update_vcpkg()
# Find out whether the user supplied their own VCPKG toolchain file
if(NOT DEFINED ${CMAKE_TOOLCHAIN_FILE})
# We know this wasn't set before so we need point the toolchain file to the newly found VCPKG_ROOT
set(CMAKE_TOOLCHAIN_FILE ${VCPKG_ROOT}/scripts/buildsystems/vcpkg.cmake CACHE STRING "")
# Just setting vcpkg.cmake as toolchain file does not seem to actually pull in the code
include(${VCPKG_ROOT}/scripts/buildsystems/vcpkg.cmake)
set(AUTOMATE_VCPKG_USE_SYSTEM_VCPKG OFF)
else()
# VCPKG_ROOT has been defined by the toolchain file already
set(AUTOMATE_VCPKG_USE_SYSTEM_VCPKG ON)
endif()
message(STATUS "Automate VCPKG status:")
message(STATUS " VCPKG_ROOT.....: ${VCPKG_ROOT}")
message(STATUS " VCPKG_EXEC.....: ${VCPKG_EXEC}")
message(STATUS " VCPKG_BOOTSTRAP: ${VCPKG_BOOTSTRAP}")
endmacro()
macro(_install_or_update_vcpkg)
if(NOT EXISTS ${VCPKG_ROOT})
message(STATUS "Cloning vcpkg in ${VCPKG_ROOT}")
execute_process(COMMAND git clone https://github.com/Microsoft/vcpkg.git ${VCPKG_ROOT} --depth 1)
# If a reproducible build is desired (and potentially old libraries are # ok), uncomment the
# following line and pin the vcpkg repository to a specific githash.
# execute_process(COMMAND git checkout 745a0aea597771a580d0b0f4886ea1e3a94dbca6 WORKING_DIRECTORY ${VCPKG_ROOT})
else()
# The following command has no effect if the vcpkg repository is in a detached head state.
message(STATUS "Auto-updating vcpkg in ${VCPKG_ROOT}")
execute_process(COMMAND git pull WORKING_DIRECTORY ${VCPKG_ROOT})
endif()
if(NOT EXISTS ${VCPKG_ROOT}/README.md)
message(FATAL_ERROR "***** FATAL ERROR: Could not clone vcpkg *****")
endif()
if(WIN32)
set(VCPKG_EXEC ${VCPKG_ROOT}/vcpkg.exe)
set(VCPKG_BOOTSTRAP ${VCPKG_ROOT}/bootstrap-vcpkg.bat)
else()
set(VCPKG_EXEC ${VCPKG_ROOT}/vcpkg)
set(VCPKG_BOOTSTRAP ${VCPKG_ROOT}/bootstrap-vcpkg.sh)
endif()
if(NOT EXISTS ${VCPKG_EXEC})
message("Bootstrapping vcpkg in ${VCPKG_ROOT}")
execute_process(COMMAND ${VCPKG_BOOTSTRAP} WORKING_DIRECTORY ${VCPKG_ROOT})
endif()
if(NOT EXISTS ${VCPKG_EXEC})
message(FATAL_ERROR "***** FATAL ERROR: Could not bootstrap vcpkg *****")
endif()
endmacro()
# Installs the list of packages given as parameters using Vcpkg
macro(vcpkg_install_packages)
# Need the given list to be space-separated
#string (REPLACE ";" " " PACKAGES_LIST_STR "${ARGN}")
message(STATUS "Installing/Updating the following vcpkg-packages: ${PACKAGES_LIST_STR}")
if (VCPKG_TRIPLET)
set(ENV{VCPKG_DEFAULT_TRIPLET} "${VCPKG_TRIPLET}")
endif()
execute_process(
COMMAND ${VCPKG_EXEC} install ${ARGN}
WORKING_DIRECTORY ${VCPKG_ROOT}
)
endmacro()
# MIT License
#
# Copyright (c) 2019 REGoth-project
#
# Permission is hereby granted, free of charge, to any person obtaining a copy
# of this software and associated documentation files (the "Software"), to deal
# in the Software without restriction, including without limitation the rights
# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
# copies of the Software, and to permit persons to whom the Software is
# furnished to do so, subject to the following conditions:
#
# The above copyright notice and this permission notice shall be included in all
# copies or substantial portions of the Software.
#
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
# SOFTWARE.

225
CMakeLists.txt Normal file
View File

@ -0,0 +1,225 @@
cmake_minimum_required(VERSION 3.16.0 FATAL_ERROR)
set(CMAKE_SYSTEM_VERSION 10.0 CACHE STRING "" FORCE)
set(CMAKE_CXX_STANDARD 20 CACHE STRING "The C++ standard to use")
set(CMAKE_OSX_DEPLOYMENT_TARGET "10.15" CACHE STRING "Minimum OS X deployment version")
project(2s2h VERSION 0.0.1 LANGUAGES C CXX)
set(PROJECT_BUILD_NAME "PRE ALPHA" CACHE STRING "")
set(PROJECT_TEAM "github.com/harbourmasters" CACHE STRING "")
set_property(DIRECTORY ${CMAKE_SOURCE_DIR} PROPERTY VS_STARTUP_PROJECT mm)
add_compile_options($<$<CXX_COMPILER_ID:MSVC>:/MP>)
add_compile_options($<$<CXX_COMPILER_ID:MSVC>:/utf-8>)
if (CMAKE_SYSTEM_NAME MATCHES "Windows|Linux")
if(NOT DEFINED BUILD_CROWD_CONTROL)
set(BUILD_CROWD_CONTROL OFF)
endif()
endif()
if (CMAKE_SYSTEM_NAME STREQUAL "Windows")
include(CMake/automate-vcpkg.cmake)
set(VCPKG_TRIPLET x86-windows-static)
set(VCPKG_TARGET_TRIPLET x86-windows-static)
vcpkg_bootstrap()
vcpkg_install_packages(zlib bzip2 libpng sdl2 sdl2-net glew glfw3)
endif()
################################################################################
# Set target arch type if empty. Visual studio solution generator provides it.
################################################################################
if (CMAKE_SYSTEM_NAME STREQUAL "Windows")
if(NOT CMAKE_VS_PLATFORM_NAME)
set(CMAKE_VS_PLATFORM_NAME "x64")
endif()
message("${CMAKE_VS_PLATFORM_NAME} architecture in use")
if(NOT ("${CMAKE_VS_PLATFORM_NAME}" STREQUAL "x64"
OR "${CMAKE_VS_PLATFORM_NAME}" STREQUAL "Win32"))
message(FATAL_ERROR "${CMAKE_VS_PLATFORM_NAME} arch is not supported!")
endif()
endif()
################################################################################
# Global configuration types
################################################################################
if (CMAKE_SYSTEM_NAME STREQUAL "NintendoSwitch")
set(CMAKE_C_FLAGS_DEBUG "-g -ffast-math -DDEBUG")
set(CMAKE_CXX_FLAGS_DEBUG "-g -ffast-math -DDEBUG")
set(CMAKE_C_FLAGS_RELEASE "-O3 -ffast-math -DNDEBUG")
set(CMAKE_CXX_FLAGS_RELEASE "-O3 -ffast-math -DNDEBUG")
else()
set(CMAKE_C_FLAGS_RELEASE "-O2 -DNDEBUG")
set(CMAKE_CXX_FLAGS_DEBUG "-fuse-ld=lld")
set(CMAKE_C_FLAGS_DEBUG "-g")
set(CMAKE_LINKER_FLAGS_DEBUG "-fuse-ld=lld")
set(CMAKE_CXX_FLAGS_RELEASE "-O2 -DNDEBUG")
set(CMAKE_OBJCXX_FLAGS_RELEASE "-O2 -DNDEBUG")
endif()
if(NOT CMAKE_BUILD_TYPE )
set(CMAKE_BUILD_TYPE "Debug" CACHE STRING "Choose the type of build." FORCE)
endif()
################################################################################
# Common utils
################################################################################
include(CMake/Utils.cmake)
if(CMAKE_SYSTEM_NAME MATCHES "Linux")
get_linux_lsb_release_information()
message(STATUS "Linux ${LSB_RELEASE_ID_SHORT} ${LSB_RELEASE_VERSION_SHORT} ${LSB_RELEASE_CODENAME_SHORT}")
else()
message(STATUS ${CMAKE_SYSTEM_NAME})
endif()
################################################################################
# Additional Global Settings(add specific info there)
################################################################################
include(CMake/GlobalSettingsInclude.cmake OPTIONAL)
################################################################################
# Use solution folders feature
################################################################################
set_property(GLOBAL PROPERTY USE_FOLDERS ON)
################################################################################
# Sub-projects
################################################################################
add_subdirectory(libultraship ${CMAKE_BINARY_DIR}/libultraship)
add_subdirectory(ZAPDTR/ZAPD ${CMAKE_BINARY_DIR}/ZAPD)
add_subdirectory(OTRExporter)
add_subdirectory(mm)
set_property(TARGET mm PROPERTY APPIMAGE_DESKTOP_FILE_TERMINAL YES)
set_property(TARGET mm PROPERTY APPIMAGE_DESKTOP_FILE "${CMAKE_SOURCE_DIR}/scripts/linux/appimage/soh.desktop")
set_property(TARGET mm PROPERTY APPIMAGE_ICON_FILE "${CMAKE_BINARY_DIR}/sohIcon.png")
#if("${CMAKE_SYSTEM_NAME}" STREQUAL "Linux")
#install(PROGRAMS "${CMAKE_SOURCE_DIR}/scripts/linux/appimage/soh.sh" DESTINATION . COMPONENT appimage)
#install(FILES "${CMAKE_SOURCE_DIR}/soh.otr" DESTINATION . COMPONENT ship)
#install(TARGETS ZAPD DESTINATION ./assets/extractor COMPONENT extractor)
#install(DIRECTORY "${CMAKE_SOURCE_DIR}/soh/assets/extractor/" DESTINATION ./assets/extractor COMPONENT extractor)
#install(DIRECTORY "${CMAKE_SOURCE_DIR}/soh/assets/xml/" DESTINATION ./assets/extractor/xmls COMPONENT extractor)
#install(DIRECTORY "${CMAKE_SOURCE_DIR}/OTRExporter/CFG/filelists/" DESTINATION ./assets/extractor/filelists COMPONENT extractor)
#install(FILES "${CMAKE_SOURCE_DIR}/OTRExporter/CFG/ActorList_OoTMqDbg.txt" DESTINATION ./assets/extractor/symbols COMPONENT extractor)
#install(FILES "${CMAKE_SOURCE_DIR}/OTRExporter/CFG/ObjectList_OoTMqDbg.txt" DESTINATION ./assets/extractor/symbols COMPONENT extractor)
#install(FILES "${CMAKE_SOURCE_DIR}/OTRExporter/CFG/SymbolMap_OoTMqDbg.txt" DESTINATION ./assets/extractor/symbols COMPONENT extractor)
#endif()
if ("${CMAKE_SYSTEM_NAME}" STREQUAL "Windows")
install(DIRECTORY "${CMAKE_SOURCE_DIR}/mm/assets/extractor/" DESTINATION ./assets/extractor COMPONENT 2s2h)
install(DIRECTORY "${CMAKE_SOURCE_DIR}/mm/assets/xml/" DESTINATION ./assets/extractor/xmls COMPONENT 2s2h)
install(DIRECTORY "${CMAKE_SOURCE_DIR}/OTRExporter/CFG/filelists/" DESTINATION ./assets/extractor/filelists COMPONENT 2s2h)
install(FILES "${CMAKE_SOURCE_DIR}/OTRExporter/CFG/ActorList_OoTMqDbg.txt" DESTINATION ./assets/extractor/symbols COMPONENT 2s2h)
install(FILES "${CMAKE_SOURCE_DIR}/OTRExporter/CFG/ObjectList_OoTMqDbg.txt" DESTINATION ./assets/extractor/symbols COMPONENT 2s2h)
install(FILES "${CMAKE_SOURCE_DIR}/OTRExporter/CFG/SymbolMap_OoTMqDbg.txt" DESTINATION ./assets/extractor/symbols COMPONENT 2s2h)
endif()
find_package(Python3 COMPONENTS Interpreter)
# Target to generate OTRs
add_custom_target(
ExtractAssets
# CMake versions prior to 3.17 do not have the rm command, use remove instead for older versions
COMMAND ${CMAKE_COMMAND} -E $<IF:$<VERSION_LESS:${CMAKE_VERSION},3.17>,remove,rm> -f oot.otr oot-mq.otr soh.otr
COMMAND ${Python3_EXECUTABLE} ${CMAKE_CURRENT_SOURCE_DIR}/OTRExporter/extract_assets.py -z "$<TARGET_FILE:ZAPD>" --non-interactive
COMMAND ${CMAKE_COMMAND} -DSYSTEM_NAME=${CMAKE_SYSTEM_NAME} -DTARGET_DIR="$<TARGET_FILE_DIR:ZAPD>" -DSOURCE_DIR=${CMAKE_CURRENT_SOURCE_DIR} -DBINARY_DIR=${CMAKE_BINARY_DIR} -P ${CMAKE_CURRENT_SOURCE_DIR}/copy-existing-otrs.cmake
WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}/OTRExporter
COMMENT "Running asset extraction..."
DEPENDS ZAPD
BYPRODUCTS mm.otr ${CMAKE_SOURCE_DIR}/mm.otr ${CMAKE_SOURCE_DIR}/soh.otr
)
# Target to generate headers
add_custom_target(
ExtractAssetHeaders
COMMAND ${Python3_EXECUTABLE} ${CMAKE_CURRENT_SOURCE_DIR}/OTRExporter/extract_assets.py -z "$<TARGET_FILE:ZAPD>" --non-interactive --gen-headers
WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}/OTRExporter
COMMENT "Generating asset headers..."
DEPENDS ZAPD
)
# Target to generate only soh.otr
add_custom_target(
GenerateSohOtr
# CMake versions prior to 3.17 do not have the rm command, use remove instead for older versions
COMMAND ${CMAKE_COMMAND} -E $<IF:$<VERSION_LESS:${CMAKE_VERSION},3.17>,remove,rm> -f soh.otr
COMMAND ${Python3_EXECUTABLE} ${CMAKE_CURRENT_SOURCE_DIR}/OTRExporter/extract_assets.py -z "$<TARGET_FILE:ZAPD>" --norom
COMMAND ${CMAKE_COMMAND} -DSYSTEM_NAME=${CMAKE_SYSTEM_NAME} -DTARGET_DIR="$<TARGET_FILE_DIR:ZAPD>" -DSOURCE_DIR=${CMAKE_CURRENT_SOURCE_DIR} -DBINARY_DIR=${CMAKE_BINARY_DIR} -DONLYSOHOTR=On -P ${CMAKE_CURRENT_SOURCE_DIR}/copy-existing-otrs.cmake
WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}/OTRExporter
COMMENT "Generating soh.otr..."
DEPENDS ZAPD
)
if(CMAKE_SYSTEM_NAME MATCHES "Linux")
find_package(ImageMagick COMPONENTS convert)
if (ImageMagick_FOUND)
execute_process (
COMMAND ${ImageMagick_convert_EXECUTABLE} mm/macosx/sohIcon.png -resize 512x512 ${CMAKE_BINARY_DIR}/sohIcon.png
OUTPUT_VARIABLE outVar
)
endif()
endif()
#if(CMAKE_SYSTEM_NAME MATCHES "Darwin")
#add_custom_target(CreateOSXIcons
# COMMAND mkdir -p ${CMAKE_BINARY_DIR}/macosx/soh.iconset
# COMMAND sips -z 16 16 soh/macosx/sohIcon.png --out ${CMAKE_BINARY_DIR}/macosx/soh.iconset/icon_16x16.png
# COMMAND sips -z 32 32 soh/macosx/sohIcon.png --out ${CMAKE_BINARY_DIR}/macosx/soh.iconset/icon_16x16@2x.png
# COMMAND sips -z 32 32 soh/macosx/sohIcon.png --out ${CMAKE_BINARY_DIR}/macosx/soh.iconset/icon_32x32.png
# COMMAND sips -z 64 64 soh/macosx/sohIcon.png --out ${CMAKE_BINARY_DIR}/macosx/soh.iconset/icon_32x32@2x.png
# COMMAND sips -z 128 128 soh/macosx/sohIcon.png --out ${CMAKE_BINARY_DIR}/macosx/soh.iconset/icon_128x128.png
# COMMAND sips -z 256 256 soh/macosx/sohIcon.png --out ${CMAKE_BINARY_DIR}/macosx/soh.iconset/icon_128x128@2x.png
# COMMAND sips -z 256 256 soh/macosx/sohIcon.png --out ${CMAKE_BINARY_DIR}/macosx/soh.iconset/icon_256x256.png
# COMMAND sips -z 512 512 soh/macosx/sohIcon.png --out ${CMAKE_BINARY_DIR}/macosx/soh.iconset/icon_256x256@2x.png
# COMMAND sips -z 512 512 soh/macosx/sohIcon.png --out ${CMAKE_BINARY_DIR}/macosx/soh.iconset/icon_512x512.png
# COMMAND cp soh/macosx/sohIcon.png ${CMAKE_BINARY_DIR}/macosx/soh.iconset/icon_512x512@2x.png
# COMMAND iconutil -c icns -o ${CMAKE_BINARY_DIR}/macosx/soh.icns ${CMAKE_BINARY_DIR}/macosx/soh.iconset
# WORKING_DIRECTORY ${CMAKE_SOURCE_DIR}
# COMMENT "Creating OSX icons ..."
# )
#add_dependencies(soh CreateOSXIcons)
install(TARGETS ZAPD DESTINATION ${CMAKE_BINARY_DIR}/assets/extractor)
set(PROGRAM_PERMISSIONS_EXECUTE OWNER_EXECUTE OWNER_WRITE OWNER_READ GROUP_EXECUTE GROUP_READ WORLD_EXECUTE WORLD_READ)
install(DIRECTORY "${CMAKE_SOURCE_DIR}/mm/assets/extractor/" DESTINATION ./assets/extractor)
install(DIRECTORY "${CMAKE_SOURCE_DIR}/mm/assets/xml/" DESTINATION ./assets/extractor/xmls)
install(DIRECTORY "${CMAKE_SOURCE_DIR}/OTRExporter/CFG/filelists/" DESTINATION ./assets/extractor/filelists)
install(FILES "${CMAKE_SOURCE_DIR}/OTRExporter/CFG/ActorList_OoTMqDbg.txt" DESTINATION ./assets/extractor/symbols)
install(FILES "${CMAKE_SOURCE_DIR}/OTRExporter/CFG/ObjectList_OoTMqDbg.txt" DESTINATION ./assets/extractor/symbols)
install(FILES "${CMAKE_SOURCE_DIR}/OTRExporter/CFG/SymbolMap_OoTMqDbg.txt" DESTINATION ./assets/extractor/symbols)
install(DIRECTORY ${CMAKE_BINARY_DIR}/assets
DESTINATION .
PATTERN ZAPD.out
PERMISSIONS ${PROGRAM_PERMISSIONS_EXECUTE}
)
#install(CODE "
# include(BundleUtilities)
# fixup_bundle(\"\${CMAKE_INSTALL_PREFIX}/soh-macos\" \"\" \"${dirs}\")
# ")
#endif()
#if(CMAKE_SYSTEM_NAME MATCHES "Windows|NintendoSwitch|CafeOS")
#install(FILES ${CMAKE_SOURCE_DIR}/README.md DESTINATION . COMPONENT 2s2h RENAME readme.txt )
#endif()
if(CMAKE_SYSTEM_NAME MATCHES "Linux")
set(CPACK_GENERATOR "External")
elseif(CMAKE_SYSTEM_NAME MATCHES "Windows|NintendoSwitch|CafeOS")
set(CPACK_GENERATOR "ZIP")
elseif(CMAKE_SYSTEM_NAME MATCHES "Darwin")
set(CPACK_GENERATOR "Bundle")
endif()
#set(CPACK_PROJECT_CONFIG_FILE ${CMAKE_SOURCE_DIR}/CMake/Packaging-2.cmake)
#include(CMake/Packaging.cmake)

57
Dockerfile Normal file
View File

@ -0,0 +1,57 @@
FROM ubuntu:latest
ARG MY_XAUTH_COOKIE
ENV LANG C.UTF-8
ARG DEBIAN_FRONTEND=noninteractive
RUN dpkg --add-architecture i386
RUN apt-get update
RUN apt-get install -y \
binutils:i386 \
gcc-12:i386 \
g++-12:i386 && \
ln -sf /usr/bin/python3.10 /usr/bin/python3 && \
ln -s /usr/bin/gcc-12 /usr/bin/gcc && \
ln -s /usr/bin/gcc-12 /usr/bin/cc && \
ln -s /usr/bin/g++-12 /usr/bin/g++ && \
ln -s /usr/bin/g++-12 /usr/bin/c++
RUN apt-get install -y \
libsdl2-dev:i386 \
zlib1g-dev:i386 \
libbz2-dev:i386 \
libpng-dev:i386 \
libboost-dev:i386 \
libgles2-mesa-dev
RUN apt-get install -y \
make \
cmake \
git \
gdb \
lld \
python3.10 \
ninja-build \
lsb-release \
clang-format
RUN git clone https://github.com/Perlmint/glew-cmake.git && \
cmake -B glew-cmake/builddir -S glew-cmake -GNinja && \
cmake --build glew-cmake/builddir && \
cmake --install glew-cmake/builddir --prefix /usr && \
mv /usr/lib/libglew-shared.so /usr/lib/libglew.so
RUN git clone https://github.com/libsdl-org/SDL_net.git -b SDL2 && \
cmake -B SDL_net/build -S SDL_net -DCMAKE_BUILD_TYPE=Release && \
cmake --build SDL_net/build --config Release --parallel && \
cmake --install SDL_net/build --config Release
RUN touch /root/.Xauthority && \
xauth add $MY_XAUTH_COOKIE
RUN mkdir /2ship
WORKDIR /2ship

121
LICENSE Normal file
View File

@ -0,0 +1,121 @@
Creative Commons Legal Code
CC0 1.0 Universal
CREATIVE COMMONS CORPORATION IS NOT A LAW FIRM AND DOES NOT PROVIDE
LEGAL SERVICES. DISTRIBUTION OF THIS DOCUMENT DOES NOT CREATE AN
ATTORNEY-CLIENT RELATIONSHIP. CREATIVE COMMONS PROVIDES THIS
INFORMATION ON AN "AS-IS" BASIS. CREATIVE COMMONS MAKES NO WARRANTIES
REGARDING THE USE OF THIS DOCUMENT OR THE INFORMATION OR WORKS
PROVIDED HEREUNDER, AND DISCLAIMS LIABILITY FOR DAMAGES RESULTING FROM
THE USE OF THIS DOCUMENT OR THE INFORMATION OR WORKS PROVIDED
HEREUNDER.
Statement of Purpose
The laws of most jurisdictions throughout the world automatically confer
exclusive Copyright and Related Rights (defined below) upon the creator
and subsequent owner(s) (each and all, an "owner") of an original work of
authorship and/or a database (each, a "Work").
Certain owners wish to permanently relinquish those rights to a Work for
the purpose of contributing to a commons of creative, cultural and
scientific works ("Commons") that the public can reliably and without fear
of later claims of infringement build upon, modify, incorporate in other
works, reuse and redistribute as freely as possible in any form whatsoever
and for any purposes, including without limitation commercial purposes.
These owners may contribute to the Commons to promote the ideal of a free
culture and the further production of creative, cultural and scientific
works, or to gain reputation or greater distribution for their Work in
part through the use and efforts of others.
For these and/or other purposes and motivations, and without any
expectation of additional consideration or compensation, the person
associating CC0 with a Work (the "Affirmer"), to the extent that he or she
is an owner of Copyright and Related Rights in the Work, voluntarily
elects to apply CC0 to the Work and publicly distribute the Work under its
terms, with knowledge of his or her Copyright and Related Rights in the
Work and the meaning and intended legal effect of CC0 on those rights.
1. Copyright and Related Rights. A Work made available under CC0 may be
protected by copyright and related or neighboring rights ("Copyright and
Related Rights"). Copyright and Related Rights include, but are not
limited to, the following:
i. the right to reproduce, adapt, distribute, perform, display,
communicate, and translate a Work;
ii. moral rights retained by the original author(s) and/or performer(s);
iii. publicity and privacy rights pertaining to a person's image or
likeness depicted in a Work;
iv. rights protecting against unfair competition in regards to a Work,
subject to the limitations in paragraph 4(a), below;
v. rights protecting the extraction, dissemination, use and reuse of data
in a Work;
vi. database rights (such as those arising under Directive 96/9/EC of the
European Parliament and of the Council of 11 March 1996 on the legal
protection of databases, and under any national implementation
thereof, including any amended or successor version of such
directive); and
vii. other similar, equivalent or corresponding rights throughout the
world based on applicable law or treaty, and any national
implementations thereof.
2. Waiver. To the greatest extent permitted by, but not in contravention
of, applicable law, Affirmer hereby overtly, fully, permanently,
irrevocably and unconditionally waives, abandons, and surrenders all of
Affirmer's Copyright and Related Rights and associated claims and causes
of action, whether now known or unknown (including existing as well as
future claims and causes of action), in the Work (i) in all territories
worldwide, (ii) for the maximum duration provided by applicable law or
treaty (including future time extensions), (iii) in any current or future
medium and for any number of copies, and (iv) for any purpose whatsoever,
including without limitation commercial, advertising or promotional
purposes (the "Waiver"). Affirmer makes the Waiver for the benefit of each
member of the public at large and to the detriment of Affirmer's heirs and
successors, fully intending that such Waiver shall not be subject to
revocation, rescission, cancellation, termination, or any other legal or
equitable action to disrupt the quiet enjoyment of the Work by the public
as contemplated by Affirmer's express Statement of Purpose.
3. Public License Fallback. Should any part of the Waiver for any reason
be judged legally invalid or ineffective under applicable law, then the
Waiver shall be preserved to the maximum extent permitted taking into
account Affirmer's express Statement of Purpose. In addition, to the
extent the Waiver is so judged Affirmer hereby grants to each affected
person a royalty-free, non transferable, non sublicensable, non exclusive,
irrevocable and unconditional license to exercise Affirmer's Copyright and
Related Rights in the Work (i) in all territories worldwide, (ii) for the
maximum duration provided by applicable law or treaty (including future
time extensions), (iii) in any current or future medium and for any number
of copies, and (iv) for any purpose whatsoever, including without
limitation commercial, advertising or promotional purposes (the
"License"). The License shall be deemed effective as of the date CC0 was
applied by Affirmer to the Work. Should any part of the License for any
reason be judged legally invalid or ineffective under applicable law, such
partial invalidity or ineffectiveness shall not invalidate the remainder
of the License, and in such case Affirmer hereby affirms that he or she
will not (i) exercise any of his or her remaining Copyright and Related
Rights in the Work or (ii) assert any associated claims and causes of
action with respect to the Work, in either case contrary to Affirmer's
express Statement of Purpose.
4. Limitations and Disclaimers.
a. No trademark or patent rights held by Affirmer are waived, abandoned,
surrendered, licensed or otherwise affected by this document.
b. Affirmer offers the Work as-is and makes no representations or
warranties of any kind concerning the Work, express, implied,
statutory or otherwise, including without limitation warranties of
title, merchantability, fitness for a particular purpose, non
infringement, or the absence of latent or other defects, accuracy, or
the present or absence of errors, whether or not discoverable, all to
the greatest extent permissible under applicable law.
c. Affirmer disclaims responsibility for clearing rights of other persons
that may apply to the Work or any use thereof, including without
limitation any person's Copyright and Related Rights in the Work.
Further, Affirmer disclaims responsibility for obtaining any necessary
consents, permissions or other rights required for any use of the
Work.
d. Affirmer understands and acknowledges that Creative Commons is not a
party to this document and has no duty or obligation with respect to
this CC0 or use of the Work.

1
OTRExporter Submodule

@ -0,0 +1 @@
Subproject commit 6212ebc4407107340a76b3ab052f94170a42a3a6

1
ZAPDTR Submodule

@ -0,0 +1 @@
Subproject commit 01615a6c4c6f8e95149fd52ab85b1ae970167bc3

1
libultraship Submodule

@ -0,0 +1 @@
Subproject commit 1dd5f43ffcf4d3d9d322da2408aca76bd41b0bb2

2
mm/.gitignore vendored
View File

@ -7,7 +7,6 @@ __pycache__/
.vscode/
.vs/
.idea/
CMakeLists.txt
cmake-build-debug
venv/
tags
@ -55,3 +54,4 @@ docs/doxygen/
.python-version
.make_options
.*env
*.otr

1340
mm/2s2h/BenPort.cpp Normal file

File diff suppressed because it is too large Load Diff

137
mm/2s2h/BenPort.h Normal file
View File

@ -0,0 +1,137 @@
#ifndef OTR_GLOBALS_H
#define OTR_GLOBALS_H
#pragma once
#define GAME_REGION_NTSC 0
#define GAME_REGION_PAL 1
#define GAME_PLATFORM_N64 0
#define GAME_PLATFORM_GC 1
#ifdef __cplusplus
#include <Context.h>
#include <vector>
const std::string customMessageTableID = "BaseGameOverrides";
const std::string appShortName = "soh";
class OTRGlobals {
public:
static OTRGlobals* Instance;
std::shared_ptr<LUS::Context> context;
OTRGlobals();
~OTRGlobals();
bool HasMasterQuest();
bool HasOriginal();
uint32_t GetInterpolationFPS();
std::shared_ptr<std::vector<std::string>> ListFiles(std::string path);
private:
void CheckSaveFile(size_t sramSize) const;
bool hasMasterQuest;
bool hasOriginal;
};
uint32_t IsGameMasterQuest();
#endif
#ifndef __cplusplus
void InitOTR(void);
void DeinitOTR(void);
void VanillaItemTable_Init();
void OTRAudio_Init();
void OTRMessage_Init();
void InitAudio();
void Graph_StartFrame();
void Graph_ProcessGfxCommands(Gfx* commands);
void Graph_ProcessFrame(void (*run_one_game_iter)(void));
void OTRLogString(const char* src);
void OTRGfxPrint(const char* str, void* printer, void (*printImpl)(void*, char));
void OTRGetPixelDepthPrepare(float x, float y);
uint16_t OTRGetPixelDepth(float x, float y);
int32_t OTRGetLastScancode();
uint32_t ResourceMgr_IsGameMasterQuest();
uint32_t ResourceMgr_IsSceneMasterQuest(s16 sceneNum);
uint32_t ResourceMgr_GameHasMasterQuest();
uint32_t ResourceMgr_GameHasOriginal();
uint32_t ResourceMgr_GetNumGameVersions();
uint32_t ResourceMgr_GetGameVersion(int index);
uint32_t ResourceMgr_GetGamePlatform(int index);
uint32_t ResourceMgr_GetGameRegion(int index);
void ResourceMgr_LoadDirectory(const char* resName);
char** ResourceMgr_ListFiles(const char* searchMask, int* resultSize);
uint8_t ResourceMgr_FileExists(const char* resName);
char* GetResourceDataByNameHandlingMQ(const char* path);
void ResourceMgr_LoadFile(const char* resName);
char* ResourceMgr_LoadFileFromDisk(const char* filePath);
uint8_t ResourceMgr_ResourceIsBackground(char* texPath);
char* ResourceMgr_LoadJPEG(char* data, size_t dataSize);
uint16_t ResourceMgr_LoadTexWidthByName(char* texPath);
uint16_t ResourceMgr_LoadTexHeightByName(char* texPath);
CollisionHeader* ResourceMgr_LoadColByName(const char* path);
AnimatedMaterial* ResourceMgr_LoadAnimatedMatByName(const char* path);
char* ResourceMgr_LoadTexOrDListByName(const char* filePath);
char* ResourceMgr_LoadPlayerAnimByName(const char* animPath);
AnimationHeaderCommon* ResourceMgr_LoadAnimByName(const char* path);
char* ResourceMgr_GetNameByCRC(uint64_t crc, char* alloc);
Gfx* ResourceMgr_LoadGfxByCRC(uint64_t crc);
Gfx* ResourceMgr_LoadGfxByName(const char* path);
void ResourceMgr_PatchGfxByName(const char* path, const char* patchName, int index, Gfx instruction);
void ResourceMgr_UnpatchGfxByName(const char* path, const char* patchName);
char* ResourceMgr_LoadArrayByNameAsVec3s(const char* path);
char* ResourceMgr_LoadArrayByName(const char* path);
size_t ResourceMgr_GetArraySizeByName(const char* path);
Vtx* ResourceMgr_LoadVtxByCRC(uint64_t crc);
char* ResourceMgr_LoadVtxArrayByName(const char* path);
size_t ResourceMgr_GetVtxArraySizeByName(const char* path);
Vtx* ResourceMgr_LoadVtxByName(char* path);
void Ctx_ReadSaveFile(uintptr_t addr, void* dramAddr, size_t size);
void Ctx_WriteSaveFile(uintptr_t addr, void* dramAddr, size_t size);
uint64_t GetPerfCounter();
struct SkeletonHeader* ResourceMgr_LoadSkeletonByName(const char* path, SkelAnime* skelAnime);
void ResourceMgr_UnregisterSkeleton(SkelAnime* skelAnime);
void ResourceMgr_ClearSkeletons();
s32* ResourceMgr_LoadCSByName(const char* path);
int ResourceMgr_OTRSigCheck(char* imgData);
uint64_t osGetTime(void);
uint32_t osGetCount(void);
uint32_t OTRGetCurrentWidth(void);
uint32_t OTRGetCurrentHeight(void);
float OTRGetAspectRatio(void);
float OTRGetDimensionFromLeftEdge(float v);
float OTRGetDimensionFromRightEdge(float v);
int16_t OTRGetRectDimensionFromLeftEdge(float v);
int16_t OTRGetRectDimensionFromRightEdge(float v);
int AudioPlayer_Buffered(void);
int AudioPlayer_GetDesiredBuffered(void);
void AudioPlayer_Play(const uint8_t* buf, uint32_t len);
void AudioMgr_CreateNextAudioBuffer(s16* samples, u32 num_samples);
int Controller_ShouldRumble(size_t slot);
void Controller_BlockGameInput();
void Controller_UnblockGameInput();
void Overlay_DisplayText(float duration, const char* text);
void Overlay_DisplayText_Seconds(int seconds, const char* text);
void Gfx_RegisterBlendedTexture(const char* name, u8* mask, u8* replacement);
void CheckTracker_OnMessageClose();
int32_t GetGIID(uint32_t itemID);
#endif
#ifdef __cplusplus
extern "C" {
#endif
uint64_t GetUnixTimestamp();
#ifdef __cplusplus
};
#endif
#endif

Binary file not shown.

View File

@ -0,0 +1,603 @@
#ifdef _WIN32
#include <Windows.h>
#include <winuser.h>
#include <shlwapi.h>
#pragma comment(lib, "Shlwapi.lib")
#endif
#include "Extract.h"
#include "portable-file-dialogs.h"
#include <Utils/BitConverter.h>
#ifdef unix
#include <dirent.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <unistd.h>
#endif
#ifdef _MSC_VER
#define BSWAP32 _byteswap_ulong
#define BSWAP16 _byteswap_ushort
#elif __has_include(<byteswap.h>)
#include <byteswap.h>
#define BSWAP32 bswap_32
#define BSWAP16 bswap_16
#else
#define BSWAP16(value) ((((value)&0xff) << 8) | ((value) >> 8))
#define BSWAP32(value) \
(((uint32_t)BSWAP16((uint16_t)((value)&0xffff)) << 16) | (uint32_t)BSWAP16((uint16_t)((value) >> 16)))
#endif
#if defined(_MSC_VER)
#define UNREACHABLE __assume(0)
#elif __llvm__
#define UNREACHABLE __builtin_assume(0)
#else
#define UNREACHABLE __builtin_unreachable();
#endif
#include <stdlib.h>
#include <SDL2/SDL_messagebox.h>
#include <array>
#include <fstream>
#include <filesystem>
#include <unordered_map>
#include <random>
#include <string>
extern "C" uint32_t CRC32C(unsigned char* data, size_t dataSize);
static constexpr uint32_t OOT_PAL_GC = 0x09465AC3;
static constexpr uint32_t OOT_PAL_MQ = 0x1D4136F3;
static constexpr uint32_t OOT_PAL_GC_DBG1 = 0x871E1C92; // 03-21-2002 build
static constexpr uint32_t OOT_PAL_GC_DBG2 = 0x87121EFE; // 03-13-2002 build
static constexpr uint32_t OOT_PAL_GC_MQ_DBG = 0x917D18F6;
static constexpr uint32_t OOT_PAL_10 = 0xB044B569;
static constexpr uint32_t OOT_PAL_11 = 0xB2055FBD;
static constexpr uint32_t MM_US_10 = 0x5354631C;
static const std::unordered_map<uint32_t, const char*> verMap = {
{ MM_US_10, "U.S 1.0" },
//{ OOT_PAL_GC, "PAL Gamecube" },
//{ OOT_PAL_MQ, "PAL MQ" },
//{ OOT_PAL_GC_DBG1, "PAL Debug 1" },
//{ OOT_PAL_GC_DBG2, "PAL Debug 2" },
//{ OOT_PAL_GC_MQ_DBG, "PAL MQ Debug" },
//{ OOT_PAL_10, "PAL N64 1.0" },
//{ OOT_PAL_11, "PAL N64 1.1" },
};
// TODO only check the first 54MB of the rom.
static constexpr std::array<const uint32_t, 10> goodCrcs = {
//0xfa8c0555, // MQ DBG 64MB (Original overdump)
//0x8652ac4c, // MQ DBG 64MB
//0x5B8A1EB7, // MQ DBG 64MB (Empty overdump)
//0x1f731ffe, // MQ DBG 54MB
//0x044b3982, // NMQ DBG 54MB
//0xEB15D7B9, // NMQ DBG 64MB
//0xDA8E61BF, // GC PAL
//0x7A2FAE68, // GC MQ PAL
//0xFD9913B1, // N64 PAL 1.0
//0xE033FBBA, // N64 PAL 1.1
};
enum class ButtonId : int {
YES,
NO,
FIND,
};
void Extractor::ShowErrorBox(const char* title, const char* text) {
#ifdef _WIN32
MessageBoxA(nullptr, text, title, MB_OK | MB_ICONERROR);
#else
SDL_ShowSimpleMessageBox(SDL_MESSAGEBOX_ERROR, title, text, nullptr);
#endif
}
void Extractor::ShowSizeErrorBox() const {
std::unique_ptr<char[]> boxBuffer = std::make_unique<char[]>(mCurrentRomPath.size() + 100);
snprintf(boxBuffer.get(), mCurrentRomPath.size() + 100,
"The rom file %s was not a valid size. Was %zu MB, expecting 32, 54, or 64MB.", mCurrentRomPath.c_str(),
mCurRomSize / MB_BASE);
ShowErrorBox("Invalid Rom Size", boxBuffer.get());
}
void Extractor::ShowCrcErrorBox() const {
ShowErrorBox("Rom CRC invalid", "Rom CRC did not match the list of known good roms. Please find another.");
}
int Extractor::ShowRomPickBox(uint32_t verCrc) const {
std::unique_ptr<char[]> boxBuffer = std::make_unique<char[]>(mCurrentRomPath.size() + 100);
SDL_MessageBoxData boxData = { 0 };
SDL_MessageBoxButtonData buttons[3] = { { 0 } };
int ret;
buttons[0].buttonid = 0;
buttons[0].text = "Yes";
buttons[0].flags = SDL_MESSAGEBOX_BUTTON_RETURNKEY_DEFAULT;
buttons[1].buttonid = 1;
buttons[1].text = "No";
buttons[1].flags = SDL_MESSAGEBOX_BUTTON_ESCAPEKEY_DEFAULT;
buttons[2].buttonid = 2;
buttons[2].text = "Find ROM";
boxData.numbuttons = 3;
boxData.flags = SDL_MESSAGEBOX_INFORMATION;
boxData.message = boxBuffer.get();
boxData.title = "Rom Detected";
boxData.window = nullptr;
boxData.buttons = buttons;
snprintf(boxBuffer.get(), mCurrentRomPath.size() + 100,
"Rom detected: %s, Header CRC32: %8X. It appears to be: %s. Use this rom?", mCurrentRomPath.c_str(),
verCrc, verMap.at(verCrc));
SDL_ShowMessageBox(&boxData, &ret);
return ret;
}
int Extractor::ShowYesNoBox(const char* title, const char* box) {
int ret;
#ifdef _WIN32
ret = MessageBoxA(nullptr, box, title, MB_YESNO | MB_ICONQUESTION);
#else
SDL_MessageBoxData boxData = { 0 };
SDL_MessageBoxButtonData buttons[2] = { { 0 } };
buttons[0].buttonid = IDYES;
buttons[0].text = "Yes";
buttons[0].flags = SDL_MESSAGEBOX_BUTTON_RETURNKEY_DEFAULT;
buttons[1].buttonid = IDNO;
buttons[1].text = "No";
buttons[1].flags = SDL_MESSAGEBOX_BUTTON_ESCAPEKEY_DEFAULT;
boxData.numbuttons = 2;
boxData.flags = SDL_MESSAGEBOX_INFORMATION;
boxData.message = box;
boxData.title = title;
boxData.buttons = buttons;
SDL_ShowMessageBox(&boxData, &ret);
#endif
return ret;
}
void Extractor::SetRomInfo(const std::string& path) {
mCurrentRomPath = path;
mCurRomSize = GetCurRomSize();
}
void Extractor::FilterRoms(std::vector<std::string>& roms, RomSearchMode searchMode) {
std::ifstream inFile;
std::vector<std::string>::iterator it = roms.begin();
while (it != roms.end()) {
std::string rom = *it;
SetRomInfo(rom);
// Skip. We will handle rom size errors later on after filtering
if (!ValidateRomSize()) {
it++;
continue;
}
inFile.open(rom, std::ios::in | std::ios::binary);
inFile.read((char*)mRomData.get(), mCurRomSize);
inFile.clear();
inFile.close();
BitConverter::RomToBigEndian(mRomData.get(), mCurRomSize);
// Rom doesn't claim to be valid
// Game type doesn't match search mode
if (!verMap.contains(GetRomVerCrc()) ||
(searchMode == RomSearchMode::Vanilla && IsMasterQuest()) ||
(searchMode == RomSearchMode::MQ && !IsMasterQuest())) {
it = roms.erase(it);
continue;
}
it++;
}
}
void Extractor::GetRoms(std::vector<std::string>& roms) {
#ifdef _WIN32
WIN32_FIND_DATAA ffd;
HANDLE h = FindFirstFileA(".\\*", &ffd);
do {
if (!(ffd.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)) {
char* ext = PathFindExtensionA(ffd.cFileName);
// Check for any standard N64 rom file extensions.
if ((strcmp(ext, ".z64") == 0) || (strcmp(ext, ".n64") == 0) || (strcmp(ext, ".v64") == 0))
roms.push_back(ffd.cFileName);
}
} while (FindNextFileA(h, &ffd) != 0);
// if (h != nullptr) {
// CloseHandle(h);
//}
#elif unix
// Open the directory of the app.
DIR* d = opendir(".");
struct dirent* dir;
if (d != NULL) {
// Go through each file in the directory
while ((dir = readdir(d)) != NULL) {
struct stat path;
// Check if current entry is not folder
stat(dir->d_name, &path);
if (S_ISREG(path.st_mode)) {
// Get the position of the extension character.
char* ext = strrchr(dir->d_name, '.');
if (ext != NULL && (strcmp(ext, ".z64") == 0 || strcmp(ext, ".n64") == 0 ||
strcmp(ext, ".v64") == 0)) {
roms.push_back(dir->d_name);
}
}
}
}
closedir(d);
#else
for (const auto& file : std::filesystem::directory_iterator("./")) {
if (file.is_directory())
continue;
if ((file.path().extension() == ".n64") || (file.path().extension() == ".z64") ||
(file.path().extension() == ".v64")) {
roms.push_back((file.path()));
}
}
#endif
}
bool Extractor::GetRomPathFromBox() {
#ifdef _WIN32
OPENFILENAMEA box = { 0 };
char nameBuffer[512];
nameBuffer[0] = 0;
box.lStructSize = sizeof(box);
box.lpstrFile = nameBuffer;
box.nMaxFile = sizeof(nameBuffer) / sizeof(nameBuffer[0]);
box.lpstrTitle = "Open Rom";
box.Flags = OFN_NOCHANGEDIR | OFN_ENABLESIZING | OFN_FILEMUSTEXIST | OFN_LONGNAMES | OFN_PATHMUSTEXIST | OFN_HIDEREADONLY;
box.lpstrFilter = "N64 Roms\0*.z64;*.v64;*.n64\0\0";
if (!GetOpenFileNameA(&box)) {
DWORD err = CommDlgExtendedError();
// GetOpenFileName will return 0 but no error is set if the user just closes the box.
if (err != 0) {
const char* errStr = nullptr;
switch (err) {
case FNERR_BUFFERTOOSMALL:
errStr = "Path buffer too small. Move file closer to root of your drive";
break;
case FNERR_INVALIDFILENAME:
errStr = "File name for rom provided is invalid.";
break;
case FNERR_SUBCLASSFAILURE:
errStr = "Failed to open a filebox because there is not enough RAM to do so.";
break;
}
MessageBoxA(nullptr, "Box Error", errStr, MB_OK | MB_ICONERROR);
return false;
}
}
// The box was closed without something being selected.
if (nameBuffer[0] == 0) {
return false;
}
mCurrentRomPath = nameBuffer;
#else
auto selection = pfd::open_file("Select a file", ".", { "N64 Roms", "*.z64 *.n64 *.v64" }).result();
if (selection.empty()) {
return false;
}
mCurrentRomPath = selection[0];
#endif
mCurRomSize = GetCurRomSize();
return true;
}
uint32_t Extractor::GetRomVerCrc() const {
return BSWAP32(((uint32_t*)mRomData.get())[4]);
}
size_t Extractor::GetCurRomSize() const {
return std::filesystem::file_size(mCurrentRomPath);
}
bool Extractor::ValidateAndFixRom() {
// The MQ debug rom sometimes has the header patched to look like a US rom. Change it back
if (GetRomVerCrc() == OOT_PAL_GC_MQ_DBG) {
mRomData[0x3E] = 'P';
}
const uint32_t actualCrc = CRC32C(mRomData.get(), mCurRomSize);
for (const uint32_t crc : goodCrcs) {
if (actualCrc == crc) {
return true;
}
}
return false;
}
bool Extractor::ValidateRomSize() const {
if (mCurRomSize != MB32 && mCurRomSize != MB54 && mCurRomSize != MB64) {
return false;
}
return true;
}
bool Extractor::ValidateRom(bool skipCrcTextBox) {
if (!ValidateRomSize()) {
ShowSizeErrorBox();
return false;
}
if (!ValidateAndFixRom()) {
if (!skipCrcTextBox) {
ShowCrcErrorBox();
}
return false;
}
return true;
}
bool Extractor::ManuallySearchForRom() {
std::ifstream inFile;
if (!GetRomPathFromBox()) {
ShowErrorBox("No rom selected", "No Rom selected. Exiting");
return false;
}
inFile.open(mCurrentRomPath, std::ios::in | std::ios::binary);
if (!inFile.is_open()) {
return false; // TODO Handle error
}
inFile.read((char*)mRomData.get(), mCurRomSize);
inFile.close();
BitConverter::RomToBigEndian(mRomData.get(), mCurRomSize);
if (!ValidateRom()) {
return false;
}
return true;
}
bool Extractor::ManuallySearchForRomMatchingType(RomSearchMode searchMode) {
if (!ManuallySearchForRom()) {
return false;
}
char msgBuf[150];
snprintf(msgBuf, 150, "The selected rom does not match the expected game type\nExpected type: %s.\n\nDo you want to search again?",
searchMode == RomSearchMode::MQ ? "Master Quest" : "Vanilla");
while ((searchMode == RomSearchMode::Vanilla && IsMasterQuest()) ||
(searchMode == RomSearchMode::MQ && !IsMasterQuest())) {
int ret = ShowYesNoBox("Wrong Game Type", msgBuf);
switch (ret) {
case IDYES:
if (!ManuallySearchForRom()) {
return false;
}
continue;
case IDNO:
return false;
default:
UNREACHABLE;
break;
}
}
return true;
}
bool Extractor::Run(RomSearchMode searchMode) {
std::vector<std::string> roms;
std::ifstream inFile;
GetRoms(roms);
FilterRoms(roms, searchMode);
if (roms.empty()) {
int ret = ShowYesNoBox("No roms found", "No roms found. Look for one?");
switch (ret) {
case IDYES:
if (!ManuallySearchForRomMatchingType(searchMode)) {
return false;
}
break;
case IDNO:
ShowErrorBox("No rom selected", "No rom selected. Exiting");
return false;
default:
UNREACHABLE;
break;
}
}
for (const auto& rom : roms) {
SetRomInfo(rom);
if (!ValidateRomSize()) {
ShowSizeErrorBox();
continue;
}
inFile.open(rom, std::ios::in | std::ios::binary);
inFile.read((char*)mRomData.get(), mCurRomSize);
inFile.clear();
inFile.close();
BitConverter::RomToBigEndian(mRomData.get(), mCurRomSize);
int option = ShowRomPickBox(GetRomVerCrc());
if (option == (int)ButtonId::YES) {
if (!ValidateRom(true)) {
if (rom == roms.back()) {
ShowCrcErrorBox();
} else {
ShowErrorBox("Rom CRC invalid",
"Rom CRC did not match the list of known good roms. Trying the next one...");
}
continue;
}
break;
} else if (option == (int)ButtonId::FIND) {
if (!ManuallySearchForRomMatchingType(searchMode)) {
return false;
}
break;
} else if (option == (int)ButtonId::NO) {
if (rom == roms.back()) {
ShowErrorBox("No rom provided", "No rom provided. Exiting");
return false;
}
continue;
}
break;
}
return true;
}
bool Extractor::IsMasterQuest() const {
switch (GetRomVerCrc()) {
case OOT_PAL_MQ:
case OOT_PAL_GC_MQ_DBG:
return true;
case OOT_PAL_10:
case OOT_PAL_11:
case OOT_PAL_GC:
case OOT_PAL_GC_DBG1:
return false;
default:
UNREACHABLE;
}
}
const char* Extractor::GetZapdVerStr() const {
switch (GetRomVerCrc()) {
case OOT_PAL_GC:
return "GC_NMQ_PAL_F";
case OOT_PAL_MQ:
return "GC_MQ_PAL_F";
case OOT_PAL_GC_DBG1:
return "GC_NMQ_D";
case OOT_PAL_GC_MQ_DBG:
return "GC_MQ_D";
case OOT_PAL_10:
return "N64_PAL_10";
case OOT_PAL_11:
return "N64_PAL_11";
default:
// We should never be in a state where this path happens.
UNREACHABLE;
break;
}
}
std::string Extractor::Mkdtemp() {
std::string temp_dir = std::filesystem::temp_directory_path().string();
// create 6 random alphanumeric characters
static const char charset[] = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz";
std::random_device rd;
std::mt19937 gen(rd());
std::uniform_int_distribution<> dist(0, sizeof(charset) - 1);
char randchr[7];
for (int i = 0; i < 6; i++) {
randchr[i] = charset[dist(gen)];
}
randchr[6] = '\0';
std::string tmppath = temp_dir + "/extractor-" + randchr;
std::filesystem::create_directory(tmppath);
return tmppath;
}
extern "C" int zapd_main(int argc, char** argv);
bool Extractor::CallZapd(std::string installPath, std::string exportdir) {
constexpr int argc = 16;
char xmlPath[1024];
char confPath[1024];
std::array<const char*, argc> argv;
const char* version = GetZapdVerStr();
const char* otrFile = IsMasterQuest() ? "oot-mq.otr" : "oot.otr";
std::string romPath = std::filesystem::absolute(mCurrentRomPath).string();
installPath = std::filesystem::absolute(installPath).string();
exportdir = std::filesystem::absolute(exportdir).string();
// Work this out in the temporary folder
std::string tempdir = Mkdtemp();
std::string curdir = std::filesystem::current_path().string();
#ifdef _WIN32
std::filesystem::copy(installPath + "/assets", tempdir + "/assets",
std::filesystem::copy_options::recursive | std::filesystem::copy_options::update_existing);
#else
std::filesystem::create_symlink(installPath + "/assets", tempdir + "/assets");
#endif
std::filesystem::current_path(tempdir);
snprintf(xmlPath, 1024, "assets/extractor/xmls/%s", version);
snprintf(confPath, 1024, "assets/extractor/Config_%s.xml", version);
argv[0] = "ZAPD";
argv[1] = "ed";
argv[2] = "-i";
argv[3] = xmlPath;
argv[4] = "-b";
argv[5] = romPath.c_str();
argv[6] = "-fl";
argv[7] = "assets/extractor/filelists";
argv[8] = "-gsf";
argv[9] = "1";
argv[10] = "-rconf";
argv[11] = confPath;
argv[12] = "-se";
argv[13] = "OTR";
argv[14] = "--otrfile";
argv[15] = otrFile;
#ifdef _WIN32
// Grab a handle to the command window.
HWND cmdWindow = GetConsoleWindow();
// Normally the command window is hidden. We want the window to be shown here so the user can see the progess of the extraction.
ShowWindow(cmdWindow, SW_SHOW);
SetWindowPos(cmdWindow, HWND_NOTOPMOST, 0, 0, 0, 0, SWP_NOSIZE | SWP_NOMOVE);
#endif
zapd_main(argc, (char**)argv.data());
#ifdef _WIN32
// Hide the command window again.
ShowWindow(cmdWindow, SW_HIDE);
#endif
std::filesystem::copy(otrFile, exportdir + "/" + otrFile, std::filesystem::copy_options::overwrite_existing);
// Go back to where this game was executed from
std::filesystem::current_path(curdir);
std::filesystem::remove_all(tempdir);
return 0;
}

View File

@ -0,0 +1,64 @@
#ifndef EXTRACT_H
#define EXTRACT_H
#include <stdint.h>
#include <string>
#include <memory>
#include <vector>
// Values come from windows.h
#ifndef IDYES
#define IDYES 6
#endif
#ifndef IDNO
#define IDNO 7
#endif
static constexpr size_t MB_BASE = 1024 * 1024;
static constexpr size_t MB32 = 32 * MB_BASE;
static constexpr size_t MB54 = 54 * MB_BASE;
static constexpr size_t MB64 = 64 * MB_BASE;
enum class RomSearchMode {
Both = 0,
Vanilla = 1,
MQ = 2,
};
class Extractor {
std::unique_ptr<unsigned char[]> mRomData = std::make_unique<unsigned char[]>(MB64);
std::string mCurrentRomPath;
size_t mCurRomSize = 0;
bool GetRomPathFromBox();
uint32_t GetRomVerCrc() const;
size_t GetCurRomSize() const;
bool ValidateAndFixRom();
bool ValidateRomSize() const;
bool ValidateRom(bool skipCrcBox = false);
const char* GetZapdVerStr() const;
void SetRomInfo(const std::string& path);
void FilterRoms(std::vector<std::string>& roms, RomSearchMode searchMode);
void GetRoms(std::vector<std::string>& roms);
void ShowSizeErrorBox() const;
void ShowCrcErrorBox() const;
int ShowRomPickBox(uint32_t verCrc) const;
bool ManuallySearchForRom();
bool ManuallySearchForRomMatchingType(RomSearchMode searchMode);
public:
//TODO create some kind of abstraction for message boxes.
static int ShowYesNoBox(const char* title, const char* text);
static void ShowErrorBox(const char* title, const char* text);
bool IsMasterQuest() const;
bool Run(RomSearchMode searchMode = RomSearchMode::Both);
bool CallZapd(std::string installPath, std::string exportdir);
const char* GetZapdStr();
std::string Mkdtemp();
};
#endif

View File

@ -0,0 +1,144 @@
#include <stdint.h>
#include <stddef.h>
// Force the compiler to assume we have support for the CRC32 intrinsic. We will check for our selves later.
// Clang will define both __llvm__ and __GNUC__ but GCC will only define __GNUC__. So we need to check for __llvm__ first.
#if ((defined(__llvm__) && (defined(__x86_64__) || defined(__i386__))))
#pragma clang attribute push(__attribute__((target("crc32"))), apply_to = function)
#elif ((defined(__GNUC__) && (defined(__x86_64__) || defined(__i386__))))
// GCC Only lets you enable all of sse4.2 so we will for just this file and reset it at the end.
#pragma GCC push_options
#pragma GCC target("sse4.2")
#endif
// Include headers for the CRC32 intrinsic and cpuid instruction on windows. No need to do any other checks because it assumes the target will support CRC32
#ifdef _WIN32
#include <immintrin.h>
#include <intrin.h>
// Same as above but these platforms use slightly different headers
#elif ((defined(__GNUC__) && (defined(__x86_64__) || defined(__i386__))))
#include <nmmintrin.h>
#include <cpuid.h>
#elif defined(__aarch64__) && defined(__ARM_FEATURE_CRC32)
// Nothing cause its a compiler builtin
#else
#define NO_CRC_INTRIN
#endif
#if defined(__aarch64__) && defined(__ARM_FEATURE_CRC32)
#define INTRIN_CRC32_64(crc, value) __asm__("crc32cx %w[c], %w[c], %x[v]" : [c] "+r"(crc) : [v] "r"(value))
#define INTRIN_CRC32_32(crc, value) __asm__("crc32cw %w[c], %w[c], %w[v]" : [c] "+r"(crc) : [v] "r"(value))
#define INTRIN_CRC32_16(crc, value) __asm__("crc32ch %w[c], %w[c], %w[v]" : [c] "+r"(crc) : [v] "r"(value))
#define INTRIN_CRC32_8(crc, value) __asm__("crc32cb %w[c], %w[c], %w[v]" : [c] "+r"(crc) : [v] "r"(value))
#elif defined(__GNUC__) || defined(_MSC_VER)
#define INTRIN_CRC32_64(crc, data) crc = _mm_crc32_u64(crc, data)
#define INTRIN_CRC32_32(crc, data) crc = _mm_crc32_u32(crc, data)
#define INTRIN_CRC32_16(crc, data) crc = _mm_crc32_u16(crc, data)
#define INTRIN_CRC32_8(crc, data) crc = _mm_crc32_u8(crc, data)
#endif
static const uint32_t crc32Table[256] = {
0x00000000L, 0xF26B8303L, 0xE13B70F7L, 0x1350F3F4L, 0xC79A971FL, 0x35F1141CL, 0x26A1E7E8L, 0xD4CA64EBL, 0x8AD958CFL,
0x78B2DBCCL, 0x6BE22838L, 0x9989AB3BL, 0x4D43CFD0L, 0xBF284CD3L, 0xAC78BF27L, 0x5E133C24L, 0x105EC76FL, 0xE235446CL,
0xF165B798L, 0x030E349BL, 0xD7C45070L, 0x25AFD373L, 0x36FF2087L, 0xC494A384L, 0x9A879FA0L, 0x68EC1CA3L, 0x7BBCEF57L,
0x89D76C54L, 0x5D1D08BFL, 0xAF768BBCL, 0xBC267848L, 0x4E4DFB4BL, 0x20BD8EDEL, 0xD2D60DDDL, 0xC186FE29L, 0x33ED7D2AL,
0xE72719C1L, 0x154C9AC2L, 0x061C6936L, 0xF477EA35L, 0xAA64D611L, 0x580F5512L, 0x4B5FA6E6L, 0xB93425E5L, 0x6DFE410EL,
0x9F95C20DL, 0x8CC531F9L, 0x7EAEB2FAL, 0x30E349B1L, 0xC288CAB2L, 0xD1D83946L, 0x23B3BA45L, 0xF779DEAEL, 0x05125DADL,
0x1642AE59L, 0xE4292D5AL, 0xBA3A117EL, 0x4851927DL, 0x5B016189L, 0xA96AE28AL, 0x7DA08661L, 0x8FCB0562L, 0x9C9BF696L,
0x6EF07595L, 0x417B1DBCL, 0xB3109EBFL, 0xA0406D4BL, 0x522BEE48L, 0x86E18AA3L, 0x748A09A0L, 0x67DAFA54L, 0x95B17957L,
0xCBA24573L, 0x39C9C670L, 0x2A993584L, 0xD8F2B687L, 0x0C38D26CL, 0xFE53516FL, 0xED03A29BL, 0x1F682198L, 0x5125DAD3L,
0xA34E59D0L, 0xB01EAA24L, 0x42752927L, 0x96BF4DCCL, 0x64D4CECFL, 0x77843D3BL, 0x85EFBE38L, 0xDBFC821CL, 0x2997011FL,
0x3AC7F2EBL, 0xC8AC71E8L, 0x1C661503L, 0xEE0D9600L, 0xFD5D65F4L, 0x0F36E6F7L, 0x61C69362L, 0x93AD1061L, 0x80FDE395L,
0x72966096L, 0xA65C047DL, 0x5437877EL, 0x4767748AL, 0xB50CF789L, 0xEB1FCBADL, 0x197448AEL, 0x0A24BB5AL, 0xF84F3859L,
0x2C855CB2L, 0xDEEEDFB1L, 0xCDBE2C45L, 0x3FD5AF46L, 0x7198540DL, 0x83F3D70EL, 0x90A324FAL, 0x62C8A7F9L, 0xB602C312L,
0x44694011L, 0x5739B3E5L, 0xA55230E6L, 0xFB410CC2L, 0x092A8FC1L, 0x1A7A7C35L, 0xE811FF36L, 0x3CDB9BDDL, 0xCEB018DEL,
0xDDE0EB2AL, 0x2F8B6829L, 0x82F63B78L, 0x709DB87BL, 0x63CD4B8FL, 0x91A6C88CL, 0x456CAC67L, 0xB7072F64L, 0xA457DC90L,
0x563C5F93L, 0x082F63B7L, 0xFA44E0B4L, 0xE9141340L, 0x1B7F9043L, 0xCFB5F4A8L, 0x3DDE77ABL, 0x2E8E845FL, 0xDCE5075CL,
0x92A8FC17L, 0x60C37F14L, 0x73938CE0L, 0x81F80FE3L, 0x55326B08L, 0xA759E80BL, 0xB4091BFFL, 0x466298FCL, 0x1871A4D8L,
0xEA1A27DBL, 0xF94AD42FL, 0x0B21572CL, 0xDFEB33C7L, 0x2D80B0C4L, 0x3ED04330L, 0xCCBBC033L, 0xA24BB5A6L, 0x502036A5L,
0x4370C551L, 0xB11B4652L, 0x65D122B9L, 0x97BAA1BAL, 0x84EA524EL, 0x7681D14DL, 0x2892ED69L, 0xDAF96E6AL, 0xC9A99D9EL,
0x3BC21E9DL, 0xEF087A76L, 0x1D63F975L, 0x0E330A81L, 0xFC588982L, 0xB21572C9L, 0x407EF1CAL, 0x532E023EL, 0xA145813DL,
0x758FE5D6L, 0x87E466D5L, 0x94B49521L, 0x66DF1622L, 0x38CC2A06L, 0xCAA7A905L, 0xD9F75AF1L, 0x2B9CD9F2L, 0xFF56BD19L,
0x0D3D3E1AL, 0x1E6DCDEEL, 0xEC064EEDL, 0xC38D26C4L, 0x31E6A5C7L, 0x22B65633L, 0xD0DDD530L, 0x0417B1DBL, 0xF67C32D8L,
0xE52CC12CL, 0x1747422FL, 0x49547E0BL, 0xBB3FFD08L, 0xA86F0EFCL, 0x5A048DFFL, 0x8ECEE914L, 0x7CA56A17L, 0x6FF599E3L,
0x9D9E1AE0L, 0xD3D3E1ABL, 0x21B862A8L, 0x32E8915CL, 0xC083125FL, 0x144976B4L, 0xE622F5B7L, 0xF5720643L, 0x07198540L,
0x590AB964L, 0xAB613A67L, 0xB831C993L, 0x4A5A4A90L, 0x9E902E7BL, 0x6CFBAD78L, 0x7FAB5E8CL, 0x8DC0DD8FL, 0xE330A81AL,
0x115B2B19L, 0x020BD8EDL, 0xF0605BEEL, 0x24AA3F05L, 0xD6C1BC06L, 0xC5914FF2L, 0x37FACCF1L, 0x69E9F0D5L, 0x9B8273D6L,
0x88D28022L, 0x7AB90321L, 0xAE7367CAL, 0x5C18E4C9L, 0x4F48173DL, 0xBD23943EL, 0xF36E6F75L, 0x0105EC76L, 0x12551F82L,
0xE03E9C81L, 0x34F4F86AL, 0xC69F7B69L, 0xD5CF889DL, 0x27A40B9EL, 0x79B737BAL, 0x8BDCB4B9L, 0x988C474DL, 0x6AE7C44EL,
0xBE2DA0A5L, 0x4C4623A6L, 0x5F16D052L, 0xAD7D5351L
};
// On platforms that we know will never support a crc32 instruction (such as the WiiU) we will skip compiling this function in.
#ifndef NO_CRC_INTRIN
static uint32_t CRC32IntrinImpl(unsigned char* data, size_t dataSize) {
uint32_t ret = 0xFFFFFFFF;
int64_t sizeSigned = dataSize;
// Only 64bit platforms support doing a CRC32 operation on a 64bit value
#if defined(_M_X64) || defined(__x86_64__) || defined(__aarch64__)
while ((sizeSigned -= sizeof(uint64_t)) >= 0) {
INTRIN_CRC32_64(ret, *(uint64_t*)data);
data += sizeof(uint64_t);
}
if (sizeSigned & sizeof(uint32_t)) {
INTRIN_CRC32_32(ret, *(uint32_t*)data);
data += sizeof(uint32_t);
}
// On 32 bit we can only do 32bit operations
#elif defined(_M_IX86) || defined(__i386__)
while ((sizeSigned -= sizeof(uint32_t)) >= 0) {
INTRIN_CRC32_32(ret, *(uint32_t*)data);
data += sizeof(uint32_t);
}
#endif
if (sizeSigned & sizeof(uint16_t)) {
INTRIN_CRC32_16(ret, *(uint16_t*)data);
data += sizeof(uint16_t);
}
if (sizeSigned & sizeof(uint8_t)) {
INTRIN_CRC32_8(ret, *data);
}
return ~ret;
}
#endif
static uint32_t CRC32TableImpl(unsigned char* data, size_t dataSize) {
const uint8_t* p = data;
uint32_t crc = 0xFFFFFFFF;
while (dataSize--)
crc = crc32Table[(crc ^ *p++) & 0xff] ^ (crc >> 8);
return ~crc;
}
uint32_t CRC32C(unsigned char* data, size_t dataSize) {
#ifndef NO_CRC_INTRIN
// Test to make sure the CPU supports the CRC32 intrinsic
unsigned int cpuidData[4];
#ifdef _WIN32
__cpuid(cpuidData, 1);
#elif __APPLE__ || (defined(__aarch64__) && defined(__ARM_FEATURE_CRC32))
// Every Mac that supports SoH should support this instruction. Also check for ARM64 at the same time
return CRC32IntrinImpl(data, dataSize);
#else
__get_cpuid(1, &cpuidData[0], &cpuidData[1], &cpuidData[2], &cpuidData[3]);
#endif
if (cpuidData[2] & (1 << 20)) { // bit_SSE4_2
return CRC32IntrinImpl(data, dataSize);
}
#endif // NO_CRC_INTRIN
return CRC32TableImpl(data, dataSize);
}
#if ((defined(__llvm__) && (defined(__x86_64__) || defined(__i386__))))
#pragma clang attribute pop
#elif ((defined(__GNUC__) && (defined(__x86_64__) || defined(__i386__))))
#pragma GCC pop_options
#else
#endif

File diff suppressed because it is too large Load Diff

216
mm/2s2h/SohGui.cpp Normal file
View File

@ -0,0 +1,216 @@
//
// SohGui.cpp
// soh
//
// Created by David Chavez on 24.08.22.
//
#include "SohGui.hpp"
#include <spdlog/spdlog.h>
#include <ImGui/imgui.h>
#define IMGUI_DEFINE_MATH_OPERATORS
#include <ImGui/imgui_internal.h>
#include <libultraship/libultraship.h>
#include <Fast3D/gfx_pc.h>
#ifdef __APPLE__
#include "graphic/Fast3D/gfx_metal.h"
#endif
#ifdef __SWITCH__
#include <port/switch/SwitchImpl.h>
#endif
//#include "UIWidgets.hpp"
#include "include/global.h"
#include "include/z64audio.h"
//#include "soh/SaveManager.h"
//#include "OTRGlobals.h"
//#include "soh/Enhancements/presets.h"
//#include "2s2h/resource/type/Skeleton.h"
#include "libultraship/libultraship.h"
//#ifdef ENABLE_CROWD_CONTROL
//#include "Enhancements/crowd-control/CrowdControl.h"
//#endif
//#include "Enhancements/game-interactor/GameInteractor.h"
//#include "Enhancements/cosmetics/authenticGfxPatches.h"
bool ShouldClearTextureCacheAtEndOfFrame = false;
bool isBetaQuestEnabled = false;
extern "C" {
void enableBetaQuest() { isBetaQuestEnabled = true; }
void disableBetaQuest() { isBetaQuestEnabled = false; }
}
namespace SohGui {
// MARK: - Properties
static const char* chestSizeAndTextureMatchesContentsOptions[4] = { "Disabled", "Both", "Texture Only", "Size Only" };
static const char* bunnyHoodOptions[3] = { "Disabled", "Faster Run & Longer Jump", "Faster Run" };
static const char* allPowers[9] = {
"Vanilla (1x)",
"Double (2x)",
"Quadruple (4x)",
"Octuple (8x)",
"Foolish (16x)",
"Ridiculous (32x)",
"Merciless (64x)",
"Pure Torture (128x)",
"OHKO (256x)" };
static const char* subPowers[8] = { allPowers[0], allPowers[1], allPowers[2], allPowers[3], allPowers[4], allPowers[5], allPowers[6], allPowers[7] };
static const char* subSubPowers[7] = { allPowers[0], allPowers[1], allPowers[2], allPowers[3], allPowers[4], allPowers[5], allPowers[6] };
static const char* zFightingOptions[3] = { "Disabled", "Consistent Vanish", "No Vanish" };
static const char* autosaveLabels[6] = { "Off", "New Location + Major Item", "New Location + Any Item", "New Location", "Major Item", "Any Item" };
static const char* FastFileSelect[5] = { "File N.1", "File N.2", "File N.3", "Zelda Map Select (require OoT Debug Mode)", "File select" };
static const char* bonkDamageValues[8] = {
"No Damage",
"0.25 Heart",
"0.5 Heart",
"1 Heart",
"2 Hearts",
"4 Hearts",
"8 Hearts",
"OHKO"
};
static const inline std::vector<std::pair<const char*, const char*>> audioBackends = {
#ifdef _WIN32
{ "wasapi", "Windows Audio Session API" },
#endif
#if defined(__linux)
{ "pulse", "PulseAudio" },
#endif
{ "sdl", "SDL Audio" }
};
// MARK: - Helpers
std::string GetWindowButtonText(const char* text, bool menuOpen) {
char buttonText[100] = "";
if (menuOpen) {
strcat(buttonText, ICON_FA_CHEVRON_RIGHT " ");
}
strcat(buttonText, text);
if (!menuOpen) { strcat(buttonText, " "); }
return buttonText;
}
// MARK: - Delegates
std::shared_ptr<SohMenuBar> mSohMenuBar;
std::shared_ptr<LUS::GuiWindow> mConsoleWindow;
std::shared_ptr<LUS::GuiWindow> mStatsWindow;
std::shared_ptr<LUS::GuiWindow> mInputEditorWindow;
std::shared_ptr<LUS::GuiWindow> mGfxDebuggerWindow;
//std::shared_ptr<AudioEditor> mAudioEditorWindow;
//std::shared_ptr<GameControlEditor::GameControlEditorWindow> mGameControlEditorWindow;
//std::shared_ptr<CosmeticsEditorWindow> mCosmeticsEditorWindow;
//std::shared_ptr<ActorViewerWindow> mActorViewerWindow;
//std::shared_ptr<ColViewerWindow> mColViewerWindow;
//std::shared_ptr<SaveEditorWindow> mSaveEditorWindow;
//std::shared_ptr<DLViewerWindow> mDLViewerWindow;
//std::shared_ptr<GameplayStatsWindow> mGameplayStatsWindow;
//std::shared_ptr<CheckTracker::CheckTrackerSettingsWindow> mCheckTrackerSettingsWindow;
//std::shared_ptr<CheckTracker::CheckTrackerWindow> mCheckTrackerWindow;
//std::shared_ptr<EntranceTrackerWindow> mEntranceTrackerWindow;
//std::shared_ptr<ItemTrackerSettingsWindow> mItemTrackerSettingsWindow;
//std::shared_ptr<ItemTrackerWindow> mItemTrackerWindow;
//std::shared_ptr<RandomizerSettingsWindow> mRandomizerSettingsWindow;
void SetupGuiElements() {
auto gui = LUS::Context::GetInstance()->GetWindow()->GetGui();
mSohMenuBar = std::make_shared<SohMenuBar>("gOpenMenuBar", CVarGetInteger("gOpenMenuBar", 0));
gui->SetMenuBar(std::reinterpret_pointer_cast<LUS::GuiMenuBar>(mSohMenuBar));
if (gui->GetMenuBar() && !gui->GetMenuBar()->IsVisible()) {
#if defined(__SWITCH__) || defined(__WIIU__)
gui->GetGameOverlay()->TextDrawNotification(30.0f, true, "Press - to access enhancements menu");
#else
gui->GetGameOverlay()->TextDrawNotification(30.0f, true, "Press F1 to access enhancements menu");
#endif
}
mStatsWindow = gui->GetGuiWindow("Stats");
if (mStatsWindow == nullptr) {
SPDLOG_ERROR("Could not find stats window");
}
mConsoleWindow = gui->GetGuiWindow("Console");
if (mConsoleWindow == nullptr) {
SPDLOG_ERROR("Could not find console window");
}
mInputEditorWindow = gui->GetGuiWindow("Input Editor");
if (mInputEditorWindow == nullptr) {
SPDLOG_ERROR("Could not find input editor window");
}
mGfxDebuggerWindow = gui->GetGuiWindow("GfxDebuggerWindow");
if (mGfxDebuggerWindow == nullptr) {
SPDLOG_ERROR("Could not find input GfxDebuggerWindow");
}
/*
mAudioEditorWindow = std::make_shared<AudioEditor>("gAudioEditor.WindowOpen", "Audio Editor");
gui->AddGuiWindow(mAudioEditorWindow);
mGameControlEditorWindow = std::make_shared<GameControlEditor::GameControlEditorWindow>("gGameControlEditorEnabled", "Game Control Editor");
gui->AddGuiWindow(mGameControlEditorWindow);
mCosmeticsEditorWindow = std::make_shared<CosmeticsEditorWindow>("gCosmeticsEditorEnabled", "Cosmetics Editor");
gui->AddGuiWindow(mCosmeticsEditorWindow);
mActorViewerWindow = std::make_shared<ActorViewerWindow>("gActorViewerEnabled", "Actor Viewer");
gui->AddGuiWindow(mActorViewerWindow);
mColViewerWindow = std::make_shared<ColViewerWindow>("gCollisionViewerEnabled", "Collision Viewer");
gui->AddGuiWindow(mColViewerWindow);
mSaveEditorWindow = std::make_shared<SaveEditorWindow>("gSaveEditorEnabled", "Save Editor");
gui->AddGuiWindow(mSaveEditorWindow);
mDLViewerWindow = std::make_shared<DLViewerWindow>("gDLViewerEnabled", "Display List Viewer");
gui->AddGuiWindow(mDLViewerWindow);
mGameplayStatsWindow = std::make_shared<GameplayStatsWindow>("gGameplayStatsEnabled", "Gameplay Stats");
gui->AddGuiWindow(mGameplayStatsWindow);
mCheckTrackerWindow = std::make_shared<CheckTracker::CheckTrackerWindow>("gCheckTrackerEnabled", "Check Tracker");
gui->AddGuiWindow(mCheckTrackerWindow);
mCheckTrackerSettingsWindow = std::make_shared<CheckTracker::CheckTrackerSettingsWindow>("gCheckTrackerSettingsEnabled", "Check Tracker Settings");
gui->AddGuiWindow(mCheckTrackerSettingsWindow);
mEntranceTrackerWindow = std::make_shared<EntranceTrackerWindow>("gEntranceTrackerEnabled","Entrance Tracker");
gui->AddGuiWindow(mEntranceTrackerWindow);
mItemTrackerWindow = std::make_shared<ItemTrackerWindow>("gItemTrackerEnabled", "Item Tracker");
gui->AddGuiWindow(mItemTrackerWindow);
mItemTrackerSettingsWindow = std::make_shared<ItemTrackerSettingsWindow>("gItemTrackerSettingsEnabled", "Item Tracker Settings");
gui->AddGuiWindow(mItemTrackerSettingsWindow);
mRandomizerSettingsWindow = std::make_shared<RandomizerSettingsWindow>("gRandomizerSettingsEnabled", "Randomizer Settings");
gui->AddGuiWindow(mRandomizerSettingsWindow);
*/
}
void Destroy() {
//mRandomizerSettingsWindow = nullptr;
//mItemTrackerWindow = nullptr;
//mItemTrackerSettingsWindow = nullptr;
//mEntranceTrackerWindow = nullptr;
//mCheckTrackerWindow = nullptr;
//mCheckTrackerSettingsWindow = nullptr;
//mGameplayStatsWindow = nullptr;
//mDLViewerWindow = nullptr;
//mSaveEditorWindow = nullptr;
//mColViewerWindow = nullptr;
//mActorViewerWindow = nullptr;
//mCosmeticsEditorWindow = nullptr;
//mGameControlEditorWindow = nullptr;
//mAudioEditorWindow = nullptr;
//mInputEditorWindow = nullptr;
mStatsWindow = nullptr;
mConsoleWindow = nullptr;
mSohMenuBar = nullptr;
}
}

42
mm/2s2h/SohGui.hpp Normal file
View File

@ -0,0 +1,42 @@
//
// SohGui.hpp
// soh
//
// Created by David Chavez on 24.08.22.
//
#ifndef SohGui_hpp
#define SohGui_hpp
#include <stdio.h>
#include "SohMenuBar.h"
//#include "Enhancements/audio/AudioEditor.h"
//#include "Enhancements/controls/GameControlEditor.h"
//#include "Enhancements/cosmetics/CosmeticsEditor.h"
//#include "Enhancements/debugger/actorViewer.h"
//#include "Enhancements/debugger/colViewer.h"
//#include "Enhancements/debugger/debugSaveEditor.h"
//#include "Enhancements/debugger/dlViewer.h"
//#include "Enhancements/gameplaystatswindow.h"
//#include "Enhancements/randomizer/randomizer_check_tracker.h"
//#include "Enhancements/randomizer/randomizer_entrance_tracker.h"
//#include "Enhancements/randomizer/randomizer_item_tracker.h"
//#include "Enhancements/randomizer/randomizer_settings_window.h"
#ifdef __cplusplus
extern "C" {
#endif
void enableBetaQuest();
void disableBetaQuest();
#ifdef __cplusplus
}
#endif
namespace SohGui {
void SetupHooks();
void SetupGuiElements();
void Draw();
void Destroy();
}
#endif /* SohGui_hpp */

574
mm/2s2h/SohMenuBar.cpp Normal file
View File

@ -0,0 +1,574 @@
#include "SohMenuBar.h"
#include "ImGui/imgui.h"
#include "public/bridge/consolevariablebridge.h"
#include <libultraship/libultraship.h>
#include "UIWidgets.hpp"
//#include "include/z64audio.h"
//#include "OTRGlobals.h"
#include "z64.h"
//#include "Enhancements/game-interactor/GameInteractor.h"
//#include "soh/Enhancements/presets.h"
//#include "soh/Enhancements/mods.h"
//#include "Enhancements/cosmetics/authenticGfxPatches.h"
#ifdef ENABLE_CROWD_CONTROL
#include "Enhancements/crowd-control/CrowdControl.h"
#endif
//#include "Enhancements/audio/AudioEditor.h"
//#include "Enhancements/controls/GameControlEditor.h"
//#include "Enhancements/cosmetics/CosmeticsEditor.h"
//#include "Enhancements/debugger/actorViewer.h"
//#include "Enhancements/debugger/colViewer.h"
//#include "Enhancements/debugger/debugSaveEditor.h"
//#include "Enhancements/debugger/dlViewer.h"
//#include "Enhancements/gameplaystatswindow.h"
//#include "Enhancements/randomizer/randomizer_check_tracker.h"
//#include "Enhancements/randomizer/randomizer_entrance_tracker.h"
//#include "Enhancements/randomizer/randomizer_item_tracker.h"
//#include "Enhancements/randomizer/randomizer_settings_window.h"
extern bool ShouldClearTextureCacheAtEndOfFrame;
extern bool isBetaQuestEnabled;
extern "C" PlayState* gPlayState;
enum SeqPlayers {
/* 0 */ SEQ_BGM_MAIN,
/* 1 */ SEQ_FANFARE,
/* 2 */ SEQ_SFX,
/* 3 */ SEQ_BGM_SUB,
/* 4 */ SEQ_MAX
};
std::string GetWindowButtonText(const char* text, bool menuOpen) {
char buttonText[100] = "";
if (menuOpen) {
strcat(buttonText, ICON_FA_CHEVRON_RIGHT " ");
}
strcat(buttonText, text);
if (!menuOpen) { strcat(buttonText, " "); }
return buttonText;
}
static const char* filters[3] = {
#ifdef __WIIU__
"",
#else
"Three-Point",
#endif
"Linear", "None"
};
static const char* chestStyleMatchesContentsOptions[4] = { "Disabled", "Both", "Texture Only", "Size Only" };
static const char* bunnyHoodOptions[3] = { "Disabled", "Faster Run & Longer Jump", "Faster Run" };
static const char* mirroredWorldModes[9] = {
"Disabled", "Always", "Random", "Random (Seeded)", "Dungeons",
"Dungeons (Vanilla)", "Dungeons (MQ)", "Dungeons Random", "Dungeons Random (Seeded)",
};
static const char* enemyRandomizerModes[3] = { "Disabled", "Random", "Random (Seeded)" };
static const char* allPowers[9] = {
"Vanilla (1x)",
"Double (2x)",
"Quadruple (4x)",
"Octuple (8x)",
"Foolish (16x)",
"Ridiculous (32x)",
"Merciless (64x)",
"Pure Torture (128x)",
"OHKO (256x)" };
static const char* subPowers[8] = { allPowers[0], allPowers[1], allPowers[2], allPowers[3], allPowers[4], allPowers[5], allPowers[6], allPowers[7] };
static const char* subSubPowers[7] = { allPowers[0], allPowers[1], allPowers[2], allPowers[3], allPowers[4], allPowers[5], allPowers[6] };
static const char* zFightingOptions[3] = { "Disabled", "Consistent Vanish", "No Vanish" };
static const char* autosaveLabels[6] = { "Off", "New Location + Major Item", "New Location + Any Item", "New Location", "Major Item", "Any Item" };
static const char* DebugSaveFileModes[3] = { "Off", "Vanilla", "Maxed" };
static const char* FastFileSelect[5] = { "File N.1", "File N.2", "File N.3", "Zelda Map Select (require OoT Debug Mode)", "File select" };
static const char* DekuStickCheat[3] = { "Normal", "Unbreakable", "Unbreakable + Always on Fire" };
static const char* bonkDamageValues[8] = {
"No Damage",
"0.25 Heart",
"0.5 Heart",
"1 Heart",
"2 Hearts",
"4 Hearts",
"8 Hearts",
"OHKO"
};
static const char* timeTravelOptions[3] = { "Disabled", "Ocarina of Time", "Any Ocarina" };
extern "C" SaveContext gSaveContext;
namespace SohGui {
void DrawMenuBarIcon() {
static bool gameIconLoaded = false;
if (!gameIconLoaded) {
LUS::Context::GetInstance()->GetWindow()->GetGui()->LoadTexture("Game_Icon", "textures/icons/gIcon.png");
gameIconLoaded = true;
}
if (LUS::Context::GetInstance()->GetWindow()->GetGui()->GetTextureByName("Game_Icon")) {
#ifdef __SWITCH__
ImVec2 iconSize = ImVec2(20.0f, 20.0f);
float posScale = 1.0f;
#elif defined(__WIIU__)
ImVec2 iconSize = ImVec2(16.0f * 2, 16.0f * 2);
float posScale = 2.0f;
#else
ImVec2 iconSize = ImVec2(16.0f, 16.0f);
float posScale = 1.0f;
#endif
ImGui::SetCursorPos(ImVec2(5, 2.5f) * posScale);
ImGui::Image(LUS::Context::GetInstance()->GetWindow()->GetGui()->GetTextureByName("Game_Icon"), iconSize);
ImGui::SameLine();
ImGui::SetCursorPos(ImVec2(25, 0) * posScale);
}
}
void DrawShipMenu() {
if (ImGui::BeginMenu("Ship")) {
if (ImGui::MenuItem("Hide Menu Bar",
#if !defined(__SWITCH__) && !defined(__WIIU__)
"F1"
#else
"[-]"
#endif
)) {
LUS::Context::GetInstance()->GetWindow()->GetGui()->GetMenuBar()->ToggleVisibility();
}
UIWidgets::Spacer(0);
#if !defined(__SWITCH__) && !defined(__WIIU__)
if (ImGui::MenuItem("Toggle Fullscreen", "F11")) {
LUS::Context::GetInstance()->GetWindow()->ToggleFullscreen();
}
UIWidgets::Spacer(0);
#endif
if (ImGui::MenuItem("Reset",
#ifdef __APPLE__
"Command-R"
#elif !defined(__SWITCH__) && !defined(__WIIU__)
"Ctrl+R"
#else
""
#endif
)) {
std::reinterpret_pointer_cast<LUS::ConsoleWindow>(
LUS::Context::GetInstance()->GetWindow()->GetGui()->GetGuiWindow("Console"))
->Dispatch("reset");
}
#if !defined(__SWITCH__) && !defined(__WIIU__)
UIWidgets::Spacer(0);
if (ImGui::MenuItem("Open App Files Folder")) {
std::string filesPath = LUS::Context::GetInstance()->GetAppDirectoryPath();
SDL_OpenURL(std::string("file:///" + std::filesystem::absolute(filesPath).string()).c_str());
}
UIWidgets::Spacer(0);
if (ImGui::MenuItem("Quit")) {
LUS::Context::GetInstance()->GetWindow()->Close();
}
#endif
ImGui::EndMenu();
}
}
extern std::shared_ptr<LUS::GuiWindow> mInputEditorWindow;
// extern std::shared_ptr<GameControlEditor::GameControlEditorWindow> mGameControlEditorWindow;
void DrawSettingsMenu() {
if (ImGui::BeginMenu("Settings")) {
if (ImGui::BeginMenu("Audio")) {
UIWidgets::PaddedEnhancementSliderFloat("Master Volume: %d %%", "##Master_Vol", "gGameMasterVolume", 0.0f,
1.0f, "", 1.0f, true, true, false, true);
if (UIWidgets::PaddedEnhancementSliderFloat("Main Music Volume: %d %%", "##Main_Music_Vol",
"gMainMusicVolume", 0.0f, 1.0f, "", 1.0f, true, true, false,
true)) {
// Audio_SetGameVolume(SEQ_BGM_MAIN, CVarGetFloat("gMainMusicVolume", 1.0f));
}
if (UIWidgets::PaddedEnhancementSliderFloat("Sub Music Volume: %d %%", "##Sub_Music_Vol", "gSubMusicVolume",
0.0f, 1.0f, "", 1.0f, true, true, false, true)) {
// Audio_SetGameVolume(SEQ_BGM_SUB, CVarGetFloat("gSubMusicVolume", 1.0f));
}
if (UIWidgets::PaddedEnhancementSliderFloat("Sound Effects Volume: %d %%", "##Sound_Effect_Vol",
"gSFXMusicVolume", 0.0f, 1.0f, "", 1.0f, true, true, false,
true)) {
// Audio_SetGameVolume(SEQ_SFX, CVarGetFloat("gSFXMusicVolume", 1.0f));
}
if (UIWidgets::PaddedEnhancementSliderFloat("Fanfare Volume: %d %%", "##Fanfare_Vol", "gFanfareVolume",
0.0f, 1.0f, "", 1.0f, true, true, false, true)) {
// Audio_SetGameVolume(SEQ_FANFARE, CVarGetFloat("gFanfareVolume", 1.0f));
}
static std::unordered_map<LUS::AudioBackend, const char*> audioBackendNames = {
{ LUS::AudioBackend::WASAPI, "Windows Audio Session API" },
{ LUS::AudioBackend::PULSE, "PulseAudio" },
{ LUS::AudioBackend::SDL, "SDL" },
};
ImGui::Text("Audio API (Needs reload)");
auto currentAudioBackend = LUS::Context::GetInstance()->GetAudio()->GetAudioBackend();
if (LUS::Context::GetInstance()->GetAudio()->GetAvailableAudioBackends()->size() <= 1) {
UIWidgets::DisableComponent(ImGui::GetStyle().Alpha * 0.5f);
}
if (ImGui::BeginCombo("##AApi", audioBackendNames[currentAudioBackend])) {
for (uint8_t i = 0; i < LUS::Context::GetInstance()->GetAudio()->GetAvailableAudioBackends()->size();
i++) {
auto backend = LUS::Context::GetInstance()->GetAudio()->GetAvailableAudioBackends()->data()[i];
if (ImGui::Selectable(audioBackendNames[backend], backend == currentAudioBackend)) {
LUS::Context::GetInstance()->GetAudio()->SetAudioBackend(backend);
}
}
ImGui::EndCombo();
}
if (LUS::Context::GetInstance()->GetAudio()->GetAvailableAudioBackends()->size() <= 1) {
UIWidgets::ReEnableComponent("");
}
ImGui::EndMenu();
}
UIWidgets::Spacer(0);
if (ImGui::BeginMenu("Controller")) {
//ImGui::PushStyleVar(ImGuiStyleVar_FramePadding, ImVec2(12.0f, 6.0f));
//ImGui::PushStyleVar(ImGuiStyleVar_ButtonTextAlign, ImVec2(0.0f, 0.0f));
//ImGui::PushStyleVar(ImGuiStyleVar_FrameBorderSize, 1.0f);
//ImGui::PushStyleColor(ImGuiCol_Border, ImVec4(0.22f, 0.38f, 0.56f, 1.0f));
if (mInputEditorWindow) {
if (ImGui::Button(
GetWindowButtonText("Controller Mapping", CVarGetInteger("gControllerConfigurationEnabled", 0))
.c_str(),
ImVec2(-1.0f, 0.0f))) {
mInputEditorWindow->ToggleVisibility();
}
}
// if (mGameControlEditorWindow) {
// if (ImGui::Button(GetWindowButtonText("Additional Controller Options",
// CVarGetInteger("gGameControlEditorEnabled", 0)).c_str(), ImVec2(-1.0f, 0.0f))) {
// mGameControlEditorWindow->ToggleVisibility();
//}
ImGui::EndMenu();
}
UIWidgets::PaddedSeparator();
//ImGui::PopStyleColor(1);
//ImGui::PopStyleVar(3);
#ifndef __SWITCH__
UIWidgets::EnhancementCheckbox("Menubar Controller Navigation", "gControlNav");
UIWidgets::Tooltip("Allows controller navigation of the SOH menu bar (Settings, Enhancements,...)\nCAUTION: "
"This will disable game inputs while the menubar is visible.\n\nD-pad to move between "
"items, A to select, and X to grab focus on the menu bar");
#endif
UIWidgets::PaddedEnhancementCheckbox("Show Inputs", "gInputEnabled", true, false);
UIWidgets::Tooltip("Shows currently pressed inputs on the bottom right of the screen");
UIWidgets::PaddedEnhancementSliderFloat("Input Scale: %.1f", "##Input", "gInputScale", 1.0f, 3.0f, "", 1.0f,
false, true, true, false);
UIWidgets::Tooltip("Sets the on screen size of the displayed inputs from the Show Inputs setting");
UIWidgets::PaddedEnhancementSliderInt("Simulated Input Lag: %d frames", "##SimulatedInputLag",
"gSimulatedInputLag", 0, 6, "", 0, true, true, false);
UIWidgets::Tooltip("Buffers your inputs to be executed a specified amount of frames later");
ImGui::EndMenu();
}
UIWidgets::Spacer(0);
if (ImGui::BeginMenu("Graphics")) {
#ifndef __APPLE__
if (UIWidgets::EnhancementSliderFloat("Internal Resolution: %d %%", "##IMul", "gInternalResolution", 0.5f, 2.0f,
"", 1.0f, true)) {
LUS::Context::GetInstance()->GetWindow()->SetResolutionMultiplier(CVarGetFloat("gInternalResolution", 1));
};
UIWidgets::Tooltip("Multiplies your output resolution by the value inputted, as a more intensive but effective "
"form of anti-aliasing");
#endif
#ifndef __WIIU__
if (UIWidgets::PaddedEnhancementSliderInt("MSAA: %d", "##IMSAA", "gMSAAValue", 1, 8, "", 1, true, true,
false)) {
LUS::Context::GetInstance()->GetWindow()->SetMsaaLevel(CVarGetInteger("gMSAAValue", 1));
};
UIWidgets::Tooltip("Activates multi-sample anti-aliasing when above 1x up to 8x for 8 samples for every pixel");
#endif
{ // FPS Slider
const int minFps = 20;
static int maxFps;
if (LUS::Context::GetInstance()->GetWindow()->GetWindowBackend() == LUS::WindowBackend::DX11) {
maxFps = 360;
} else {
maxFps = LUS::Context::GetInstance()->GetWindow()->GetCurrentRefreshRate();
}
// int currentFps = fmax(fmin(OTRGlobals::Instance->GetInterpolationFPS(), maxFps), minFps);
int currentFps = 20;
bool matchingRefreshRate =
CVarGetInteger("gMatchRefreshRate", 0) &&
LUS::Context::GetInstance()->GetWindow()->GetWindowBackend() != LUS::WindowBackend::DX11;
UIWidgets::PaddedEnhancementSliderInt((currentFps == 20) ? "FPS: Original (20)" : "FPS: %d",
"##FPSInterpolation", "gInterpolationFPS", minFps, maxFps, "", 20,
true, true, false, matchingRefreshRate);
if (LUS::Context::GetInstance()->GetWindow()->GetWindowBackend() == LUS::WindowBackend::DX11) {
UIWidgets::Tooltip(
"Uses Matrix Interpolation to create extra frames, resulting in smoother graphics. This is purely "
"visual and does not impact game logic, execution of glitches etc.\n\n"
"A higher target FPS than your monitor's refresh rate will waste resources, and might give a worse "
"result.");
} else {
UIWidgets::Tooltip(
"Uses Matrix Interpolation to create extra frames, resulting in smoother graphics. This is purely "
"visual and does not impact game logic, execution of glitches etc.");
}
} // END FPS Slider
if (LUS::Context::GetInstance()->GetWindow()->GetWindowBackend() == LUS::WindowBackend::DX11) {
UIWidgets::Spacer(0);
if (ImGui::Button("Match Refresh Rate")) {
int hz = LUS::Context::GetInstance()->GetWindow()->GetCurrentRefreshRate();
if (hz >= 20 && hz <= 360) {
CVarSetInteger("gInterpolationFPS", hz);
LUS::Context::GetInstance()->GetWindow()->GetGui()->SaveConsoleVariablesOnNextTick();
}
}
} else {
UIWidgets::PaddedEnhancementCheckbox("Match Refresh Rate", "gMatchRefreshRate", true, false);
}
UIWidgets::Tooltip("Matches interpolation value to the current game's window refresh rate");
if (LUS::Context::GetInstance()->GetWindow()->GetWindowBackend() == LUS::WindowBackend::DX11) {
UIWidgets::PaddedEnhancementSliderInt(
CVarGetInteger("gExtraLatencyThreshold", 80) == 0 ? "Jitter fix: Off" : "Jitter fix: >= %d FPS",
"##ExtraLatencyThreshold", "gExtraLatencyThreshold", 0, 360, "", 80, true, true, false);
UIWidgets::Tooltip("When Interpolation FPS setting is at least this threshold, add one frame of input lag "
"(e.g. 16.6 ms for 60 FPS) in order to avoid jitter. This setting allows the CPU to "
"work on one frame while GPU works on the previous frame.\nThis setting should be used "
"when your computer is too slow to do CPU + GPU work in time.");
}
UIWidgets::PaddedSeparator(true, true, 3.0f, 3.0f);
static std::unordered_map<LUS::WindowBackend, const char*> windowBackendNames = {
{ LUS::WindowBackend::DX11, "DirectX" },
{ LUS::WindowBackend::SDL_OPENGL, "OpenGL" },
{ LUS::WindowBackend::SDL_METAL, "Metal" },
{ LUS::WindowBackend::GX2, "GX2" }
};
ImGui::Text("Renderer API (Needs reload)");
LUS::WindowBackend runningWindowBackend = LUS::Context::GetInstance()->GetWindow()->GetWindowBackend();
LUS::WindowBackend configWindowBackend;
int configWindowBackendId = LUS::Context::GetInstance()->GetConfig()->GetInt("Window.Backend.Id", -1);
if (configWindowBackendId != -1 &&
configWindowBackendId < static_cast<int>(LUS::WindowBackend::BACKEND_COUNT)) {
configWindowBackend = static_cast<LUS::WindowBackend>(configWindowBackendId);
} else {
configWindowBackend = runningWindowBackend;
}
if (LUS::Context::GetInstance()->GetWindow()->GetAvailableWindowBackends()->size() <= 1) {
UIWidgets::DisableComponent(ImGui::GetStyle().Alpha * 0.5f);
}
if (ImGui::BeginCombo("##RApi", windowBackendNames[configWindowBackend])) {
for (size_t i = 0; i < LUS::Context::GetInstance()->GetWindow()->GetAvailableWindowBackends()->size();
i++) {
auto backend = LUS::Context::GetInstance()->GetWindow()->GetAvailableWindowBackends()->data()[i];
if (ImGui::Selectable(windowBackendNames[backend], backend == configWindowBackend)) {
LUS::Context::GetInstance()->GetConfig()->SetInt("Window.Backend.Id", static_cast<int>(backend));
LUS::Context::GetInstance()->GetConfig()->SetString("Window.Backend.Name",
windowBackendNames[backend]);
LUS::Context::GetInstance()->GetConfig()->Save();
}
}
ImGui::EndCombo();
}
if (LUS::Context::GetInstance()->GetWindow()->GetAvailableWindowBackends()->size() <= 1) {
UIWidgets::ReEnableComponent("");
}
if (LUS::Context::GetInstance()->GetWindow()->CanDisableVerticalSync()) {
UIWidgets::PaddedEnhancementCheckbox("Enable Vsync", "gVsyncEnabled", true, false);
}
if (LUS::Context::GetInstance()->GetWindow()->SupportsWindowedFullscreen()) {
UIWidgets::PaddedEnhancementCheckbox("Windowed fullscreen", "gSdlWindowedFullscreen", true, false);
}
if (LUS::Context::GetInstance()->GetWindow()->GetGui()->SupportsViewports()) {
UIWidgets::PaddedEnhancementCheckbox("Allow multi-windows", "gEnableMultiViewports", true, false, false, "",
UIWidgets::CheckboxGraphics::Cross, true);
UIWidgets::Tooltip("Allows windows to be able to be dragged off of the main game window. Requires a reload "
"to take effect.");
}
// If more filters are added to LUS, make sure to add them to the filters list here
ImGui::Text("Texture Filter (Needs reload)");
UIWidgets::EnhancementCombobox("gTextureFilter", filters, FILTER_THREE_POINT);
UIWidgets::Spacer(0);
LUS::Context::GetInstance()->GetWindow()->GetGui()->GetGameOverlay()->DrawSettings();
ImGui::EndMenu();
}
UIWidgets::Spacer(0);
if (ImGui::BeginMenu("Languages")) {
UIWidgets::PaddedEnhancementCheckbox("Translate Title Screen", "gTitleScreenTranslation");
if (UIWidgets::EnhancementRadioButton("English", "gLanguages", LANGUAGE_ENG)) {
// GameInteractor::Instance->ExecuteHooks<GameInteractor::OnSetGameLanguage>();
}
if (UIWidgets::EnhancementRadioButton("German", "gLanguages", LANGUAGE_GER)) {
// GameInteractor::Instance->ExecuteHooks<GameInteractor::OnSetGameLanguage>();
}
// if (UIWidgets::EnhancementRadioButton("French", "gLanguages", LANGUAGE_FRA)) {
// GameInteractor::Instance->ExecuteHooks<GameInteractor::OnSetGameLanguage>();
//}
ImGui::EndMenu();
}
UIWidgets::Spacer(0);
if (ImGui::BeginMenu("Accessibility")) {
#if defined(_WIN32) || defined(__APPLE__)
UIWidgets::PaddedEnhancementCheckbox("Text to Speech", "gA11yTTS");
UIWidgets::Tooltip("Enables text to speech for in game dialog");
#endif
UIWidgets::PaddedEnhancementCheckbox("Disable Idle Camera Re-Centering", "gA11yDisableIdleCam");
UIWidgets::Tooltip("Disables the automatic re-centering of the camera when idle.");
ImGui::EndMenu();
}
//ImGui::EndMenu();
}
extern std::shared_ptr<LUS::GuiWindow> mStatsWindow;
extern std::shared_ptr<LUS::GuiWindow> mConsoleWindow;
extern std::shared_ptr<LUS::GuiWindow> mGfxDebuggerWindow;
// extern std::shared_ptr<SaveEditorWindow> mSaveEditorWindow;
// extern std::shared_ptr<ColViewerWindow> mColViewerWindow;
// extern std::shared_ptr<ActorViewerWindow> mActorViewerWindow;
// extern std::shared_ptr<DLViewerWindow> mDLViewerWindow;
void DrawDeveloperToolsMenu() {
if (ImGui::BeginMenu("Developer Tools")) {
UIWidgets::EnhancementCheckbox("OoT Debug Mode", "gDebugEnabled");
UIWidgets::Tooltip("Enables Debug Mode, allowing you to select maps with L + R + Z, noclip with L + D-pad "
"Right, and open the debug menu with L on the pause screen");
if (CVarGetInteger("gDebugEnabled", 0)) {
ImGui::Text("Debug Save File Mode:");
UIWidgets::EnhancementCombobox("gDebugSaveFileMode", DebugSaveFileModes, 1);
UIWidgets::Tooltip("Changes the behaviour of debug file select creation (creating a save file on slot 1 "
"with debug mode on)\n"
"- Off: The debug save file will be a normal savefile\n"
"- Vanilla: The debug save file will be the debug save file from the original game\n"
"- Maxed: The debug save file will be a save file with all of the items & upgrades");
}
UIWidgets::PaddedEnhancementCheckbox("OoT Skulltula Debug", "gSkulltulaDebugEnabled", true, false);
UIWidgets::Tooltip("Enables Skulltula Debug, when moving the cursor in the menu above various map icons (boss "
"key, compass, map screen locations, etc) will set the GS bits in that area.\nUSE WITH "
"CAUTION AS IT DOES NOT UPDATE THE GS COUNT.");
UIWidgets::PaddedEnhancementCheckbox("Fast File Select", "gSkipLogoTitle", true, false);
UIWidgets::Tooltip(
"Load the game to the selected menu or file\n\"Zelda Map Select\" require debug mode else you will "
"fallback to File choose menu\nUsing a file number that don't have save will create a save file only if "
"you toggle on \"Create a new save if none ?\" else it will bring you to the File choose menu");
if (CVarGetInteger("gSkipLogoTitle", 0)) {
ImGui::Text("Loading:");
UIWidgets::EnhancementCombobox("gSaveFileID", FastFileSelect, 0);
};
UIWidgets::PaddedEnhancementCheckbox("Better Debug Warp Screen", "gBetterDebugWarpScreen", true, false);
UIWidgets::Tooltip("Optimized debug warp screen, with the added ability to chose entrances and time of day");
UIWidgets::PaddedEnhancementCheckbox("Debug Warp Screen Translation", "gDebugWarpScreenTranslation", true,
false, false, "", UIWidgets::CheckboxGraphics::Cross, true);
UIWidgets::Tooltip("Translate the Debug Warp Screen based on the game language");
UIWidgets::PaddedSeparator();
ImGui::PushStyleVar(ImGuiStyleVar_FramePadding, ImVec2(12.0f, 6.0f));
ImGui::PushStyleVar(ImGuiStyleVar_ButtonTextAlign, ImVec2(0, 0));
ImGui::PushStyleVar(ImGuiStyleVar_FrameBorderSize, 1.0f);
ImGui::PushStyleColor(ImGuiCol_Border, ImVec4(0.22f, 0.38f, 0.56f, 1.0f));
if (mStatsWindow) {
if (ImGui::Button(GetWindowButtonText("Stats", CVarGetInteger("gStatsEnabled", 0)).c_str(),
ImVec2(-1.0f, 0.0f))) {
mStatsWindow->ToggleVisibility();
}
UIWidgets::Tooltip("Shows the stats window, with your FPS and frametimes, and the OS you're playing on");
}
UIWidgets::Spacer(0);
if (mConsoleWindow) {
if (ImGui::Button(GetWindowButtonText("Console", CVarGetInteger("gConsoleEnabled", 0)).c_str(),
ImVec2(-1.0f, 0.0f))) {
mConsoleWindow->ToggleVisibility();
}
UIWidgets::Tooltip(
"Enables the console window, allowing you to input commands, type help for some examples");
}
UIWidgets::Spacer(0);
if (mGfxDebuggerWindow) {
if (ImGui::Button(GetWindowButtonText("Gfx Debugger", CVarGetInteger("gGfxDebuggerEnabled", 0)).c_str(),
ImVec2(-1.0f, 0.0f))) {
mGfxDebuggerWindow->ToggleVisibility();
}
UIWidgets::Tooltip(
"Enables the Gfx Debugger window, allowing you to input commands, type help for some examples");
}
UIWidgets::Spacer(0);
// if (mSaveEditorWindow) {
// if (ImGui::Button(GetWindowButtonText("Save Editor", CVarGetInteger("gSaveEditorEnabled", 0)).c_str(),
// ImVec2(-1.0f, 0.0f))) {
// //mSaveEditorWindow->ToggleVisibility();
// }
// }
// UIWidgets::Spacer(0);
// if (mColViewerWindow) {
// if (ImGui::Button(GetWindowButtonText("Collision Viewer", CVarGetInteger("gCollisionViewerEnabled",
// 0)).c_str(), ImVec2(-1.0f, 0.0f))) {
// //mColViewerWindow->ToggleVisibility();
// }
// }
// UIWidgets::Spacer(0);
// if (mActorViewerWindow) {
// if (ImGui::Button(GetWindowButtonText("Actor Viewer", CVarGetInteger("gActorViewerEnabled", 0)).c_str(),
// ImVec2(-1.0f, 0.0f))) {
// //mActorViewerWindow->ToggleVisibility();
// }
// }
// UIWidgets::Spacer(0);
// if (mDLViewerWindow) {
// if (ImGui::Button(GetWindowButtonText("Display List Viewer", CVarGetInteger("gDLViewerEnabled",
// 0)).c_str(), ImVec2(-1.0f, 0.0f))) {
// //mDLViewerWindow->ToggleVisibility();
// }
// }
ImGui::PopStyleVar(3);
ImGui::PopStyleColor(1);
ImGui::EndMenu();
}
}
void SohMenuBar::DrawElement() {
if (ImGui::BeginMenuBar()) {
static ImVec2 sWindowPadding(8.0f, 8.0f);
ImGui::PushStyleVar(ImGuiStyleVar_WindowPadding, sWindowPadding);
ImGui::SetCursorPosY(0.0f);
DrawSettingsMenu();
ImGui::SetCursorPosY(0.0f);
DrawDeveloperToolsMenu();
ImGui::SetCursorPosY(0.0f);
ImGui::PopStyleVar(1);
ImGui::EndMenuBar();
}
}
}
// namespace SohGui

16
mm/2s2h/SohMenuBar.h Normal file
View File

@ -0,0 +1,16 @@
#pragma once
//#include <libultraship/libultraship.h>
#include "window/gui/GuiMenuBar.h"
#include "window/gui/GuiElement.h"
namespace SohGui {
class SohMenuBar : public LUS::GuiMenuBar {
public:
using LUS::GuiMenuBar::GuiMenuBar;
protected:
void DrawElement() override;
void InitElement() override {};
void UpdateElement() override {};
};
} // namespace SohGui

716
mm/2s2h/UIWidgets.cpp Normal file
View File

@ -0,0 +1,716 @@
//
// UIWidgets.cpp
// soh
//
// Created by David Chavez on 25.08.22.
//
#include "UIWidgets.hpp"
#define IMGUI_DEFINE_MATH_OPERATORS
#include <ImGui/imgui_internal.h>
#include <libultraship/libultraship.h>
#include <libultraship/libultra/types.h>
//#include "soh/Enhancements/cosmetics/CosmeticsEditor.h"
namespace UIWidgets {
// MARK: - Layout Helper
// Automatically adds newlines to break up text longer than a specified number of characters
// Manually included newlines will still be respected and reset the line length
// If line is midword when it hits the limit, text should break at the last encountered space
char* WrappedText(const char* text, unsigned int charactersPerLine) {
std::string newText(text);
const size_t tipLength = newText.length();
int lastSpace = -1;
int currentLineLength = 0;
for (unsigned int currentCharacter = 0; currentCharacter < tipLength; currentCharacter++) {
if (newText[currentCharacter] == '\n') {
currentLineLength = 0;
lastSpace = -1;
continue;
} else if (newText[currentCharacter] == ' ') {
lastSpace = currentCharacter;
}
if ((currentLineLength >= charactersPerLine) && (lastSpace >= 0)) {
newText[lastSpace] = '\n';
currentLineLength = currentCharacter - lastSpace - 1;
lastSpace = -1;
}
currentLineLength++;
}
return strdup(newText.c_str());
}
char* WrappedText(const std::string& text, unsigned int charactersPerLine) {
return WrappedText(text.c_str(), charactersPerLine);
}
void SetLastItemHoverText(const std::string& text) {
if (ImGui::IsItemHovered()) {
ImGui::BeginTooltip();
ImGui::Text("%s", WrappedText(text, 60));
ImGui::EndTooltip();
}
}
void SetLastItemHoverText(const char* text) {
if (ImGui::IsItemHovered()) {
ImGui::BeginTooltip();
ImGui::Text("%s", WrappedText(text, 60));
ImGui::EndTooltip();
}
}
// Adds a "?" next to the previous ImGui item with a custom tooltip
void InsertHelpHoverText(const std::string& text) {
ImGui::SameLine();
ImGui::TextColored(ImVec4(0.7f, 0.7f, 0.7f, 1.0f), "?");
if (ImGui::IsItemHovered()) {
ImGui::BeginTooltip();
ImGui::Text("%s", WrappedText(text, 60));
ImGui::EndTooltip();
}
}
void InsertHelpHoverText(const char* text) {
ImGui::SameLine();
ImGui::TextColored(ImVec4(0.7f, 0.7f, 0.7f, 1.0f), "?");
if (ImGui::IsItemHovered()) {
ImGui::BeginTooltip();
ImGui::Text("%s", WrappedText(text, 60));
ImGui::EndTooltip();
}
}
// MARK: - UI Elements
void Tooltip(const char* text) {
if (ImGui::IsItemHovered()) {
ImGui::SetTooltip("%s", WrappedText(text));
}
}
void Spacer(float height) {
ImGui::Dummy(ImVec2(0.0f, height));
}
void PaddedSeparator(bool padTop, bool padBottom, float extraVerticalTopPadding, float extraVerticalBottomPadding) {
if (padTop) {
Spacer(extraVerticalTopPadding);
}
ImGui::Separator();
if (padBottom) {
Spacer(extraVerticalBottomPadding);
}
}
void RenderCross(ImDrawList* draw_list, ImVec2 pos, ImU32 col, float sz) {
float thickness = ImMax(sz / 5.0f, 1.0f);
sz -= thickness * 0.5f;
pos += ImVec2(thickness * 0.25f, thickness * 0.25f);
draw_list->PathLineTo(ImVec2(pos.x, pos.y));
draw_list->PathLineTo(ImVec2(pos.x + sz, pos.y + sz));
draw_list->PathStroke(col, 0, thickness);
draw_list->PathLineTo(ImVec2(pos.x + sz, pos.y));
draw_list->PathLineTo(ImVec2(pos.x, pos.y + sz));
draw_list->PathStroke(col, 0, thickness);
}
bool CustomCheckbox(const char* label, bool* v, bool disabled, CheckboxGraphics disabledGraphic) {
ImGuiWindow* window = ImGui::GetCurrentWindow();
if (window->SkipItems) {
return false;
}
ImGuiContext& g = *GImGui;
const ImGuiStyle& style = g.Style;
const ImGuiID id = window->GetID(label);
const ImVec2 label_size = ImGui::CalcTextSize(label, NULL, true);
const float square_sz = ImGui::GetFrameHeight();
const ImVec2 pos = window->DC.CursorPos;
const ImRect total_bb(pos, pos + ImVec2(square_sz + (label_size.x > 0.0f ? style.ItemInnerSpacing.x + label_size.x : 0.0f), label_size.y + style.FramePadding.y * 2.0f));
ImGui::ItemSize(total_bb, style.FramePadding.y);
if (!ImGui::ItemAdd(total_bb, id)) {
IMGUI_TEST_ENGINE_ITEM_INFO(id, label, g.LastItemData.StatusFlags | ImGuiItemStatusFlags_Checkable | (*v ? ImGuiItemStatusFlags_Checked : 0));
return false;
}
bool hovered, held;
bool pressed = ImGui::ButtonBehavior(total_bb, id, &hovered, &held);
if (pressed) {
*v = !(*v);
ImGui::MarkItemEdited(id);
}
const ImRect check_bb(pos, pos + ImVec2(square_sz, square_sz));
ImGui::RenderNavHighlight(total_bb, id);
ImGui::RenderFrame(check_bb.Min, check_bb.Max, ImGui::GetColorU32((held && hovered) ? ImGuiCol_FrameBgActive : hovered ? ImGuiCol_FrameBgHovered : ImGuiCol_FrameBg), true, style.FrameRounding);
ImU32 check_col = ImGui::GetColorU32(ImGuiCol_CheckMark);
ImU32 cross_col = ImGui::GetColorU32(ImVec4(0.50f, 0.50f, 0.50f, 1.00f));
bool mixed_value = (g.LastItemData.InFlags & ImGuiItemFlags_MixedValue) != 0;
if (mixed_value) {
// Undocumented tristate/mixed/indeterminate checkbox (#2644)
// This may seem awkwardly designed because the aim is to make ImGuiItemFlags_MixedValue supported by all widgets (not just checkbox)
ImVec2 pad(ImMax(1.0f, IM_FLOOR(square_sz / 3.6f)), ImMax(1.0f, IM_FLOOR(square_sz / 3.6f)));
window->DrawList->AddRectFilled(check_bb.Min + pad, check_bb.Max - pad, check_col, style.FrameRounding);
} else if ((!disabled && *v) || (disabled && disabledGraphic == CheckboxGraphics::Checkmark)) {
const float pad = ImMax(1.0f, IM_FLOOR(square_sz / 6.0f));
ImGui::RenderCheckMark(window->DrawList, check_bb.Min + ImVec2(pad, pad), check_col, square_sz - pad * 2.0f);
} else if (disabled && disabledGraphic == CheckboxGraphics::Cross) {
const float pad = ImMax(1.0f, IM_FLOOR(square_sz / 6.0f));
RenderCross(window->DrawList, check_bb.Min + ImVec2(pad, pad), cross_col, square_sz - pad * 2.0f);
}
ImVec2 label_pos = ImVec2(check_bb.Max.x + style.ItemInnerSpacing.x, check_bb.Min.y + style.FramePadding.y);
if (g.LogEnabled) {
ImGui::LogRenderedText(&label_pos, mixed_value ? "[~]" : *v ? "[x]" : "[ ]");
}
if (label_size.x > 0.0f) {
ImGui::RenderText(label_pos, label);
}
IMGUI_TEST_ENGINE_ITEM_INFO(id, label, g.LastItemData.StatusFlags | ImGuiItemStatusFlags_Checkable | (*v ? ImGuiItemStatusFlags_Checked : 0));
return pressed;
}
void ReEnableComponent(const char* disabledTooltipText) {
// End of disable region of previous component
ImGui::PopStyleVar(1);
if (ImGui::IsItemHovered(ImGuiHoveredFlags_AllowWhenDisabled) && strcmp(disabledTooltipText, "") != 0) {
ImGui::SetTooltip("%s", disabledTooltipText);
}
ImGui::PopItemFlag();
}
void DisableComponent(const float alpha) {
ImGui::PushItemFlag(ImGuiItemFlags_Disabled, true);
ImGui::PushStyleVar(ImGuiStyleVar_Alpha, alpha);
}
bool EnhancementCheckbox(const char* text, const char* cvarName, bool disabled, const char* disabledTooltipText, CheckboxGraphics disabledGraphic, bool defaultValue) {
bool changed = false;
if (disabled) {
DisableComponent(ImGui::GetStyle().Alpha * 0.5f);
}
bool val = (bool)CVarGetInteger(cvarName, defaultValue);
if (CustomCheckbox(text, &val, disabled, disabledGraphic)) {
CVarSetInteger(cvarName, val);
LUS::Context::GetInstance()->GetWindow()->GetGui()->SaveConsoleVariablesOnNextTick();
changed = true;
}
if (disabled) {
ReEnableComponent(disabledTooltipText);
}
return changed;
}
bool PaddedEnhancementCheckbox(const char* text, const char* cvarName, bool padTop, bool padBottom, bool disabled, const char* disabledTooltipText, CheckboxGraphics disabledGraphic, bool defaultValue) {
ImGui::BeginGroup();
if (padTop) Spacer(0);
bool changed = EnhancementCheckbox(text, cvarName, disabled, disabledTooltipText, disabledGraphic, defaultValue);
if (padBottom) Spacer(0);
ImGui::EndGroup();
return changed;
}
bool EnhancementCombobox(const char* cvarName, std::span<const char*, std::dynamic_extent> comboArray, uint8_t defaultIndex, bool disabled, const char* disabledTooltipText, uint8_t disabledValue) {
bool changed = false;
if (defaultIndex <= 0) {
defaultIndex = 0;
}
if (disabled) {
DisableComponent(ImGui::GetStyle().Alpha * 0.5f);
}
uint8_t selected = CVarGetInteger(cvarName, defaultIndex);
std::string comboName = std::string("##") + std::string(cvarName);
if (ImGui::BeginCombo(comboName.c_str(), comboArray[selected])) {
for (uint8_t i = 0; i < comboArray.size(); i++) {
if (strlen(comboArray[i]) > 0) {
if (ImGui::Selectable(comboArray[i], i == selected)) {
CVarSetInteger(cvarName, i);
selected = i;
changed = true;
LUS::Context::GetInstance()->GetWindow()->GetGui()->SaveConsoleVariablesOnNextTick();
}
}
}
ImGui::EndCombo();
}
if (disabled) {
ReEnableComponent(disabledTooltipText);
if (disabledValue >= 0 && selected != disabledValue) {
CVarSetInteger(cvarName, disabledValue);
changed = true;
LUS::Context::GetInstance()->GetWindow()->GetGui()->SaveConsoleVariablesOnNextTick();
}
}
return changed;
}
bool LabeledRightAlignedEnhancementCombobox(const char* label, const char* cvarName, std::span<const char*, std::dynamic_extent> comboArray, uint8_t defaultIndex, bool disabled, const char* disabledTooltipText, uint8_t disabledValue) {
ImGui::Text("%s", label);
s32 currentValue = CVarGetInteger(cvarName, defaultIndex);
#ifdef __WIIU__
ImGui::SameLine(ImGui::GetContentRegionAvail().x - (ImGui::CalcTextSize(comboArray[currentValue]).x + 40.0f));
ImGui::PushItemWidth(ImGui::CalcTextSize(comboArray[currentValue]).x + 60.0f);
#else
ImGui::SameLine(ImGui::GetContentRegionAvail().x - (ImGui::CalcTextSize(comboArray[currentValue]).x + 20.0f));
ImGui::PushItemWidth(ImGui::CalcTextSize(comboArray[currentValue]).x + 30.0f);
#endif
bool changed = EnhancementCombobox(cvarName, comboArray, defaultIndex, disabled, disabledTooltipText, disabledValue);
ImGui::PopItemWidth();
return changed;
}
void PaddedText(const char* text, bool padTop, bool padBottom) {
if (padTop) Spacer(0);
ImGui::Text("%s", text);
if (padBottom) Spacer(0);
}
bool EnhancementSliderInt(const char* text, const char* id, const char* cvarName, int min, int max, const char* format, int defaultValue, bool PlusMinusButton, bool disabled, const char* disabledTooltipText) {
bool changed = false;
int val = CVarGetInteger(cvarName, defaultValue);
if (disabled) {
DisableComponent(ImGui::GetStyle().Alpha * 0.5f);
}
ImGui::Text(text, val);
Spacer(0);
ImGui::BeginGroup();
if (PlusMinusButton) {
std::string MinusBTNName = " - ##" + std::string(cvarName);
if (ImGui::Button(MinusBTNName.c_str())) {
val--;
changed = true;
}
ImGui::SameLine();
ImGui::SetCursorPosX(ImGui::GetCursorPosX() - 7.0f);
}
ImGui::PushItemWidth(std::min((ImGui::GetContentRegionAvail().x - (PlusMinusButton ? sliderButtonWidth : 0.0f)), maxSliderWidth));
if (ImGui::SliderInt(id, &val, min, max, format, ImGuiSliderFlags_AlwaysClamp))
{
changed = true;
}
ImGui::PopItemWidth();
if (PlusMinusButton) {
std::string PlusBTNName = " + ##" + std::string(cvarName);
ImGui::SameLine();
ImGui::SetCursorPosX(ImGui::GetCursorPosX() - 7.0f);
if (ImGui::Button(PlusBTNName.c_str())) {
val++;
changed = true;
}
}
ImGui::EndGroup();
if (disabled) {
ReEnableComponent(disabledTooltipText);
}
if (val < min) {
val = min;
changed = true;
}
if (val > max) {
val = max;
changed = true;
}
if (changed) {
CVarSetInteger(cvarName, val);
LUS::Context::GetInstance()->GetWindow()->GetGui()->SaveConsoleVariablesOnNextTick();
}
return changed;
}
bool EnhancementSliderFloat(const char* text, const char* id, const char* cvarName, float min, float max, const char* format, float defaultValue, bool isPercentage, bool PlusMinusButton, bool disabled, const char* disabledTooltipText) {
bool changed = false;
float val = CVarGetFloat(cvarName, defaultValue);
if (disabled) {
DisableComponent(ImGui::GetStyle().Alpha * 0.5f);
}
if (!isPercentage) {
ImGui::Text(text, val);
} else {
ImGui::Text(text, static_cast<int>(100 * val));
}
Spacer(0);
ImGui::BeginGroup();
if (PlusMinusButton) {
std::string MinusBTNName = " - ##" + std::string(cvarName);
if (ImGui::Button(MinusBTNName.c_str())) {
if (isPercentage) {
val -= 0.01f;
} else {
val -= 0.1f;
}
changed = true;
}
ImGui::SameLine();
ImGui::SetCursorPosX(ImGui::GetCursorPosX() - 7.0f);
}
ImGui::PushItemWidth(std::min((ImGui::GetContentRegionAvail().x - (PlusMinusButton ? sliderButtonWidth : 0.0f)), maxSliderWidth));
if (ImGui::SliderFloat(id, &val, min, max, format, ImGuiSliderFlags_AlwaysClamp)) {
if (isPercentage) {
val = roundf(val * 100) / 100;
}
changed = true;
}
ImGui::PopItemWidth();
if (PlusMinusButton) {
std::string PlusBTNName = " + ##" + std::string(cvarName);
ImGui::SameLine();
ImGui::SetCursorPosX(ImGui::GetCursorPosX() - 7.0f);
if (ImGui::Button(PlusBTNName.c_str())) {
if (isPercentage) {
val += 0.01f;
} else {
val += 0.1f;
}
changed = true;
}
}
ImGui::EndGroup();
if (disabled) {
ReEnableComponent(disabledTooltipText);
}
if (val < min) {
val = min;
changed = true;
}
if (val > max) {
val = max;
changed = true;
}
if (changed) {
CVarSetFloat(cvarName, val);
LUS::Context::GetInstance()->GetWindow()->GetGui()->SaveConsoleVariablesOnNextTick();
}
return changed;
}
bool PaddedEnhancementSliderInt(const char* text, const char* id, const char* cvarName, int min, int max, const char* format, int defaultValue, bool PlusMinusButton, bool padTop, bool padBottom, bool disabled, const char* disabledTooltipText) {
bool changed = false;
ImGui::BeginGroup();
if (padTop) Spacer(0);
changed = EnhancementSliderInt(text, id, cvarName, min, max, format, defaultValue, PlusMinusButton, disabled, disabledTooltipText);
if (padBottom) Spacer(0);
ImGui::EndGroup();
return changed;
}
bool PaddedEnhancementSliderFloat(const char* text, const char* id, const char* cvarName, float min, float max, const char* format, float defaultValue, bool isPercentage, bool PlusMinusButton, bool padTop, bool padBottom, bool disabled, const char* disabledTooltipText) {
bool changed = false;
ImGui::BeginGroup();
if (padTop) Spacer(0);
changed = EnhancementSliderFloat(text, id, cvarName, min, max, format, defaultValue, isPercentage, PlusMinusButton, disabled, disabledTooltipText);
if (padBottom) Spacer(0);
ImGui::EndGroup();
return changed;
}
bool EnhancementRadioButton(const char* text, const char* cvarName, int id) {
/*Usage :
EnhancementRadioButton("My Visible Name","gMyCVarName", MyID);
First arg is the visible name of the Radio button
Second is the cvar name where MyID will be saved.
Note: the CVar name should be the same to each Buddies.
Example :
EnhancementRadioButton("English", "gLanguages", LANGUAGE_ENG);
EnhancementRadioButton("German", "gLanguages", LANGUAGE_GER);
EnhancementRadioButton("French", "gLanguages", LANGUAGE_FRA);
*/
std::string make_invisible = "##" + std::string(text) + std::string(cvarName);
bool ret = false;
int val = CVarGetInteger(cvarName, 0);
if (ImGui::RadioButton(make_invisible.c_str(), id == val)) {
CVarSetInteger(cvarName, id);
LUS::Context::GetInstance()->GetWindow()->GetGui()->SaveConsoleVariablesOnNextTick();
ret = true;
}
ImGui::SameLine();
ImGui::Text("%s", text);
return ret;
}
bool DrawResetColorButton(const char* cvarName, ImVec4* colors, ImVec4 defaultcolors, bool has_alpha) {
bool changed = false;
std::string Cvar_RBM = std::string(cvarName) + "RBM";
std::string MakeInvisible = "Reset##" + std::string(cvarName) + "Reset";
if (ImGui::Button(MakeInvisible.c_str())) {
colors->x = defaultcolors.x;
colors->y = defaultcolors.y;
colors->z = defaultcolors.z;
colors->w = has_alpha ? defaultcolors.w : 255.0f;
Color_RGBA8 colorsRGBA;
colorsRGBA.r = defaultcolors.x;
colorsRGBA.g = defaultcolors.y;
colorsRGBA.b = defaultcolors.z;
colorsRGBA.a = has_alpha ? defaultcolors.w : 255.0f;
CVarSetColor(cvarName, colorsRGBA);
CVarSetInteger(Cvar_RBM.c_str(), 0); //On click disable rainbow mode.
LUS::Context::GetInstance()->GetWindow()->GetGui()->SaveConsoleVariablesOnNextTick();
changed = true;
}
Tooltip("Revert colors to the game's original colors (GameCube version)\nOverwrites previously chosen color");
return changed;
}
bool DrawRandomizeColorButton(const char* cvarName, ImVec4* colors) {
return false;
}
void DrawLockColorCheckbox(const char* cvarName) {
std::string Cvar_Lock = std::string(cvarName) + "Lock";
s32 lock = CVarGetInteger(Cvar_Lock.c_str(), 0);
std::string FullName = "Lock##" + Cvar_Lock;
EnhancementCheckbox(FullName.c_str(), Cvar_Lock.c_str());
Tooltip("Prevents this color from being changed upon selecting \"Randomize all\"");
}
void RainbowColor(const char* cvarName, ImVec4* colors) {
std::string Cvar_RBM = std::string(cvarName) + "RBM";
std::string MakeInvisible = "Rainbow##" + std::string(cvarName) + "Rainbow";
EnhancementCheckbox(MakeInvisible.c_str(), Cvar_RBM.c_str());
Tooltip("Cycles through colors on a timer\nOverwrites previously chosen color");
}
void LoadPickersColors(ImVec4& ColorArray, const char* cvarname, const ImVec4& default_colors, bool has_alpha) {
Color_RGBA8 defaultColors;
defaultColors.r = default_colors.x;
defaultColors.g = default_colors.y;
defaultColors.b = default_colors.z;
defaultColors.a = default_colors.w;
Color_RGBA8 cvarColor = CVarGetColor(cvarname, defaultColors);
ColorArray.x = cvarColor.r / 255.0;
ColorArray.y = cvarColor.g / 255.0;
ColorArray.z = cvarColor.b / 255.0;
ColorArray.w = cvarColor.a / 255.0;
}
bool EnhancementColor(const char* text, const char* cvarName, ImVec4 ColorRGBA, ImVec4 default_colors, bool allow_rainbow, bool has_alpha, bool TitleSameLine) {
bool changed = false;
LoadPickersColors(ColorRGBA, cvarName, default_colors, has_alpha);
ImGuiColorEditFlags flags = ImGuiColorEditFlags_None;
if (!TitleSameLine) {
ImGui::Text("%s", text);
flags = ImGuiColorEditFlags_NoLabel;
}
ImGui::PushID(cvarName);
if (!has_alpha) {
if (ImGui::ColorEdit3(text, (float*)&ColorRGBA, flags))
{
Color_RGBA8 colors;
colors.r = ColorRGBA.x * 255.0;
colors.g = ColorRGBA.y * 255.0;
colors.b = ColorRGBA.z * 255.0;
colors.a = 255.0;
CVarSetColor(cvarName, colors);
LUS::Context::GetInstance()->GetWindow()->GetGui()->SaveConsoleVariablesOnNextTick();
changed = true;
}
}
else
{
flags |= ImGuiColorEditFlags_AlphaBar | ImGuiColorEditFlags_AlphaPreview;
if (ImGui::ColorEdit4(text, (float*)&ColorRGBA, flags))
{
Color_RGBA8 colors;
colors.r = ColorRGBA.x * 255.0;
colors.g = ColorRGBA.y * 255.0;
colors.b = ColorRGBA.z * 255.0;
colors.a = ColorRGBA.w * 255.0;
CVarSetColor(cvarName, colors);
LUS::Context::GetInstance()->GetWindow()->GetGui()->SaveConsoleVariablesOnNextTick();
changed = true;
}
}
ImGui::PopID();
//ImGui::SameLine(); // Removing that one to gain some width spacing on the HUD editor
ImGui::PushItemWidth(-FLT_MIN);
if (DrawResetColorButton(cvarName, &ColorRGBA, default_colors, has_alpha)) {
changed = true;
}
ImGui::SameLine();
if (DrawRandomizeColorButton(cvarName, &ColorRGBA)) {
changed = true;
}
if (allow_rainbow) {
if (ImGui::GetContentRegionAvail().x > 185) {
ImGui::SameLine();
}
RainbowColor(cvarName, &ColorRGBA);
}
DrawLockColorCheckbox(cvarName);
ImGui::NewLine();
ImGui::PopItemWidth();
return changed;
}
void DrawFlagArray32(const std::string& name, uint32_t& flags) {
ImGui::PushID(name.c_str());
for (int32_t flagIndex = 0; flagIndex < 32; flagIndex++) {
if ((flagIndex % 8) != 0) {
ImGui::SameLine();
}
ImGui::PushID(flagIndex);
uint32_t bitMask = 1 << flagIndex;
bool flag = (flags & bitMask) != 0;
if (ImGui::Checkbox("##check", &flag)) {
if (flag) {
flags |= bitMask;
} else {
flags &= ~bitMask;
}
}
ImGui::PopID();
}
ImGui::PopID();
}
void DrawFlagArray16(const std::string& name, uint16_t& flags) {
ImGui::PushID(name.c_str());
for (int16_t flagIndex = 0; flagIndex < 16; flagIndex++) {
if ((flagIndex % 8) != 0) {
ImGui::SameLine();
}
ImGui::PushID(flagIndex);
uint16_t bitMask = 1 << flagIndex;
bool flag = (flags & bitMask) != 0;
if (ImGui::Checkbox("##check", &flag)) {
if (flag) {
flags |= bitMask;
} else {
flags &= ~bitMask;
}
}
ImGui::PopID();
}
ImGui::PopID();
}
void DrawFlagArray8(const std::string& name, uint8_t& flags) {
ImGui::PushID(name.c_str());
for (int8_t flagIndex = 0; flagIndex < 8; flagIndex++) {
if ((flagIndex % 8) != 0) {
ImGui::SameLine();
}
ImGui::PushID(flagIndex);
uint8_t bitMask = 1 << flagIndex;
bool flag = (flags & bitMask) != 0;
if (ImGui::Checkbox("##check", &flag)) {
if (flag) {
flags |= bitMask;
} else {
flags &= ~bitMask;
}
}
ImGui::PopID();
}
ImGui::PopID();
}
bool StateButtonEx(const char* str_id, const char* label, ImVec2 size, ImGuiButtonFlags flags) {
ImGuiContext& g = *GImGui;
ImGuiWindow* window = ImGui::GetCurrentWindow();
if (window->SkipItems)
return false;
const ImGuiStyle& style = g.Style;
const ImVec2 label_size = ImGui::CalcTextSize(label, NULL, true);
const ImGuiID id = window->GetID(str_id);
const ImRect bb(window->DC.CursorPos, window->DC.CursorPos + size);
const float default_size = ImGui::GetFrameHeight();
ImGui::ItemSize(size, (size.y >= default_size) ? g.Style.FramePadding.y : -1.0f);
if (!ImGui::ItemAdd(bb, id))
return false;
if (g.LastItemData.InFlags & ImGuiItemFlags_ButtonRepeat)
flags |= ImGuiButtonFlags_Repeat;
bool hovered, held;
bool pressed = ImGui::ButtonBehavior(bb, id, &hovered, &held, flags);
// Render
const ImU32 bg_col = ImGui::GetColorU32((held && hovered) ? ImGuiCol_ButtonActive
: hovered ? ImGuiCol_ButtonHovered
: ImGuiCol_Button);
//const ImU32 text_col = ImGui::GetColorU32(ImGuiCol_Text);
ImGui::RenderNavHighlight(bb, id);
ImGui::RenderFrame(bb.Min, bb.Max, bg_col, true, g.Style.FrameRounding);
ImGui::RenderTextClipped(bb.Min + style.FramePadding, bb.Max - style.FramePadding, label, NULL, &label_size, {0.55f, 0.45f}, &bb);
/*ImGui::RenderArrow(window->DrawList,
bb.Min +
ImVec2(ImMax(0.0f, (size.x - g.FontSize) * 0.5f), ImMax(0.0f, (size.y - g.FontSize) * 0.5f)),
text_col, dir);*/
IMGUI_TEST_ENGINE_ITEM_INFO(id, str_id, g.LastItemData.StatusFlags);
return pressed;
}
bool StateButton(const char* str_id, const char* label) {
float sz = ImGui::GetFrameHeight();
return StateButtonEx(str_id, label, ImVec2(sz, sz), ImGuiButtonFlags_None);
}
}

101
mm/2s2h/UIWidgets.hpp Normal file
View File

@ -0,0 +1,101 @@
//
// UIWidgets.hpp
// soh
//
// Created by David Chavez on 25.08.22.
//
#ifndef UIWidgets_hpp
#define UIWidgets_hpp
#include <string>
#include <vector>
#include <span>
#include <stdint.h>
#include <ImGui/imgui.h>
namespace UIWidgets {
struct TextFilters {
static int FilterNumbers(ImGuiInputTextCallbackData* data) {
if (data->EventChar < 256 && strchr("1234567890", (char)data->EventChar)) {
return 0;
}
return 1;
}
static int FilterAlphaNum(ImGuiInputTextCallbackData* data) {
const char* alphanum = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWYZ0123456789";
if (data->EventChar < 256 && strchr(alphanum, (char)data->EventChar)) {
return 0;
}
return 1;
}
};
// MARK: - Enums
enum class CheckboxGraphics {
Cross,
Checkmark,
None
};
constexpr float maxSliderWidth = 260.0f;
#ifdef __SWITCH__
constexpr float sliderButtonWidth = 42.0f;
#elif defined(__WIIU__)
constexpr float sliderButtonWidth = 60.0f;
#else
constexpr float sliderButtonWidth = 30.0f;
#endif
char* WrappedText(const char* text, unsigned int charactersPerLine = 60);
char* WrappedText(const std::string& text, unsigned int charactersPerLine);
void SetLastItemHoverText(const std::string& text);
void SetLastItemHoverText(const char* text);
void InsertHelpHoverText(const std::string& text);
void InsertHelpHoverText(const char* text);
void Tooltip(const char* text);
void Spacer(float height);
void PaddedSeparator(bool padTop = true, bool padBottom = true, float extraVerticalTopPadding = 0.0f, float extraVerticalBottomPadding = 0.0f);
void RenderCross(ImDrawList* draw_list, ImVec2 pos, ImU32 col, float sz);
bool CustomCheckbox(const char* label, bool* v, bool disabled, CheckboxGraphics disabledGraphic);
void ReEnableComponent(const char* disabledTooltipText);
void DisableComponent(const float alpha);
bool EnhancementCheckbox(const char* text, const char* cvarName, bool disabled = false, const char* disabledTooltipText = "", CheckboxGraphics disabledGraphic = CheckboxGraphics::Cross, bool defaultValue = false);
bool PaddedEnhancementCheckbox(const char* text, const char* cvarName, bool padTop = true, bool padBottom = true, bool disabled = false, const char* disabledTooltipText = "", CheckboxGraphics disabledGraphic = CheckboxGraphics::Cross, bool defaultValue = false);
bool EnhancementCombobox(const char* cvarName, std::span<const char*, std::dynamic_extent> comboArray, uint8_t defaultIndex, bool disabled = false, const char* disabledTooltipText = "", uint8_t disabledValue = -1);
bool LabeledRightAlignedEnhancementCombobox(const char* label, const char* cvarName, std::span<const char*, std::dynamic_extent> comboArray, uint8_t defaultIndex, bool disabled = false, const char* disabledTooltipText = "", uint8_t disabledValue = -1);
void PaddedText(const char* text, bool padTop = true, bool padBottom = true);
bool EnhancementSliderInt(const char* text, const char* id, const char* cvarName, int min, int max, const char* format, int defaultValue = 0, bool PlusMinusButton = true, bool disabled = false, const char* disabledTooltipText = "");
bool PaddedEnhancementSliderInt(const char* text, const char* id, const char* cvarName, int min, int max, const char* format, int defaultValue = 0, bool PlusMinusButton = true, bool padTop = true, bool padBottom = true, bool disabled = false, const char* disabledTooltipText = "");
bool EnhancementSliderFloat(const char* text, const char* id, const char* cvarName, float min, float max, const char* format, float defaultValue, bool isPercentage, bool PlusMinusButton = true, bool disabled = false, const char* disabledTooltipText = "");
bool PaddedEnhancementSliderFloat(const char* text, const char* id, const char* cvarName, float min, float max, const char* format, float defaultValue, bool isPercentage, bool PlusMinusButton = true, bool padTop = true, bool padBottom = true, bool disabled = false, const char* disabledTooltipText = "");
bool EnhancementRadioButton(const char* text, const char* cvarName, int id);
bool DrawResetColorButton(const char* cvarName, ImVec4* colors, ImVec4 defaultcolors, bool has_alpha);
bool DrawRandomizeColorButton(const char* cvarName, ImVec4* colors);
void DrawLockColorCheckbox(const char* cvarName);
void RainbowColor(const char* cvarName, ImVec4* colors);
void LoadPickersColors(ImVec4& ColorArray, const char* cvarname, const ImVec4& default_colors, bool has_alpha);
bool EnhancementColor(const char* text, const char* cvarName, ImVec4 ColorRGBA, ImVec4 default_colors, bool allow_rainbow = true, bool has_alpha = false, bool TitleSameLine = false);
void DrawFlagArray32(const std::string& name, uint32_t& flags);
void DrawFlagArray16(const std::string& name, uint16_t& flags);
void DrawFlagArray8(const std::string& name, uint8_t& flags);
bool StateButton(const char* str_id, const char* label);
}
#endif /* UIWidgets_hpp */

88
mm/2s2h/gu_pc.c Normal file
View File

@ -0,0 +1,88 @@
#include <math.h>
#include "z64.h"
void guMtxF2L(float mf[4][4], Mtx* m) {
unsigned int r, c;
s32 tmp1;
s32 tmp2;
s32* m1 = &m->m[0][0];
s32* m2 = &m->m[2][0];
for (r = 0; r < 4; r++) {
for (c = 0; c < 2; c++) {
tmp1 = mf[r][2 * c] * 65536.0f;
tmp2 = mf[r][2 * c + 1] * 65536.0f;
*m1++ = (tmp1 & 0xffff0000) | ((tmp2 >> 0x10) & 0xffff);
*m2++ = ((tmp1 << 0x10) & 0xffff0000) | (tmp2 & 0xffff);
}
}
}
void guMtxL2F(float mf[4][4], Mtx* m) {
unsigned int r, c;
u32 tmp1;
u32 tmp2;
u32* m1;
u32* m2;
s32 stmp1, stmp2;
m1 = (u32*)&m->m[0][0];
m2 = (u32*)&m->m[2][0];
for (r = 0; r < 4; r++) {
for (c = 0; c < 2; c++) {
tmp1 = (*m1 & 0xffff0000) | ((*m2 >> 0x10) & 0xffff);
tmp2 = ((*m1++ << 0x10) & 0xffff0000) | (*m2++ & 0xffff);
stmp1 = *(s32*)&tmp1;
stmp2 = *(s32*)&tmp2;
mf[r][c * 2 + 0] = stmp1 / 65536.0f;
mf[r][c * 2 + 1] = stmp2 / 65536.0f;
}
}
}
void guMtxIdentF(f32 mf[4][4]) {
unsigned int r, c;
for (r = 0; r < 4; r++) {
for (c = 0; c < 4; c++) {
if (r == c) {
mf[r][c] = 1.0f;
} else {
mf[r][c] = 0.0f;
}
}
}
}
void guMtxIdent(Mtx* m) {
guMtxIdentF(m->m);
}
void guTranslateF(float m[4][4], float x, float y, float z) {
guMtxIdentF(m);
m[3][0] = x;
m[3][1] = y;
m[3][2] = z;
}
void guTranslate(Mtx* m, float x, float y, float z) {
float mf[4][4];
guTranslateF(mf, x, y, z);
guMtxF2L(mf, m);
}
void guScaleF(float mf[4][4], float x, float y, float z) {
guMtxIdentF(mf);
mf[0][0] = x;
mf[1][1] = y;
mf[2][2] = z;
mf[3][3] = 1.0;
}
void guScale(Mtx* m, float x, float y, float z) {
float mf[4][4];
guScaleF(mf, x, y, z);
guMtxF2L(mf, m);
}
void guNormalize(f32* x, f32* y, f32* z) {
f32 tmp = 1.0f / sqrtf(*x * *x + *y * *y + *z * *z);
*x = *x * tmp;
*y = *y * tmp;
*z = *z * tmp;
}

View File

@ -0,0 +1,108 @@
#include "2s2h/resource/importer/AnimationFactory.h"
#include "2s2h/resource/type/Animation.h"
#include "2s2h/resource/importer/PlayerAnimationFactory.h"
#include <libultraship/libultraship.h>
#include "spdlog/spdlog.h"
namespace LUS {
std::shared_ptr<IResource>
AnimationFactory::ReadResource(std::shared_ptr<ResourceInitData> initData, std::shared_ptr<BinaryReader> reader) {
auto resource = std::make_shared<Animation>(initData);
std::shared_ptr<ResourceVersionFactory> factory = nullptr;
switch (resource->GetInitData()->ResourceVersion) {
case 0:
factory = std::make_shared<AnimationFactoryV0>();
break;
}
if (factory == nullptr) {
SPDLOG_ERROR("Failed to load Animation with version {}", resource->GetInitData()->ResourceVersion);
return nullptr;
}
factory->ParseFileBinary(reader, resource);
return resource;
}
void LUS::AnimationFactoryV0::ParseFileBinary(std::shared_ptr<BinaryReader> reader, std::shared_ptr<IResource> resource) {
std::shared_ptr<Animation> animation = std::static_pointer_cast<Animation>(resource);
ResourceVersionFactory::ParseFileBinary(reader, animation);
AnimationType animType = (AnimationType)reader->ReadUInt32();
animation->type = animType;
if (animType == AnimationType::Normal) {
// Set frame count
animation->animationData.animationHeader.common.frameCount = reader->ReadInt16();
// Populate frame data
uint32_t rotValuesCnt = reader->ReadUInt32();
animation->rotationValues.reserve(rotValuesCnt);
for (uint32_t i = 0; i < rotValuesCnt; i++) {
animation->rotationValues.push_back(reader->ReadUInt16());
}
animation->animationData.animationHeader.frameData = (int16_t*)animation->rotationValues.data();
// Populate joint indices
uint32_t rotIndCnt = reader->ReadUInt32();
animation->rotationIndices.reserve(rotIndCnt);
for (size_t i = 0; i < rotIndCnt; i++) {
uint16_t x = reader->ReadUInt16();
uint16_t y = reader->ReadUInt16();
uint16_t z = reader->ReadUInt16();
animation->rotationIndices.push_back(RotationIndex(x, y, z));
}
animation->animationData.animationHeader.jointIndices = (JointIndex*)animation->rotationIndices.data();
// Set static index max
animation->animationData.animationHeader.staticIndexMax = reader->ReadInt16();
} else if (animType == AnimationType::Curve) {
// Read frame count (unused in this animation type)
reader->ReadInt16();
// Set refIndex
uint32_t refArrCnt = reader->ReadUInt32();
animation->refIndexArr.reserve(refArrCnt);
for (uint32_t i = 0; i < refArrCnt; i++) {
animation->refIndexArr.push_back(reader->ReadUByte());
}
animation->animationData.transformUpdateIndex.refIndex = animation->refIndexArr.data();
// Populate transform data
uint32_t transformDataCnt = reader->ReadUInt32();
animation->transformDataArr.reserve(transformDataCnt);
for (uint32_t i = 0; i < transformDataCnt; i++) {
TransformData data;
data.unk_00 = reader->ReadUInt16();
data.unk_02 = reader->ReadInt16();
data.unk_04 = reader->ReadInt16();
data.unk_06 = reader->ReadInt16();
data.unk_08 = reader->ReadFloat();
animation->transformDataArr.push_back(data);
}
animation->animationData.transformUpdateIndex.transformData = animation->transformDataArr.data();
// Populate copy values
uint32_t copyValuesCnt = reader->ReadUInt32();
animation->copyValuesArr.reserve(copyValuesCnt);
for (uint32_t i = 0; i < copyValuesCnt; i++) {
animation->copyValuesArr.push_back(reader->ReadInt16());
}
animation->animationData.transformUpdateIndex.copyValues = animation->copyValuesArr.data();
} else if (animType == AnimationType::Link) {
// Read the frame count
animation->animationData.linkAnimationHeader.common.frameCount = reader->ReadInt16();
// Read the segment pointer (always 32 bit, doesn't adjust for system pointer size)
std::string path = reader->ReadString();
animation->animationData.linkAnimationHeader.segment = ResourceGetDataByName(path.c_str());
} else if (animType == AnimationType::Legacy) {
SPDLOG_DEBUG("BEYTAH ANIMATION?!");
}
}
} // namespace LUS

View File

@ -0,0 +1,17 @@
#pragma once
#include "Resource.h"
#include "ResourceFactory.h"
namespace LUS {
class AnimationFactory : public ResourceFactory {
public:
std::shared_ptr<IResource>
ReadResource(std::shared_ptr<ResourceInitData> initData, std::shared_ptr<BinaryReader> reader) override;
};
class AnimationFactoryV0 : public ResourceVersionFactory {
public:
void ParseFileBinary(std::shared_ptr<BinaryReader> reader, std::shared_ptr<IResource> resource) override;
};
}; // namespace LUS

View File

@ -0,0 +1,141 @@
#include "2s2h/resource/importer/AudioSampleFactory.h"
#include "2s2h/resource/type/AudioSample.h"
#include "spdlog/spdlog.h"
namespace LUS {
std::shared_ptr<IResource>
AudioSampleFactory::ReadResource(std::shared_ptr<ResourceInitData> initData, std::shared_ptr<BinaryReader> reader) {
auto resource = std::make_shared<AudioSample>(initData);
std::shared_ptr<ResourceVersionFactory> factory = nullptr;
switch (resource->GetInitData()->ResourceVersion) {
case 2:
factory = std::make_shared<AudioSampleFactoryV0>();
break;
}
if (factory == nullptr) {
SPDLOG_ERROR("Failed to load AudioSample with version {}", resource->GetInitData()->ResourceVersion);
return nullptr;
}
factory->ParseFileBinary(reader, resource);
return resource;
}
void LUS::AudioSampleFactoryV0::ParseFileBinary(std::shared_ptr<BinaryReader> reader,
std::shared_ptr<IResource> resource)
{
std::shared_ptr<AudioSample> audioSample = std::static_pointer_cast<AudioSample>(resource);
ResourceVersionFactory::ParseFileBinary(reader, audioSample);
audioSample->sample.codec = reader->ReadUByte();
audioSample->sample.medium = reader->ReadUByte();
audioSample->sample.unk_bit26 = reader->ReadUByte();
audioSample->sample.unk_bit25 = reader->ReadUByte();
audioSample->sample.size = reader->ReadUInt32();
audioSample->audioSampleData.reserve(audioSample->sample.size);
for (uint32_t i = 0; i < audioSample->sample.size; i++) {
audioSample->audioSampleData.push_back(reader->ReadUByte());
}
audioSample->sample.sampleAddr = audioSample->audioSampleData.data();
audioSample->loop.start = reader->ReadUInt32();
audioSample->loop.end = reader->ReadUInt32();
audioSample->loop.count = reader->ReadUInt32();
audioSample->loopStateCount = reader->ReadUInt32();
for (int i = 0; i < 16; i++) {
audioSample->loop.state[i] = 0;
}
for (uint32_t i = 0; i < audioSample->loopStateCount; i++) {
audioSample->loop.state[i] = reader->ReadInt16();
}
audioSample->sample.loop = &audioSample->loop;
audioSample->book.order = reader->ReadInt32();
audioSample->book.npredictors = reader->ReadInt32();
audioSample->bookDataCount = reader->ReadUInt32();
audioSample->bookData.reserve(audioSample->bookDataCount);
for (uint32_t i = 0; i < audioSample->bookDataCount; i++) {
audioSample->bookData.push_back(reader->ReadInt16());
}
audioSample->book.book = audioSample->bookData.data();
audioSample->sample.book = &audioSample->book;
}
} // namespace LUS
/*
in ResourceMgr_LoadAudioSample we used to have
--------------
if (cachedCustomSFs.find(path) != cachedCustomSFs.end())
return cachedCustomSFs[path];
SoundFontSample* cSample = ReadCustomSample(path);
if (cSample != nullptr)
return cSample;
--------------
before the rest of the standard sample reading, this is the ReadCustomSample code we used to have
extern "C" SoundFontSample* ReadCustomSample(const char* path) {
if (!ExtensionCache.contains(path))
return nullptr;
ExtensionEntry entry = ExtensionCache[path];
auto sampleRaw = LUS::Context::GetInstance()->GetResourceManager()->LoadFile(entry.path);
uint32_t* strem = (uint32_t*)sampleRaw->Buffer.get();
uint8_t* strem2 = (uint8_t*)strem;
SoundFontSample* sampleC = new SoundFontSample;
if (entry.ext == "wav") {
drwav_uint32 channels;
drwav_uint32 sampleRate;
drwav_uint64 totalPcm;
drmp3_int16* pcmData =
drwav_open_memory_and_read_pcm_frames_s16(strem2, sampleRaw->BufferSize, &channels, &sampleRate, &totalPcm, NULL);
sampleC->size = totalPcm;
sampleC->sampleAddr = (uint8_t*)pcmData;
sampleC->codec = CODEC_S16;
sampleC->loop = new AdpcmLoop;
sampleC->loop->start = 0;
sampleC->loop->end = sampleC->size - 1;
sampleC->loop->count = 0;
sampleC->sampleRateMagicValue = 'RIFF';
sampleC->sampleRate = sampleRate;
cachedCustomSFs[path] = sampleC;
return sampleC;
} else if (entry.ext == "mp3") {
drmp3_config mp3Info;
drmp3_uint64 totalPcm;
drmp3_int16* pcmData =
drmp3_open_memory_and_read_pcm_frames_s16(strem2, sampleRaw->BufferSize, &mp3Info, &totalPcm, NULL);
sampleC->size = totalPcm * mp3Info.channels * sizeof(short);
sampleC->sampleAddr = (uint8_t*)pcmData;
sampleC->codec = CODEC_S16;
sampleC->loop = new AdpcmLoop;
sampleC->loop->start = 0;
sampleC->loop->end = sampleC->size;
sampleC->loop->count = 0;
sampleC->sampleRateMagicValue = 'RIFF';
sampleC->sampleRate = mp3Info.sampleRate;
cachedCustomSFs[path] = sampleC;
return sampleC;
}
return nullptr;
}
*/

View File

@ -0,0 +1,19 @@
#pragma once
#include "Resource.h"
#include "ResourceFactory.h"
namespace LUS {
class AudioSampleFactory : public ResourceFactory
{
public:
std::shared_ptr<IResource>
ReadResource(std::shared_ptr<ResourceInitData> initData, std::shared_ptr<BinaryReader> reader) override;
};
class AudioSampleFactoryV0 : public ResourceVersionFactory
{
public:
void ParseFileBinary(std::shared_ptr<BinaryReader> reader, std::shared_ptr<IResource> resource) override;
};
}; // namespace LUS

View File

@ -0,0 +1,52 @@
#include "2s2h/resource/importer/AudioSequenceFactory.h"
#include "2s2h/resource/type/AudioSequence.h"
#include "spdlog/spdlog.h"
namespace LUS {
std::shared_ptr<IResource>
AudioSequenceFactory::ReadResource(std::shared_ptr<ResourceInitData> initData, std::shared_ptr<BinaryReader> reader) {
auto resource = std::make_shared<AudioSequence>(initData);
std::shared_ptr<ResourceVersionFactory> factory = nullptr;
switch (resource->GetInitData()->ResourceVersion) {
case 2:
factory = std::make_shared<AudioSequenceFactoryV0>();
break;
}
if (factory == nullptr)
{
SPDLOG_ERROR("Failed to load AudioSequence with version {}", resource->GetInitData()->ResourceVersion);
return nullptr;
}
factory->ParseFileBinary(reader, resource);
return resource;
}
void LUS::AudioSequenceFactoryV0::ParseFileBinary(std::shared_ptr<BinaryReader> reader,
std::shared_ptr<IResource> resource) {
std::shared_ptr<AudioSequence> audioSequence = std::static_pointer_cast<AudioSequence>(resource);
ResourceVersionFactory::ParseFileBinary(reader, audioSequence);
audioSequence->sequence.seqDataSize = reader->ReadInt32();
audioSequence->sequenceData.reserve(audioSequence->sequence.seqDataSize);
for (uint32_t i = 0; i < audioSequence->sequence.seqDataSize; i++) {
audioSequence->sequenceData.push_back(reader->ReadChar());
}
audioSequence->sequence.seqData = audioSequence->sequenceData.data();
audioSequence->sequence.seqNumber = reader->ReadUByte();
audioSequence->sequence.medium = reader->ReadUByte();
audioSequence->sequence.cachePolicy = reader->ReadUByte();
audioSequence->sequence.numFonts = reader->ReadUInt32();
for (uint32_t i = 0; i < 16; i++) {
audioSequence->sequence.fonts[i] = 0;
}
for (uint32_t i = 0; i < audioSequence->sequence.numFonts; i++) {
audioSequence->sequence.fonts[i] = reader->ReadUByte();
}
}
} // namespace LUS

View File

@ -0,0 +1,19 @@
#pragma once
#include "Resource.h"
#include "ResourceFactory.h"
namespace LUS {
class AudioSequenceFactory : public ResourceFactory
{
public:
std::shared_ptr<IResource>
ReadResource(std::shared_ptr<ResourceInitData> initData, std::shared_ptr<BinaryReader> reader) override;
};
class AudioSequenceFactoryV0 : public ResourceVersionFactory
{
public:
void ParseFileBinary(std::shared_ptr<BinaryReader> reader, std::shared_ptr<IResource> resource) override;
};
}; // namespace LUS

View File

@ -0,0 +1,190 @@
#include "2s2h/resource/importer/AudioSoundFontFactory.h"
#include "2s2h/resource/type/AudioSoundFont.h"
#include "spdlog/spdlog.h"
#include "libultraship/libultraship.h"
namespace LUS {
std::shared_ptr<IResource>
AudioSoundFontFactory::ReadResource(std::shared_ptr<ResourceInitData> initData, std::shared_ptr<BinaryReader> reader) {
auto resource = std::make_shared<AudioSoundFont>(initData);
std::shared_ptr<ResourceVersionFactory> factory = nullptr;
switch (resource->GetInitData()->ResourceVersion) {
case 2:
factory = std::make_shared<AudioSoundFontFactoryV0>();
break;
}
if (factory == nullptr)
{
SPDLOG_ERROR("Failed to load AudioSoundFont with version {}", resource->GetInitData()->ResourceVersion);
return nullptr;
}
factory->ParseFileBinary(reader, resource);
return resource;
}
void LUS::AudioSoundFontFactoryV0::ParseFileBinary(std::shared_ptr<BinaryReader> reader,
std::shared_ptr<IResource> resource) {
std::shared_ptr<AudioSoundFont> audioSoundFont = std::static_pointer_cast<AudioSoundFont>(resource);
ResourceVersionFactory::ParseFileBinary(reader, audioSoundFont);
audioSoundFont->soundFont.fntIndex = reader->ReadInt32();
audioSoundFont->medium = reader->ReadInt8();
audioSoundFont->cachePolicy = reader->ReadInt8();
audioSoundFont->data1 = reader->ReadUInt16();
audioSoundFont->soundFont.sampleBankId1 = audioSoundFont->data1 >> 8;
audioSoundFont->soundFont.sampleBankId2 = audioSoundFont->data1 & 0xFF;
audioSoundFont->data2 = reader->ReadUInt16();
audioSoundFont->data3 = reader->ReadUInt16();
uint32_t drumCount = reader->ReadUInt32();
audioSoundFont->soundFont.numDrums = drumCount;
uint32_t instrumentCount = reader->ReadUInt32();
audioSoundFont->soundFont.numInstruments = instrumentCount;
uint32_t soundEffectCount = reader->ReadUInt32();
audioSoundFont->soundFont.numSfx = soundEffectCount;
// 🥁 DRUMS 🥁
audioSoundFont->drums.reserve(audioSoundFont->soundFont.numDrums);
audioSoundFont->drumAddresses.reserve(audioSoundFont->soundFont.numDrums);
for (uint32_t i = 0; i < audioSoundFont->soundFont.numDrums; i++) {
Drum drum;
drum.releaseRate = reader->ReadUByte();
drum.pan = reader->ReadUByte();
drum.loaded = reader->ReadUByte();
drum.loaded = 0; // this was always getting set to zero in ResourceMgr_LoadAudioSoundFont
uint32_t envelopeCount = reader->ReadUInt32();
audioSoundFont->drumEnvelopeCounts.push_back(envelopeCount);
std::vector<AdsrEnvelope> drumEnvelopes;
drumEnvelopes.reserve(audioSoundFont->drumEnvelopeCounts[i]);
for (uint32_t j = 0; j < audioSoundFont->drumEnvelopeCounts.back(); j++) {
AdsrEnvelope env;
int16_t delay = reader->ReadInt16();
int16_t arg = reader->ReadInt16();
env.delay = BE16SWAP(delay);
env.arg = BE16SWAP(arg);
drumEnvelopes.push_back(env);
}
audioSoundFont->drumEnvelopeArrays.push_back(drumEnvelopes);
drum.envelope = audioSoundFont->drumEnvelopeArrays.back().data();
bool hasSample = reader->ReadInt8();
std::string sampleFileName = reader->ReadString();
drum.sound.tuning = reader->ReadFloat();
if (sampleFileName.empty()) {
drum.sound.sample = nullptr;
} else {
auto res = LUS::Context::GetInstance()->GetResourceManager()->LoadResourceProcess(sampleFileName.c_str());
drum.sound.sample = static_cast<Sample*>(res ? res->GetRawPointer() : nullptr);
}
audioSoundFont->drums.push_back(drum);
audioSoundFont->drumAddresses.push_back(&audioSoundFont->drums.back());
}
audioSoundFont->soundFont.drums = audioSoundFont->drumAddresses.data();
// 🎺🎻🎷🎸🎹 INSTRUMENTS 🎹🎸🎷🎻🎺
audioSoundFont->instruments.reserve(audioSoundFont->soundFont.numInstruments);
for (uint32_t i = 0; i < audioSoundFont->soundFont.numInstruments; i++) {
Instrument instrument;
uint8_t isValidEntry = reader->ReadUByte();
instrument.loaded = reader->ReadUByte();
instrument.loaded = 0; // this was always getting set to zero in ResourceMgr_LoadAudioSoundFont
instrument.normalRangeLo = reader->ReadUByte();
instrument.normalRangeHi = reader->ReadUByte();
instrument.releaseRate = reader->ReadUByte();
uint32_t envelopeCount = reader->ReadInt32();
audioSoundFont->instrumentEnvelopeCounts.push_back(envelopeCount);
std::vector<AdsrEnvelope> instrumentEnvelopes;
for (uint32_t j = 0; j < audioSoundFont->instrumentEnvelopeCounts.back(); j++) {
AdsrEnvelope env;
int16_t delay = reader->ReadInt16();
int16_t arg = reader->ReadInt16();
env.delay = BE16SWAP(delay);
env.arg = BE16SWAP(arg);
instrumentEnvelopes.push_back(env);
}
audioSoundFont->instrumentEnvelopeArrays.push_back(instrumentEnvelopes);
instrument.envelope = audioSoundFont->instrumentEnvelopeArrays.back().data();
bool hasLowNoteSoundFontEntry = reader->ReadInt8();
if (hasLowNoteSoundFontEntry) {
bool hasSampleRef = reader->ReadInt8();
std::string sampleFileName = reader->ReadString();
instrument.lowNotesSound.tuning = reader->ReadFloat();
auto res = LUS::Context::GetInstance()->GetResourceManager()->LoadResourceProcess(sampleFileName.c_str());
instrument.lowNotesSound.sample = static_cast<Sample*>(res ? res->GetRawPointer() : nullptr);
} else {
instrument.lowNotesSound.sample = nullptr;
instrument.lowNotesSound.tuning = 0;
}
bool hasNormalNoteSoundFontEntry = reader->ReadInt8();
if (hasNormalNoteSoundFontEntry) {
bool hasSampleRef = reader->ReadInt8();
std::string sampleFileName = reader->ReadString();
instrument.normalNotesSound.tuning = reader->ReadFloat();
auto res = LUS::Context::GetInstance()->GetResourceManager()->LoadResourceProcess(sampleFileName.c_str());
instrument.normalNotesSound.sample = static_cast<Sample*>(res ? res->GetRawPointer() : nullptr);
} else {
instrument.normalNotesSound.sample = nullptr;
instrument.normalNotesSound.tuning = 0;
}
bool hasHighNoteSoundFontEntry = reader->ReadInt8();
if (hasHighNoteSoundFontEntry) {
bool hasSampleRef = reader->ReadInt8();
std::string sampleFileName = reader->ReadString();
instrument.highNotesSound.tuning = reader->ReadFloat();
auto res = LUS::Context::GetInstance()->GetResourceManager()->LoadResourceProcess(sampleFileName.c_str());
instrument.highNotesSound.sample = static_cast<Sample*>(res ? res->GetRawPointer() : nullptr);
} else {
instrument.highNotesSound.sample = nullptr;
instrument.highNotesSound.tuning = 0;
}
audioSoundFont->instruments.push_back(instrument);
audioSoundFont->instrumentAddresses.push_back(isValidEntry ?
&audioSoundFont->instruments.back() :
nullptr);
}
audioSoundFont->soundFont.instruments = audioSoundFont->instrumentAddresses.data();
// 🔊 SOUND EFFECTS 🔊
audioSoundFont->soundEffects.reserve(audioSoundFont->soundFont.numSfx);
for (uint32_t i = 0; i < audioSoundFont->soundFont.numSfx; i++) {
SoundFontSound soundEffect;
bool hasSFEntry = reader->ReadInt8();
if (hasSFEntry) {
bool hasSampleRef = reader->ReadInt8();
std::string sampleFileName = reader->ReadString();
soundEffect.tuning = reader->ReadFloat();
auto res = LUS::Context::GetInstance()->GetResourceManager()->LoadResourceProcess(sampleFileName.c_str());
soundEffect.sample = static_cast<Sample*>(res ? res->GetRawPointer() : nullptr);
}
audioSoundFont->soundEffects.push_back(soundEffect);
}
audioSoundFont->soundFont.soundEffects = audioSoundFont->soundEffects.data();
}
} // namespace LUS

View File

@ -0,0 +1,19 @@
#pragma once
#include "Resource.h"
#include "ResourceFactory.h"
namespace LUS {
class AudioSoundFontFactory : public ResourceFactory
{
public:
std::shared_ptr<IResource>
ReadResource(std::shared_ptr<ResourceInitData> initData, std::shared_ptr<BinaryReader> reader) override;
};
class AudioSoundFontFactoryV0 : public ResourceVersionFactory
{
public:
void ParseFileBinary(std::shared_ptr<BinaryReader> reader, std::shared_ptr<IResource> resource) override;
};
}; // namespace LUS

View File

@ -0,0 +1,39 @@
#include "2s2h/resource/importer/BackgroundFactory.h"
#include "2s2h/resource/type/Background.h"
#include "spdlog/spdlog.h"
namespace LUS {
std::shared_ptr<IResource>
BackgroundFactory::ReadResource(std::shared_ptr<ResourceInitData> initData, std::shared_ptr<BinaryReader> reader) {
auto resource = std::make_shared<Background>(initData);
std::shared_ptr<ResourceVersionFactory> factory = nullptr;
switch (resource->GetInitData()->ResourceVersion) {
case 0:
factory = std::make_shared<BackgroundFactoryV0>();
break;
}
if (factory == nullptr) {
SPDLOG_ERROR("Failed to load Background with version {}", resource->GetInitData()->ResourceVersion);
return nullptr;
}
factory->ParseFileBinary(reader, resource);
return resource;
}
void BackgroundFactoryV0::ParseFileBinary(std::shared_ptr<BinaryReader> reader, std::shared_ptr<IResource> resource) {
std::shared_ptr<Background> background = std::static_pointer_cast<Background>(resource);
ResourceVersionFactory::ParseFileBinary(reader, background);
uint32_t dataSize = reader->ReadUInt32();
background->Data.reserve(dataSize);
for (uint32_t i = 0; i < dataSize; i++) {
background->Data.push_back(reader->ReadUByte());
}
}
} // namespace LUS

View File

@ -0,0 +1,17 @@
#pragma once
#include "resource/Resource.h"
#include "resource/ResourceFactory.h"
namespace LUS {
class BackgroundFactory : public ResourceFactory {
public:
std::shared_ptr<IResource>
ReadResource(std::shared_ptr<ResourceInitData> initData, std::shared_ptr<BinaryReader> reader) override;
};
class BackgroundFactoryV0 : public ResourceVersionFactory {
public:
void ParseFileBinary(std::shared_ptr<BinaryReader> reader, std::shared_ptr<IResource> resource) override;
};
}; // namespace LUS

View File

@ -0,0 +1,142 @@
#include "2s2h/resource/importer/CollisionHeaderFactory.h"
#include "2s2h/resource/type/CollisionHeader.h"
#include "spdlog/spdlog.h"
namespace LUS {
std::shared_ptr<IResource>
CollisionHeaderFactory::ReadResource(std::shared_ptr<ResourceInitData> initData, std::shared_ptr<BinaryReader> reader) {
auto resource = std::make_shared<CollisionHeader>(initData);
std::shared_ptr<ResourceVersionFactory> factory = nullptr;
switch (resource->GetInitData()->ResourceVersion) {
case 0:
factory = std::make_shared<CollisionHeaderFactoryV0>();
break;
}
if (factory == nullptr) {
SPDLOG_ERROR("Failed to load Collision Header with version {}", resource->GetInitData()->ResourceVersion);
return nullptr;
}
factory->ParseFileBinary(reader, resource);
return resource;
}
void LUS::CollisionHeaderFactoryV0::ParseFileBinary(std::shared_ptr<BinaryReader> reader,
std::shared_ptr<IResource> resource)
{
std::shared_ptr<CollisionHeader> collisionHeader = std::static_pointer_cast<CollisionHeader>(resource);
ResourceVersionFactory::ParseFileBinary(reader, collisionHeader);
collisionHeader->collisionHeaderData.minBounds.x = reader->ReadInt16();
collisionHeader->collisionHeaderData.minBounds.y = reader->ReadInt16();
collisionHeader->collisionHeaderData.minBounds.z = reader->ReadInt16();
collisionHeader->collisionHeaderData.maxBounds.x = reader->ReadInt16();
collisionHeader->collisionHeaderData.maxBounds.y = reader->ReadInt16();
collisionHeader->collisionHeaderData.maxBounds.z = reader->ReadInt16();
collisionHeader->collisionHeaderData.numVertices = reader->ReadInt32();
collisionHeader->vertices.reserve(collisionHeader->collisionHeaderData.numVertices);
for (int32_t i = 0; i < collisionHeader->collisionHeaderData.numVertices; i++) {
Vec3s vtx;
vtx.x = reader->ReadInt16();
vtx.y = reader->ReadInt16();
vtx.z = reader->ReadInt16();
collisionHeader->vertices.push_back(vtx);
}
collisionHeader->collisionHeaderData.vtxList = collisionHeader->vertices.data();
collisionHeader->collisionHeaderData.numPolygons = reader->ReadUInt32();
collisionHeader->polygons.reserve(collisionHeader->collisionHeaderData.numPolygons);
for (uint32_t i = 0; i < collisionHeader->collisionHeaderData.numPolygons; i++) {
CollisionPoly polygon;
polygon.type = reader->ReadUInt16();
polygon.flags_vIA = reader->ReadUInt16();
polygon.flags_vIB = reader->ReadUInt16();
polygon.vIC = reader->ReadUInt16();
polygon.normal.x = reader->ReadUInt16();
polygon.normal.y = reader->ReadUInt16();
polygon.normal.z = reader->ReadUInt16();
polygon.dist = reader->ReadUInt16();
collisionHeader->polygons.push_back(polygon);
}
collisionHeader->collisionHeaderData.polyList = collisionHeader->polygons.data();
collisionHeader->surfaceTypesCount = reader->ReadUInt32();
collisionHeader->surfaceTypes.reserve(collisionHeader->surfaceTypesCount);
for (uint32_t i = 0; i < collisionHeader->surfaceTypesCount; i++) {
SurfaceType surfaceType;
surfaceType.data[1] = reader->ReadUInt32();
surfaceType.data[0] = reader->ReadUInt32();
collisionHeader->surfaceTypes.push_back(surfaceType);
}
collisionHeader->collisionHeaderData.surfaceTypeList = collisionHeader->surfaceTypes.data();
collisionHeader->camDataCount = reader->ReadUInt32();
collisionHeader->camData.reserve(collisionHeader->camDataCount);
collisionHeader->camPosDataIndices.reserve(collisionHeader->camDataCount);
for (uint32_t i = 0; i < collisionHeader->camDataCount; i++) {
CamData camDataEntry;
camDataEntry.cameraSType = reader->ReadUInt16();
camDataEntry.numCameras = reader->ReadInt16();
collisionHeader->camData.push_back(camDataEntry);
int32_t camPosDataIdx = reader->ReadInt32();
collisionHeader->camPosDataIndices.push_back(camPosDataIdx);
}
collisionHeader->camPosCount = reader->ReadInt32();
collisionHeader->camPosData.reserve(collisionHeader->camPosCount);
for (int32_t i = 0; i < collisionHeader->camPosCount; i++) {
Vec3s pos;
pos.x = reader->ReadInt16();
pos.y = reader->ReadInt16();
pos.z = reader->ReadInt16();
collisionHeader->camPosData.push_back(pos);
}
Vec3s zero;
zero.x = 0;
zero.y = 0;
zero.z = 0;
collisionHeader->camPosDataZero = zero;
for (size_t i = 0; i < collisionHeader->camDataCount; i++) {
int32_t idx = collisionHeader->camPosDataIndices[i];
if (collisionHeader->camPosCount > 0) {
collisionHeader->camData[i].camPosData = &collisionHeader->camPosData[idx];
} else {
collisionHeader->camData[i].camPosData = &collisionHeader->camPosDataZero;
}
}
collisionHeader->collisionHeaderData.cameraDataList = collisionHeader->camData.data();
collisionHeader->collisionHeaderData.cameraDataListLen = collisionHeader->camDataCount;
collisionHeader->collisionHeaderData.numWaterBoxes = reader->ReadInt32();
collisionHeader->waterBoxes.reserve(collisionHeader->collisionHeaderData.numWaterBoxes);
for (int32_t i = 0; i < collisionHeader->collisionHeaderData.numWaterBoxes; i++) {
WaterBox waterBox;
waterBox.xMin = reader->ReadInt16();
waterBox.ySurface = reader->ReadInt16();
waterBox.zMin = reader->ReadInt16();
waterBox.xLength = reader->ReadInt16();
waterBox.zLength = reader->ReadInt16();
waterBox.properties = reader->ReadInt32();
collisionHeader->waterBoxes.push_back(waterBox);
}
collisionHeader->collisionHeaderData.waterBoxes = collisionHeader->waterBoxes.data();
}
}

View File

@ -0,0 +1,17 @@
#pragma once
#include "Resource.h"
#include "ResourceFactory.h"
namespace LUS {
class CollisionHeaderFactory : public ResourceFactory {
public:
std::shared_ptr<IResource>
ReadResource(std::shared_ptr<ResourceInitData> initData, std::shared_ptr<BinaryReader> reader) override;
};
class CollisionHeaderFactoryV0 : public ResourceVersionFactory {
public:
void ParseFileBinary(std::shared_ptr<BinaryReader> reader, std::shared_ptr<IResource> resource) override;
};
}; // namespace LUS

View File

@ -0,0 +1,917 @@
#include "2s2h/resource/importer/CutsceneFactory.h"
#include "2s2h/resource/type/Cutscene.h"
#include "spdlog/spdlog.h"
// TODO headers
// extern "C" {
//#include "z64cutscene.h"
//}
typedef enum {
/* 0x00A */ CS_CMD_TEXT = 10,
/* 0x05A */ CS_CMD_CAMERA_SPLINE = 90,
/* 0x064 */ CS_CMD_ACTOR_CUE_100 = 100,
/* 0x065 */ CS_CMD_ACTOR_CUE_101,
/* 0x066 */ CS_CMD_ACTOR_CUE_102,
/* 0x067 */ CS_CMD_ACTOR_CUE_103,
/* 0x068 */ CS_CMD_ACTOR_CUE_104,
/* 0x069 */ CS_CMD_ACTOR_CUE_105,
/* 0x06A */ CS_CMD_ACTOR_CUE_106,
/* 0x06B */ CS_CMD_ACTOR_CUE_107,
/* 0x06C */ CS_CMD_ACTOR_CUE_108,
/* 0x06D */ CS_CMD_ACTOR_CUE_109,
/* 0x06E */ CS_CMD_ACTOR_CUE_110,
/* 0x06F */ CS_CMD_ACTOR_CUE_111,
/* 0x070 */ CS_CMD_ACTOR_CUE_112,
/* 0x071 */ CS_CMD_ACTOR_CUE_113,
/* 0x072 */ CS_CMD_ACTOR_CUE_114,
/* 0x073 */ CS_CMD_ACTOR_CUE_115,
/* 0x074 */ CS_CMD_ACTOR_CUE_116,
/* 0x075 */ CS_CMD_ACTOR_CUE_117,
/* 0x076 */ CS_CMD_ACTOR_CUE_118,
/* 0x077 */ CS_CMD_ACTOR_CUE_119,
/* 0x078 */ CS_CMD_ACTOR_CUE_120,
/* 0x079 */ CS_CMD_ACTOR_CUE_121,
/* 0x07A */ CS_CMD_ACTOR_CUE_122,
/* 0x07B */ CS_CMD_ACTOR_CUE_123,
/* 0x07C */ CS_CMD_ACTOR_CUE_124,
/* 0x07D */ CS_CMD_ACTOR_CUE_125,
/* 0x07E */ CS_CMD_ACTOR_CUE_126,
/* 0x07F */ CS_CMD_ACTOR_CUE_127,
/* 0x080 */ CS_CMD_ACTOR_CUE_128,
/* 0x081 */ CS_CMD_ACTOR_CUE_129,
/* 0x082 */ CS_CMD_ACTOR_CUE_130,
/* 0x083 */ CS_CMD_ACTOR_CUE_131,
/* 0x084 */ CS_CMD_ACTOR_CUE_132,
/* 0x085 */ CS_CMD_ACTOR_CUE_133,
/* 0x086 */ CS_CMD_ACTOR_CUE_134,
/* 0x087 */ CS_CMD_ACTOR_CUE_135,
/* 0x088 */ CS_CMD_ACTOR_CUE_136,
/* 0x089 */ CS_CMD_ACTOR_CUE_137,
/* 0x08A */ CS_CMD_ACTOR_CUE_138,
/* 0x08B */ CS_CMD_ACTOR_CUE_139,
/* 0x08C */ CS_CMD_ACTOR_CUE_140,
/* 0x08D */ CS_CMD_ACTOR_CUE_141,
/* 0x08E */ CS_CMD_ACTOR_CUE_142,
/* 0x08F */ CS_CMD_ACTOR_CUE_143,
/* 0x090 */ CS_CMD_ACTOR_CUE_144,
/* 0x091 */ CS_CMD_ACTOR_CUE_145,
/* 0x092 */ CS_CMD_ACTOR_CUE_146,
/* 0x093 */ CS_CMD_ACTOR_CUE_147,
/* 0x094 */ CS_CMD_ACTOR_CUE_148,
/* 0x095 */ CS_CMD_ACTOR_CUE_149,
/* 0x096 */ CS_CMD_MISC,
/* 0x097 */ CS_CMD_LIGHT_SETTING,
/* 0x098 */ CS_CMD_TRANSITION,
/* 0x099 */ CS_CMD_MOTION_BLUR,
/* 0x09A */ CS_CMD_GIVE_TATL,
/* 0x09B */ CS_CMD_TRANSITION_GENERAL,
/* 0x09C */ CS_CMD_FADE_OUT_SEQ,
/* 0x09D */ CS_CMD_TIME,
/* 0x0C8 */ CS_CMD_PLAYER_CUE = 200,
/* 0x0C9 */ CS_CMD_ACTOR_CUE_201,
/* 0x0FA */ CS_CMD_UNK_DATA_FA = 0xFA,
/* 0x0FE */ CS_CMD_UNK_DATA_FE = 0xFE,
/* 0x0FF */ CS_CMD_UNK_DATA_FF,
/* 0x100 */ CS_CMD_UNK_DATA_100,
/* 0x101 */ CS_CMD_UNK_DATA_101,
/* 0x102 */ CS_CMD_UNK_DATA_102,
/* 0x103 */ CS_CMD_UNK_DATA_103,
/* 0x104 */ CS_CMD_UNK_DATA_104,
/* 0x105 */ CS_CMD_UNK_DATA_105,
/* 0x108 */ CS_CMD_UNK_DATA_108 = 0x108,
/* 0x109 */ CS_CMD_UNK_DATA_109,
/* 0x12C */ CS_CMD_START_SEQ = 300,
/* 0x12D */ CS_CMD_STOP_SEQ,
/* 0x12E */ CS_CMD_START_AMBIENCE,
/* 0x12F */ CS_CMD_FADE_OUT_AMBIENCE,
/* 0x130 */ CS_CMD_SFX_REVERB_INDEX_2,
/* 0x131 */ CS_CMD_SFX_REVERB_INDEX_1,
/* 0x132 */ CS_CMD_MODIFY_SEQ,
/* 0x15E */ CS_CMD_DESTINATION = 350,
/* 0x15F */ CS_CMD_CHOOSE_CREDITS_SCENES,
/* 0x190 */ CS_CMD_RUMBLE = 400,
/* 0x1C2 */ CS_CMD_ACTOR_CUE_450 = 450,
/* 0x1C3 */ CS_CMD_ACTOR_CUE_451,
/* 0x1C4 */ CS_CMD_ACTOR_CUE_452,
/* 0x1C5 */ CS_CMD_ACTOR_CUE_453,
/* 0x1C6 */ CS_CMD_ACTOR_CUE_454,
/* 0x1C7 */ CS_CMD_ACTOR_CUE_455,
/* 0x1C8 */ CS_CMD_ACTOR_CUE_456,
/* 0x1C9 */ CS_CMD_ACTOR_CUE_457,
/* 0x1CA */ CS_CMD_ACTOR_CUE_458,
/* 0x1CB */ CS_CMD_ACTOR_CUE_459,
/* 0x1CC */ CS_CMD_ACTOR_CUE_460,
/* 0x1CD */ CS_CMD_ACTOR_CUE_461,
/* 0x1CE */ CS_CMD_ACTOR_CUE_462,
/* 0x1CF */ CS_CMD_ACTOR_CUE_463,
/* 0x1D0 */ CS_CMD_ACTOR_CUE_464,
/* 0x1D1 */ CS_CMD_ACTOR_CUE_465,
/* 0x1D2 */ CS_CMD_ACTOR_CUE_466,
/* 0x1D3 */ CS_CMD_ACTOR_CUE_467,
/* 0x1D4 */ CS_CMD_ACTOR_CUE_468,
/* 0x1D5 */ CS_CMD_ACTOR_CUE_469,
/* 0x1D6 */ CS_CMD_ACTOR_CUE_470,
/* 0x1D7 */ CS_CMD_ACTOR_CUE_471,
/* 0x1D8 */ CS_CMD_ACTOR_CUE_472,
/* 0x1D9 */ CS_CMD_ACTOR_CUE_473,
/* 0x1DA */ CS_CMD_ACTOR_CUE_474,
/* 0x1DB */ CS_CMD_ACTOR_CUE_475,
/* 0x1DC */ CS_CMD_ACTOR_CUE_476,
/* 0x1DD */ CS_CMD_ACTOR_CUE_477,
/* 0x1DE */ CS_CMD_ACTOR_CUE_478,
/* 0x1DF */ CS_CMD_ACTOR_CUE_479,
/* 0x1E0 */ CS_CMD_ACTOR_CUE_480,
/* 0x1E1 */ CS_CMD_ACTOR_CUE_481,
/* 0x1E2 */ CS_CMD_ACTOR_CUE_482,
/* 0x1E3 */ CS_CMD_ACTOR_CUE_483,
/* 0x1E4 */ CS_CMD_ACTOR_CUE_484,
/* 0x1E5 */ CS_CMD_ACTOR_CUE_485,
/* 0x1E6 */ CS_CMD_ACTOR_CUE_486,
/* 0x1E7 */ CS_CMD_ACTOR_CUE_487,
/* 0x1E8 */ CS_CMD_ACTOR_CUE_488,
/* 0x1E9 */ CS_CMD_ACTOR_CUE_489,
/* 0x1EA */ CS_CMD_ACTOR_CUE_490,
/* 0x1EB */ CS_CMD_ACTOR_CUE_491,
/* 0x1EC */ CS_CMD_ACTOR_CUE_492,
/* 0x1ED */ CS_CMD_ACTOR_CUE_493,
/* 0x1EE */ CS_CMD_ACTOR_CUE_494,
/* 0x1EF */ CS_CMD_ACTOR_CUE_495,
/* 0x1F0 */ CS_CMD_ACTOR_CUE_496,
/* 0x1F1 */ CS_CMD_ACTOR_CUE_497,
/* 0x1F2 */ CS_CMD_ACTOR_CUE_498,
/* 0x1F3 */ CS_CMD_ACTOR_CUE_499,
/* 0x1F4 */ CS_CMD_ACTOR_CUE_500,
/* 0x1F5 */ CS_CMD_ACTOR_CUE_501,
/* 0x1F6 */ CS_CMD_ACTOR_CUE_502,
/* 0x1F7 */ CS_CMD_ACTOR_CUE_503,
/* 0x1F8 */ CS_CMD_ACTOR_CUE_504,
/* 0x1F9 */ CS_CMD_ACTOR_CUE_SOTCS, // Song of Time Cutscenes (Double SoT, Three-Day Reset SoT)
/* 0x1FA */ CS_CMD_ACTOR_CUE_506,
/* 0x1FB */ CS_CMD_ACTOR_CUE_507,
/* 0x1FC */ CS_CMD_ACTOR_CUE_508,
/* 0x1FD */ CS_CMD_ACTOR_CUE_509,
/* 0x1FE */ CS_CMD_ACTOR_CUE_510,
/* 0x1FF */ CS_CMD_ACTOR_CUE_511,
/* 0x200 */ CS_CMD_ACTOR_CUE_512,
/* 0x201 */ CS_CMD_ACTOR_CUE_513,
/* 0x202 */ CS_CMD_ACTOR_CUE_514,
/* 0x203 */ CS_CMD_ACTOR_CUE_515,
/* 0x204 */ CS_CMD_ACTOR_CUE_516,
/* 0x205 */ CS_CMD_ACTOR_CUE_517,
/* 0x206 */ CS_CMD_ACTOR_CUE_518,
/* 0x207 */ CS_CMD_ACTOR_CUE_519,
/* 0x208 */ CS_CMD_ACTOR_CUE_520,
/* 0x209 */ CS_CMD_ACTOR_CUE_521,
/* 0x20A */ CS_CMD_ACTOR_CUE_522,
/* 0x20B */ CS_CMD_ACTOR_CUE_523,
/* 0x20C */ CS_CMD_ACTOR_CUE_524,
/* 0x20D */ CS_CMD_ACTOR_CUE_525,
/* 0x20E */ CS_CMD_ACTOR_CUE_526,
/* 0x20F */ CS_CMD_ACTOR_CUE_527,
/* 0x210 */ CS_CMD_ACTOR_CUE_528,
/* 0x211 */ CS_CMD_ACTOR_CUE_529,
/* 0x212 */ CS_CMD_ACTOR_CUE_530,
/* 0x213 */ CS_CMD_ACTOR_CUE_531,
/* 0x214 */ CS_CMD_ACTOR_CUE_532,
/* 0x215 */ CS_CMD_ACTOR_CUE_533,
/* 0x216 */ CS_CMD_ACTOR_CUE_534,
/* 0x217 */ CS_CMD_ACTOR_CUE_535,
/* 0x218 */ CS_CMD_ACTOR_CUE_536,
/* 0x219 */ CS_CMD_ACTOR_CUE_537,
/* 0x21A */ CS_CMD_ACTOR_CUE_538,
/* 0x21B */ CS_CMD_ACTOR_CUE_539,
/* 0x21C */ CS_CMD_ACTOR_CUE_540,
/* 0x21D */ CS_CMD_ACTOR_CUE_541,
/* 0x21E */ CS_CMD_ACTOR_CUE_542,
/* 0x21F */ CS_CMD_ACTOR_CUE_543,
/* 0x220 */ CS_CMD_ACTOR_CUE_544,
/* 0x221 */ CS_CMD_ACTOR_CUE_545,
/* 0x222 */ CS_CMD_ACTOR_CUE_546,
/* 0x223 */ CS_CMD_ACTOR_CUE_547,
/* 0x224 */ CS_CMD_ACTOR_CUE_548,
/* 0x225 */ CS_CMD_ACTOR_CUE_549,
/* 0x226 */ CS_CMD_ACTOR_CUE_550,
/* 0x227 */ CS_CMD_ACTOR_CUE_551,
/* 0x228 */ CS_CMD_ACTOR_CUE_552,
/* 0x229 */ CS_CMD_ACTOR_CUE_553,
/* 0x22A */ CS_CMD_ACTOR_CUE_554,
/* 0x22B */ CS_CMD_ACTOR_CUE_555,
/* 0x22C */ CS_CMD_ACTOR_CUE_556,
/* 0x22D */ CS_CMD_ACTOR_CUE_557,
/* 0x22E */ CS_CMD_ACTOR_CUE_558,
/* 0x22F */ CS_CMD_ACTOR_CUE_559,
/* 0x230 */ CS_CMD_ACTOR_CUE_560,
/* 0x231 */ CS_CMD_ACTOR_CUE_561,
/* 0x232 */ CS_CMD_ACTOR_CUE_562,
/* 0x233 */ CS_CMD_ACTOR_CUE_563,
/* 0x234 */ CS_CMD_ACTOR_CUE_564,
/* 0x235 */ CS_CMD_ACTOR_CUE_565,
/* 0x236 */ CS_CMD_ACTOR_CUE_566,
/* 0x237 */ CS_CMD_ACTOR_CUE_567,
/* 0x238 */ CS_CMD_ACTOR_CUE_568,
/* 0x239 */ CS_CMD_ACTOR_CUE_569,
/* 0x23A */ CS_CMD_ACTOR_CUE_570,
/* 0x23B */ CS_CMD_ACTOR_CUE_571,
/* 0x23C */ CS_CMD_ACTOR_CUE_572,
/* 0x23D */ CS_CMD_ACTOR_CUE_573,
/* 0x23E */ CS_CMD_ACTOR_CUE_574,
/* 0x23F */ CS_CMD_ACTOR_CUE_575,
/* 0x240 */ CS_CMD_ACTOR_CUE_576,
/* 0x241 */ CS_CMD_ACTOR_CUE_577,
/* 0x242 */ CS_CMD_ACTOR_CUE_578,
/* 0x243 */ CS_CMD_ACTOR_CUE_579,
/* 0x244 */ CS_CMD_ACTOR_CUE_580,
/* 0x245 */ CS_CMD_ACTOR_CUE_581,
/* 0x246 */ CS_CMD_ACTOR_CUE_582,
/* 0x247 */ CS_CMD_ACTOR_CUE_583,
/* 0x248 */ CS_CMD_ACTOR_CUE_584,
/* 0x249 */ CS_CMD_ACTOR_CUE_585,
/* 0x24A */ CS_CMD_ACTOR_CUE_586,
/* 0x24B */ CS_CMD_ACTOR_CUE_587,
/* 0x24C */ CS_CMD_ACTOR_CUE_588,
/* 0x24D */ CS_CMD_ACTOR_CUE_589,
/* 0x24E */ CS_CMD_ACTOR_CUE_590,
/* 0x24F */ CS_CMD_ACTOR_CUE_591,
/* 0x250 */ CS_CMD_ACTOR_CUE_592,
/* 0x251 */ CS_CMD_ACTOR_CUE_593,
/* 0x252 */ CS_CMD_ACTOR_CUE_594,
/* 0x253 */ CS_CMD_ACTOR_CUE_595,
/* 0x254 */ CS_CMD_ACTOR_CUE_596,
/* 0x255 */ CS_CMD_ACTOR_CUE_597,
/* 0x256 */ CS_CMD_ACTOR_CUE_598,
/* 0x257 */ CS_CMD_ACTOR_CUE_599,
/* -2 */ CS_CMD_ACTOR_CUE_POST_PROCESS = 0xFFFFFFFE,
/* -1 */ CS_CAM_STOP // OoT Remnant
} CutsceneCmd;
namespace LUS {
std::shared_ptr<IResource> CutsceneFactory::ReadResource(std::shared_ptr<ResourceInitData> initData,
std::shared_ptr<BinaryReader> reader) {
auto resource = std::make_shared<Cutscene>(initData);
std::shared_ptr<ResourceVersionFactory> factory = nullptr;
switch (resource->GetInitData()->ResourceVersion) {
case 0:
factory = std::make_shared<CutsceneFactoryV0>();
break;
}
if (factory == nullptr) {
SPDLOG_ERROR("Failed to load Cutscene with version {}", resource->GetInitData()->ResourceVersion);
return nullptr;
}
factory->ParseFileBinary(reader, resource);
return resource;
}
static inline uint32_t read_CMD_BBBB(std::shared_ptr<BinaryReader> reader) {
uint32_t v;
reader->Read((char*)&v, sizeof(uint32_t));
return v;
}
static inline uint32_t read_CMD_BBH(std::shared_ptr<BinaryReader> reader) {
uint32_t v;
reader->Read((char*)&v, sizeof(uint32_t));
// swap the half word to match endianness
if (reader->GetEndianness() != LUS::Endianness::Native) {
uint8_t* b = (uint8_t*)&v;
uint8_t tmp = b[2];
b[2] = b[3];
b[3] = tmp;
}
return v;
}
static inline uint32_t read_CMD_HBB(std::shared_ptr<BinaryReader> reader) {
uint32_t v;
reader->Read((char*)&v, sizeof(uint32_t));
// swap the half word to match endianness
if (reader->GetEndianness() != LUS::Endianness::Native) {
uint8_t* b = (uint8_t*)&v;
uint8_t tmp = b[0];
b[0] = b[1];
b[1] = tmp;
}
return v;
}
static inline uint32_t read_CMD_HH(std::shared_ptr<BinaryReader> reader) {
uint32_t v;
reader->Read((char*)&v, sizeof(uint32_t));
// swap the half words to match endianness
if (reader->GetEndianness() != LUS::Endianness::Native) {
uint8_t* b = (uint8_t*)&v;
uint8_t tmp = b[0];
b[0] = b[1];
b[1] = tmp;
tmp = b[2];
b[2] = b[3];
b[3] = tmp;
}
return v;
}
void LUS::CutsceneFactoryV0::ParseFileBinary(std::shared_ptr<BinaryReader> reader,
std::shared_ptr<IResource> resource) {
std::shared_ptr<Cutscene> cutscene = std::static_pointer_cast<Cutscene>(resource);
ResourceVersionFactory::ParseFileBinary(reader, cutscene);
uint32_t numEntries = reader->ReadUInt32();
cutscene->commands.reserve(numEntries);
cutscene->numCommands = reader->ReadUInt32();
cutscene->commands.push_back(cutscene->numCommands);
cutscene->endFrame = reader->ReadUInt32();
cutscene->commands.push_back(cutscene->endFrame);
// BENTODO detect the game
ParseFileBinaryMM(reader, cutscene);
}
void LUS::CutsceneFactoryV0::ParseFileBinaryOoT(std::shared_ptr<BinaryReader> reader,
std::shared_ptr<Cutscene> cutscene) {
while (true) {
uint32_t commandId = reader->ReadUInt32();
cutscene->commands.push_back(commandId);
switch (commandId) {
case (uint32_t)CutsceneCommands::SetCameraPos: {
cutscene->commands.push_back(read_CMD_HH(reader));
cutscene->commands.push_back(read_CMD_HH(reader));
while (true) {
uint32_t val = read_CMD_BBH(reader);
int8_t continueFlag = ((int8_t*)&val)[0];
cutscene->commands.push_back(val);
cutscene->commands.push_back(reader->ReadUInt32());
cutscene->commands.push_back(read_CMD_HH(reader));
cutscene->commands.push_back(read_CMD_HH(reader));
if (continueFlag == -1) {
break;
}
}
} break;
case (uint32_t)CutsceneCommands::SetCameraFocus: {
cutscene->commands.push_back(read_CMD_HH(reader));
cutscene->commands.push_back(read_CMD_HH(reader));
while (true) {
uint32_t val = read_CMD_BBH(reader);
int8_t continueFlag = ((int8_t*)&val)[0];
cutscene->commands.push_back(val);
cutscene->commands.push_back(reader->ReadUInt32());
cutscene->commands.push_back(read_CMD_HH(reader));
cutscene->commands.push_back(read_CMD_HH(reader));
if (continueFlag == -1) {
break;
}
}
break;
}
case (uint32_t)CutsceneCommands::SpecialAction: {
uint32_t size = reader->ReadUInt32();
cutscene->commands.push_back(size);
for (uint32_t i = 0; i < size; i++) {
cutscene->commands.push_back(read_CMD_HH(reader));
cutscene->commands.push_back(read_CMD_HH(reader));
cutscene->commands.push_back(reader->ReadUInt32());
cutscene->commands.push_back(reader->ReadUInt32());
cutscene->commands.push_back(reader->ReadUInt32());
cutscene->commands.push_back(reader->ReadUInt32());
cutscene->commands.push_back(reader->ReadUInt32());
cutscene->commands.push_back(reader->ReadUInt32());
cutscene->commands.push_back(reader->ReadUInt32());
cutscene->commands.push_back(reader->ReadUInt32());
cutscene->commands.push_back(reader->ReadUInt32());
cutscene->commands.push_back(reader->ReadUInt32());
}
break;
}
case (uint32_t)CutsceneCommands::SetLighting: {
uint32_t size = reader->ReadUInt32();
cutscene->commands.push_back(size);
for (uint32_t i = 0; i < size; i++) {
cutscene->commands.push_back(read_CMD_HH(reader));
cutscene->commands.push_back(read_CMD_HH(reader));
cutscene->commands.push_back(reader->ReadUInt32());
cutscene->commands.push_back(reader->ReadUInt32());
cutscene->commands.push_back(reader->ReadUInt32());
cutscene->commands.push_back(reader->ReadUInt32());
cutscene->commands.push_back(reader->ReadUInt32());
cutscene->commands.push_back(reader->ReadUInt32());
cutscene->commands.push_back(reader->ReadUInt32());
cutscene->commands.push_back(reader->ReadUInt32());
cutscene->commands.push_back(reader->ReadUInt32());
cutscene->commands.push_back(reader->ReadUInt32());
}
break;
}
case (uint32_t)CutsceneCommands::SetCameraPosLink: {
cutscene->commands.push_back(read_CMD_HH(reader));
cutscene->commands.push_back(read_CMD_HH(reader));
while (true) {
uint32_t val = read_CMD_BBH(reader);
int8_t continueFlag = ((int8_t*)&val)[0];
cutscene->commands.push_back(val);
cutscene->commands.push_back(reader->ReadUInt32());
cutscene->commands.push_back(read_CMD_HH(reader));
cutscene->commands.push_back(read_CMD_HH(reader));
if (continueFlag == -1) {
break;
}
}
break;
}
case (uint32_t)CutsceneCommands::SetCameraFocusLink: {
cutscene->commands.push_back(read_CMD_HH(reader));
cutscene->commands.push_back(read_CMD_HH(reader));
while (true) {
uint32_t val = read_CMD_BBH(reader);
int8_t continueFlag = ((int8_t*)&val)[0];
cutscene->commands.push_back(val);
cutscene->commands.push_back(reader->ReadUInt32());
cutscene->commands.push_back(read_CMD_HH(reader));
cutscene->commands.push_back(read_CMD_HH(reader));
if (continueFlag == -1) {
break;
}
}
break;
}
case (uint32_t)CutsceneCommands::Cmd09: {
uint32_t size = reader->ReadUInt32();
cutscene->commands.push_back(size);
for (uint32_t i = 0; i < size; i++) {
cutscene->commands.push_back(read_CMD_HH(reader));
cutscene->commands.push_back(read_CMD_HBB(reader));
cutscene->commands.push_back(read_CMD_BBH(reader));
}
break;
}
case 0x15:
case (uint32_t)CutsceneCommands::Unknown: {
uint32_t size = reader->ReadUInt32();
cutscene->commands.push_back(size);
for (uint32_t i = 0; i < size; i++) {
cutscene->commands.push_back(reader->ReadUInt32());
cutscene->commands.push_back(reader->ReadUInt32());
cutscene->commands.push_back(reader->ReadUInt32());
cutscene->commands.push_back(reader->ReadUInt32());
cutscene->commands.push_back(reader->ReadUInt32());
cutscene->commands.push_back(reader->ReadUInt32());
cutscene->commands.push_back(reader->ReadUInt32());
cutscene->commands.push_back(reader->ReadUInt32());
cutscene->commands.push_back(reader->ReadUInt32());
cutscene->commands.push_back(reader->ReadUInt32());
cutscene->commands.push_back(reader->ReadUInt32());
cutscene->commands.push_back(reader->ReadUInt32());
}
} break;
case (uint32_t)CutsceneCommands::Textbox: {
uint32_t size = reader->ReadUInt32();
cutscene->commands.push_back(size);
for (uint32_t i = 0; i < size; i++) {
cutscene->commands.push_back(read_CMD_HH(reader));
cutscene->commands.push_back(read_CMD_HH(reader));
cutscene->commands.push_back(read_CMD_HH(reader));
}
break;
}
case (uint32_t)CutsceneCommands::SetActorAction0:
case (uint32_t)CutsceneCommands::SetActorAction1:
case 17:
case 18:
case 23:
case 34:
case 39:
case 46:
case 76:
case 85:
case 93:
case 105:
case 107:
case 110:
case 119:
case 123:
case 138:
case 139:
case 144:
case (uint32_t)CutsceneCommands::SetActorAction2:
case 16:
case 24:
case 35:
case 40:
case 48:
case 64:
case 68:
case 70:
case 78:
case 80:
case 94:
case 116:
case 118:
case 120:
case 125:
case 131:
case 141:
case (uint32_t)CutsceneCommands::SetActorAction3:
case 36:
case 41:
case 50:
case 67:
case 69:
case 72:
case 74:
case 81:
case 106:
case 117:
case 121:
case 126:
case 132:
case (uint32_t)CutsceneCommands::SetActorAction4:
case 37:
case 42:
case 51:
case 53:
case 63:
case 65:
case 66:
case 75:
case 82:
case 108:
case 127:
case 133:
case (uint32_t)CutsceneCommands::SetActorAction5:
case 38:
case 43:
case 47:
case 54:
case 79:
case 83:
case 128:
case 135:
case (uint32_t)CutsceneCommands::SetActorAction6:
case 55:
case 77:
case 84:
case 90:
case 129:
case 136:
case (uint32_t)CutsceneCommands::SetActorAction7:
case 52:
case 57:
case 58:
case 88:
case 115:
case 130:
case 137:
case (uint32_t)CutsceneCommands::SetActorAction8:
case 60:
case 89:
case 111:
case 114:
case 134:
case 142:
case (uint32_t)CutsceneCommands::SetActorAction9:
case (uint32_t)CutsceneCommands::SetActorAction10: {
uint32_t size = reader->ReadUInt32();
cutscene->commands.push_back(size);
for (uint32_t i = 0; i < size; i++) {
cutscene->commands.push_back(read_CMD_HH(reader));
cutscene->commands.push_back(read_CMD_HH(reader));
cutscene->commands.push_back(read_CMD_HH(reader));
cutscene->commands.push_back(reader->ReadUInt32());
cutscene->commands.push_back(reader->ReadUInt32());
cutscene->commands.push_back(reader->ReadUInt32());
cutscene->commands.push_back(reader->ReadUInt32());
cutscene->commands.push_back(reader->ReadUInt32());
cutscene->commands.push_back(reader->ReadUInt32());
cutscene->commands.push_back(reader->ReadUInt32());
cutscene->commands.push_back(reader->ReadUInt32());
cutscene->commands.push_back(reader->ReadUInt32());
}
break;
}
case (uint32_t)CutsceneCommands::SetSceneTransFX: {
cutscene->commands.push_back(reader->ReadUInt32());
cutscene->commands.push_back(read_CMD_HH(reader));
cutscene->commands.push_back(read_CMD_HH(reader));
break;
}
case (uint32_t)CutsceneCommands::PlayBGM: {
uint32_t size = reader->ReadUInt32();
cutscene->commands.push_back(size);
for (uint32_t i = 0; i < size; i++) {
cutscene->commands.push_back(read_CMD_HH(reader));
cutscene->commands.push_back(read_CMD_HH(reader));
cutscene->commands.push_back(reader->ReadUInt32());
cutscene->commands.push_back(reader->ReadUInt32());
cutscene->commands.push_back(reader->ReadUInt32());
cutscene->commands.push_back(reader->ReadUInt32());
cutscene->commands.push_back(reader->ReadUInt32());
cutscene->commands.push_back(reader->ReadUInt32());
cutscene->commands.push_back(reader->ReadUInt32());
cutscene->commands.push_back(reader->ReadUInt32());
cutscene->commands.push_back(reader->ReadUInt32());
cutscene->commands.push_back(reader->ReadUInt32());
}
break;
}
case (uint32_t)CutsceneCommands::StopBGM: {
uint32_t size = reader->ReadUInt32();
cutscene->commands.push_back(size);
for (uint32_t i = 0; i < size; i++) {
cutscene->commands.push_back(read_CMD_HH(reader));
cutscene->commands.push_back(read_CMD_HH(reader));
cutscene->commands.push_back(reader->ReadUInt32());
cutscene->commands.push_back(reader->ReadUInt32());
cutscene->commands.push_back(reader->ReadUInt32());
cutscene->commands.push_back(reader->ReadUInt32());
cutscene->commands.push_back(reader->ReadUInt32());
cutscene->commands.push_back(reader->ReadUInt32());
cutscene->commands.push_back(reader->ReadUInt32());
cutscene->commands.push_back(reader->ReadUInt32());
cutscene->commands.push_back(reader->ReadUInt32());
cutscene->commands.push_back(reader->ReadUInt32());
}
break;
}
case (uint32_t)CutsceneCommands::FadeBGM: {
uint32_t size = reader->ReadUInt32();
cutscene->commands.push_back(size);
for (uint32_t i = 0; i < size; i++) {
cutscene->commands.push_back(read_CMD_HH(reader));
cutscene->commands.push_back(read_CMD_HH(reader));
cutscene->commands.push_back(reader->ReadUInt32());
cutscene->commands.push_back(reader->ReadUInt32());
cutscene->commands.push_back(reader->ReadUInt32());
cutscene->commands.push_back(reader->ReadUInt32());
cutscene->commands.push_back(reader->ReadUInt32());
cutscene->commands.push_back(reader->ReadUInt32());
cutscene->commands.push_back(reader->ReadUInt32());
cutscene->commands.push_back(reader->ReadUInt32());
cutscene->commands.push_back(reader->ReadUInt32());
cutscene->commands.push_back(reader->ReadUInt32());
}
break;
}
case (uint32_t)CutsceneCommands::SetTime: {
uint32_t size = reader->ReadUInt32();
cutscene->commands.push_back(size);
for (uint32_t i = 0; i < size; i++) {
cutscene->commands.push_back(read_CMD_HH(reader));
cutscene->commands.push_back(read_CMD_HBB(reader));
cutscene->commands.push_back(reader->ReadUInt32());
}
break;
}
case (uint32_t)CutsceneCommands::Terminator: {
cutscene->commands.push_back(reader->ReadUInt32());
cutscene->commands.push_back(read_CMD_HH(reader));
cutscene->commands.push_back(read_CMD_HH(reader));
break;
}
case 0xFFFFFFFF: // CS_END
{
cutscene->commands.push_back(reader->ReadUInt32());
return;
}
default:
SPDLOG_TRACE("CutsceneV0: Unknown command {}\n", commandId);
// error?
break;
}
}
}
void LUS::CutsceneFactoryV0::ParseFileBinaryMM(std::shared_ptr<BinaryReader> reader,
std::shared_ptr<Cutscene> cutscene) {
while (true) {
uint32_t command = reader->ReadUInt32();
cutscene->commands.push_back(command);
if (((command >= CS_CMD_ACTOR_CUE_100) && (command <= CS_CMD_ACTOR_CUE_149)) ||
(command == CS_CMD_ACTOR_CUE_201) ||
((command >= CS_CMD_ACTOR_CUE_450) && (command <= CS_CMD_ACTOR_CUE_599))) {
goto actorCue;
}
switch (command) {
case CS_CMD_TEXT: {
uint32_t size = reader->ReadUInt32();
// uint8_t type = reader->ReadInt8();
cutscene->commands.push_back(size);
// BENTODO do we need to read the type?
for (uint32_t i = 0; i < size; i++) {
cutscene->commands.push_back(read_CMD_HH(reader));
cutscene->commands.push_back(read_CMD_HH(reader));
cutscene->commands.push_back(read_CMD_HH(reader));
}
break;
}
case CS_CMD_CAMERA_SPLINE: {
uint32_t size = reader->ReadUInt32();
cutscene->commands.push_back(size);
for (uint32_t i = 0; i < (size / 4); i++) {
cutscene->commands.push_back(read_CMD_HH(reader));
}
break;
}
case CS_CMD_MISC: {
uint32_t size = reader->ReadUInt32();
cutscene->commands.push_back(size);
for (uint32_t i = 0; i < size; i++) {
cutscene->commands.push_back(read_CMD_HH(reader));
cutscene->commands.push_back(read_CMD_HH(reader));
}
break;
}
case CS_CMD_LIGHT_SETTING: {
uint32_t size = reader->ReadUInt32();
cutscene->commands.push_back(size);
for (uint32_t i = 0; i < size; i++) {
cutscene->commands.push_back(read_CMD_BBH(reader));
cutscene->commands.push_back(read_CMD_HH(reader));
}
break;
}
case CS_CMD_TRANSITION: {
uint32_t size = reader->ReadUInt32();
cutscene->commands.push_back(size);
for (uint32_t i = 0; i < size; i++) {
cutscene->commands.push_back(read_CMD_HH(reader));
cutscene->commands.push_back(read_CMD_HH(reader));
}
break;
}
case CS_CMD_MOTION_BLUR: {
uint32_t size = reader->ReadUInt32();
cutscene->commands.push_back(size);
for (uint32_t i = 0; i < size; i++) {
cutscene->commands.push_back(read_CMD_HH(reader));
cutscene->commands.push_back(read_CMD_HH(reader));
}
break;
}
case CS_CMD_GIVE_TATL: {
uint32_t size = reader->ReadUInt32();
cutscene->commands.push_back(size);
for (uint32_t i = 0; i < size; i++) {
cutscene->commands.push_back(read_CMD_HH(reader));
cutscene->commands.push_back(read_CMD_HH(reader));
}
break;
}
case CS_CMD_START_SEQ:
case CS_CMD_STOP_SEQ: {
uint32_t size = reader->ReadUInt32();
cutscene->commands.push_back(size);
for (uint32_t i = 0; i < size; i++) {
cutscene->commands.push_back(read_CMD_BBH(reader));
cutscene->commands.push_back(read_CMD_HH(reader));
}
break;
}
case CS_CMD_SFX_REVERB_INDEX_2:
case CS_CMD_SFX_REVERB_INDEX_1:
case CS_CMD_MODIFY_SEQ:
case CS_CMD_START_AMBIENCE:
case CS_CMD_FADE_OUT_AMBIENCE:
case CS_CMD_DESTINATION:
case CS_CMD_CHOOSE_CREDITS_SCENES:
case CS_CMD_UNK_DATA_FA:
case CS_CMD_UNK_DATA_FE:
case CS_CMD_UNK_DATA_FF:
case CS_CMD_UNK_DATA_100:
case CS_CMD_UNK_DATA_101:
case CS_CMD_UNK_DATA_102:
case CS_CMD_UNK_DATA_103:
case CS_CMD_UNK_DATA_104:
case CS_CMD_UNK_DATA_105:
case CS_CMD_UNK_DATA_108:
case CS_CMD_UNK_DATA_109: {
uint32_t size = reader->ReadUInt32();
cutscene->commands.push_back(size);
for (uint32_t i = 0; i < size; i++) {
cutscene->commands.push_back(read_CMD_BBH(reader));
cutscene->commands.push_back(read_CMD_HH(reader));
}
break;
}
case CS_CMD_TRANSITION_GENERAL: {
uint32_t size = reader->ReadUInt32();
cutscene->commands.push_back(size);
for (uint32_t i = 0; i < size; i++) {
cutscene->commands.push_back(read_CMD_HH(reader));
cutscene->commands.push_back(read_CMD_HBB(reader));
cutscene->commands.push_back(read_CMD_BBBB(reader));
}
break;
}
case CS_CMD_FADE_OUT_SEQ: {
uint32_t size = reader->ReadUInt32();
cutscene->commands.push_back(size);
for (uint32_t i = 0; i < size; i++) {
cutscene->commands.push_back(read_CMD_HH(reader));
cutscene->commands.push_back(read_CMD_HH(reader));
}
break;
}
case CS_CMD_TIME: {
uint32_t size = reader->ReadUInt32();
cutscene->commands.push_back(size);
for (uint32_t i = 0; i < size; i++) {
cutscene->commands.push_back(read_CMD_HH(reader));
cutscene->commands.push_back(read_CMD_HBB(reader));
}
break;
}
case CS_CMD_PLAYER_CUE: {
actorCue:
uint32_t size = reader->ReadUInt32();
cutscene->commands.push_back(size);
for (uint32_t i = 0; i < size; i++) {
cutscene->commands.push_back(read_CMD_HH(reader));
cutscene->commands.push_back(read_CMD_HH(reader));
cutscene->commands.push_back(read_CMD_HH(reader));
cutscene->commands.push_back(reader->ReadUInt32());
cutscene->commands.push_back(reader->ReadUInt32());
cutscene->commands.push_back(reader->ReadUInt32());
cutscene->commands.push_back(reader->ReadUInt32());
cutscene->commands.push_back(reader->ReadUInt32());
cutscene->commands.push_back(reader->ReadUInt32());
cutscene->commands.push_back(reader->ReadUInt32());
cutscene->commands.push_back(reader->ReadUInt32());
cutscene->commands.push_back(reader->ReadUInt32());
}
break;
}
case CS_CMD_RUMBLE: {
uint32_t size = reader->ReadUInt32();
cutscene->commands.push_back(size);
for (uint32_t i = 0; i < size; i++) {
cutscene->commands.push_back(read_CMD_HH(reader));
cutscene->commands.push_back(read_CMD_HBB(reader));
cutscene->commands.push_back(read_CMD_BBBB(reader));
}
break;
}
case 0xFFFFFFFF: {
cutscene->commands.push_back(reader->ReadUInt32());
return;
}
default:
SPDLOG_TRACE("CutsceneV0: Unknown command {}\n", command);
// error?
break;
}
}
}
} // namespace LUS

View File

@ -0,0 +1,25 @@
#pragma once
#include "Resource.h"
#include "ResourceFactory.h"
namespace LUS {
class Cutscene;
class CutsceneFactory : public ResourceFactory
{
public:
std::shared_ptr<IResource>
ReadResource(std::shared_ptr<ResourceInitData> initData, std::shared_ptr<BinaryReader> reader) override;
};
class CutsceneFactoryV0 : public ResourceVersionFactory
{
public:
void ParseFileBinary(std::shared_ptr<BinaryReader> reader, std::shared_ptr<IResource> resource) override;
private:
void ParseFileBinaryOoT(std::shared_ptr<BinaryReader> reader,std::shared_ptr<Cutscene> cutscene);
void ParseFileBinaryMM(std::shared_ptr<BinaryReader> reader, std::shared_ptr<Cutscene> cutscene);
};
}; // namespace LUS

View File

@ -0,0 +1,113 @@
#include "2s2h/resource/importer/PathFactory.h"
#include "2s2h/resource/type/Path.h"
#include "spdlog/spdlog.h"
namespace LUS {
std::shared_ptr<IResource>
PathFactory::ReadResource(std::shared_ptr<ResourceInitData> initData, std::shared_ptr<BinaryReader> reader) {
auto resource = std::make_shared<Path>(initData);
std::shared_ptr<ResourceVersionFactory> factory = nullptr;
switch (resource->GetInitData()->ResourceVersion) {
case 0:
factory = std::make_shared<PathFactoryV0>();
break;
}
if (factory == nullptr) {
SPDLOG_ERROR("Failed to load Path with version {}", resource->GetInitData()->ResourceVersion);
return nullptr;
}
factory->ParseFileBinary(reader, resource);
return resource;
}
void LUS::PathFactoryV0::ParseFileBinary(std::shared_ptr<BinaryReader> reader,
std::shared_ptr<IResource> resource) {
std::shared_ptr<Path> path = std::static_pointer_cast<Path>(resource);
ResourceVersionFactory::ParseFileBinary(reader, path);
path->numPaths = reader->ReadUInt32();
path->paths.reserve(path->numPaths);
for (uint32_t k = 0; k < path->numPaths; k++) {
std::vector<Vec3s> points;
uint32_t pointCount = reader->ReadUInt32();
points.reserve(pointCount);
for (uint32_t i = 0; i < pointCount; i++) {
Vec3s point;
point.x = reader->ReadInt16();
point.y = reader->ReadInt16();
point.z = reader->ReadInt16();
points.push_back(point);
}
PathData pathDataEntry;
pathDataEntry.count = pointCount;
path->paths.push_back(points);
pathDataEntry.points = path->paths.back().data();
path->pathData.push_back(pathDataEntry);
}
}
std::shared_ptr<IResource> PathFactoryMM::ReadResource(std::shared_ptr<ResourceInitData> initData,
std::shared_ptr<BinaryReader> reader) {
auto resource = std::make_shared<Path>(initData);
std::shared_ptr<ResourceVersionFactory> factory = nullptr;
switch (resource->GetInitData()->ResourceVersion) {
case 0:
factory = std::make_shared<PathFactoryMMV0>();
break;
}
if (factory == nullptr) {
SPDLOG_ERROR("Failed to load Path with version {}", resource->GetInitData()->ResourceVersion);
return nullptr;
}
factory->ParseFileBinary(reader, resource);
return resource;
}
void LUS::PathFactoryMMV0::ParseFileBinary(std::shared_ptr<BinaryReader> reader, std::shared_ptr<IResource> resource) {
std::shared_ptr<PathMM> path = std::static_pointer_cast<PathMM>(resource);
ResourceVersionFactory::ParseFileBinary(reader, path);
path->numPaths = reader->ReadUInt32();
path->paths.reserve(path->numPaths);
for (uint32_t k = 0; k < path->numPaths; k++) {
std::vector<Vec3s> points;
uint32_t pointCount = reader->ReadUInt32();
uint8_t additionalPathIndex = reader->ReadUByte();
int16_t customValue = reader->ReadInt16();
for (uint32_t i = 0; i < pointCount; i++) {
Vec3s point;
point.x = reader->ReadInt16();
point.y = reader->ReadInt16();
point.z = reader->ReadInt16();
points.push_back(point);
}
PathDataMM pathDataEntry;
pathDataEntry.count = pointCount;
pathDataEntry.additionalPathIndex = additionalPathIndex;
pathDataEntry.customValue = customValue;
path->paths.push_back(points);
pathDataEntry.points = path->paths.back().data();
path->pathData.push_back(pathDataEntry);
}
}
} // namespace LUS

View File

@ -0,0 +1,31 @@
#pragma once
#include "Resource.h"
#include "ResourceFactory.h"
namespace LUS {
class PathFactory : public ResourceFactory
{
public:
std::shared_ptr<IResource>
ReadResource(std::shared_ptr<ResourceInitData> initData, std::shared_ptr<BinaryReader> reader) override;
};
class PathFactoryV0 : public ResourceVersionFactory
{
public:
void ParseFileBinary(std::shared_ptr<BinaryReader> reader, std::shared_ptr<IResource> resource) override;
};
class PathFactoryMM : public ResourceFactory {
public:
std::shared_ptr<IResource> ReadResource(std::shared_ptr<ResourceInitData> initData,
std::shared_ptr<BinaryReader> reader) override;
};
class PathFactoryMMV0 : public ResourceVersionFactory {
public:
void ParseFileBinary(std::shared_ptr<BinaryReader> reader, std::shared_ptr<IResource> resource) override;
};
}; // namespace LUS

View File

@ -0,0 +1,41 @@
#include "2s2h/resource/importer/PlayerAnimationFactory.h"
#include "2s2h/resource/type/PlayerAnimation.h"
#include "spdlog/spdlog.h"
namespace LUS {
std::shared_ptr<IResource>
PlayerAnimationFactory::ReadResource(std::shared_ptr<ResourceInitData> initData, std::shared_ptr<BinaryReader> reader) {
auto resource = std::make_shared<PlayerAnimation>(initData);
std::shared_ptr<ResourceVersionFactory> factory = nullptr;
switch (resource->GetInitData()->ResourceVersion) {
case 0:
factory = std::make_shared<PlayerAnimationFactoryV0>();
break;
}
if (factory == nullptr)
{
SPDLOG_ERROR("Failed to load PlayerAnimation with version {}", resource->GetInitData()->ResourceVersion);
return nullptr;
}
factory->ParseFileBinary(reader, resource);
return resource;
}
void LUS::PlayerAnimationFactoryV0::ParseFileBinary(std::shared_ptr<BinaryReader> reader,
std::shared_ptr<IResource> resource)
{
std::shared_ptr<PlayerAnimation> playerAnimation = std::static_pointer_cast<PlayerAnimation>(resource);
ResourceVersionFactory::ParseFileBinary(reader, playerAnimation);
uint32_t numEntries = reader->ReadUInt32();
playerAnimation->limbRotData.reserve(numEntries);
for (uint32_t i = 0; i < numEntries; i++) {
playerAnimation->limbRotData.push_back(reader->ReadInt16());
}
}
} // namespace LUS

View File

@ -0,0 +1,17 @@
#pragma once
#include "Resource.h"
#include "ResourceFactory.h"
namespace LUS {
class PlayerAnimationFactory : public ResourceFactory {
public:
std::shared_ptr<IResource>
ReadResource(std::shared_ptr<ResourceInitData> initData, std::shared_ptr<BinaryReader> reader) override;
};
class PlayerAnimationFactoryV0 : public ResourceVersionFactory {
public:
void ParseFileBinary(std::shared_ptr<BinaryReader> reader, std::shared_ptr<IResource> resource) override;
};
}; // namespace LUS

View File

@ -0,0 +1,140 @@
#include "spdlog/spdlog.h"
#include "2s2h/resource/importer/SceneFactory.h"
#include "2s2h/resource/type/Scene.h"
#include "2s2h/resource/type/scenecommand/SceneCommand.h"
#include "2s2h/resource/importer/scenecommand/SetLightingSettingsFactory.h"
#include "2s2h/resource/importer/scenecommand/SetWindSettingsFactory.h"
#include "2s2h/resource/importer/scenecommand/SetExitListFactory.h"
#include "2s2h/resource/importer/scenecommand/SetTimeSettingsFactory.h"
#include "2s2h/resource/importer/scenecommand/SetSkyboxModifierFactory.h"
#include "2s2h/resource/importer/scenecommand/SetEchoSettingsFactory.h"
#include "2s2h/resource/importer/scenecommand/SetSoundSettingsFactory.h"
#include "2s2h/resource/importer/scenecommand/SetSkyboxSettingsFactory.h"
#include "2s2h/resource/importer/scenecommand/SetRoomBehaviorFactory.h"
#include "2s2h/resource/importer/scenecommand/SetCsCameraFactory.h"
#include "2s2h/resource/importer/scenecommand/SetCameraSettingsFactory.h"
#include "2s2h/resource/importer/scenecommand/SetRoomListFactory.h"
#include "2s2h/resource/importer/scenecommand/SetCollisionHeaderFactory.h"
#include "2s2h/resource/importer/scenecommand/SetEntranceListFactory.h"
#include "2s2h/resource/importer/scenecommand/SetSpecialObjectsFactory.h"
#include "2s2h/resource/importer/scenecommand/SetObjectListFactory.h"
#include "2s2h/resource/importer/scenecommand/SetStartPositionListFactory.h"
#include "2s2h/resource/importer/scenecommand/SetActorListFactory.h"
#include "2s2h/resource/importer/scenecommand/SetTransitionActorListFactory.h"
#include "2s2h/resource/importer/scenecommand/EndMarkerFactory.h"
#include "2s2h/resource/importer/scenecommand/SetAlternateHeadersFactory.h"
#include "2s2h/resource/importer/scenecommand/SetPathwaysFactory.h"
#include "2s2h/resource/importer/scenecommand/SetCutscenesFactory.h"
#include "2s2h/resource/importer/scenecommand/SetLightListFactory.h"
#include "2s2h/resource/importer/scenecommand/SetMeshFactory.h"
#include "2s2h/resource/importer/scenecommand/SetAnimatedMaterialListFactory.h"
#include "2s2h/resource/importer/scenecommand/SetMinimapListFactory.h"
#include "2s2h/resource/importer/scenecommand/SetMinimapChestsFactory.h"
#include "2s2h/resource/importer/scenecommand/SetActorCutsceneListFactory.h"
namespace LUS {
std::shared_ptr<IResource>
SceneFactory::ReadResource(std::shared_ptr<ResourceInitData> initData, std::shared_ptr<BinaryReader> reader) {
if (SceneFactory::sceneCommandFactories.empty()) {
SceneFactory::sceneCommandFactories[LUS::SceneCommandID::SetLightingSettings] = std::make_shared<SetLightingSettingsFactory>();
SceneFactory::sceneCommandFactories[LUS::SceneCommandID::SetWind] = std::make_shared<SetWindSettingsFactory>();
SceneFactory::sceneCommandFactories[LUS::SceneCommandID::SetExitList] = std::make_shared<SetExitListFactory>();
SceneFactory::sceneCommandFactories[LUS::SceneCommandID::SetTimeSettings] = std::make_shared<SetTimeSettingsFactory>();
SceneFactory::sceneCommandFactories[LUS::SceneCommandID::SetSkyboxModifier] = std::make_shared<SetSkyboxModifierFactory>();
SceneFactory::sceneCommandFactories[LUS::SceneCommandID::SetEchoSettings] = std::make_shared<SetEchoSettingsFactory>();
SceneFactory::sceneCommandFactories[LUS::SceneCommandID::SetSoundSettings] = std::make_shared<SetSoundSettingsFactory>();
SceneFactory::sceneCommandFactories[LUS::SceneCommandID::SetSkyboxSettings] = std::make_shared<SetSkyboxSettingsFactory>();
SceneFactory::sceneCommandFactories[LUS::SceneCommandID::SetRoomBehavior] = std::make_shared<SetRoomBehaviorMMFactory>();
SceneFactory::sceneCommandFactories[LUS::SceneCommandID::SetCsCamera] = std::make_shared<SetCsCameraFactory>();
SceneFactory::sceneCommandFactories[LUS::SceneCommandID::SetCameraSettings] = std::make_shared<SetCameraSettingsFactory>();
SceneFactory::sceneCommandFactories[LUS::SceneCommandID::SetRoomList] = std::make_shared<SetRoomListFactory>();
SceneFactory::sceneCommandFactories[LUS::SceneCommandID::SetCollisionHeader] = std::make_shared<SetCollisionHeaderFactory>();
SceneFactory::sceneCommandFactories[LUS::SceneCommandID::SetEntranceList] = std::make_shared<SetEntranceListFactory>();
SceneFactory::sceneCommandFactories[LUS::SceneCommandID::SetSpecialObjects] = std::make_shared<SetSpecialObjectsFactory>();
SceneFactory::sceneCommandFactories[LUS::SceneCommandID::SetObjectList] = std::make_shared<SetObjectListFactory>();
SceneFactory::sceneCommandFactories[LUS::SceneCommandID::SetStartPositionList] = std::make_shared<SetStartPositionListFactory>();
SceneFactory::sceneCommandFactories[LUS::SceneCommandID::SetActorList] = std::make_shared<SetActorListFactory>();
SceneFactory::sceneCommandFactories[LUS::SceneCommandID::SetTransitionActorList] = std::make_shared<SetTransitionActorListFactory>();
SceneFactory::sceneCommandFactories[LUS::SceneCommandID::EndMarker] = std::make_shared<EndMarkerFactory>();
SceneFactory::sceneCommandFactories[LUS::SceneCommandID::SetAlternateHeaders] = std::make_shared<SetAlternateHeadersFactory>();
// TODO should we use a different custom scene command like cutscenes?
SceneFactory::sceneCommandFactories[LUS::SceneCommandID::SetPathways] = std::make_shared<SetPathwaysMMFactory>();
SceneFactory::sceneCommandFactories[LUS::SceneCommandID::SetCutscenes] = std::make_shared<SetCutscenesFactory>();
SceneFactory::sceneCommandFactories[LUS::SceneCommandID::SetLightList] = std::make_shared<SetLightListFactory>();
SceneFactory::sceneCommandFactories[LUS::SceneCommandID::SetMesh] = std::make_shared<SetMeshFactory>();
SceneFactory::sceneCommandFactories[LUS::SceneCommandID::SetCutscenesMM] = std::make_shared<SetCutsceneFactoryMM>();
SceneFactory::sceneCommandFactories[LUS::SceneCommandID::SetAnimatedMaterialList] =
std::make_shared<SetAnimatedMaterialListFactory>();
SceneFactory::sceneCommandFactories[LUS::SceneCommandID::SetMinimapList] =
std::make_shared<SetMinimapListFactory>();
SceneFactory::sceneCommandFactories[LUS::SceneCommandID::SetMinimapChests] =
std::make_shared<SetMinimapChestsFactory>();
SceneFactory::sceneCommandFactories[LUS::SceneCommandID::SetActorCutsceneList] =
std::make_shared<SetActorCutsceneListFactory>();
}
auto resource = std::make_shared<Scene>(initData);
std::shared_ptr<ResourceVersionFactory> factory = nullptr;
switch (resource->GetInitData()->ResourceVersion) {
case 0:
factory = std::make_shared<SceneFactoryV0>();
break;
}
if (factory == nullptr) {
SPDLOG_ERROR("Failed to load Scene with version {}", resource->GetInitData()->ResourceVersion);
return nullptr;
}
factory->ParseFileBinary(reader, resource);
return resource;
}
void SceneFactoryV0::ParseFileBinary(std::shared_ptr<BinaryReader> reader,
std::shared_ptr<IResource> resource)
{
std::shared_ptr<Scene> scene = std::static_pointer_cast<Scene>(resource);
ResourceVersionFactory::ParseFileBinary(reader, scene);
ParseSceneCommands(scene, reader);
}
void SceneFactoryV0::ParseSceneCommands(std::shared_ptr<Scene> scene, std::shared_ptr<BinaryReader> reader) {
uint32_t commandCount = reader->ReadUInt32();
scene->commands.reserve(commandCount);
for (uint32_t i = 0; i < commandCount; i++) {
scene->commands.push_back(ParseSceneCommand(scene, reader, i));
}
}
std::shared_ptr<ISceneCommand> SceneFactoryV0::ParseSceneCommand(std::shared_ptr<Scene> scene,
std::shared_ptr<BinaryReader> reader, uint32_t index) {
SceneCommandID cmdID = (SceneCommandID)reader->ReadInt32();
reader->Seek(-sizeof(int32_t), SeekOffsetType::Current);
std::shared_ptr<ISceneCommand> result = nullptr;
std::shared_ptr<SceneCommandFactory> commandFactory = SceneFactory::sceneCommandFactories[cmdID];
if (commandFactory != nullptr) {
auto initData = std::make_shared<ResourceInitData>();
initData->Id = scene->GetInitData()->Id;
initData->Type = ResourceType::SOH_SceneCommand;
initData->Path = scene->GetInitData()->Path + "/SceneCommand" + std::to_string(index);
initData->ResourceVersion = scene->GetInitData()->ResourceVersion;
result = std::static_pointer_cast<ISceneCommand>(commandFactory->ReadResource(initData, reader));
// Cache the resource?
}
if (result == nullptr) {
SPDLOG_ERROR("Failed to load scene command of type {} in scene {}", (uint32_t)cmdID, scene->GetInitData()->Path);
}
return result;
}
} // namespace LUS

View File

@ -0,0 +1,29 @@
#pragma once
#include "2s2h/resource/type/Scene.h"
#include "2s2h/resource/type/scenecommand/SceneCommand.h"
#include "2s2h/resource/importer/scenecommand/SceneCommandFactory.h"
#include "Resource.h"
#include "ResourceFactory.h"
namespace LUS {
class SceneFactory : public ResourceFactory {
public:
std::shared_ptr<IResource>
ReadResource(std::shared_ptr<ResourceInitData> initData, std::shared_ptr<BinaryReader> reader) override;
// Doing something very similar to what we do on the ResourceLoader.
// Eventually, scene commands should be moved up to the ResourceLoader as well.
// They can not right now because the exporter does not give them a proper resource type enum value,
// and the exporter does not export the commands with a proper OTR header.
static inline std::unordered_map<SceneCommandID, std::shared_ptr<SceneCommandFactory>> sceneCommandFactories;
};
class SceneFactoryV0 : public ResourceVersionFactory {
public:
void ParseFileBinary(std::shared_ptr<BinaryReader> reader, std::shared_ptr<IResource> resource) override;
void ParseSceneCommands(std::shared_ptr<Scene> scene, std::shared_ptr<BinaryReader> reader);
protected:
std::shared_ptr<ISceneCommand> ParseSceneCommand(std::shared_ptr<Scene> scene, std::shared_ptr<BinaryReader> reader, uint32_t index);
};
}; // namespace LUS

View File

@ -0,0 +1,158 @@
#include "2s2h/resource/importer/SkeletonFactory.h"
#include "2s2h/resource/type/Skeleton.h"
#include <spdlog/spdlog.h>
#include <libultraship/libultraship.h>
namespace LUS {
std::shared_ptr<IResource>
SkeletonFactory::ReadResource(std::shared_ptr<ResourceInitData> initData, std::shared_ptr<BinaryReader> reader) {
auto resource = std::make_shared<Skeleton>(initData);
std::shared_ptr<ResourceVersionFactory> factory = nullptr;
switch (resource->GetInitData()->ResourceVersion) {
case 0:
factory = std::make_shared<SkeletonFactoryV0>();
break;
}
if (factory == nullptr) {
SPDLOG_ERROR("Failed to load Skeleton with version {}", resource->GetInitData()->ResourceVersion);
return nullptr;
}
factory->ParseFileBinary(reader, resource);
return resource;
}
std::shared_ptr<IResource>
SkeletonFactory::ReadResourceXML(std::shared_ptr<ResourceInitData> initData, tinyxml2::XMLElement *reader) {
auto resource = std::make_shared<Skeleton>(initData);
std::shared_ptr<ResourceVersionFactory> factory = nullptr;
switch (resource->GetInitData()->ResourceVersion) {
case 0:
factory = std::make_shared<SkeletonFactoryV0>();
break;
}
if (factory == nullptr) {
SPDLOG_ERROR("Failed to load Skeleton with version {}", resource->GetInitData()->ResourceVersion);
return nullptr;
}
factory->ParseFileXML(reader, resource);
return resource;
}
void SkeletonFactoryV0::ParseFileBinary(std::shared_ptr<BinaryReader> reader,
std::shared_ptr<IResource> resource)
{
std::shared_ptr<Skeleton> skeleton = std::static_pointer_cast<Skeleton>(resource);
ResourceVersionFactory::ParseFileBinary(reader, skeleton);
skeleton->type = (SkeletonType)reader->ReadInt8();
skeleton->limbType = (LimbType)reader->ReadInt8();
skeleton->limbCount = reader->ReadUInt32();
skeleton->dListCount = reader->ReadUInt32();
skeleton->limbTableType = (LimbType)reader->ReadInt8();
skeleton->limbTableCount = reader->ReadUInt32();
skeleton->limbTable.reserve(skeleton->limbTableCount);
for (uint32_t i = 0; i < skeleton->limbTableCount; i++) {
std::string limbPath = reader->ReadString();
skeleton->limbTable.push_back(limbPath);
}
if (skeleton->type == LUS::SkeletonType::Curve) {
skeleton->skeletonData.skelCurveLimbList.limbCount = skeleton->limbCount;
skeleton->curveLimbArray.reserve(skeleton->skeletonData.skelCurveLimbList.limbCount);
} else if (skeleton->type == LUS::SkeletonType::Flex) {
skeleton->skeletonData.flexSkeletonHeader.dListCount = skeleton->dListCount;
}
if (skeleton->type == LUS::SkeletonType::Normal) {
skeleton->skeletonData.skeletonHeader.limbCount = skeleton->limbCount;
skeleton->standardLimbArray.reserve(skeleton->skeletonData.skeletonHeader.limbCount);
} else if (skeleton->type == LUS::SkeletonType::Flex) {
skeleton->skeletonData.flexSkeletonHeader.sh.limbCount = skeleton->limbCount;
skeleton->standardLimbArray.reserve(skeleton->skeletonData.flexSkeletonHeader.sh.limbCount);
}
for (size_t i = 0; i < skeleton->limbTable.size(); i++) {
std::string limbStr = skeleton->limbTable[i];
auto limb = LUS::Context::GetInstance()->GetResourceManager()->LoadResourceProcess(limbStr.c_str());
skeleton->skeletonHeaderSegments.push_back(limb ? limb->GetRawPointer() : nullptr);
}
if (skeleton->type == LUS::SkeletonType::Normal) {
skeleton->skeletonData.skeletonHeader.segment = (void**)skeleton->skeletonHeaderSegments.data();
} else if (skeleton->type == LUS::SkeletonType::Flex) {
skeleton->skeletonData.flexSkeletonHeader.sh.segment = (void**)skeleton->skeletonHeaderSegments.data();
} else if (skeleton->type == LUS::SkeletonType::Curve) {
skeleton->skeletonData.skelCurveLimbList.limbs = (SkelCurveLimb**)skeleton->skeletonHeaderSegments.data();
} else {
SPDLOG_ERROR("unknown skeleton type {}", (uint32_t)skeleton->type);
}
skeleton->skeletonData.skeletonHeader.skeletonType = (uint8_t)skeleton->type;
}
void SkeletonFactoryV0::ParseFileXML(tinyxml2::XMLElement* reader, std::shared_ptr<IResource> resource)
{
std::shared_ptr<Skeleton> skel = std::static_pointer_cast<Skeleton>(resource);
std::string skeletonType = reader->Attribute("Type");
// std::string skeletonLimbType = reader->Attribute("LimbType");
int numLimbs = reader->IntAttribute("LimbCount");
int numDLs = reader->IntAttribute("DisplayListCount");
if (skeletonType == "Flex") {
skel->type = SkeletonType::Flex;
} else if (skeletonType == "Curve") {
skel->type = SkeletonType::Curve;
} else if (skeletonType == "Normal") {
skel->type = SkeletonType::Normal;
}
skel->type = SkeletonType::Flex;
skel->limbType = LimbType::LOD;
// if (skeletonLimbType == "Standard")
// skel->limbType = LimbType::Standard;
// else if (skeletonLimbType == "LOD")
// skel->limbType = LimbType::LOD;
// else if (skeletonLimbType == "Curve")
// skel->limbType = LimbType::Curve;
// else if (skeletonLimbType == "Skin")
// skel->limbType = LimbType::Skin;
// else if (skeletonLimbType == "Legacy")
// Sskel->limbType = LimbType::Legacy;
auto child = reader->FirstChildElement();
skel->limbCount = numLimbs;
skel->dListCount = numDLs;
while (child != nullptr) {
std::string childName = child->Name();
if (childName == "SkeletonLimb") {
std::string limbName = child->Attribute("Path");
skel->limbTable.push_back(limbName);
auto limb = LUS::Context::GetInstance()->GetResourceManager()->LoadResourceProcess(limbName.c_str());
skel->skeletonHeaderSegments.push_back(limb ? limb->GetRawPointer() : nullptr);
}
child = child->NextSiblingElement();
}
skel->skeletonData.flexSkeletonHeader.sh.limbCount = skel->limbCount;
skel->skeletonData.flexSkeletonHeader.sh.segment = (void**)skel->skeletonHeaderSegments.data();
skel->skeletonData.flexSkeletonHeader.dListCount = skel->dListCount;
skel->skeletonData.skeletonHeader.skeletonType = (uint8_t)skel->type;
}
} // namespace LUS

View File

@ -0,0 +1,23 @@
#pragma once
#include "Resource.h"
#include "ResourceFactory.h"
namespace LUS {
class SkeletonFactory : public ResourceFactory
{
public:
std::shared_ptr<IResource>
ReadResource(std::shared_ptr<ResourceInitData> initData, std::shared_ptr<BinaryReader> reader) override;
std::shared_ptr<IResource>
ReadResourceXML(std::shared_ptr<ResourceInitData> initData, tinyxml2::XMLElement *reader) override;
};
class SkeletonFactoryV0 : public ResourceVersionFactory
{
public:
void ParseFileBinary(std::shared_ptr<BinaryReader> reader, std::shared_ptr<IResource> resource) override;
void ParseFileXML(tinyxml2::XMLElement* reader, std::shared_ptr<IResource> resource) override;
};
}; // namespace LUS

View File

@ -0,0 +1,271 @@
#include "2s2h/resource/importer/SkeletonLimbFactory.h"
#include "2s2h/resource/type/SkeletonLimb.h"
#include "spdlog/spdlog.h"
#include "libultraship/libultraship.h"
namespace LUS {
std::shared_ptr<IResource>
SkeletonLimbFactory::ReadResource(std::shared_ptr<ResourceInitData> initData, std::shared_ptr<BinaryReader> reader) {
auto resource = std::make_shared<SkeletonLimb>(initData);
std::shared_ptr<ResourceVersionFactory> factory = nullptr;
switch (resource->GetInitData()->ResourceVersion) {
case 0:
factory = std::make_shared<SkeletonLimbFactoryV0>();
break;
}
if (factory == nullptr) {
SPDLOG_ERROR("Failed to load Skeleton Limb with version {}", resource->GetInitData()->ResourceVersion);
return nullptr;
}
factory->ParseFileBinary(reader, resource);
return resource;
}
std::shared_ptr<IResource>
SkeletonLimbFactory::ReadResourceXML(std::shared_ptr<ResourceInitData> initData, tinyxml2::XMLElement *reader) {
auto resource = std::make_shared<SkeletonLimb>(initData);
std::shared_ptr<ResourceVersionFactory> factory = nullptr;
switch (resource->GetInitData()->ResourceVersion) {
case 0:
factory = std::make_shared<SkeletonLimbFactoryV0>();
break;
}
if (factory == nullptr) {
SPDLOG_ERROR("Failed to load Skeleton Limb with version {}", resource->GetInitData()->ResourceVersion);
return nullptr;
}
factory->ParseFileXML(reader, resource);
return resource;
}
void LUS::SkeletonLimbFactoryV0::ParseFileBinary(std::shared_ptr<BinaryReader> reader,
std::shared_ptr<IResource> resource)
{
std::shared_ptr<SkeletonLimb> skeletonLimb = std::static_pointer_cast<SkeletonLimb>(resource);
ResourceVersionFactory::ParseFileBinary(reader, skeletonLimb);
skeletonLimb->limbType = (LimbType)reader->ReadInt8();
skeletonLimb->skinSegmentType = (ZLimbSkinType)reader->ReadInt8();
skeletonLimb->skinDList = reader->ReadString();
skeletonLimb->skinVtxCnt = reader->ReadUInt16();
skeletonLimb->skinLimbModifCount = reader->ReadUInt32();
skeletonLimb->skinLimbModifArray.reserve(skeletonLimb->skinLimbModifCount);
skeletonLimb->skinLimbModifVertexArrays.reserve(skeletonLimb->skinLimbModifCount);
skeletonLimb->skinLimbModifTransformationArrays.reserve(skeletonLimb->skinLimbModifCount);
for (size_t i = 0; i < skeletonLimb->skinLimbModifCount; i++) {
SkinLimbModif skinLimbModif;
skinLimbModif.unk_4 = reader->ReadUInt16();
skeletonLimb->skinLimbModifArray.push_back(skinLimbModif);
std::vector<SkinVertex> skinVertexArray;
int32_t skinVertexCount = reader->ReadInt32();
skinVertexArray.reserve(skinVertexCount);
for (int32_t k = 0; k < skinVertexCount; k++) {
SkinVertex skinVertex;
skinVertex.index = reader->ReadInt16();
skinVertex.s = reader->ReadInt16();
skinVertex.t = reader->ReadInt16();
skinVertex.normX = reader->ReadInt8();
skinVertex.normY = reader->ReadInt8();
skinVertex.normZ = reader->ReadInt8();
skinVertex.alpha = reader->ReadUByte();
skinVertexArray.push_back(skinVertex);
}
skeletonLimb->skinLimbModifVertexArrays.push_back(skinVertexArray);
std::vector<SkinTransformation> skinTransformationArray;
int32_t skinTransformationCount = reader->ReadInt32();
skinTransformationArray.reserve(skinTransformationCount);
for (int32_t k = 0; k < skinTransformationCount; k++) {
SkinTransformation skinTransformation;
skinTransformation.limbIndex = reader->ReadUByte();
skinTransformation.x = reader->ReadInt16();
skinTransformation.y = reader->ReadInt16();
skinTransformation.z = reader->ReadInt16();
skinTransformation.scale = reader->ReadUByte();
skinTransformationArray.push_back(skinTransformation);
}
skeletonLimb->skinLimbModifTransformationArrays.push_back(skinTransformationArray);
}
skeletonLimb->skinDList2 = reader->ReadString();
skeletonLimb->legTransX = reader->ReadFloat();
skeletonLimb->legTransY = reader->ReadFloat();
skeletonLimb->legTransZ = reader->ReadFloat();
skeletonLimb->rotX = reader->ReadUInt16();
skeletonLimb->rotY = reader->ReadUInt16();
skeletonLimb->rotZ = reader->ReadUInt16();
skeletonLimb->childPtr = reader->ReadString();
skeletonLimb->siblingPtr = reader->ReadString();
skeletonLimb->dListPtr = reader->ReadString();
skeletonLimb->dList2Ptr = reader->ReadString();
skeletonLimb->transX = reader->ReadInt16();
skeletonLimb->transY = reader->ReadInt16();
skeletonLimb->transZ = reader->ReadInt16();
skeletonLimb->childIndex = reader->ReadUByte();
skeletonLimb->siblingIndex = reader->ReadUByte();
if (skeletonLimb->limbType == LUS::LimbType::LOD) {
skeletonLimb->limbData.lodLimb.jointPos.x = skeletonLimb->transX;
skeletonLimb->limbData.lodLimb.jointPos.y = skeletonLimb->transY;
skeletonLimb->limbData.lodLimb.jointPos.z = skeletonLimb->transZ;
skeletonLimb->limbData.lodLimb.child = skeletonLimb->childIndex;
skeletonLimb->limbData.lodLimb.sibling = skeletonLimb->siblingIndex;
if (skeletonLimb->dListPtr != "") {
auto dList = LUS::Context::GetInstance()->GetResourceManager()->LoadResourceProcess(skeletonLimb->dListPtr.c_str());
skeletonLimb->limbData.lodLimb.dLists[0] = (Gfx*)(dList ? dList->GetRawPointer() : nullptr);
} else {
skeletonLimb->limbData.lodLimb.dLists[0] = nullptr;
}
if (skeletonLimb->dList2Ptr != "") {
auto dList = LUS::Context::GetInstance()->GetResourceManager()->LoadResourceProcess(skeletonLimb->dList2Ptr.c_str());
skeletonLimb->limbData.lodLimb.dLists[1] = (Gfx*)(dList ? dList->GetRawPointer() : nullptr);
} else {
skeletonLimb->limbData.lodLimb.dLists[1] = nullptr;
}
} else if (skeletonLimb->limbType == LUS::LimbType::Standard) {
skeletonLimb->limbData.standardLimb.jointPos.x = skeletonLimb->transX;
skeletonLimb->limbData.standardLimb.jointPos.y = skeletonLimb->transY;
skeletonLimb->limbData.standardLimb.jointPos.z = skeletonLimb->transZ;
skeletonLimb->limbData.standardLimb.child = skeletonLimb->childIndex;
skeletonLimb->limbData.standardLimb.sibling = skeletonLimb->siblingIndex;
skeletonLimb->limbData.standardLimb.dList = nullptr;
if (!skeletonLimb->dListPtr.empty()) {
const auto dList = LUS::Context::GetInstance()->GetResourceManager()->LoadResourceProcess(skeletonLimb->dListPtr.c_str());
skeletonLimb->limbData.standardLimb.dList = (Gfx*)(dList ? dList->GetRawPointer() : nullptr);
}
} else if (skeletonLimb->limbType == LUS::LimbType::Curve) {
skeletonLimb->limbData.skelCurveLimb.firstChildIdx = skeletonLimb->childIndex;
skeletonLimb->limbData.skelCurveLimb.nextLimbIdx = skeletonLimb->siblingIndex;
skeletonLimb->limbData.skelCurveLimb.dList[0] = nullptr;
skeletonLimb->limbData.skelCurveLimb.dList[1] = nullptr;
if (!skeletonLimb->dListPtr.empty()) {
const auto dList = LUS::Context::GetInstance()->GetResourceManager()->LoadResourceProcess(skeletonLimb->dListPtr.c_str());
skeletonLimb->limbData.skelCurveLimb.dList[0] = (Gfx*)(dList ? dList->GetRawPointer() : nullptr);
}
if (!skeletonLimb->dList2Ptr.empty()) {
const auto dList = LUS::Context::GetInstance()->GetResourceManager()->LoadResourceProcess(skeletonLimb->dList2Ptr.c_str());
skeletonLimb->limbData.skelCurveLimb.dList[1] = (Gfx*)(dList ? dList->GetRawPointer() : nullptr);
}
} else if (skeletonLimb->limbType == LUS::LimbType::Skin) {
skeletonLimb->limbData.skinLimb.jointPos.x = skeletonLimb->transX;
skeletonLimb->limbData.skinLimb.jointPos.y = skeletonLimb->transY;
skeletonLimb->limbData.skinLimb.jointPos.z = skeletonLimb->transZ;
skeletonLimb->limbData.skinLimb.child = skeletonLimb->childIndex;
skeletonLimb->limbData.skinLimb.sibling = skeletonLimb->siblingIndex;
if (skeletonLimb->skinSegmentType == LUS::ZLimbSkinType::SkinType_DList) {
skeletonLimb->limbData.skinLimb.segmentType = static_cast<int32_t>(skeletonLimb->skinSegmentType);
} else if (skeletonLimb->skinSegmentType == LUS::ZLimbSkinType::SkinType_4) {
skeletonLimb->limbData.skinLimb.segmentType = 4;
} else if (skeletonLimb->skinSegmentType == LUS::ZLimbSkinType::SkinType_5) {
skeletonLimb->limbData.skinLimb.segmentType = 5;
} else {
skeletonLimb->limbData.skinLimb.segmentType = 0;
}
if (skeletonLimb->skinSegmentType == LUS::ZLimbSkinType::SkinType_DList) {
auto res = LUS::Context::GetInstance()->GetResourceManager()->LoadResourceProcess(skeletonLimb->skinDList.c_str());
skeletonLimb->limbData.skinLimb.segment = res ? res->GetRawPointer() : nullptr;
} else if (skeletonLimb->skinSegmentType == LUS::ZLimbSkinType::SkinType_4) {
skeletonLimb->skinAnimLimbData.totalVtxCount = skeletonLimb->skinVtxCnt;
skeletonLimb->skinAnimLimbData.limbModifCount = skeletonLimb->skinLimbModifCount;
skeletonLimb->skinAnimLimbData.limbModifications = skeletonLimb->skinLimbModifArray.data();
auto res = LUS::Context::GetInstance()->GetResourceManager()->LoadResourceProcess(skeletonLimb->skinDList2.c_str());
skeletonLimb->skinAnimLimbData.dlist = (Gfx*)(res ? res->GetRawPointer() : nullptr);
for (size_t i = 0; i < skeletonLimb->skinLimbModifArray.size(); i++) {
skeletonLimb->skinAnimLimbData.limbModifications[i].vtxCount = skeletonLimb->skinLimbModifVertexArrays[i].size();
skeletonLimb->skinAnimLimbData.limbModifications[i].skinVertices = skeletonLimb->skinLimbModifVertexArrays[i].data();
skeletonLimb->skinAnimLimbData.limbModifications[i].transformCount = skeletonLimb->skinLimbModifTransformationArrays[i].size();
skeletonLimb->skinAnimLimbData.limbModifications[i].limbTransformations = skeletonLimb->skinLimbModifTransformationArrays[i].data();
skeletonLimb->skinAnimLimbData.limbModifications[i].unk_4 = skeletonLimb->skinLimbModifArray[i].unk_4;
}
skeletonLimb->limbData.skinLimb.segment = &skeletonLimb->skinAnimLimbData;
}
}
}
void SkeletonLimbFactoryV0::ParseFileXML(tinyxml2::XMLElement* reader, std::shared_ptr<IResource> resource)
{
std::shared_ptr<SkeletonLimb> skelLimb = std::static_pointer_cast<SkeletonLimb>(resource);
std::string limbType = reader->Attribute("Type");
// OTRTODO
skelLimb->limbType = LimbType::LOD;
// skelLimb->legTransX = reader->FloatAttribute("LegTransX");
// skelLimb->legTransY = reader->FloatAttribute("LegTransY");
// skelLimb->legTransZ = reader->FloatAttribute("LegTransZ");
skelLimb->rotX = reader->IntAttribute("RotX");
skelLimb->rotY = reader->IntAttribute("RotY");
skelLimb->rotZ = reader->IntAttribute("RotZ");
// skelLimb->transX = reader->IntAttribute("TransX");
// skelLimb->transY = reader->IntAttribute("TransY");
// skelLimb->transZ = reader->IntAttribute("TransZ");
skelLimb->transX = (int)reader->FloatAttribute("LegTransX");
skelLimb->transY = (int)reader->FloatAttribute("LegTransY");
skelLimb->transZ = (int)reader->FloatAttribute("LegTransZ");
skelLimb->childIndex = reader->IntAttribute("ChildIndex");
skelLimb->siblingIndex = reader->IntAttribute("SiblingIndex");
// skelLimb->childPtr = reader->Attribute("ChildLimb");
// skelLimb->siblingPtr = reader->Attribute("SiblingLimb");
skelLimb->dListPtr = reader->Attribute("DisplayList1");
if (std::string(reader->Attribute("DisplayList1")) == "gEmptyDL") {
skelLimb->dListPtr = "";
}
auto& limbData = skelLimb->limbData;
limbData.lodLimb.jointPos.x = skelLimb->transX;
limbData.lodLimb.jointPos.y = skelLimb->transY;
limbData.lodLimb.jointPos.z = skelLimb->transZ;
if (skelLimb->dListPtr != "") {
auto res = LUS::Context::GetInstance()->GetResourceManager()->LoadResourceProcess((const char*)skelLimb->dListPtr.c_str());
limbData.lodLimb.dLists[0] = (Gfx*)(res ? res->GetRawPointer() : nullptr);
} else {
limbData.lodLimb.dLists[0] = nullptr;
}
limbData.lodLimb.dLists[1] = nullptr;
limbData.lodLimb.child = skelLimb->childIndex;
limbData.lodLimb.sibling = skelLimb->siblingIndex;
// skelLimb->dList2Ptr = reader->Attribute("DisplayList2");
}
} // namespace LUS

View File

@ -0,0 +1,23 @@
#pragma once
#include "Resource.h"
#include "ResourceFactory.h"
namespace LUS {
class SkeletonLimbFactory : public ResourceFactory
{
public:
std::shared_ptr<IResource>
ReadResource(std::shared_ptr<ResourceInitData> initData, std::shared_ptr<BinaryReader> reader) override;
std::shared_ptr<IResource>
ReadResourceXML(std::shared_ptr<ResourceInitData> initData, tinyxml2::XMLElement *reader) override;
};
class SkeletonLimbFactoryV0 : public ResourceVersionFactory
{
public:
void ParseFileBinary(std::shared_ptr<BinaryReader> reader, std::shared_ptr<IResource> resource) override;
void ParseFileXML(tinyxml2::XMLElement* reader, std::shared_ptr<IResource> resource) override;
};
}; // namespace LUS

View File

@ -0,0 +1,93 @@
#include "2s2h/resource/importer/TextFactory.h"
#include "2s2h/resource/type/Text.h"
#include "spdlog/spdlog.h"
namespace LUS {
std::shared_ptr<IResource>
TextFactory::ReadResource(std::shared_ptr<ResourceInitData> initData, std::shared_ptr<BinaryReader> reader) {
auto resource = std::make_shared<Text>(initData);
std::shared_ptr<ResourceVersionFactory> factory = nullptr;
switch (resource->GetInitData()->ResourceVersion) {
case 0:
factory = std::make_shared<TextFactoryV0>();
break;
default:
// VERSION NOT SUPPORTED
break;
}
if (factory == nullptr) {
SPDLOG_ERROR("Failed to load Text with version {}", resource->GetInitData()->ResourceVersion);
return nullptr;
}
factory->ParseFileBinary(reader, resource);
return resource;
}
std::shared_ptr<IResource>
TextFactory::ReadResourceXML(std::shared_ptr<ResourceInitData> initData, tinyxml2::XMLElement *reader) {
auto resource = std::make_shared<Text>(initData);
std::shared_ptr<ResourceVersionFactory> factory = nullptr;
switch (resource->GetInitData()->ResourceVersion) {
case 0:
factory = std::make_shared<TextFactoryV0>();
break;
}
if (factory == nullptr) {
SPDLOG_ERROR("Failed to load Text with version {}", resource->GetInitData()->ResourceVersion);
return nullptr;
}
factory->ParseFileXML(reader, resource);
return resource;
}
void LUS::TextFactoryV0::ParseFileBinary(std::shared_ptr<BinaryReader> reader,
std::shared_ptr<IResource> resource) {
std::shared_ptr<Text> text = std::static_pointer_cast<Text>(resource);
ResourceVersionFactory::ParseFileBinary(reader, text);
uint32_t msgCount = reader->ReadUInt32();
text->messages.reserve(msgCount);
for (uint32_t i = 0; i < msgCount; i++) {
MessageEntry entry;
entry.id = reader->ReadUInt16();
entry.textboxType = reader->ReadUByte();
entry.textboxYPos = reader->ReadUByte();
entry.msg = reader->ReadString();
text->messages.push_back(entry);
}
}
void TextFactoryV0::ParseFileXML(tinyxml2::XMLElement* reader, std::shared_ptr<IResource> resource) {
std::shared_ptr<Text> txt = std::static_pointer_cast<Text>(resource);
auto child = reader->FirstChildElement();
while (child != nullptr) {
std::string childName = child->Name();
if (childName == "TextEntry") {
MessageEntry entry;
entry.id = child->IntAttribute("ID");
entry.textboxType = child->IntAttribute("TextboxType");
entry.textboxYPos = child->IntAttribute("TextboxYPos");
entry.msg = child->Attribute("Message");
entry.msg += "\x2";
txt->messages.push_back(entry);
int bp = 0;
}
child = child->NextSiblingElement();
}
}
} // namespace LUS

View File

@ -0,0 +1,23 @@
#pragma once
#include "Resource.h"
#include "ResourceFactory.h"
namespace LUS {
class TextFactory : public ResourceFactory
{
public:
std::shared_ptr<IResource>
ReadResource(std::shared_ptr<ResourceInitData> initData, std::shared_ptr<BinaryReader> reader) override;
std::shared_ptr<IResource>
ReadResourceXML(std::shared_ptr<ResourceInitData> initData, tinyxml2::XMLElement *reader) override;
};
class TextFactoryV0 : public ResourceVersionFactory
{
public:
void ParseFileBinary(std::shared_ptr<BinaryReader> reader, std::shared_ptr<IResource> resource) override;
void ParseFileXML(tinyxml2::XMLElement* reader, std::shared_ptr<IResource> resource) override;
};
}; // namespace LUS

View File

@ -0,0 +1,100 @@
#include "2s2h/resource/importer/TextMMFactory.h"
#include "2s2h/resource/type/TextMM.h"
#include "spdlog/spdlog.h"
namespace LUS {
std::shared_ptr<IResource>
TextMMFactory::ReadResource(std::shared_ptr<ResourceInitData> initData, std::shared_ptr<BinaryReader> reader) {
auto resource = std::make_shared<TextMM>(initData);
std::shared_ptr<ResourceVersionFactory> factory = nullptr;
switch (resource->GetInitData()->ResourceVersion) {
case 0:
factory = std::make_shared<TextMMFactoryV0>();
break;
default:
// VERSION NOT SUPPORTED
break;
}
if (factory == nullptr) {
SPDLOG_ERROR("Failed to load Text with version {}", resource->GetInitData()->ResourceVersion);
return nullptr;
}
factory->ParseFileBinary(reader, resource);
return resource;
}
std::shared_ptr<IResource> TextMMFactory::ReadResourceXML(std::shared_ptr<ResourceInitData> initData,
tinyxml2::XMLElement* reader) {
auto resource = std::make_shared<TextMM>(initData);
std::shared_ptr<ResourceVersionFactory> factory = nullptr;
switch (resource->GetInitData()->ResourceVersion) {
case 0:
factory = std::make_shared<TextMMFactoryV0>();
break;
}
if (factory == nullptr) {
SPDLOG_ERROR("Failed to load Text with version {}", resource->GetInitData()->ResourceVersion);
return nullptr;
}
factory->ParseFileXML(reader, resource);
return resource;
}
void LUS::TextMMFactoryV0::ParseFileBinary(std::shared_ptr<BinaryReader> reader, std::shared_ptr<IResource> resource) {
std::shared_ptr<TextMM> text = std::static_pointer_cast<TextMM>(resource);
ResourceVersionFactory::ParseFileBinary(reader, text);
uint32_t msgCount = reader->ReadUInt32();
text->messages.reserve(msgCount);
for (uint32_t i = 0; i < msgCount; i++) {
MessageEntryMM entry;
entry.id = reader->ReadUInt16();
entry.textboxType = reader->ReadUByte();
entry.textboxYPos = reader->ReadUByte();
entry.icon = reader->ReadUByte();
entry.nextMessageID = reader->ReadUInt16();
entry.firstItemCost = reader->ReadUInt16();
entry.secondItemCost = reader->ReadUInt16();
entry.msg = reader->ReadString();
text->messages.push_back(entry);
}
}
void TextMMFactoryV0::ParseFileXML(tinyxml2::XMLElement* reader, std::shared_ptr<IResource> resource) {
std::shared_ptr<TextMM> txt = std::static_pointer_cast<TextMM>(resource);
auto child = reader->FirstChildElement();
while (child != nullptr) {
std::string childName = child->Name();
if (childName == "TextEntry") {
MessageEntryMM entry;
entry.id = child->IntAttribute("ID");
entry.textboxType = child->IntAttribute("TextboxType");
entry.textboxYPos = child->IntAttribute("TextboxYPos");
// BENTODO: MM Unique Fields
entry.msg = child->Attribute("Message");
entry.msg += "\x2";
txt->messages.push_back(entry);
int bp = 0;
}
child = child->NextSiblingElement();
}
}
} // namespace LUS

View File

@ -0,0 +1,23 @@
#pragma once
#include "Resource.h"
#include "ResourceFactory.h"
namespace LUS {
class TextMMFactory : public ResourceFactory
{
public:
std::shared_ptr<IResource>
ReadResource(std::shared_ptr<ResourceInitData> initData, std::shared_ptr<BinaryReader> reader) override;
std::shared_ptr<IResource>
ReadResourceXML(std::shared_ptr<ResourceInitData> initData, tinyxml2::XMLElement *reader) override;
};
class TextMMFactoryV0 : public ResourceVersionFactory
{
public:
void ParseFileBinary(std::shared_ptr<BinaryReader> reader, std::shared_ptr<IResource> resource) override;
void ParseFileXML(tinyxml2::XMLElement* reader, std::shared_ptr<IResource> resource) override;
};
}; // namespace LUS

View File

@ -0,0 +1,124 @@
#include "2s2h/resource/importer/TextureAnimationFactory.h"
#include "2s2h/resource/type/TextureAnimation.h"
#include <libultraship/libultraship.h>
#include "spdlog/spdlog.h"
namespace LUS {
std::shared_ptr<IResource> TextureAnimationFactory::ReadResource(std::shared_ptr<ResourceInitData> initData,
std::shared_ptr<BinaryReader> reader) {
auto resource = std::make_shared<TextureAnimation>(initData);
std::shared_ptr<ResourceVersionFactory> factory = nullptr;
switch (resource->GetInitData()->ResourceVersion) {
case 0:
factory = std::make_shared<TextureAnimationFactoryV0>();
break;
}
if (factory == nullptr) {
SPDLOG_ERROR("Failed to load Texture Animation with version {}", resource->GetInitData()->ResourceVersion);
return nullptr;
}
factory->ParseFileBinary(reader, resource);
return resource;
}
void LUS::TextureAnimationFactoryV0::ParseFileBinary(std::shared_ptr<BinaryReader> reader,
std::shared_ptr<IResource> resource) {
std::shared_ptr<TextureAnimation> tAnim = std::static_pointer_cast<TextureAnimation>(resource);
ResourceVersionFactory::ParseFileBinary(reader, tAnim);
size_t numEntries = reader->ReadUInt32();
for (size_t i = 0; i < numEntries; i++) {
AnimatedMaterial anim;
anim.segment = reader->ReadInt8();
anim.type = reader->ReadInt8();
switch ((TextureAnimationParamsType)anim.type) {
case TextureAnimationParamsType::SingleScroll: {
auto* e = new AnimatedMatTexScrollParams;
e->xStep = reader->ReadInt8();
e->yStep = reader->ReadInt8();
e->width = reader->ReadUByte();
e->height = reader->ReadUByte();
anim.params = e;
break;
}
case TextureAnimationParamsType::DualScroll: {
auto* e = new AnimatedMatTexScrollParams[2];
e[0].xStep = reader->ReadInt8();
e[0].yStep = reader->ReadInt8();
e[0].width = reader->ReadUByte();
e[0].height = reader->ReadUByte();
e[1].xStep = reader->ReadInt8();
e[1].yStep = reader->ReadInt8();
e[1].width = reader->ReadUByte();
e[1].height = reader->ReadUByte();
anim.params = e;
break;
}
case TextureAnimationParamsType::ColorChange:
case TextureAnimationParamsType::ColorChangeLERP:
case TextureAnimationParamsType::ColorChangeLagrange: {
auto* e = new AnimatedMatColorParams;
e->keyFrameLength = reader->ReadUInt16();
e->keyFrameCount = reader->ReadUInt16();
size_t frames = reader->ReadUInt32();
e->keyFrames = new uint16_t[frames];
for (size_t i = 0; i < frames; i++) {
e->keyFrames[i] = reader->ReadUInt16();
}
size_t primColorSize = reader->ReadUInt32();
e->primColors = new F3DPrimColor[primColorSize];
for (size_t i = 0; i < primColorSize; i++) {
e->primColors[i].r = reader->ReadUByte();
e->primColors[i].g = reader->ReadUByte();
e->primColors[i].b = reader->ReadUByte();
e->primColors[i].a = reader->ReadUByte();
e->primColors[i].lodFrac = reader->ReadUByte();
}
size_t envColorSize = reader->ReadUInt16();
e->envColors = new F3DEnvColor[envColorSize];
for (size_t i = 0; i < envColorSize; i++) {
e->envColors[i].r = reader->ReadUByte();
e->envColors[i].g = reader->ReadUByte();
e->envColors[i].b = reader->ReadUByte();
e->envColors[i].a = reader->ReadUByte();
}
anim.params = e;
break;
}
case TextureAnimationParamsType::TextureCycle: {
auto* e = new AnimatedMatTexCycleParams;
e->keyFrameLength = reader->ReadUInt16();
e->textureList = new void*[e->keyFrameLength];
e->textureIndexList = new uint8_t[e->keyFrameLength];
for (size_t i = 0; i < e->keyFrameLength; i++) {
e->textureList[i] = ResourceGetDataByName(reader->ReadString().c_str());
}
for (size_t i = 0; i < e->keyFrameLength; i++) {
e->textureIndexList[i] = reader->ReadUByte();
}
anim.params = e;
break;
}
case TextureAnimationParamsType::Empty: {
anim.params = nullptr;
break;
}
}
tAnim->anims.emplace_back(anim);
}
}
} // namespace LUS

View File

@ -0,0 +1,18 @@
#pragma once
#include "Resource.h"
#include "ResourceFactory.h"
namespace LUS {
class TextureAnimationFactory : public ResourceFactory {
public:
std::shared_ptr<IResource> ReadResource(std::shared_ptr<ResourceInitData> initData,
std::shared_ptr<BinaryReader> reader) override;
};
class TextureAnimationFactoryV0 : public ResourceVersionFactory {
public:
void ParseFileBinary(std::shared_ptr<BinaryReader> reader, std::shared_ptr<IResource> resource) override;
};
}; // namespace LUS

View File

@ -0,0 +1,38 @@
#include "2s2h/resource/importer/scenecommand/EndMarkerFactory.h"
#include "2s2h/resource/type/scenecommand/EndMarker.h"
#include "spdlog/spdlog.h"
namespace LUS {
std::shared_ptr<IResource>
EndMarkerFactory::ReadResource(std::shared_ptr<ResourceInitData> initData, std::shared_ptr<BinaryReader> reader) {
auto resource = std::make_shared<EndMarker>(initData);
std::shared_ptr<ResourceVersionFactory> factory = nullptr;
switch (resource->GetInitData()->ResourceVersion) {
case 0:
factory = std::make_shared<EndMarkerFactoryV0>();
break;
}
if (factory == nullptr) {
SPDLOG_ERROR("Failed to load EndMarker with version {}", resource->GetInitData()->ResourceVersion);
return nullptr;
}
factory->ParseFileBinary(reader, resource);
return resource;
}
void LUS::EndMarkerFactoryV0::ParseFileBinary(std::shared_ptr<BinaryReader> reader,
std::shared_ptr<IResource> resource)
{
std::shared_ptr<EndMarker> endMarker = std::static_pointer_cast<EndMarker>(resource);
ResourceVersionFactory::ParseFileBinary(reader, endMarker);
ReadCommandId(endMarker, reader);
// This has no data.
}
} // namespace LUS

View File

@ -0,0 +1,16 @@
#pragma once
#include "2s2h/resource/importer/scenecommand/SceneCommandFactory.h"
namespace LUS {
class EndMarkerFactory : public SceneCommandFactory {
public:
std::shared_ptr<IResource>
ReadResource(std::shared_ptr<ResourceInitData> initData, std::shared_ptr<BinaryReader> reader) override;
};
class EndMarkerFactoryV0 : public SceneCommandVersionFactory {
public:
void ParseFileBinary(std::shared_ptr<BinaryReader> reader, std::shared_ptr<IResource> resource) override;
};
}; // namespace LUS

View File

@ -0,0 +1,10 @@
#include "2s2h/resource/importer/scenecommand/SceneCommandFactory.h"
#include "2s2h/resource/type/scenecommand/SceneCommand.h"
#include "spdlog/spdlog.h"
namespace LUS {
void SceneCommandVersionFactory::ReadCommandId(std::shared_ptr<ISceneCommand> command, std::shared_ptr<BinaryReader> reader) {
command->cmdId = (SceneCommandID)reader->ReadInt32();
}
}

View File

@ -0,0 +1,15 @@
#pragma once
#include <memory>
#include "Resource.h"
#include "ResourceFactory.h"
#include "2s2h/resource/type/scenecommand/SceneCommand.h"
namespace LUS {
class SceneCommandFactory : public ResourceFactory {};
class SceneCommandVersionFactory : public ResourceVersionFactory {
protected:
void ReadCommandId(std::shared_ptr<ISceneCommand> command, std::shared_ptr<BinaryReader> reader);
};
}; // namespace LUS

View File

@ -0,0 +1,55 @@
#include "2s2h/resource/importer/scenecommand/SetActorCutsceneListFactory.h"
#include "2s2h/resource/type/scenecommand/SetActorCutsceneList.h"
#include "spdlog/spdlog.h"
namespace LUS {
std::shared_ptr<IResource> SetActorCutsceneListFactory::ReadResource(std::shared_ptr<ResourceInitData> initData,
std::shared_ptr<BinaryReader> reader) {
auto resource = std::make_shared<SetActorCutsceneList>(initData);
std::shared_ptr<ResourceVersionFactory> factory = nullptr;
switch (resource->GetInitData()->ResourceVersion) {
case 0:
factory = std::make_shared<SetActorCutsceneListFactoryV0>();
break;
}
if (factory == nullptr) {
SPDLOG_ERROR("Failed to load SetActorList with version {}", resource->GetInitData()->ResourceVersion);
return nullptr;
}
factory->ParseFileBinary(reader, resource);
return resource;
}
void SetActorCutsceneListFactoryV0::ParseFileBinary(std::shared_ptr<BinaryReader> reader,
std::shared_ptr<IResource> resource) {
std::shared_ptr<SetActorCutsceneList> setActorCsList = std::static_pointer_cast<SetActorCutsceneList>(resource);
ResourceVersionFactory::ParseFileBinary(reader, setActorCsList);
ReadCommandId(setActorCsList, reader);
setActorCsList->numEntries = reader->ReadUInt32();
setActorCsList->entries.reserve(setActorCsList->numEntries);
for (uint32_t i = 0; i < setActorCsList->numEntries; i++) {
CutsceneEntry e;
e.priority = reader->ReadInt16();
e.length = reader->ReadInt16();
e.csCamId = reader->ReadInt16();
e.scriptIndex = reader->ReadInt16();
e.additionalCsId = reader->ReadInt16();
e.endSfx = reader->ReadUByte();
e.customValue = reader->ReadUByte();
e.hudVisibility = reader->ReadInt16();
e.endCam = reader->ReadUByte();
e.letterboxSize = reader->ReadUByte();
setActorCsList->entries.emplace_back(e);
}
}
} // namespace LUS

View File

@ -0,0 +1,17 @@
#pragma once
#include "2s2h/resource/importer/scenecommand/SceneCommandFactory.h"
namespace LUS {
class SetActorCutsceneListFactory : public SceneCommandFactory {
std::shared_ptr<IResource> ReadResource(std::shared_ptr<ResourceInitData> initData,
std::shared_ptr<BinaryReader> reader) override;
};
class SetActorCutsceneListFactoryV0 : public SceneCommandVersionFactory {
public:
void ParseFileBinary(std::shared_ptr<BinaryReader> reader, std::shared_ptr<IResource> resource) override;
};
}

View File

@ -0,0 +1,53 @@
#include "2s2h/resource/importer/scenecommand/SetActorListFactory.h"
#include "2s2h/resource/type/scenecommand/SetActorList.h"
#include "spdlog/spdlog.h"
namespace LUS {
std::shared_ptr<IResource>
SetActorListFactory::ReadResource(std::shared_ptr<ResourceInitData> initData, std::shared_ptr<BinaryReader> reader) {
auto resource = std::make_shared<SetActorList>(initData);
std::shared_ptr<ResourceVersionFactory> factory = nullptr;
switch (resource->GetInitData()->ResourceVersion) {
case 0:
factory = std::make_shared<SetActorListFactoryV0>();
break;
}
if (factory == nullptr)
{
SPDLOG_ERROR("Failed to load SetActorList with version {}", resource->GetInitData()->ResourceVersion);
return nullptr;
}
factory->ParseFileBinary(reader, resource);
return resource;
}
void LUS::SetActorListFactoryV0::ParseFileBinary(std::shared_ptr<BinaryReader> reader,
std::shared_ptr<IResource> resource) {
std::shared_ptr<SetActorList> setActorList = std::static_pointer_cast<SetActorList>(resource);
ResourceVersionFactory::ParseFileBinary(reader, setActorList);
ReadCommandId(setActorList, reader);
setActorList->numActors = reader->ReadUInt32();
setActorList->actorList.reserve(setActorList->numActors);
for (uint32_t i = 0; i < setActorList->numActors; i++) {
ActorEntry entry;
entry.id = reader->ReadUInt16();
entry.pos.x = reader->ReadInt16();
entry.pos.y = reader->ReadInt16();
entry.pos.z = reader->ReadInt16();
entry.rot.x = reader->ReadInt16();
entry.rot.y = reader->ReadInt16();
entry.rot.z = reader->ReadInt16();
entry.params = reader->ReadUInt16();
setActorList->actorList.push_back(entry);
}
}
} // namespace LUS

View File

@ -0,0 +1,16 @@
#pragma once
#include "2s2h/resource/importer/scenecommand/SceneCommandFactory.h"
namespace LUS {
class SetActorListFactory : public SceneCommandFactory {
public:
std::shared_ptr<IResource>
ReadResource(std::shared_ptr<ResourceInitData> initData, std::shared_ptr<BinaryReader> reader) override;
};
class SetActorListFactoryV0 : public SceneCommandVersionFactory {
public:
void ParseFileBinary(std::shared_ptr<BinaryReader> reader, std::shared_ptr<IResource> resource) override;
};
}; // namespace LUS

View File

@ -0,0 +1,49 @@
#include "2s2h/resource/importer/scenecommand/SetAlternateHeadersFactory.h"
#include "2s2h/resource/type/scenecommand/SetAlternateHeaders.h"
#include "spdlog/spdlog.h"
#include "libultraship/libultraship.h"
namespace LUS {
std::shared_ptr<IResource> SetAlternateHeadersFactory::ReadResource(std::shared_ptr<ResourceInitData> initData,
std::shared_ptr<BinaryReader> reader) {
auto resource = std::make_shared<SetAlternateHeaders>(initData);
std::shared_ptr<ResourceVersionFactory> factory = nullptr;
switch (resource->GetInitData()->ResourceVersion) {
case 0:
factory = std::make_shared<SetAlternateHeadersFactoryV0>();
break;
}
if (factory == nullptr)
{
SPDLOG_ERROR("Failed to load SetAlternateHeaders with version {}", resource->GetInitData()->ResourceVersion);
return nullptr;
}
factory->ParseFileBinary(reader, resource);
return resource;
}
void LUS::SetAlternateHeadersFactoryV0::ParseFileBinary(std::shared_ptr<BinaryReader> reader,
std::shared_ptr<IResource> resource)
{
std::shared_ptr<SetAlternateHeaders> setAlternateHeaders = std::static_pointer_cast<SetAlternateHeaders>(resource);
ResourceVersionFactory::ParseFileBinary(reader, setAlternateHeaders);
ReadCommandId(setAlternateHeaders, reader);
setAlternateHeaders->numHeaders = reader->ReadUInt32();
setAlternateHeaders->headers.reserve(setAlternateHeaders->numHeaders);
for (uint32_t i = 0; i < setAlternateHeaders->numHeaders; i++) {
auto headerName = reader->ReadString();
if (!headerName.empty()) {
setAlternateHeaders->headers.push_back(std::static_pointer_cast<LUS::Scene>(LUS::Context::GetInstance()->GetResourceManager()->LoadResourceProcess(headerName.c_str())));
} else {
setAlternateHeaders->headers.push_back(nullptr);
}
}
}
} // namespace LUS

View File

@ -0,0 +1,16 @@
#pragma once
#include "2s2h/resource/importer/scenecommand/SceneCommandFactory.h"
namespace LUS {
class SetAlternateHeadersFactory : public SceneCommandFactory {
public:
std::shared_ptr<IResource>
ReadResource(std::shared_ptr<ResourceInitData> initData, std::shared_ptr<BinaryReader> reader) override;
};
class SetAlternateHeadersFactoryV0 : public SceneCommandVersionFactory {
public:
void ParseFileBinary(std::shared_ptr<BinaryReader> reader, std::shared_ptr<IResource> resource) override;
};
}; // namespace LUS

View File

@ -0,0 +1,41 @@
#include "2s2h/resource/importer/scenecommand/SetAnimatedMaterialListFactory.h"
#include "2s2h/resource/type/scenecommand/SetAnimatedMaterialList.h"
#include "2s2h/resource/type/TextureAnimation.h"
#include "spdlog/spdlog.h"
#include <libultraship/libultraship.h>
namespace LUS {
std::shared_ptr<IResource> LUS::SetAnimatedMaterialListFactory::ReadResource(std::shared_ptr<ResourceInitData> initData,
std::shared_ptr<BinaryReader> reader) {
auto resource = std::make_shared<SetAnimatedMaterialList>(initData);
std::shared_ptr<ResourceVersionFactory> factory = nullptr;
switch (resource->GetInitData()->ResourceVersion) {
case 0:
factory = std::make_shared<SetAnimatedMaterialListFactoryV0>();
break;
}
if (factory == nullptr) {
SPDLOG_ERROR("Failed to load SetAnimatedMaterialList with version {}", resource->GetInitData()->ResourceVersion);
return nullptr;
}
factory->ParseFileBinary(reader, resource);
return resource;
}
void LUS::SetAnimatedMaterialListFactoryV0::ParseFileBinary(std::shared_ptr<BinaryReader> reader,
std::shared_ptr<IResource> resource) {
std::shared_ptr<SetAnimatedMaterialList> setAnimatedMat =
std::static_pointer_cast<SetAnimatedMaterialList>(resource);
ResourceVersionFactory::ParseFileBinary(reader, setAnimatedMat);
ReadCommandId(setAnimatedMat, reader);
AnimatedMaterialData* res = (AnimatedMaterialData*)ResourceGetDataByName(reader->ReadString().c_str());
setAnimatedMat->mat = res;
}
} // namespace LUS

View File

@ -0,0 +1,17 @@
#pragma once
#include "2s2h/resource/importer/scenecommand/SceneCommandFactory.h"
namespace LUS {
class SetAnimatedMaterialListFactory : public SceneCommandFactory {
public:
std::shared_ptr<IResource> ReadResource(std::shared_ptr<ResourceInitData> initData,
std::shared_ptr<BinaryReader> reader) override;
};
class SetAnimatedMaterialListFactoryV0 : public SceneCommandVersionFactory {
public:
void ParseFileBinary(std::shared_ptr<BinaryReader> reader, std::shared_ptr<IResource> resource) override;
};
}

View File

@ -0,0 +1,39 @@
#include "2s2h/resource/importer/scenecommand/SetCameraSettingsFactory.h"
#include "2s2h/resource/type/scenecommand/SetCameraSettings.h"
#include "spdlog/spdlog.h"
namespace LUS {
std::shared_ptr<IResource> SetCameraSettingsFactory::ReadResource(std::shared_ptr<ResourceInitData> initData,
std::shared_ptr<BinaryReader> reader) {
auto resource = std::make_shared<SetCameraSettings>(initData);
std::shared_ptr<ResourceVersionFactory> factory = nullptr;
switch (resource->GetInitData()->ResourceVersion) {
case 0:
factory = std::make_shared<SetCameraSettingsFactoryV0>();
break;
}
if (factory == nullptr) {
SPDLOG_ERROR("Failed to load SetCameraSettings with version {}", resource->GetInitData()->ResourceVersion);
return nullptr;
}
factory->ParseFileBinary(reader, resource);
return resource;
}
void LUS::SetCameraSettingsFactoryV0::ParseFileBinary(std::shared_ptr<BinaryReader> reader,
std::shared_ptr<IResource> resource)
{
std::shared_ptr<SetCameraSettings> setCameraSettings = std::static_pointer_cast<SetCameraSettings>(resource);
ResourceVersionFactory::ParseFileBinary(reader, setCameraSettings);
ReadCommandId(setCameraSettings, reader);
// BENTODO in MM this scene command is only used as a signal to have the scene system mark an area as visted. We should make a new command factory for this but this is fine for now.
//setCameraSettings->settings.cameraMovement = reader->ReadInt8();
//setCameraSettings->settings.worldMapArea = reader->ReadInt32();
}
} // namespace LUS

View File

@ -0,0 +1,16 @@
#pragma once
#include "2s2h/resource/importer/scenecommand/SceneCommandFactory.h"
namespace LUS {
class SetCameraSettingsFactory : public SceneCommandFactory {
public:
std::shared_ptr<IResource>
ReadResource(std::shared_ptr<ResourceInitData> initData, std::shared_ptr<BinaryReader> reader) override;
};
class SetCameraSettingsFactoryV0 : public SceneCommandVersionFactory {
public:
void ParseFileBinary(std::shared_ptr<BinaryReader> reader, std::shared_ptr<IResource> resource) override;
};
}; // namespace LUS

View File

@ -0,0 +1,39 @@
#include "2s2h/resource/importer/scenecommand/SetCollisionHeaderFactory.h"
#include "2s2h/resource/type/scenecommand/SetCollisionHeader.h"
#include "libultraship/libultraship.h"
#include "spdlog/spdlog.h"
namespace LUS {
std::shared_ptr<IResource> SetCollisionHeaderFactory::ReadResource(std::shared_ptr<ResourceInitData> initData,
std::shared_ptr<BinaryReader> reader) {
auto resource = std::make_shared<SetCollisionHeader>(initData);
std::shared_ptr<ResourceVersionFactory> factory = nullptr;
switch (resource->GetInitData()->ResourceVersion) {
case 0:
factory = std::make_shared<SetCollisionHeaderFactoryV0>();
break;
}
if (factory == nullptr) {
SPDLOG_ERROR("Failed to load SetCollisionHeader with version {}", resource->GetInitData()->ResourceVersion);
return nullptr;
}
factory->ParseFileBinary(reader, resource);
return resource;
}
void LUS::SetCollisionHeaderFactoryV0::ParseFileBinary(std::shared_ptr<BinaryReader> reader,
std::shared_ptr<IResource> resource) {
std::shared_ptr<SetCollisionHeader> setCollisionHeader = std::static_pointer_cast<SetCollisionHeader>(resource);
ResourceVersionFactory::ParseFileBinary(reader, setCollisionHeader);
ReadCommandId(setCollisionHeader, reader);
setCollisionHeader->fileName = reader->ReadString();
setCollisionHeader->collisionHeader = std::static_pointer_cast<CollisionHeader>(LUS::Context::GetInstance()->GetResourceManager()->LoadResourceProcess(setCollisionHeader->fileName.c_str()));
}
} // namespace LUS

View File

@ -0,0 +1,16 @@
#pragma once
#include "2s2h/resource/importer/scenecommand/SceneCommandFactory.h"
namespace LUS {
class SetCollisionHeaderFactory : public SceneCommandFactory {
public:
std::shared_ptr<IResource>
ReadResource(std::shared_ptr<ResourceInitData> initData, std::shared_ptr<BinaryReader> reader) override;
};
class SetCollisionHeaderFactoryV0 : public SceneCommandVersionFactory {
public:
void ParseFileBinary(std::shared_ptr<BinaryReader> reader, std::shared_ptr<IResource> resource) override;
};
}; // namespace LUS

View File

@ -0,0 +1,55 @@
#include "2s2h/resource/importer/scenecommand/SetCsCameraFactory.h"
#include "2s2h/resource/type/scenecommand/SetCsCamera.h"
#include "spdlog/spdlog.h"
namespace LUS {
std::shared_ptr<IResource>
SetCsCameraFactory::ReadResource(std::shared_ptr<ResourceInitData> initData, std::shared_ptr<BinaryReader> reader) {
auto resource = std::make_shared<SetCsCamera>(initData);
std::shared_ptr<ResourceVersionFactory> factory = nullptr;
switch (resource->GetInitData()->ResourceVersion) {
case 0:
factory = std::make_shared<SetCsCameraFactoryV0>();
break;
}
if (factory == nullptr) {
SPDLOG_ERROR("Failed to load SetCsCamera with version {}", resource->GetInitData()->ResourceVersion);
return nullptr;
}
factory->ParseFileBinary(reader, resource);
return resource;
}
void LUS::SetCsCameraFactoryV0::ParseFileBinary(std::shared_ptr<BinaryReader> reader,
std::shared_ptr<IResource> resource) {
std::shared_ptr<SetCsCamera> setCsCamera = std::static_pointer_cast<SetCsCamera>(resource);
ResourceVersionFactory::ParseFileBinary(reader, setCsCamera);
ReadCommandId(setCsCamera, reader);
size_t camSize = reader->ReadUInt32();
for (size_t i = 0; i < camSize; i++) {
ActorCsCamInfoData data;
data.setting = reader->ReadUInt16();
data.count = reader->ReadUInt16();
if (data.count == 0) {
data.actorCsCamFuncData = nullptr;
continue;
}
data.actorCsCamFuncData = new z64Vec3s[data.count];
for (size_t j = 0; j < data.count; j++) {
data.actorCsCamFuncData[j].x = reader->ReadInt16();
data.actorCsCamFuncData[j].y = reader->ReadInt16();
data.actorCsCamFuncData[j].z = reader->ReadInt16();
}
setCsCamera->csCamera.emplace_back(data);
}
}
} // namespace LUS

View File

@ -0,0 +1,16 @@
#pragma once
#include "2s2h/resource/importer/scenecommand/SceneCommandFactory.h"
namespace LUS {
class SetCsCameraFactory : public SceneCommandFactory {
public:
std::shared_ptr<IResource>
ReadResource(std::shared_ptr<ResourceInitData> initData, std::shared_ptr<BinaryReader> reader) override;
};
class SetCsCameraFactoryV0 : public SceneCommandVersionFactory {
public:
void ParseFileBinary(std::shared_ptr<BinaryReader> reader, std::shared_ptr<IResource> resource) override;
};
}; // namespace LUS

View File

@ -0,0 +1,81 @@
#include "2s2h/resource/importer/scenecommand/SetCutscenesFactory.h"
#include "2s2h/resource/type/scenecommand/SetCutscenes.h"
#include <libultraship/libultraship.h>
#include "spdlog/spdlog.h"
namespace LUS {
std::shared_ptr<IResource>
SetCutscenesFactory::ReadResource(std::shared_ptr<ResourceInitData> initData, std::shared_ptr<BinaryReader> reader) {
auto resource = std::make_shared<SetCutscenes>(initData);
std::shared_ptr<ResourceVersionFactory> factory = nullptr;
switch (resource->GetInitData()->ResourceVersion) {
case 0:
factory = std::make_shared<SetCutscenesFactoryV0>();
break;
}
if (factory == nullptr)
{
SPDLOG_ERROR("Failed to load SetCutscenes with version {}", resource->GetInitData()->ResourceVersion);
return nullptr;
}
factory->ParseFileBinary(reader, resource);
return resource;
}
void LUS::SetCutscenesFactoryV0::ParseFileBinary(std::shared_ptr<BinaryReader> reader,
std::shared_ptr<IResource> resource) {
std::shared_ptr<SetCutscenes> setCutscenes = std::static_pointer_cast<SetCutscenes>(resource);
ResourceVersionFactory::ParseFileBinary(reader, setCutscenes);
ReadCommandId(setCutscenes, reader);
setCutscenes->fileName = reader->ReadString();
setCutscenes->cutscene = std::static_pointer_cast<Cutscene>(LUS::Context::GetInstance()->GetResourceManager()->LoadResourceProcess(setCutscenes->fileName.c_str()));
}
std::shared_ptr<IResource> SetCutsceneFactoryMM::ReadResource(std::shared_ptr<ResourceInitData> initData,
std::shared_ptr<BinaryReader> reader) {
auto resource = std::make_shared<SetCutscenesMM>(initData);
std::shared_ptr<ResourceVersionFactory> factory = nullptr;
switch (resource->GetInitData()->ResourceVersion) {
case 0:
factory = std::make_shared<SetCutscenesFactoryMMV0>();
break;
}
if (factory == nullptr) {
SPDLOG_ERROR("Failed to load SetCutscenes with version {}", resource->GetInitData()->ResourceVersion);
return nullptr;
}
factory->ParseFileBinary(reader, resource);
return resource;
}
void LUS::SetCutscenesFactoryMMV0::ParseFileBinary(std::shared_ptr<BinaryReader> reader,
std::shared_ptr<IResource> resource) {
std::shared_ptr<SetCutscenesMM> setCutscenes = std::static_pointer_cast<SetCutscenesMM>(resource);
ResourceVersionFactory::ParseFileBinary(reader, setCutscenes);
ReadCommandId(setCutscenes, reader);
size_t numCs = reader->ReadUByte();
for (size_t i = 0; i < numCs; i++) {
CutsceneScriptEntry entry;
std::string path = reader->ReadString();
entry.exit = reader->ReadUInt16();
entry.entrance = reader->ReadUByte();
entry.flag = reader->ReadUByte();
entry.data = ResourceGetDataByName(path.c_str());
setCutscenes->entries.emplace_back(entry);
}
}
} // namespace LUS

View File

@ -0,0 +1,28 @@
#pragma once
#include "2s2h/resource/importer/scenecommand/SceneCommandFactory.h"
namespace LUS {
class SetCutscenesFactory : public SceneCommandFactory {
public:
std::shared_ptr<IResource>
ReadResource(std::shared_ptr<ResourceInitData> initData, std::shared_ptr<BinaryReader> reader) override;
};
class SetCutscenesFactoryV0 : public SceneCommandVersionFactory {
public:
void ParseFileBinary(std::shared_ptr<BinaryReader> reader, std::shared_ptr<IResource> resource) override;
};
class SetCutsceneFactoryMM : public SceneCommandFactory {
public:
std::shared_ptr<IResource> ReadResource(std::shared_ptr<ResourceInitData> initData,
std::shared_ptr<BinaryReader> reader) override;
};
class SetCutscenesFactoryMMV0 : public SceneCommandVersionFactory {
public:
void ParseFileBinary(std::shared_ptr<BinaryReader> reader, std::shared_ptr<IResource> resource) override;
};
}; // namespace LUS

View File

@ -0,0 +1,38 @@
#include "2s2h/resource/importer/scenecommand/SetEchoSettingsFactory.h"
#include "2s2h/resource/type/scenecommand/SetEchoSettings.h"
#include "spdlog/spdlog.h"
namespace LUS {
std::shared_ptr<IResource>
SetEchoSettingsFactory::ReadResource(std::shared_ptr<ResourceInitData> initData, std::shared_ptr<BinaryReader> reader) {
auto resource = std::make_shared<SetEchoSettings>(initData);
std::shared_ptr<ResourceVersionFactory> factory = nullptr;
switch (resource->GetInitData()->ResourceVersion) {
case 0:
factory = std::make_shared<SetEchoSettingsFactoryV0>();
break;
}
if (factory == nullptr) {
SPDLOG_ERROR("Failed to load SetEchoSettings with version {}", resource->GetInitData()->ResourceVersion);
return nullptr;
}
factory->ParseFileBinary(reader, resource);
return resource;
}
void LUS::SetEchoSettingsFactoryV0::ParseFileBinary(std::shared_ptr<BinaryReader> reader,
std::shared_ptr<IResource> resource)
{
std::shared_ptr<SetEchoSettings> setEchoSettings = std::static_pointer_cast<SetEchoSettings>(resource);
ResourceVersionFactory::ParseFileBinary(reader, setEchoSettings);
ReadCommandId(setEchoSettings, reader);
setEchoSettings->settings.echo = reader->ReadInt8();
}
} // namespace LUS

View File

@ -0,0 +1,16 @@
#pragma once
#include "2s2h/resource/importer/scenecommand/SceneCommandFactory.h"
namespace LUS {
class SetEchoSettingsFactory : public SceneCommandFactory {
public:
std::shared_ptr<IResource>
ReadResource(std::shared_ptr<ResourceInitData> initData, std::shared_ptr<BinaryReader> reader) override;
};
class SetEchoSettingsFactoryV0 : public SceneCommandVersionFactory {
public:
void ParseFileBinary(std::shared_ptr<BinaryReader> reader, std::shared_ptr<IResource> resource) override;
};
}; // namespace LUS

View File

@ -0,0 +1,46 @@
#include "2s2h/resource/importer/scenecommand/SetEntranceListFactory.h"
#include "2s2h/resource/type/scenecommand/SetEntranceList.h"
#include "spdlog/spdlog.h"
namespace LUS {
std::shared_ptr<IResource>
SetEntranceListFactory::ReadResource(std::shared_ptr<ResourceInitData> initData, std::shared_ptr<BinaryReader> reader) {
auto resource = std::make_shared<SetEntranceList>(initData);
std::shared_ptr<ResourceVersionFactory> factory = nullptr;
switch (resource->GetInitData()->ResourceVersion) {
case 0:
factory = std::make_shared<SetEntranceListFactoryV0>();
break;
}
if (factory == nullptr) {
SPDLOG_ERROR("Failed to load SetEntranceListList with version {}", resource->GetInitData()->ResourceVersion);
return nullptr;
}
factory->ParseFileBinary(reader, resource);
return resource;
}
void LUS::SetEntranceListFactoryV0::ParseFileBinary(std::shared_ptr<BinaryReader> reader,
std::shared_ptr<IResource> resource) {
std::shared_ptr<SetEntranceList> setEntranceList = std::static_pointer_cast<SetEntranceList>(resource);
ResourceVersionFactory::ParseFileBinary(reader, setEntranceList);
ReadCommandId(setEntranceList, reader);
setEntranceList->numEntrances = reader->ReadUInt32();
setEntranceList->entrances.reserve(setEntranceList->numEntrances);
for (uint32_t i = 0; i < setEntranceList->numEntrances; i++) {
EntranceEntry entranceEntry;
entranceEntry.spawn = reader->ReadInt8();
entranceEntry.room = reader->ReadInt8();
setEntranceList->entrances.push_back(entranceEntry);
}
}
} // namespace LUS

View File

@ -0,0 +1,16 @@
#pragma once
#include "2s2h/resource/importer/scenecommand/SceneCommandFactory.h"
namespace LUS {
class SetEntranceListFactory : public SceneCommandFactory {
public:
std::shared_ptr<IResource>
ReadResource(std::shared_ptr<ResourceInitData> initData, std::shared_ptr<BinaryReader> reader) override;
};
class SetEntranceListFactoryV0 : public SceneCommandVersionFactory {
public:
void ParseFileBinary(std::shared_ptr<BinaryReader> reader, std::shared_ptr<IResource> resource) override;
};
}; // namespace LUS

View File

@ -0,0 +1,41 @@
#include "2s2h/resource/importer/scenecommand/SetExitListFactory.h"
#include "2s2h/resource/type/scenecommand/SetExitList.h"
#include "spdlog/spdlog.h"
namespace LUS {
std::shared_ptr<IResource>
SetExitListFactory::ReadResource(std::shared_ptr<ResourceInitData> initData, std::shared_ptr<BinaryReader> reader) {
auto resource = std::make_shared<SetExitList>( initData);
std::shared_ptr<ResourceVersionFactory> factory = nullptr;
switch (resource->GetInitData()->ResourceVersion) {
case 0:
factory = std::make_shared<SetExitListFactoryV0>();
break;
}
if (factory == nullptr) {
SPDLOG_ERROR("Failed to load SetExitList with version {}", resource->GetInitData()->ResourceVersion);
return nullptr;
}
factory->ParseFileBinary(reader, resource);
return resource;
}
void LUS::SetExitListFactoryV0::ParseFileBinary(std::shared_ptr<BinaryReader> reader,
std::shared_ptr<IResource> resource) {
std::shared_ptr<SetExitList> setExitList = std::static_pointer_cast<SetExitList>(resource);
ResourceVersionFactory::ParseFileBinary(reader, setExitList);
ReadCommandId(setExitList, reader);
setExitList->numExits = reader->ReadUInt32();
setExitList->exits.reserve(setExitList->numExits);
for (uint32_t i = 0; i < setExitList->numExits; i++) {
setExitList->exits.push_back(reader->ReadUInt16());
}
}
} // namespace LUS

View File

@ -0,0 +1,16 @@
#pragma once
#include "2s2h/resource/importer/scenecommand/SceneCommandFactory.h"
namespace LUS {
class SetExitListFactory : public SceneCommandFactory {
public:
std::shared_ptr<IResource>
ReadResource(std::shared_ptr<ResourceInitData> initData, std::shared_ptr<BinaryReader> reader) override;
};
class SetExitListFactoryV0 : public SceneCommandVersionFactory {
public:
void ParseFileBinary(std::shared_ptr<BinaryReader> reader, std::shared_ptr<IResource> resource) override;
};
}; // namespace LUS

View File

@ -0,0 +1,58 @@
#include "2s2h/resource/importer/scenecommand/SetLightListFactory.h"
#include "2s2h/resource/type/scenecommand/SetLightList.h"
#include "spdlog/spdlog.h"
namespace LUS {
std::shared_ptr<IResource>
SetLightListFactory::ReadResource(std::shared_ptr<ResourceInitData> initData, std::shared_ptr<BinaryReader> reader) {
auto resource = std::make_shared<SetLightList>(initData);
std::shared_ptr<ResourceVersionFactory> factory = nullptr;
switch (resource->GetInitData()->ResourceVersion) {
case 0:
factory = std::make_shared<SetLightListFactoryV0>();
break;
}
if (factory == nullptr)
{
SPDLOG_ERROR("Failed to load SetLightList with version {}", resource->GetInitData()->ResourceVersion);
return nullptr;
}
factory->ParseFileBinary(reader, resource);
return resource;
}
void LUS::SetLightListFactoryV0::ParseFileBinary(std::shared_ptr<BinaryReader> reader,
std::shared_ptr<IResource> resource)
{
std::shared_ptr<SetLightList> setLightList = std::static_pointer_cast<SetLightList>(resource);
ResourceVersionFactory::ParseFileBinary(reader, setLightList);
ReadCommandId(setLightList, reader);
setLightList->numLights = reader->ReadUInt32();
setLightList->lightList.reserve(setLightList->numLights);
for (uint32_t i = 0; i < setLightList->numLights; i++) {
LightInfo light;
light.type = reader->ReadUByte();
light.params.point.x = reader->ReadInt16();
light.params.point.y = reader->ReadInt16();
light.params.point.z = reader->ReadInt16();
light.params.point.color[0] = reader->ReadUByte(); // r
light.params.point.color[1] = reader->ReadUByte(); // g
light.params.point.color[2] = reader->ReadUByte(); // b
light.params.point.drawGlow = reader->ReadUByte();
light.params.point.radius = reader->ReadInt16();
setLightList->lightList.push_back(light);
}
}
} // namespace LUS

View File

@ -0,0 +1,16 @@
#pragma once
#include "2s2h/resource/importer/scenecommand/SceneCommandFactory.h"
namespace LUS {
class SetLightListFactory : public SceneCommandFactory {
public:
std::shared_ptr<IResource>
ReadResource(std::shared_ptr<ResourceInitData> initData, std::shared_ptr<BinaryReader> reader) override;
};
class SetLightListFactoryV0 : public SceneCommandVersionFactory {
public:
void ParseFileBinary(std::shared_ptr<BinaryReader> reader, std::shared_ptr<IResource> resource) override;
};
}; // namespace LUS

View File

@ -0,0 +1,70 @@
#include "2s2h/resource/importer/scenecommand/SetLightingSettingsFactory.h"
#include "2s2h/resource/type/scenecommand/SetLightingSettings.h"
#include "spdlog/spdlog.h"
namespace LUS {
std::shared_ptr<IResource> SetLightingSettingsFactory::ReadResource(std::shared_ptr<ResourceInitData> initData,
std::shared_ptr<BinaryReader> reader) {
auto resource = std::make_shared<SetLightingSettings>(initData);
std::shared_ptr<ResourceVersionFactory> factory = nullptr;
switch (resource->GetInitData()->ResourceVersion) {
case 0:
factory = std::make_shared<SetLightingSettingsFactoryV0>();
break;
}
if (factory == nullptr) {
SPDLOG_ERROR("Failed to load SetLightingSettings with version {}", resource->GetInitData()->ResourceVersion);
return nullptr;
}
factory->ParseFileBinary(reader, resource);
return resource;
}
void LUS::SetLightingSettingsFactoryV0::ParseFileBinary(std::shared_ptr<BinaryReader> reader,
std::shared_ptr<IResource> resource)
{
std::shared_ptr<SetLightingSettings> setLightingSettings = std::static_pointer_cast<SetLightingSettings>(resource);
ResourceVersionFactory::ParseFileBinary(reader, setLightingSettings);
ReadCommandId(setLightingSettings, reader);
uint32_t count = reader->ReadInt32();
setLightingSettings->settings.reserve(count);
for (uint32_t i = 0; i < count; i++) {
EnvLightSettings lightSettings;
lightSettings.ambientColor[0] = reader->ReadInt8();
lightSettings.ambientColor[1] = reader->ReadInt8();
lightSettings.ambientColor[2] = reader->ReadInt8();
lightSettings.light1Dir[0] = reader->ReadInt8();
lightSettings.light1Dir[1] = reader->ReadInt8();
lightSettings.light1Dir[2] = reader->ReadInt8();
lightSettings.light1Color[0] = reader->ReadInt8();
lightSettings.light1Color[1] = reader->ReadInt8();
lightSettings.light1Color[2] = reader->ReadInt8();
lightSettings.light2Dir[0] = reader->ReadInt8();
lightSettings.light2Dir[1] = reader->ReadInt8();
lightSettings.light2Dir[2] = reader->ReadInt8();
lightSettings.light2Color[0] = reader->ReadInt8();
lightSettings.light2Color[1] = reader->ReadInt8();
lightSettings.light2Color[2] = reader->ReadInt8();
lightSettings.fogColor[0] = reader->ReadInt8();
lightSettings.fogColor[1] = reader->ReadInt8();
lightSettings.fogColor[2] = reader->ReadInt8();
lightSettings.fogNear = reader->ReadInt16();
lightSettings.fogFar = reader->ReadUInt16();
setLightingSettings->settings.push_back(lightSettings);
}
}
} // namespace LUS

View File

@ -0,0 +1,16 @@
#pragma once
#include "2s2h/resource/importer/scenecommand/SceneCommandFactory.h"
namespace LUS {
class SetLightingSettingsFactory : public SceneCommandFactory {
public:
std::shared_ptr<IResource>
ReadResource(std::shared_ptr<ResourceInitData> initData, std::shared_ptr<BinaryReader> reader) override;
};
class SetLightingSettingsFactoryV0 : public SceneCommandVersionFactory {
public:
void ParseFileBinary(std::shared_ptr<BinaryReader> reader, std::shared_ptr<IResource> resource) override;
};
}; // namespace LUS

View File

@ -0,0 +1,169 @@
#include "2s2h/resource/importer/scenecommand/SetMeshFactory.h"
#include "2s2h/resource/type/scenecommand/SetMesh.h"
#include "spdlog/spdlog.h"
#include "libultraship/libultraship.h"
namespace LUS {
std::shared_ptr<IResource>
SetMeshFactory::ReadResource(std::shared_ptr<ResourceInitData> initData, std::shared_ptr<BinaryReader> reader) {
auto resource = std::make_shared<SetMesh>(initData);
std::shared_ptr<ResourceVersionFactory> factory = nullptr;
switch (resource->GetInitData()->ResourceVersion) {
case 0:
factory = std::make_shared<SetMeshFactoryV0>();
break;
}
if (factory == nullptr)
{
SPDLOG_ERROR("Failed to load SetMesh with version {}", resource->GetInitData()->ResourceVersion);
return nullptr;
}
factory->ParseFileBinary(reader, resource);
return resource;
}
void LUS::SetMeshFactoryV0::ParseFileBinary(std::shared_ptr<BinaryReader> reader,
std::shared_ptr<IResource> resource)
{
std::shared_ptr<SetMesh> setMesh = std::static_pointer_cast<SetMesh>(resource);
ResourceVersionFactory::ParseFileBinary(reader, setMesh);
ReadCommandId(setMesh, reader);
setMesh->data = reader->ReadInt8();
setMesh->meshHeader.base.type = reader->ReadInt8();
int32_t polyNum = 1;
if (setMesh->meshHeader.base.type != 1) {
polyNum = reader->ReadInt8();
if (setMesh->meshHeader.base.type == 0) {
setMesh->meshHeader.polygon0.num = polyNum;
} else if (setMesh->meshHeader.base.type == 2) {
setMesh->meshHeader.polygon2.num = polyNum;
} else {
SPDLOG_ERROR("Tried to load mesh in SetMesh scene header with type that doesn't exist: {}", setMesh->meshHeader.base.type);
}
}
if (setMesh->meshHeader.base.type == 2) {
setMesh->dlists2.reserve(polyNum);
} else {
setMesh->dlists.reserve(setMesh->meshHeader.polygon0.num);
}
for (int32_t i = 0; i < polyNum; i++) {
if (setMesh->meshHeader.base.type == 0) {
PolygonDlist dlist;
int32_t polyType = reader->ReadInt8(); // Unused
std::string meshOpa = reader->ReadString();
std::string meshXlu = reader->ReadString();
auto opaRes = LUS::Context::GetInstance()->GetResourceManager()->LoadResourceProcess(meshOpa.c_str());
auto xluRes = LUS::Context::GetInstance()->GetResourceManager()->LoadResourceProcess(meshXlu.c_str());
dlist.opa = meshOpa != "" ? (Gfx*)(opaRes ? opaRes->GetRawPointer() : nullptr) : 0;
dlist.xlu = meshXlu != "" ? (Gfx*)(xluRes ? xluRes->GetRawPointer() : nullptr) : 0;
setMesh->dlists.push_back(dlist);
} else if (setMesh->meshHeader.base.type == 1) {
PolygonDlist pType;
setMesh->meshHeader.polygon1.format = reader->ReadUByte();
std::string imgOpa = reader->ReadString();
std::string imgXlu = reader->ReadString();
auto opaRes = LUS::Context::GetInstance()->GetResourceManager()->LoadResourceProcess(imgOpa.c_str());
auto xluRes = LUS::Context::GetInstance()->GetResourceManager()->LoadResourceProcess(imgXlu.c_str());
pType.opa = imgOpa != "" ? (Gfx*)(opaRes ? opaRes->GetRawPointer() : nullptr) : 0;
pType.xlu = imgXlu != "" ? (Gfx*)(xluRes ? xluRes->GetRawPointer() : nullptr) : 0;
int32_t bgImageCount = reader->ReadUInt32();
setMesh->images.reserve(bgImageCount);
for (int32_t i = 0; i < bgImageCount; i++) {
BgImage image;
image.unk_00 = reader->ReadUInt16();
image.id = reader->ReadUByte();
std::string imagePath = "__OTR__" + reader->ReadString();
setMesh->imagePaths.push_back(imagePath);
image.source = (void*)setMesh->imagePaths.back().c_str();
image.unk_0C = reader->ReadUInt32();
image.tlut = reader->ReadUInt32();
image.width = reader->ReadUInt16();
image.height = reader->ReadUInt16();
image.fmt = reader->ReadUByte();
image.siz = reader->ReadUByte();
image.mode0 = reader->ReadUInt16();
image.tlutCount = reader->ReadUInt16();
if (setMesh->meshHeader.polygon1.format == 1) {
setMesh->meshHeader.polygon1.single.source = image.source;
setMesh->meshHeader.polygon1.single.unk_0C = image.unk_0C;
setMesh->meshHeader.polygon1.single.tlut = (void*)image.tlut; // OTRTODO: type of bgimage.tlut should be uintptr_t
setMesh->meshHeader.polygon1.single.width = image.width;
setMesh->meshHeader.polygon1.single.height = image.height;
setMesh->meshHeader.polygon1.single.fmt = image.fmt;
setMesh->meshHeader.polygon1.single.siz = image.siz;
setMesh->meshHeader.polygon1.single.mode0 = image.mode0;
setMesh->meshHeader.polygon1.single.tlutCount = image.tlutCount;
} else {
setMesh->images.push_back(image);
}
}
if (setMesh->meshHeader.polygon1.format != 1) {
setMesh->meshHeader.polygon1.multi.count = bgImageCount;
}
int32_t polyType = reader->ReadInt8(); // Unused??
std::string meshOpa = reader->ReadString();
std::string meshXlu = reader->ReadString();
opaRes = LUS::Context::GetInstance()->GetResourceManager()->LoadResourceProcess(meshOpa.c_str());
xluRes = LUS::Context::GetInstance()->GetResourceManager()->LoadResourceProcess(meshXlu.c_str());
pType.opa = meshOpa != "" ? (Gfx*)(opaRes ? opaRes->GetRawPointer() : nullptr) : 0;
pType.xlu = meshXlu != "" ? (Gfx*)(xluRes ? xluRes->GetRawPointer() : nullptr) : 0;
setMesh->dlists.push_back(pType);
} else if (setMesh->meshHeader.base.type == 2) {
PolygonDlist2 dlist;
int32_t polyType = reader->ReadInt8(); // Unused
dlist.pos.x = reader->ReadInt16();
dlist.pos.y = reader->ReadInt16();
dlist.pos.z = reader->ReadInt16();
dlist.unk_06 = reader->ReadInt16();
std::string meshOpa = reader->ReadString();
std::string meshXlu = reader->ReadString();
auto opaRes = LUS::Context::GetInstance()->GetResourceManager()->LoadResourceProcess(meshOpa.c_str());
auto xluRes = LUS::Context::GetInstance()->GetResourceManager()->LoadResourceProcess(meshXlu.c_str());
dlist.opa = meshOpa != "" ? (Gfx*)(opaRes ? opaRes->GetRawPointer() : nullptr) : 0;
dlist.xlu = meshXlu != "" ? (Gfx*)(xluRes ? xluRes->GetRawPointer() : nullptr) : 0;
setMesh->dlists2.push_back(dlist);
} else {
SPDLOG_ERROR("Tried to load mesh in SetMesh scene header with type that doesn't exist: {}", setMesh->meshHeader.base.type);
}
}
if (setMesh->meshHeader.base.type == 2) {
setMesh->meshHeader.polygon2.start = setMesh->dlists2.data();
} else if (setMesh->meshHeader.base.type == 0) {
setMesh->meshHeader.polygon0.start = setMesh->dlists.data();
} else if (setMesh->meshHeader.base.type == 1) {
setMesh->meshHeader.polygon1.multi.list = setMesh->images.data();
setMesh->meshHeader.polygon1.dlist = (Gfx*)setMesh->dlists.data();
} else {
SPDLOG_ERROR("Tried to load mesh in SetMesh scene header with type that doesn't exist: {}", setMesh->meshHeader.base.type);
}
}
} // namespace LUS

View File

@ -0,0 +1,16 @@
#pragma once
#include "2s2h/resource/importer/scenecommand/SceneCommandFactory.h"
namespace LUS {
class SetMeshFactory : public SceneCommandFactory {
public:
std::shared_ptr<IResource>
ReadResource(std::shared_ptr<ResourceInitData> initData, std::shared_ptr<BinaryReader> reader) override;
};
class SetMeshFactoryV0 : public SceneCommandVersionFactory {
public:
void ParseFileBinary(std::shared_ptr<BinaryReader> reader, std::shared_ptr<IResource> resource) override;
};
}; // namespace LUS

View File

@ -0,0 +1,50 @@
#include "2s2h/resource/importer/scenecommand/SetMinimapChestsFactory.h"
#include "2s2h/resource/type/scenecommand/SetMinimapChests.h"
#include "spdlog/spdlog.h"
namespace LUS {
std::shared_ptr<IResource> SetMinimapChestsFactory::ReadResource(std::shared_ptr<ResourceInitData> initData,
std::shared_ptr<BinaryReader> reader) {
auto resource = std::make_shared<SetMinimapChests>(initData);
std::shared_ptr<ResourceVersionFactory> factory = nullptr;
switch (resource->GetInitData()->ResourceVersion) {
case 0:
factory = std::make_shared<SetMinimapChestsFactoryV0>();
break;
}
if (factory == nullptr) {
SPDLOG_ERROR("Failed to load SetMinimapChestsFactory with version {}", resource->GetInitData()->ResourceVersion);
return nullptr;
}
factory->ParseFileBinary(reader, resource);
return resource;
}
void SetMinimapChestsFactoryV0::ParseFileBinary(std::shared_ptr<BinaryReader> reader,
std::shared_ptr<IResource> resource) {
std::shared_ptr<SetMinimapChests> chests = std::static_pointer_cast<SetMinimapChests>(resource);
ResourceVersionFactory::ParseFileBinary(reader, chests);
ReadCommandId(chests, reader);
size_t size = reader->ReadUInt32();
chests->chests.reserve(size);
for (size_t i = 0; i < size; i++) {
MinimapChestData d;
d.unk_0 = reader->ReadUInt16();
d.unk_2 = reader->ReadUInt16();
d.unk_4 = reader->ReadUInt16();
d.unk_6 = reader->ReadUInt16();
d.unk_8 = reader->ReadUInt16();
chests->chests.emplace_back(d);
}
}
} // namespace LUS

View File

@ -0,0 +1,16 @@
#pragma once
#include "2s2h/resource/importer/scenecommand/SceneCommandFactory.h"
namespace LUS {
class SetMinimapChestsFactory : public SceneCommandFactory {
public:
std::shared_ptr<IResource> ReadResource(std::shared_ptr<ResourceInitData> initData,
std::shared_ptr<BinaryReader> reader) override;
};
class SetMinimapChestsFactoryV0 : public SceneCommandVersionFactory {
public:
void ParseFileBinary(std::shared_ptr<BinaryReader> reader, std::shared_ptr<IResource> resource) override;
};
}

View File

@ -0,0 +1,50 @@
#include "2s2h/resource/importer/scenecommand/SetMinimapListFactory.h"
#include "2s2h/resource/type/scenecommand/SetMinimapList.h"
#include "spdlog/spdlog.h"
namespace LUS {
std::shared_ptr<IResource> SetMinimapListFactory::ReadResource(std::shared_ptr<ResourceInitData> initData,
std::shared_ptr<BinaryReader> reader) {
auto resource = std::make_shared<SetMinimapList>(initData);
std::shared_ptr<ResourceVersionFactory> factory = nullptr;
switch (resource->GetInitData()->ResourceVersion) {
case 0:
factory = std::make_shared<SetMinimapListFactoryV0>();
break;
}
if (factory == nullptr) {
SPDLOG_ERROR("Failed to load SetMinimapListFactory with version {}", resource->GetInitData()->ResourceVersion);
return nullptr;
}
factory->ParseFileBinary(reader, resource);
return resource;
}
void SetMinimapListFactoryV0::ParseFileBinary(std::shared_ptr<BinaryReader> reader,
std::shared_ptr<IResource> resource) {
std::shared_ptr<SetMinimapList> mapList = std::static_pointer_cast<SetMinimapList>(resource);
ResourceVersionFactory::ParseFileBinary(reader, mapList);
ReadCommandId(mapList, reader);
size_t size = reader->ReadUInt32();
mapList->list.scale = reader->ReadUInt16();
mapList->entries.reserve(size);
for (size_t i = 0; i < size; i++) {
MinimapEntryData data;
data.mapId = reader->ReadUInt16();
data.unk2 = reader->ReadUInt16();
data.unk4 = reader->ReadUInt16();
data.unk6 = reader->ReadUInt16();
data.unk8 = reader->ReadUInt16();
mapList->entries.emplace_back(data);
}
mapList->list.entry = mapList->entries.data();
}
} // namespace LUS

View File

@ -0,0 +1,16 @@
#pragma once
#include "2s2h/resource/importer/scenecommand/SceneCommandFactory.h"
namespace LUS {
class SetMinimapListFactory : public SceneCommandFactory {
public:
std::shared_ptr<IResource> ReadResource(std::shared_ptr<ResourceInitData> initData,
std::shared_ptr<BinaryReader> reader) override;
};
class SetMinimapListFactoryV0 : public SceneCommandVersionFactory {
public:
void ParseFileBinary(std::shared_ptr<BinaryReader> reader, std::shared_ptr<IResource> resource) override;
};
}; // namespace LUS

View File

@ -0,0 +1,42 @@
#include "2s2h/resource/importer/scenecommand/SetObjectListFactory.h"
#include "2s2h/resource/type/scenecommand/SetObjectList.h"
#include "spdlog/spdlog.h"
namespace LUS {
std::shared_ptr<IResource>
SetObjectListFactory::ReadResource(std::shared_ptr<ResourceInitData> initData, std::shared_ptr<BinaryReader> reader) {
auto resource = std::make_shared<SetObjectList>(initData);
std::shared_ptr<ResourceVersionFactory> factory = nullptr;
switch (resource->GetInitData()->ResourceVersion) {
case 0:
factory = std::make_shared<SetObjectListFactoryV0>();
break;
}
if (factory == nullptr) {
SPDLOG_ERROR("Failed to load SetObjectList with version {}", resource->GetInitData()->ResourceVersion);
return nullptr;
}
factory->ParseFileBinary(reader, resource);
return resource;
}
void LUS::SetObjectListFactoryV0::ParseFileBinary(std::shared_ptr<BinaryReader> reader,
std::shared_ptr<IResource> resource)
{
std::shared_ptr<SetObjectList> setObjectList = std::static_pointer_cast<SetObjectList>(resource);
ResourceVersionFactory::ParseFileBinary(reader, setObjectList);
ReadCommandId(setObjectList, reader);
setObjectList->numObjects = reader->ReadUInt32();
setObjectList->objects.reserve(setObjectList->numObjects);
for (uint32_t i = 0; i < setObjectList->numObjects; i++) {
setObjectList->objects.push_back(reader->ReadUInt16());
}
}
} // namespace LUS

View File

@ -0,0 +1,16 @@
#pragma once
#include "2s2h/resource/importer/scenecommand/SceneCommandFactory.h"
namespace LUS {
class SetObjectListFactory : public SceneCommandFactory {
public:
std::shared_ptr<IResource>
ReadResource(std::shared_ptr<ResourceInitData> initData, std::shared_ptr<BinaryReader> reader) override;
};
class SetObjectListFactoryV0 : public SceneCommandVersionFactory {
public:
void ParseFileBinary(std::shared_ptr<BinaryReader> reader, std::shared_ptr<IResource> resource) override;
};
}; // namespace LUS

Some files were not shown because too many files have changed in this diff Show More