diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml new file mode 100644 index 0000000000..1412aec639 --- /dev/null +++ b/.github/workflows/build.yml @@ -0,0 +1,206 @@ +name: Build + +on: + push: + paths-ignore: + - '*.md' + - '*LICENSE' + pull_request: + +env: + SCCACHE_GHA_ENABLED: "true" + RUSTC_WRAPPER: "sccache" + +jobs: + build-linux: + name: Build Linux (${{matrix.name}}) + runs-on: ${{matrix.runner}} + + strategy: + fail-fast: false + matrix: + include: + - name: GCC x86_64 + runner: ubuntu-latest + preset: gcc + artifact_arch: x86_64 + - name: GCC aarch64 + runner: ubuntu-24.04-arm + preset: gcc + artifact_arch: aarch64 + # - name: Clang x86_64 + # runner: ubuntu-latest + # preset: clang + # artifact_arch: x86_64 + + steps: + - uses: actions/checkout@v6 + with: + fetch-depth: 0 + submodules: recursive + + - name: Install dependencies + run: | + sudo apt-get update + sudo apt-get -y install ninja-build clang lld openssl libcurl4-openssl-dev \ + zlib1g-dev libglu1-mesa-dev libdbus-1-dev libvulkan-dev libxi-dev libxrandr-dev libasound2-dev \ + libpulse-dev libudev-dev libpng-dev libncurses5-dev libx11-xcb-dev libfreetype-dev \ + libxinerama-dev libxcursor-dev python3-markupsafe libgtk-3-dev libssl-dev \ + libxss-dev libfuse2 + + - name: Setup sccache + uses: mozilla-actions/sccache-action@v0.0.9 + + - name: Configure CMake + run: cmake --preset x-linux-ci-${{matrix.preset}} + + - name: Build + run: cmake --build --preset x-linux-ci-${{matrix.preset}} + + - name: Generate AppImage + run: ci/build-appimage.sh + + - name: Upload artifacts + uses: actions/upload-artifact@v7 + with: + name: dusk-${{env.DUSK_VERSION}}-linux-${{matrix.preset}}-${{matrix.artifact_arch}} + path: | + build/install/Dusk-*.AppImage + build/install/debug.tar.* + + + build-apple: + name: Build Apple (${{matrix.name}}) + runs-on: macos-latest + strategy: + fail-fast: false + matrix: + include: + - name: AppleClang macOS universal + platform: macos + preset: x-macos-ci + artifact_name: macos-appleclang-universal + # - name: AppleClang iOS arm64 # TODO enable when CI is free + # platform: ios + # preset: x-ios-ci + # artifact_name: ios-appleclang-arm64 + # - name: AppleClang tvOS arm64 # TODO enable when CI is free + # platform: tvos + # preset: x-tvos-ci + # artifact_name: tvos-appleclang-arm64 + + steps: + - uses: actions/checkout@v6 + with: + fetch-depth: 0 + submodules: recursive + + - name: Update Homebrew + if: matrix.platform == 'tvos' + run: | + brew update + brew upgrade --formula + + - name: Install dependencies + run: brew install cmake ninja + + - name: Install markupsafe + if: matrix.platform == 'tvos' + run: pip3 install --break-system-packages markupsafe + + - name: Install Rust iOS target + if: matrix.platform == 'ios' + run: rustup target add aarch64-apple-ios + + - name: Install Rust tvOS target + if: matrix.platform == 'tvos' + run: | + rustup toolchain install nightly + rustup target add --toolchain nightly aarch64-apple-tvos + + - name: Setup sccache + uses: mozilla-actions/sccache-action@v0.0.9 + + - name: Configure CMake + run: cmake --preset ${{matrix.preset}} + + - name: Build + run: cmake --build --preset ${{matrix.preset}} + + - name: Upload artifacts + uses: actions/upload-artifact@v7 + with: + name: dusk-${{env.DUSK_VERSION}}-${{matrix.artifact_name}} + path: | + build/install/Dusk.app + build/install/debug.tar.* + + build-windows: + name: Build Windows (${{matrix.name}}) + runs-on: ${{matrix.runner}} + + env: + BUILD_DIR: C:\build + SCCACHE_DIR: C:\sccache + + strategy: + fail-fast: false + matrix: + include: + - name: MSVC x86_64 + runner: windows-latest + preset: msvc + msvc_arch: amd64 + vcpkg_arch: x64 + artifact_arch: x86_64 + - name: MSVC arm64 + runner: windows-11-arm + preset: arm64-msvc + msvc_arch: arm64 + vcpkg_arch: arm64 + artifact_arch: arm64 + # - name: Clang x86_64 + # runner: windows-latest + # preset: clang + # msvc_arch: amd64 + # vcpkg_arch: x64 + # artifact_arch: x86_64 + + steps: + - uses: actions/checkout@v6 + with: + fetch-depth: 0 + submodules: recursive + + - name: Enable Visual Studio environment + uses: ilammy/msvc-dev-cmd@v1 + with: + arch: ${{matrix.msvc_arch}} + + # msvc-dev-cmd sets VCPKG_ROOT, set it back + - name: Override VCPKG_ROOT + run: echo "VCPKG_ROOT=C:\vcpkg" >> $env:GITHUB_ENV + + - name: Setup sccache + uses: mozilla-actions/sccache-action@v0.0.9 + + - name: Install dependencies + run: | + choco install ninja + vcpkg install zlib:${{matrix.vcpkg_arch}}-windows-static bzip2:${{matrix.vcpkg_arch}}-windows-static ` + zstd:${{matrix.vcpkg_arch}}-windows-static liblzma:${{matrix.vcpkg_arch}}-windows-static ` + freetype:${{matrix.vcpkg_arch}}-windows-static + + - name: Configure CMake + run: cmake --preset x-windows-ci-${{matrix.preset}} + + - name: Build + run: cmake --build --preset x-windows-ci-${{matrix.preset}} + + - name: Upload artifacts + uses: actions/upload-artifact@v7 + with: + name: dusk-${{env.DUSK_VERSION}}-win32-msvc-${{matrix.artifact_arch}} + path: | + ${{env.BUILD_DIR}}/install/*.exe + ${{env.BUILD_DIR}}/install/debug.7z diff --git a/.gitignore b/.gitignore index 2fa85e7a9c..a1839ff34e 100644 --- a/.gitignore +++ b/.gitignore @@ -17,6 +17,10 @@ orig/*/* *.map *.MAP +# Save files +*.raw +*.gci + # Build files build/ .ninja_* @@ -32,9 +36,16 @@ compile_commands.json # Miscellaneous *.exe +*.zip # MacOS .DS_Store # ISOs *.iso + +*.ini +*.controller +pipeline_cache.bin + +extract diff --git a/.vscode/settings.json b/.vscode/settings.json index 4573e4a21c..bacff1eb9b 100644 --- a/.vscode/settings.json +++ b/.vscode/settings.json @@ -1,5 +1,10 @@ { - "cmake.buildDirectory": "${workspaceFolder}/build/dusk/${buildType}/${variant:platform}/${variant:tp_version}", + "cmake.buildDirectory": "${workspaceFolder}/build/dusk/${buildType}/${variant:tp_version}", + "cmake.generator": "Ninja", + "cmake.configureSettings": { + "CMAKE_EXPORT_COMPILE_COMMANDS": "ON" + }, + "cmake.copyCompileCommands": "${workspaceFolder}/compile_commands.json", "[c]": { "files.encoding": "utf8", "editor.defaultFormatter": "llvm-vs-code-extensions.vscode-clangd" @@ -44,8 +49,7 @@ "build.ninja": true, ".ninja_*": true, "objdiff.json": true, - ".cache/**": true, - "compile_commands.json": true, + ".cache/**": true }, "clangd.arguments": [ "--function-arg-placeholders=0", diff --git a/CMakeLists.txt b/CMakeLists.txt index 9395f83759..d87bb1afe2 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1,14 +1,86 @@ -cmake_minimum_required(VERSION 3.13) -if (APPLE) - project(dusk LANGUAGES C CXX OBJC OBJCXX) -else () - project(dusk LANGUAGES C CXX) +cmake_minimum_required(VERSION 3.25) + +if (NOT CMAKE_BUILD_TYPE) + set(CMAKE_BUILD_TYPE "RelWithDebInfo" CACHE STRING + "Build type options: Debug Release RelWithDebInfo MinSizeRel" FORCE) endif () +# obtain revision info from git +find_package(Git) +if (GIT_FOUND) + # make sure version information gets re-run when the current Git HEAD changes + execute_process(WORKING_DIRECTORY ${CMAKE_SOURCE_DIR} COMMAND ${GIT_EXECUTABLE} rev-parse --git-path HEAD + OUTPUT_VARIABLE dusk_git_head_filename + OUTPUT_STRIP_TRAILING_WHITESPACE) + set_property(DIRECTORY APPEND PROPERTY CMAKE_CONFIGURE_DEPENDS "${dusk_git_head_filename}") + + execute_process(WORKING_DIRECTORY ${CMAKE_SOURCE_DIR} COMMAND ${GIT_EXECUTABLE} rev-parse --symbolic-full-name HEAD + OUTPUT_VARIABLE dusk_git_head_symbolic + OUTPUT_STRIP_TRAILING_WHITESPACE) + execute_process(WORKING_DIRECTORY ${CMAKE_SOURCE_DIR} + COMMAND ${GIT_EXECUTABLE} rev-parse --git-path ${dusk_git_head_symbolic} + OUTPUT_VARIABLE dusk_git_head_symbolic_filename + OUTPUT_STRIP_TRAILING_WHITESPACE) + set_property(DIRECTORY APPEND PROPERTY CMAKE_CONFIGURE_DEPENDS "${dusk_git_head_symbolic_filename}") + + # defines DUSK_WC_REVISION + execute_process(WORKING_DIRECTORY ${CMAKE_SOURCE_DIR} COMMAND ${GIT_EXECUTABLE} rev-parse HEAD + OUTPUT_VARIABLE DUSK_WC_REVISION + OUTPUT_STRIP_TRAILING_WHITESPACE) + # defines DUSK_WC_DESCRIBE + execute_process(WORKING_DIRECTORY ${CMAKE_SOURCE_DIR} COMMAND ${GIT_EXECUTABLE} describe --tags --long --dirty --match "v*" + OUTPUT_VARIABLE DUSK_WC_DESCRIBE + OUTPUT_STRIP_TRAILING_WHITESPACE) + + # remove the git hash, then collapse a clean "-0" suffix only + string(REGEX REPLACE "-[^-]+(-dirty|)$" "\\1" DUSK_WC_DESCRIBE "${DUSK_WC_DESCRIBE}") + string(REGEX REPLACE "-0$" "" DUSK_WC_DESCRIBE "${DUSK_WC_DESCRIBE}") + + # defines DUSK_WC_BRANCH + execute_process(WORKING_DIRECTORY ${CMAKE_SOURCE_DIR} COMMAND ${GIT_EXECUTABLE} rev-parse --abbrev-ref HEAD + OUTPUT_VARIABLE DUSK_WC_BRANCH + OUTPUT_STRIP_TRAILING_WHITESPACE) + # defines DUSK_WC_DATE + execute_process(WORKING_DIRECTORY ${CMAKE_SOURCE_DIR} COMMAND ${GIT_EXECUTABLE} log -1 --format=%ad + OUTPUT_VARIABLE DUSK_WC_DATE + OUTPUT_STRIP_TRAILING_WHITESPACE) +else () + message(STATUS "Unable to find git, commit information will not be available") +endif () + +if (DUSK_WC_DESCRIBE) + string(REGEX REPLACE "v([0-9]+)\.([0-9]+)\.([0-9]+)\-([0-9]+).*" "\\1.\\2.\\3.\\4" DUSK_VERSION_STRING "${DUSK_WC_DESCRIBE}") + string(REGEX REPLACE "v([0-9]+)\.([0-9]+)\.([0-9]+).*" "\\1.\\2.\\3" DUSK_SHORT_VERSION_STRING "${DUSK_WC_DESCRIBE}") +else () + set(DUSK_WC_DESCRIBE "UNKNOWN-VERSION") + set(DUSK_VERSION_STRING "0.0.0") +endif () + +# Add version information to CI environment variables +if(DEFINED ENV{GITHUB_ENV}) + file(APPEND "$ENV{GITHUB_ENV}" "DUSK_VERSION=${DUSK_WC_DESCRIBE}\n") +endif() +message(STATUS "Dusk version set to ${DUSK_WC_DESCRIBE}") +message(STATUS "Build type: ${CMAKE_BUILD_TYPE}") +project(dusk LANGUAGES C CXX VERSION ${DUSK_VERSION_STRING}) +if (APPLE AND NOT TVOS AND CMAKE_SYSTEM_NAME STREQUAL tvOS) + # ios.toolchain.cmake hack for SDL + set(TVOS ON) + set(IOS OFF) +endif () + +if(APPLE AND NOT CMAKE_OSX_SYSROOT) + # If the Xcode SDK is lagging behind system version, CMake needs this done first + execute_process(COMMAND xcrun --sdk macosx --show-sdk-path + OUTPUT_VARIABLE CMAKE_OSX_SYSROOT + OUTPUT_STRIP_TRAILING_WHITESPACE) +endif() + set(CMAKE_C_STANDARD 11) set(CMAKE_CXX_STANDARD 20) set(CMAKE_CXX_STANDARD_REQUIRED ON) set(CMAKE_POSITION_INDEPENDENT_CODE ON) +set(CMAKE_WINDOWS_EXPORT_ALL_SYMBOLS ON) if (CMAKE_SYSTEM_NAME STREQUAL Linux) set(DAWN_USE_WAYLAND ON CACHE BOOL "Enable support for Wayland surface" FORCE) @@ -17,8 +89,49 @@ set(AURORA_ENABLE_DVD ON CACHE BOOL "Enable DVD API support" FORCE) set(AURORA_ENABLE_CARD ON CACHE BOOL "Enable CARD API support" FORCE) add_subdirectory(extern/aurora EXCLUDE_FROM_ALL) -option(DUSK_BUILD_WARNINGS "If off, compiler warnings will be suppressed") +add_subdirectory(libs/freeverb) + +option(DUSK_BUILD_WARNINGS "Enable compiler warnings (off by default)") option(DUSK_SELECTED_OPT "If on, selected parts of the project will be compiled with optimizations on Debug, intending to make the game run at 30 FPS. Note for MSVC: you will need to remove '/RTC1' from your debug flags in CMake.") +option(DUSK_MOVIE_SUPPORT "If on, compile against libjpeg-turbo to enable THP file decoding" ON) + +if (DUSK_MOVIE_SUPPORT) + find_package(libjpeg-turbo QUIET) + if (libjpeg-turbo_FOUND) + message(STATUS "dusk: Using system libjpeg-turbo") + else () + message(STATUS "dusk: Fetching libjpeg-turbo") + include(ExternalProject) + set(_jpeg_install_dir ${CMAKE_BINARY_DIR}/libjpeg-turbo-install) + if (WIN32) + set(_jpeg_lib ${_jpeg_install_dir}/lib/turbojpeg-static.lib) + else () + set(_jpeg_lib ${_jpeg_install_dir}/lib/libturbojpeg.a) + endif () + ExternalProject_Add(libjpeg-turbo-ext + URL https://github.com/libjpeg-turbo/libjpeg-turbo/archive/refs/tags/3.1.0.tar.gz + URL_HASH SHA256=35fec2e1ddfb05ecf6d93e50bc57c1e54bc81c16d611ddf6eff73fff266d8285 + CMAKE_ARGS + -DCMAKE_BUILD_TYPE=${CMAKE_BUILD_TYPE} + -DCMAKE_INSTALL_PREFIX=${_jpeg_install_dir} + -DCMAKE_TOOLCHAIN_FILE=${CMAKE_TOOLCHAIN_FILE} + -DCMAKE_C_COMPILER=${CMAKE_C_COMPILER} + -DCMAKE_C_COMPILER_LAUNCHER=${CMAKE_C_COMPILER_LAUNCHER} + -DCMAKE_MSVC_RUNTIME_LIBRARY=${CMAKE_MSVC_RUNTIME_LIBRARY} + -DENABLE_SHARED=OFF + -DWITH_TURBOJPEG=ON + -DWITH_JAVA=OFF + BUILD_BYPRODUCTS ${_jpeg_lib} + ) + file(MAKE_DIRECTORY ${_jpeg_install_dir}/include) + add_library(libjpeg-turbo::turbojpeg-static STATIC IMPORTED GLOBAL) + set_target_properties(libjpeg-turbo::turbojpeg-static PROPERTIES + IMPORTED_LOCATION ${_jpeg_lib} + INTERFACE_INCLUDE_DIRECTORIES ${_jpeg_install_dir}/include + ) + add_dependencies(libjpeg-turbo::turbojpeg-static libjpeg-turbo-ext) + endif () +endif () if (CMAKE_SYSTEM_NAME STREQUAL Linux) # -Wno-multichar: Multi-character constants ('ABCD') are implementation-defined but all compilers @@ -38,6 +151,8 @@ elseif (MSVC) add_compile_options(/bigobj) add_compile_options(/Zc:strictStrings-) add_compile_options(/MP) + add_compile_options(/FS) + if (NOT DUSK_BUILD_WARNINGS) add_compile_options(/W0) else () @@ -53,63 +168,153 @@ endif () include(FetchContent) +# Declare all dependencies first so CMake can download them in parallel message(STATUS "dusk: Fetching cxxopts") -FetchContent_Declare( - cxxopts - GIT_REPOSITORY https://github.com/jarro2783/cxxopts.git - GIT_TAG v3.3.1 +FetchContent_Declare(cxxopts + URL https://github.com/jarro2783/cxxopts/archive/refs/tags/v3.3.1.tar.gz + URL_HASH SHA256=3bfc70542c521d4b55a46429d808178916a579b28d048bd8c727ee76c39e2072 + DOWNLOAD_EXTRACT_TIMESTAMP TRUE ) +message(STATUS "dusk: Fetching nlohmann/json") +FetchContent_Declare(json + URL https://github.com/nlohmann/json/releases/download/v3.12.0/json.tar.xz + URL_HASH SHA256=42f6e95cad6ec532fd372391373363b62a14af6d771056dbfc86160e6dfff7aa + DOWNLOAD_EXTRACT_TIMESTAMP TRUE +) +FetchContent_MakeAvailable(cxxopts json) -FetchContent_MakeAvailable(cxxopts) - +configure_file(${CMAKE_SOURCE_DIR}/version.h.in ${CMAKE_BINARY_DIR}/version.h) include(files.cmake) # TODO: version handling for res includes +set(DUSK_BUNDLE_NAME Dusk) +set(DUSK_BUNDLE_IDENTIFIER dev.decomp.dusk) set(DUSK_GAME_NAME "GZ2E") set(DUSK_GAME_VERSION "01") - set(DUSK_TP_VERSION ${DUSK_GAME_NAME}${DUSK_GAME_VERSION}) -message(STATUS "dusk: Game Name: ${DUSK_GAME_NAME}") -message(STATUS "dusk: Game Version: ${DUSK_GAME_VERSION}") -message(STATUS "dusk: TP Version: ${DUSK_TP_VERSION}") +message(STATUS "dusk: Game Version: ${DUSK_TP_VERSION}") source_group("dolzel" FILES ${DOLZEL_FILES} ${Z2AUDIOLIB_FILES} ${JSYSTEM_FILES} ${JSYSTEM_DEBUG_FILES} ${REL_FILES}) source_group("dusk" FILES ${DUSK_FILES}) +set(GAME_COMPILE_DEFS TARGET_PC WIDESCREEN_SUPPORT=1 AVOID_UB=1 VERSION=0 + DUSK_TP_VERSION="${DUSK_TP_VERSION}" DUSK_GAME_NAME="${DUSK_GAME_NAME}" DUSK_GAME_VERSION="${DUSK_GAME_VERSION}") + +set(GAME_INCLUDE_DIRS + include + src + assets/${DUSK_TP_VERSION} + libs/JSystem/include + libs + extern/aurora/include/dolphin + extern + ${CMAKE_BINARY_DIR}) + +set(GAME_LIBS aurora::core aurora::gx aurora::gd aurora::si aurora::vi aurora::pad aurora::mtx aurora::os aurora::dvd + aurora::card freeverb cxxopts::cxxopts absl::flat_hash_map nlohmann_json::nlohmann_json TracyClient) + +if (DUSK_MOVIE_SUPPORT) + if (TARGET libjpeg-turbo::turbojpeg-static) + list(APPEND GAME_LIBS libjpeg-turbo::turbojpeg-static) + else () + list(APPEND GAME_LIBS libjpeg-turbo::turbojpeg) + endif () + list(APPEND GAME_COMPILE_DEFS MOVIE_SUPPORT=1) +endif () + # game_debug is for game code files that we know work when compiled with DEBUG=1 # Of course, if building a release build, this distinction is irrelevant -add_library(game_debug STATIC ${JSYSTEM_DEBUG_FILES} ${SSYSTEM_FILES}) -target_compile_definitions(game_debug PRIVATE TARGET_PC AVOID_UB=1 VERSION=0 $<$:DEBUG=1>) +add_library(game_debug OBJECT ${JSYSTEM_DEBUG_FILES} ${SSYSTEM_FILES} + src/dusk/audio/DuskAudioSystem.cpp + src/dusk/audio/JASCriticalSection.cpp + src/dusk/audio/DuskDsp.cpp + src/dusk/audio/Adpcm.cpp + src/dusk/audio/DspStub.cpp + src/dusk/imgui/ImGuiAudio.cpp) -# Make these properties PUBLIC so that the regular game target also sees them. -target_include_directories(game_debug PUBLIC - include - src - assets/${DUSK_TP_VERSION} - libs/JSystem/include - extern/aurora/include/dolphin - extern - ${CMAKE_SOURCE_DIR}/build/${DUSK_TP_VERSION}/include - build/${DUSK_TP_VERSION}/include) -target_link_libraries(game_debug PUBLIC aurora::core aurora::gx aurora::gd aurora::si aurora::vi aurora::pad aurora::mtx aurora::os aurora::dvd aurora::card) +# game_base is for all other game code files +add_library(game_base OBJECT ${DOLZEL_FILES} ${Z2AUDIOLIB_FILES} ${JSYSTEM_FILES} ${REL_FILES} ${DUSK_FILES} ${DOLPHIN_FILES}) -set(CMAKE_WINDOWS_EXPORT_ALL_SYMBOLS ON) -add_library(game SHARED ${DOLZEL_FILES} ${Z2AUDIOLIB_FILES} ${SSYSTEM_FILES} ${JSYSTEM_FILES} ${REL_FILES} ${DUSK_FILES} ${DOLPHIN_FILES} - src/dusk/imgui/ImGuiStubLog.cpp) +target_compile_definitions(game_debug PRIVATE ${GAME_COMPILE_DEFS} $<$:DEBUG=1> $<$:PARTIAL_DEBUG=1>) +target_compile_definitions(game_base PRIVATE ${GAME_COMPILE_DEFS} NDEBUG=1 NDEBUG_DEFINED=1 DEBUG_DEFINED=0 $<$:PARTIAL_DEBUG=1>) + +# only apply PCH to game_base since not all headers are necessarily validated with DEBUG=1 +target_precompile_headers(game_base PRIVATE "$<$:${CMAKE_SOURCE_DIR}/include/dusk_pch.hpp>") + +target_include_directories(game_debug PRIVATE ${GAME_INCLUDE_DIRS}) +target_include_directories(game_base PRIVATE ${GAME_INCLUDE_DIRS}) + +# This implicitly pulls in the library include directories even though no +# linking actually takes place for object libraries +target_link_libraries(game_debug PRIVATE ${GAME_LIBS}) +target_link_libraries(game_base PRIVATE ${GAME_LIBS}) + +# Combined game library +add_library(game STATIC + $ + $) +target_link_libraries(game PUBLIC ${GAME_LIBS}) -target_link_libraries(game PRIVATE game_debug cxxopts::cxxopts) -target_compile_definitions(game PRIVATE TARGET_PC AVOID_UB=1 VERSION=0 NDEBUG=1 NDEBUG_DEFINED=1 DEBUG_DEFINED=0 - DUSK_TP_VERSION="${DUSK_TP_VERSION}" DUSK_GAME_NAME="${DUSK_GAME_NAME}" DUSK_GAME_VERSION="${DUSK_GAME_VERSION}") add_executable(dusk src/dusk/main.cpp) target_compile_definitions(dusk PRIVATE TARGET_PC AVOID_UB=1 VERSION=0) target_include_directories(dusk PRIVATE include) target_link_libraries(dusk PRIVATE game aurora::main) +add_custom_command(TARGET dusk POST_BUILD + COMMAND ${CMAKE_COMMAND} -E copy_directory + "${CMAKE_SOURCE_DIR}/res" + "$/res" + COMMENT "Copying resources" +) + +if (APPLE) + if (IOS) + set(DUSK_RESOURCE_DIR ${CMAKE_CURRENT_SOURCE_DIR}/platforms/ios) + set(DUSK_INFO_PLIST ${DUSK_RESOURCE_DIR}/Info.plist.in) + file(GLOB_RECURSE DUSK_RESOURCE_FILES "${DUSK_RESOURCE_DIR}/Base.lproj/*") + endif () + if (IOS OR TVOS) + target_sources(dusk PRIVATE ${DUSK_RESOURCE_FILES}) + foreach (FILE ${DUSK_RESOURCE_FILES}) + file(RELATIVE_PATH NEW_FILE "${DUSK_RESOURCE_DIR}" ${FILE}) + get_filename_component(NEW_FILE_PATH ${NEW_FILE} DIRECTORY) + set_property(SOURCE ${FILE} PROPERTY MACOSX_PACKAGE_LOCATION "Resources/${NEW_FILE_PATH}") + endforeach () + set_target_properties( + dusk PROPERTIES + MACOSX_BUNDLE TRUE + MACOSX_BUNDLE_BUNDLE_NAME ${DUSK_BUNDLE_NAME} + MACOSX_BUNDLE_GUI_IDENTIFIER ${DUSK_BUNDLE_IDENTIFIER} + MACOSX_BUNDLE_BUNDLE_VERSION ${DUSK_VERSION_STRING} + MACOSX_BUNDLE_SHORT_VERSION_STRING ${DUSK_SHORT_VERSION_STRING} + OUTPUT_NAME dusk + XCODE_ATTRIBUTE_CODE_SIGNING_ALLOWED "YES" + XCODE_ATTRIBUTE_CODE_SIGNING_REQUIRED "YES" + ) + if (CMAKE_GENERATOR STREQUAL "Xcode") + set_target_properties(dusk PROPERTIES MACOSX_BUNDLE_INFO_PLIST ${DUSK_INFO_PLIST}) + elseif (DEFINED DUSK_INFO_PLIST) + set(MACOSX_BUNDLE_EXECUTABLE_NAME dusk) + set(MACOSX_BUNDLE_GUI_IDENTIFIER ${DUSK_BUNDLE_IDENTIFIER}) + set(MACOSX_BUNDLE_BUNDLE_NAME ${DUSK_BUNDLE_NAME}) + set(MACOSX_BUNDLE_BUNDLE_VERSION ${DUSK_VERSION_STRING}) + set(MACOSX_BUNDLE_SHORT_VERSION_STRING ${DUSK_SHORT_VERSION_STRING}) + set(DUSK_GENERATED_INFO_PLIST ${CMAKE_CURRENT_BINARY_DIR}/dusk.Info.plist) + configure_file(${DUSK_INFO_PLIST} ${DUSK_GENERATED_INFO_PLIST}) + add_custom_command( + TARGET dusk POST_BUILD + COMMAND ${CMAKE_COMMAND} -E copy_if_different ${DUSK_GENERATED_INFO_PLIST} $/Info.plist + VERBATIM + ) + endif () + endif () +endif () + include(extern/aurora/cmake/AuroraCopyRuntimeDLLs.cmake) -aurora_copy_runtime_dlls(dusk game) +aurora_copy_runtime_dlls(dusk) if (DUSK_SELECTED_OPT) if (CMAKE_CXX_COMPILER_FRONTEND_VARIANT STREQUAL "MSVC") @@ -120,4 +325,81 @@ if (DUSK_SELECTED_OPT) target_compile_options(xxhash PRIVATE ${_opt_flags}) target_compile_options(aurora_gx PRIVATE ${_opt_flags}) + target_compile_options(freeverb PRIVATE ${_opt_flags}) endif () + +# Packaging logic +function(get_target_output_name target result_var) + get_target_property(output_name ${target} OUTPUT_NAME) + if (NOT output_name) + set(${result_var} "${target}" PARENT_SCOPE) + else () + set(${result_var} "${output_name}" PARENT_SCOPE) + endif () +endfunction() +function(get_target_prefix target result_var) + set(${result_var} "" PARENT_SCOPE) + if (APPLE) + # Have to recreate some bundle logic here, since CMake can't tell us + get_target_property(is_bundle ${target} MACOSX_BUNDLE) + if (is_bundle) + get_target_output_name(${target} output_name) + if (CMAKE_SYSTEM_NAME STREQUAL Darwin) + set(${result_var} "${output_name}.app/Contents/MacOS/" PARENT_SCOPE) + else () + set(${result_var} "${output_name}.app/" PARENT_SCOPE) + endif () + endif () + endif () +endfunction() +list(APPEND BINARY_TARGETS dusk) +set(EXTRA_TARGETS "") +if (TARGET crashpad_handler) + list(APPEND EXTRA_TARGETS crashpad_handler) +endif () +install(TARGETS ${BINARY_TARGETS} ${EXTRA_TARGETS} DESTINATION ${CMAKE_INSTALL_PREFIX}) +if (CMAKE_BUILD_TYPE STREQUAL Debug OR CMAKE_BUILD_TYPE STREQUAL RelWithDebInfo) + set(DEBUG_FILES_LIST "") + foreach (target IN LISTS BINARY_TARGETS EXTRA_TARGETS) + get_target_output_name(${target} output_name) + if (WIN32) + install(FILES $ DESTINATION ${CMAKE_INSTALL_PREFIX} OPTIONAL) + elseif (APPLE) + get_target_prefix(${target} target_prefix) + install(CODE "execute_process(WORKING_DIRECTORY \"${CMAKE_INSTALL_PREFIX}\" COMMAND rm -fr \"$.dSYM\")") + install(CODE "execute_process(WORKING_DIRECTORY \"${CMAKE_INSTALL_PREFIX}\" COMMAND dsymutil \"${target_prefix}$\")") + install(CODE "execute_process(WORKING_DIRECTORY \"${CMAKE_INSTALL_PREFIX}\" COMMAND strip -S \"${target_prefix}$\")") + if (NOT target_prefix STREQUAL "") + install(CODE "execute_process(WORKING_DIRECTORY \"${CMAKE_INSTALL_PREFIX}\" COMMAND mv \"${target_prefix}$.dSYM\" .)") + endif () + elseif (UNIX) + get_target_prefix(${target} target_prefix) + install(CODE "execute_process(WORKING_DIRECTORY \"${CMAKE_INSTALL_PREFIX}\" COMMAND objcopy --only-keep-debug \"${target_prefix}$\" \"${target_prefix}$.dbg\")") + install(CODE "execute_process(WORKING_DIRECTORY \"${CMAKE_INSTALL_PREFIX}\" COMMAND objcopy --strip-debug --add-gnu-debuglink=$.dbg \"${target_prefix}$\")") + endif () + list(APPEND DEBUG_FILES_LIST "${output_name}") + endforeach () + if (WIN32) + list(TRANSFORM DEBUG_FILES_LIST APPEND ".pdb") + list(JOIN DEBUG_FILES_LIST " " DEBUG_FILES) + install(CODE "execute_process(WORKING_DIRECTORY \"${CMAKE_INSTALL_PREFIX}\" COMMAND 7z a -t7z \"${CMAKE_INSTALL_PREFIX}/debug.7z\" ${DEBUG_FILES})") + elseif (APPLE) + list(TRANSFORM DEBUG_FILES_LIST APPEND ".dSYM") + list(JOIN DEBUG_FILES_LIST " " DEBUG_FILES) + install(CODE "execute_process(WORKING_DIRECTORY \"${CMAKE_INSTALL_PREFIX}\" COMMAND tar acfv \"${CMAKE_INSTALL_PREFIX}/debug.tar.xz\" ${DEBUG_FILES})") + elseif (UNIX) + list(TRANSFORM DEBUG_FILES_LIST APPEND ".dbg") + list(JOIN DEBUG_FILES_LIST " " DEBUG_FILES) + install(CODE "execute_process(WORKING_DIRECTORY \"${CMAKE_INSTALL_PREFIX}\" COMMAND tar -I \"xz -9 -T0\" -cvf \"${CMAKE_INSTALL_PREFIX}/debug.tar.xz\" ${DEBUG_FILES})") + endif () +endif () +foreach (target IN LISTS BINARY_TARGETS) + get_target_prefix(${target} target_prefix) + foreach (extra_target IN LISTS EXTRA_TARGETS) + get_target_prefix(${extra_target} extra_prefix) + if (NOT "${target_prefix}" STREQUAL "${extra_prefix}") + # Copy extra target to target prefix + install(CODE "execute_process(WORKING_DIRECTORY \"${CMAKE_INSTALL_PREFIX}\" COMMAND cp \"${extra_prefix}$\" \"${target_prefix}$\")") + endif () + endforeach () +endforeach () diff --git a/CMakePresets.json b/CMakePresets.json new file mode 100644 index 0000000000..73c9915aba --- /dev/null +++ b/CMakePresets.json @@ -0,0 +1,603 @@ +{ + "version": 2, + "cmakeMinimumRequired": { + "major": 3, + "minor": 25, + "patch": 0 + }, + "configurePresets": [ + { + "name": "debug", + "hidden": true, + "cacheVariables": { + "CMAKE_BUILD_TYPE": "Debug", + "CMAKE_MSVC_RUNTIME_LIBRARY": "MultiThreadedDebugDLL" + } + }, + { + "name": "relwithdebinfo", + "hidden": true, + "cacheVariables": { + "CMAKE_BUILD_TYPE": "RelWithDebInfo", + "CMAKE_MSVC_RUNTIME_LIBRARY": "MultiThreaded" + } + }, + { + "name": "linux-default", + "displayName": "Linux (default)", + "generator": "Ninja", + "binaryDir": "${sourceDir}/build/${presetName}", + "cacheVariables": { + "CMAKE_INSTALL_PREFIX": "${sourceDir}/build/install" + }, + "vendor": { + "microsoft.com/VisualStudioSettings/CMake/1.0": { + "hostOS": [ + "Linux" + ] + }, + "microsoft.com/VisualStudioRemoteSettings/CMake/1.0": { + "sourceDir": "$env{HOME}/.vs/$ms{projectDirName}" + } + } + }, + { + "name": "linux-default-debug", + "displayName": "Linux (default) Debug", + "inherits": [ + "debug", + "linux-default" + ] + }, + { + "name": "linux-default-relwithdebinfo", + "displayName": "Linux (default) RelWithDebInfo", + "inherits": [ + "relwithdebinfo", + "linux-default" + ] + }, + { + "name": "linux-clang", + "displayName": "Linux (Clang)", + "inherits": [ + "linux-default" + ], + "cacheVariables": { + "CMAKE_C_COMPILER": "clang", + "CMAKE_CXX_COMPILER": "clang++" + } + }, + { + "name": "linux-clang-debug", + "displayName": "Linux (Clang) Debug", + "inherits": [ + "debug", + "linux-clang" + ] + }, + { + "name": "linux-clang-relwithdebinfo", + "displayName": "Linux (Clang) RelWithDebInfo", + "inherits": [ + "relwithdebinfo", + "linux-clang" + ] + }, + { + "name": "windows-msvc", + "displayName": "Windows (MSVC)", + "generator": "Ninja", + "binaryDir": "${sourceDir}/out/build/${presetName}", + "architecture": { + "value": "x64", + "strategy": "external" + }, + "cacheVariables": { + "CMAKE_C_COMPILER": "cl", + "CMAKE_CXX_COMPILER": "cl", + "CMAKE_INSTALL_PREFIX": "${sourceDir}/out/install" + }, + "vendor": { + "microsoft.com/VisualStudioSettings/CMake/1.0": { + "hostOS": [ + "Windows" + ] + } + } + }, + { + "name": "windows-msvc-debug", + "displayName": "Windows (MSVC) Debug", + "inherits": [ + "debug", + "windows-msvc" + ] + }, + { + "name": "windows-msvc-relwithdebinfo", + "displayName": "Windows (MSVC) RelWithDebInfo", + "inherits": [ + "relwithdebinfo", + "windows-msvc" + ] + }, + { + "name": "windows-arm64-msvc", + "displayName": "Windows ARM64 (MSVC)", + "generator": "Ninja", + "binaryDir": "${sourceDir}/out/build/${presetName}", + "architecture": { + "value": "arm64", + "strategy": "external" + }, + "cacheVariables": { + "CMAKE_C_COMPILER": "cl", + "CMAKE_CXX_COMPILER": "cl", + "CMAKE_INSTALL_PREFIX": "${sourceDir}/out/install", + "AURORA_DAWN_PROVIDER": "vendor" + }, + "vendor": { + "microsoft.com/VisualStudioSettings/CMake/1.0": { + "hostOS": [ + "Windows" + ] + } + } + }, + { + "name": "windows-clang", + "displayName": "Windows (Clang)", + "inherits": [ + "windows-msvc" + ], + "cacheVariables": { + "CMAKE_C_COMPILER": "clang-cl", + "CMAKE_CXX_COMPILER": "clang-cl", + "CMAKE_LINKER": "lld-link" + }, + "vendor": { + "microsoft.com/VisualStudioSettings/CMake/1.0": { + "intelliSenseMode": "windows-clang-x64" + } + } + }, + { + "name": "windows-clang-debug", + "displayName": "Windows (Clang) Debug", + "inherits": [ + "debug", + "windows-clang" + ] + }, + { + "name": "windows-clang-relwithdebinfo", + "displayName": "Windows (Clang) RelWithDebInfo", + "inherits": [ + "relwithdebinfo", + "windows-clang" + ] + }, + { + "name": "macos-default", + "displayName": "macOS (default)", + "generator": "Ninja", + "binaryDir": "${sourceDir}/build/${presetName}", + "cacheVariables": { + "CMAKE_INSTALL_PREFIX": "${sourceDir}/build/install" + }, + "vendor": { + "microsoft.com/VisualStudioSettings/CMake/1.0": { + "hostOS": [ + "macOS" + ] + } + } + }, + { + "name": "macos-default-debug", + "displayName": "macOS (default) Debug", + "inherits": [ + "debug", + "macos-default" + ] + }, + { + "name": "macos-default-relwithdebinfo", + "displayName": "macOS (default) RelWithDebInfo", + "inherits": [ + "relwithdebinfo", + "macos-default" + ] + }, + { + "name": "ios-default", + "displayName": "iOS", + "generator": "Ninja", + "binaryDir": "${sourceDir}/build/${presetName}", + "inherits": [ + "relwithdebinfo" + ], + "cacheVariables": { + "CMAKE_TOOLCHAIN_FILE": "ios.toolchain.cmake", + "CMAKE_INSTALL_PREFIX": "${sourceDir}/build/install", + "PLATFORM": "OS64", + "DEPLOYMENT_TARGET": "14.0", + "ENABLE_BITCODE": { + "type": "BOOL", + "value": false + }, + "ENABLE_ARC": { + "type": "BOOL", + "value": false + }, + "Rust_CARGO_TARGET": "aarch64-apple-ios", + "BUILD_SHARED_LIBS": { + "type": "BOOL", + "value": false + }, + "CMAKE_DISABLE_FIND_PACKAGE_BZip2": { + "type": "BOOL", + "value": true + }, + "CMAKE_DISABLE_FIND_PACKAGE_LibLZMA": { + "type": "BOOL", + "value": true + }, + "CMAKE_DISABLE_FIND_PACKAGE_zstd": { + "type": "BOOL", + "value": true + }, + "CMAKE_DISABLE_FIND_PACKAGE_Freetype": { + "type": "BOOL", + "value": true + } + }, + "vendor": { + "microsoft.com/VisualStudioSettings/CMake/1.0": { + "hostOS": [ + "macOS" + ] + } + } + }, + { + "name": "tvos-default", + "displayName": "tvOS", + "generator": "Ninja", + "binaryDir": "${sourceDir}/build/${presetName}", + "inherits": [ + "relwithdebinfo" + ], + "cacheVariables": { + "CMAKE_TOOLCHAIN_FILE": "ios.toolchain.cmake", + "CMAKE_INSTALL_PREFIX": "${sourceDir}/build/install", + "PLATFORM": "TVOS", + "DEPLOYMENT_TARGET": "14.5", + "ENABLE_BITCODE": { + "type": "BOOL", + "value": false + }, + "Rust_CARGO_TARGET": "aarch64-apple-tvos", + "Rust_TOOLCHAIN": "nightly", + "BUILD_SHARED_LIBS": { + "type": "BOOL", + "value": false + }, + "CMAKE_DISABLE_FIND_PACKAGE_BZip2": { + "type": "BOOL", + "value": true + }, + "CMAKE_DISABLE_FIND_PACKAGE_LibLZMA": { + "type": "BOOL", + "value": true + }, + "CMAKE_DISABLE_FIND_PACKAGE_zstd": { + "type": "BOOL", + "value": true + } + }, + "vendor": { + "microsoft.com/VisualStudioSettings/CMake/1.0": { + "hostOS": [ + "macOS" + ] + } + } + }, + { + "name": "android-base", + "hidden": true, + "generator": "Ninja", + "binaryDir": "${sourceDir}/build/${presetName}", + "inherits": [ + "relwithdebinfo" + ], + "cacheVariables": { + "CMAKE_INSTALL_PREFIX": "${sourceDir}/build/install", + "CMAKE_TOOLCHAIN_FILE": "$env{ANDROID_HOME}/ndk/$env{ANDROID_NDK_VERSION}/build/cmake/android.toolchain.cmake", + "ANDROID_PLATFORM": "android-24" + } + }, + { + "name": "android-arm64", + "displayName": "Android (arm64-v8a)", + "inherits": [ + "android-base" + ], + "cacheVariables": { + "ANDROID_ABI": "arm64-v8a" + } + }, + { + "name": "android-x86_64", + "displayName": "Android (x86_64)", + "inherits": [ + "android-base" + ], + "cacheVariables": { + "ANDROID_ABI": "x86_64" + } + }, + { + "name": "x-linux-ci", + "hidden": true, + "inherits": [ + "relwithdebinfo" + ], + "cacheVariables": { + "CMAKE_C_COMPILER_LAUNCHER": "sccache", + "CMAKE_CXX_COMPILER_LAUNCHER": "sccache" + } + }, + { + "name": "x-linux-ci-gcc", + "inherits": [ + "x-linux-ci", + "linux-default" + ] + }, + { + "name": "x-linux-ci-clang", + "inherits": [ + "x-linux-ci", + "linux-clang" + ] + }, + { + "name": "x-macos-ci", + "inherits": [ + "macos-default-relwithdebinfo" + ], + "cacheVariables": { + "CMAKE_C_COMPILER_LAUNCHER": "sccache", + "CMAKE_CXX_COMPILER_LAUNCHER": "sccache" + } + }, + { + "name": "x-ios-ci", + "inherits": [ + "ios-default" + ], + "cacheVariables": { + "CMAKE_C_COMPILER_LAUNCHER": "sccache", + "CMAKE_CXX_COMPILER_LAUNCHER": "sccache" + } + }, + { + "name": "x-tvos-ci", + "inherits": [ + "tvos-default" + ], + "cacheVariables": { + "CMAKE_C_COMPILER_LAUNCHER": "sccache", + "CMAKE_CXX_COMPILER_LAUNCHER": "sccache" + } + }, + { + "name": "x-windows-ci", + "hidden": true, + "inherits": [ + "relwithdebinfo" + ], + "binaryDir": "$env{BUILD_DIR}", + "cacheVariables": { + "CMAKE_INSTALL_PREFIX": "$env{BUILD_DIR}/install", + "CMAKE_C_COMPILER_LAUNCHER": "sccache", + "CMAKE_CXX_COMPILER_LAUNCHER": "sccache", + "CMAKE_MSVC_DEBUG_INFORMATION_FORMAT": "Embedded" + } + }, + { + "name": "x-windows-ci-msvc", + "inherits": [ + "x-windows-ci", + "windows-msvc" + ] + }, + { + "name": "x-windows-ci-clang", + "inherits": [ + "x-windows-ci", + "windows-clang" + ] + }, + { + "name": "x-windows-ci-arm64-msvc", + "inherits": [ + "x-windows-ci", + "windows-arm64-msvc" + ] + } + ], + "buildPresets": [ + { + "name": "linux-default-debug", + "configurePreset": "linux-default-debug", + "description": "Linux (default) debug build", + "displayName": "Linux (default) Debug" + }, + { + "name": "linux-default-relwithdebinfo", + "configurePreset": "linux-default-relwithdebinfo", + "description": "Linux (default) release build with debug info", + "displayName": "Linux (default) RelWithDebInfo" + }, + { + "name": "linux-clang-debug", + "configurePreset": "linux-clang-debug", + "description": "Linux (Clang) debug build", + "displayName": "Linux (Clang) Debug" + }, + { + "name": "linux-clang-relwithdebinfo", + "configurePreset": "linux-clang-relwithdebinfo", + "description": "Linux (Clang) release build with debug info", + "displayName": "Linux (Clang) RelWithDebInfo" + }, + { + "name": "macos-default-debug", + "configurePreset": "macos-default-debug", + "description": "macOS debug build", + "displayName": "macOS Debug" + }, + { + "name": "macos-default-relwithdebinfo", + "configurePreset": "macos-default-relwithdebinfo", + "description": "macOS release build with debug info", + "displayName": "macOS RelWithDebInfo" + }, + { + "name": "ios-default", + "configurePreset": "ios-default", + "description": "iOS release build with debug info", + "displayName": "iOS RelWithDebInfo", + "targets": [ + "dusk" + ] + }, + { + "name": "tvos-default", + "configurePreset": "tvos-default", + "description": "tvOS release build with debug info", + "displayName": "tvOS RelWithDebInfo", + "targets": [ + "dusk" + ] + }, + { + "name": "android-arm64", + "configurePreset": "android-arm64", + "description": "Android arm64-v8a release build with debug info", + "displayName": "Android arm64-v8a RelWithDebInfo", + "targets": [ + "dusk" + ] + }, + { + "name": "android-x86_64", + "configurePreset": "android-x86_64", + "description": "Android x86_64 release build with debug info", + "displayName": "Android x86_64 RelWithDebInfo", + "targets": [ + "dusk" + ] + }, + { + "name": "windows-msvc-debug", + "configurePreset": "windows-msvc-debug", + "description": "Windows (MSVC) debug build", + "displayName": "Windows (MSVC) Debug" + }, + { + "name": "windows-msvc-relwithdebinfo", + "configurePreset": "windows-msvc-relwithdebinfo", + "description": "Windows (MSVC) release build with debug info", + "displayName": "Windows (MSVC) RelWithDebInfo" + }, + { + "name": "windows-clang-debug", + "configurePreset": "windows-clang-debug", + "description": "Windows (Clang) debug build", + "displayName": "Windows (Clang) Debug" + }, + { + "name": "windows-clang-relwithdebinfo", + "configurePreset": "windows-clang-relwithdebinfo", + "description": "Windows (Clang) release build with debug info", + "displayName": "Windows (Clang) RelWithDebInfo" + }, + { + "name": "x-linux-ci-gcc", + "configurePreset": "x-linux-ci-gcc", + "description": "(Internal) Linux CI GCC", + "displayName": "(Internal) Linux CI GCC", + "targets": [ + "install" + ] + }, + { + "name": "x-linux-ci-clang", + "configurePreset": "x-linux-ci-clang", + "description": "(Internal) Linux CI Clang", + "displayName": "(Internal) Linux CI Clang", + "targets": [ + "install" + ] + }, + { + "name": "x-macos-ci", + "configurePreset": "x-macos-ci", + "description": "(Internal) macOS CI", + "displayName": "(Internal) macOS CI", + "targets": [ + "install" + ] + }, + { + "name": "x-ios-ci", + "configurePreset": "x-ios-ci", + "description": "(Internal) iOS CI", + "displayName": "(Internal) iOS CI", + "targets": [ + "install" + ] + }, + { + "name": "x-tvos-ci", + "configurePreset": "x-tvos-ci", + "description": "(Internal) tvOS CI", + "displayName": "(Internal) tvOS CI", + "targets": [ + "install" + ] + }, + { + "name": "x-windows-ci-msvc", + "configurePreset": "x-windows-ci-msvc", + "description": "(Internal) Windows CI MSVC", + "displayName": "(Internal) Windows CI MSVC", + "targets": [ + "install" + ] + }, + { + "name": "x-windows-ci-clang", + "configurePreset": "x-windows-ci-clang", + "description": "(Internal) Windows CI Clang", + "displayName": "(Internal) Windows CI Clang", + "targets": [ + "install" + ] + }, + { + "name": "x-windows-ci-arm64-msvc", + "configurePreset": "x-windows-ci-arm64-msvc", + "description": "(Internal) Windows CI MSVC arm64", + "displayName": "(Internal) Windows CI MSVC arm64", + "targets": [ + "install" + ] + } + ] +} diff --git a/README.md b/README.md index 200913770a..754d3ff1dc 100644 --- a/README.md +++ b/README.md @@ -2,22 +2,22 @@ ### Building #### Prerequisites -* [CMake 3.30+](https://cmake.org) +* [CMake 3.25+](https://cmake.org) * Windows: Install `CMake Tools` in Visual Studio * macOS: `brew install cmake` * [Python 3+](https://python.org) * Windows: [Microsoft Store](https://go.microsoft.com/fwlink?linkID=2082640) * Verify it's added to `%PATH%` by typing `python` in `cmd`. * macOS: `brew install python@3` -* **[Windows]** [Visual Studio 2022 Community](https://www.visualstudio.com/en-us/products/visual-studio-community-vs.aspx) +* **[Windows]** [Visual Studio 2026 Community](https://www.visualstudio.com/en-us/products/visual-studio-community-vs.aspx) * Select `C++ Development` and verify the following packages are included: - * `Windows 10 SDK` + * `Windows 11 SDK` * `CMake Tools` * `C++ Clang Compiler` * `C++ Clang-cl` -* **[macOS]** [Xcode 11.5+](https://developer.apple.com/xcode/download/) -* **[Linux]** Actively tested on Ubuntu 20.04, Arch Linux & derivatives. - * Ubuntu 20.04+ packages +* **[macOS]** [Xcode 16.4+](https://developer.apple.com/xcode/download/) +* **[Linux]** Actively tested on Ubuntu 24.04, Arch Linux & derivatives. + * Ubuntu 24.04+ packages ``` build-essential curl git ninja-build clang lld zlib1g-dev libcurl4-openssl-dev \ libglu1-mesa-dev libdbus-1-dev libvulkan-dev libxi-dev libxrandr-dev libasound2-dev libpulse-dev \ @@ -37,35 +37,64 @@ sudo dnf groupinstall "Development Tools" "Development Libraries" ``` #### Setup -1. Clone and initialize the Dusk repository +Clone and initialize the Dusk repository ```sh -git clone --recursive https://github.com/TakaRikka/dusk.git +git clone --recursive https://github.com/TwilitRealm/dusk.git cd dusk git pull -git submodule update --recursive -``` -2. Generate assets -```sh -cp /path/to/GZ2E01.iso orig/GZ2E01/. -python3 ./configure.py -ninja +git submodule update --init --recursive ``` #### Building -**Visual Studio (Recommended for Windows)** + +**CLion (Windows / macOS / Linux)** + +Open the project directory in CLion. Enable the appropriate presets for your platform: + +![CLion](assets/clion.png) + +**Visual Studio (Windows)** + +Open the project directory in Visual Studio. The CMake configuration will be loaded automatically. + +**ninja (macOS)** + ```sh -cmake -B build/dusk -G "Visual Studio 17 2022" -A x64 # Win32 for 32bit +cmake --preset macos-default-relwithdebinfo +cmake --build --preset macos-default-relwithdebinfo ``` -**ninja (Windows/macOS/Linux)** + +Alternate presets available: +- `macos-default-debug`: Clang, Debug + +**ninja (Linux)** + ```sh -cmake -B build/dusk -GNinja -ninja -C build/dusk +cmake --preset linux-default-relwithdebinfo +cmake --build --preset linux-default-relwithdebinfo ``` +Alternate presets available: +- `linux-default-debug`: GCC, Debug +- `linux-clang-relwithdebinfo`: Clang, RelWithDebInfo +- `linux-clang-debug`: Clang, Debug + +**ninja (Windows)** + +```sh +cmake --preset windows-msvc-relwithdebinfo +cmake --build --preset windows-msvc-relwithdebinfo +``` + +Alternate presets available: +- `windows-msvc-debug`: MSVC, Debug +- `windows-clang-relwithdebinfo`: Clang-cl, RelWithDebInfo +- `windows-clang-debug`: Clang-cl, Debug + #### Running Pass the disc image as a positional argument. Supported formats: ISO (GCM), RVZ, WIA, WBFS, CISO, GCZ ```sh -build/dusk/dusk /path/to/game.rvz +build/{preset}/dusk /path/to/game.rvz ``` If no path is specified, Dusk defaults to `game.iso` in the current working directory. diff --git a/assets/clion.png b/assets/clion.png new file mode 100644 index 0000000000..d4f4f6fb19 Binary files /dev/null and b/assets/clion.png differ diff --git a/ci/build-appimage.sh b/ci/build-appimage.sh new file mode 100755 index 0000000000..82c4cffaeb --- /dev/null +++ b/ci/build-appimage.sh @@ -0,0 +1,18 @@ +#!/bin/bash -ex +shopt -s extglob + +# Get linuxdeploy +cd "$RUNNER_WORKSPACE" +curl -fOL https://github.com/linuxdeploy/linuxdeploy/releases/download/continuous/linuxdeploy-$(uname -m).AppImage +chmod +x linuxdeploy-$(uname -m).AppImage + +# Build AppImage +cd "$GITHUB_WORKSPACE" +mkdir -p build/appdir/usr/{bin,share/{applications,icons/hicolor}} +cp build/install/!(*.*) build/appdir/usr/bin +cp -r platforms/freedesktop/{16x16,32x32,48x48,64x64,128x128,256x256,512x512,1024x1024} build/appdir/usr/share/icons/hicolor +cp platforms/freedesktop/dusk.desktop build/appdir/usr/share/applications + +cd build/install +VERSION="$DUSK_VERSION" NO_STRIP=1 "$RUNNER_WORKSPACE"/linuxdeploy-$(uname -m).AppImage \ + --appdir "$GITHUB_WORKSPACE"/build/appdir --output appimage diff --git a/cmake-variants.yaml b/cmake-variants.yaml index f9f6ad51bd..62d2642311 100644 --- a/cmake-variants.yaml +++ b/cmake-variants.yaml @@ -14,22 +14,6 @@ buildType: long: Optimized, with debug symbols buildType: RelWithDebInfo -platform: - default: win64 - description: Target platform - choices: - win32: - short: Win32 - long: Windows 32-bit (MSVC) - settings: - CMAKE_GENERATOR_PLATFORM: Win32 - - win64: - short: Win64 - long: Windows 64-bit (MSVC) - settings: - CMAKE_GENERATOR_PLATFORM: x64 - tp_version: default: GZ2E01 description: TP Version diff --git a/configure.py b/configure.py index 313d24f55c..147b7150e7 100755 --- a/configure.py +++ b/configure.py @@ -1,5 +1,9 @@ #!/usr/bin/env python3 +print("You do not need to run configure.py for Dusk! This file is here to avoid conflicts with decomp.") +print("Use CMake to configure your build instead.") +exit(1) + ### # Generates build files for the project. # This file also includes the project configuration, diff --git a/extern/aurora b/extern/aurora index d76b70fc72..3bedc9950d 160000 --- a/extern/aurora +++ b/extern/aurora @@ -1 +1 @@ -Subproject commit d76b70fc72c6a5904a9e78c0526353f8b8e93c61 +Subproject commit 3bedc9950da12533f34c1f51fce1b7e6fe5ddcbc diff --git a/files.cmake b/files.cmake index 1302f3c71f..e9149a1777 100644 --- a/files.cmake +++ b/files.cmake @@ -507,10 +507,6 @@ set(JSYSTEM_DEBUG_FILES libs/JSystem/src/JAudio2/JASDSPInterface.cpp libs/JSystem/src/JAudio2/JASDriverIF.cpp libs/JSystem/src/JAudio2/JASSoundParams.cpp - libs/JSystem/src/JAudio2/dspproc.cpp - libs/JSystem/src/JAudio2/dsptask.cpp - libs/JSystem/src/JAudio2/osdsp.cpp - libs/JSystem/src/JAudio2/osdsp_task.cpp libs/JSystem/src/JAudio2/JAIAudible.cpp libs/JSystem/src/JAudio2/JAIAudience.cpp libs/JSystem/src/JAudio2/JAISe.cpp @@ -1336,20 +1332,34 @@ set(DOLPHIN_FILES set(DUSK_FILES include/dusk/endian_gx.hpp + include/dusk/config.hpp + include/dusk/dvd_asset.hpp + src/dusk/dvd_asset.cpp + src/d/actor/d_a_alink_dusk.cpp src/dusk/asserts.cpp + src/dusk/config.cpp + src/dusk/settings.cpp src/dusk/logging.cpp + src/dusk/layout.cpp src/dusk/stubs.cpp src/dusk/endian.cpp src/dusk/extras.c src/dusk/extras.cpp + src/dusk/io.cpp src/dusk/globals.cpp + src/dusk/settings.cpp #src/dusk/m_Do_ext_dusk.cpp + src/dusk/imgui/ImGuiConfig.hpp src/dusk/imgui/ImGuiConsole.hpp src/dusk/imgui/ImGuiConsole.cpp + src/dusk/imgui/ImGuiEngine.cpp + src/dusk/imgui/ImGuiEngine.hpp src/dusk/imgui/ImGuiMenuGame.cpp src/dusk/imgui/ImGuiMenuGame.hpp src/dusk/imgui/ImGuiMenuTools.cpp src/dusk/imgui/ImGuiMenuTools.hpp + src/dusk/imgui/ImGuiMenuEnhancements.cpp + src/dusk/imgui/ImGuiMenuEnhancements.hpp src/dusk/imgui/ImGuiProcessOverlay.cpp src/dusk/imgui/ImGuiCameraOverlay.cpp src/dusk/imgui/ImGuiHeapOverlay.cpp diff --git a/include/SSystem/SComponent/c_cc_s.h b/include/SSystem/SComponent/c_cc_s.h index 62815fb3b6..525781279b 100644 --- a/include/SSystem/SComponent/c_cc_s.h +++ b/include/SSystem/SComponent/c_cc_s.h @@ -15,7 +15,7 @@ public: /* 0x0400 */ cCcD_Obj* mpObjTg[0x300]; /* 0x1000 */ cCcD_Obj* mpObjCo[0x100]; /* 0x1400 */ cCcD_Obj* mpObj[0x500]; -#if DEBUG +#if TARGET_PC || DEBUG /* 0x2800 */ u32 m_debug_code; #endif /* 0x2800 */ u16 mObjAtCount; diff --git a/include/Z2AudioCS/SpkTable.h b/include/Z2AudioCS/SpkTable.h index 8fc12bd735..862fdba3c1 100644 --- a/include/Z2AudioCS/SpkTable.h +++ b/include/Z2AudioCS/SpkTable.h @@ -18,10 +18,10 @@ public: SpkTable(void); void setResource(void* res); - inline s32 getName(s32 num) { + inline const char* getName(s32 num) { JUT_ASSERT(0x35, num >= 0); JUT_ASSERT(0x36, num < mNumOfSound); - return *(mDataOffsets + num); + return (const char*)*(mDataOffsets + num); } inline s32 getNumOfSound() const { return mNumOfSound; } inline bool isValid(void) const { return mIsInitialized; } diff --git a/include/Z2AudioCS/Z2AudioCS.h b/include/Z2AudioCS/Z2AudioCS.h index 7d13accabc..694218ab4f 100644 --- a/include/Z2AudioCS/Z2AudioCS.h +++ b/include/Z2AudioCS/Z2AudioCS.h @@ -19,7 +19,7 @@ public: static SpkSoundHandle* getHandleSoundID(s32 soundNum); static SpkSoundHandle* start(s32 id, s32 chan); static SpkSoundHandle* startLevel(s32 id, s32 chan); - static s32 getName(s32 num); + static const char* getName(s32 num); static s32 getNumOfSound(void); static void stopAll(s32 chan, s32 msec); static void stop(s32 chan); diff --git a/include/Z2AudioLib/Z2DebugSys.h b/include/Z2AudioLib/Z2DebugSys.h index 694086a469..80cadc7a85 100644 --- a/include/Z2AudioLib/Z2DebugSys.h +++ b/include/Z2AudioLib/Z2DebugSys.h @@ -26,7 +26,7 @@ public: virtual ~Z2HioSeSeqDataMgr() {} virtual SeqDataReturnValue getSeqData(JAISoundID param_1, JAISeqData* param_2) { if (field_0x18->getSeqList()->getSeqData(param_1, param_2)) { - param_2->field_0x4 = 4; + param_2->mOffset = 4; return SeqDataReturnValue_2; } else { return JAUSeqDataMgr_SeqCollection::getSeqData(param_1, param_2); diff --git a/include/Z2AudioLib/Z2Instances.h b/include/Z2AudioLib/Z2Instances.h index 0f1a02cdb1..b8e6af7a3e 100644 --- a/include/Z2AudioLib/Z2Instances.h +++ b/include/Z2AudioLib/Z2Instances.h @@ -6,6 +6,9 @@ #include "JSystem/JAudio2/JASAudioThread.h" #include "JSystem/JAudio2/JAUSoundTable.h" +#if TARGET_PC +#define AUDIO_INSTANCES +#else #define AUDIO_INSTANCES \ template<> JASDefaultBankTable* JASGlobalInstance::sInstance; \ template<> JASAudioThread* JASGlobalInstance::sInstance; \ @@ -32,5 +35,6 @@ template<> Z2EnvSeMgr* JASGlobalInstance::sInstance; \ template<> Z2SpeechMgr* JASGlobalInstance::sInstance; \ template<> Z2WolfHowlMgr* JASGlobalInstance::sInstance; +#endif #endif diff --git a/include/Z2AudioLib/Z2SoundHandles.h b/include/Z2AudioLib/Z2SoundHandles.h index 2d9d490f5e..5915e5967b 100644 --- a/include/Z2AudioLib/Z2SoundHandles.h +++ b/include/Z2AudioLib/Z2SoundHandles.h @@ -22,7 +22,7 @@ public: bool isActive() const; Z2SoundHandlePool* getHandleSoundID(JAISoundID soundID); - Z2SoundHandlePool* getHandleUserData(u32 userData); + Z2SoundHandlePool* getHandleUserData(uintptr_t userData); void stopAllSounds(u32 fadeTime); diff --git a/include/Z2AudioLib/Z2SoundPlayer.h b/include/Z2AudioLib/Z2SoundPlayer.h index 6937ba63af..3baf4c15b5 100644 --- a/include/Z2AudioLib/Z2SoundPlayer.h +++ b/include/Z2AudioLib/Z2SoundPlayer.h @@ -3,6 +3,7 @@ #include "JSystem/JAWExtSystem/JAWWindow.h" #include "JSystem/JAudio2/JAISoundHandles.h" +#include "JSystem/JAudio2/JAUSoundTable.h" class Z2SoundPlayer : public JAWWindow { public: @@ -24,43 +25,32 @@ public: virtual void onKeyRight(const JUTGamePad&); u32 getCursorMoveMax(const JUTGamePad&); + int getMenuNumberMax(); + void correctSeNumber(); - /* 0x3ED */ u8 field_0x3ed; - /* 0x3EE */ u8 field_0x3ee; - /* 0x3EF */ u8 field_0x3ef; - /* 0x3F0 */ u8 field_0x3f0; - /* 0x3F4 */ const char* field_0x3f4; - /* 0x3F8 */ short field_0x3f8; - /* 0x3FA */ short field_0x3fa; - /* 0x3FC */ short field_0x3fc; - /* 0x3FE */ short field_0x3fe; - /* 0x400 */ short field_0x400; - /* 0x402 */ short field_0x402; - /* 0x404 */ const char* field_0x404; - /* 0x408 */ const char* field_0x408; - /* 0x40C */ const char* field_0x40c; - /* 0x410 */ const char* field_0x410; - /* 0x414 */ const char* field_0x414; - /* 0x418 */ const char* field_0x418; - /* 0x41C */ const char* field_0x41c; - /* 0x420 */ const char* field_0x420; - /* 0x424 */ const char* field_0x424; - /* 0x428 */ const char* field_0x428; - /* 0x42C */ const char* field_0x42c; - /* 0x430 */ const char* field_0x430; - /* 0x434 */ const char* field_0x434; - /* 0x438 */ const char* field_0x438; - /* 0x43C */ const char* field_0x43c; - /* 0x440 */ const char* field_0x440; - /* 0x444 */ short field_0x444; + void onDrawSoundItem(JAWGraphContext*, JAUSoundNameTable*, int, const JUtility::TColor&, const JUtility::TColor&, const char*, u32, u32, u32); + + /* 0x3ED */ bool field_0x3ed; + /* 0x3EE */ bool field_0x3ee; + /* 0x3EF */ bool field_0x3ef; + /* 0x3F0 */ bool field_0x3f0; + /* 0x3F4 */ const char* m_name; + /* 0x3F8 */ s16 field_0x3f8; + /* 0x3FA */ s16 field_0x3fa; + /* 0x3FC */ s16 field_0x3fc; + /* 0x3FE */ s16 field_0x3fe; + /* 0x400 */ s16 field_0x400; + /* 0x402 */ s16 m_portNum; + /* 0x404 */ const char* m_portNames[16]; + /* 0x444 */ s16 m_portVal; /* 0x446 */ u8 field_0x446; - /* 0x448 */ short* field_0x448[7]; - /* 0x464 */ int field_0x464; - /* 0x468 */ int field_0x468; + /* 0x448 */ s16* field_0x448[7]; + /* 0x464 */ u32 m_cursorY; + /* 0x468 */ int m_cursorMax; /* 0x46C */ JAISoundHandle field_0x46c[8]; /* 0x48C */ JAISoundHandles field_0x48c; /* 0x494 */ JAISoundHandle field_0x494; - /* 0x498 */ JAISoundHandle* field_0x498; + /* 0x498 */ JAISoundHandle* mp_subBgmHandle; /* 0x49C */ JAISoundHandle field_0x49c; /* 0x4A0 */ int field_0x4a0; /* 0x4A4 */ f32 field_0x4a4; diff --git a/include/Z2AudioLib/Z2WaveArcLoader.h b/include/Z2AudioLib/Z2WaveArcLoader.h index 81a4bc2123..ac15c50001 100644 --- a/include/Z2AudioLib/Z2WaveArcLoader.h +++ b/include/Z2AudioLib/Z2WaveArcLoader.h @@ -2,10 +2,39 @@ #define Z2WAVEARCLOADER_H #include "JSystem/JAWExtSystem/JAWWindow.h" +#include "JSystem/JAudio2/JASWaveArcLoader.h" +#include "JSystem/JAudio2/JASWaveInfo.h" class Z2WaveArcLoader : public JAWWindow { public: Z2WaveArcLoader(); + virtual ~Z2WaveArcLoader(); + + virtual void onDraw(JAWGraphContext*); + + void checkWaveBank(); + void checkWaveArc(); + + virtual void onKeyUp(const JUTGamePad&); + virtual void onKeyDown(const JUTGamePad&); + virtual void onKeyLeft(const JUTGamePad&); + virtual void onKeyRight(const JUTGamePad&); + virtual void onTrigA(const JUTGamePad&); + virtual void onTrigB(const JUTGamePad&); + virtual void onTrigZ(const JUTGamePad&); + + /* 0x3F0 */ JASWaveBank* mpWaveBank; + /* 0x3F4 */ JASWaveArc* mpWaveArc; + /* 0x3F8 */ u32 mWaveUsedSize; + /* 0x3FC */ int mTotalUsedSize; + /* 0x400 */ u8 mBankNo; + /* 0x404 */ u32 mArcCount; + /* 0x408 */ u32 field_0x408; + /* 0x40C */ u32 field_0x40c; + /* 0x410 */ u32 field_0x410; + /* 0x414 */ u8 field_0x414; + /* 0x415 */ u8 field_0x415; + /* 0x416 */ bool mIsLoadTail; }; #endif /* Z2WAVEARCLOADER_H */ diff --git a/include/d/actor/d_a_alink.h b/include/d/actor/d_a_alink.h index 7c70ea54e5..f74aef4f0a 100644 --- a/include/d/actor/d_a_alink.h +++ b/include/d/actor/d_a_alink.h @@ -4547,6 +4547,10 @@ public: /* 0x03848 */ cXyz* field_0x3848; /* 0x0384C */ cXyz* field_0x384c; /* 0x03850 */ daAlink_procFunc mpProcFunc; + +#if TARGET_PC + void handleQuickTransform(); +#endif }; // Size: 0x385C class daAlinkHIO_data_c : public JORReflexible { diff --git a/include/d/actor/d_a_e_ws.h b/include/d/actor/d_a_e_ws.h index c7b6ae5c58..ada0509d24 100644 --- a/include/d/actor/d_a_e_ws.h +++ b/include/d/actor/d_a_e_ws.h @@ -50,30 +50,30 @@ public: int create(); /* 0x5AC */ request_of_phase_process_class mPhase; - /* 0x5B4 */ mDoExt_McaMorfSO* mpModelMorf; + /* 0x5B4 */ mDoExt_McaMorfSO* mAnm_p; /* 0x5B8 */ Z2CreatureEnemy mSound; - /* 0x65C */ cXyz field_0x65c; - /* 0x668 */ csXyz field_0x668; - /* 0x66E */ csXyz field_0x66e; + /* 0x65C */ cXyz mHomePos; + /* 0x668 */ csXyz mTargetWallAngle; + /* 0x66E */ csXyz mWallAngle; /* 0x674 */ f32 mDownColor; /* 0x678 */ f32 mBodyScale; /* 0x67C */ int mAction; /* 0x680 */ int mMode; /* 0x684 */ u32 mShadowId; /* 0x688 */ s16 mTargetAngle; - /* 0x68A */ s16 mTargetStep; - /* 0x68C */ u8 mMoveWaitTimer; + /* 0x68A */ s16 mStepAngle; + /* 0x68C */ u8 mWaitTimer; /* 0x68E */ s16 mInvulnerabilityTimer; - /* 0x690 */ u8 field_0x690; - /* 0x691 */ u8 field_0x691; - /* 0x692 */ u8 mSwbit; - /* 0x694 */ dBgS_AcchCir mAcchCir; + /* 0x690 */ u8 mIsReturnHome; + /* 0x691 */ u8 arg0; + /* 0x692 */ u8 bitSw; + /* 0x694 */ dBgS_AcchCir mBgc; /* 0x6D4 */ dBgS_ObjAcch mAcch; /* 0x8AC */ dCcD_Stts mCcStts; /* 0x8E8 */ dCcD_Sph mCcSph; /* 0xA20 */ dCcD_Sph mCcBokkuriSph; /* 0xB58 */ dCcU_AtInfo mAtInfo; - /* 0xB7C */ u8 mHIOInit; + /* 0xB7C */ u8 mHioSet; }; STATIC_ASSERT(sizeof(daE_WS_c) == 0xb80); diff --git a/include/d/actor/d_a_movie_player.h b/include/d/actor/d_a_movie_player.h index e064d558dd..0ddc675c24 100644 --- a/include/d/actor/d_a_movie_player.h +++ b/include/d/actor/d_a_movie_player.h @@ -1,7 +1,11 @@ #ifndef D_A_MOVIE_PLAYER_H #define D_A_MOVIE_PLAYER_H +#if !TARGET_PC #include +#else +#include +#endif #include "f_op/f_op_actor.h" #include "d/d_drawlist.h" @@ -11,6 +15,85 @@ struct daMP_THPReadBuffer { BOOL isValid; }; +#if TARGET_PC +// Copying here because thp.h is probably erroneous in the dolphin lib, +// and it's kind of a problem being there (Aurora owns the headers). +// TODO: Move this stuff in decomp? +typedef struct THPAudioRecordHeader { + BE(u32) offsetNextChannel; + BE(u32) sampleSize; + BE(s16) lCoef[8][2]; + BE(s16) rCoef[8][2]; + BE(s16) lYn1; + BE(s16) lYn2; + BE(s16) rYn1; + BE(s16) rYn2; +} THPAudioRecordHeader; + +typedef struct THPAudioDecodeInfo { + u8* encodeData; + u32 offsetNibbles; + u8 predictor; + u8 scale; + s16 yn1; + s16 yn2; +} THPAudioDecodeInfo; + +typedef struct THPTextureSet { + u8* ytexture; + u8* utexture; + u8* vtexture; + s32 frameNumber; +} THPTextureSet; + +typedef struct THPAudioBuffer { + s16* buffer; + s16* curPtr; + u32 validSample; +} THPAudioBuffer; + +typedef struct THPVideoInfo { + BE(u32) xSize; + BE(u32) ySize; + BE(u32) videoType; +} THPVideoInfo; + +typedef struct THPAudioInfo { + BE(u32) sndChannels; + BE(u32) sndFrequency; + BE(u32) sndNumSamples; + BE(u32) sndNumTracks; +} THPAudioInfo; + +typedef struct THPFrameCompInfo { + BE(u32) numComponents; + u8 frameComp[16]; +} THPFrameCompInfo; + +typedef struct THPHeader { + /* 0x00 */ char magic[4]; + /* 0x04 */ BE(u32) version; + /* 0x08 */ BE(u32) bufsize; + /* 0x0C */ BE(u32) audioMaxSamples; + /* 0x10 */ BE(f32) frameRate; + /* 0x14 */ BE(u32) numFrames; + /* 0x18 */ BE(u32) firstFrameSize; + /* 0x1C */ BE(u32) movieDataSize; + /* 0x20 */ BE(u32) compInfoDataOffsets; + /* 0x24 */ BE(u32) offsetDataOffsets; + /* 0x28 */ BE(u32) movieDataOffsets; + /* 0x2C */ BE(u32) finalFrameDataOffsets; +} THPHeader; + +static u32 THPAudioDecode(s16* audioBuffer, u8* audioFrame, s32 flag); +static s32 __THPAudioGetNewSample(THPAudioDecodeInfo* info); +static void __THPAudioInitialize(THPAudioDecodeInfo* info, u8* ptr); + +#define THP_AUDIO_BUFFER_COUNT 3 +#define THP_READ_BUFFER_COUNT 10 +#define THP_TEXTURE_SET_COUNT 3 +#endif + struct daMP_THPPlayer { /* 0x000 */ DVDFileInfo fileInfo; /* 0x03C */ THPHeader header; @@ -34,7 +117,11 @@ struct daMP_THPPlayer { /* 0x0C8 */ s64 retaceCount; /* 0x0D0 */ s32 prevCount; /* 0x0D4 */ s32 curCount; +#if TARGET_PC + /* 0x0D8 */ std::atomic videoDecodeCount; +#else /* 0x0D8 */ s32 videoDecodeCount; +#endif /* 0x0DC */ f32 curVolume; /* 0x0E0 */ f32 targetVolume; /* 0x0E4 */ f32 deltaVolume; diff --git a/include/d/actor/d_a_npc_sola.h b/include/d/actor/d_a_npc_sola.h index 6d6cf742f8..0b13842f9c 100644 --- a/include/d/actor/d_a_npc_sola.h +++ b/include/d/actor/d_a_npc_sola.h @@ -77,7 +77,7 @@ public: int CreateHeap(); int Delete(); int Execute(); - void Draw(); + int Draw(); static BOOL createHeapCallBack(fopAc_ac_c*); static BOOL ctrlJointCallBack(J3DJoint*, int); bool getType(); diff --git a/include/d/actor/d_flower.h b/include/d/actor/d_flower.h index 92bdad59a2..cd505335a8 100644 --- a/include/d/actor/d_flower.h +++ b/include/d/actor/d_flower.h @@ -103,6 +103,11 @@ public: /* 0x12A48 */ u32 m_Jhana01DL_size; /* 0x12A4C */ u8* mp_Jhana01_cDL; /* 0x12A50 */ u32 m_Jhana01_cDL_size; + +#if TARGET_PC + TGXTexObj mTexObj_l_J_Ohana00_64TEX; + TGXTexObj mTexObj_l_J_Ohana01_64128_0419TEX; +#endif }; // Size: 0x12A54 #endif /* D_FLOWER_H */ diff --git a/include/d/actor/d_grass.h b/include/d/actor/d_grass.h index 5a152ed478..47b948679d 100644 --- a/include/d/actor/d_grass.h +++ b/include/d/actor/d_grass.h @@ -108,8 +108,8 @@ public: /* 0x1D714 */ s16 field_0x1d714; #if TARGET_PC - GXTexObj mTexObj_l_M_Hijiki00TEX{}; - GXTexObj mTexObj_l_M_kusa05_RGBATEX{}; + TGXTexObj mTexObj_l_M_Hijiki00TEX; + TGXTexObj mTexObj_l_M_kusa05_RGBATEX; #endif }; // Size: 0x1D718 diff --git a/include/d/d_bright_check.h b/include/d/d_bright_check.h index d8686944e6..dc9ae941cf 100644 --- a/include/d/d_bright_check.h +++ b/include/d/d_bright_check.h @@ -29,6 +29,9 @@ public: void _move(); void modeWait(); void modeMove(); + #if TARGET_PC + void brightCheckWide(); + #endif void _draw(); void draw() { diff --git a/include/d/d_camera.h b/include/d/d_camera.h index 37b634d18f..85e930c395 100644 --- a/include/d/d_camera.h +++ b/include/d/d_camera.h @@ -1154,7 +1154,7 @@ public: static engine_fn engine_tbl[]; /* 0x000 */ camera_class* field_0x0; -#if DEBUG +#if PARTIAL_DEBUG || DEBUG // Ensure struct layout consistent in all TUs. cXyz dbg_field_0x04[16]; s8 dbg_field_0xc4[0x10]; u32 dbg_field_0xd4; diff --git a/include/d/d_com_inf_game.h b/include/d/d_com_inf_game.h index fc60c5d107..78ab356500 100644 --- a/include/d/d_com_inf_game.h +++ b/include/d/d_com_inf_game.h @@ -17,6 +17,8 @@ #include "m_Do/m_Do_graphic.h" #include +#include "tracy/Tracy.hpp" + enum dComIfG_ButtonStatus { /* 0x00 */ BUTTON_STATUS_NONE, /* 0x01 */ BUTTON_STATUS_LET_GO, @@ -3109,114 +3111,133 @@ inline void dComIfGp_particle_calcMenu() { } inline void dComIfGp_particle_draw(JPADrawInfo* i_drawInfo) { + ZoneScoped; if (g_dComIfG_gameInfo.play.getParticle() != NULL) { g_dComIfG_gameInfo.play.getParticle()->drawNormal(i_drawInfo); } } inline void dComIfGp_particle_drawFog(JPADrawInfo* i_drawInfo) { + ZoneScoped; if (g_dComIfG_gameInfo.play.getParticle() != NULL) { g_dComIfG_gameInfo.play.getParticle()->drawNormalFog(i_drawInfo); } } inline void dComIfGp_particle_drawP1(JPADrawInfo* i_drawInfo) { + ZoneScoped; if (g_dComIfG_gameInfo.play.getParticle() != NULL) { g_dComIfG_gameInfo.play.getParticle()->drawNormalP1(i_drawInfo); } } inline void dComIfGp_particle_drawProjection(JPADrawInfo* i_drawInfo) { + ZoneScoped; if (g_dComIfG_gameInfo.play.getParticle() != NULL) { g_dComIfG_gameInfo.play.getParticle()->drawProjection(i_drawInfo); } } inline void dComIfGp_particle_drawNormalPri0_A(JPADrawInfo* i_drawInfo) { + ZoneScoped; if (g_dComIfG_gameInfo.play.getParticle() != NULL) { g_dComIfG_gameInfo.play.getParticle()->drawNormalPri0_A(i_drawInfo); } } inline void dComIfGp_particle_drawNormalPri0_B(JPADrawInfo* i_drawInfo) { + ZoneScoped; if (g_dComIfG_gameInfo.play.getParticle() != NULL) { g_dComIfG_gameInfo.play.getParticle()->drawNormalPri0_B(i_drawInfo); } } inline void dComIfGp_particle_drawFogPri0_A(JPADrawInfo* i_drawInfo) { + ZoneScoped; if (g_dComIfG_gameInfo.play.getParticle() != NULL) { g_dComIfG_gameInfo.play.getParticle()->drawFogPri0_A(i_drawInfo); } } inline void dComIfGp_particle_drawFogPri0_B(JPADrawInfo* i_drawInfo) { + ZoneScoped; if (g_dComIfG_gameInfo.play.getParticle() != NULL) { g_dComIfG_gameInfo.play.getParticle()->drawFogPri0_B(i_drawInfo); } } inline void dComIfGp_particle_drawFogPri1(JPADrawInfo* i_drawInfo) { + ZoneScoped; if (g_dComIfG_gameInfo.play.getParticle() != NULL) { g_dComIfG_gameInfo.play.getParticle()->drawFogPri1(i_drawInfo); } } inline void dComIfGp_particle_drawFogPri2(JPADrawInfo* i_drawInfo) { + ZoneScoped; if (g_dComIfG_gameInfo.play.getParticle() != NULL) { g_dComIfG_gameInfo.play.getParticle()->drawFogPri2(i_drawInfo); } } inline void dComIfGp_particle_drawFogPri3(JPADrawInfo* i_drawInfo) { + ZoneScoped; if (g_dComIfG_gameInfo.play.getParticle() != NULL) { g_dComIfG_gameInfo.play.getParticle()->drawFogPri3(i_drawInfo); } } inline void dComIfGp_particle_drawFogPri4(JPADrawInfo* i_drawInfo) { + ZoneScoped; if (g_dComIfG_gameInfo.play.getParticle() != NULL) { g_dComIfG_gameInfo.play.getParticle()->drawFogPri4(i_drawInfo); } } inline void dComIfGp_particle_drawDarkworld(JPADrawInfo* i_drawInfo) { + ZoneScoped; if (g_dComIfG_gameInfo.play.getParticle() != NULL) { g_dComIfG_gameInfo.play.getParticle()->drawDarkworld(i_drawInfo); } } inline void dComIfGp_particle_drawScreen(JPADrawInfo* i_drawInfo) { + ZoneScoped; if (g_dComIfG_gameInfo.play.getParticle() != NULL) { g_dComIfG_gameInfo.play.getParticle()->drawFogScreen(i_drawInfo); } } inline void dComIfGp_particle_draw2Dgame(JPADrawInfo* i_drawInfo) { + ZoneScoped; if (g_dComIfG_gameInfo.play.getParticle() != NULL) { g_dComIfG_gameInfo.play.getParticle()->draw2Dgame(i_drawInfo); } } inline void dComIfGp_particle_draw2Dfore(JPADrawInfo* i_drawInfo) { + ZoneScoped; if (g_dComIfG_gameInfo.play.getParticle() != NULL) { g_dComIfG_gameInfo.play.getParticle()->draw2Dfore(i_drawInfo); } } inline void dComIfGp_particle_draw2Dback(JPADrawInfo* i_drawInfo) { + ZoneScoped; if (g_dComIfG_gameInfo.play.getParticle() != NULL) { g_dComIfG_gameInfo.play.getParticle()->draw2Dback(i_drawInfo); } } inline void dComIfGp_particle_draw2DmenuFore(JPADrawInfo* i_drawInfo) { + ZoneScoped; if (g_dComIfG_gameInfo.play.getParticle() != NULL) { g_dComIfG_gameInfo.play.getParticle()->draw2DmenuFore(i_drawInfo); } } inline void dComIfGp_particle_draw2DmenuBack(JPADrawInfo* i_drawInfo) { + ZoneScoped; if (g_dComIfG_gameInfo.play.getParticle() != NULL) { g_dComIfG_gameInfo.play.getParticle()->draw2DmenuBack(i_drawInfo); } @@ -4736,114 +4757,142 @@ inline void dComIfGd_setViewport(view_port_class* port) { } inline void dComIfGd_entryZSortListZxlu(J3DPacket* i_packet, cXyz& param_1) { + ZoneScoped; g_dComIfG_gameInfo.drawlist.entryZSortListZxlu(i_packet, param_1); } inline void dComIfGd_entryZSortXluList(J3DPacket* i_packet, cXyz& param_1) { + ZoneScoped; g_dComIfG_gameInfo.drawlist.entryZSortXluList(i_packet, param_1); } inline void dComIfGd_drawCopy2D() { + ZoneScoped; g_dComIfG_gameInfo.drawlist.drawCopy2D(); } inline void dComIfGd_drawOpaListSky() { + ZoneScoped; g_dComIfG_gameInfo.drawlist.drawOpaListSky(); } inline void dComIfGd_drawXluListSky() { + ZoneScoped; g_dComIfG_gameInfo.drawlist.drawXluListSky(); } inline void dComIfGd_drawOpaListBG() { + ZoneScoped; g_dComIfG_gameInfo.drawlist.drawOpaListBG(); } inline void dComIfGd_drawOpaListDarkBG() { + ZoneScoped; g_dComIfG_gameInfo.drawlist.drawOpaListDarkBG(); } inline void dComIfGd_drawOpaListMiddle() { + ZoneScoped; g_dComIfG_gameInfo.drawlist.drawOpaListMiddle(); } inline void dComIfGd_drawOpaList() { + ZoneScoped; g_dComIfG_gameInfo.drawlist.drawOpaList(); } inline void dComIfGd_drawOpaListDark() { + ZoneScoped; g_dComIfG_gameInfo.drawlist.drawOpaListDark(); } inline void dComIfGd_drawOpaListPacket() { + ZoneScoped; g_dComIfG_gameInfo.drawlist.drawOpaListPacket(); } inline void dComIfGd_drawXluListBG() { + ZoneScoped; g_dComIfG_gameInfo.drawlist.drawXluListBG(); } inline void dComIfGd_drawXluListDarkBG() { + ZoneScoped; g_dComIfG_gameInfo.drawlist.drawXluListDarkBG(); } inline void dComIfGd_drawXluList() { + ZoneScoped; g_dComIfG_gameInfo.drawlist.drawXluList(); } inline void dComIfGd_drawXluListDark() { + ZoneScoped; g_dComIfG_gameInfo.drawlist.drawXluListDark(); } inline void dComIfGd_drawXluListInvisible() { + ZoneScoped; g_dComIfG_gameInfo.drawlist.drawXluListInvisible(); } inline void dComIfGd_drawOpaListInvisible() { + ZoneScoped; g_dComIfG_gameInfo.drawlist.drawOpaListInvisible(); } inline void dComIfGd_drawXluListZxlu() { + ZoneScoped; g_dComIfG_gameInfo.drawlist.drawXluListZxlu(); } inline void dComIfGd_drawXluList2DScreen() { + ZoneScoped; g_dComIfG_gameInfo.drawlist.drawXluList2DScreen(); } inline void dComIfGd_drawOpaList3Dlast() { + ZoneScoped; g_dComIfG_gameInfo.drawlist.drawOpaList3Dlast(); } inline void dComIfGd_draw2DOpa() { + ZoneScoped; g_dComIfG_gameInfo.drawlist.draw2DOpa(); } inline void dComIfGd_draw2DOpaTop() { + ZoneScoped; g_dComIfG_gameInfo.drawlist.draw2DOpaTop(); } inline void dComIfGd_draw2DXlu() { + ZoneScoped; g_dComIfG_gameInfo.drawlist.draw2DXlu(); } inline void dComIfGd_drawOpaListFilter() { + ZoneScoped; g_dComIfG_gameInfo.drawlist.drawOpaListFilter(); } inline void dComIfGd_drawIndScreen() { + ZoneScoped; g_dComIfG_gameInfo.drawlist.drawOpaListP0(); } inline void dComIfGd_drawListZxlu() { + ZoneScoped; g_dComIfG_gameInfo.drawlist.drawXluListZxlu(); } inline void dComIfGd_drawShadow(Mtx param_0) { + ZoneScoped; g_dComIfG_gameInfo.drawlist.drawShadow(param_0); } inline void dComIfGd_imageDrawShadow(Mtx param_0) { + ZoneScoped; g_dComIfG_gameInfo.drawlist.imageDrawShadow(param_0); } diff --git a/include/d/d_file_select.h b/include/d/d_file_select.h index 810831a830..72f7cb7f42 100644 --- a/include/d/d_file_select.h +++ b/include/d/d_file_select.h @@ -367,6 +367,9 @@ public: void menuCursorShow(); void yesnoWakuAlpahAnmInit(u8, u8, u8, u8); bool yesnoWakuAlpahAnm(u8); + #if TARGET_PC + void fileSelectWide(); + #endif void _draw(); void errorMoveAnmInitSet(int, int); bool errorMoveAnm(); diff --git a/include/d/d_map.h b/include/d/d_map.h index 66a51aae75..28786e4f94 100644 --- a/include/d/d_map.h +++ b/include/d/d_map.h @@ -66,14 +66,14 @@ struct dMap_prm_res_s { /* 0x1A7 */ u8 field_0x1a7; /* 0x1A8 */ u8 field_0x1a8; /* 0x1A9 */ u8 field_0x1a9; - /* 0x1AA */ s16 field_0x1aa; - /* 0x1AC */ s16 field_0x1ac; - /* 0x1AE */ s16 field_0x1ae; - /* 0x1B0 */ s16 field_0x1b0; - /* 0x1B2 */ s16 field_0x1b2; - /* 0x1B4 */ s16 field_0x1b4; - /* 0x1B6 */ s16 field_0x1b6; - /* 0x1B8 */ f32 cursor_size; + /* 0x1AA */ BE(s16) field_0x1aa; + /* 0x1AC */ BE(s16) field_0x1ac; + /* 0x1AE */ BE(s16) field_0x1ae; + /* 0x1B0 */ BE(s16) field_0x1b0; + /* 0x1B2 */ BE(s16) field_0x1b2; + /* 0x1B4 */ BE(s16) field_0x1b4; + /* 0x1B6 */ BE(s16) field_0x1b6; + /* 0x1B8 */ BE(f32) cursor_size; }; struct dMap_prm_hio_s { diff --git a/include/d/d_map_path.h b/include/d/d_map_path.h index 3dcfd2b38d..495fdf396a 100644 --- a/include/d/d_map_path.h +++ b/include/d/d_map_path.h @@ -5,7 +5,7 @@ #include "JSystem/JHostIO/JORMContext.h" struct dMpath_RGB5A3_s { - u16 color; + BE(u16) color; }; namespace dMpath_ColorCnv_n { diff --git a/include/d/d_menu_collect.h b/include/d/d_menu_collect.h index 01ee32f6d4..55d5373c71 100644 --- a/include/d/d_menu_collect.h +++ b/include/d/d_menu_collect.h @@ -29,6 +29,11 @@ public: class dMenu_Collect2D_c : public dDlst_base_c { public: dMenu_Collect2D_c(JKRExpHeap*, STControl*, CSTControl*); + + #if TARGET_PC + void menuCollectWide(); + #endif + void _create(); void _delete(); void initialize(); @@ -45,7 +50,11 @@ public: void changeShield(); void changeClothe(); void setArrowMaxNum(u8); +#if TARGET_PC + void setWalletSizeNum(u16); +#else void setWalletMaxNum(u16); +#endif void setSmellType(); void setHeartPiece(); void setPohMaxNum(u8); diff --git a/include/d/d_menu_map_common.h b/include/d/d_menu_map_common.h index 84da15328c..989aee7d8b 100644 --- a/include/d/d_menu_map_common.h +++ b/include/d/d_menu_map_common.h @@ -75,9 +75,9 @@ public: /* 0x00 */ char mName[8]; /* 0x08 */ u8 mRoomNo; /* 0x09 */ u8 mRegionNo; - /* 0x0A */ u16 mAreaName; - /* 0x0C */ f32 mOffsetX; - /* 0x10 */ f32 mOffsetZ; + /* 0x0A */ BE(u16) mAreaName; + /* 0x0C */ BE(f32) mOffsetX; + /* 0x10 */ BE(f32) mOffsetZ; }; /* 0x0 */ u8 mCount; diff --git a/include/d/d_menu_save.h b/include/d/d_menu_save.h index a6b174bbf4..4a70d1d045 100644 --- a/include/d/d_menu_save.h +++ b/include/d/d_menu_save.h @@ -263,6 +263,11 @@ public: void setSaveData(); void setInitSaveData(); void _draw(); + + #if TARGET_PC + void menuSaveWide(); + #endif + void _draw2(); virtual ~dMenu_save_c() {} diff --git a/include/d/d_meter2_draw.h b/include/d/d_meter2_draw.h index c11bd680bb..10cded803d 100644 --- a/include/d/d_meter2_draw.h +++ b/include/d/d_meter2_draw.h @@ -148,6 +148,12 @@ public: void setEmphasisB(u8 param_0) { field_0x762 = param_0; } u8 getInsideObjCheck() { return field_0x772; } +#if TARGET_PC + constexpr f32 getButtonZAlpha() const { + return mButtonZAlpha; + } +#endif + private: /* 0x004 */ item_params mItemParams[4]; /* 0x074 */ JKRExpHeap* heap; diff --git a/include/d/d_meter2_info.h b/include/d/d_meter2_info.h index 72ca6ad9b2..51f07f4dc3 100644 --- a/include/d/d_meter2_info.h +++ b/include/d/d_meter2_info.h @@ -321,6 +321,7 @@ int dMeter2Info_setNewLetterSender(); bool dMeter2Info_isItemOpenCheck(); bool dMeter2Info_isMapOpenCheck(); s16 dMeter2Info_getNowLifeGauge(); +bool dMeter2Info_isNextStage(const char*, s16, s16, s16); #if WIDESCREEN_SUPPORT void dMeter2Info_onWide2D(); @@ -844,10 +845,6 @@ inline void dMeter2Info_onTempBit(int i_bit) { g_meter2_info.onTempBit(i_bit); } -inline bool dMeter2Info_isNextStage(const char*, s16, s16, s16) { - return false; -} - inline void dMeter2Info_setFloatingMessage(u16 i_msgID, s16 i_msgTimer, bool i_wakuVisible) { g_meter2_info.setFloatingMessage(i_msgID, i_msgTimer, i_wakuVisible); } diff --git a/include/d/d_meter_map.h b/include/d/d_meter_map.h index ecf645a6ac..b17f51846e 100644 --- a/include/d/d_meter_map.h +++ b/include/d/d_meter_map.h @@ -89,7 +89,7 @@ public: virtual void draw(); virtual ~dMeterMap_c(); - bool isDispPosInsideFlg() { return field_0x2d != 0; } + bool isDispPosInsideFlg() { return mMapIsInside != 0; } dMeterMap_c* getMapPointer() { return (dMeterMap_c*)mMap; } void setSizeW(f32 w) { mSizeW = w; } void setSizeH(f32 h) { mSizeH = h; } @@ -108,15 +108,15 @@ private: /* 0x0C */ s32 mIsCompass; /* 0x10 */ s32 mIsMap; /* 0x14 */ u32 field_0x14; - /* 0x18 */ f32 field_0x18; - /* 0x1C */ f32 field_0x1c; + /* 0x18 */ f32 mDrawPosX; + /* 0x1C */ f32 mDrawPosY; /* 0x20 */ f32 mSizeW; /* 0x24 */ f32 mSizeH; - /* 0x28 */ s16 field_0x28; + /* 0x28 */ s16 mSlidePositionOffset; /* 0x2A */ u8 field_0x2a; /* 0x2B */ u8 field_0x2b; /* 0x2C */ u8 mMapAlpha; - /* 0x2D */ u8 field_0x2d; + /* 0x2D */ u8 mMapIsInside; /* 0x2E */ u8 field_0x2e; /* 0x30 */ int field_0x30; }; diff --git a/include/d/d_msg_object.h b/include/d/d_msg_object.h index 45606e4e81..b55ea73904 100644 --- a/include/d/d_msg_object.h +++ b/include/d/d_msg_object.h @@ -562,6 +562,10 @@ inline void dMsgObject_setOffering(u16 i_num) { dComIfGs_setEventReg(0xF8FF, i_num & 0xFF); } +inline void dMsgObject_setLetterNameID(u16 id) { + dMsgObject_getMsgObjectClass()->setLetterNameID(id); +} + class dMsgObject_HowlHIO_c { public: dMsgObject_HowlHIO_c(); diff --git a/include/d/d_name.h b/include/d/d_name.h index 0d877e6b09..e685871738 100644 --- a/include/d/d_name.h +++ b/include/d/d_name.h @@ -110,6 +110,11 @@ public: void menuCursorMove(); void menuCursorMove2(); void selectCursorPosSet(int); + + #if TARGET_PC + void nameWide(); + #endif + void _draw(); void screenSet(); void displayInit(); diff --git a/include/d/d_path.h b/include/d/d_path.h index 6e4e159a61..fb83709bad 100644 --- a/include/d/d_path.h +++ b/include/d/d_path.h @@ -20,7 +20,7 @@ struct dPath { /* 0x2 */ BE(u16) m_nextID; /* 0x4 */ u8 field_0x4; /* 0x5 */ bool m_closed; - /* 0x6 */ u8 field_0x6; + /* 0x6 */ u8 swbit; /* 0x7 */ u8 field_0x7; /* 0x8 */ OFFSET_PTR(dPnt) m_points; }; diff --git a/include/d/d_s_name.h b/include/d/d_s_name.h index 73d3d703be..72a44c02de 100644 --- a/include/d/d_s_name.h +++ b/include/d/d_s_name.h @@ -48,6 +48,7 @@ public: void FileSelectClose(); void brightCheckOpen(); void brightCheck(); + void doPreLoadSetup(); void changeGameScene(); #if VERSION == VERSION_GCN_PAL @@ -70,6 +71,9 @@ private: /* 0x41E */ u8 mWaitTimer; /* 0x41F */ u8 field_0x41f; /* 0x420 */ u8 field_0x420; +#if TARGET_PC + bool mShowTvSettingsScreen; +#endif }; #endif /* D_S_D_S_NAME_H */ diff --git a/include/d/d_stage.h b/include/d/d_stage.h index 03dd7491b0..bd8e7d5728 100644 --- a/include/d/d_stage.h +++ b/include/d/d_stage.h @@ -267,7 +267,7 @@ struct dStage_MemoryConfig_c { // PATH / RPAT struct dPath; struct dStage_dPath_c { - /* 0x0 */ BE(int) m_num; + /* 0x0 */ BE(int) num; /* 0x4 */ OFFSET_PTR(dPath) m_path; }; diff --git a/include/d/d_vibration.h b/include/d/d_vibration.h index 204f6e759c..4018acea50 100644 --- a/include/d/d_vibration.h +++ b/include/d/d_vibration.h @@ -47,18 +47,21 @@ class dVibTest_c : public JORReflexible { public: dVibTest_c(); + void Init(); + void setDefault(); + virtual void listenPropertyEvent(const JORPropertyEvent*); virtual void genMessage(JORMContext*); - virtual ~dVibTest_c() {} + virtual ~dVibTest_c(); - /* 0x04 */ s8 field_0x4; + /* 0x04 */ s8 id; /* 0x06 */ u16 m_pattern; /* 0x08 */ u16 m_pattern2; /* 0x0A */ u16 field_0xa; /* 0x0C */ s16 m_randombit; /* 0x0E */ s16 m_length; /* 0x10 */ int field_0x10; - /* 0x14 */ int m_vibswitch; + /* 0x14 */ s32 m_vibswitch; /* 0x18 */ u16 m_displayDbg; }; @@ -82,6 +85,10 @@ public: void Pause(); void Remove(); + #if DEBUG + int testShake(); + #endif + static const vib_pattern MS_patt[VIBMODE_S_MAX]; static const vib_pattern CS_patt[VIBMODE_S_MAX]; static const vib_pattern MQ_patt[VIBMODE_Q_MAX]; @@ -123,4 +130,7 @@ private: /* 0x8C */ s32 mMode; }; // Size: 0x90 +extern const char* shock_names[VIBMODE_S_MAX]; +extern const char* quake_names[VIBMODE_Q_MAX]; + #endif /* D_D_VIBRATION_H */ diff --git a/include/d/dolzel_base.pch b/include/d/dolzel_base.pch index ac45474890..e603a50e14 100644 --- a/include/d/dolzel_base.pch +++ b/include/d/dolzel_base.pch @@ -2,7 +2,9 @@ #define DOLZEL_BASE_PCH // Fixes weak .bss +#if !TARGET_PC #include "weak_bss_1109_to_1009.h" // IWYU pragma: export +#endif #include // IWYU pragma: export #include // IWYU pragma: export diff --git a/include/dusk/app_info.hpp b/include/dusk/app_info.hpp new file mode 100644 index 0000000000..d5d5f40083 --- /dev/null +++ b/include/dusk/app_info.hpp @@ -0,0 +1,20 @@ +#ifndef DUSK_APPNAME_HPP +#define DUSK_APPNAME_HPP + +namespace dusk { + /** + * \brief The internal application name for the game. + * + * This gets used for file paths and such, and cannot be changed! + */ + constexpr auto AppName = "Dusk"; + + /** + * \brief The internal organization name for the game. + * + * This gets used for file paths and such, and cannot be changed! + */ + constexpr auto OrgName = "TwilitRealm"; +} + +#endif // DUSK_APPNAME_HPP diff --git a/include/dusk/audio.h b/include/dusk/audio.h index 46a2dd8859..e3dfda9f52 100644 --- a/include/dusk/audio.h +++ b/include/dusk/audio.h @@ -2,13 +2,13 @@ #define DUSK_AUDIO_H #if TARGET_PC -#define DUSK_AUDIO_DISABLED 1 +#define DUSK_AUDIO_DISABLED 0 #else #define DUSK_AUDIO_DISABLED 0 #endif #if TARGET_PC -#define DUSK_AUDIO_SKIP(...) return __VA_ARGS__; +#define DUSK_AUDIO_SKIP(...) #else #define DUSK_AUDIO_SKIP(...) #endif diff --git a/include/dusk/audio/DuskAudioSystem.h b/include/dusk/audio/DuskAudioSystem.h new file mode 100644 index 0000000000..724776f5f1 --- /dev/null +++ b/include/dusk/audio/DuskAudioSystem.h @@ -0,0 +1,18 @@ +#pragma once + +#include + +namespace dusk::audio { + /** + * Initialize the audio system and start playing audio. + */ + void Initialize(); + + void SetEnableReverb(bool value); + + void SetMasterVolume(f32 value); + + u32 GetResetCount(int channelIdx); + + f32 VolumeFromU16(u16 value); +} diff --git a/include/dusk/config.hpp b/include/dusk/config.hpp new file mode 100644 index 0000000000..258e012f2b --- /dev/null +++ b/include/dusk/config.hpp @@ -0,0 +1,122 @@ +#ifndef DUSK_CONFIG_HPP +#define DUSK_CONFIG_HPP + +#include +#include "nlohmann/json.hpp" +#include "config_var.hpp" + +namespace dusk::config { + +/* + * config.hpp is a heavier "full" header for the configuration system. + * For a basic overview and the basic types (sufficient for accessing settings), + * look at config_var.hpp. + * + * Avoid including this header in the entire game, it's heavier than I'd like! + */ + +/** + * \brief Base class containing virtual functions used for save/load of CVars. + */ +class ConfigImplBase { +protected: + virtual ~ConfigImplBase() = default; + +public: + /** + * \brief Load a JSON value into a CVar at the Value layer. + */ + virtual void loadFromJson(ConfigVarBase& cVar, const nlohmann::json& jsonValue) const = 0; + + /** + * \brief Load a simple launch argument into the CVar at the Override layer. + */ + virtual void loadFromArg(ConfigVarBase& cVar, std::string_view stringValue) const = 0; + + /** + * \brief Dump the value contained in the CVar to JSON. + */ + [[nodiscard]] virtual nlohmann::json dumpToJson(const ConfigVarBase& cVar) const = 0; +}; + +template +class ConfigImpl : public ConfigImplBase { + // Just downcasting the references... + void loadFromJson(ConfigVarBase& cVar, const nlohmann::json& jsonValue) const final { + assert(typeid(cVar) == typeid(ConfigVar)); + loadFromJson(dynamic_cast&>(cVar), jsonValue); + } + + void loadFromArg(ConfigVarBase& cVar, std::string_view stringValue) const final { + assert(typeid(cVar) == typeid(ConfigVar)); + loadFromArg(dynamic_cast&>(cVar), stringValue); + } + + [[nodiscard]] nlohmann::json dumpToJson(const ConfigVarBase& cVar) const final { + assert(typeid(cVar) == typeid(ConfigVar)); + return dumpToJson(dynamic_cast&>(cVar)); + } + + /** + * \brief Load a JSON value into a CVar at the Value layer. + */ + static void loadFromJson(ConfigVar& cVar, const nlohmann::json& jsonValue); + + /** + * \brief Load a simple launch argument into the CVar at the Override layer. + */ + static void loadFromArg(ConfigVar& cVar, std::string_view stringValue); + + /** + * \brief Dump the value contained in the CVar to JSON. + */ + [[nodiscard]] static nlohmann::json dumpToJson(const ConfigVar& cVar); +}; + +/** + * \brief Thrown by config loading functions if the value provided is invalid for the CVar. + */ +class InvalidConfigError : public std::runtime_error { +public: + explicit InvalidConfigError(const char* what) : runtime_error(what) {} +}; + +/** + * \brief Register a CVar to make the config system aware of it. + * + * This must be done on startup *before* config has been loaded. + */ +void Register(ConfigVarBase& configVar); + +/** + * \brief Indicate that all registrations have happened and everything should lock in. + */ +void FinishRegistration(); + +/** + * \brief Load config from the standard user preferences location. + */ +void LoadFromUserPreferences(); +void LoadFromFileName(const char* path); + +/** + * \brief Save the config to file. + */ +void Save(); + +/** + * \brief Get a registered CVar by name. + * + * @return null if the CVar does not exist. + */ +ConfigVarBase* GetConfigVar(std::string_view name); + +template +const ConfigImplBase* GetConfigImpl() { + static ConfigImpl config; + return &config; +} + +} // namespace dusk::config + +#endif diff --git a/include/dusk/config_var.hpp b/include/dusk/config_var.hpp new file mode 100644 index 0000000000..6b78ee2e33 --- /dev/null +++ b/include/dusk/config_var.hpp @@ -0,0 +1,235 @@ +#ifndef DUSK_CONFIG_VAR_HPP +#define DUSK_CONFIG_VAR_HPP + +#include "dolphin/types.h" +#include +#include +#include + +/** + * The configuration system. + * + * Configuration works via "configuration variables" aka "CVars". Each stores a single value that + * may be individually written to/from a configuration file. + * + * CVars, like ogres, have layers. Higher layers (e.g. a set value) override lower layers + * (e.g. the default value). + * + * To define a CVar, simply make a global variable of type ConfigVar, + * and make sure Register() is called on it during program startup. + * + * config_var.hpp contains the simplest "just the configuration vars themselves". + * This should be safe to include for files that need to *access* configuration, + * without blowing up compile times on implementation details. + * + * config.hpp on the other hand contains far more calls for mutating, loading, and defining CVars. + */ +namespace dusk::config { + +/** + * \brief Layers that a configuration variable can currently be at. + * + * A configuration variable can be on one of multiple *layers*, which determines where + * the current value is coming from. + */ +enum class ConfigVarLayer : u8 { + /** + * The CVar is at the default value defined by the application code. + */ + Default, + + /** + * The CVar has been modified by the user and may be saved to config. + */ + Value, + + /** + * The CVar is modified by launch argument, overruling the normal config value. + * Will not get saved to config. + */ + Override, +}; + +class ConfigImplBase; + +/** + * Base class that all CVars inherit from. + * You want the templated ConfigVar instead for actual usage. + */ +class ConfigVarBase { +protected: + /** + * The name of this CVar, used in the configuration file. + */ + const char* name; + + /** + * Whether this CVar has been registered with the global managing logic. + * If this is not done, it is not functional. + */ + bool registered; + + /** + * The layer this CVar is at. + */ + ConfigVarLayer layer; + + /** + * Pointer to an implementation struct for various load/save calls. + */ + const ConfigImplBase* impl; + + ConfigVarBase(const char* name, const ConfigImplBase* impl); + virtual ~ConfigVarBase() = default; + + /** + * Check that the CVar is registered, aborting if this is not the case. + */ + void checkRegistered() const { + if (!registered) + abort(); + } + +public: + /** + * Get the name of this CVar, used in the configuration file. + */ + [[nodiscard]] const char* getName() const noexcept; + + /** + * Get the pointer to the implementation struct. + */ + [[nodiscard]] const ConfigImplBase* getImpl() const noexcept; + + /** + * Get the layer this CVar is currently at. + */ + [[nodiscard]] constexpr ConfigVarLayer getLayer() const noexcept { + return layer; + } + + /** + * Mark this CVar as being registered with the central save/load logic. + * This is necessary to make it legal to access. + */ + void markRegistered(); +}; + +template +concept ConfigValueInteger = + std::is_same_v + || std::is_same_v + || std::is_same_v + || std::is_same_v + || std::is_same_v + || std::is_same_v + || std::is_same_v + || std::is_same_v; + +/** + * \brief Concept that defines the legal set of types that can be used for CVar values. + * + * Valid types cannot be cv-qualified and must be basic primitive types (int, float, bool), + * strings, or enums of the basic primitives. + */ +template +concept ConfigValue = + !std::is_const_v + && !std::is_volatile_v + && (std::is_same_v + || ConfigValueInteger + || std::is_same_v + || std::is_same_v + || std::is_same_v + || (std::is_enum_v && ConfigValueInteger>)); + +template +const ConfigImplBase* GetConfigImpl(); + +/** + * \brief A CVar storing values. + * + * @tparam T The type of value stored in the CVar. + */ +template +class ConfigVar : public ConfigVarBase { + T defaultValue; + T value; + T overrideValue; + +public: + /** + * \brief Construct a CVar. + * + * @param name The name of this CVar. Must be unique. + * @param arg Arguments to forward to construct the default value. + */ + template + ConfigVar(const char* name, Args&&... arg) + : ConfigVarBase(name, GetConfigImpl()), defaultValue(std::forward(arg)...), + value(), overrideValue() {} + + /** + * \brief Get the current value of the CVar. + * + * This reference is not guaranteed to remain up-to-date after modification of the CVar. + * It will, however, remain sound to access. + */ + [[nodiscard]] constexpr const T& getValue() const noexcept { + checkRegistered(); + switch (layer) { + case ConfigVarLayer::Default: + return defaultValue; + case ConfigVarLayer::Value: + return value; + case ConfigVarLayer::Override: + return overrideValue; + default: + abort(); + } + } + + /** + * \brief Change the value of a CVar. + * + * The new value is always stored at the Value layer. + * + * @param newValue The new value the CVar will get. + * @param replaceOverride If true, clear an existing override layer if there is one. + * If this is false and there is an override layer, + * the result of getValue() will not change immediately. + */ + void setValue(T newValue, bool replaceOverride = true) { + checkRegistered(); + value = std::move(newValue); + + if (replaceOverride) { + overrideValue = {}; + layer = ConfigVarLayer::Value; + } else if (layer != ConfigVarLayer::Override) { + layer = ConfigVarLayer::Value; + } + } + + operator const T&() { + return getValue(); + } + + /** + * \brief Give a CVar an override value. + * + * This overrides (but does not replace) the apparent set value of this CVar. + * The overriden value will not get saved to config. + * + * @param newValue The new value the CVar will get. + */ + void setOverrideValue(T newValue) { + checkRegistered(); + overrideValue = std::move(newValue); + layer = ConfigVarLayer::Override; + } +}; + +} + +#endif // DUSK_CONFIG_VAR_HPP diff --git a/include/dusk/dusk.h b/include/dusk/dusk.h index d84e496827..b751990d9c 100644 --- a/include/dusk/dusk.h +++ b/include/dusk/dusk.h @@ -3,6 +3,22 @@ #include +#include "aurora/gfx.h" + extern AuroraInfo auroraInfo; +extern const char* configPath; + +namespace dusk { + extern AuroraStats lastFrameAuroraStats; + extern float frameUsagePct; +} + +constexpr u32 defaultWindowWidth = 608; +constexpr u32 defaultWindowHeight = 448; + +constexpr u32 defaultAspectRatioW = 19; +constexpr u32 defaultAspectRatioH = 14; + +static_assert(defaultWindowWidth / defaultAspectRatioW == defaultWindowHeight / defaultAspectRatioH); #endif // DUSK_DUSK_H diff --git a/include/dusk/dvd_asset.hpp b/include/dusk/dvd_asset.hpp new file mode 100644 index 0000000000..014c683d44 --- /dev/null +++ b/include/dusk/dvd_asset.hpp @@ -0,0 +1,22 @@ +#pragma once + +#include "dolphin/types.h" + +namespace dusk { + +/** + * Load bytes from the main DOL by GameCube virtual address + */ +bool LoadDolAsset(void* dst, u32 virtualAddress, s32 size); + +/** + * Load bytes from a REL file in the ISO filesystem, dst must be 32-byte aligned + */ +bool LoadRelAsset(void* dst, const char* dvdPath, s32 offset, s32 size); + +/** + * Load bytes from a REL inside RELS.arc + */ +bool LoadArchivedRelAsset(void* dst, u32 memType, const char* relFileName, s32 offset, s32 size); + +} // namespace dusk diff --git a/include/dusk/gx_helper.h b/include/dusk/gx_helper.h index adb547ac29..bf81424c99 100644 --- a/include/dusk/gx_helper.h +++ b/include/dusk/gx_helper.h @@ -42,4 +42,13 @@ typedef GXTexObjRAII TGXTexObj; typedef GXTexObj TGXTexObj; #endif +struct GXScopedDebugGroup { + explicit GXScopedDebugGroup(const char* text) { + GXPushDebugGroup(text); + } + ~GXScopedDebugGroup() { + GXPopDebugGroup(); + } +}; + #endif // DUSK_GX_HELPER_H diff --git a/include/dusk/hotkeys.h b/include/dusk/hotkeys.h new file mode 100644 index 0000000000..6e98d62521 --- /dev/null +++ b/include/dusk/hotkeys.h @@ -0,0 +1,25 @@ +#ifndef DUSK_HOTKEYS_H +#define DUSK_HOTKEYS_H + +namespace dusk::hotkeys { + +#if __APPLE__ +constexpr const char* DO_RESET = "Cmd+R"; +#else +constexpr const char* DO_RESET = "Ctrl+R"; +#endif + +constexpr const char* TOGGLE_FULLSCREEN = "F11"; + +constexpr const char* SHOW_PROCESS_MANAGEMENT = "F2"; +constexpr const char* SHOW_DEBUG_OVERLAY = "F3"; +constexpr const char* SHOW_HEAP_VIEWER = "F4"; +constexpr const char* SHOW_STUB_LOG = "F5"; +constexpr const char* SHOW_CAMERA_DEBUG = "F6"; +constexpr const char* SHOW_AUDIO_DEBUG = "F7"; + +constexpr const char* TURBO = "Tab"; + +} + +#endif // DUSK_HOTKEYS_H diff --git a/include/dusk/io.hpp b/include/dusk/io.hpp new file mode 100644 index 0000000000..fb71a77d68 --- /dev/null +++ b/include/dusk/io.hpp @@ -0,0 +1,75 @@ +#ifndef DUSK_IO_HPP +#define DUSK_IO_HPP + +#include + +// I can't believe it's 2026 and neither SDL (no error codes) nor +// C++ (no error codes) have a file system API functional enough for me to use. +// Here you go, this one's inspired by C#. I only wrote the functions I need. + +namespace dusk::io { + +/** + * \brief A simple file stream wrapping cstdio FILE*. + * + * Methods on this class throw appropriate C++ exceptions when an error occurs. + */ +class FileStream { + void* file; + +public: + FileStream() noexcept; + + /** + * \brief Take ownership of a FILE* handle. + */ + explicit FileStream(void* file); + FileStream(const FileStream& other) = delete; + FileStream(FileStream&& other) noexcept; + + ~FileStream(); + + /** + * \brief Open a file for reading at the given path. + */ + static FileStream OpenRead(const char* utf8Path); + + /** + * \brief Create a file for writing. + * + * If there is an existing file, its contents are demolished. + */ + static FileStream Create(const char* utf8Path); + + /** + * \brief Read the byte contents of a file directly into a vector. + */ + static std::vector ReadAllBytes(const char* utf8Path); + + /** + * \brief Read the byte contents of a file directly into a vector. + */ + static void WriteAllText(const char* utf8Path, std::string_view text); + + /** + * \brief Read the remaining contents of the file directly into a vector. + */ + std::vector ReadFull(); + + /** + * Get direct access to the underlying FILE* handle. + */ + [[nodiscard]] void* GetFileHandle() const noexcept { + return file; + } + + /** + * Write data to the file. + */ + void Write(const char* data, size_t dataLen); +}; + +} + + +#endif // DUSK_IO_HPP diff --git a/include/dusk/layout.hpp b/include/dusk/layout.hpp new file mode 100644 index 0000000000..78316d2e09 --- /dev/null +++ b/include/dusk/layout.hpp @@ -0,0 +1,37 @@ +#ifndef DUSK_LAYOUT_H +#define DUSK_LAYOUT_H + +#include "dolphin/types.h" + +namespace dusk { + +/** + * Helper struct for laying things out on the screen. Represents a rectangle via two corner + * positions. + */ +struct LayoutRect { + f32 PosX; + f32 PosY; + f32 PosX2; + f32 PosY2; + + [[nodiscard]] constexpr f32 Width() const { + return PosX2 - PosX; + } + + [[nodiscard]] constexpr f32 Height() const { + return PosY2 - PosY; + } + + /** + * Calculates the position to render one rectangle inside another, centered and maintaining aspect ratio. + */ + [[nodiscard]] static LayoutRect FitRectInRect( + f32 widthOuter, + f32 heightOuter, + f32 widthInner, + f32 heightInner); +}; +} + +#endif // DUSK_LAYOUT_H diff --git a/include/dusk/main.h b/include/dusk/main.h new file mode 100644 index 0000000000..b357de8ea5 --- /dev/null +++ b/include/dusk/main.h @@ -0,0 +1,8 @@ +#ifndef DUSK_MAIN_H +#define DUSK_MAIN_H + +namespace dusk { + extern bool IsShuttingDown; +} + +#endif // DUSK_MAIN_H diff --git a/include/dusk/map_loader_definitions.h b/include/dusk/map_loader_definitions.h index 31dfef7157..a0f7150d2d 100644 --- a/include/dusk/map_loader_definitions.h +++ b/include/dusk/map_loader_definitions.h @@ -617,5 +617,8 @@ static const auto gameRegions = std::to_array({ MapEntry("Cutscene: Hyrule Castle Throne Room", "R_SP301", { {0, {0, 20, 100}}, }), + MapEntry("Title screen movie map", "S_MV000", { + {0, {0, 1}}, + }), }) }); diff --git a/include/dusk/os.h b/include/dusk/os.h new file mode 100644 index 0000000000..180bdb9b1a --- /dev/null +++ b/include/dusk/os.h @@ -0,0 +1,14 @@ +#ifndef DUSK_OS_H +#define DUSK_OS_H + +#ifdef __cplusplus +extern "C" { +#endif + +void OSSetCurrentThreadName(const char* name); + +#ifdef __cplusplus +} +#endif + +#endif // DUSK_OS_H \ No newline at end of file diff --git a/include/dusk/settings.h b/include/dusk/settings.h new file mode 100644 index 0000000000..8b818801a7 --- /dev/null +++ b/include/dusk/settings.h @@ -0,0 +1,101 @@ +#ifndef DUSK_CONFIG_H +#define DUSK_CONFIG_H + +#include "dusk/config_var.hpp" + +namespace dusk { + +using namespace config; + +// Persistent user settings + +struct UserSettings { + // Program settings + + struct { + // Video + ConfigVar enableFullscreen; + ConfigVar enableVsync; + ConfigVar lockAspectRatio; + } video; + + struct { + // Audio + ConfigVar masterVolume; + ConfigVar mainMusicVolume; + ConfigVar subMusicVolume; + ConfigVar soundEffectsVolume; + ConfigVar fanfareVolume; + ConfigVar enableReverb; + } audio; + + // Game settings + + struct { + // QoL + ConfigVar enableQuickTransform; + ConfigVar hideTvSettingsScreen; + ConfigVar biggerWallets; + ConfigVar noReturnRupees; + ConfigVar disableRupeeCutscenes; + ConfigVar noSwordRecoil; + ConfigVar damageMultiplier; + ConfigVar instantDeath; + ConfigVar fastClimbing; + ConfigVar noMissClimbing; + ConfigVar fastTears; + ConfigVar instantSaves; + + // Preferences + ConfigVar enableMirrorMode; + ConfigVar invertCameraXAxis; + + // Graphics + ConfigVar enableBloom; + ConfigVar useWaterProjectionOffset; + + // Audio + ConfigVar noLowHpSound; + ConfigVar midnasLamentNonStop; + + // Cheats + ConfigVar enableFastIronBoots; + ConfigVar canTransformAnywhere; + ConfigVar fastSpinner; + ConfigVar freeMagicArmor; + + // Technical + ConfigVar restoreWiiGlitches; + + // Controls + ConfigVar enableTurboKeybind; + } game; +}; + +UserSettings& getSettings(); + +void registerSettings(); + +// Transient settings + +struct CollisionViewSettings { + bool enableTerrainView; + bool enableWireframe; + bool enableAtView; + bool enableTgView; + bool enableCoView; + float terrainViewOpacity; + float colliderViewOpacity; + float drawRange; +}; + +struct TransientSettings { + CollisionViewSettings collisionView; + bool skipFrameRateLimit; +}; + +TransientSettings& getTransientSettings(); + +} + +#endif // DUSK_CONFIG_H diff --git a/include/dusk/string.hpp b/include/dusk/string.hpp new file mode 100644 index 0000000000..7de1b1ad75 --- /dev/null +++ b/include/dusk/string.hpp @@ -0,0 +1,58 @@ +#ifndef DUSK_STRING_HPP +#define DUSK_STRING_HPP + +#include "global.h" +#include +#include + +namespace dusk { + +inline void strncpyProxy(char* dst, const char* src, size_t count) { +#if _MSC_VER +#pragma warning(push) +#pragma warning(disable : 4996) +#endif + strncpy(dst, src, count); +#if _MSC_VER +#pragma warning(pop) +#endif +} + +/** + * Copy a string to a fixed-size array. + * Truncates if the destination is not large enough, always inserts a null terminator (padding the remainder of the buffer with zeroes.) + */ +template +void SafeStringCopyTruncate(char (&buffer)[BufSize], const char* src) { + static_assert(BufSize > 0, "Target buffer cannot be size zero"); + + if (buffer == src) { + CRASH("Cannot copy string to same buffer"); + } + + strncpyProxy(buffer, src, BufSize); + buffer[BufSize - 1] = 0; +} + +/** + * Copy a string to a fixed-size array. + * Aborts if the destination is not large enough, always inserts a null terminator (padding the remainder of the buffer with zeroes.) + */ +template +void SafeStringCopy(char (&buffer)[BufSize], const char* src) { + static_assert(BufSize > 0, "Target buffer cannot be size zero"); + if (buffer == src) { + CRASH("Cannot copy string to same buffer"); + } + + if (strlen(src) > BufSize - 1) { + CRASH("Destination buffer too small!"); + } + + strncpyProxy(buffer, src, BufSize); + buffer[BufSize - 1] = 0; +} + +} + +#endif // DUSK_STRING_HPP diff --git a/include/dusk/time.h b/include/dusk/time.h index 501875971b..94f819f76b 100644 --- a/include/dusk/time.h +++ b/include/dusk/time.h @@ -14,6 +14,7 @@ #endif #include #include +#include #endif #include "dusk/logging.h" @@ -92,7 +93,11 @@ private: } do { QueryPerformanceCounter(¤t); - _mm_pause(); // Yield CPU +#if defined(_M_ARM64) || defined(_M_ARM) + __yield(); +#else + _mm_pause(); +#endif } while (current.QuadPart - start.QuadPart < ticksToWait); } #else diff --git a/include/dusk_pch.hpp b/include/dusk_pch.hpp new file mode 100644 index 0000000000..adac2d33d2 --- /dev/null +++ b/include/dusk_pch.hpp @@ -0,0 +1,7 @@ +#pragma once + +#define PROCS_DUMP_NAMES 1 + +#include "d/dolzel.pch" +#include "d/dolzel_base.pch" +#include "d/dolzel_rel.pch" diff --git a/include/f_pc/f_pc_manager.h b/include/f_pc/f_pc_manager.h index f772949d85..d8d9cbe1c9 100644 --- a/include/f_pc/f_pc_manager.h +++ b/include/f_pc/f_pc_manager.h @@ -9,7 +9,11 @@ #include "f_pc/f_pc_stdcreate_req.h" #include "f_pc/f_pc_searcher.h" +#if TARGET_PC +enum : u32 { +#else enum { +#endif fpcM_UNK_PROCESS_ID_e = 0xFFFFFFFE, fpcM_ERROR_PROCESS_ID_e = 0xFFFFFFFF, }; diff --git a/include/global.h b/include/global.h index e6291778d4..ff2d18427d 100644 --- a/include/global.h +++ b/include/global.h @@ -83,7 +83,11 @@ extern int __abs(int); void* __memcpy(void*, const void*, int); #endif -#ifdef _MSVC_LANG +#ifndef M_PI +#define M_PI 3.14159265358979323846f +#endif + +#if defined(_MSVC_LANG) && !defined(__clang__) inline int __builtin_clz(unsigned int v) { int count = 32; while (v != 0) { @@ -94,7 +98,6 @@ inline int __builtin_clz(unsigned int v) { } #define COMPOUND_LITERAL(x) -#define M_PI 3.14159265358979323846f #else #define COMPOUND_LITERAL(x) (x) @@ -191,15 +194,12 @@ static const float INF = 2000000000.0f; #endif // potential fakematch? -#if DEBUG #define FABSF fabsf -#else -#define FABSF std::fabsf -#endif #ifndef __MWERKS__ #if __cplusplus #include +#include using std::isnan; #endif #endif @@ -215,4 +215,6 @@ using std::isnan; #define IS_REF_NONNULL(r) (1) #endif +#define CRASH(msg, ...) OSPanic(__FILE__, __LINE__, "%s", msg, ##__VA_ARGS__) + #endif diff --git a/include/m_Do/m_Do_controller_pad.h b/include/m_Do/m_Do_controller_pad.h index 6960a7da7d..e187efd17d 100644 --- a/include/m_Do/m_Do_controller_pad.h +++ b/include/m_Do/m_Do_controller_pad.h @@ -3,6 +3,7 @@ #include "JSystem/JUtility/JUTGamePad.h" #include "SSystem/SComponent/c_API_controller_pad.h" +#include "dusk/settings.h" // Controller Ports 1 - 4 enum { PAD_1, PAD_2, PAD_3, PAD_4 }; @@ -52,8 +53,31 @@ public: static f32 getStickX3D(u32 pad) { return getCpadInfo(pad).mMainStickPosX; } static f32 getStickValue(u32 pad) { return getCpadInfo(pad).mMainStickValue; } static s16 getStickAngle(u32 pad) { return getCpadInfo(pad).mMainStickAngle; } - static s16 getStickAngle3D(u32 pad) { return getCpadInfo(pad).mMainStickAngle; } - static f32 getSubStickX3D(u32 pad) { return getCpadInfo(pad).mCStickPosX; } + + static s16 getStickAngle3D(u32 pad) { + #if TARGET_PC + if (dusk::getSettings().game.enableMirrorMode) { + return -getCpadInfo(pad).mMainStickAngle; + } else { + return getCpadInfo(pad).mMainStickAngle; + } + #else + return getCpadInfo(pad).mMainStickAngle; + #endif + } + + static f32 getSubStickX3D(u32 pad) { + #if TARGET_PC + if (dusk::getSettings().game.enableMirrorMode) { + return -getCpadInfo(pad).mCStickPosX; + } else { + return getCpadInfo(pad).mCStickPosX; + } + #else + return getCpadInfo(pad).mCStickPosX; + #endif + } + static f32 getSubStickX(u32 pad) { return getCpadInfo(pad).mCStickPosX; } static f32 getSubStickY(u32 pad) { return getCpadInfo(pad).mCStickPosY; } static f32 getSubStickValue(u32 pad) { return getCpadInfo(pad).mCStickValue; } @@ -61,7 +85,7 @@ public: static f32 getAnalogR(u32 pad) { return getCpadInfo(pad).mTriggerRight; } static f32 getAnalogL(u32 pad) { return getCpadInfo(pad).mTriggerLeft; } static BOOL isConnect(u32 pad) { return JUTGamePad::getPortStatus((JUTGamePad::EPadPort)pad) == 0; } - static void startMotorWave(u32 pad, void* data, JUTGamePad::CRumble::ERumble rumble, u32 length) { + static void startMotorWave(u32 pad, u8* data, JUTGamePad::CRumble::ERumble rumble, u32 length) { m_gamePad[pad]->startMotorWave(data, rumble, length); } static void stopMotor(u32 pad) { m_gamePad[pad]->stopMotor(); } diff --git a/include/m_Do/m_Do_graphic.h b/include/m_Do/m_Do_graphic.h index c30c28a517..421e1ae47f 100644 --- a/include/m_Do/m_Do_graphic.h +++ b/include/m_Do/m_Do_graphic.h @@ -4,12 +4,11 @@ #include "JSystem/JFramework/JFWDisplay.h" #include "m_Do/m_Do_mtx.h" #include "global.h" -#include "dusk/logging.h" #if TARGET_PC #include #endif -#if WIDESCREEN_SUPPORT +#if WIDESCREEN_SUPPORT && !TARGET_PC #define FB_WIDTH (640) #define FB_HEIGHT (456) #else @@ -100,9 +99,7 @@ public: } static int startFadeOut(int param_0) { return JFWDisplay::getManager()->startFadeOut(param_0); } - static int startFadeIn(int param_0) { - DuskLog.debug("mDoGph_gInf_c::startFadeIn START"); - return JFWDisplay::getManager()->startFadeIn(param_0); } + static int startFadeIn(int param_0) { return JFWDisplay::getManager()->startFadeIn(param_0); } static void setFadeColor(JUtility::TColor& color) { mFader->setColor(color); } static void setClearColor(JUtility::TColor color) { JFWDisplay::getManager()->setClearColor(color); } static void setBackColor(GXColor& color) { mBackColor = color; } @@ -120,6 +117,13 @@ public: static void setTickRate(u32 rate) { JFWDisplay::getManager()->setTickRate(rate); } static void waitBlanking(int wait) { JFWDisplay::getManager()->waitBlanking(wait); } +#if TARGET_PC + static f32 hudAspectScaleDown; + static f32 hudAspectScaleUp; + static f32 ScaleHUDXLeft(f32 baseX) { return getMinXF() + baseX; } + static f32 ScaleHUDXRight(f32 baseX) { return -getMinXF() + baseX; } +#endif + static void setBlureMtx(const Mtx m) { cMtx_copy(m, mBlureMtx); } @@ -269,7 +273,12 @@ public: #if WIDESCREEN_SUPPORT static void setTvSize(); + #if TARGET_PC + static void onWide(f32 width, f32 height); + #else static void onWide(); + #endif + static void offWide(); static u8 isWide(); @@ -315,6 +324,12 @@ public: static JKRHeap* m_heap; #endif +#if PLATFORM_WII || PLATFORM_SHIELD || TARGET_PC + static ResTIMG* m_fullFrameBufferTimg; + static void* m_fullFrameBufferTex; + static TGXTexObj m_fullFrameBufferTexObj; +#endif + #if PLATFORM_WII || PLATFORM_SHIELD static void resetDimming(); @@ -329,9 +344,6 @@ public: #if WIDESCREEN_SUPPORT static u8 mWide; static u8 mWideZoom; - static ResTIMG* m_fullFrameBufferTimg; - static void* m_fullFrameBufferTex; - static TGXTexObj m_fullFrameBufferTexObj; static f32 m_aspect; static f32 m_scale; diff --git a/include/m_Do/m_Do_machine.h b/include/m_Do/m_Do_machine.h index 53c47c07a7..eeea7e77ce 100644 --- a/include/m_Do/m_Do_machine.h +++ b/include/m_Do/m_Do_machine.h @@ -15,6 +15,9 @@ void my_SysPrintHeap(char const*, void*, u32); void mDoMch_HeapCheckAll(); void mDoMch_HeapFreeFillAll(); int mDoMch_Create(); +#if TARGET_PC +void mDoMch_Destroy(); +#endif extern GXRenderModeObj g_ntscZeldaProg; diff --git a/include/os_report.h b/include/os_report.h index 1fcf08bc57..78177a199d 100644 --- a/include/os_report.h +++ b/include/os_report.h @@ -31,4 +31,10 @@ extern u8 __OSReport_Warning_disable; extern u8 __OSReport_System_disable; extern u8 __OSReport_enable; +#if TARGET_PC +namespace dusk { + extern bool OSReportReallyForceEnable; +} +#endif + #endif // _OS_REPORT_H diff --git a/ios.toolchain.cmake b/ios.toolchain.cmake new file mode 100644 index 0000000000..fb6052fc9b --- /dev/null +++ b/ios.toolchain.cmake @@ -0,0 +1,1177 @@ +# This file is part of the ios-cmake project. It was retrieved from +# https://github.com/leetal/ios-cmake.git, which is a fork of +# https://github.com/gerstrong/ios-cmake.git, which is a fork of +# https://github.com/cristeab/ios-cmake.git, which is a fork of +# https://code.google.com/p/ios-cmake/. Which in turn is based off of +# the Platform/Darwin.cmake and Platform/UnixPaths.cmake files which +# are included with CMake 2.8.4 +# +# The ios-cmake project is licensed under the new BSD license. +# +# Copyright (c) 2014, Bogdan Cristea and LTE Engineering Software, +# Kitware, Inc., Insight Software Consortium. All rights reserved. +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions +# are met: +# 1. Redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer. +# +# 2. Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in the +# documentation and/or other materials provided with the distribution. +# +# 3. Neither the name of the copyright holder nor the names of its +# contributors may be used to endorse or promote products derived from +# this software without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS +# FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE +# COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, +# INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, +# BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +# LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +# CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN +# ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +# POSSIBILITY OF SUCH DAMAGE. +# +# This file is based on the Platform/Darwin.cmake and +# Platform/UnixPaths.cmake files which are included with CMake 2.8.4 +# It has been altered for iOS development. +# +# Updated by Alex Stewart (alexs.mac@gmail.com) +# +# ***************************************************************************** +# Now maintained by Alexander Widerberg (widerbergaren [at] gmail.com) +# under the BSD-3-Clause license +# https://github.com/leetal/ios-cmake +# ***************************************************************************** +# +# INFORMATION / HELP +# +############################################################################### +# OPTIONS # +############################################################################### +# +# PLATFORM: (default "OS64") +# OS = Build for iPhoneOS. +# OS64 = Build for arm64 iphoneOS. +# OS64COMBINED = Build for arm64 x86_64 iphoneOS + iphoneOS Simulator. Combined into FAT STATIC lib (only supported on 3.14+ of CMake with "-G Xcode" argument in combination with the "cmake --install" CMake build step) +# SIMULATOR = Build for x86 i386 iphoneOS Simulator. +# SIMULATOR64 = Build for x86_64 iphoneOS Simulator. +# SIMULATORARM64 = Build for arm64 iphoneOS Simulator. +# SIMULATOR64COMBINED = Build for arm64 x86_64 iphoneOS Simulator. Combined into FAT STATIC lib (supported on 3.14+ of CMakewith "-G Xcode" argument ONLY) +# TVOS = Build for arm64 tvOS. +# TVOSCOMBINED = Build for arm64 x86_64 tvOS + tvOS Simulator. Combined into FAT STATIC lib (only supported on 3.14+ of CMake with "-G Xcode" argument in combination with the "cmake --install" CMake build step) +# SIMULATOR_TVOS = Build for x86_64 tvOS Simulator. +# SIMULATORARM64_TVOS = Build for arm64 tvOS Simulator. +# VISIONOSCOMBINED = Build for arm64 visionOS + visionOS Simulator. Combined into FAT STATIC lib (only supported on 3.14+ of CMake with "-G Xcode" argument in combination with the "cmake --install" CMake build step) +# VISIONOS = Build for arm64 visionOS. +# SIMULATOR_VISIONOS = Build for arm64 visionOS Simulator. +# WATCHOS = Build for armv7k arm64_32 for watchOS. +# WATCHOSCOMBINED = Build for armv7k arm64_32 x86_64 watchOS + watchOS Simulator. Combined into FAT STATIC lib (only supported on 3.14+ of CMake with "-G Xcode" argument in combination with the "cmake --install" CMake build step) +# SIMULATOR_WATCHOS = Build for x86_64 for watchOS Simulator. +# SIMULATORARM64_WATCHOS = Build for arm64 for watchOS Simulator. +# SIMULATOR_WATCHOSCOMBINED = Build for arm64 x86_64 for watchOS Simulator. Combined into FAT STATIC lib (supported on 3.14+ of CMakewith "-G Xcode" argument ONLY) +# MAC = Build for x86_64 macOS. +# MAC_ARM64 = Build for Apple Silicon macOS. +# MAC_UNIVERSAL = Combined build for x86_64 and Apple Silicon on macOS. +# MAC_CATALYST = Build for x86_64 macOS with Catalyst support (iOS toolchain on macOS). +# Note: The build argument "MACOSX_DEPLOYMENT_TARGET" can be used to control min-version of macOS +# MAC_CATALYST_ARM64 = Build for Apple Silicon macOS with Catalyst support (iOS toolchain on macOS). +# Note: The build argument "MACOSX_DEPLOYMENT_TARGET" can be used to control min-version of macOS +# MAC_CATALYST_UNIVERSAL = Combined build for x86_64 and Apple Silicon on Catalyst. +# +# CMAKE_OSX_SYSROOT: Path to the SDK to use. By default this is +# automatically determined from PLATFORM and xcodebuild, but +# can also be manually specified (although this should not be required). +# +# CMAKE_DEVELOPER_ROOT: Path to the Developer directory for the platform +# being compiled for. By default, this is automatically determined from +# CMAKE_OSX_SYSROOT, but can also be manually specified (although this should +# not be required). +# +# DEPLOYMENT_TARGET: Minimum SDK version to target. Default 6.0 on watchOS, 13.0 on tvOS+iOS/iPadOS, 11.0 on macOS, 1.0 on visionOS +# +# NAMED_LANGUAGE_SUPPORT: +# ON (default) = Will require "enable_language(OBJC) and/or enable_language(OBJCXX)" for full OBJC|OBJCXX support +# OFF = Will embed the OBJC and OBJCXX flags into the CMAKE_C_FLAGS and CMAKE_CXX_FLAGS (legacy behavior, CMake version < 3.16) +# +# ENABLE_BITCODE: (ON|OFF) Enables or disables bitcode support. Default OFF +# +# ENABLE_ARC: (ON|OFF) Enables or disables ARC support. Default ON (ARC enabled by default) +# +# ENABLE_VISIBILITY: (ON|OFF) Enables or disables symbol visibility support. Default OFF (visibility hidden by default) +# +# ENABLE_STRICT_TRY_COMPILE: (ON|OFF) Enables or disables strict try_compile() on all Check* directives (will run linker +# to actually check if linking is possible). Default OFF (will set CMAKE_TRY_COMPILE_TARGET_TYPE to STATIC_LIBRARY) +# +# ARCHS: (armv7 armv7s armv7k arm64 arm64_32 i386 x86_64) If specified, will override the default architectures for the given PLATFORM +# OS = armv7 armv7s arm64 (if applicable) +# OS64 = arm64 (if applicable) +# SIMULATOR = i386 +# SIMULATOR64 = x86_64 +# SIMULATORARM64 = arm64 +# TVOS = arm64 +# SIMULATOR_TVOS = x86_64 (i386 has since long been deprecated) +# SIMULATORARM64_TVOS = arm64 +# WATCHOS = armv7k arm64_32 (if applicable) +# SIMULATOR_WATCHOS = x86_64 (i386 has since long been deprecated) +# SIMULATORARM64_WATCHOS = arm64 +# MAC = x86_64 +# MAC_ARM64 = arm64 +# MAC_UNIVERSAL = x86_64 arm64 +# MAC_CATALYST = x86_64 +# MAC_CATALYST_ARM64 = arm64 +# MAC_CATALYST_UNIVERSAL = x86_64 arm64 +# +# NOTE: When manually specifying ARCHS, put a semi-colon between the entries. E.g., -DARCHS="armv7;arm64" +# +############################################################################### +# END OPTIONS # +############################################################################### +# +# This toolchain defines the following properties (available via get_property()) for use externally: +# +# PLATFORM: The currently targeted platform. +# XCODE_VERSION: Version number (not including Build version) of Xcode detected. +# SDK_VERSION: Version of SDK being used. +# OSX_ARCHITECTURES: Architectures being compiled for (generated from PLATFORM). +# APPLE_TARGET_TRIPLE: Used by autoconf build systems. NOTE: If "ARCHS" is overridden, this will *NOT* be set! +# +# This toolchain defines the following macros for use externally: +# +# set_xcode_property (TARGET XCODE_PROPERTY XCODE_VALUE XCODE_VARIANT) +# A convenience macro for setting xcode specific properties on targets. +# Available variants are: All, Release, RelWithDebInfo, Debug, MinSizeRel +# example: set_xcode_property (myioslib IPHONEOS_DEPLOYMENT_TARGET "3.1" "all"). +# +# find_host_package (PROGRAM ARGS) +# A macro used to find executable programs on the host system, not within the +# environment. Thanks to the android-cmake project for providing the +# command. +# + +cmake_minimum_required(VERSION 3.8..3.30) + +# CMake invokes the toolchain file twice during the first build, but only once during subsequent rebuilds. +# NOTE: To improve single-library build-times, provide the flag "OS_SINGLE_BUILD" as a build argument. +if(DEFINED OS_SINGLE_BUILD AND DEFINED ENV{_IOS_TOOLCHAIN_HAS_RUN}) + return() +endif() +set(ENV{_IOS_TOOLCHAIN_HAS_RUN} true) + +# List of supported platform values +list(APPEND _supported_platforms + "OS" "OS64" "OS64COMBINED" "SIMULATOR" "SIMULATOR64" "SIMULATORARM64" "SIMULATOR64COMBINED" + "TVOS" "TVOSCOMBINED" "SIMULATOR_TVOS" "SIMULATORARM64_TVOS" + "WATCHOS" "WATCHOSCOMBINED" "SIMULATOR_WATCHOS" "SIMULATORARM64_WATCHOS" "SIMULATOR_WATCHOSCOMBINED" + "MAC" "MAC_ARM64" "MAC_UNIVERSAL" + "VISIONOS" "SIMULATOR_VISIONOS" "VISIONOSCOMBINED" + "MAC_CATALYST" "MAC_CATALYST_ARM64" "MAC_CATALYST_UNIVERSAL") + +# Cache what generator is used +set(USED_CMAKE_GENERATOR "${CMAKE_GENERATOR}") + +# Check if using a CMake version capable of building combined FAT builds (simulator and target slices combined in one static lib) +if(${CMAKE_VERSION} VERSION_GREATER_EQUAL "3.14") + set(MODERN_CMAKE YES) +endif() + +# Get the Xcode version being used. +# Problem: CMake runs toolchain files multiple times, but can't read cache variables on some runs. +# Workaround: On the first run (in which cache variables are always accessible), set an intermediary environment variable. +# +# NOTE: This pattern is used in many places in this toolchain to speed up checks of all sorts +if(DEFINED XCODE_VERSION_INT) + # Environment variables are always preserved. + set(ENV{_XCODE_VERSION_INT} "${XCODE_VERSION_INT}") +elseif(DEFINED ENV{_XCODE_VERSION_INT}) + set(XCODE_VERSION_INT "$ENV{_XCODE_VERSION_INT}") +elseif(NOT DEFINED XCODE_VERSION_INT) + find_program(XCODEBUILD_EXECUTABLE xcodebuild) + if(NOT XCODEBUILD_EXECUTABLE) + message(FATAL_ERROR "xcodebuild not found. Please install either the standalone commandline tools or Xcode.") + endif() + execute_process(COMMAND ${XCODEBUILD_EXECUTABLE} -version + OUTPUT_VARIABLE XCODE_VERSION_INT + ERROR_QUIET + OUTPUT_STRIP_TRAILING_WHITESPACE) + string(REGEX MATCH "Xcode [0-9\\.]+" XCODE_VERSION_INT "${XCODE_VERSION_INT}") + string(REGEX REPLACE "Xcode ([0-9\\.]+)" "\\1" XCODE_VERSION_INT "${XCODE_VERSION_INT}") + set(XCODE_VERSION_INT "${XCODE_VERSION_INT}" CACHE INTERNAL "") +endif() + +# Assuming that xcode 12.0 is installed you most probably have ios sdk 14.0 or later installed (tested on Big Sur) +# if you don't set a deployment target it will be set the way you only get 64-bit builds +#if(NOT DEFINED DEPLOYMENT_TARGET AND XCODE_VERSION_INT VERSION_GREATER 12.0) +# Temporarily fix the arm64 issues in CMake install-combined by excluding arm64 for simulator builds (needed for Apple Silicon...) +# set(CMAKE_XCODE_ATTRIBUTE_EXCLUDED_ARCHS[sdk=iphonesimulator*] "arm64") +#endif() + +# Check if the platform variable is set +if(DEFINED PLATFORM) + # Environment variables are always preserved. + set(ENV{_PLATFORM} "${PLATFORM}") +elseif(DEFINED ENV{_PLATFORM}) + set(PLATFORM "$ENV{_PLATFORM}") +elseif(NOT DEFINED PLATFORM) + message(FATAL_ERROR "PLATFORM argument not set. Bailing configure since I don't know what target you want to build for!") +endif () + +if(PLATFORM MATCHES ".*COMBINED" AND NOT CMAKE_GENERATOR MATCHES "Xcode") + message(FATAL_ERROR "The combined builds support requires Xcode to be used as a generator via '-G Xcode' command-line argument in CMake") +endif() + +# Safeguard that the platform value is set and is one of the supported values +list(FIND _supported_platforms ${PLATFORM} contains_PLATFORM) +if("${contains_PLATFORM}" EQUAL "-1") + string(REPLACE ";" "\n * " _supported_platforms_formatted "${_supported_platforms}") + message(FATAL_ERROR " Invalid PLATFORM specified! Current value: ${PLATFORM}.\n" + " Supported PLATFORM values: \n * ${_supported_platforms_formatted}") +endif() + +# Check if Apple Silicon is supported +if(PLATFORM MATCHES "^(MAC_ARM64)$|^(MAC_CATALYST_ARM64)$|^(MAC_UNIVERSAL)$|^(MAC_CATALYST_UNIVERSAL)$" AND ${CMAKE_VERSION} VERSION_LESS "3.19.5") + message(FATAL_ERROR "Apple Silicon builds requires a minimum of CMake 3.19.5") +endif() + +# Touch the toolchain variable to suppress the "unused variable" warning. +# This happens if CMake is invoked with the same command line the second time. +if(CMAKE_TOOLCHAIN_FILE) +endif() + +# Fix for PThread library not in path +set(CMAKE_THREAD_LIBS_INIT "-lpthread") +set(CMAKE_HAVE_THREADS_LIBRARY 1) +set(CMAKE_USE_WIN32_THREADS_INIT 0) +set(CMAKE_USE_PTHREADS_INIT 1) + +# Specify named language support defaults. +if(NOT DEFINED NAMED_LANGUAGE_SUPPORT AND ${CMAKE_VERSION} VERSION_GREATER_EQUAL "3.16") + set(NAMED_LANGUAGE_SUPPORT ON) + message(STATUS "[DEFAULTS] Using explicit named language support! E.g., enable_language(CXX) is needed in the project files.") +elseif(NOT DEFINED NAMED_LANGUAGE_SUPPORT AND ${CMAKE_VERSION} VERSION_LESS "3.16") + set(NAMED_LANGUAGE_SUPPORT OFF) + message(STATUS "[DEFAULTS] Disabling explicit named language support. Falling back to legacy behavior.") +elseif(DEFINED NAMED_LANGUAGE_SUPPORT AND ${CMAKE_VERSION} VERSION_LESS "3.16") + message(FATAL_ERROR "CMake named language support for OBJC and OBJCXX was added in CMake 3.16.") +endif() +set(NAMED_LANGUAGE_SUPPORT_INT ${NAMED_LANGUAGE_SUPPORT} CACHE BOOL + "Whether or not to enable explicit named language support" FORCE) + +# Specify the minimum version of the deployment target. +if(NOT DEFINED DEPLOYMENT_TARGET) + if (PLATFORM MATCHES "WATCHOS") + # Unless specified, SDK version 6.0 is used by default as minimum target version (watchOS). + set(DEPLOYMENT_TARGET "6.0") + elseif(PLATFORM STREQUAL "MAC") + # Unless specified, SDK version 11.0 (Big Sur) is used by default as the minimum target version (macOS on x86). + set(DEPLOYMENT_TARGET "11.0") + elseif(PLATFORM STREQUAL "VISIONOS" OR PLATFORM STREQUAL "SIMULATOR_VISIONOS" OR PLATFORM STREQUAL "VISIONOSCOMBINED") + # Unless specified, SDK version 1.0 is used by default as minimum target version (visionOS). + set(DEPLOYMENT_TARGET "1.0") + elseif(PLATFORM STREQUAL "MAC_ARM64") + # Unless specified, SDK version 11.0 (Big Sur) is used by default as the minimum target version (macOS on arm). + set(DEPLOYMENT_TARGET "11.0") + elseif(PLATFORM STREQUAL "MAC_UNIVERSAL") + # Unless specified, SDK version 11.0 (Big Sur) is used by default as minimum target version for universal builds. + set(DEPLOYMENT_TARGET "11.0") + elseif(PLATFORM STREQUAL "MAC_CATALYST" OR PLATFORM STREQUAL "MAC_CATALYST_ARM64" OR PLATFORM STREQUAL "MAC_CATALYST_UNIVERSAL") + # Unless specified, SDK version 13.1 is used by default as the minimum target version (mac catalyst minimum requirement). + set(DEPLOYMENT_TARGET "13.1") + else() + # Unless specified, SDK version 13.0 is used by default as the minimum target version (iOS, tvOS). + set(DEPLOYMENT_TARGET "13.0") + endif() + message(STATUS "[DEFAULTS] Using the default min-version since DEPLOYMENT_TARGET not provided!") +elseif(DEFINED DEPLOYMENT_TARGET AND PLATFORM MATCHES "^MAC_CATALYST" AND ${DEPLOYMENT_TARGET} VERSION_LESS "13.1") + message(FATAL_ERROR "Mac Catalyst builds requires a minimum deployment target of 13.1!") +endif() + +# Store the DEPLOYMENT_TARGET in the cache +set(DEPLOYMENT_TARGET "${DEPLOYMENT_TARGET}" CACHE INTERNAL "") + +# Handle the case where we are targeting iOS and a version above 10.3.4 (32-bit support dropped officially) +if(PLATFORM STREQUAL "OS" AND DEPLOYMENT_TARGET VERSION_GREATER_EQUAL 10.3.4) + set(PLATFORM "OS64") + message(STATUS "Targeting minimum SDK version ${DEPLOYMENT_TARGET}. Dropping 32-bit support.") +elseif(PLATFORM STREQUAL "SIMULATOR" AND DEPLOYMENT_TARGET VERSION_GREATER_EQUAL 10.3.4) + set(PLATFORM "SIMULATOR64") + message(STATUS "Targeting minimum SDK version ${DEPLOYMENT_TARGET}. Dropping 32-bit support.") +endif() + +set(PLATFORM_INT "${PLATFORM}") + +if(DEFINED ARCHS) + string(REPLACE ";" "-" ARCHS_SPLIT "${ARCHS}") +endif() + +# Determine the platform name and architectures for use in xcodebuild commands +# from the specified PLATFORM_INT name. +if(PLATFORM_INT STREQUAL "OS") + set(SDK_NAME iphoneos) + if(NOT ARCHS) + set(ARCHS armv7 armv7s arm64) + set(APPLE_TARGET_TRIPLE_INT arm-apple-ios${DEPLOYMENT_TARGET}) + else() + set(APPLE_TARGET_TRIPLE_INT ${ARCHS_SPLIT}-apple-ios${DEPLOYMENT_TARGET}) + endif() +elseif(PLATFORM_INT STREQUAL "OS64") + set(SDK_NAME iphoneos) + if(NOT ARCHS) + if (XCODE_VERSION_INT VERSION_GREATER 10.0) + set(ARCHS arm64) # FIXME: Add arm64e when Apple has fixed the integration issues with it, libarclite_iphoneos.a is currently missing bitcode markers for example + else() + set(ARCHS arm64) + endif() + set(APPLE_TARGET_TRIPLE_INT arm64-apple-ios${DEPLOYMENT_TARGET}) + else() + set(APPLE_TARGET_TRIPLE_INT ${ARCHS_SPLIT}-apple-ios${DEPLOYMENT_TARGET}) + endif() +elseif(PLATFORM_INT STREQUAL "OS64COMBINED") + set(SDK_NAME iphoneos) + if(MODERN_CMAKE) + if(NOT ARCHS) + if (XCODE_VERSION_INT VERSION_GREATER 12.0) + set(ARCHS arm64 x86_64) + set(CMAKE_XCODE_ATTRIBUTE_ARCHS[sdk=iphoneos*] "arm64") + set(CMAKE_XCODE_ATTRIBUTE_ARCHS[sdk=iphonesimulator*] "x86_64 arm64") + set(CMAKE_XCODE_ATTRIBUTE_VALID_ARCHS[sdk=iphoneos*] "arm64") + set(CMAKE_XCODE_ATTRIBUTE_VALID_ARCHS[sdk=iphonesimulator*] "x86_64 arm64") + else() + set(ARCHS arm64 x86_64) + set(CMAKE_XCODE_ATTRIBUTE_ARCHS[sdk=iphoneos*] "arm64") + set(CMAKE_XCODE_ATTRIBUTE_ARCHS[sdk=iphonesimulator*] "x86_64") + set(CMAKE_XCODE_ATTRIBUTE_VALID_ARCHS[sdk=iphoneos*] "arm64") + set(CMAKE_XCODE_ATTRIBUTE_VALID_ARCHS[sdk=iphonesimulator*] "x86_64") + endif() + set(APPLE_TARGET_TRIPLE_INT arm64-x86_64-apple-ios${DEPLOYMENT_TARGET}) + else() + set(APPLE_TARGET_TRIPLE_INT ${ARCHS_SPLIT}-apple-ios${DEPLOYMENT_TARGET}) + endif() + else() + message(FATAL_ERROR "Please make sure that you are running CMake 3.14+ to make the OS64COMBINED setting work") + endif() +elseif(PLATFORM_INT STREQUAL "SIMULATOR64COMBINED") + set(SDK_NAME iphonesimulator) + if(MODERN_CMAKE) + if(NOT ARCHS) + if (XCODE_VERSION_INT VERSION_GREATER 12.0) + set(ARCHS arm64 x86_64) # FIXME: Add arm64e when Apple have fixed the integration issues with it, libarclite_iphoneos.a is currently missing bitcode markers for example + set(CMAKE_XCODE_ATTRIBUTE_ARCHS[sdk=iphoneos*] "") + set(CMAKE_XCODE_ATTRIBUTE_ARCHS[sdk=iphonesimulator*] "x86_64 arm64") + set(CMAKE_XCODE_ATTRIBUTE_VALID_ARCHS[sdk=iphoneos*] "") + set(CMAKE_XCODE_ATTRIBUTE_VALID_ARCHS[sdk=iphonesimulator*] "x86_64 arm64") + else() + set(ARCHS arm64 x86_64) + set(CMAKE_XCODE_ATTRIBUTE_ARCHS[sdk=iphoneos*] "") + set(CMAKE_XCODE_ATTRIBUTE_ARCHS[sdk=iphonesimulator*] "x86_64") + set(CMAKE_XCODE_ATTRIBUTE_VALID_ARCHS[sdk=iphoneos*] "") + set(CMAKE_XCODE_ATTRIBUTE_VALID_ARCHS[sdk=iphonesimulator*] "x86_64") + endif() + set(APPLE_TARGET_TRIPLE_INT aarch64-x86_64-apple-ios${DEPLOYMENT_TARGET}-simulator) + else() + set(APPLE_TARGET_TRIPLE_INT ${ARCHS_SPLIT}-apple-ios${DEPLOYMENT_TARGET}-simulator) + endif() + else() + message(FATAL_ERROR "Please make sure that you are running CMake 3.14+ to make the SIMULATOR64COMBINED setting work") + endif() +elseif(PLATFORM_INT STREQUAL "SIMULATOR") + set(SDK_NAME iphonesimulator) + if(NOT ARCHS) + set(ARCHS i386) + set(APPLE_TARGET_TRIPLE_INT i386-apple-ios${DEPLOYMENT_TARGET}-simulator) + else() + set(APPLE_TARGET_TRIPLE_INT ${ARCHS_SPLIT}-apple-ios${DEPLOYMENT_TARGET}-simulator) + endif() + message(DEPRECATION "SIMULATOR IS DEPRECATED. Consider using SIMULATOR64 instead.") +elseif(PLATFORM_INT STREQUAL "SIMULATOR64") + set(SDK_NAME iphonesimulator) + if(NOT ARCHS) + set(ARCHS x86_64) + set(APPLE_TARGET_TRIPLE_INT x86_64-apple-ios${DEPLOYMENT_TARGET}-simulator) + else() + set(APPLE_TARGET_TRIPLE_INT ${ARCHS_SPLIT}-apple-ios${DEPLOYMENT_TARGET}-simulator) + endif() +elseif(PLATFORM_INT STREQUAL "SIMULATORARM64") + set(SDK_NAME iphonesimulator) + if(NOT ARCHS) + set(ARCHS arm64) + set(APPLE_TARGET_TRIPLE_INT arm64-apple-ios${DEPLOYMENT_TARGET}-simulator) + else() + set(APPLE_TARGET_TRIPLE_INT ${ARCHS_SPLIT}-apple-ios${DEPLOYMENT_TARGET}-simulator) + endif() +elseif(PLATFORM_INT STREQUAL "TVOS") + set(SDK_NAME appletvos) + if(NOT ARCHS) + set(ARCHS arm64) + set(APPLE_TARGET_TRIPLE_INT arm64-apple-tvos${DEPLOYMENT_TARGET}) + else() + set(APPLE_TARGET_TRIPLE_INT ${ARCHS_SPLIT}-apple-tvos${DEPLOYMENT_TARGET}) + endif() +elseif (PLATFORM_INT STREQUAL "TVOSCOMBINED") + set(SDK_NAME appletvos) + if(MODERN_CMAKE) + if(NOT ARCHS) + set(ARCHS arm64 x86_64) + set(APPLE_TARGET_TRIPLE_INT arm64-x86_64-apple-tvos${DEPLOYMENT_TARGET}) + set(CMAKE_XCODE_ATTRIBUTE_ARCHS[sdk=appletvos*] "arm64") + set(CMAKE_XCODE_ATTRIBUTE_ARCHS[sdk=appletvsimulator*] "x86_64 arm64") + set(CMAKE_XCODE_ATTRIBUTE_VALID_ARCHS[sdk=appletvos*] "arm64") + set(CMAKE_XCODE_ATTRIBUTE_VALID_ARCHS[sdk=appletvsimulator*] "x86_64 arm64") + else() + set(APPLE_TARGET_TRIPLE_INT ${ARCHS_SPLIT}-apple-tvos${DEPLOYMENT_TARGET}) + endif() + else() + message(FATAL_ERROR "Please make sure that you are running CMake 3.14+ to make the TVOSCOMBINED setting work") + endif() +elseif(PLATFORM_INT STREQUAL "SIMULATOR_TVOS") + set(SDK_NAME appletvsimulator) + if(NOT ARCHS) + set(ARCHS x86_64) + set(APPLE_TARGET_TRIPLE_INT x86_64-apple-tvos${DEPLOYMENT_TARGET}-simulator) + else() + set(APPLE_TARGET_TRIPLE_INT ${ARCHS_SPLIT}-apple-tvos${DEPLOYMENT_TARGET}-simulator) + endif() +elseif(PLATFORM_INT STREQUAL "SIMULATORARM64_TVOS") + set(SDK_NAME appletvsimulator) + if(NOT ARCHS) + set(ARCHS arm64) + set(APPLE_TARGET_TRIPLE_INT arm64-apple-tvos${DEPLOYMENT_TARGET}-simulator) + else() + set(APPLE_TARGET_TRIPLE_INT ${ARCHS_SPLIT}-apple-tvos${DEPLOYMENT_TARGET}-simulator) + endif() +elseif(PLATFORM_INT STREQUAL "WATCHOS") + set(SDK_NAME watchos) + if(NOT ARCHS) + if (XCODE_VERSION_INT VERSION_GREATER 10.0) + set(ARCHS armv7k arm64_32) + set(APPLE_TARGET_TRIPLE_INT arm64_32-apple-watchos${DEPLOYMENT_TARGET}) + else() + set(ARCHS armv7k) + set(APPLE_TARGET_TRIPLE_INT arm-apple-watchos${DEPLOYMENT_TARGET}) + endif() + else() + set(APPLE_TARGET_TRIPLE_INT ${ARCHS_SPLIT}-apple-watchos${DEPLOYMENT_TARGET}) + endif() +elseif(PLATFORM_INT STREQUAL "WATCHOSCOMBINED") + set(SDK_NAME watchos) + if(MODERN_CMAKE) + if(NOT ARCHS) + if (XCODE_VERSION_INT VERSION_GREATER 10.0) + set(ARCHS armv7k arm64_32 x86_64) + set(APPLE_TARGET_TRIPLE_INT arm64_32-x86_64-apple-watchos${DEPLOYMENT_TARGET}) + set(CMAKE_XCODE_ATTRIBUTE_ARCHS[sdk=watchos*] "armv7k arm64_32") + set(CMAKE_XCODE_ATTRIBUTE_ARCHS[sdk=watchsimulator*] "x86_64") + set(CMAKE_XCODE_ATTRIBUTE_VALID_ARCHS[sdk=watchos*] "armv7k arm64_32") + set(CMAKE_XCODE_ATTRIBUTE_VALID_ARCHS[sdk=watchsimulator*] "x86_64") + else() + set(ARCHS armv7k i386) + set(APPLE_TARGET_TRIPLE_INT arm-i386-apple-watchos${DEPLOYMENT_TARGET}) + set(CMAKE_XCODE_ATTRIBUTE_ARCHS[sdk=watchos*] "armv7k") + set(CMAKE_XCODE_ATTRIBUTE_ARCHS[sdk=watchsimulator*] "i386") + set(CMAKE_XCODE_ATTRIBUTE_VALID_ARCHS[sdk=watchos*] "armv7k") + set(CMAKE_XCODE_ATTRIBUTE_VALID_ARCHS[sdk=watchsimulator*] "i386") + endif() + else() + set(APPLE_TARGET_TRIPLE_INT ${ARCHS_SPLIT}-apple-watchos${DEPLOYMENT_TARGET}) + endif() + else() + message(FATAL_ERROR "Please make sure that you are running CMake 3.14+ to make the WATCHOSCOMBINED setting work") + endif() +elseif(PLATFORM_INT STREQUAL "SIMULATOR_WATCHOS") + set(SDK_NAME watchsimulator) + if(NOT ARCHS) + if (XCODE_VERSION_INT VERSION_GREATER 10.0) + set(ARCHS x86_64) + set(APPLE_TARGET_TRIPLE_INT x86_64-apple-watchos${DEPLOYMENT_TARGET}-simulator) + else() + set(ARCHS i386) + set(APPLE_TARGET_TRIPLE_INT i386-apple-watchos${DEPLOYMENT_TARGET}-simulator) + endif() + else() + set(APPLE_TARGET_TRIPLE_INT ${ARCHS_SPLIT}-apple-watchos${DEPLOYMENT_TARGET}-simulator) + endif() +elseif(PLATFORM_INT STREQUAL "SIMULATORARM64_WATCHOS") + set(SDK_NAME watchsimulator) + if(NOT ARCHS) + set(ARCHS arm64) + set(APPLE_TARGET_TRIPLE_INT arm64-apple-watchos${DEPLOYMENT_TARGET}-simulator) + else() + set(APPLE_TARGET_TRIPLE_INT ${ARCHS_SPLIT}-apple-watchos${DEPLOYMENT_TARGET}-simulator) + endif() +elseif(PLATFORM_INT STREQUAL "SIMULATOR_WATCHOSCOMBINED") + set(SDK_NAME watchsimulator) + if(MODERN_CMAKE) + if(NOT ARCHS) + if (XCODE_VERSION_INT VERSION_GREATER 12.0) + set(ARCHS arm64 x86_64) + set(CMAKE_XCODE_ATTRIBUTE_ARCHS[sdk=watchos*] "") + set(CMAKE_XCODE_ATTRIBUTE_ARCHS[sdk=watchsimulator*] "arm64 x86_64") + set(CMAKE_XCODE_ATTRIBUTE_VALID_ARCHS[sdk=watchos*] "") + set(CMAKE_XCODE_ATTRIBUTE_VALID_ARCHS[sdk=watchsimulator*] "arm64 x86_64") + set(APPLE_TARGET_TRIPLE_INT arm64_x86_64-apple-watchos${DEPLOYMENT_TARGET}-simulator) + else() + set(ARCHS arm64 i386) + set(CMAKE_XCODE_ATTRIBUTE_ARCHS[sdk=watchos*] "") + set(CMAKE_XCODE_ATTRIBUTE_ARCHS[sdk=watchsimulator*] "i386") + set(CMAKE_XCODE_ATTRIBUTE_VALID_ARCHS[sdk=watchos*] "") + set(CMAKE_XCODE_ATTRIBUTE_VALID_ARCHS[sdk=watchsimulator*] "i386") + set(APPLE_TARGET_TRIPLE_INT arm64_i386-apple-watchos${DEPLOYMENT_TARGET}-simulator) + endif() + else() + set(APPLE_TARGET_TRIPLE_INT ${ARCHS_SPLIT}-apple-watchos${DEPLOYMENT_TARGET}-simulator) + endif() + else() + message(FATAL_ERROR "Please make sure that you are running CMake 3.14+ to make the SIMULATOR_WATCHOSCOMBINED setting work") + endif() +elseif(PLATFORM_INT STREQUAL "SIMULATOR_VISIONOS") + set(SDK_NAME xrsimulator) + if(NOT ARCHS) + set(ARCHS arm64) + set(APPLE_TARGET_TRIPLE_INT arm64-apple-xros${DEPLOYMENT_TARGET}-simulator) + else() + set(APPLE_TARGET_TRIPLE_INT ${ARCHS_SPLIT}-apple-xros${DEPLOYMENT_TARGET}-simulator) + endif() +elseif(PLATFORM_INT STREQUAL "VISIONOS") + set(SDK_NAME xros) + if(NOT ARCHS) + set(ARCHS arm64) + set(APPLE_TARGET_TRIPLE_INT arm64-apple-xros${DEPLOYMENT_TARGET}) + else() + set(APPLE_TARGET_TRIPLE_INT ${ARCHS_SPLIT}-apple-xros${DEPLOYMENT_TARGET}) + endif() +elseif(PLATFORM_INT STREQUAL "VISIONOSCOMBINED") + set(SDK_NAME xros) + if(MODERN_CMAKE) + if(NOT ARCHS) + set(ARCHS arm64) + set(APPLE_TARGET_TRIPLE_INT arm64-apple-xros${DEPLOYMENT_TARGET}) + set(CMAKE_XCODE_ATTRIBUTE_ARCHS[sdk=xros*] "arm64") + set(CMAKE_XCODE_ATTRIBUTE_ARCHS[sdk=xrsimulator*] "arm64") + else() + set(APPLE_TARGET_TRIPLE_INT ${ARCHS_SPLIT}-apple-xros${DEPLOYMENT_TARGET}) + endif() + else() + message(FATAL_ERROR "Please make sure that you are running CMake 3.14+ to make the VISIONOSCOMBINED setting work") + endif() +elseif(PLATFORM_INT STREQUAL "MAC" OR PLATFORM_INT STREQUAL "MAC_CATALYST") + set(SDK_NAME macosx) + if(NOT ARCHS) + set(ARCHS x86_64) + endif() + string(REPLACE ";" "-" ARCHS_SPLIT "${ARCHS}") + if(PLATFORM_INT STREQUAL "MAC") + set(APPLE_TARGET_TRIPLE_INT ${ARCHS_SPLIT}-apple-macosx${DEPLOYMENT_TARGET}) + elseif(PLATFORM_INT STREQUAL "MAC_CATALYST") + set(APPLE_TARGET_TRIPLE_INT ${ARCHS_SPLIT}-apple-ios${DEPLOYMENT_TARGET}-macabi) + endif() +elseif(PLATFORM_INT MATCHES "^(MAC_ARM64)$|^(MAC_CATALYST_ARM64)$") + set(SDK_NAME macosx) + if(NOT ARCHS) + set(ARCHS arm64) + endif() + string(REPLACE ";" "-" ARCHS_SPLIT "${ARCHS}") + if(PLATFORM_INT STREQUAL "MAC_ARM64") + set(APPLE_TARGET_TRIPLE_INT ${ARCHS_SPLIT}-apple-macosx${DEPLOYMENT_TARGET}) + elseif(PLATFORM_INT STREQUAL "MAC_CATALYST_ARM64") + set(APPLE_TARGET_TRIPLE_INT ${ARCHS_SPLIT}-apple-ios${DEPLOYMENT_TARGET}-macabi) + endif() +elseif(PLATFORM_INT STREQUAL "MAC_UNIVERSAL") + set(SDK_NAME macosx) + if(NOT ARCHS) + set(ARCHS "x86_64;arm64") + endif() + # For universal builds, don't set target triple - let CMake handle it + # string(REPLACE ";" "-" ARCHS_SPLIT "${ARCHS}") + # set(APPLE_TARGET_TRIPLE_INT ${ARCHS_SPLIT}-apple-macosx${DEPLOYMENT_TARGET}) +elseif(PLATFORM_INT STREQUAL "MAC_CATALYST_UNIVERSAL") + set(SDK_NAME macosx) + if(NOT ARCHS) + set(ARCHS "x86_64;arm64") + endif() + string(REPLACE ";" "-" ARCHS_SPLIT "${ARCHS}") + set(APPLE_TARGET_TRIPLE_INT apple-ios${DEPLOYMENT_TARGET}-macabi) +else() + message(FATAL_ERROR "Invalid PLATFORM: ${PLATFORM_INT}") +endif() + +string(REPLACE ";" " " ARCHS_SPACED "${ARCHS}") + +if(MODERN_CMAKE AND PLATFORM_INT MATCHES ".*COMBINED" AND NOT CMAKE_GENERATOR MATCHES "Xcode") + message(FATAL_ERROR "The COMBINED options only work with Xcode generator, -G Xcode") +endif() + +if(CMAKE_GENERATOR MATCHES "Xcode" AND PLATFORM_INT MATCHES "^MAC_CATALYST") + set(CMAKE_XCODE_ATTRIBUTE_CLANG_CXX_LIBRARY "libc++") + set(CMAKE_XCODE_ATTRIBUTE_SUPPORTED_PLATFORMS "macosx") + set(CMAKE_XCODE_ATTRIBUTE_SUPPORTS_MACCATALYST "YES") + if(NOT DEFINED MACOSX_DEPLOYMENT_TARGET) + set(CMAKE_XCODE_ATTRIBUTE_MACOSX_DEPLOYMENT_TARGET "10.15") + else() + set(CMAKE_XCODE_ATTRIBUTE_MACOSX_DEPLOYMENT_TARGET "${MACOSX_DEPLOYMENT_TARGET}") + endif() +elseif(CMAKE_GENERATOR MATCHES "Xcode") + set(CMAKE_XCODE_ATTRIBUTE_CLANG_CXX_LIBRARY "libc++") + set(CMAKE_XCODE_ATTRIBUTE_IPHONEOS_DEPLOYMENT_TARGET "${DEPLOYMENT_TARGET}") + if(NOT PLATFORM_INT MATCHES ".*COMBINED") + set(CMAKE_XCODE_ATTRIBUTE_ARCHS[sdk=${SDK_NAME}*] "${ARCHS_SPACED}") + set(CMAKE_XCODE_ATTRIBUTE_VALID_ARCHS[sdk=${SDK_NAME}*] "${ARCHS_SPACED}") + endif() +endif() + +# If the user did not specify the SDK root to use, then query xcodebuild for it. +if(DEFINED CMAKE_OSX_SYSROOT_INT) + # Environment variables are always preserved. + set(ENV{_CMAKE_OSX_SYSROOT_INT} "${CMAKE_OSX_SYSROOT_INT}") +elseif(DEFINED ENV{_CMAKE_OSX_SYSROOT_INT}) + set(CMAKE_OSX_SYSROOT_INT "$ENV{_CMAKE_OSX_SYSROOT_INT}") +elseif(NOT DEFINED CMAKE_OSX_SYSROOT_INT) + execute_process(COMMAND ${XCODEBUILD_EXECUTABLE} -version -sdk ${SDK_NAME} Path + OUTPUT_VARIABLE CMAKE_OSX_SYSROOT_INT + ERROR_QUIET + OUTPUT_STRIP_TRAILING_WHITESPACE) +endif() + +if (NOT DEFINED CMAKE_OSX_SYSROOT_INT AND NOT DEFINED CMAKE_OSX_SYSROOT) + message(SEND_ERROR "Please make sure that Xcode is installed and that the toolchain" + "is pointing to the correct path. Please run:" + "sudo xcode-select -s /Applications/Xcode.app/Contents/Developer" + "and see if that fixes the problem for you.") + message(FATAL_ERROR "Invalid CMAKE_OSX_SYSROOT: ${CMAKE_OSX_SYSROOT} " + "does not exist.") +elseif(DEFINED CMAKE_OSX_SYSROOT_INT) + set(CMAKE_OSX_SYSROOT_INT "${CMAKE_OSX_SYSROOT_INT}" CACHE INTERNAL "") + # Specify the location or name of the platform SDK to be used in CMAKE_OSX_SYSROOT. + set(CMAKE_OSX_SYSROOT "${CMAKE_OSX_SYSROOT_INT}" CACHE INTERNAL "") +endif() + +# Use bitcode or not +if(NOT DEFINED ENABLE_BITCODE) + message(STATUS "[DEFAULTS] Disabling bitcode support by default. ENABLE_BITCODE not provided for override!") + set(ENABLE_BITCODE OFF) +endif() +set(ENABLE_BITCODE_INT ${ENABLE_BITCODE} CACHE BOOL + "Whether or not to enable bitcode" FORCE) +# Use ARC or not +if(NOT DEFINED ENABLE_ARC) + # Unless specified, enable ARC support by default + set(ENABLE_ARC ON) + message(STATUS "[DEFAULTS] Enabling ARC support by default. ENABLE_ARC not provided!") +endif() +set(ENABLE_ARC_INT ${ENABLE_ARC} CACHE BOOL "Whether or not to enable ARC" FORCE) +# Use hidden visibility or not +if(NOT DEFINED ENABLE_VISIBILITY) + # Unless specified, disable symbols visibility by default + set(ENABLE_VISIBILITY OFF) + message(STATUS "[DEFAULTS] Hiding symbols visibility by default. ENABLE_VISIBILITY not provided!") +endif() +set(ENABLE_VISIBILITY_INT ${ENABLE_VISIBILITY} CACHE BOOL "Whether or not to hide symbols from the dynamic linker (-fvisibility=hidden)" FORCE) +# Set strict compiler checks or not +if(NOT DEFINED ENABLE_STRICT_TRY_COMPILE) + # Unless specified, disable strict try_compile() + set(ENABLE_STRICT_TRY_COMPILE OFF) + message(STATUS "[DEFAULTS] Using NON-strict compiler checks by default. ENABLE_STRICT_TRY_COMPILE not provided!") +endif() +set(ENABLE_STRICT_TRY_COMPILE_INT ${ENABLE_STRICT_TRY_COMPILE} CACHE BOOL + "Whether or not to use strict compiler checks" FORCE) + +# Get the SDK version information. +if(DEFINED SDK_VERSION) + # Environment variables are always preserved. + set(ENV{_SDK_VERSION} "${SDK_VERSION}") +elseif(DEFINED ENV{_SDK_VERSION}) + set(SDK_VERSION "$ENV{_SDK_VERSION}") +elseif(NOT DEFINED SDK_VERSION) + execute_process(COMMAND ${XCODEBUILD_EXECUTABLE} -sdk ${CMAKE_OSX_SYSROOT_INT} -version SDKVersion + OUTPUT_VARIABLE SDK_VERSION + ERROR_QUIET + OUTPUT_STRIP_TRAILING_WHITESPACE) +endif() + +# Find the Developer root for the specific iOS platform being compiled for +# from CMAKE_OSX_SYSROOT. Should be ../../ from SDK specified in +# CMAKE_OSX_SYSROOT. There does not appear to be a direct way to obtain +# this information from xcrun or xcodebuild. +if (NOT DEFINED CMAKE_DEVELOPER_ROOT AND NOT CMAKE_GENERATOR MATCHES "Xcode") + get_filename_component(PLATFORM_SDK_DIR ${CMAKE_OSX_SYSROOT_INT} PATH) + get_filename_component(CMAKE_DEVELOPER_ROOT ${PLATFORM_SDK_DIR} PATH) + if (NOT EXISTS "${CMAKE_DEVELOPER_ROOT}") + message(FATAL_ERROR "Invalid CMAKE_DEVELOPER_ROOT: ${CMAKE_DEVELOPER_ROOT} does not exist.") + endif() +endif() + +# Find the C & C++ compilers for the specified SDK. +if(DEFINED CMAKE_C_COMPILER) + # Environment variables are always preserved. + set(ENV{_CMAKE_C_COMPILER} "${CMAKE_C_COMPILER}") +elseif(DEFINED ENV{_CMAKE_C_COMPILER}) + set(CMAKE_C_COMPILER "$ENV{_CMAKE_C_COMPILER}") + set(CMAKE_ASM_COMPILER ${CMAKE_C_COMPILER}) +elseif(NOT DEFINED CMAKE_C_COMPILER) + execute_process(COMMAND xcrun -sdk ${CMAKE_OSX_SYSROOT_INT} -find clang + OUTPUT_VARIABLE CMAKE_C_COMPILER + ERROR_QUIET + OUTPUT_STRIP_TRAILING_WHITESPACE) + set(CMAKE_ASM_COMPILER ${CMAKE_C_COMPILER}) +endif() +if(DEFINED CMAKE_CXX_COMPILER) + # Environment variables are always preserved. + set(ENV{_CMAKE_CXX_COMPILER} "${CMAKE_CXX_COMPILER}") +elseif(DEFINED ENV{_CMAKE_CXX_COMPILER}) + set(CMAKE_CXX_COMPILER "$ENV{_CMAKE_CXX_COMPILER}") +elseif(NOT DEFINED CMAKE_CXX_COMPILER) + execute_process(COMMAND xcrun -sdk ${CMAKE_OSX_SYSROOT_INT} -find clang++ + OUTPUT_VARIABLE CMAKE_CXX_COMPILER + ERROR_QUIET + OUTPUT_STRIP_TRAILING_WHITESPACE) +endif() +# Find (Apple's) libtool. +if(DEFINED BUILD_LIBTOOL) + # Environment variables are always preserved. + set(ENV{_BUILD_LIBTOOL} "${BUILD_LIBTOOL}") +elseif(DEFINED ENV{_BUILD_LIBTOOL}) + set(BUILD_LIBTOOL "$ENV{_BUILD_LIBTOOL}") +elseif(NOT DEFINED BUILD_LIBTOOL) + execute_process(COMMAND xcrun -sdk ${CMAKE_OSX_SYSROOT_INT} -find libtool + OUTPUT_VARIABLE BUILD_LIBTOOL + ERROR_QUIET + OUTPUT_STRIP_TRAILING_WHITESPACE) +endif() +# Find the toolchain's provided install_name_tool if none is found on the host +if(DEFINED CMAKE_INSTALL_NAME_TOOL) + # Environment variables are always preserved. + set(ENV{_CMAKE_INSTALL_NAME_TOOL} "${CMAKE_INSTALL_NAME_TOOL}") +elseif(DEFINED ENV{_CMAKE_INSTALL_NAME_TOOL}) + set(CMAKE_INSTALL_NAME_TOOL "$ENV{_CMAKE_INSTALL_NAME_TOOL}") +elseif(NOT DEFINED CMAKE_INSTALL_NAME_TOOL) + execute_process(COMMAND xcrun -sdk ${CMAKE_OSX_SYSROOT_INT} -find install_name_tool + OUTPUT_VARIABLE CMAKE_INSTALL_NAME_TOOL_INT + ERROR_QUIET + OUTPUT_STRIP_TRAILING_WHITESPACE) + set(CMAKE_INSTALL_NAME_TOOL ${CMAKE_INSTALL_NAME_TOOL_INT} CACHE INTERNAL "") +endif() + +# Configure libtool to be used instead of ar + ranlib to build static libraries. +# This is required on Xcode 7+, but should also work on previous versions of +# Xcode. +get_property(languages GLOBAL PROPERTY ENABLED_LANGUAGES) +foreach(lang ${languages}) + set(CMAKE_${lang}_CREATE_STATIC_LIBRARY "${BUILD_LIBTOOL} -static -o " CACHE INTERNAL "") +endforeach() + +# CMake 3.14+ support building for iOS, watchOS, and tvOS out of the box. +if(MODERN_CMAKE) + if(SDK_NAME MATCHES "iphone") + set(CMAKE_SYSTEM_NAME iOS) + elseif(SDK_NAME MATCHES "xros") + set(CMAKE_SYSTEM_NAME visionOS) + elseif(SDK_NAME MATCHES "xrsimulator") + set(CMAKE_SYSTEM_NAME visionOS) + elseif(SDK_NAME MATCHES "macosx") + set(CMAKE_SYSTEM_NAME Darwin) + elseif(SDK_NAME MATCHES "appletv") + set(CMAKE_SYSTEM_NAME tvOS) + elseif(SDK_NAME MATCHES "watch") + set(CMAKE_SYSTEM_NAME watchOS) + endif() + # Provide flags for a combined FAT library build on newer CMake versions + if(PLATFORM_INT MATCHES ".*COMBINED") + set(CMAKE_IOS_INSTALL_COMBINED YES) + if(CMAKE_GENERATOR MATCHES "Xcode") + # Set the SDKROOT Xcode properties to a Xcode-friendly value (the SDK_NAME, E.g, iphoneos) + # This way, Xcode will automatically switch between the simulator and device SDK when building. + set(CMAKE_XCODE_ATTRIBUTE_SDKROOT "${SDK_NAME}") + # Force to not build just one ARCH, but all! + set(CMAKE_XCODE_ATTRIBUTE_ONLY_ACTIVE_ARCH "NO") + endif() + endif() +elseif(NOT DEFINED CMAKE_SYSTEM_NAME AND ${CMAKE_VERSION} VERSION_GREATER_EQUAL "3.10") + # Legacy code path prior to CMake 3.14 or fallback if no CMAKE_SYSTEM_NAME specified + set(CMAKE_SYSTEM_NAME iOS) +elseif(NOT DEFINED CMAKE_SYSTEM_NAME) + # Legacy code path before CMake 3.14 or fallback if no CMAKE_SYSTEM_NAME specified + set(CMAKE_SYSTEM_NAME Darwin) +endif() +# Standard settings. +set(CMAKE_SYSTEM_VERSION ${SDK_VERSION} CACHE INTERNAL "") +set(UNIX ON CACHE BOOL "") +set(APPLE ON CACHE BOOL "") +if(PLATFORM STREQUAL "MAC" OR PLATFORM STREQUAL "MAC_ARM64" OR PLATFORM STREQUAL "MAC_UNIVERSAL") + set(IOS OFF CACHE BOOL "") + set(MACOS ON CACHE BOOL "") +elseif(PLATFORM STREQUAL "MAC_CATALYST" OR PLATFORM STREQUAL "MAC_CATALYST_ARM64" OR PLATFORM STREQUAL "MAC_CATALYST_UNIVERSAL") + set(IOS ON CACHE BOOL "") + set(MACOS ON CACHE BOOL "") +elseif(PLATFORM STREQUAL "VISIONOS" OR PLATFORM STREQUAL "SIMULATOR_VISIONOS" OR PLATFORM STREQUAL "VISIONOSCOMBINED") + set(IOS OFF CACHE BOOL "") + set(VISIONOS ON CACHE BOOL "") +else() + set(IOS ON CACHE BOOL "") +endif() +# Set the architectures for which to build. +set(CMAKE_OSX_ARCHITECTURES ${ARCHS} CACHE INTERNAL "") +# Change the type of target generated for try_compile() so it'll work when cross-compiling, weak compiler checks +if(NOT ENABLE_STRICT_TRY_COMPILE_INT) + set(CMAKE_TRY_COMPILE_TARGET_TYPE STATIC_LIBRARY) +endif() +# All iOS/Darwin specific settings - some may be redundant. +if (NOT DEFINED CMAKE_MACOSX_BUNDLE) + set(CMAKE_MACOSX_BUNDLE YES) +endif() +set(CMAKE_XCODE_ATTRIBUTE_CODE_SIGNING_REQUIRED "NO") +set(CMAKE_XCODE_ATTRIBUTE_CODE_SIGNING_ALLOWED "NO") +set(CMAKE_SHARED_LIBRARY_PREFIX "lib") +set(CMAKE_SHARED_LIBRARY_SUFFIX ".dylib") +set(CMAKE_EXTRA_SHARED_LIBRARY_SUFFIXES ".tbd" ".so") +set(CMAKE_SHARED_MODULE_PREFIX "lib") +set(CMAKE_SHARED_MODULE_SUFFIX ".so") +set(CMAKE_C_COMPILER_ABI ELF) +set(CMAKE_CXX_COMPILER_ABI ELF) +set(CMAKE_C_HAS_ISYSROOT 1) +set(CMAKE_CXX_HAS_ISYSROOT 1) +set(CMAKE_MODULE_EXISTS 1) +set(CMAKE_DL_LIBS "") +set(CMAKE_C_OSX_COMPATIBILITY_VERSION_FLAG "-compatibility_version ") +set(CMAKE_C_OSX_CURRENT_VERSION_FLAG "-current_version ") +set(CMAKE_CXX_OSX_COMPATIBILITY_VERSION_FLAG "${CMAKE_C_OSX_COMPATIBILITY_VERSION_FLAG}") +set(CMAKE_CXX_OSX_CURRENT_VERSION_FLAG "${CMAKE_C_OSX_CURRENT_VERSION_FLAG}") + +if(ARCHS MATCHES "((^|;|, )(arm64|arm64e|x86_64))+") + set(CMAKE_C_SIZEOF_DATA_PTR 8) + set(CMAKE_CXX_SIZEOF_DATA_PTR 8) + if(ARCHS MATCHES "((^|;|, )(arm64|arm64e))+") + set(CMAKE_SYSTEM_PROCESSOR "aarch64") + else() + set(CMAKE_SYSTEM_PROCESSOR "x86_64") + endif() +else() + set(CMAKE_C_SIZEOF_DATA_PTR 4) + set(CMAKE_CXX_SIZEOF_DATA_PTR 4) + set(CMAKE_SYSTEM_PROCESSOR "arm") +endif() + +# Note that only Xcode 7+ supports the newer more specific: +# -m${SDK_NAME}-version-min flags, older versions of Xcode use: +# -m(ios/ios-simulator)-version-min instead. +if(${CMAKE_VERSION} VERSION_LESS "3.11") + if(PLATFORM_INT STREQUAL "OS" OR PLATFORM_INT STREQUAL "OS64") + if(XCODE_VERSION_INT VERSION_LESS 7.0) + set(SDK_NAME_VERSION_FLAGS + "-mios-version-min=${DEPLOYMENT_TARGET}") + else() + # Xcode 7.0+ uses flags we can build directly from SDK_NAME. + set(SDK_NAME_VERSION_FLAGS + "-m${SDK_NAME}-version-min=${DEPLOYMENT_TARGET}") + endif() + elseif(PLATFORM_INT STREQUAL "TVOS") + set(SDK_NAME_VERSION_FLAGS + "-mtvos-version-min=${DEPLOYMENT_TARGET}") + elseif(PLATFORM_INT STREQUAL "SIMULATOR_TVOS") + set(SDK_NAME_VERSION_FLAGS + "-mtvos-simulator-version-min=${DEPLOYMENT_TARGET}") +elseif(PLATFORM_INT STREQUAL "SIMULATORARM64_TVOS") + set(SDK_NAME_VERSION_FLAGS + "-mtvos-simulator-version-min=${DEPLOYMENT_TARGET}") + elseif(PLATFORM_INT STREQUAL "WATCHOS") + set(SDK_NAME_VERSION_FLAGS + "-mwatchos-version-min=${DEPLOYMENT_TARGET}") + elseif(PLATFORM_INT STREQUAL "SIMULATOR_WATCHOS") + set(SDK_NAME_VERSION_FLAGS + "-mwatchos-simulator-version-min=${DEPLOYMENT_TARGET}") + elseif(PLATFORM_INT STREQUAL "SIMULATORARM64_WATCHOS") + set(SDK_NAME_VERSION_FLAGS + "-mwatchos-simulator-version-min=${DEPLOYMENT_TARGET}") + elseif(PLATFORM_INT STREQUAL "MAC") + set(SDK_NAME_VERSION_FLAGS + "-mmacosx-version-min=${DEPLOYMENT_TARGET}") + else() + # SIMULATOR or SIMULATOR64 both use -mios-simulator-version-min. + set(SDK_NAME_VERSION_FLAGS + "-mios-simulator-version-min=${DEPLOYMENT_TARGET}") + endif() +elseif(NOT PLATFORM_INT MATCHES "^MAC_CATALYST") + # Newer versions of CMake sets the version min flags correctly, skip this for Mac Catalyst targets + set(CMAKE_OSX_DEPLOYMENT_TARGET ${DEPLOYMENT_TARGET} CACHE INTERNAL "Minimum OS X deployment version") +endif() + +if(DEFINED APPLE_TARGET_TRIPLE_INT) + set(APPLE_TARGET_TRIPLE ${APPLE_TARGET_TRIPLE_INT} CACHE INTERNAL "") + set(CMAKE_C_COMPILER_TARGET ${APPLE_TARGET_TRIPLE}) + set(CMAKE_CXX_COMPILER_TARGET ${APPLE_TARGET_TRIPLE}) + set(CMAKE_ASM_COMPILER_TARGET ${APPLE_TARGET_TRIPLE}) +endif() + +if(PLATFORM_INT MATCHES "^MAC_CATALYST") + set(C_TARGET_FLAGS "-isystem ${CMAKE_OSX_SYSROOT_INT}/System/iOSSupport/usr/include -iframework ${CMAKE_OSX_SYSROOT_INT}/System/iOSSupport/System/Library/Frameworks") +endif() + +if(ENABLE_BITCODE_INT) + set(BITCODE "-fembed-bitcode") + set(CMAKE_XCODE_ATTRIBUTE_BITCODE_GENERATION_MODE "bitcode") + set(CMAKE_XCODE_ATTRIBUTE_ENABLE_BITCODE "YES") +else() + set(BITCODE "") + set(CMAKE_XCODE_ATTRIBUTE_ENABLE_BITCODE "NO") +endif() + +if(ENABLE_ARC_INT) + set(FOBJC_ARC "-fobjc-arc") + set(CMAKE_XCODE_ATTRIBUTE_CLANG_ENABLE_OBJC_ARC "YES") +else() + set(FOBJC_ARC "-fno-objc-arc") + set(CMAKE_XCODE_ATTRIBUTE_CLANG_ENABLE_OBJC_ARC "NO") +endif() + +if(NAMED_LANGUAGE_SUPPORT_INT) + set(OBJC_VARS "-fobjc-abi-version=2 -DOBJC_OLD_DISPATCH_PROTOTYPES=0") + set(OBJC_LEGACY_VARS "") +else() + set(OBJC_VARS "") + set(OBJC_LEGACY_VARS "-fobjc-abi-version=2 -DOBJC_OLD_DISPATCH_PROTOTYPES=0") +endif() + +if(NOT ENABLE_VISIBILITY_INT) + foreach(lang ${languages}) + set(CMAKE_${lang}_VISIBILITY_PRESET "hidden" CACHE INTERNAL "") + endforeach() + set(CMAKE_XCODE_ATTRIBUTE_GCC_SYMBOLS_PRIVATE_EXTERN "YES") + set(VISIBILITY "-fvisibility=hidden -fvisibility-inlines-hidden") +else() + foreach(lang ${languages}) + set(CMAKE_${lang}_VISIBILITY_PRESET "default" CACHE INTERNAL "") + endforeach() + set(CMAKE_XCODE_ATTRIBUTE_GCC_SYMBOLS_PRIVATE_EXTERN "NO") + set(VISIBILITY "-fvisibility=default") +endif() + +if(DEFINED APPLE_TARGET_TRIPLE) + set(APPLE_TARGET_TRIPLE_FLAG "-target ${APPLE_TARGET_TRIPLE}") +endif() + +#Check if Xcode generator is used since that will handle these flags automagically +if(CMAKE_GENERATOR MATCHES "Xcode") + message(STATUS "Not setting any manual command-line buildflags, since Xcode is selected as the generator. Modifying the Xcode build-settings directly instead.") +else() + set(CMAKE_C_FLAGS "${C_TARGET_FLAGS} ${APPLE_TARGET_TRIPLE_FLAG} ${SDK_NAME_VERSION_FLAGS} ${OBJC_LEGACY_VARS} ${BITCODE} ${VISIBILITY} ${CMAKE_C_FLAGS}" CACHE INTERNAL + "Flags used by the compiler during all C build types.") + set(CMAKE_C_FLAGS_DEBUG "-O0 -g ${CMAKE_C_FLAGS_DEBUG}") + set(CMAKE_C_FLAGS_MINSIZEREL "-DNDEBUG -Os ${CMAKE_C_FLAGS_MINSIZEREL}") + set(CMAKE_C_FLAGS_RELWITHDEBINFO "-DNDEBUG -O2 -g ${CMAKE_C_FLAGS_RELWITHDEBINFO}") + set(CMAKE_C_FLAGS_RELEASE "-DNDEBUG -O3 ${CMAKE_C_FLAGS_RELEASE}") + set(CMAKE_CXX_FLAGS "${C_TARGET_FLAGS} ${APPLE_TARGET_TRIPLE_FLAG} ${SDK_NAME_VERSION_FLAGS} ${OBJC_LEGACY_VARS} ${BITCODE} ${VISIBILITY} ${CMAKE_CXX_FLAGS}" CACHE INTERNAL + "Flags used by the compiler during all CXX build types.") + set(CMAKE_CXX_FLAGS_DEBUG "-O0 -g ${CMAKE_CXX_FLAGS_DEBUG}") + set(CMAKE_CXX_FLAGS_MINSIZEREL "-DNDEBUG -Os ${CMAKE_CXX_FLAGS_MINSIZEREL}") + set(CMAKE_CXX_FLAGS_RELWITHDEBINFO "-DNDEBUG -O2 -g ${CMAKE_CXX_FLAGS_RELWITHDEBINFO}") + set(CMAKE_CXX_FLAGS_RELEASE "-DNDEBUG -O3 ${CMAKE_CXX_FLAGS_RELEASE}") + if(NAMED_LANGUAGE_SUPPORT_INT) + set(CMAKE_OBJC_FLAGS "${C_TARGET_FLAGS} ${APPLE_TARGET_TRIPLE_FLAG} ${SDK_NAME_VERSION_FLAGS} ${BITCODE} ${VISIBILITY} ${FOBJC_ARC} ${OBJC_VARS} ${CMAKE_OBJC_FLAGS}" CACHE INTERNAL + "Flags used by the compiler during all OBJC build types.") + set(CMAKE_OBJC_FLAGS_DEBUG "-O0 -g ${CMAKE_OBJC_FLAGS_DEBUG}") + set(CMAKE_OBJC_FLAGS_MINSIZEREL "-DNDEBUG -Os ${CMAKE_OBJC_FLAGS_MINSIZEREL}") + set(CMAKE_OBJC_FLAGS_RELWITHDEBINFO "-DNDEBUG -O2 -g ${CMAKE_OBJC_FLAGS_RELWITHDEBINFO}") + set(CMAKE_OBJC_FLAGS_RELEASE "-DNDEBUG -O3 ${CMAKE_OBJC_FLAGS_RELEASE}") + set(CMAKE_OBJCXX_FLAGS "${C_TARGET_FLAGS} ${APPLE_TARGET_TRIPLE_FLAG} ${SDK_NAME_VERSION_FLAGS} ${BITCODE} ${VISIBILITY} ${FOBJC_ARC} ${OBJC_VARS} ${CMAKE_OBJCXX_FLAGS}" CACHE INTERNAL + "Flags used by the compiler during all OBJCXX build types.") + set(CMAKE_OBJCXX_FLAGS_DEBUG "-O0 -g ${CMAKE_OBJCXX_FLAGS_DEBUG}") + set(CMAKE_OBJCXX_FLAGS_MINSIZEREL "-DNDEBUG -Os ${CMAKE_OBJCXX_FLAGS_MINSIZEREL}") + set(CMAKE_OBJCXX_FLAGS_RELWITHDEBINFO "-DNDEBUG -O2 -g ${CMAKE_OBJCXX_FLAGS_RELWITHDEBINFO}") + set(CMAKE_OBJCXX_FLAGS_RELEASE "-DNDEBUG -O3 ${CMAKE_OBJCXX_FLAGS_RELEASE}") + endif() + set(CMAKE_C_LINK_FLAGS "${C_TARGET_FLAGS} ${SDK_NAME_VERSION_FLAGS} -Wl,-search_paths_first ${CMAKE_C_LINK_FLAGS}" CACHE INTERNAL + "Flags used by the compiler for all C link types.") + set(CMAKE_CXX_LINK_FLAGS "${C_TARGET_FLAGS} ${SDK_NAME_VERSION_FLAGS} -Wl,-search_paths_first ${CMAKE_CXX_LINK_FLAGS}" CACHE INTERNAL + "Flags used by the compiler for all CXX link types.") + if(NAMED_LANGUAGE_SUPPORT_INT) + set(CMAKE_OBJC_LINK_FLAGS "${C_TARGET_FLAGS} ${SDK_NAME_VERSION_FLAGS} -Wl,-search_paths_first ${CMAKE_OBJC_LINK_FLAGS}" CACHE INTERNAL + "Flags used by the compiler for all OBJC link types.") + set(CMAKE_OBJCXX_LINK_FLAGS "${C_TARGET_FLAGS} ${SDK_NAME_VERSION_FLAGS} -Wl,-search_paths_first ${CMAKE_OBJCXX_LINK_FLAGS}" CACHE INTERNAL + "Flags used by the compiler for all OBJCXX link types.") + endif() + set(CMAKE_ASM_FLAGS "${CMAKE_C_FLAGS} -x assembler-with-cpp" CACHE INTERNAL + "Flags used by the compiler for all ASM build types.") +endif() + +## Print status messages to inform of the current state +message(STATUS "Configuring ${SDK_NAME} build for platform: ${PLATFORM_INT}, architecture(s): ${ARCHS}") +message(STATUS "Using SDK: ${CMAKE_OSX_SYSROOT_INT}") +message(STATUS "Using C compiler: ${CMAKE_C_COMPILER}") +message(STATUS "Using CXX compiler: ${CMAKE_CXX_COMPILER}") +message(STATUS "Using libtool: ${BUILD_LIBTOOL}") +message(STATUS "Using install name tool: ${CMAKE_INSTALL_NAME_TOOL}") +if(DEFINED APPLE_TARGET_TRIPLE) + message(STATUS "Autoconf target triple: ${APPLE_TARGET_TRIPLE}") +endif() +message(STATUS "Using minimum deployment version: ${DEPLOYMENT_TARGET}" + " (SDK version: ${SDK_VERSION})") +if(MODERN_CMAKE) + message(STATUS "Merging integrated CMake 3.14+ iOS,tvOS,watchOS,macOS toolchain(s) with this toolchain!") + if(PLATFORM_INT MATCHES ".*COMBINED") + message(STATUS "Will combine built (static) artifacts into FAT lib...") + endif() +endif() +if(CMAKE_GENERATOR MATCHES "Xcode") + message(STATUS "Using Xcode version: ${XCODE_VERSION_INT}") +endif() +message(STATUS "CMake version: ${CMAKE_VERSION}") +if(DEFINED SDK_NAME_VERSION_FLAGS) + message(STATUS "Using version flags: ${SDK_NAME_VERSION_FLAGS}") +endif() +message(STATUS "Using a data_ptr size of: ${CMAKE_CXX_SIZEOF_DATA_PTR}") +if(ENABLE_BITCODE_INT) + message(STATUS "Bitcode: Enabled") +else() + message(STATUS "Bitcode: Disabled") +endif() + +if(ENABLE_ARC_INT) + message(STATUS "ARC: Enabled") +else() + message(STATUS "ARC: Disabled") +endif() + +if(ENABLE_VISIBILITY_INT) + message(STATUS "Hiding symbols: Disabled") +else() + message(STATUS "Hiding symbols: Enabled") +endif() + +# Set global properties +set_property(GLOBAL PROPERTY PLATFORM "${PLATFORM}") +set_property(GLOBAL PROPERTY APPLE_TARGET_TRIPLE "${APPLE_TARGET_TRIPLE_INT}") +set_property(GLOBAL PROPERTY SDK_VERSION "${SDK_VERSION}") +set_property(GLOBAL PROPERTY XCODE_VERSION "${XCODE_VERSION_INT}") +set_property(GLOBAL PROPERTY OSX_ARCHITECTURES "${CMAKE_OSX_ARCHITECTURES}") + +# Export configurable variables for the try_compile() command. +set(CMAKE_TRY_COMPILE_PLATFORM_VARIABLES + PLATFORM + XCODE_VERSION_INT + SDK_VERSION + NAMED_LANGUAGE_SUPPORT + DEPLOYMENT_TARGET + CMAKE_DEVELOPER_ROOT + CMAKE_OSX_SYSROOT_INT + ENABLE_BITCODE + ENABLE_ARC + CMAKE_ASM_COMPILER + CMAKE_C_COMPILER + CMAKE_C_COMPILER_TARGET + CMAKE_CXX_COMPILER + CMAKE_CXX_COMPILER_TARGET + BUILD_LIBTOOL + CMAKE_INSTALL_NAME_TOOL + CMAKE_C_FLAGS + CMAKE_C_DEBUG + CMAKE_C_MINSIZEREL + CMAKE_C_RELWITHDEBINFO + CMAKE_C_RELEASE + CMAKE_CXX_FLAGS + CMAKE_CXX_FLAGS_DEBUG + CMAKE_CXX_FLAGS_MINSIZEREL + CMAKE_CXX_FLAGS_RELWITHDEBINFO + CMAKE_CXX_FLAGS_RELEASE + CMAKE_C_LINK_FLAGS + CMAKE_CXX_LINK_FLAGS + CMAKE_ASM_FLAGS +) + +if(NAMED_LANGUAGE_SUPPORT_INT) + list(APPEND CMAKE_TRY_COMPILE_PLATFORM_VARIABLES + CMAKE_OBJC_FLAGS + CMAKE_OBJC_DEBUG + CMAKE_OBJC_MINSIZEREL + CMAKE_OBJC_RELWITHDEBINFO + CMAKE_OBJC_RELEASE + CMAKE_OBJCXX_FLAGS + CMAKE_OBJCXX_DEBUG + CMAKE_OBJCXX_MINSIZEREL + CMAKE_OBJCXX_RELWITHDEBINFO + CMAKE_OBJCXX_RELEASE + CMAKE_OBJC_LINK_FLAGS + CMAKE_OBJCXX_LINK_FLAGS + ) +endif() + +set(CMAKE_PLATFORM_HAS_INSTALLNAME 1) +set(CMAKE_SHARED_LINKER_FLAGS "-rpath @executable_path/Frameworks -rpath @loader_path/Frameworks") +set(CMAKE_SHARED_LIBRARY_CREATE_C_FLAGS "-dynamiclib -Wl,-headerpad_max_install_names") +set(CMAKE_SHARED_MODULE_CREATE_C_FLAGS "-bundle -Wl,-headerpad_max_install_names") +set(CMAKE_SHARED_MODULE_LOADER_C_FLAG "-Wl,-bundle_loader,") +set(CMAKE_SHARED_MODULE_LOADER_CXX_FLAG "-Wl,-bundle_loader,") +set(CMAKE_FIND_LIBRARY_SUFFIXES ".tbd" ".dylib" ".so" ".a") +set(CMAKE_SHARED_LIBRARY_SONAME_C_FLAG "-install_name") + +# Set the find root to the SDK developer roots. +# Note: CMAKE_FIND_ROOT_PATH is only useful when cross-compiling. Thus, do not set on macOS builds. +if(NOT PLATFORM_INT MATCHES "^MAC.*$") + list(APPEND CMAKE_FIND_ROOT_PATH "${CMAKE_OSX_SYSROOT_INT}" CACHE INTERNAL "") + set(CMAKE_IGNORE_PATH "/System/Library/Frameworks;/usr/local/lib;/opt/homebrew" CACHE INTERNAL "") +endif() + +# Default to searching for frameworks first. +IF(NOT DEFINED CMAKE_FIND_FRAMEWORK) + set(CMAKE_FIND_FRAMEWORK FIRST) +ENDIF(NOT DEFINED CMAKE_FIND_FRAMEWORK) + +# Set up the default search directories for frameworks. +if(PLATFORM_INT MATCHES "^MAC_CATALYST") + set(CMAKE_FRAMEWORK_PATH + ${CMAKE_DEVELOPER_ROOT}/Library/PrivateFrameworks + ${CMAKE_OSX_SYSROOT_INT}/System/Library/Frameworks + ${CMAKE_OSX_SYSROOT_INT}/System/iOSSupport/System/Library/Frameworks + ${CMAKE_FRAMEWORK_PATH} CACHE INTERNAL "") +else() + set(CMAKE_FRAMEWORK_PATH + ${CMAKE_DEVELOPER_ROOT}/Library/PrivateFrameworks + ${CMAKE_OSX_SYSROOT_INT}/System/Library/Frameworks + ${CMAKE_FRAMEWORK_PATH} CACHE INTERNAL "") +endif() + +# By default, search both the specified iOS SDK and the remainder of the host filesystem. +if(NOT CMAKE_FIND_ROOT_PATH_MODE_PROGRAM) + set(CMAKE_FIND_ROOT_PATH_MODE_PROGRAM BOTH CACHE INTERNAL "") +endif() +if(NOT CMAKE_FIND_ROOT_PATH_MODE_LIBRARY) + set(CMAKE_FIND_ROOT_PATH_MODE_LIBRARY BOTH CACHE INTERNAL "") +endif() +if(NOT CMAKE_FIND_ROOT_PATH_MODE_INCLUDE) + set(CMAKE_FIND_ROOT_PATH_MODE_INCLUDE BOTH CACHE INTERNAL "") +endif() +if(NOT CMAKE_FIND_ROOT_PATH_MODE_PACKAGE) + set(CMAKE_FIND_ROOT_PATH_MODE_PACKAGE BOTH CACHE INTERNAL "") +endif() + +# +# Some helper-macros below to simplify and beautify the CMakeFile +# + +# This little macro lets you set any Xcode specific property. +macro(set_xcode_property TARGET XCODE_PROPERTY XCODE_VALUE XCODE_RELVERSION) + set(XCODE_RELVERSION_I "${XCODE_RELVERSION}") + if(XCODE_RELVERSION_I STREQUAL "All") + set_property(TARGET ${TARGET} PROPERTY XCODE_ATTRIBUTE_${XCODE_PROPERTY} "${XCODE_VALUE}") + else() + set_property(TARGET ${TARGET} PROPERTY XCODE_ATTRIBUTE_${XCODE_PROPERTY}[variant=${XCODE_RELVERSION_I}] "${XCODE_VALUE}") + endif() +endmacro(set_xcode_property) + +# This macro lets you find executable programs on the host system. +macro(find_host_package) + set(CMAKE_FIND_ROOT_PATH_MODE_PROGRAM NEVER) + set(CMAKE_FIND_ROOT_PATH_MODE_LIBRARY NEVER) + set(CMAKE_FIND_ROOT_PATH_MODE_INCLUDE NEVER) + set(CMAKE_FIND_ROOT_PATH_MODE_PACKAGE NEVER) + set(_TOOLCHAIN_IOS ${IOS}) + set(IOS OFF) + find_package(${ARGN}) + set(IOS ${_TOOLCHAIN_IOS}) + set(CMAKE_FIND_ROOT_PATH_MODE_PROGRAM BOTH) + set(CMAKE_FIND_ROOT_PATH_MODE_LIBRARY BOTH) + set(CMAKE_FIND_ROOT_PATH_MODE_INCLUDE BOTH) + set(CMAKE_FIND_ROOT_PATH_MODE_PACKAGE BOTH) +endmacro(find_host_package) diff --git a/libs/JSystem/include/JSystem/J3DGraphAnimator/J3DAnimation.h b/libs/JSystem/include/JSystem/J3DGraphAnimator/J3DAnimation.h index c7c8730a44..3c5133e880 100644 --- a/libs/JSystem/include/JSystem/J3DGraphAnimator/J3DAnimation.h +++ b/libs/JSystem/include/JSystem/J3DGraphAnimator/J3DAnimation.h @@ -9,9 +9,9 @@ #include "dusk/endian.h" #if TARGET_PC -#define OFFSET_PTR BE(u32) +#define OFFSET_PTR_V0 BE(u32) #else -#define OFFSET_PTR void* +#define OFFSET_PTR_V0 void* #endif struct J3DTransformInfo; @@ -80,7 +80,7 @@ struct J3DAnmColorKeyTable { */ struct J3DAnmVtxColorIndexData { /* 0x00 */ BE(u16) mNum; - /* 0x04 */ OFFSET_PTR mpData; + /* 0x04 */ OFFSET_PTR_V0 mpData; }; /** @@ -200,13 +200,13 @@ struct J3DAnmVtxColorFullData { /* 0x0A */ BE(s16) mFrameMax; /* 0x0C */ BE(u16) mAnmTableNum[2]; /* 0x10 */ u8 field_0x10[0x18 - 0x10]; - /* 0x18 */ OFFSET_PTR mTableOffsets[2]; - /* 0x20 */ OFFSET_PTR mVtxColorIndexDataOffsets[2]; - /* 0x28 */ OFFSET_PTR mVtxColorIndexPointerOffsets[2]; - /* 0x30 */ OFFSET_PTR mRValuesOffset; - /* 0x34 */ OFFSET_PTR mGValuesOffset; - /* 0x38 */ OFFSET_PTR mBValuesOffset; - /* 0x3C */ OFFSET_PTR mAValuesOffset; + /* 0x18 */ OFFSET_PTR_V0 mTableOffsets[2]; + /* 0x20 */ OFFSET_PTR_V0 mVtxColorIndexDataOffsets[2]; + /* 0x28 */ OFFSET_PTR_V0 mVtxColorIndexPointerOffsets[2]; + /* 0x30 */ OFFSET_PTR_V0 mRValuesOffset; + /* 0x34 */ OFFSET_PTR_V0 mGValuesOffset; + /* 0x38 */ OFFSET_PTR_V0 mBValuesOffset; + /* 0x3C */ OFFSET_PTR_V0 mAValuesOffset; }; // Size = 0x40 STATIC_ASSERT(sizeof(J3DAnmVtxColorFullData) == 0x40); @@ -222,8 +222,8 @@ struct J3DAnmVisibilityFullData { /* 0x0A */ BE(s16) mFrameMax; /* 0x0C */ BE(u16) field_0xc; /* 0x0E */ BE(u16) field_0xe; - /* 0x10 */ OFFSET_PTR mTableOffset; - /* 0x14 */ OFFSET_PTR mValuesOffset; + /* 0x10 */ OFFSET_PTR_V0 mTableOffset; + /* 0x14 */ OFFSET_PTR_V0 mValuesOffset; }; // Size = 0x18 STATIC_ASSERT(sizeof(J3DAnmVisibilityFullData) == 0x18); @@ -239,10 +239,10 @@ struct J3DAnmTransformFullData { /* 0x0A */ BE(s16) mFrameMax; /* 0x0C */ BE(u16) field_0xc; /* 0x0E */ u8 field_0xe[0x14 - 0xe]; - /* 0x14 */ OFFSET_PTR mTableOffset; - /* 0x18 */ OFFSET_PTR mScaleValOffset; - /* 0x1C */ OFFSET_PTR mRotValOffset; - /* 0x20 */ OFFSET_PTR mTransValOffset; + /* 0x14 */ OFFSET_PTR_V0 mTableOffset; + /* 0x18 */ OFFSET_PTR_V0 mScaleValOffset; + /* 0x1C */ OFFSET_PTR_V0 mRotValOffset; + /* 0x20 */ OFFSET_PTR_V0 mTransValOffset; }; // Size = 0x24 STATIC_ASSERT(sizeof(J3DAnmTransformFullData) == 0x24); @@ -261,13 +261,13 @@ struct J3DAnmColorKeyData { /* 0x12 */ BE(u16) field_0x12; /* 0x14 */ BE(u16) field_0x14; /* 0x16 */ BE(u16) field_0x16; - /* 0x18 */ OFFSET_PTR mTableOffset; - /* 0x1C */ OFFSET_PTR mUpdateMaterialIDOffset; - /* 0x20 */ OFFSET_PTR mNameTabOffset; - /* 0x24 */ OFFSET_PTR mRValOffset; - /* 0x28 */ OFFSET_PTR mGValOffset; - /* 0x2C */ OFFSET_PTR mBValOffset; - /* 0x30 */ OFFSET_PTR mAValOffset; + /* 0x18 */ OFFSET_PTR_V0 mTableOffset; + /* 0x1C */ OFFSET_PTR_V0 mUpdateMaterialIDOffset; + /* 0x20 */ OFFSET_PTR_V0 mNameTabOffset; + /* 0x24 */ OFFSET_PTR_V0 mRValOffset; + /* 0x28 */ OFFSET_PTR_V0 mGValOffset; + /* 0x2C */ OFFSET_PTR_V0 mBValOffset; + /* 0x30 */ OFFSET_PTR_V0 mAValOffset; }; // Size = 0x34 STATIC_ASSERT(sizeof(J3DAnmColorKeyData) == 0x34); @@ -285,26 +285,26 @@ struct J3DAnmTextureSRTKeyData { /* 0x0E */ BE(u16) field_0xe; /* 0x10 */ BE(u16) field_0x10; /* 0x12 */ BE(u16) field_0x12; - /* 0x14 */ OFFSET_PTR mTableOffset; - /* 0x18 */ OFFSET_PTR mUpdateMatIDOffset; - /* 0x1C */ OFFSET_PTR mNameTab1Offset; - /* 0x20 */ OFFSET_PTR mUpdateTexMtxIDOffset; - /* 0x24 */ OFFSET_PTR unkOffset; - /* 0x28 */ OFFSET_PTR mScaleValOffset; - /* 0x2C */ OFFSET_PTR mRotValOffset; - /* 0x30 */ OFFSET_PTR mTransValOffset; + /* 0x14 */ OFFSET_PTR_V0 mTableOffset; + /* 0x18 */ OFFSET_PTR_V0 mUpdateMatIDOffset; + /* 0x1C */ OFFSET_PTR_V0 mNameTab1Offset; + /* 0x20 */ OFFSET_PTR_V0 mUpdateTexMtxIDOffset; + /* 0x24 */ OFFSET_PTR_V0 unkOffset; + /* 0x28 */ OFFSET_PTR_V0 mScaleValOffset; + /* 0x2C */ OFFSET_PTR_V0 mRotValOffset; + /* 0x30 */ OFFSET_PTR_V0 mTransValOffset; /* 0x34 */ BE(u16) field_0x34; /* 0x36 */ BE(u16) field_0x36; /* 0x38 */ BE(u16) field_0x38; /* 0x3A */ BE(u16) field_0x3a; - /* 0x3C */ OFFSET_PTR mInfoTable2Offset; - /* 0x40 */ OFFSET_PTR field_0x40; - /* 0x44 */ OFFSET_PTR mNameTab2Offset; - /* 0x48 */ OFFSET_PTR field_0x48; - /* 0x4C */ OFFSET_PTR field_0x4c; - /* 0x50 */ OFFSET_PTR field_0x50; - /* 0x54 */ OFFSET_PTR field_0x54; - /* 0x58 */ OFFSET_PTR field_0x58; + /* 0x3C */ OFFSET_PTR_V0 mInfoTable2Offset; + /* 0x40 */ OFFSET_PTR_V0 field_0x40; + /* 0x44 */ OFFSET_PTR_V0 mNameTab2Offset; + /* 0x48 */ OFFSET_PTR_V0 field_0x48; + /* 0x4C */ OFFSET_PTR_V0 field_0x4c; + /* 0x50 */ OFFSET_PTR_V0 field_0x50; + /* 0x54 */ OFFSET_PTR_V0 field_0x54; + /* 0x58 */ OFFSET_PTR_V0 field_0x58; /* 0x5C */ BE(s32) field_0x5c; }; // Size = 0x60 @@ -321,13 +321,13 @@ struct J3DAnmVtxColorKeyData { /* 0x0A */ BE(s16) mFrameMax; /* 0x0C */ BE(u16) mAnmTableNum[2]; /* 0x10 */ u8 field_0x10[0x18 - 0x10]; - /* 0x18 */ OFFSET_PTR mTableOffsets[2]; - /* 0x20 */ OFFSET_PTR mVtxColoIndexDataOffset[2]; - /* 0x28 */ OFFSET_PTR mVtxColoIndexPointerOffset[2]; - /* 0x30 */ OFFSET_PTR mRValOffset; - /* 0x34 */ OFFSET_PTR mGValOffset; - /* 0x38 */ OFFSET_PTR mBValOffset; - /* 0x3C */ OFFSET_PTR mAValOffset; + /* 0x18 */ OFFSET_PTR_V0 mTableOffsets[2]; + /* 0x20 */ OFFSET_PTR_V0 mVtxColoIndexDataOffset[2]; + /* 0x28 */ OFFSET_PTR_V0 mVtxColoIndexPointerOffset[2]; + /* 0x30 */ OFFSET_PTR_V0 mRValOffset; + /* 0x34 */ OFFSET_PTR_V0 mGValOffset; + /* 0x38 */ OFFSET_PTR_V0 mBValOffset; + /* 0x3C */ OFFSET_PTR_V0 mAValOffset; }; // Size = 0x40 STATIC_ASSERT(sizeof(J3DAnmVtxColorKeyData) == 0x40); @@ -343,10 +343,10 @@ struct J3DAnmTexPatternFullData { /* 0x0A */ BE(s16) mFrameMax; /* 0x0C */ BE(u16) field_0xc; /* 0x0E */ BE(u16) field_0xe; - /* 0x10 */ OFFSET_PTR mTableOffset; - /* 0x14 */ OFFSET_PTR mValuesOffset; - /* 0x18 */ OFFSET_PTR mUpdateMaterialIDOffset; - /* 0x1C */ OFFSET_PTR mNameTabOffset; + /* 0x10 */ OFFSET_PTR_V0 mTableOffset; + /* 0x14 */ OFFSET_PTR_V0 mValuesOffset; + /* 0x18 */ OFFSET_PTR_V0 mUpdateMaterialIDOffset; + /* 0x1C */ OFFSET_PTR_V0 mNameTabOffset; }; // Size = 0x20 STATIC_ASSERT(sizeof(J3DAnmTexPatternFullData) == 0x20); @@ -370,20 +370,20 @@ struct J3DAnmTevRegKeyData { /* 0x1A */ BE(u16) field_0x1a; /* 0x1C */ BE(u16) field_0x1c; /* 0x1E */ BE(u16) field_0x1e; - /* 0x20 */ OFFSET_PTR mCRegTableOffset; - /* 0x24 */ OFFSET_PTR mKRegTableOffset; - /* 0x28 */ OFFSET_PTR mCRegUpdateMaterialIDOffset; - /* 0x2C */ OFFSET_PTR mKRegUpdateMaterialIDOffset; - /* 0x30 */ OFFSET_PTR mCRegNameTabOffset; - /* 0x34 */ OFFSET_PTR mKRegNameTabOffset; - /* 0x38 */ OFFSET_PTR mCRValuesOffset; - /* 0x3C */ OFFSET_PTR mCGValuesOffset; - /* 0x40 */ OFFSET_PTR mCBValuesOffset; - /* 0x44 */ OFFSET_PTR mCAValuesOffset; - /* 0x48 */ OFFSET_PTR mKRValuesOffset; - /* 0x4C */ OFFSET_PTR mKGValuesOffset; - /* 0x50 */ OFFSET_PTR mKBValuesOffset; - /* 0x54 */ OFFSET_PTR mKAValuesOffset; + /* 0x20 */ OFFSET_PTR_V0 mCRegTableOffset; + /* 0x24 */ OFFSET_PTR_V0 mKRegTableOffset; + /* 0x28 */ OFFSET_PTR_V0 mCRegUpdateMaterialIDOffset; + /* 0x2C */ OFFSET_PTR_V0 mKRegUpdateMaterialIDOffset; + /* 0x30 */ OFFSET_PTR_V0 mCRegNameTabOffset; + /* 0x34 */ OFFSET_PTR_V0 mKRegNameTabOffset; + /* 0x38 */ OFFSET_PTR_V0 mCRValuesOffset; + /* 0x3C */ OFFSET_PTR_V0 mCGValuesOffset; + /* 0x40 */ OFFSET_PTR_V0 mCBValuesOffset; + /* 0x44 */ OFFSET_PTR_V0 mCAValuesOffset; + /* 0x48 */ OFFSET_PTR_V0 mKRValuesOffset; + /* 0x4C */ OFFSET_PTR_V0 mKGValuesOffset; + /* 0x50 */ OFFSET_PTR_V0 mKBValuesOffset; + /* 0x54 */ OFFSET_PTR_V0 mKAValuesOffset; }; // Size = 0x58 STATIC_ASSERT(sizeof(J3DAnmTevRegKeyData) == 0x58); @@ -399,13 +399,13 @@ struct J3DAnmColorFullData { /* PlaceHolder Structure */ /* 0x0C */ BE(s16) mFrameMax; /* 0x0E */ BE(u16) mUpdateMaterialNum; /* 0x10 */ u8 field_0x10[0x18 - 0x10]; - /* 0x18 */ OFFSET_PTR mTableOffset; - /* 0x1C */ OFFSET_PTR mUpdateMaterialIDOffset; - /* 0x20 */ OFFSET_PTR mNameTabOffset; - /* 0x24 */ OFFSET_PTR mRValuesOffset; - /* 0x28 */ OFFSET_PTR mGValuesOffset; - /* 0x2C */ OFFSET_PTR mBValuesOffset; - /* 0x30 */ OFFSET_PTR mAValuesOffset; + /* 0x18 */ OFFSET_PTR_V0 mTableOffset; + /* 0x1C */ OFFSET_PTR_V0 mUpdateMaterialIDOffset; + /* 0x20 */ OFFSET_PTR_V0 mNameTabOffset; + /* 0x24 */ OFFSET_PTR_V0 mRValuesOffset; + /* 0x28 */ OFFSET_PTR_V0 mGValuesOffset; + /* 0x2C */ OFFSET_PTR_V0 mBValuesOffset; + /* 0x30 */ OFFSET_PTR_V0 mAValuesOffset; }; // Size = 0x34 STATIC_ASSERT(sizeof(J3DAnmColorFullData) == 0x34); @@ -431,10 +431,10 @@ struct J3DAnmTransformKeyData { /* 0x0E */ BE(u16) mSCount; /* 0x10 */ BE(u16) mRCount; /* 0x12 */ BE(u16) mTCount; - /* 0x14 */ OFFSET_PTR mJointAnimationTableOffs; - /* 0x18 */ OFFSET_PTR mSTableOffs; - /* 0x1c */ OFFSET_PTR mRTableOffs; - /* 0x20 */ OFFSET_PTR mTTableOffs; + /* 0x14 */ OFFSET_PTR_V0 mJointAnimationTableOffs; + /* 0x18 */ OFFSET_PTR_V0 mSTableOffs; + /* 0x1c */ OFFSET_PTR_V0 mRTableOffs; + /* 0x20 */ OFFSET_PTR_V0 mTTableOffs; }; /** @@ -446,8 +446,8 @@ struct J3DAnmClusterKeyData { /* 0x08 */ u8 field_0x8; /* 0x0A */ BE(s16) mFrameMax; /* 0x0C */ BE(s32) field_0xc; - /* 0x10 */ OFFSET_PTR mTableOffset; - /* 0x14 */ OFFSET_PTR mWeightOffset; + /* 0x10 */ OFFSET_PTR_V0 mTableOffset; + /* 0x14 */ OFFSET_PTR_V0 mWeightOffset; }; /** @@ -459,8 +459,8 @@ struct J3DAnmClusterFullData { /* 0x08 */ u8 field_0x8; /* 0x0A */ BE(s16) mFrameMax; /* 0x0C */ BE(s32) field_0xc; - /* 0x10 */ OFFSET_PTR mTableOffset; - /* 0x14 */ OFFSET_PTR mWeightOffset; + /* 0x10 */ OFFSET_PTR_V0 mTableOffset; + /* 0x14 */ OFFSET_PTR_V0 mWeightOffset; }; /** @@ -718,7 +718,7 @@ public: // Address to which getAnmVtxColorIndexData pointers are relative. u16* colorAddressBase[2]; - u16* offsetColorIndexAddress(u8 index, OFFSET_PTR ptr) const { + u16* offsetColorIndexAddress(u8 index, OFFSET_PTR_V0 ptr) const { return colorAddressBase[index] + ptr; } #endif @@ -994,6 +994,6 @@ public: /* 0x10 */ f32 mFrame; }; // Size: 0x14 -#undef OFFSET_PTR +#undef OFFSET_PTR_V0 #endif /* J3DANIMATION_H */ diff --git a/libs/JSystem/include/JSystem/J3DGraphAnimator/J3DCluster.h b/libs/JSystem/include/JSystem/J3DGraphAnimator/J3DCluster.h index 3cbb6f195d..2a71ada3dd 100644 --- a/libs/JSystem/include/JSystem/J3DGraphAnimator/J3DCluster.h +++ b/libs/JSystem/include/JSystem/J3DGraphAnimator/J3DCluster.h @@ -14,9 +14,9 @@ class J3DAnmCluster; class JUTNameTab; #if TARGET_PC -#define OFFSET_PTR BE(u32) +#define OFFSET_PTR_V0 BE(u32) #else -#define OFFSET_PTR void* +#define OFFSET_PTR_V0 void* #endif /** @@ -49,7 +49,7 @@ public: /* 0x00 */ BE(f32) mMaxAngle; /* 0x04 */ BE(f32) mMinAngle; - /* 0x08 */ OFFSET_PTR mClusterKey; + /* 0x08 */ OFFSET_PTR_V0 mClusterKey; /* 0x0C */ u8 mFlags; /* 0x0E */ u8 field_0xe[0x10 - 0xD]; /* 0x10 */ BE(u16) mKeyNum; @@ -57,9 +57,9 @@ public: /* 0x14 */ BE(u16) field_0x14; /* 0x16 */ BE(u16) field_0x16; #if TARGET_PC - OFFSET_PTR field_0x18; - OFFSET_PTR mClusterVertex; - OFFSET_PTR mDeformer; + OFFSET_PTR_V0 field_0x18; + OFFSET_PTR_V0 mClusterVertex; + OFFSET_PTR_V0 mDeformer; #else /* 0x18 */ u16* field_0x18; /* 0x1C */ J3DClusterVertex* mClusterVertex; @@ -82,8 +82,8 @@ public: /* 0x00 */ BE(u16) mPosNum; /* 0x02 */ BE(u16) mNrmNum; - /* 0x04 */ OFFSET_PTR field_0x4; - /* 0x08 */ OFFSET_PTR field_0x8; + /* 0x04 */ OFFSET_PTR_V0 field_0x4; + /* 0x08 */ OFFSET_PTR_V0 field_0x8; }; // Size: 0x0C /** @@ -144,14 +144,14 @@ public: /* 0x00 */ BE(u16) mNum; #if TARGET_PC - /* 0x04 */ OFFSET_PTR field_0x4; - /* 0x08 */ OFFSET_PTR field_0x8; + /* 0x04 */ OFFSET_PTR_V0 field_0x4; + /* 0x08 */ OFFSET_PTR_V0 field_0x8; #else /* 0x04 */ u16* field_0x4; /* 0x08 */ u16* field_0x8; #endif }; // Size: 0x0C -#undef OFFSET_PTR +#undef OFFSET_PTR_V0 #endif /* J3DCLUSTER_H */ diff --git a/libs/JSystem/include/JSystem/J3DGraphBase/J3DSys.h b/libs/JSystem/include/JSystem/J3DGraphBase/J3DSys.h index 9c806c92ba..b3c4f1eb16 100644 --- a/libs/JSystem/include/JSystem/J3DGraphBase/J3DSys.h +++ b/libs/JSystem/include/JSystem/J3DGraphBase/J3DSys.h @@ -150,13 +150,13 @@ struct J3DSys { void setModelDrawMtx(Mtx* pMtxArr) { J3D_ASSERT_NULLPTR(230, pMtxArr); mModelDrawMtx = pMtxArr; - GXSETARRAY(GX_POS_MTX_ARRAY, mModelDrawMtx, sizeof(*mModelDrawMtx), sizeof(*mModelDrawMtx)); + GXSETARRAY(GX_POS_MTX_ARRAY, mModelDrawMtx, 10 * sizeof(Mtx), sizeof(*mModelDrawMtx), true); } void setModelNrmMtx(Mtx33* pMtxArr) { J3D_ASSERT_NULLPTR(241, pMtxArr); mModelNrmMtx = pMtxArr; - GXSETARRAY(GX_NRM_MTX_ARRAY, mModelNrmMtx, sizeof(*mModelNrmMtx), sizeof(*mModelNrmMtx)); + GXSETARRAY(GX_NRM_MTX_ARRAY, mModelNrmMtx, 10 * sizeof(Mtx33), sizeof(*mModelNrmMtx), true); } void* getVtxPos() { return mVtxPos; } diff --git a/libs/JSystem/include/JSystem/J3DGraphLoader/J3DClusterLoader.h b/libs/JSystem/include/JSystem/J3DGraphLoader/J3DClusterLoader.h index 8fa2681f35..2899065150 100644 --- a/libs/JSystem/include/JSystem/J3DGraphLoader/J3DClusterLoader.h +++ b/libs/JSystem/include/JSystem/J3DGraphLoader/J3DClusterLoader.h @@ -7,9 +7,9 @@ #include "dusk/endian.h" #if TARGET_PC -#define OFFSET_PTR BE(u32) +#define OFFSET_PTR_V0 BE(u32) #else -#define OFFSET_PTR void* +#define OFFSET_PTR_V0 void* #endif /** @@ -31,13 +31,13 @@ public: /* 0x0C */ BE(u16) mClusterVertexNum; /* 0x0E */ BE(u16) mVtxPosNum; /* 0x10 */ BE(u16) mVtxNrmNum; - /* 0x14 */ OFFSET_PTR mClusterPointer; - /* 0x18 */ OFFSET_PTR mClusterKeyPointer; - /* 0x1C */ OFFSET_PTR mClusterVertex; - /* 0x20 */ OFFSET_PTR mVtxPos; - /* 0x24 */ OFFSET_PTR mVtxNrm; - /* 0x28 */ OFFSET_PTR mClusterName; - /* 0x2C */ OFFSET_PTR mClusterKeyName; + /* 0x14 */ OFFSET_PTR_V0 mClusterPointer; + /* 0x18 */ OFFSET_PTR_V0 mClusterKeyPointer; + /* 0x1C */ OFFSET_PTR_V0 mClusterVertex; + /* 0x20 */ OFFSET_PTR_V0 mVtxPos; + /* 0x24 */ OFFSET_PTR_V0 mVtxNrm; + /* 0x28 */ OFFSET_PTR_V0 mClusterName; + /* 0x2C */ OFFSET_PTR_V0 mClusterKeyName; }; /** @@ -67,6 +67,6 @@ public: /* 0x04 */ J3DDeformData* mpDeformData; }; -#undef OFFSET_PTR +#undef OFFSET_PTR_V0 #endif /* J3DCLUSTERLOADER_H */ diff --git a/libs/JSystem/include/JSystem/J3DGraphLoader/J3DMaterialFactory_v21.h b/libs/JSystem/include/JSystem/J3DGraphLoader/J3DMaterialFactory_v21.h index 6b70201532..93d4fb9b7d 100644 --- a/libs/JSystem/include/JSystem/J3DGraphLoader/J3DMaterialFactory_v21.h +++ b/libs/JSystem/include/JSystem/J3DGraphLoader/J3DMaterialFactory_v21.h @@ -82,7 +82,7 @@ public: /* 0x00 */ u16 mMaterialNum; /* 0x04 */ J3DMaterialInitData_v21* mpMaterialInitData; - /* 0x08 */ u16* mpMaterialID; + /* 0x08 */ BE(u16)* mpMaterialID; /* 0x0C */ GXColor* mpMatColor; /* 0x10 */ u8* mpColorChanNum; /* 0x14 */ J3DColorChanInfo* mpColorChanInfo; @@ -91,10 +91,10 @@ public: /* 0x20 */ J3DTexCoord2Info* mpTexCoord2Info; /* 0x24 */ J3DTexMtxInfo* mpTexMtxInfo; /* 0x28 */ J3DTexMtxInfo* field_0x28; - /* 0x2C */ u16* mpTexNo; - /* 0x30 */ GXCullMode* mpCullMode; + /* 0x2C */ BE(u16)* mpTexNo; + /* 0x30 */ BE(GXCullMode)* mpCullMode; /* 0x34 */ J3DTevOrderInfo* mpTevOrderInfo; - /* 0x38 */ GXColorS10* mpTevColor; + /* 0x38 */ BE(GXColorS10)* mpTevColor; /* 0x3C */ GXColor* mpTevKColor; /* 0x40 */ u8* mpTevStageNum; /* 0x44 */ J3DTevStageInfo* mpTevStageInfo; diff --git a/libs/JSystem/include/JSystem/JAWExtSystem/JAWGraphContext.h b/libs/JSystem/include/JSystem/JAWExtSystem/JAWGraphContext.h index 2719500e1c..99fac05626 100644 --- a/libs/JSystem/include/JSystem/JAWExtSystem/JAWGraphContext.h +++ b/libs/JSystem/include/JSystem/JAWExtSystem/JAWGraphContext.h @@ -24,6 +24,15 @@ public: void setGXforPrint(); void setGXforDraw(); + void color(const JUtility::TColor& color0, const JUtility::TColor& color1) { + color(color0, color1, color0, color1); + } + + void lineWidth(u8 width) { + field_0x16 = width; + GXSetLineWidth(field_0x16, GX_TO_ZERO); + } + /* 0x00 */ J2DPrint* field_0x0; /* 0x04 */ JUtility::TColor field_0x4; /* 0x08 */ JUtility::TColor field_0x8; diff --git a/libs/JSystem/include/JSystem/JAWExtSystem/JAWWindow.h b/libs/JSystem/include/JSystem/JAWExtSystem/JAWWindow.h index 7a570565cd..7ada3a548e 100644 --- a/libs/JSystem/include/JSystem/JAWExtSystem/JAWWindow.h +++ b/libs/JSystem/include/JSystem/JAWExtSystem/JAWWindow.h @@ -16,8 +16,8 @@ public: y = i_y; } - /* 0x00*/ int x; - /* 0x04*/ int y; + /* 0x00 */ int x; + /* 0x04 */ int y; }; class JAWWindow { @@ -29,9 +29,9 @@ public: virtual void drawSelf(f32, f32); virtual void drawSelf(f32, f32, Mtx*); - /* 0x0FC */ JAWGraphContext field_0xfc; + /* 0x0FC */ JAWGraphContext m_graf; /* 0x118 */ JAWWindow* m_pParent; - /* 0x11C */ JUTPoint field_0x11c; + /* 0x11C */ JUTPoint m_point; }; class TJ2DWindowDraw : public J2DWindow { @@ -94,21 +94,29 @@ public: static JUtility::TColor convJudaColor(u16); void padProc(const JUTGamePad&); + void setWindowColor(const JUtility::TColor& color) { + setWindowColor(color, color, color, color); + } + + void setWindowColor(u8 r, u8 g, u8 b, u8 a) { + setWindowColor(JUtility::TColor(r, g, b, a)); + } + /* 0x004 */ Mtx mMatrix; /* 0x034 */ u8 field_0x34[0x38 - 0x34]; - /* 0x038 */ TJ2DWindowDraw field_0x38; - /* 0x180 */ J2DTextBox field_0x180; - /* 0x2B0 */ TWindowText field_0x2b0; - /* 0x3D8 */ JUtility::TColor field_0x3d8; - /* 0x3DC */ JUtility::TColor field_0x3dc; - /* 0x3E0 */ JUtility::TColor field_0x3e0; - /* 0x3E4 */ JUtility::TColor field_0x3e4; + /* 0x038 */ TJ2DWindowDraw m_drawWindow; + /* 0x180 */ J2DTextBox m_titleText; + /* 0x2B0 */ TWindowText m_windowText; + /* 0x3D8 */ JUtility::TColor m_windowColor0; + /* 0x3DC */ JUtility::TColor m_windowColor1; + /* 0x3E0 */ JUtility::TColor m_windowColor2; + /* 0x3E4 */ JUtility::TColor m_windowColor3; /* 0x3E8 */ int field_0x3e8; - /* 0x3EC */ u8 field_0x3ec; + /* 0x3EC */ u8 m_isInit; void setMatrix(Mtx mtx) { MTXCopy(mtx, mMatrix); } - void setAlpha(u8 alpha) { field_0x38.setAlpha(alpha); } - void draw(int x, int y, const J2DGrafContext* p_grafCtx) { field_0x38.drawPane(x, y, p_grafCtx); } + void setAlpha(u8 alpha) { m_drawWindow.setAlpha(alpha); } + void draw(int x, int y, const J2DGrafContext* p_grafCtx) { m_drawWindow.drawPane(x, y, p_grafCtx); } }; #endif /* JAWWINDOW_H */ diff --git a/libs/JSystem/include/JSystem/JAudio2/JAISeqDataMgr.h b/libs/JSystem/include/JSystem/JAudio2/JAISeqDataMgr.h index 510f1f4905..a517a58c16 100644 --- a/libs/JSystem/include/JSystem/JAudio2/JAISeqDataMgr.h +++ b/libs/JSystem/include/JSystem/JAudio2/JAISeqDataMgr.h @@ -10,17 +10,17 @@ */ struct JAISeqData { JAISeqData(const void* param_0, u32 param_1) { - field_0x0 = (void*)param_0; - field_0x4 = param_1; + mBase = (void*)param_0; + mOffset = param_1; } void set(const void* param_0, u32 param_1) { - field_0x0 = (void*)param_0; - field_0x4 = param_1; + mBase = (void*)param_0; + mOffset = param_1; } - /* 0x00 */ void* field_0x0; - /* 0x04 */ u32 field_0x4; + /* 0x00 */ void* mBase; + /* 0x04 */ u32 mOffset; }; /** @@ -29,10 +29,10 @@ struct JAISeqData { */ struct JAISeqDataRegion { bool intersects(const JAISeqData& seqData) const { - if ((uintptr_t)addr + size < (uintptr_t)seqData.field_0x0) { + if ((uintptr_t)addr + size < (uintptr_t)seqData.mBase) { return false; } - if ((uintptr_t)seqData.field_0x0 + seqData.field_0x4 < (uintptr_t)addr) { + if ((uintptr_t)seqData.mBase + seqData.mOffset < (uintptr_t)addr) { return false; } return true; diff --git a/libs/JSystem/include/JSystem/JAudio2/JAISound.h b/libs/JSystem/include/JSystem/JAudio2/JAISound.h index 5e1cd40b4b..e96053fc9f 100644 --- a/libs/JSystem/include/JSystem/JAudio2/JAISound.h +++ b/libs/JSystem/include/JSystem/JAudio2/JAISound.h @@ -5,6 +5,7 @@ #include "JSystem/JAudio2/JAIAudible.h" #include "JSystem/JUtility/JUTAssert.h" #include "global.h" +#include "dusk/endian.h" #include class JAISound; @@ -49,22 +50,28 @@ public: JAISoundID(const JAISoundID& other) { id_.composite_ = other.id_.composite_; }; + JAISoundID(unsigned int sectionID, unsigned int groupID, unsigned int waveID) { + id_.info.type.parts.sectionID = sectionID; + id_.info.type.parts.groupID = groupID; + id_.info.waveID = waveID; + } + JAISoundID() {} bool isAnonymous() const { return id_.composite_ == -1; } void setAnonymous() { id_.composite_ = -1; } union { - u32 composite_; + BE(u32) composite_; struct { union { - u16 value; + BE(u16) value; struct { u8 sectionID; u8 groupID; } parts; } type; - u16 waveID; + BE(u16) waveID; } info; } id_; }; @@ -322,6 +329,8 @@ public: status_.field_0x0.flags.paused = param_0; } + bool isPaused() const { return status_.field_0x0.flags.paused; } + void updateLifeTime(u32 lifeTime) { if (lifeTime > lifeTime_) { lifeTime_ = lifeTime; diff --git a/libs/JSystem/include/JSystem/JAudio2/JASAramStream.h b/libs/JSystem/include/JSystem/JAudio2/JASAramStream.h index 17d4c6f521..dcfcebd30a 100644 --- a/libs/JSystem/include/JSystem/JAudio2/JASAramStream.h +++ b/libs/JSystem/include/JSystem/JAudio2/JASAramStream.h @@ -4,6 +4,7 @@ #include "JSystem/JAudio2/JASTaskThread.h" #include "JSystem/JUtility/JUTAssert.h" #include +#include "dusk/endian.h" class JASChannel; @@ -11,12 +12,17 @@ namespace JASDsp { struct TChannel; } +#define STREAM_FORMAT_ADPCM4 0 +#define STREAM_FORMAT_PCM16 1 + /** * @ingroup jsystem-jaudio - * + * Plays streamed music from DVD .ast files. */ class JASAramStream { public: + static const int CHANNEL_MAX = 6; + typedef void (*StreamCallback)(u32, JASAramStream*, void*); enum CallbackType { @@ -27,34 +33,40 @@ public: // Used internally for passing data to task functions struct TaskData { /* 0x0 */ JASAramStream* stream; - /* 0x4 */ u32 field_0x4; - /* 0x8 */ int field_0x8; + /* 0x4 */ u32 param0; + /* 0x8 */ int param1; }; struct Header { - /* 0x00 */ u32 tag; + /* 0x00 */ BE(u32) tag; // 'STRM' +#if TARGET_PC + /* 0x04 */ BE(u32) soundBlockSize; + /* 0x08 */ BE(u16) format; + /* 0x0A */ BE(u16) bits; +#else /* 0x04 */ u8 field_0x4[5]; /* 0x09 */ u8 format; /* 0x0A */ u8 bits; - /* 0x0C */ u16 channels; - /* 0x0E */ u16 loop; - /* 0x10 */ int field_0x10; - /* 0x14 */ u8 field_0x14[4]; - /* 0x18 */ int loop_start; - /* 0x1C */ int loop_end; - /* 0x20 */ u32 block_size; - /* 0x24 */ u8 field_0x24[4]; - /* 0x28 */ u8 field_0x28; - /* 0x29 */ u8 field_0x29[0x17]; +#endif + /* 0x0C */ BE(u16) channels; + /* 0x0E */ BE(u16) loop; + /* 0x10 */ BE(int) mSampleRate; + /* 0x14 */ BE(u32) mSampleCount; // unused + /* 0x18 */ BE(int) loop_start; + /* 0x1C */ BE(int) loop_end; + /* 0x20 */ BE(u32) block_size; + /* 0x24 */ u8 _unused2[4]; + /* 0x28 */ u8 mVolume; + /* 0x29 */ u8 _unused3[0x17]; }; // Size: 0x40 struct BlockHeader { - /* 0x00 */ u32 tag; - /* 0x04 */ u32 field_0x4; + /* 0x00 */ BE(u32) tag; // 'BLCK' + /* 0x04 */ BE(u32) mSize; /* 0x08 */ struct { - s16 field_0x0; - s16 field_0x2; - } field_0x8[6]; + BE(s16) mpLast; + BE(s16) mpPenult; + } mAdpcmContinuationData[CHANNEL_MAX]; }; // Size: 0x20 static void initSystem(u32, u32); @@ -65,6 +77,10 @@ public: bool stop(u16); bool pause(bool); bool cancel(); + + /** + * Calculate the amount of (decoded) audio samples in a single block of streamed audio. + */ u32 getBlockSamples() const; static void headerLoadTask(void*); static void firstLoadTask(void*); @@ -128,46 +144,103 @@ public: static u32 getBlockSize() { return sBlockSize; } - static const int CHANNEL_MAX = 6; + /** + * Queue used to send specific commands that will be processed on the audio thread. + * These commands are sent from the main thread. + */ + /* 0x000 */ OSMessageQueue mMainCommandQueue; - /* 0x000 */ OSMessageQueue field_0x000; - /* 0x020 */ OSMessageQueue field_0x020; - /* 0x040 */ void* field_0x040[16]; - /* 0x080 */ void* field_0x080[4]; + /** + * Queue used to send specific commands that will be processed on the audio thread. + * These commands are sent from the load (DVD) thread. + */ + /* 0x020 */ OSMessageQueue mLoadCommandQueue; + + /** + * Backing message storage for mMainCommandQueue. + */ + /* 0x040 */ void* mMainCommandQueueArray[16]; + + /** + * Backing message storage for mLoadCommandQueue. + */ + /* 0x080 */ void* mLoadCommandQueueArray[4]; /* 0x090 */ JASChannel* mChannels[CHANNEL_MAX]; - /* 0x0A8 */ JASChannel* field_0x0a8; - /* 0x0AC */ bool field_0x0ac; - /* 0x0AD */ bool field_0x0ad; - /* 0x0AE */ u8 field_0x0ae; + + /** + * The first audio channel initialized among mChannels. + * Used for the majority of bookkeeping, other channels replicate its state. + */ + /* 0x0A8 */ JASChannel* mPrimaryChannel; + + /** + * If true, stream has finished preparing (reading headers and initial blocks), + * and is ready to play. + */ + /* 0x0AC */ bool mPrepareFinished; + /* 0x0AD */ bool mLoopEndLoaded; + + /** + * Bitflag containing pause reasons/state for the stream. + */ + /* 0x0AE */ u8 mPauseFlags; /* 0x0B0 */ int field_0x0b0; - /* 0x0B4 */ int field_0x0b4; - /* 0x0B8 */ u32 field_0x0b8; + + /** + * (adjusted) value of mSamplesLeft on the primary channel last subframe. + * Used to calculate how many samples have been read and determine when the DSP looped. + */ + /* 0x0B4 */ int mLastSamplesLeft; + + /** + * How many (decoded) samples the DSP has read so far. + */ + /* 0x0B8 */ u32 mReadSample; /* 0x0BC */ int field_0x0bc; - /* 0x0C0 */ bool field_0x0c0; + + /** + * If true, the current end (of loop, or just finish) is very close. + * Loop start/end positions are modified while this is set to account for this. + */ + /* 0x0C0 */ bool mEndSetup; /* 0x0C4 */ volatile u32 field_0x0c4; /* 0x0C8 */ volatile f32 field_0x0c8; /* 0x0CC */ DVDFileInfo mDvdFileInfo; - /* 0x108 */ u32 field_0x108; - /* 0x10C */ int field_0x10c; + /* 0x108 */ u32 mRingEndIndex; + + /** + * Index into the ARAM ring buffer that is currently being loaded. + * Wrapped around when incremented. + */ + /* 0x10C */ int mBlockRingIndex; + + /** + * Block currently being loaded. + */ /* 0x110 */ u32 mBlock; - /* 0x114 */ u8 field_0x114; - /* 0x118 */ u32 field_0x118; - /* 0x11C */ int field_0x11c; - /* 0x120 */ int field_0x120; - /* 0x124 */ int field_0x124; - /* 0x128 */ u16 field_0x128; - /* 0x12C */ int field_0x12c; - /* 0x130 */ s16 field_0x130[CHANNEL_MAX]; - /* 0x13C */ s16 field_0x13c[CHANNEL_MAX]; - /* 0x148 */ int field_0x148; - /* 0x14C */ u32 field_0x14c; + /* 0x114 */ u8 mIsCancelled; + /* 0x118 */ u32 mPendingLoadTasks; + /* 0x11C */ int mUpdateSamplesLeft; + /* 0x120 */ int mUpdateLoopStartSample; + /* 0x124 */ int mUpdateEndSample; + /* 0x128 */ u16 mUpdateLoopFlag; + + /** + * Bitflags updated in the play callback to track what data needs to be synchronized + * between all channels. + */ + /* 0x12C */ int mChannelUpdateFlags; + /* 0x130 */ s16 mpLasts[CHANNEL_MAX]; + /* 0x13C */ s16 mpPenults[CHANNEL_MAX]; + /* 0x148 */ int mAramAddress; + /* 0x14C */ u32 mAramSize; /* 0x150 */ StreamCallback mCallback; /* 0x154 */ void* mCallbackData; - /* 0x158 */ u16 field_0x158; + /* 0x158 */ u16 mFormat; /* 0x15A */ u16 mChannelNum; /* 0x15C */ u32 mBufCount; - /* 0x160 */ u32 field_0x160; - /* 0x164 */ u32 field_0x164; + /* 0x160 */ u32 mAramBlocksPerChannel; + /* 0x164 */ u32 mSampleRate; /* 0x168 */ bool mLoop; /* 0x16C */ u32 mLoopStart; /* 0x170 */ u32 mLoopEnd; @@ -177,11 +250,29 @@ public: /* 0x194 */ f32 mChannelPan[CHANNEL_MAX]; /* 0x1AC */ f32 mChannelFxMix[CHANNEL_MAX]; /* 0x1C4 */ f32 mChannelDolby[CHANNEL_MAX]; - /* 0x1DC */ u16 field_0x1dc[CHANNEL_MAX]; + /* 0x1DC */ u16 mMixConfig[CHANNEL_MAX]; + /** + * Thread that will be sent DVD load commands. + * This is the JASDvd thread in practice. + */ static JASTaskThread* sLoadThread; + + /** + * Buffer used to read DVD data. Can store the size of an entire streamed audio block. + */ static u8* sReadBuffer; + + /** + * Block size used by all streamed music in the game. + * This is 0x2760 for TP. + */ static u32 sBlockSize; + + /** + * Maximum amount of output channels for all streamed music in the game. + * This is 2 for TP (stereo). + */ static u32 sChannelMax; }; diff --git a/libs/JSystem/include/JSystem/JAudio2/JASAudioThread.h b/libs/JSystem/include/JSystem/JAudio2/JASAudioThread.h index 6be7d07000..dd9fed2183 100644 --- a/libs/JSystem/include/JSystem/JAudio2/JASAudioThread.h +++ b/libs/JSystem/include/JSystem/JAudio2/JASAudioThread.h @@ -32,11 +32,6 @@ struct JASAudioThread : public JKRThread, public JASGlobalInstance mInstOffset[0x80]; /* 0x204 */ u8 field_0x204[0x190]; /* 0x394 */ TOffset mPercOffset[12]; diff --git a/libs/JSystem/include/JSystem/JAudio2/JASCalc.h b/libs/JSystem/include/JSystem/JAudio2/JASCalc.h index bb8054675f..35b8fd5516 100644 --- a/libs/JSystem/include/JSystem/JAudio2/JASCalc.h +++ b/libs/JSystem/include/JSystem/JAudio2/JASCalc.h @@ -33,7 +33,11 @@ struct JASCalc { f32 fake2(s32 x); f32 fake3(); +#if AVOID_UB + static const s16 CUTOFF_TO_IIR_TABLE[129][4]; +#else static const s16 CUTOFF_TO_IIR_TABLE[128][4]; +#endif }; template diff --git a/libs/JSystem/include/JSystem/JAudio2/JASChannel.h b/libs/JSystem/include/JSystem/JAudio2/JASChannel.h index 042e3343cd..ce9b0b20de 100644 --- a/libs/JSystem/include/JSystem/JAudio2/JASChannel.h +++ b/libs/JSystem/include/JSystem/JAudio2/JASChannel.h @@ -6,6 +6,7 @@ #include "JSystem/JAudio2/JASOscillator.h" #include "JSystem/JAudio2/JASSoundParams.h" #include "JSystem/JAudio2/JASWaveInfo.h" +#include "JSystem/JAudio2/JASDSPInterface.h" #include struct JASDSPChannel; @@ -45,6 +46,9 @@ public: /* 0x14 */ f32 mDolby; }; +#define CHANNEL_WAVE 0 +#define CHANNEL_OSCILLATOR 2 + /** * @ingroup jsystem-jaudio * @@ -52,7 +56,7 @@ public: class JASChannel : public JASPoolAllocObject_MultiThreaded { public: typedef void (*Callback)(u32, JASChannel*, JASDsp::TChannel*, void*); - static const int BUSOUT_CPUCH = 6; + static const int BUSOUT_CPUCH = DSP_OUTPUT_CHANNELS; static const int OSC_NUM = 2; enum CallbackType { @@ -75,7 +79,7 @@ public: }; union MixConfig { - u16 whole; + BE(u16) whole; struct { u8 upper; u8 lower0 : 4; @@ -153,10 +157,14 @@ public: /* 0xD4 */ u32 mKeySweepCount; /* 0xD8 */ u32 mSkipSamples; struct { - u32 field_0x0; - JASWaveInfo field_0x4; + u32 mChannelType; // CHANNEL_WAVE or CHANNEL_OSCILLATOR + JASWaveInfo mWaveInfo; } field_0xdc; - intptr_t field_0x104; + union { + u32 mWaveAramAddress; + u32 mOscillatorSomething; + u32 field_0x104; + }; static OSMessageQueue sBankDisposeMsgQ; static OSMessage sBankDisposeMsg[16]; diff --git a/libs/JSystem/include/JSystem/JAudio2/JASCriticalSection.h b/libs/JSystem/include/JSystem/JAudio2/JASCriticalSection.h index 53faae80fe..ed4cb023ed 100644 --- a/libs/JSystem/include/JSystem/JAudio2/JASCriticalSection.h +++ b/libs/JSystem/include/JSystem/JAudio2/JASCriticalSection.h @@ -8,12 +8,18 @@ * */ class JASCriticalSection { +public: +#if TARGET_PC + JASCriticalSection(); + ~JASCriticalSection(); +#else public: JASCriticalSection() { mInterruptState = OSDisableInterrupts(); }; ~JASCriticalSection() { OSRestoreInterrupts(mInterruptState); }; private: u32 mInterruptState; +#endif }; #endif /* JASCRITICALSECTION_H */ diff --git a/libs/JSystem/include/JSystem/JAudio2/JASDSPChannel.h b/libs/JSystem/include/JSystem/JAudio2/JASDSPChannel.h index f843562f37..8204ab0838 100644 --- a/libs/JSystem/include/JSystem/JAudio2/JASDSPChannel.h +++ b/libs/JSystem/include/JSystem/JAudio2/JASDSPChannel.h @@ -5,9 +5,14 @@ /** * @ingroup jsystem-jaudio - * + * Responsible for allocating and prioritizing the available hardware DSP channels. */ struct JASDSPChannel { + /** + * Callback used to update DSP channel information on a regular basis. + * Parameters are a CallbackType, hardware channel, and specified user data. + * Return -1 to immediately abort playback. + */ typedef s32 (*Callback)(u32, JASDsp::TChannel*, void*); enum Status { @@ -17,9 +22,24 @@ struct JASDSPChannel { }; enum CallbackType { + /** + * Fired on a regular basis during play to update parameters. + */ /* 0 */ CB_PLAY, + + /** + * Fired once, when the channel starts playing. + */ /* 1 */ CB_START, + + /** + * Fired once, when the channel naturally finishes playing. + */ /* 2 */ CB_STOP, + + /** + * Fired once, if the channel is abruptly stopped due to an error or prioritization. + */ /* 3 */ CB_DROP, }; @@ -46,9 +66,13 @@ struct JASDSPChannel { static JASDSPChannel* sDspChannels; /* 0x00 */ s32 mStatus; + + /** + * Priority of this DSP channel. Used to + */ /* 0x04 */ s16 mPriority; /* 0x08 */ u32 mFlags; - /* 0x0C */ u32 field_0xc; + /* 0x0C */ u32 mUpdateCounter; /* 0x10 */ Callback mCallback; /* 0x14 */ void* mCallbackData; /* 0x18 */ JASDsp::TChannel* mChannel; diff --git a/libs/JSystem/include/JSystem/JAudio2/JASDSPInterface.h b/libs/JSystem/include/JSystem/JAudio2/JASDSPInterface.h index 44f2805bfe..a9a9b2d11e 100644 --- a/libs/JSystem/include/JSystem/JAudio2/JASDSPInterface.h +++ b/libs/JSystem/include/JSystem/JAudio2/JASDSPInterface.h @@ -4,6 +4,21 @@ #include #include +/** + * Amount of separate audio channels (i.e. individual playbacks, voices) the DSP can mix at once. + */ +#define DSP_CHANNELS 64 + +/** + * Amount of audio channels the DSP can calculate outputs for. + */ +#define DSP_OUTPUT_CHANNELS 6 // Presumed 5.1 surround + +/** + * Amount of audio samples rendered by the DSP in a single sub frame. + */ +#define DSP_SUBFRAME_SIZE 0x50 + struct JASWaveInfo; namespace JASDsp { @@ -30,6 +45,24 @@ namespace JASDsp { u16 field_0x10[8]; } FxBuf; + struct OutputChannelConfig { + u16 mBusConnect; + u16 mTargetVolume; + u16 mCurrentVolume; + + /** + * Gets upper 8 bits cleared when audio volume is changed mid-playback. + * Presumed to be some kind of progress used by the DSP to calculate position between + * mTargetVolume and mCurrentVolume. + */ + u16 mVolumeProgress; + }; + + /** + * DSP memory for each playback channel ("voice"). + * The DSP can read and write this memory. It is used as configuration, feedback, + * and working memory. + */ struct TChannel { void init(); void playStart(); @@ -37,67 +70,115 @@ namespace JASDsp { void replyFinishRequest(); void forceStop(); bool isActive() const; + + /** + * Check whether the DSP has finished playing this channel. + */ bool isFinish() const; void setWaveInfo(JASWaveInfo const&, u32, u32); void setOscInfo(u32); void initAutoMixer(); void setAutoMixer(u16, u8, u8, u8, u8); void setPitch(u16); - void setMixerInitVolume(u8, s16); - void setMixerVolume(u8, s16); + void setMixerInitVolume(u8 outputChannel, s16 volume); + void setMixerVolume(u8 outputChannel, s16 volume); void setPauseFlag(u8); + + /** + * Flushes backing memory of channel out of the data cache. + */ void flush(); void initFilter(); void setFilterMode(u16); void setIIRFilterParam(s16*); void setFIR8FilterParam(s16*); void setDistFilter(s16); - void setBusConnect(u8, u8); + void setBusConnect(u8 outputChannel, u8 param_1); + /** + * Whether this channel is currently actively playing audio. + */ /* 0x000 */ u16 mIsActive; + + /** + * Written by DSP to indicate playback has finished. + */ /* 0x002 */ u16 mIsFinished; + + /** + * Pitch shift via changing playback speed. + */ /* 0x004 */ u16 mPitch; - /* 0x006 */ short field_0x006; - /* 0x008 */ u16 field_0x008; - /* 0x00A */ u8 field_0x00A[0x00C - 0x00A]; + /* 0x006 */ short _unused1; + + /** + * Set to 1 when playback starts, cleared by DSP later, + * checked by JASAramStream before actually doing processing. + * Presumably to instruct DSP to clear state? + * (Corroborated by fields JASAramStream checks never being cleared explicitly by CPU.) + */ + /* 0x008 */ u16 mResetFlag; + /* 0x00A */ u8 _unused2[0x00C - 0x00A]; /* 0x00C */ s16 mPauseFlag; - /* 0x00E */ short field_0x00E; - /* 0x010 */ u16 field_0x010[1][4]; // array size unknown - /* 0x018 */ u8 field_0x018[0x050 - 0x018]; - /* 0x050 */ u16 field_0x050; - /* 0x052 */ u16 field_0x052; - /* 0x054 */ u16 field_0x054; - /* 0x056 */ u16 field_0x056; - /* 0x058 */ u16 field_0x058; - /* 0x05A */ u8 field_0x05A[0x060 - 0x05A]; - /* 0x060 */ short field_0x060; - /* 0x062 */ u8 field_0x062[0x064 - 0x062]; - /* 0x064 */ u16 field_0x064; - /* 0x066 */ short field_0x066; - /* 0x068 */ int field_0x068; - /* 0x06C */ u8 field_0x06C[0x070 - 0x06C]; - /* 0x070 */ int field_0x070; - /* 0x074 */ int field_0x074; - /* 0x078 */ short field_0x078[4]; - /* 0x080 */ short field_0x080[20]; - /* 0x0A8 */ short field_0x0a8[4]; - /* 0x0B0 */ u16 field_0x0b0[16]; - /* 0x0D0 */ u8 field_0x0D0[0x100 - 0x0D0]; - /* 0x100 */ u16 field_0x100; - /* 0x102 */ u16 field_0x102; - /* 0x104 */ s16 field_0x104; - /* 0x106 */ s16 field_0x106; + /* 0x00E */ short _unused3; + /* 0x010 */ OutputChannelConfig mOutputChannels[DSP_OUTPUT_CHANNELS]; + /* 0x040 */ u8 _unused4[0x050 - 0x040]; + /* 0x050 */ u16 mAutoMixerPanDolby; // pan is upper 8 bits, dolby lower 8. + /* 0x052 */ u16 mAutoMixerFxMix; + /* 0x054 */ u16 mAutoMixerInitVolume; + /* 0x056 */ u16 mAutoMixerVolume; + /* 0x058 */ u16 mAutoMixerBeenSet; + /* 0x05A */ u8 _unused5[0x060 - 0x05A]; + /* 0x060 */ short field_0x060; // Only cleared to zero, presumed used by DSP. + /* 0x062 */ u8 _unused6[0x064 - 0x062]; + + /** + * Samples per ADPCM frame for ADPCM audio. Seems just set to 1 for PCM formats. + * Name could use improvement, probably? + */ + /* 0x064 */ u16 mSamplesPerBlock; + /* 0x066 */ short field_0x066; // Only cleared to zero, presumed used by DSP. + /* 0x068 */ u32 mSamplePosition; // Only ever initialized by code, name is guess. + /* 0x06C */ u8 _unused7[0x070 - 0x06C]; + + /** + * Current audio read position in ARAM. Updated by DSP. + */ + /* 0x070 */ u32 mAramStreamPosition; + + /** + * Amount of (decoded) audio samples left until the end of the buffer. + * Gets written by DSP, but also CPU. + */ + /* 0x074 */ u32 mSamplesLeft; // Never directly cleared to zero. Seems sus. Cleared by DSP? + /* 0x078 */ short field_0x078[4]; // Only cleared to zero, presumed used by DSP. + /* 0x080 */ short field_0x080[20]; // Only cleared to zero, presumed used by DSP. + /* 0x0A8 */ short field_0x0a8[4]; // Only cleared to zero, presumed used by DSP. + /* 0x0B0 */ u16 field_0x0b0[16]; // Only cleared to zero, presumed used by DSP. + /* 0x0D0 */ u8 _unused8[0x100 - 0x0D0]; + /* 0x100 */ u16 mBytesPerBlock; + /* 0x102 */ u16 mLoopFlag; + + /** + * Used for decoding ADPCM data around loop edges. + */ + /* 0x104 */ s16 mpLast; + + /** + * Used for decoding ADPCM data around loop edges. + */ + /* 0x106 */ s16 mpPenult; /* 0x108 */ u16 mFilterMode; /* 0x10A */ u16 mForcedStop; /* 0x10C */ int field_0x10c; - /* 0x110 */ u32 field_0x110; - /* 0x114 */ u32 field_0x114; - /* 0x118 */ u32 field_0x118; - /* 0x11C */ int field_0x11c; + /* 0x110 */ u32 mLoopStartSample; + /* 0x114 */ u32 mEndSample; + /* 0x118 */ u32 mWaveAramAddress; + /* 0x11C */ int mSampleCount; /* 0x120 */ s16 fir_filter_params[8]; - /* 0x130 */ u8 field_0x130[0x148 - 0x130]; + /* 0x130 */ u8 _unused9[0x148 - 0x130]; /* 0x148 */ s16 iir_filter_params[8]; - /* 0x158 */ u8 field_0x158[0x180 - 0x158]; + /* 0x158 */ u8 _unused10[0x180 - 0x158]; }; void boot(void (*)(void*)); diff --git a/libs/JSystem/include/JSystem/JAudio2/JASDriverIF.h b/libs/JSystem/include/JSystem/JAudio2/JASDriverIF.h index 319c826345..5cddc38596 100644 --- a/libs/JSystem/include/JSystem/JAudio2/JASDriverIF.h +++ b/libs/JSystem/include/JSystem/JAudio2/JASDriverIF.h @@ -3,6 +3,10 @@ #include "JSystem/JAudio2/JASCallback.h" +#define JAS_OUTPUT_MONO OS_SOUND_MODE_MONO +#define JAS_OUTPUT_STEREO OS_SOUND_MODE_STEREO +#define JAS_OUTPUT_SURROUND 2 + typedef s32 (*DriverCallback)(void*); namespace JASDriver { diff --git a/libs/JSystem/include/JSystem/JAudio2/JASHeapCtrl.h b/libs/JSystem/include/JSystem/JAudio2/JASHeapCtrl.h index 70f63bc889..7a3ae12470 100644 --- a/libs/JSystem/include/JSystem/JAudio2/JASHeapCtrl.h +++ b/libs/JSystem/include/JSystem/JAudio2/JASHeapCtrl.h @@ -33,6 +33,9 @@ public: bool isAllocated() const { return mBase; } u32 getSize() const { return mSize; } + JSUTree* getFirstChild() { return mTree.getFirstChild(); } + JSUTree* getEndChild() { return mTree.getEndChild(); } + /* 0x00 */ JSUTree mTree; /* 0x1C */ OSMutex mMutex; /* 0x34 */ JASDisposer* mDisposer; @@ -352,6 +355,28 @@ template JASMemPool JASPoolAllocObject::memPool_; template class JASMemPool_MultiThreaded : public JASGenericMemPool { public: +#if TARGET_PC + OSMutex mutex; + + JASMemPool_MultiThreaded() { + OSInitMutex(&mutex); + } + + void newMemPool(int param_0) { + JASThreadingModel::ObjectLevelLockable::Lock lock(mutex); + JASGenericMemPool::newMemPool(sizeof(T), param_0); + } + + void* alloc(size_t count) { + JASThreadingModel::ObjectLevelLockable::Lock lock(mutex); + return JASGenericMemPool::alloc(count); + } + + void free(void* ptr, u32 param_1) { + JASThreadingModel::ObjectLevelLockable::Lock lock(mutex); + JASGenericMemPool::free(ptr, param_1); + } +#else void newMemPool(int param_0) { typename JASThreadingModel::InterruptsDisable >::Lock lock(*this); JASGenericMemPool::newMemPool(sizeof(T), param_0); @@ -366,6 +391,7 @@ public: typename JASThreadingModel::InterruptsDisable >::Lock lock(*this); JASGenericMemPool::free(ptr, param_1); } +#endif }; /** diff --git a/libs/JSystem/include/JSystem/JAudio2/JASOscillator.h b/libs/JSystem/include/JSystem/JAudio2/JASOscillator.h index 746d462e12..e811e890ab 100644 --- a/libs/JSystem/include/JSystem/JAudio2/JASOscillator.h +++ b/libs/JSystem/include/JSystem/JAudio2/JASOscillator.h @@ -9,10 +9,21 @@ * */ struct JASOscillator { + enum EnvelopeMode { + /* 0x0 */ ENVELOPE_LINEAR, + /* 0x1 */ ENVELOPE_SQUARE, + /* 0x2 */ ENVELOPE_SQUARE_ROOT, + /* 0x3 */ ENVELOPE_SAMPLE_CELL, + + ENVELOPE_LOOP = 0xD, + ENVELOPE_HOLD = 0xE, + ENVELOPE_STOP = 0xF, + }; + struct Point { - /* 0x0 */ BE(s16) _0; - /* 0x2 */ BE(s16) _2; - /* 0x4 */ BE(s16) _4; + /* 0x0 */ BE(s16) mEnvelopeMode; // EnvelopeMode + /* 0x2 */ BE(s16) mTime; + /* 0x4 */ BE(s16) mValue; }; struct EffectParams { @@ -37,11 +48,11 @@ struct JASOscillator { struct Data { /* 0x00 */ u32 mTarget; - /* 0x04 */ f32 _04; + /* 0x04 */ f32 mRate; /* 0x08 */ const Point* mTable; /* 0x0C */ const Point* rel_table; - /* 0x10 */ f32 mScale; - /* 0x14 */ f32 _14; + /* 0x10 */ f32 mScale; // aka width + /* 0x14 */ f32 mVertex; }; enum Target { @@ -75,9 +86,9 @@ struct JASOscillator { /* 0x08 */ f32 _08; /* 0x0C */ f32 _0C; /* 0x10 */ f32 _10; - /* 0x14 */ u16 _14; + /* 0x14 */ u16 mCurPoint; /* 0x16 */ u16 mDirectRelease; - /* 0x18 */ u8 _18; + /* 0x18 */ u8 mEnvelopeMode; // EnvelopeMode /* 0x1A */ u16 _1A; /* 0x1C */ int _1C; diff --git a/libs/JSystem/include/JSystem/JAudio2/JASSeqParser.h b/libs/JSystem/include/JSystem/JAudio2/JASSeqParser.h index 096cbadd98..51db04ba26 100644 --- a/libs/JSystem/include/JSystem/JAudio2/JASSeqParser.h +++ b/libs/JSystem/include/JSystem/JAudio2/JASSeqParser.h @@ -14,9 +14,9 @@ public: enum BranchCondition {}; struct CmdInfo { - s32 (JASSeqParser::*field_0x0)(JASTrack*, u32*); - u16 field_0xc; - u16 field_0xe; + s32 (JASSeqParser::*mHandler)(JASTrack*, u32*); + u16 mParameterCount; + u16 mParameterTypes; }; virtual ~JASSeqParser() {} diff --git a/libs/JSystem/include/JSystem/JAudio2/JASSeqReader.h b/libs/JSystem/include/JSystem/JAudio2/JASSeqReader.h index 9dce7f56f7..878713602a 100644 --- a/libs/JSystem/include/JSystem/JAudio2/JASSeqReader.h +++ b/libs/JSystem/include/JSystem/JAudio2/JASSeqReader.h @@ -3,6 +3,8 @@ #include +#define JAS_SEQ_STACK_SIZE 8 + /** * @ingroup jsystem-jaudio * @@ -19,55 +21,55 @@ public: int readMidiValue(); void jump(u32 param_1) { - field_0x04 = field_0x00 + param_1; + mCurPos = mBase + param_1; } void jump(void* param_1) { - field_0x04 = (u8*)param_1; + mCurPos = (u8*)param_1; } u32 get24(u32 param_0) const { - return (*(u32*)(field_0x00 + param_0 - 1)) & 0xffffff; + return (*(BE(u32)*)(mBase + param_0 - 1)) & 0xffffff; } - u32* getBase() { return (u32*)field_0x00; } - void* getAddr(u32 param_0) { return field_0x00 + param_0; } - u8 getByte(u32 param_0) const { return *(field_0x00 + param_0); } - u16 get16(u32 param_0) const { return *(u16*)(field_0x00 + param_0); } - u32 get32(u32 param_0) const { return *(u32*)(field_0x00 + param_0); } - u8* getCur() { return field_0x04; } - u32 readByte() { return *field_0x04++; } + u32* getBase() { return (u32*)mBase; } + void* getAddr(u32 param_0) { return mBase + param_0; } + u8 getByte(u32 param_0) const { return *(mBase + param_0); } + u16 get16(u32 param_0) const { return *(BE(u16)*)(mBase + param_0); } + u32 get32(u32 param_0) const { return *(BE(u32)*)(mBase + param_0); } + u8* getCur() { return mCurPos; } + u32 readByte() { return *mCurPos++; } u32 read16() { #ifdef __MWERKS__ - return *((u16*)field_0x04)++; + return *((u16*)mCurPos)++; #else - u16* value = (u16*)field_0x04; - field_0x04 += 2; + BE(u16)* value = (BE(u16)*)mCurPos; + mCurPos += 2; return *value; #endif } u32 read24() { - field_0x04--; + mCurPos--; #ifdef __MWERKS__ - return (*((u32*)field_0x04)++) & 0x00ffffff; + return (*((u32*)mCurPos)++) & 0x00ffffff; #else - u32* value = (u32*)field_0x04; - field_0x04 += 4; + BE(u32)* value = (BE(u32)*)mCurPos; + mCurPos += 4; return (*value) & 0x00ffffff; #endif } u16 getLoopCount() const { - if (field_0x08 == 0) { + if (mCurStackDepth == 0) { return 0; } - return field_0x2c[field_0x08 - 1]; + return mLoopCount[mCurStackDepth - 1]; } - /* 0x00 */ u8* field_0x00; - /* 0x04 */ u8* field_0x04; - /* 0x08 */ u32 field_0x08; - /* 0x0C */ u16* field_0x0c[8]; - /* 0x2C */ u16 field_0x2c[8]; + /* 0x00 */ u8* mBase; + /* 0x04 */ u8* mCurPos; + /* 0x08 */ u32 mCurStackDepth; + /* 0x0C */ u16* mReturnAddr[JAS_SEQ_STACK_SIZE]; + /* 0x2C */ u16 mLoopCount[JAS_SEQ_STACK_SIZE]; }; #endif /* JASSEQREADER_H */ diff --git a/libs/JSystem/include/JSystem/JAudio2/JASTrack.h b/libs/JSystem/include/JSystem/JAudio2/JASTrack.h index 796bb6afd7..b54a98aa77 100644 --- a/libs/JSystem/include/JSystem/JAudio2/JASTrack.h +++ b/libs/JSystem/include/JSystem/JAudio2/JASTrack.h @@ -54,7 +54,7 @@ struct JASTrack : public JASPoolAllocObject_MultiThreaded { /* 0x4c */ JASTrack* mTrack; }; - struct TList : JGadget::TLinkList { + struct TList : JGadget::TLinkList { TList() : mCallbackRegistered(false) {} void append(JASTrack*); void seqMain(); diff --git a/libs/JSystem/include/JSystem/JAudio2/JASTrackPort.h b/libs/JSystem/include/JSystem/JAudio2/JASTrackPort.h index 393a701c27..781da78049 100644 --- a/libs/JSystem/include/JSystem/JAudio2/JASTrackPort.h +++ b/libs/JSystem/include/JSystem/JAudio2/JASTrackPort.h @@ -19,12 +19,12 @@ public: u32 checkImport(u32) const; u32 checkExport(u32) const; - u16 get(u32 param_0) const { return field_0x4[param_0]; } - void set(u32 param_0, u16 param_1) { field_0x4[param_0] = param_1; } + u16 get(u32 param_0) const { return mPortValues[param_0]; } + void set(u32 param_0, u16 param_1) { mPortValues[param_0] = param_1; } u16 field_0x0; u16 field_0x2; - u16 field_0x4[MAX_PORTS]; + u16 mPortValues[MAX_PORTS]; }; #endif /* JASTRACKPORT_H */ diff --git a/libs/JSystem/include/JSystem/JAudio2/JASWSParser.h b/libs/JSystem/include/JSystem/JAudio2/JASWSParser.h index 020158c096..68d91006ba 100644 --- a/libs/JSystem/include/JSystem/JAudio2/JASWSParser.h +++ b/libs/JSystem/include/JSystem/JAudio2/JASWSParser.h @@ -31,26 +31,28 @@ public: struct TWave { /* 0x00 */ u8 _00; - /* 0x01 */ u8 _01; - /* 0x02 */ u8 _02; - /* 0x04 */ BE(f32) _04; - /* 0x08 */ BE(u32) mOffset; - /* 0x0C */ BE(u32) _0C; - /* 0x10 */ BE(u32) _10; - /* 0x14 */ BE(u32) _14; - /* 0x18 */ BE(u32) _18; - /* 0x1C */ BE(u32) _1C; - /* 0x20 */ BE(s16) _20; - /* 0x22 */ BE(s16) _22; + /* 0x01 */ u8 mWaveFormat; + /* 0x02 */ u8 mBaseKey; + /* 0x04 */ BE(f32) mSampleRate; + /* 0x08 */ BE(u32) mAWOffsetStart; + /* 0x0C */ BE(u32) mAWOffsetEnd; + /* 0x10 */ BE(u32) mLoopFlags; + /* 0x14 */ BE(u32) mLoopStartSample; + /* 0x18 */ BE(u32) mLoopEndSample; + /* 0x1C */ BE(u32) mSampleCount; + /* 0x20 */ BE(s16) mpLast; + /* 0x22 */ BE(s16) mpPenult; }; struct TWaveArchive { - /* 0x00 */ char mFileName[0x74]; // unknown length + /* 0x00 */ char mFileName[0x70]; + /* 0x70 */ BE(u32) mWaveCount; /* 0x74 */ TOffset mWaveOffsets[0]; }; struct TWaveArchiveBank { - /* 0x0 */ u8 _00[8]; + /* 0x0 */ BE(u32) mMagic; // 'WINF' + /* 0x0 */ BE(u32) mArchiveCounts; /* 0x8 */ TOffset mArchiveOffsets[0]; }; @@ -66,14 +68,17 @@ public: }; struct TCtrlGroup { - /* 0x0 */ u8 _00[8]; + /* 0x0 */ BE(u32) mMagic; // 'WBCT' + /* 0x4 */ u32 mUnknown; /* 0x8 */ BE(u32) mGroupCount; /* 0xC */ TOffset mCtrlSceneOffsets[0]; }; /** @fabricated */ struct THeader { - /* 0x00 */ u8 _00[0xC]; + /* 0x00 */ BE(u32) mMagic; // 'WSYS' + /* 0x04 */ BE(u32) mSize; + /* 0x08 */ BE(u32) mId; /* 0x0C */ BE(u32) mWaveTableSize; /* 0x10 */ TOffset mArchiveBankOffset; /* 0x14 */ TOffset mCtrlGroupOffset; diff --git a/libs/JSystem/include/JSystem/JAudio2/JASWaveArcLoader.h b/libs/JSystem/include/JSystem/JAudio2/JASWaveArcLoader.h index 593e69f1fd..eea3eddac3 100644 --- a/libs/JSystem/include/JSystem/JAudio2/JASWaveArcLoader.h +++ b/libs/JSystem/include/JSystem/JAudio2/JASWaveArcLoader.h @@ -54,6 +54,8 @@ struct JASWaveArc : JASDisposer { virtual void onEraseDone() {} s32 getStatus() const { return mStatus; } + u32 getFileSize() const { return mFileLength; } + JASHeap* getHeap() { return &mHeap; } struct loadToAramCallbackParams { // not official struct name diff --git a/libs/JSystem/include/JSystem/JAudio2/JASWaveInfo.h b/libs/JSystem/include/JSystem/JAudio2/JASWaveInfo.h index cbff6d3ac2..cac518836e 100644 --- a/libs/JSystem/include/JSystem/JAudio2/JASWaveInfo.h +++ b/libs/JSystem/include/JSystem/JAudio2/JASWaveInfo.h @@ -3,7 +3,12 @@ #include -class JASWaveArc; +struct JASWaveArc; + +#define WAVE_FORMAT_ADPCM4 0 +#define WAVE_FORMAT_ADPCM2 1 +#define WAVE_FORMAT_PCM8 2 +#define WAVE_FORMAT_PCM16 3 /** * @ingroup jsystem-jaudio @@ -11,21 +16,21 @@ class JASWaveArc; */ struct JASWaveInfo { JASWaveInfo() { - field_0x01 = 0x3c; + mBaseKey = 0x3c; field_0x20 = &one; } - /* 0x00 */ u8 field_0x00; - /* 0x01 */ u8 field_0x01; - /* 0x02 */ u8 field_0x02; - /* 0x04 */ f32 field_0x04; - /* 0x08 */ int field_0x08; - /* 0x0C */ int field_0x0c; - /* 0x10 */ u32 field_0x10; - /* 0x14 */ int field_0x14; - /* 0x18 */ int field_0x18; - /* 0x1C */ s16 field_0x1c; - /* 0x1E */ s16 field_0x1e; + /* 0x00 */ u8 mWaveFormat; + /* 0x01 */ u8 mBaseKey; + /* 0x02 */ u8 mLoopFlag; + /* 0x04 */ f32 mSampleRate; + /* 0x08 */ int mOffsetStart; + /* 0x0C */ int mOffsetLength; + /* 0x10 */ u32 mLoopStartSample; + /* 0x14 */ int mLoopEndSample; + /* 0x18 */ int mSampleCount; + /* 0x1C */ s16 mpLast; + /* 0x1E */ s16 mpPenult; /* 0x20 */ const u32* field_0x20; static u32 one; diff --git a/libs/JSystem/include/JSystem/JAudio2/JAUAudibleParam.h b/libs/JSystem/include/JSystem/JAudio2/JAUAudibleParam.h index 89b016cb0a..44d4137d9b 100644 --- a/libs/JSystem/include/JSystem/JAudio2/JAUAudibleParam.h +++ b/libs/JSystem/include/JSystem/JAudio2/JAUAudibleParam.h @@ -2,6 +2,7 @@ #define JAUAUDIBLEPARAM_H #include +#include "dusk/endian.h" /** * @ingroup jsystem-jaudio @@ -9,13 +10,13 @@ */ struct JAUAudibleParam { f32 getDopplerPower() const { - return (u32)((*(u8*)&field_0x0.raw >> 4) & 0xf) * (1.0f / 15.0f); + return field_0x0.bytes.b0_0 * (1.0f / 15.0f); } union { struct { - u16 f0; - u16 f1; + BE(u16) f0; + BE(u16) f1; } half; struct { u8 b0_0 : 4; @@ -29,7 +30,7 @@ struct JAUAudibleParam { u8 b2; u8 b3; } bytes; - u32 raw; + BE(u32) raw; } field_0x0; }; diff --git a/libs/JSystem/include/JSystem/JAudio2/JAUInitializer.h b/libs/JSystem/include/JSystem/JAudio2/JAUInitializer.h index 8b5090c580..9f9e5bc6fd 100644 --- a/libs/JSystem/include/JSystem/JAudio2/JAUInitializer.h +++ b/libs/JSystem/include/JSystem/JAudio2/JAUInitializer.h @@ -21,7 +21,7 @@ public: /* 0x10 */ int audioThreadPriority_; /* 0x14 */ int dvdThreadId_; /* 0x18 */ int audioThreadId_; - /* 0x1C */ int field_0x1c; + /* 0x1C */ int mJasTrackPoolSize; /* 0x20 */ int field_0x20; /* 0x24 */ int aramBlockSize_; /* 0x28 */ int aramChannelNum_; @@ -38,10 +38,10 @@ public: JAU_JAIInitializer(); void initJAInterface(); - int field_0x0; - int field_0x4; - int field_0x8; - int field_0xc; + int mJaiSePoolSize; + int mJaiSeqPoolSize; + int mJaiStreamPoolSize; + int mJaiSoundChildPoolSize; }; #endif /* JAUINITIALIZER_H */ diff --git a/libs/JSystem/include/JSystem/JAudio2/JAUSeqCollection.h b/libs/JSystem/include/JSystem/JAudio2/JAUSeqCollection.h index 1812976e2f..bfc88ef3ad 100644 --- a/libs/JSystem/include/JSystem/JAudio2/JAUSeqCollection.h +++ b/libs/JSystem/include/JSystem/JAudio2/JAUSeqCollection.h @@ -11,11 +11,11 @@ struct JAISeqDataRegion; * */ struct JAUSeqCollectionData { - s8 field_0x0; - s8 field_0x1; - BE(u16) field_0x2; - BE(u32) field_0x4; - BE(u32) field_0x8; + s8 mMagic1; // 'S' + s8 mMagic2; // 'C' + BE(u16) mNumSoundCategories; + BE(u32) mSectionSize; + BE(u32) mTableOffsets[0]; // VLA }; /** @@ -29,12 +29,12 @@ public: bool getSeqData(int, int, JAISeqData*); bool getSeqDataRegion(JAISeqDataRegion*); - bool isValid() const { return field_0x8; } + bool isValid() const { return mHeader; } - /* 0x00 */ u16 field_0x0; - /* 0x04 */ const BE(u32)* field_0x4; - /* 0x08 */ const JAUSeqCollectionData* field_0x8; - /* 0x0C */ int field_0xc; + /* 0x00 */ u16 mNumSoundCategories; + /* 0x04 */ const BE(u32)* mTableOffsets; + /* 0x08 */ const JAUSeqCollectionData* mHeader; + /* 0x0C */ u32 mSectionSize; }; /** @@ -49,7 +49,7 @@ public: SeqDataReturnValue getSeqData(JAISoundID, JAISeqData*); ~JAUSeqDataMgr_SeqCollection(); - const void* getResource() const { return field_0x4; } + const void* getResource() const { return mTableOffsets; } void init(const void* param_1) { JAUSeqCollection::init(param_1); } /* 0x14 */ JAISeqDataUser* user_; diff --git a/libs/JSystem/include/JSystem/JAudio2/JAUSoundAnimator.h b/libs/JSystem/include/JSystem/JAudio2/JAUSoundAnimator.h index b9e1d433c9..e81cd70ee4 100644 --- a/libs/JSystem/include/JSystem/JAudio2/JAUSoundAnimator.h +++ b/libs/JSystem/include/JSystem/JAudio2/JAUSoundAnimator.h @@ -2,6 +2,7 @@ #define JAUSOUNDANIMATOR_H #include "JSystem/JAudio2/JAISound.h" +#include "dusk/offset_ptr.h" class JAUSoundAnimation; @@ -62,10 +63,10 @@ public: } /* 0x00 */ JAISoundID mSoundId; - /* 0x04 */ f32 field_0x04; - /* 0x08 */ f32 field_0x08; - /* 0x0C */ f32 field_0x0c; - /* 0x10 */ u32 mFlags; + /* 0x04 */ BE(f32) field_0x04; + /* 0x08 */ BE(f32) field_0x08; + /* 0x0C */ BE(f32) field_0x0c; + /* 0x10 */ BE(u32) mFlags; /* 0x14 */ u8 field_0x14; /* 0x15 */ u8 field_0x15; /* 0x16 */ u8 field_0x16; @@ -97,23 +98,31 @@ public: int getEndSoundIndex(f32) const; u16 getNumSounds() const { +#if TARGET_PC + return mNumSounds; +#else if (mControl != NULL) { return mControl->getNumSounds(this); } else { return mNumSounds; } +#endif } const JAUSoundAnimationSound* getSound(int i_index) const { +#if TARGET_PC + return &mSounds + i_index; +#else if (mControl != NULL) { return mControl->getSound(this, i_index); } else { return &mSounds + i_index; } +#endif } - /* 0x0 */ u16 mNumSounds; - /* 0x4 */ JAUSoundAnimationControl* mControl; + /* 0x0 */ BE(u16) mNumSounds; + /* 0x4 */ OFFSET_PTR(JAUSoundAnimationControl) mControl; /* 0x8 */ JAUSoundAnimationSound mSounds; // actually an array }; diff --git a/libs/JSystem/include/JSystem/JAudio2/JAUSoundTable.h b/libs/JSystem/include/JSystem/JAudio2/JAUSoundTable.h index b7eaee0ffe..4cc48f2a0b 100644 --- a/libs/JSystem/include/JSystem/JAudio2/JAUSoundTable.h +++ b/libs/JSystem/include/JSystem/JAudio2/JAUSoundTable.h @@ -12,9 +12,9 @@ struct JAUSoundTableItem { u8 mPriority; u8 field_0x1; - u16 mResourceId; - u32 field_0x4; - f32 field_0x8; + BE(u16) mResourceId; + BE(u32) field_0x4; + BE(f32) field_0x8; }; /** @@ -149,6 +149,8 @@ struct JAUSoundTable : public JASGlobalInstance { void init(void const*); u8 getTypeID(JAISoundID) const; JAUSoundTableItem* getData(JAISoundID) const; + int getNumGroups_inSection(u8) const; + int getNumItems_inGroup(u8, u8) const; JAUSoundTableItem* getItem(JAUSoundTableGroup* group, int index) const { u32 offset = group->getItemOffset(index); diff --git a/libs/JSystem/include/JSystem/JAudio2/JAUStreamAramMgr.h b/libs/JSystem/include/JSystem/JAudio2/JAUStreamAramMgr.h index bf861b495d..f1cfe8f7f6 100644 --- a/libs/JSystem/include/JSystem/JAudio2/JAUStreamAramMgr.h +++ b/libs/JSystem/include/JSystem/JAudio2/JAUStreamAramMgr.h @@ -48,13 +48,13 @@ template class JAUStreamStaticAramMgr_ : public JAUStreamAramMgrBase_ { public: JAUStreamStaticAramMgr_() { field_0x4c = 0; } - virtual void* newStreamAram(u32* param_0) { + virtual void* newStreamAram(u32* size) { for (u32 i = 0; i < field_0x4c; i++) { if (this->field_0x4.test(i)) { continue; } this->field_0x4.set(i, true); - *param_0 = this->mHeaps[i].getSize(); + *size = this->mHeaps[i].getSize(); return this->mHeaps[i].getBase(); } return NULL; diff --git a/libs/JSystem/include/JSystem/JAudio2/dspproc.h b/libs/JSystem/include/JSystem/JAudio2/dspproc.h index 868080031a..c49c143fe4 100644 --- a/libs/JSystem/include/JSystem/JAudio2/dspproc.h +++ b/libs/JSystem/include/JSystem/JAudio2/dspproc.h @@ -4,7 +4,7 @@ #include void DSPReleaseHalt2(u32 msg); -void DsetupTable(u32 param_0, u32 param_1, u32 param_2, u32 param_3, u32 param_4); +void DsetupTable(u32 channelCount, u32 channelBufferAddress, u32 param_2, u32 param_3, u32 param_4); void DsetMixerLevel(f32 level); void DsyncFrame2ch(u32 param_0, u32 param_1, u32 param_2); void DsyncFrame4ch(u32 param_0, u32 param_1, u32 param_2, u32 param_3, u32 param_4); diff --git a/libs/JSystem/include/JSystem/JAudio2/dsptask.h b/libs/JSystem/include/JSystem/JAudio2/dsptask.h index 8042d1884b..7dbcff2dec 100644 --- a/libs/JSystem/include/JSystem/JAudio2/dsptask.h +++ b/libs/JSystem/include/JSystem/JAudio2/dsptask.h @@ -3,7 +3,7 @@ #include -void DspBoot(void (*)(void*)); +void DspBoot(void (*requestCallback)(void*)); void DspFinishWork(u16 param_0); int DSPSendCommands2(u32* msgs, u32 param_1, void (*param_2)(u16)); diff --git a/libs/JSystem/include/JSystem/JFramework/JFWSystem.h b/libs/JSystem/include/JSystem/JFramework/JFWSystem.h index bb4dfa01cd..288b5f03d8 100644 --- a/libs/JSystem/include/JSystem/JFramework/JFWSystem.h +++ b/libs/JSystem/include/JSystem/JFramework/JFWSystem.h @@ -33,6 +33,9 @@ struct JFWSystem { static void firstInit(); static void init(); +#if TARGET_PC + static void shutdown(); +#endif static JUTConsole* getSystemConsole() { return systemConsole; } static JKRExpHeap* getSystemHeap() { return systemHeap; } diff --git a/libs/JSystem/include/JSystem/JKernel/JKRAram.h b/libs/JSystem/include/JSystem/JKernel/JKRAram.h index 9c8ebd88d1..dd3bf54f9c 100644 --- a/libs/JSystem/include/JSystem/JKernel/JKRAram.h +++ b/libs/JSystem/include/JSystem/JKernel/JKRAram.h @@ -39,6 +39,9 @@ public: public: static JKRAram* create(u32, u32, s32, s32, s32); +#if TARGET_PC + static void destroy(); +#endif static void checkOkAddress(u8*, u32, JKRAramBlock*, u32); static void changeGroupIdIfNeed(u8*, int); static JKRAramBlock* mainRamToAram(u8*, u32, u32, JKRExpandSwitch, u32, JKRHeap*, int, u32*); diff --git a/libs/JSystem/include/JSystem/JKernel/JKRDecomp.h b/libs/JSystem/include/JSystem/JKernel/JKRDecomp.h index 9131ecfbaa..2e7ce0ef1c 100644 --- a/libs/JSystem/include/JSystem/JKernel/JKRDecomp.h +++ b/libs/JSystem/include/JSystem/JKernel/JKRDecomp.h @@ -48,6 +48,9 @@ private: public: static JKRDecomp* create(s32); +#if TARGET_PC + static void destroy(); +#endif static JKRDecompCommand* prepareCommand(u8*, u8*, u32, u32, JKRDecompCommand::AsyncCallback); static void sendCommand(JKRDecompCommand*); static bool sync(JKRDecompCommand*, int); diff --git a/libs/JSystem/include/JSystem/JKernel/JKRDvdRipper.h b/libs/JSystem/include/JSystem/JKernel/JKRDvdRipper.h index 82b9c21a2e..0720605efb 100644 --- a/libs/JSystem/include/JSystem/JKernel/JKRDvdRipper.h +++ b/libs/JSystem/include/JSystem/JKernel/JKRDvdRipper.h @@ -36,6 +36,9 @@ public: static JSUList sDvdAsyncList; static u32 sSZSBufferSize; static bool errorRetry; +#if TARGET_PC + static JKRHeap* sHeap; +#endif enum EAllocDirection { UNKNOWN_EALLOC_DIRECTION = 0, @@ -54,6 +57,12 @@ public: static bool isErrorRetry(void) { return errorRetry; } inline static u32 getSZSBufferSize() { return sSZSBufferSize; } + +#if TARGET_PC + static inline JKRHeap* getHeap() { return sHeap; } + static inline void setHeap(JKRHeap* i_heap) { sHeap = i_heap; } + +#endif }; // void JKRDecompressFromDVD(JKRDvdFile*, void*, u32, u32, u32, u32, u32*); diff --git a/libs/JSystem/include/JSystem/JKernel/JKRExpHeap.h b/libs/JSystem/include/JSystem/JKernel/JKRExpHeap.h index a31b2c5e84..09687e688b 100644 --- a/libs/JSystem/include/JSystem/JKernel/JKRExpHeap.h +++ b/libs/JSystem/include/JSystem/JKernel/JKRExpHeap.h @@ -121,6 +121,13 @@ public: static s32 getUsedSize_(JKRExpHeap* heap) { return heap->mSize - heap->getTotalFreeSize(); } static void* getState_(TState* state) { return getState_buf_(state); } + +#if TARGET_PC + [[nodiscard]] CMemBlock* getFreeHead() { return mHeadFreeList; } + [[nodiscard]] const CMemBlock* getFreeHead() const { return mHeadFreeList; } + [[nodiscard]] CMemBlock* getUsedHead() { return mHeadUsedList; } + [[nodiscard]] const CMemBlock* getUsedHead() const { return mHeadUsedList; } +#endif }; inline JKRExpHeap* JKRCreateExpHeap(u32 size, JKRHeap* parent, bool errorFlag) { diff --git a/libs/JSystem/include/JSystem/JKernel/JKRHeap.h b/libs/JSystem/include/JSystem/JKernel/JKRHeap.h index d988f09d74..d3710bd5df 100644 --- a/libs/JSystem/include/JSystem/JKernel/JKRHeap.h +++ b/libs/JSystem/include/JSystem/JKernel/JKRHeap.h @@ -283,7 +283,18 @@ void jkrDelete(T* ptr) { return; } ptr->~T(); - operator delete(ptr, JKRHeapToken::Dummy); + + if constexpr (requires { T::operator delete(ptr, JKRHeapToken::Dummy); }) { + T::operator delete(ptr, JKRHeapToken::Dummy); + } else if constexpr (requires { T::operator delete(ptr, sizeof(T), JKRHeapToken::Dummy); }) { + T::operator delete(ptr, sizeof(T), JKRHeapToken::Dummy); + } else if constexpr (requires { T::operator delete(ptr); }) { + T::operator delete(ptr); + } else if constexpr (requires { T::operator delete(ptr, sizeof(T)); }) { + T::operator delete(ptr, sizeof(T)); + } else { + operator delete(ptr, JKRHeapToken::Dummy); + } } template<> diff --git a/libs/JSystem/include/JSystem/JKernel/JKRThread.h b/libs/JSystem/include/JSystem/JKernel/JKRThread.h index b58dc6232d..79217f3675 100644 --- a/libs/JSystem/include/JSystem/JKernel/JKRThread.h +++ b/libs/JSystem/include/JSystem/JKernel/JKRThread.h @@ -101,11 +101,22 @@ public: } return message; } +#ifdef TARGET_PC + OSMessage waitMessageBlock(BOOL* received) { + OSMessage message; + BOOL rv = OSReceiveMessage(&mMessageQueue, &message, OS_MESSAGE_BLOCK); + if (received) { + *received = rv; + } + return message; + } +#else OSMessage waitMessageBlock() { OSMessage message; OSReceiveMessage(&mMessageQueue, &message, OS_MESSAGE_BLOCK); return message; } +#endif void jamMessageBlock(OSMessage message) { OSJamMessage(&mMessageQueue, message, OS_MESSAGE_BLOCK); } @@ -132,6 +143,10 @@ public: static JSUList sThreadList; // static u8 sThreadList[12]; + +#if TARGET_PC + const char* mThreadName; +#endif }; class JKRIdleThread : public JKRThread { diff --git a/libs/JSystem/include/JSystem/JSupport/JSUList.h b/libs/JSystem/include/JSystem/JSupport/JSUList.h index 3021a3a879..69356600a7 100644 --- a/libs/JSystem/include/JSystem/JSupport/JSUList.h +++ b/libs/JSystem/include/JSystem/JSupport/JSUList.h @@ -230,6 +230,8 @@ public: return *this; } + operator int() { return (int)mTree; } + T* getObject() const { return this->mTree->getObject(); } bool operator==(const JSUTree* other) const { return this->mTree == other; } diff --git a/libs/JSystem/include/JSystem/JUtility/JUTGamePad.h b/libs/JSystem/include/JSystem/JUtility/JUTGamePad.h index bf939f0831..30bf685700 100644 --- a/libs/JSystem/include/JSystem/JUtility/JUTGamePad.h +++ b/libs/JSystem/include/JSystem/JUtility/JUTGamePad.h @@ -117,7 +117,7 @@ public: } void stopMotorWave() { mRumble.stopPatternedRumbleAtThePeriod(); } - void stopMotor() { mRumble.stopMotor(mPortNum, false); } + void stopMotor() { mRumble.stopMotor(mPortNum); } void stopMotorHard() { CRumble::stopMotorHard(mPortNum); } static s8 getPortStatus(EPadPort port) { @@ -233,7 +233,7 @@ public: /* 0x10 */ u8* field_0x10; }; // Size: 0x14 - void startMotorWave(void* data, CRumble::ERumble rumble, u32 length) { + void startMotorWave(u8* data, CRumble::ERumble rumble, u32 length) { mRumble.startPatternedRumble(data, rumble, length); } diff --git a/libs/JSystem/include/JSystem/JUtility/JUTResFont.h b/libs/JSystem/include/JSystem/JUtility/JUTResFont.h index 09d3303da0..8709822d7b 100644 --- a/libs/JSystem/include/JSystem/JUtility/JUTResFont.h +++ b/libs/JSystem/include/JSystem/JUtility/JUTResFont.h @@ -18,6 +18,10 @@ struct BlockHeader { BE(u32) size; }; +#if TARGET_PC +struct GlyphTextures; +#endif + /** * @ingroup jsystem-jutility * @@ -64,7 +68,11 @@ public: // some types uncertain, may need to be fixed /* 0x1C */ int mWidth; /* 0x20 */ int mHeight; +#if TARGET_PC + GlyphTextures* mGlyphTextures; +#else /* 0x24 */ TGXTexObj mTexObj; +#endif /* 0x44 */ int mTexPageIdx; /* 0x48 */ const ResFONT* mResFont; /* 0x4C */ ResFONT::INF1* mInf1Ptr; diff --git a/libs/JSystem/src/J3DGraphBase/J3DDrawBuffer.cpp b/libs/JSystem/src/J3DGraphBase/J3DDrawBuffer.cpp index b18a53b8c1..c533face96 100644 --- a/libs/JSystem/src/J3DGraphBase/J3DDrawBuffer.cpp +++ b/libs/JSystem/src/J3DGraphBase/J3DDrawBuffer.cpp @@ -8,6 +8,7 @@ #include "JSystem/J3DGraphBase/J3DDrawBuffer.h" #include "JSystem/J3DGraphBase/J3DMaterial.h" #include "JSystem/JKernel/JKRHeap.h" +#include "tracy/Tracy.hpp" void J3DDrawBuffer::calcZRatio() { mZRatio = (mZFar - mZNear) / (f32)mEntryTableSize; @@ -224,6 +225,7 @@ void J3DDrawBuffer::draw() const { } void J3DDrawBuffer::drawHead() const { + ZoneScoped; u32 size = mEntryTableSize; J3DPacket** buf = mpBuffer; @@ -235,6 +237,7 @@ void J3DDrawBuffer::drawHead() const { } void J3DDrawBuffer::drawTail() const { + ZoneScoped; for (int i = mEntryTableSize - 1; i >= 0; i--) { for (J3DPacket* packet = mpBuffer[i]; packet != NULL; packet = packet->getNextPacket()) { packet->draw(); diff --git a/libs/JSystem/src/J3DGraphBase/J3DPacket.cpp b/libs/JSystem/src/J3DGraphBase/J3DPacket.cpp index a702ff5523..bf2348020a 100644 --- a/libs/JSystem/src/J3DGraphBase/J3DPacket.cpp +++ b/libs/JSystem/src/J3DGraphBase/J3DPacket.cpp @@ -1,14 +1,15 @@ #include "JSystem/JSystem.h" // IWYU pragma: keep -#include "JSystem/J3DGraphBase/J3DPacket.h" +#include +#include #include "JSystem/J3DGraphAnimator/J3DModel.h" #include "JSystem/J3DGraphBase/J3DDrawBuffer.h" #include "JSystem/J3DGraphBase/J3DMaterial.h" +#include "JSystem/J3DGraphBase/J3DPacket.h" #include "JSystem/J3DGraphBase/J3DShapeMtx.h" #include "JSystem/JKernel/JKRHeap.h" -#include -#include #include "global.h" +#include "tracy/Tracy.hpp" J3DError J3DDisplayListObj::newDisplayList(u32 maxSize) { mMaxSize = ALIGN_NEXT(maxSize, 0x20); @@ -207,12 +208,13 @@ bool J3DMatPacket::isSame(J3DMatPacket* pOther) const { } void J3DMatPacket::draw() { + ZoneScoped; #if TARGET_PC j3dSys.setTexture(mpTexture); #endif mpMaterial->load(); -#if TARGET_PC +#if DEBUG && TARGET_PC if (mpMaterial->mMaterialName != nullptr) { char buf[64]; snprintf(buf, sizeof(buf), "Mat: %s", mpMaterial->mMaterialName); @@ -239,7 +241,7 @@ void J3DMatPacket::draw() { J3DShape::resetVcdVatCache(); -#if TARGET_PC +#if DEBUG && TARGET_PC if (mpMaterial->mMaterialName != nullptr) { GXPopDebugGroup(); } @@ -388,6 +390,7 @@ void J3DShapePacket::draw() { } void J3DShapePacket::drawFast() { + ZoneScoped; if (!checkFlag(J3DShpFlag_Hidden) && mpShape != NULL) { prepareDraw(); diff --git a/libs/JSystem/src/J3DGraphBase/J3DShape.cpp b/libs/JSystem/src/J3DGraphBase/J3DShape.cpp index b3c16f00a7..fc7ac5b727 100644 --- a/libs/JSystem/src/J3DGraphBase/J3DShape.cpp +++ b/libs/JSystem/src/J3DGraphBase/J3DShape.cpp @@ -3,13 +3,13 @@ #include "JSystem/J3DGraphBase/J3DShape.h" #include +#include +#include #include "JSystem/J3DGraphBase/J3DFifo.h" #include "JSystem/J3DGraphBase/J3DPacket.h" #include "JSystem/J3DGraphBase/J3DVertex.h" -#include "JSystem/J3DGraphBase/J3DFifo.h" -#include -#include #include "JSystem/JKernel/JKRHeap.h" +#include "tracy/Tracy.hpp" void J3DGDSetVtxAttrFmtv(GXVtxFmt, GXVtxAttrFmtList const*, bool); void J3DFifoLoadPosMtxImm(Mtx, u32); @@ -134,12 +134,13 @@ void J3DLoadCPCmd(u8 addr, u32 val) { } #if TARGET_PC -static void J3DLoadArrayBasePtr(GXAttr attr, void* data, u32 size) { +static void J3DLoadArrayBasePtr(GXAttr attr, void* data, u32 size, bool le) { u32 idx = (attr == GX_VA_NBT) ? 1 : (attr - GX_VA_POS); GXCmd1u8(GX_LOAD_AURORA); GXCmd1u16(GX_LOAD_AURORA_ARRAYBASE | idx); GXCmd1u64((u64)data); - GXCmd1u64((u64)size); + GXCmd1u32(size); + GXCmd1u8(le ? 1 : 0); } #else static void J3DLoadArrayBasePtr(GXAttr attr, void* data) { @@ -152,15 +153,15 @@ void J3DShape::loadVtxArray() const { #if TARGET_PC // TODO: these can very easily overcount if the data isn't in F32 format if (j3dSys.getVtxPos() != mVertexData->getVtxPosArray()) { - J3DLoadArrayBasePtr(GX_VA_POS, j3dSys.getVtxPos(), j3dSys.mVtxPosNum * sizeof(Vec)); + J3DLoadArrayBasePtr(GX_VA_POS, j3dSys.getVtxPos(), j3dSys.mVtxPosNum * sizeof(Vec), true); } if (!mHasNBT && j3dSys.getVtxNrm() != mVertexData->getVtxNrmArray()) { - J3DLoadArrayBasePtr(GX_VA_NRM, j3dSys.getVtxNrm(), j3dSys.mVtxNrmNum * sizeof(Vec)); + J3DLoadArrayBasePtr(GX_VA_NRM, j3dSys.getVtxNrm(), j3dSys.mVtxNrmNum * sizeof(Vec), true); } if (j3dSys.getVtxCol() != mVertexData->getVtxColorArray(0)) { - J3DLoadArrayBasePtr(GX_VA_CLR0, j3dSys.getVtxCol(), j3dSys.mVtxColNum * sizeof(GXColor)); + J3DLoadArrayBasePtr(GX_VA_CLR0, j3dSys.getVtxCol(), j3dSys.mVtxColNum * sizeof(GXColor), true); } #else J3DLoadArrayBasePtr(GX_VA_POS, j3dSys.getVtxPos()); @@ -257,9 +258,9 @@ void J3DShape::makeVtxArrayCmd() { for (u32 i = 0; i < 12; i++) { GXAttr attr = GXAttr(i + GX_VA_POS); if (array[i] != nullptr) - GDSetArraySized(attr, array[i], mVertexData->getVtxArrByteSize(attr), mVertexData->getVtxArrStride(attr)); + GDSetArraySized(attr, array[i], mVertexData->getVtxArrByteSize(attr), mVertexData->getVtxArrStride(attr), true); else - GDSetArraySized(attr, nullptr, 0, mVertexData->getVtxArrStride(attr)); + GDSetArraySized(attr, nullptr, 0, mVertexData->getVtxArrStride(attr), true); } #else for (u32 i = 0; i < 12; i++) { @@ -317,6 +318,7 @@ void J3DShape::setArrayAndBindPipeline() const { } void J3DShape::drawFast() const { + ZoneScoped; if (sOldVcdVatCmd != mVcdVatCmd) { GXCallDisplayList(mVcdVatCmd, kVcdVatDLSize); sOldVcdVatCmd = mVcdVatCmd; diff --git a/libs/JSystem/src/J3DGraphBase/J3DSys.cpp b/libs/JSystem/src/J3DGraphBase/J3DSys.cpp index c34ba546f0..b4598bfa7a 100644 --- a/libs/JSystem/src/J3DGraphBase/J3DSys.cpp +++ b/libs/JSystem/src/J3DGraphBase/J3DSys.cpp @@ -6,6 +6,7 @@ #include "JSystem/J3DGraphBase/J3DTexture.h" #include "dusk/gx_helper.h" #include "global.h" +#include "tracy/Tracy.hpp" J3DSys j3dSys; @@ -17,7 +18,11 @@ Vec J3DSys::mParentS; J3DTexCoordScaleInfo J3DSys::sTexCoordScaleTable[8]; +#if TARGET_PC // Original game bug, array is too small. +static u8 NullTexData[0x20] ATTRIBUTE_ALIGN(32) = {0}; +#else static u8 NullTexData[0x10] ATTRIBUTE_ALIGN(32) = {0}; +#endif static Mtx j3dIdentityMtx = { 1.0f, 0.0f, 0.0f, 0.0f, @@ -117,6 +122,8 @@ void J3DSys::setTexCacheRegion(GXTexCacheSize size) { } void J3DSys::drawInit() { + ZoneScoped; + GXInvalidateVtxCache(); GXSetCurrentMtx(GX_PNMTX0); GXSetCullMode(GX_CULL_BACK); @@ -222,6 +229,7 @@ void J3DSys::drawInit() { } void J3DSys::reinitGX() { + ZoneScoped; reinitGenMode(); reinitLighting(); reinitTransform(); diff --git a/libs/JSystem/src/J3DGraphBase/J3DTevs.cpp b/libs/JSystem/src/J3DGraphBase/J3DTevs.cpp index 0c712dac81..09ddc0b405 100644 --- a/libs/JSystem/src/J3DGraphBase/J3DTevs.cpp +++ b/libs/JSystem/src/J3DGraphBase/J3DTevs.cpp @@ -276,7 +276,7 @@ bool isTexNoReg(void* pDL) { } u16 getTexNoReg(void* pDL) { - u32 var_r31 = *(u32*)((u8*)pDL + 1); + u32 var_r31 = *(BE(u32)*)((u8*)pDL + 1); return var_r31 & 0xFFFFFF; } diff --git a/libs/JSystem/src/J3DGraphLoader/J3DMaterialFactory_v21.cpp b/libs/JSystem/src/J3DGraphLoader/J3DMaterialFactory_v21.cpp index 229309545a..f6cca25525 100644 --- a/libs/JSystem/src/J3DGraphLoader/J3DMaterialFactory_v21.cpp +++ b/libs/JSystem/src/J3DGraphLoader/J3DMaterialFactory_v21.cpp @@ -10,8 +10,8 @@ J3DMaterialFactory_v21::J3DMaterialFactory_v21(J3DMaterialBlock_v21 const& i_block) { mMaterialNum = i_block.mMaterialNum; mpMaterialInitData = JSUConvertOffsetToPtr(&i_block, i_block.mpMaterialInitData); - mpMaterialID = JSUConvertOffsetToPtr(&i_block, i_block.mpMaterialID); - mpCullMode = JSUConvertOffsetToPtr(&i_block, i_block.mpCullMode); + mpMaterialID = JSUConvertOffsetToPtr(&i_block, i_block.mpMaterialID); + mpCullMode = JSUConvertOffsetToPtr(&i_block, i_block.mpCullMode); mpMatColor = JSUConvertOffsetToPtr(&i_block, i_block.mpMatColor); mpColorChanNum = JSUConvertOffsetToPtr(&i_block, i_block.mpColorChanNum); mpColorChanInfo = JSUConvertOffsetToPtr(&i_block, i_block.mpColorChanInfo); @@ -20,9 +20,9 @@ J3DMaterialFactory_v21::J3DMaterialFactory_v21(J3DMaterialBlock_v21 const& i_blo mpTexCoord2Info = JSUConvertOffsetToPtr(&i_block, i_block.mpTexCoord2Info); mpTexMtxInfo = JSUConvertOffsetToPtr(&i_block, i_block.mpTexMtxInfo); field_0x28 = JSUConvertOffsetToPtr(&i_block, i_block.field_0x38); - mpTexNo = JSUConvertOffsetToPtr(&i_block, i_block.mpTexNo); + mpTexNo = JSUConvertOffsetToPtr(&i_block, i_block.mpTexNo); mpTevOrderInfo = JSUConvertOffsetToPtr(&i_block, i_block.mpTevOrderInfo); - mpTevColor = JSUConvertOffsetToPtr(&i_block, i_block.mpTevColor); + mpTevColor = JSUConvertOffsetToPtr(&i_block, i_block.mpTevColor); mpTevKColor = JSUConvertOffsetToPtr(&i_block, i_block.mpTevKColor); mpTevStageNum = JSUConvertOffsetToPtr(&i_block, i_block.mpTevStageNum); mpTevStageInfo = JSUConvertOffsetToPtr(&i_block, i_block.mpTevStageInfo); @@ -260,7 +260,7 @@ J3DGXColorS10 J3DMaterialFactory_v21::newTevColor(int i_idx, int i_no) const { J3DGXColorS10 dflt = defaultTevColor; J3DMaterialInitData_v21* mtl_init_data = &mpMaterialInitData[mpMaterialID[i_idx]]; if (mtl_init_data->mTevColorIdx[i_no] != 0xffff) { - return mpTevColor[mtl_init_data->mTevColorIdx[i_no]]; + return (GXColorS10)mpTevColor[mtl_init_data->mTevColorIdx[i_no]]; } else { return dflt; } diff --git a/libs/JSystem/src/J3DGraphLoader/J3DModelLoader.cpp b/libs/JSystem/src/J3DGraphLoader/J3DModelLoader.cpp index 72a48007c0..3d064e33de 100644 --- a/libs/JSystem/src/J3DGraphLoader/J3DModelLoader.cpp +++ b/libs/JSystem/src/J3DGraphLoader/J3DModelLoader.cpp @@ -242,7 +242,7 @@ void J3DModelLoader::setupBBoardInfo() { J3DMaterial* mesh = mpModelData->getJointNodePointer(i)->getMesh(); if (mesh != NULL) { u32 shape_index = mesh->getShape()->getIndex(); - u16* index_table = JSUConvertOffsetToPtr(mpShapeBlock, + BE(u16)* index_table = JSUConvertOffsetToPtr(mpShapeBlock, (uintptr_t)mpShapeBlock->mpIndexTable); J3DShapeInitData* shape_init_data = JSUConvertOffsetToPtr(mpShapeBlock, diff --git a/libs/JSystem/src/JAHostIO/JAHioNode.cpp b/libs/JSystem/src/JAHostIO/JAHioNode.cpp index 66c9431a41..9a30991e4f 100644 --- a/libs/JSystem/src/JAHostIO/JAHioNode.cpp +++ b/libs/JSystem/src/JAHostIO/JAHioNode.cpp @@ -101,7 +101,9 @@ JAHioNode* JAHioNode::getParent() { void JAHioNode::listenPropertyEvent(const JORPropertyEvent* event) { propertyEvent(JAH_P_EVENT0, (uintptr_t)event->id); +#if DEBUG JORReflexible::listenPropertyEvent(event); +#endif propertyEvent(JAH_P_EVENT1, (uintptr_t)event->id); } diff --git a/libs/JSystem/src/JAWExtSystem/JAWWindow.cpp b/libs/JSystem/src/JAWExtSystem/JAWWindow.cpp index 5163355615..e551e59952 100644 --- a/libs/JSystem/src/JAWExtSystem/JAWWindow.cpp +++ b/libs/JSystem/src/JAWExtSystem/JAWWindow.cpp @@ -6,29 +6,29 @@ #include "JSystem/JGeometry.h" JAWWindow::JAWWindow(const char* param_1, int param_2, int param_3) : - field_0x38('WIN1', JGeometry::TBox2(0.0f, 0.0f, param_2, param_3), "frame_lu.bti"), - field_0x180('TITL', JGeometry::TBox2(10.0f, 10.0f, 640.0f, 170.0f), (const ResFONT*)JUTResFONT_Ascfont_fix16, param_1, -1, HBIND_LEFT, VBIND_TOP), - field_0x2b0(this), - field_0x3d8(JUtility::TColor(0, 0, 0, 255)), - field_0x3dc(JUtility::TColor(0, 0, 0, 255)), - field_0x3e0(JUtility::TColor(0, 0, 0, 255)), - field_0x3e4(JUtility::TColor(0, 0, 0, 255)) { + m_drawWindow('WIN1', JGeometry::TBox2(0.0f, 0.0f, param_2, param_3), "frame_lu.bti"), + m_titleText('TITL', JGeometry::TBox2(10.0f, 10.0f, 640.0f, 170.0f), (const ResFONT*)JUTResFONT_Ascfont_fix16, param_1, -1, HBIND_LEFT, VBIND_TOP), + m_windowText(this), + m_windowColor0(JUtility::TColor(0, 0, 0, 255)), + m_windowColor1(JUtility::TColor(0, 0, 0, 255)), + m_windowColor2(JUtility::TColor(0, 0, 0, 255)), + m_windowColor3(JUtility::TColor(0, 0, 0, 255)) { field_0x3e8 = 0; - field_0x3ec = 0; - field_0x38.setContentsColor(field_0x3d8, field_0x3e0, field_0x3dc, field_0x3e4); - field_0x180.setCharColor(JUtility::TColor(0, 255, 0, 255)); - field_0x180.setGradColor(JUtility::TColor(255, 255, 255, 255)); - field_0x38.appendChild(&field_0x180); - field_0x38.appendChild(&field_0x2b0); + m_isInit = FALSE; + m_drawWindow.setContentsColor(m_windowColor0, m_windowColor2, m_windowColor1, m_windowColor3); + m_titleText.setCharColor(JUtility::TColor(0, 255, 0, 255)); + m_titleText.setGradColor(JUtility::TColor(255, 255, 255, 255)); + m_drawWindow.appendChild(&m_titleText); + m_drawWindow.appendChild(&m_windowText); } JAWWindow::~JAWWindow() {} BOOL JAWWindow::initIf() { - if (field_0x3ec) { + if (m_isInit) { return TRUE; } else { - field_0x3ec = TRUE; + m_isInit = TRUE; return onInit(); } } @@ -36,30 +36,30 @@ BOOL JAWWindow::initIf() { BOOL JAWWindow::onInit() { return TRUE; } void JAWWindow::setTitleColor(const JUtility::TColor& param_1, const JUtility::TColor& param_2) { - field_0x180.setCharColor(param_1); - field_0x180.setGradColor(param_2); + m_titleText.setCharColor(param_1); + m_titleText.setGradColor(param_2); } void JAWWindow::setWindowColor(const JUtility::TColor& param_1, const JUtility::TColor& param_2, const JUtility::TColor& param_3, const JUtility::TColor& param_4) { - field_0x3d8 = param_1; - field_0x3dc = param_2; - field_0x3e0 = param_3; - field_0x3e4 = param_4; - field_0x38.setContentsColor(field_0x3d8, field_0x3e0, field_0x3dc, field_0x3e4); + m_windowColor0 = param_1; + m_windowColor1 = param_2; + m_windowColor2 = param_3; + m_windowColor3 = param_4; + m_drawWindow.setContentsColor(m_windowColor0, m_windowColor2, m_windowColor1, m_windowColor3); } void JAWWindow::onDraw(JAWGraphContext*) {} void JAWWindow::move(f32 param_1, f32 param_2) { - field_0x38.move(param_1, param_2); + m_drawWindow.move(param_1, param_2); } void JAWWindow::addPosition(f32 param_1, f32 param_2) { - field_0x38.add(param_1, param_2); + m_drawWindow.add(param_1, param_2); } void JAWWindow::addSize(f32 width, f32 height) { - JGeometry::TBox2 bounds = field_0x38.getBounds(); + JGeometry::TBox2 bounds = m_drawWindow.getBounds(); f32 newWidth = width + bounds.getWidth(); f32 newHeight = height + bounds.getHeight(); if (newWidth < 36.0f) { @@ -72,7 +72,7 @@ void JAWWindow::addSize(f32 width, f32 height) { } else if (newHeight > 480.0f) { newHeight = 480.0f; } - field_0x38.resize(newWidth, newHeight); + m_drawWindow.resize(newWidth, newHeight); } JUtility::TColor JAWWindow::convJudaColor(u16 param_1) { @@ -189,7 +189,7 @@ void JAWWindow::padProc(const JUTGamePad& pad) { JAWWindow::TWindowText::TWindowText(JAWWindow* window) : J2DPane('TEXT', JGeometry::TBox2(10.0f, 30.0f, 650.0f, 510.0f)), m_pParent(window), - field_0x11c(0, 0) { + m_point(0, 0) { } JAWWindow::TWindowText::~TWindowText() {} @@ -201,15 +201,15 @@ void JAWWindow::TWindowText::drawSelf(f32 param_1, f32 param_2) { } void JAWWindow::TWindowText::drawSelf(f32, f32, Mtx* param_3) { - field_0xfc.reset(); - MTXTrans(*param_3, -field_0x11c.x, -field_0x11c.y, 0.0f); + m_graf.reset(); + MTXTrans(*param_3, -m_point.x, -m_point.y, 0.0f); Mtx stack_48; MTXConcat(*param_3, mGlobalMtx, stack_48); GXLoadPosMtxImm(stack_48, 0); - field_0xfc.setParentAlpha(mColorAlpha); + m_graf.setParentAlpha(mColorAlpha); JUT_ASSERT(209, m_pParent != NULL); m_pParent->setMatrix(stack_48); - m_pParent->onDraw(&field_0xfc); + m_pParent->onDraw(&m_graf); } static void dummy(J2DPane* pane, J2DWindow* window) { diff --git a/libs/JSystem/src/JAudio2/JAIAudience.cpp b/libs/JSystem/src/JAudio2/JAIAudience.cpp index 3e1205e2fc..a14422a943 100644 --- a/libs/JSystem/src/JAudio2/JAIAudience.cpp +++ b/libs/JSystem/src/JAudio2/JAIAudience.cpp @@ -1,11 +1,20 @@ #include "JSystem/JSystem.h" // IWYU pragma: keep #include "JSystem/JAudio2/JAIAudience.h" + #include "JSystem/JAudio2/JAISeMgr.h" #include "JSystem/JAudio2/JAISeqMgr.h" #include "JSystem/JAudio2/JAIStreamMgr.h" +#include "dusk/main.h" JAIAudience::~JAIAudience() { +#if TARGET_PC + if (dusk::IsShuttingDown) { + // Those asserts down there crash on shutdown from dtors. + return; + } +#endif + JUT_ASSERT(14, ! JAISeMgr::getInstance() || ( JAISeMgr::getInstance() ->getAudience() != this )); JUT_ASSERT(15, ! JAISeqMgr::getInstance() || ( JAISeqMgr::getInstance() ->getAudience() != this )); JUT_ASSERT(16, ! JAIStreamMgr::getInstance() || ( JAIStreamMgr::getInstance() ->getAudience() != this )); diff --git a/libs/JSystem/src/JAudio2/JAISe.cpp b/libs/JSystem/src/JAudio2/JAISe.cpp index 4e453811a9..504c875bad 100644 --- a/libs/JSystem/src/JAudio2/JAISe.cpp +++ b/libs/JSystem/src/JAudio2/JAISe.cpp @@ -57,7 +57,7 @@ void JAISe::startTrack_(const JASSoundParams& params) { } inner_.field_0x26c = 1; - inner_.track.setSeqData(inner_.mSeqData.field_0x0, inner_.mSeqData.field_0x4); + inner_.track.setSeqData(inner_.mSeqData.mBase, inner_.mSeqData.mOffset); inner_.track.startSeq(); } diff --git a/libs/JSystem/src/JAudio2/JAISeq.cpp b/libs/JSystem/src/JAudio2/JAISeq.cpp index e3d07d5418..c05494b82e 100644 --- a/libs/JSystem/src/JAudio2/JAISeq.cpp +++ b/libs/JSystem/src/JAudio2/JAISeq.cpp @@ -40,7 +40,7 @@ void JAISeq::JAISeqMgr_startID_(JAISoundID id, const JGeometry::TVec3* posP void JAISeq::playSeqData_(const JASSoundParams& params, JAISoundActivity activity) { JUT_ASSERT(72, JASTrack_isFreeOrStopped( & inner_.outputTrack )); - inner_.outputTrack.setSeqData(inner_.mSeqData.field_0x0, inner_.mSeqData.field_0x4); + inner_.outputTrack.setSeqData(inner_.mSeqData.mBase, inner_.mSeqData.mOffset); if (audible_) { initTrack_JAISound_(&inner_.outputTrack); } else { diff --git a/libs/JSystem/src/JAudio2/JAIStream.cpp b/libs/JSystem/src/JAudio2/JAIStream.cpp index 72f37ec248..5799080b12 100644 --- a/libs/JSystem/src/JAudio2/JAIStream.cpp +++ b/libs/JSystem/src/JAudio2/JAIStream.cpp @@ -48,7 +48,7 @@ void JAIStream::JAIStreamMgr_startID_(JAISoundID id, s32 streamFileEntry, } bool JAIStream::prepare_prepareStream_() { - u32 local_28; + u32 size; JAIStreamAramMgr* streamAramMgr; switch (field_0x290) { @@ -56,9 +56,9 @@ bool JAIStream::prepare_prepareStream_() { streamAramMgr = streamMgr_->getStreamAramMgr(); JUT_ASSERT(100, streamAramMgr); - streamAramAddr_ = streamAramMgr->newStreamAram(&local_28); + streamAramAddr_ = streamAramMgr->newStreamAram(&size); if (streamAramAddr_ != NULL) { - inner_.aramStream_.init((uintptr_t)streamAramAddr_, local_28, &JAIStream_JASAramStreamCallback_, this); + inner_.aramStream_.init((uintptr_t)streamAramAddr_, size, &JAIStream_JASAramStreamCallback_, this); field_0x290 = 1; prepareCount_ = 0; } else { diff --git a/libs/JSystem/src/JAudio2/JASAiCtrl.cpp b/libs/JSystem/src/JAudio2/JASAiCtrl.cpp index 4e1c296388..75b475342b 100644 --- a/libs/JSystem/src/JAudio2/JASAiCtrl.cpp +++ b/libs/JSystem/src/JAudio2/JASAiCtrl.cpp @@ -18,6 +18,8 @@ #include #include +#include "tracy/Tracy.hpp" + s16* JASDriver::sDmaDacBuffer[3]; static u8 data_804507A8 = 3; @@ -98,7 +100,10 @@ void JASDriver::setOutputRate(JASOutputRate param_0) { sSubFrames = 10; sDacRate = 48000.0f; } + +#if !TARGET_PC sDacRate *= 1.0008897f; +#endif } const JASDriver::MixFunc JASDriver::sMixFuncs[4] = { @@ -140,6 +145,7 @@ void JASDriver::updateDac() { } void JASDriver::updateDSP() { + ZoneScoped; JASProbe::start(3, "SFR-UPDATE"); JASDsp::invalChannelAll(); @@ -149,6 +155,8 @@ void JASDriver::updateDSP() { JASPortCmd::execAllCommand(); DSPSyncCallback(); +#if !TARGET_PC + // Safety kill code? Our audio engine isn't consistent enough and hits this incorrectly. static u32 old_time = 0; static u32 history[10] = {0x000F4240}; u32 r28 = OSGetTick(); @@ -169,6 +177,7 @@ void JASDriver::updateDSP() { JASDSPChannel::killActiveChannel(); #endif } +#endif JASChannel::receiveBankDisposeMsg(); JASDSPChannel::updateAll(); @@ -254,6 +263,10 @@ void JASDriver::finishDSPFrame() { } void JASDriver::registerMixCallback(MixCallback param_0, JASMixMode param_1) { +#if TARGET_PC + JASCriticalSection section; +#endif + extMixCallback = param_0; sMixMode = param_1; } @@ -271,11 +284,11 @@ u32 JASDriver::getSubFrames() { } u32 JASDriver::getDacSize() { - return sSubFrames * 0x50 * 2; + return sSubFrames * DSP_SUBFRAME_SIZE * 2; } u32 JASDriver::getFrameSamples() { - return sSubFrames * 0x50; + return sSubFrames * DSP_SUBFRAME_SIZE; } void JASDriver::mixMonoTrack(s16* buffer, u32 param_1, MixCallback param_2) { diff --git a/libs/JSystem/src/JAudio2/JASAramStream.cpp b/libs/JSystem/src/JAudio2/JASAramStream.cpp index 14f3221711..64ddfc467e 100644 --- a/libs/JSystem/src/JAudio2/JASAramStream.cpp +++ b/libs/JSystem/src/JAudio2/JASAramStream.cpp @@ -1,11 +1,12 @@ #include "JSystem/JSystem.h" // IWYU pragma: keep -#include "JSystem/JAudio2/JASAramStream.h" #include "JSystem/JAudio2/JASAiCtrl.h" +#include "JSystem/JAudio2/JASAramStream.h" +#include "JSystem/JAudio2/JASAudioThread.h" #include "JSystem/JAudio2/JASChannel.h" #include "JSystem/JAudio2/JASCriticalSection.h" -#include "JSystem/JAudio2/JASDriverIF.h" #include "JSystem/JAudio2/JASDSPInterface.h" +#include "JSystem/JAudio2/JASDriverIF.h" #include "JSystem/JAudio2/JASDvdThread.h" #include "JSystem/JKernel/JKRAram.h" #include "JSystem/JKernel/JKRSolidHeap.h" @@ -19,8 +20,23 @@ u32 JASAramStream::sBlockSize; u32 JASAramStream::sChannelMax; -bool struct_80451260; -bool struct_80451261; +bool dvdHasErrored; +bool hasErrored; + +#define PAUSE_REQUESTED 1 +#define PAUSE_DVD_ERROR 2 +#define PAUSE_UNDERFLOW 4 +#define PAUSE_OTHER_ERROR 8 + +// CMDs for mMainCommandQueue. +#define CMD_START 0 +#define CMD_STOP 1 // upper 16 bits of cmd contain oscillator direct release value. +#define CMD_PAUSE 2 +#define CMD_UNPAUSE 3 + +// CMDs for mLoadCommandQueue +#define CMD_PREPARE_FINISHED 4 +#define CMD_LOOP_END_LOADED 5 void JASAramStream::initSystem(u32 block_size, u32 channel_max) { JUT_ASSERT(66, block_size % 32 == 0); @@ -33,42 +49,46 @@ void JASAramStream::initSystem(u32 block_size, u32 channel_max) { if (sLoadThread == NULL) { sLoadThread = JASDvd::getThreadPointer(); } + + // Pretty sure this 0x20 corresponds to sizeof(BlockHeader). + // But that shouldn't be getting multiplied by the channel count. + // Bug in the original game, I guess? sReadBuffer = JKR_NEW_ARRAY_ARGS(u8, (block_size + 0x20) * channel_max, JASDram, 0x20); JUT_ASSERT(79, sReadBuffer); sBlockSize = block_size; sChannelMax = channel_max; - struct_80451260 = false; - struct_80451261 = false; + dvdHasErrored = false; + hasErrored = false; } } JASAramStream::JASAramStream() { - field_0x0a8 = NULL; - field_0x0ac = false; - field_0x0ad = false; - field_0x0ae = 0; + mPrimaryChannel = NULL; + mPrepareFinished = false; + mLoopEndLoaded = false; + mPauseFlags = 0; field_0x0b0 = 0; - field_0x0b4 = 0; - field_0x0b8 = 0; + mLastSamplesLeft = 0; + mReadSample = 0; field_0x0bc = 0; - field_0x0c0 = false; + mEndSetup = false; field_0x0c4 = 0; field_0x0c8 = 0.0f; - field_0x108 = 0; - field_0x10c = 0; + mRingEndIndex = 0; + mBlockRingIndex = 0; mBlock = 0; - field_0x114 = 0; - field_0x118 = 0; - field_0x12c = 0; - field_0x148 = 0; - field_0x14c = 0; + mIsCancelled = 0; + mPendingLoadTasks = 0; + mChannelUpdateFlags = 0; + mAramAddress = 0; + mAramSize = 0; mCallback = NULL; mCallbackData = NULL; - field_0x158 = 0; + mFormat = 0; mChannelNum = 0; mBufCount = 0; - field_0x160 = 0; - field_0x164 = 0; + mAramBlocksPerChannel = 0; + mSampleRate = 0; mLoop = false; mLoopStart = 0; mLoopEnd = 0; @@ -76,27 +96,27 @@ JASAramStream::JASAramStream() { mPitch = 1.0f; for (int i = 0; i < 6; i++) { mChannels[i] = NULL; - field_0x130[i] = 0; - field_0x13c[i] = 0; + mpLasts[i] = 0; + mpPenults[i] = 0; mChannelVolume[i] = 1.0f; mChannelPan[i] = 0.5f; mChannelFxMix[i] = 0.0f; mChannelDolby[i] = 0.0f; } for (int i = 0; i < 6; i++) { - field_0x1dc[i] = 0; + mMixConfig[i] = 0; } } -void JASAramStream::init(u32 param_0, u32 param_1, StreamCallback i_callback, void* i_callbackData) { +void JASAramStream::init(u32 aramAddress, u32 aramSize, StreamCallback i_callback, void* i_callbackData) { JUT_ASSERT(153, sReadBuffer != NULL); - field_0x148 = param_0; - field_0x14c = param_1; + mAramAddress = aramAddress; + mAramSize = aramSize; field_0x0c8 = 0.0f; - field_0x0ae = 0; - field_0x0ac = false; - field_0x0ad = false; - field_0x114 = 0; + mPauseFlags = 0; + mPrepareFinished = false; + mLoopEndLoaded = false; + mIsCancelled = 0; mChannelNum = 0; for (int i = 0; i < 6; i++) { mChannelVolume[i] = 1.0f; @@ -106,11 +126,11 @@ void JASAramStream::init(u32 param_0, u32 param_1, StreamCallback i_callback, vo } mVolume = 1.0f; mPitch = 1.0f; - field_0x1dc[0] = 0xffff; + mMixConfig[0] = 0xffff; mCallback = i_callback; mCallbackData = i_callbackData; - OSInitMessageQueue(&field_0x000, field_0x040, 0x10); - OSInitMessageQueue(&field_0x020, field_0x080, 4); + OSInitMessageQueue(&mMainCommandQueue, mMainCommandQueueArray, ARRAY_SIZEU(mMainCommandQueueArray)); + OSInitMessageQueue(&mLoadCommandQueue, mLoadCommandQueueArray, ARRAY_SIZEU(mLoadCommandQueueArray)); } bool JASAramStream::prepare(s32 param_0, int param_1) { @@ -124,9 +144,9 @@ bool JASAramStream::prepare(s32 param_0, int param_1) { } TaskData data; data.stream = this; - data.field_0x4 = field_0x14c; - data.field_0x8 = param_1; - if (!sLoadThread->sendCmdMsg(headerLoadTask, &data, 0xc)) { + data.param0 = mAramSize; + data.param1 = param_1; + if (!sLoadThread->sendCmdMsg(headerLoadTask, &data, sizeof(data))) { JUT_WARN(254, "%s", "sendCmdMsg headerLoadTask Failed"); JASDriver::rejectCallback(channelProcCallback, this); return false; @@ -135,24 +155,24 @@ bool JASAramStream::prepare(s32 param_0, int param_1) { } bool JASAramStream::start() { - if (!OSSendMessage(&field_0x000, (OSMessage)0, OS_MESSAGE_NOBLOCK)) { + if (!OSSendMessage(&mMainCommandQueue, (OSMessage)CMD_START, OS_MESSAGE_NOBLOCK)) { JUT_WARN(273, "%s", "OSSendMessage Failed") return false; } return true; } -bool JASAramStream::stop(u16 param_0) { - if (!OSSendMessage(&field_0x000, (OSMessage)(uintptr_t)(param_0 << 0x10 | 1), OS_MESSAGE_NOBLOCK)) { +bool JASAramStream::stop(u16 directRelease) { + if (!OSSendMessage(&mMainCommandQueue, (OSMessage)(uintptr_t)(directRelease << 0x10 | CMD_STOP), OS_MESSAGE_NOBLOCK)) { JUT_WARN(290, "%s", "OSSendMessage Failed"); return false; } return true; } -bool JASAramStream::pause(bool param_0) { - OSMessage msg = param_0 ? (OSMessage)2 : (OSMessage)3; - if (!OSSendMessage(&field_0x000, msg, OS_MESSAGE_NOBLOCK)) { +bool JASAramStream::pause(bool newPauseFlag) { + OSMessage msg = newPauseFlag ? (OSMessage)CMD_PAUSE : (OSMessage)CMD_UNPAUSE; + if (!OSSendMessage(&mMainCommandQueue, msg, OS_MESSAGE_NOBLOCK)) { JUT_WARN(308, "%s", "OSSendMessage Failed"); return false; } @@ -160,7 +180,7 @@ bool JASAramStream::pause(bool param_0) { } bool JASAramStream::cancel() { - field_0x114 = 1; + mIsCancelled = 1; if (!sLoadThread->sendCmdMsg(finishTask, this)) { JUT_WARN(326, "%s", "sendCmdMsg finishTask Failed"); return false; @@ -169,12 +189,12 @@ bool JASAramStream::cancel() { } u32 JASAramStream::getBlockSamples() const { - return field_0x158 == 0 ? (sBlockSize << 4) / 9 : sBlockSize >> 1; + return mFormat == STREAM_FORMAT_ADPCM4 ? (sBlockSize << 4) / 9 : sBlockSize >> 1; } void JASAramStream::headerLoadTask(void* i_data) { TaskData* data = (TaskData*)i_data; - data->stream->headerLoad(data->field_0x4, data->field_0x8); + data->stream->headerLoad(data->param0, data->param1); } void JASAramStream::firstLoadTask(void* i_data) { @@ -183,23 +203,23 @@ void JASAramStream::firstLoadTask(void* i_data) { if (!_this->load()) { return; } - if (data->field_0x8 > 0) { - data->field_0x8--; - if (data->field_0x8 == 0) { + if (data->param1 > 0) { + data->param1--; + if (data->param1 == 0) { if (!sLoadThread->sendCmdMsg(prepareFinishTask, _this)) { JUT_WARN(364, "%s", "sendCmdMsg prepareFinishTask Failed"); - struct_80451261 = true; + hasErrored = true; } } } - if (data->field_0x4 != 0) { - data->field_0x4--; - if (!sLoadThread->sendCmdMsg(firstLoadTask, data, 0xc)) { + if (data->param0 != 0) { + data->param0--; + if (!sLoadThread->sendCmdMsg(firstLoadTask, data, sizeof(*data))) { JUT_WARN(372, "%s", "sendCmdMsg firstLoadTask Failed"); - struct_80451261 = true; + hasErrored = true; } JASCriticalSection cs; - _this->field_0x118++; + _this->mPendingLoadTasks++; } } @@ -221,22 +241,22 @@ void JASAramStream::finishTask(void* i_this) { void JASAramStream::prepareFinishTask(void* i_this) { JASAramStream* _this = (JASAramStream*)i_this; - OSSendMessage(&_this->field_0x020, (OSMessage)4, OS_MESSAGE_BLOCK); + OSSendMessage(&_this->mLoadCommandQueue, (OSMessage)CMD_PREPARE_FINISHED, OS_MESSAGE_BLOCK); if (_this->mCallback != NULL) { _this->mCallback(CB_STOP, _this, _this->mCallbackData); } } -bool JASAramStream::headerLoad(u32 param_0, int param_1) { - if (struct_80451261) { +bool JASAramStream::headerLoad(u32 aramSize, int param_1) { + if (hasErrored) { return false; } - if (field_0x114 != 0) { + if (mIsCancelled != 0) { return false; } if (DVDReadPrio(&mDvdFileInfo, sReadBuffer, sizeof(Header), 0, 1) < 0) { JUT_WARN(420, "%s", "DVDReadPrio Failed"); - struct_80451261 = true; + hasErrored = true; return false; } Header* header = (Header*)sReadBuffer; @@ -245,45 +265,45 @@ bool JASAramStream::headerLoad(u32 param_0, int param_1) { JUT_ASSERT(428, header->bits == 16); JUT_ASSERT(429, header->channels <= sChannelMax); JUT_ASSERT(430, header->block_size == sBlockSize); - field_0x158 = header->format; + mFormat = header->format; mChannelNum = header->channels; - field_0x164 = header->field_0x10; + mSampleRate = header->mSampleRate; mLoop = header->loop != 0; mLoopStart = header->loop_start; mLoopEnd = header->loop_end; - mVolume = header->field_0x28 / 127.0f; - field_0x118 = 0; + mVolume = header->mVolume / 127.0f; + mPendingLoadTasks = 0; mBlock = 0; - field_0x10c = 0; - field_0x160 = (param_0 / sBlockSize) / header->channels; - mBufCount = field_0x160; + mBlockRingIndex = 0; + mAramBlocksPerChannel = (aramSize / sBlockSize) / header->channels; + mBufCount = mAramBlocksPerChannel; JUT_ASSERT(445, mBufCount > 0); mBufCount--; if (mBufCount < 3) { JUT_WARN(449, "%s", "Too few Buffer-Size"); } - field_0x108 = mBufCount; + mRingEndIndex = mBufCount; u32 local_2c = (mLoopEnd - 1) / getBlockSamples(); if (local_2c <= mBufCount && mLoop) { JUT_WARN(458, "%s", "Too few samples for Loop-buffer"); } - if (param_1 < 0 || param_1 > field_0x108) { - param_1 = field_0x108; + if (param_1 < 0 || param_1 > mRingEndIndex) { + param_1 = mRingEndIndex; } - if (field_0x114 != 0) { + if (mIsCancelled != 0) { return false; } TaskData data; data.stream = this; - data.field_0x4 = field_0x108 - 1; - data.field_0x8 = param_1; - if (!sLoadThread->sendCmdMsg(firstLoadTask, &data, 0xc)) { + data.param0 = mRingEndIndex - 1; + data.param1 = param_1; + if (!sLoadThread->sendCmdMsg(firstLoadTask, &data, sizeof(data))) { JUT_WARN(472, "%s", "sendCmdMsg firstLoadTask Failed"); - struct_80451261 = true; + hasErrored = true; return false; } JASCriticalSection cs; - field_0x118++; + mPendingLoadTasks++; return true; } @@ -291,12 +311,12 @@ bool JASAramStream::headerLoad(u32 param_0, int param_1) { bool JASAramStream::load() { { JASCriticalSection cs; - field_0x118--; + mPendingLoadTasks--; } - if (struct_80451261) { + if (hasErrored) { return false; } - if (field_0x114 != 0) { + if (mIsCancelled != 0) { return false; } u32 loop_end_block = (mLoopEnd - 1) / getBlockSamples(); @@ -311,31 +331,31 @@ bool JASAramStream::load() { } if (DVDReadPrio(&mDvdFileInfo, sReadBuffer, size, offset, 1) < 0) { JUT_WARN(507, "%s", "DVDReadPrio Failed"); - struct_80451261 = true; + hasErrored = true; return false; } BlockHeader* bhead = (BlockHeader*)sReadBuffer; JUT_ASSERT(512, bhead->tag == 'BLCK'); - if (field_0x114 != 0) { + if (mIsCancelled != 0) { return false; } - u32 sp08 = field_0x148 + field_0x10c * sBlockSize; + u32 blockBaseOffset = mAramAddress + mBlockRingIndex * sBlockSize; for (int i = 0; i < mChannelNum; i++) { (void)i; // Fakematch? It seems the only way to get the bhead->field_0x4 load in the right order is // with a pointer cast on its address in one of the two places it is read, but not both. - if (!JKRMainRamToAram(sReadBuffer + *(u32*)&bhead->field_0x4 * i + sizeof(BlockHeader), - sp08 + sBlockSize * field_0x160 * i, - bhead->field_0x4, EXPAND_SWITCH_UNKNOWN0, 0, NULL, -1, NULL)) { + if (!JKRMainRamToAram(sReadBuffer + bhead->mSize * i + sizeof(BlockHeader), + blockBaseOffset + sBlockSize * mAramBlocksPerChannel * i, + bhead->mSize, EXPAND_SWITCH_UNKNOWN0, 0, NULL, -1, NULL)) { JUT_WARN(522, "%s", "JKRMainRamToAram Failed"); - struct_80451261 = 1; + hasErrored = 1; return false; } } - field_0x10c++; - if (field_0x10c >= field_0x108) { + mBlockRingIndex++; + if (mBlockRingIndex >= mRingEndIndex) { u32 r28 = mBlock; - r28 += field_0x108 - 1; + r28 += mRingEndIndex - 1; if (mLoop) { JUT_ASSERT(537, loop_start_block < loop_end_block); while (r28 > loop_end_block) { @@ -344,16 +364,16 @@ bool JASAramStream::load() { } } if (r28 == loop_end_block || r28 + 2 == loop_end_block) { - field_0x108 = field_0x160; - OSSendMessage(&field_0x020, (OSMessage)5, OS_MESSAGE_BLOCK); + mRingEndIndex = mAramBlocksPerChannel; + OSSendMessage(&mLoadCommandQueue, (OSMessage)CMD_LOOP_END_LOADED, OS_MESSAGE_BLOCK); } else { - field_0x108 = field_0x160 - 1; + mRingEndIndex = mAramBlocksPerChannel - 1; } for (int i = 0; i < mChannelNum; i++) { - field_0x130[i] = (s16)bhead->field_0x8[i].field_0x0; - field_0x13c[i] = (s16)bhead->field_0x8[i].field_0x2; + mpLasts[i] = (s16)bhead->mAdpcmContinuationData[i].mpLast; + mpPenults[i] = (s16)bhead->mAdpcmContinuationData[i].mpPenult; } - field_0x10c = 0; + mBlockRingIndex = 0; } mBlock++; if (mBlock > loop_end_block && mLoop) { @@ -371,7 +391,7 @@ s32 JASAramStream::dvdErrorCheck(void* param_0) { s32 status = DVDGetDriveStatus(); switch (status) { case DVD_STATE_END: - struct_80451260 = false; + dvdHasErrored = false; break; case DVD_STATE_BUSY: break; @@ -385,7 +405,7 @@ s32 JASAramStream::dvdErrorCheck(void* param_0) { case DVD_STATE_RETRY: case DVD_STATE_FATAL_ERROR: default: - struct_80451260 = true; + dvdHasErrored = true; break; } return 0; @@ -397,98 +417,125 @@ void JASAramStream::channelCallback(u32 i_callbackType, JASChannel* i_channel, stream->updateChannel(i_callbackType, i_channel, i_dspChannel); } +#define CHANNEL_UPDATE_SAMPLES_LEFT 1 +#define CHANNEL_UPDATE_LOOP_START 2 +#define CHANNEL_UPDATE_END_SAMPLE 4 +#define CHANNEL_UPDATE_LOOP_FLAG 8 + + void JASAramStream::updateChannel(u32 i_callbackType, JASChannel* i_channel, JASDsp::TChannel* i_dspChannel) { u32 block_samples = getBlockSamples(); switch (i_callbackType) { case JASChannel::CB_START: - if (field_0x0a8 == NULL) { - field_0x0a8 = i_channel; - field_0x0b4 = block_samples * mBufCount; - field_0x0b8 = 0; + if (mPrimaryChannel == NULL) { + mPrimaryChannel = i_channel; + mLastSamplesLeft = block_samples * mBufCount; + mReadSample = 0; field_0x0b0 = 0; field_0x0bc = (mLoopEnd - 1) / block_samples; - field_0x0c0 = 0; + mEndSetup = 0; field_0x0c4 = 0; - field_0x12c = 0; + mChannelUpdateFlags = 0; } break; case JASChannel::CB_PLAY: - if (i_dspChannel->field_0x008 == 0) { - if (i_channel == field_0x0a8) { - field_0x12c = 0; - u32 sp28 = i_dspChannel->field_0x074 + i_dspChannel->field_0x064; - if (sp28 <= field_0x0b4) { - field_0x0b8 += field_0x0b4 - sp28; + if (i_dspChannel->mResetFlag == 0) { + if (i_channel == mPrimaryChannel) { + /* + if (JASAudioThread::snIntCount == 1) { + OSReportForceEnableOn(); + OSReport("mSamplesLeft: %08d, mAramStreamPosition: %08d\n", i_dspChannel->mSamplesLeft, i_dspChannel->mAramStreamPosition); + } + */ + + mChannelUpdateFlags = 0; + u32 adjustedSamplesLeft = i_dspChannel->mSamplesLeft + i_dspChannel->mSamplesPerBlock; + if (adjustedSamplesLeft <= mLastSamplesLeft) { + mReadSample += mLastSamplesLeft - adjustedSamplesLeft; } else { - if (!field_0x0c0) { - field_0x0b8 += field_0x0b4; - field_0x0b8 += block_samples * mBufCount - sp28; + // The DSP has looped. + + if (!mEndSetup) { + // Just looping the ring buffer, data continues as normal. + mReadSample += mLastSamplesLeft; + mReadSample += block_samples * mBufCount - adjustedSamplesLeft; } else { - field_0x0b8 += field_0x0b4; - field_0x0b8 += block_samples * mBufCount - sp28 - - i_dspChannel->field_0x110; - field_0x0b8 -= mLoopEnd; - field_0x0b8 += mLoopStart; - i_dspChannel->field_0x110 = 0; - field_0x120 = 0; - field_0x12c |= 2; + // We hit the actual file loop position. + mReadSample += mLastSamplesLeft; + mReadSample += block_samples * mBufCount - adjustedSamplesLeft + - i_dspChannel->mLoopStartSample; + mReadSample -= mLoopEnd; + mReadSample += mLoopStart; + i_dspChannel->mLoopStartSample = 0; + mUpdateLoopStartSample = 0; + mChannelUpdateFlags |= CHANNEL_UPDATE_LOOP_START; +#if !TARGET_PC // The variable assigned here is never used. if (field_0x0c4 < 0xffffffff) { field_0x0c4 += 1; } - field_0x0c0 = false; +#endif + mEndSetup = false; } } - if (field_0x0b8 > mLoopEnd) { + if (mReadSample > mLoopEnd) { JUT_WARN(686, "%s", "mReadSample > mLoopEnd"); - struct_80451261 = true; + hasErrored = true; } + +#if !TARGET_PC // The variable assigned here is never used. f32 fvar1 = field_0x0c4; fvar1 *= mLoopEnd - mLoopStart; if (field_0x0c4 < 0xffffffff) { - fvar1 += field_0x0b8; + fvar1 += mReadSample; } - fvar1 /= field_0x164; + fvar1 /= mSampleRate; field_0x0c8 = fvar1; - if (field_0x0b8 + 400 >= mLoopEnd && !field_0x0c0) { +#endif + + if (mReadSample + 400 >= mLoopEnd && !mEndSetup) { if (mLoop) { + // File needs to loop. Adjust loop start position + // (out of the normal ring buffer behavior). u32 uvar5 = field_0x0bc + 1; if (uvar5 >= mBufCount) { uvar5 = 0; } - i_dspChannel->field_0x110 = mLoopStart % block_samples + i_dspChannel->mLoopStartSample = mLoopStart % block_samples + uvar5 * block_samples; - field_0x120 = i_dspChannel->field_0x110; - field_0x12c |= 2; + mUpdateLoopStartSample = i_dspChannel->mLoopStartSample; + mChannelUpdateFlags |= CHANNEL_UPDATE_LOOP_START; } else { - i_dspChannel->field_0x102 = 0; - field_0x128 = 0; - field_0x12c |= 8; + // File doesn't need to loop, just unset loop flag + // and let the DSP finish naturally. + i_dspChannel->mLoopFlag = 0; + mUpdateLoopFlag = 0; + mChannelUpdateFlags |= CHANNEL_UPDATE_LOOP_FLAG; } int sp20 = field_0x0bc * block_samples + mLoopEnd % block_samples; - i_dspChannel->field_0x074 -= block_samples * mBufCount - sp20; - field_0x11c = i_dspChannel->field_0x074; - field_0x12c |= 1; + i_dspChannel->mSamplesLeft -= block_samples * mBufCount - sp20; + mUpdateSamplesLeft = i_dspChannel->mSamplesLeft; + mChannelUpdateFlags |= CHANNEL_UPDATE_SAMPLES_LEFT; field_0x0bc += (mLoopEnd - 1) / block_samples - mLoopStart / block_samples + 1; - field_0x0c0 = true; + mEndSetup = true; } - u32 uvar4 = i_dspChannel->field_0x070 - i_channel->field_0x104; + u32 uvar4 = i_dspChannel->mAramStreamPosition - i_channel->mWaveAramAddress; if (uvar4 != 0) { uvar4--; } - u32 sp18 = uvar4 / sBlockSize; + u32 blockCount = uvar4 / sBlockSize; u32 sp14 = (mLoopEnd - 1) / getBlockSamples(); - if (sp18 != field_0x0b0) { - bool cmp = sp18 < field_0x0b0; - while (sp18 != field_0x0b0) { + if (blockCount != field_0x0b0) { + bool cmp = blockCount < field_0x0b0; + while (blockCount != field_0x0b0) { if (!sLoadThread->sendCmdMsg(loadToAramTask, this)) { - JUT_WARN(741, "sendCmdMsg Failed %d %d (%d %d)", i_dspChannel->field_0x070, i_channel->field_0x104, sp18, field_0x0b0); - struct_80451261 = true; + JUT_WARN(741, "sendCmdMsg Failed %d %d (%d %d)", i_dspChannel->mAramStreamPosition, i_channel->mWaveAramAddress, blockCount, field_0x0b0); + hasErrored = true; break; } { JASCriticalSection cs; - field_0x118++; + mPendingLoadTasks++; } field_0x0b0++; if (field_0x0b0 >= mBufCount) { @@ -497,65 +544,65 @@ void JASAramStream::updateChannel(u32 i_callbackType, JASChannel* i_channel, } if (cmp) { field_0x0bc -= mBufCount; - if (field_0x0ad) { - if (!field_0x0c0) { - i_dspChannel->field_0x074 += block_samples; - field_0x11c = i_dspChannel->field_0x074; - field_0x12c |= 1; + if (mLoopEndLoaded) { + if (!mEndSetup) { + i_dspChannel->mSamplesLeft += block_samples; + mUpdateSamplesLeft = i_dspChannel->mSamplesLeft; + mChannelUpdateFlags |= CHANNEL_UPDATE_SAMPLES_LEFT; } - i_dspChannel->field_0x114 += block_samples; - field_0x124 = i_dspChannel->field_0x114; - field_0x12c |= 4; - mBufCount = field_0x160; - field_0x0ad = false; + i_dspChannel->mEndSample += block_samples; + mUpdateEndSample = i_dspChannel->mEndSample; + mChannelUpdateFlags |= CHANNEL_UPDATE_END_SAMPLE; + mBufCount = mAramBlocksPerChannel; + mLoopEndLoaded = false; } else { - if (mBufCount != field_0x160 - 1) { - mBufCount = field_0x160 - 1; - i_dspChannel->field_0x114 -= block_samples; - field_0x124 = i_dspChannel->field_0x114; - field_0x12c |= 4; - if (!field_0x0c0) { - i_dspChannel->field_0x074 -= block_samples; - field_0x11c = i_dspChannel->field_0x074; - field_0x12c |= 1; + if (mBufCount != mAramBlocksPerChannel - 1) { + mBufCount = mAramBlocksPerChannel - 1; + i_dspChannel->mEndSample -= block_samples; + mUpdateEndSample = i_dspChannel->mEndSample; + mChannelUpdateFlags |= CHANNEL_UPDATE_END_SAMPLE; + if (!mEndSetup) { + i_dspChannel->mSamplesLeft -= block_samples; + mUpdateSamplesLeft = i_dspChannel->mSamplesLeft; + mChannelUpdateFlags |= CHANNEL_UPDATE_SAMPLES_LEFT; } } } } } else { - if (field_0x118 == 0 && !struct_80451260) { - field_0x0ae &= ~2; - field_0x0ae &= ~4; + if (mPendingLoadTasks == 0 && !dvdHasErrored) { + mPauseFlags &= ~PAUSE_DVD_ERROR; + mPauseFlags &= ~PAUSE_UNDERFLOW; } } - field_0x0b4 = i_dspChannel->field_0x074 + i_dspChannel->field_0x064; - if (field_0x118 >= field_0x160 - 2) { + mLastSamplesLeft = i_dspChannel->mSamplesLeft + i_dspChannel->mSamplesPerBlock; + if (mPendingLoadTasks >= mAramBlocksPerChannel - 2) { JUT_WARN_DEVICE(810, 1, "%s", "buffer under error"); - field_0x0ae |= (u8)4; + mPauseFlags |= (u8)PAUSE_UNDERFLOW; } } else { - if (field_0x12c & 1) { - i_dspChannel->field_0x074 = field_0x11c; + if (mChannelUpdateFlags & CHANNEL_UPDATE_SAMPLES_LEFT) { + i_dspChannel->mSamplesLeft = mUpdateSamplesLeft; } - if (field_0x12c & 2) { - i_dspChannel->field_0x110 = field_0x120; + if (mChannelUpdateFlags & CHANNEL_UPDATE_LOOP_START) { + i_dspChannel->mLoopStartSample = mUpdateLoopStartSample; } - if (field_0x12c & 4) { - i_dspChannel->field_0x114 = field_0x124; + if (mChannelUpdateFlags & CHANNEL_UPDATE_END_SAMPLE) { + i_dspChannel->mEndSample = mUpdateEndSample; } - if (field_0x12c & 8) { - i_dspChannel->field_0x102 = field_0x128; + if (mChannelUpdateFlags & CHANNEL_UPDATE_LOOP_FLAG) { + i_dspChannel->mLoopFlag = mUpdateLoopFlag; } } int ch = 0; - for (; ch < 6; ch++) { + for (; ch < CHANNEL_MAX; ch++) { if (i_channel == mChannels[ch]) { break; } } JUT_ASSERT(834, ch < CHANNEL_MAX); - i_dspChannel->field_0x104 = (s16)field_0x130[ch]; - i_dspChannel->field_0x106 = (s16)field_0x13c[ch]; + i_dspChannel->mpLast = (s16)mpLasts[ch]; + i_dspChannel->mpPenult = (s16)mpPenults[ch]; } break; case JASChannel::CB_STOP: @@ -568,57 +615,57 @@ void JASAramStream::updateChannel(u32 i_callbackType, JASChannel* i_channel, } } if (!open_channel) { - field_0x114 = 1; + mIsCancelled = 1; if (!sLoadThread->sendCmdMsg(finishTask, this)) { JUT_WARN(854, "%s", "sendCmdMsg finishTask Failed"); - struct_80451261 = true; + hasErrored = true; return; } } break; } - i_channel->setPauseFlag(field_0x0ae != 0); + i_channel->setPauseFlag(mPauseFlags != 0); } s32 JASAramStream::channelProc() { OSMessage msg; - while (OSReceiveMessage(&field_0x020, &msg, OS_MESSAGE_NOBLOCK)) { + while (OSReceiveMessage(&mLoadCommandQueue, &msg, OS_MESSAGE_NOBLOCK)) { switch ((uintptr_t)msg) { - case 4: - field_0x0ac = true; + case CMD_PREPARE_FINISHED: + mPrepareFinished = true; break; - case 5: - field_0x0ad = true; + case CMD_LOOP_END_LOADED: + mLoopEndLoaded = true; break; } } - if (!field_0x0ac) { + if (!mPrepareFinished) { return 0; } - while (OSReceiveMessage(&field_0x000, &msg, OS_MESSAGE_NOBLOCK)) { + while (OSReceiveMessage(&mMainCommandQueue, &msg, OS_MESSAGE_NOBLOCK)) { switch ((uintptr_t)msg & 0xff) { - case 0: + case CMD_START: channelStart(); break; - case 1: + case CMD_STOP: channelStop(JSUHiHalf((uintptr_t)msg)); break; - case 2: - field_0x0ae |= 1; + case CMD_PAUSE: + mPauseFlags |= PAUSE_REQUESTED; break; - case 3: - field_0x0ae &= ~1; + case CMD_UNPAUSE: + mPauseFlags &= ~PAUSE_REQUESTED; break; } } - if (struct_80451261) { - field_0x0ae |= 8; + if (hasErrored) { + mPauseFlags |= PAUSE_OTHER_ERROR; } - if (struct_80451260) { - field_0x0ae |= 2; + if (dvdHasErrored) { + mPauseFlags |= PAUSE_DVD_ERROR; } for (int i = 0; i < mChannelNum; i++) { @@ -646,44 +693,44 @@ static JASOscillator::Point const OSC_RELEASE_TABLE[2] = { static JASOscillator::Data const OSC_ENV = {0, 1.0f, NULL, OSC_RELEASE_TABLE, 1.0f, 0.0f}; void JASAramStream::channelStart() { - u8 r31; - switch (field_0x158) { - case 0: - r31 = 0; + u8 format; + switch (mFormat) { + case STREAM_FORMAT_ADPCM4: + format = WAVE_FORMAT_ADPCM4; break; - case 1: - r31 = 3; + case STREAM_FORMAT_PCM16: + format = WAVE_FORMAT_PCM16; break; } for (int i = 0; i < mChannelNum; i++) { JASWaveInfo wave_info; - wave_info.field_0x00 = r31; - wave_info.field_0x02 = 0xff; - wave_info.field_0x10 = 0; - wave_info.field_0x14 = mBufCount * getBlockSamples(); - wave_info.field_0x18 = wave_info.field_0x14; - wave_info.field_0x1c = 0; - wave_info.field_0x1e = 0; + wave_info.mWaveFormat = format; + wave_info.mLoopFlag = 0xff; + wave_info.mLoopStartSample = 0; + wave_info.mLoopEndSample = mBufCount * getBlockSamples(); + wave_info.mSampleCount = wave_info.mLoopEndSample; + wave_info.mpLast = 0; + wave_info.mpPenult = 0; // probably a fake match, this should be set in the JASWaveInfo constructor static u32 const one = 1; wave_info.field_0x20 = &one; JASChannel* jc = JKR_NEW JASChannel(channelCallback, this); JUT_ASSERT(963, jc); jc->setPriority(0x7f7f); - for (u32 j = 0; j < 6; j++) { - jc->setMixConfig(j, field_0x1dc[j]); + for (u32 j = 0; j < DSP_OUTPUT_CHANNELS; j++) { + jc->setMixConfig(j, mMixConfig[j]); } - jc->setInitPitch(field_0x164 / JASDriver::getDacRate()); + jc->setInitPitch(mSampleRate / JASDriver::getDacRate()); jc->setOscInit(0, &OSC_ENV); - jc->field_0xdc.field_0x4 = wave_info; - jc->field_0x104 = field_0x148 + sBlockSize * field_0x160 * i; - jc->field_0xdc.field_0x0 = 0; + jc->field_0xdc.mWaveInfo = wave_info; + jc->mWaveAramAddress = mAramAddress + sBlockSize * mAramBlocksPerChannel * i; + jc->field_0xdc.mChannelType = 0; int ret = jc->playForce(); JUT_ASSERT(977, ret); JUT_ASSERT_MSG(979, mChannels[i] == NULL, "channelStart for already playing channel"); mChannels[i] = jc; } - field_0x0a8 = NULL; + mPrimaryChannel = NULL; } diff --git a/libs/JSystem/src/JAudio2/JASAudioReseter.cpp b/libs/JSystem/src/JAudio2/JASAudioReseter.cpp index 4d4f3517c1..46853d03e7 100644 --- a/libs/JSystem/src/JAudio2/JASAudioReseter.cpp +++ b/libs/JSystem/src/JAudio2/JASAudioReseter.cpp @@ -47,7 +47,7 @@ s32 JASAudioReseter::checkDone() const { s32 JASAudioReseter::calc() { if (field_0x0==0) { - for (size_t i = 0; i<64; i++) { + for (size_t i = 0; igetStatus() == 0) { handle->drop(); diff --git a/libs/JSystem/src/JAudio2/JASAudioThread.cpp b/libs/JSystem/src/JAudio2/JASAudioThread.cpp index fc926b3bb5..fa476d1cb4 100644 --- a/libs/JSystem/src/JAudio2/JASAudioThread.cpp +++ b/libs/JSystem/src/JAudio2/JASAudioThread.cpp @@ -21,17 +21,8 @@ JASAudioThread::JASAudioThread(int stackSize, int msgCount, u32 threadPriority) OSInitThreadQueue(&sThreadQueue); } -#if TARGET_PC -bool JASAudioThread::sThreadInitComplete = false; -OSMutex JASAudioThread::sThreadInitCompleteMutex; -OSCond JASAudioThread::sThreadInitCompleteCond; -#endif - void JASAudioThread::create(s32 threadPriority) { -#if TARGET_PC - OSInitMutex(&sThreadInitCompleteMutex); - OSInitCond(&sThreadInitCompleteCond); -#endif + OSPanic(__FILE__, __LINE__, "JASAudioThread does not work on PC!"); #if PLATFORM_GCN const int size = 0x1400; @@ -64,12 +55,18 @@ private: BOOL mInterrupts; }; +#if !TARGET_PC class JASChannel { u8 filler[0x108]; }; +#else +// You don't want to know how long I spent debugging this. +#include "JSystem/JAudio2/JASChannel.h" +#endif // NONMATCHING location of JASPoolAllocObject_MultiThreaded void* JASAudioThread::run() { +#if !TARGET_PC OSInitFastCast(); JASDriver::initAI(DMACallback); JASDsp::boot(DSPCallback); @@ -79,13 +76,6 @@ void* JASAudioThread::run() { JASPoolAllocObject_MultiThreaded::newMemPool(0x48); JASDriver::startDMA(); -#if TARGET_PC - OSLockMutex(&sThreadInitCompleteMutex); - sThreadInitComplete = true; - OSUnlockMutex(&sThreadInitCompleteMutex); - OSSignalCond(&sThreadInitCompleteCond); -#endif - OSMessage msg; while (true) { msg = waitMessageBlock(); @@ -126,6 +116,9 @@ void* JASAudioThread::run() { JUT_PANIC(152, "AUDIO THREAD INVALID MESSAGE\n"); } } +#else + return 0; +#endif } void JASAudioThread::DMACallback() { @@ -139,6 +132,7 @@ void JASAudioThread::DMACallback() { } void JASAudioThread::DSPCallback(void*) { +#if !TARGET_PC JASAudioThread* pAudioThread = getInstance(); JUT_ASSERT(184, pAudioThread); while (DSPCheckMailFromDSP() == 0) { } @@ -155,4 +149,5 @@ void JASAudioThread::DSPCallback(void*) { JASDsp::finishWork(mail); } } +#endif } diff --git a/libs/JSystem/src/JAudio2/JASBNKParser.cpp b/libs/JSystem/src/JAudio2/JASBNKParser.cpp index b9f010ad60..ddab6d2e38 100644 --- a/libs/JSystem/src/JAudio2/JASBNKParser.cpp +++ b/libs/JSystem/src/JAudio2/JASBNKParser.cpp @@ -23,7 +23,7 @@ JASBasicBank* JASBNKParser::createBasicBank(void const* stream, JKRHeap* heap) { u32 free_size = heap->getFreeSize(); TFileHeader* filep = (TFileHeader*)stream; - JUT_ASSERT(59, filep->id == 'IBNK'); + JUT_ASSERT(59, filep->mMagic == 'IBNK'); JASBasicBank* bank = NULL; switch (filep->mVersion) { case 0: @@ -79,11 +79,11 @@ JASBasicBank* JASBNKParser::Ver1::createBasicBank(void const* stream, JKRHeap* h JUT_ASSERT(155, op->id == 'Osci'); JASOscillator::Data* data = &osc_data[i]; data->mTarget = op->mTarget; - data->_04 = op->_08; + data->mRate = op->mRate; data->mScale = op->mScale; - data->_14 = op->_18; - data->mTable = (JASOscillator::Point*)(envt + op->mTableOffset); - data->rel_table = (JASOscillator::Point*)(envt + op->_10); + data->mVertex = op->mVertex; + data->mTable = (JASOscillator::Point*)(envt + op->mAttackEnvelopeOffset); + data->rel_table = (JASOscillator::Point*)(envt + op->mReleaseEnvelopeOffset); } TListChunk* list = list_chunk; JUT_ASSERT(172, list->count <= JASBank::PRG_OSC); @@ -128,8 +128,10 @@ JASBasicBank* JASBNKParser::Ver1::createBasicBank(void const* stream, JKRHeap* h case 'Perc': { JASDrumSet* drump = JKR_NEW_ARGS (heap, 0) JASDrumSet; JUT_ASSERT(264, drump != NULL); + #if PLATFORM_SHIELD u32 pmap_count = data[1]; JUT_ASSERT(268, pmap_count <= 128); + #endif u32 count = *data++; drump->newPercArray(count, heap); for (int j = 0; j < count; j++) { @@ -137,8 +139,10 @@ JASBasicBank* JASBNKParser::Ver1::createBasicBank(void const* stream, JKRHeap* h if (offset != 0) { JASDrumSet::TPerc* percp = JKR_NEW_ARGS (heap, 0) JASDrumSet::TPerc; JUT_ASSERT(277, percp); + #if PLATFORM_SHIELD u32 type = data[0]; JUT_ASSERT(282, type == 'Pmap'); + #endif BE(u32)* ptr = (BE(u32)*)((intptr_t)stream + offset); TPercData* perc_data = (TPercData*)(ptr + 1); percp->setVolume(perc_data->mVolume); @@ -203,7 +207,7 @@ JASBasicBank* JASBNKParser::Ver0::createBasicBank(void const* stream, JKRHeap* h osc = JKR_NEW_ARGS (heap, 0) JASOscillator::Data; JUT_ASSERT(386, osc != NULL); osc->mTarget = tosc->mTarget; - osc->_04 = tosc->field_0x4; + osc->mRate = tosc->field_0x4; JASOscillator::Point* points = tosc->mPointOffset.ptr(header); if (points != NULL) { @@ -230,7 +234,7 @@ JASBasicBank* JASBNKParser::Ver0::createBasicBank(void const* stream, JKRHeap* h } osc->mScale = tosc->mScale; - osc->_14 = tosc->field_0x14; + osc->mVertex = tosc->field_0x14; instp->setOsc(osc_idx, osc); } @@ -312,7 +316,7 @@ JASOscillator::Data* JASBNKParser::Ver0::findOscPtr(JASBasicBank* bank, THeader JASOscillator::Point const* JASBNKParser::Ver0::getOscTableEndPtr(JASOscillator::Point const* points) { const JASOscillator::Point* ptr = points; while(true) { - s16 tmp = ptr->_0; + s16 tmp = ptr->mEnvelopeMode; ptr++; if (tmp > 10) { break; diff --git a/libs/JSystem/src/JAudio2/JASBank.cpp b/libs/JSystem/src/JAudio2/JASBank.cpp index 7d4fb86514..29ebe11cb5 100644 --- a/libs/JSystem/src/JAudio2/JASBank.cpp +++ b/libs/JSystem/src/JAudio2/JASBank.cpp @@ -42,13 +42,13 @@ JASChannel* JASBank::noteOn(JASBank const* param_0, int param_1, u8 param_2, u8 return NULL; } channel->setPriority(param_4); - channel->field_0xdc.field_0x4 = *waveInfo; - channel->field_0x104 = wavePtr; - channel->field_0xdc.field_0x0 = stack_60.field_0x1c; + channel->field_0xdc.mWaveInfo = *waveInfo; + channel->mWaveAramAddress = wavePtr; + channel->field_0xdc.mChannelType = stack_60.field_0x1c; channel->setBankDisposeID(param_0); - channel->setInitPitch(stack_60.mPitch * (waveInfo->field_0x04 / JASDriver::getDacRate())); + channel->setInitPitch(stack_60.mPitch * (waveInfo->mSampleRate / JASDriver::getDacRate())); if (stack_60.field_0x1e == 0) { - channel->setKey(param_2 - waveInfo->field_0x01); + channel->setKey(param_2 - waveInfo->mBaseKey); } channel->setInitVolume(stack_60.mVolume); channel->setVelocity(param_3); @@ -79,10 +79,10 @@ JASChannel* JASBank::noteOnOsc(int param_0, u8 param_1, u8 param_2, u16 param_3, return NULL; } channel->setPriority(param_3); - channel->field_0x104 = param_0; - channel->field_0xdc.field_0x0 = 2; + channel->mOscillatorSomething = param_0; + channel->field_0xdc.mChannelType = 2; channel->setInitPitch(16736.016f / JASDriver::getDacRate()); - channel->setKey(param_1 - channel->field_0xdc.field_0x4.field_0x01); + channel->setKey(param_1 - channel->field_0xdc.mWaveInfo.mBaseKey); channel->setVelocity(param_2); channel->setOscInit(0, &OSC_ENV); if (!channel->play()) { diff --git a/libs/JSystem/src/JAudio2/JASBasicWaveBank.cpp b/libs/JSystem/src/JAudio2/JASBasicWaveBank.cpp index 5387238a56..9170e59ed1 100644 --- a/libs/JSystem/src/JAudio2/JASBasicWaveBank.cpp +++ b/libs/JSystem/src/JAudio2/JASBasicWaveBank.cpp @@ -50,7 +50,7 @@ void JASBasicWaveBank::incWaveTable(JASBasicWaveBank::TWaveGroup const* param_0) if (!handle->mHeap) { handle->mHeap = ¶m_0->mHeap; handle->field_0x4.field_0x20 = ¶m_0->_48; - handle->field_0x4.field_0x08 = param_0->mCtrlWaveArray[i].field_0x4; + handle->field_0x4.mOffsetStart = param_0->mCtrlWaveArray[i].field_0x4; } } } @@ -64,7 +64,7 @@ void JASBasicWaveBank::decWaveTable(JASBasicWaveBank::TWaveGroup const* param_0) if (handle->mHeap == ¶m_0->mHeap) { handle->mHeap = NULL; handle->field_0x4.field_0x20 = &mNoLoad; - handle->field_0x4.field_0x08 = -1; + handle->field_0x4.mOffsetStart = -1; } } } @@ -86,9 +86,9 @@ void JASBasicWaveBank::setWaveInfo(JASBasicWaveBank::TWaveGroup* wgrp, int index JUT_ASSERT(206, index >= 0); mWaveTable[param_2].field_0x4 = param_3; mWaveTable[param_2].field_0x4.field_0x20 = &mNoLoad; - mWaveTable[param_2].field_0x4.field_0x08 = -1; + mWaveTable[param_2].field_0x4.mOffsetStart = -1; wgrp->mCtrlWaveArray[index].field_0x0 = param_2; - wgrp->mCtrlWaveArray[index].field_0x4 = param_3.field_0x08; + wgrp->mCtrlWaveArray[index].field_0x4 = param_3.mOffsetStart; } JASBasicWaveBank::TWaveGroup::TWaveGroup() { @@ -131,5 +131,5 @@ intptr_t JASBasicWaveBank::TWaveHandle::getWavePtr() const { if (base == 0) { return 0; } - return (intptr_t)base + field_0x4.field_0x08; + return (intptr_t)base + field_0x4.mOffsetStart; } diff --git a/libs/JSystem/src/JAudio2/JASCalc.cpp b/libs/JSystem/src/JAudio2/JASCalc.cpp index 79d9cb500f..906fee2c3d 100644 --- a/libs/JSystem/src/JAudio2/JASCalc.cpp +++ b/libs/JSystem/src/JAudio2/JASCalc.cpp @@ -132,7 +132,11 @@ void JASCalc::bzero(void* dest, u32 size) { } } +#if AVOID_UB +s16 const JASCalc::CUTOFF_TO_IIR_TABLE[129][4] = { +#else s16 const JASCalc::CUTOFF_TO_IIR_TABLE[128][4] = { +#endif 0x0F5C, 0x0A3D, 0x4665, 0x1E73, 0x0F5E, 0x0A3D, 0x4664, 0x1E73, 0x0F63, 0x0A3C, 0x4661, 0x1E71, @@ -261,6 +265,10 @@ s16 const JASCalc::CUTOFF_TO_IIR_TABLE[128][4] = { 0x7C7A, 0x0052, 0x0233, 0x00F4, 0x7E3B, 0x0029, 0x011B, 0x007A, 0x7FFF, 0x0000, 0x0000, 0x0000, +#if AVOID_UB + // Game OOB reads this in some cases. + 0,0,0,0 +#endif }; // currently required because of missing functions diff --git a/libs/JSystem/src/JAudio2/JASChannel.cpp b/libs/JSystem/src/JAudio2/JASChannel.cpp index 8e81ef3e86..61fe80a098 100644 --- a/libs/JSystem/src/JAudio2/JASChannel.cpp +++ b/libs/JSystem/src/JAudio2/JASChannel.cpp @@ -31,7 +31,7 @@ JASChannel::JASChannel(Callback i_callback, void* i_callbackData) : mKeySweepCount(0), mSkipSamples(0) { - field_0xdc.field_0x0 = 0; + field_0xdc.mChannelType = 0; field_0x104 = 0; mMixConfig[0].whole = 0x150; mMixConfig[1].whole = 0x210; @@ -171,12 +171,12 @@ void JASChannel::updateEffectorParam(JASDsp::TChannel* i_channel, u16* i_mixerVo f32 pan = 0.5f; f32 dolby = 0.0f; switch (JASDriver::getOutputMode()) { - case 0: + case JAS_OUTPUT_MONO: break; - case 1: + case JAS_OUTPUT_STEREO: pan = calcPan(&pan_vector); break; - case 2: + case JAS_OUTPUT_SURROUND: pan = calcPan(&pan_vector); dolby = calcEffect(&dolby_vector); break; @@ -229,7 +229,7 @@ s32 JASChannel::initialUpdateDSPChannel(JASDsp::TChannel* i_channel) { mCallback(CB_START, this, i_channel, mCallbackData); } - if (field_0xdc.field_0x4.field_0x20[0] == 0) { + if (field_0xdc.mWaveInfo.field_0x20[0] == 0) { JUT_WARN_DEVICE(346, 2, "%s", "Lost wave data while playing"); mDspCh->free(); mDspCh = NULL; @@ -245,19 +245,19 @@ s32 JASChannel::initialUpdateDSPChannel(JASDsp::TChannel* i_channel) { return -1; } - switch (field_0xdc.field_0x0) { + switch (field_0xdc.mChannelType) { case 0: - i_channel->setWaveInfo(field_0xdc.field_0x4, field_0x104, mSkipSamples); + i_channel->setWaveInfo(field_0xdc.mWaveInfo, mWaveAramAddress, mSkipSamples); break; case 2: - i_channel->setOscInfo(field_0x104); + i_channel->setOscInfo(mOscillatorSomething); break; } - for (u8 i = 0; i < 6; i++) { + for (u8 i = 0; i < DSP_OUTPUT_CHANNELS; i++) { MixConfig mix_config = mMixConfig[i]; u32 output_mode = JASDriver::getOutputMode(); - if (output_mode == 0) { + if (output_mode == JAS_OUTPUT_MONO) { switch (mix_config.parts.upper) { case 8: mix_config.parts.upper = 11; @@ -266,7 +266,7 @@ s32 JASChannel::initialUpdateDSPChannel(JASDsp::TChannel* i_channel) { mix_config.parts.upper = 2; break; } - } else if (output_mode == 1 && mix_config.parts.upper == 8) { + } else if (output_mode == JAS_OUTPUT_STEREO && mix_config.parts.upper == 8) { mix_config.parts.upper = 11; } i_channel->setBusConnect(i, mix_config.parts.upper); @@ -281,9 +281,9 @@ s32 JASChannel::initialUpdateDSPChannel(JASDsp::TChannel* i_channel) { } mVibrate.resetCounter(); mTremolo.resetCounter(); - u16 mixer_volume[6]; + u16 mixer_volume[DSP_OUTPUT_CHANNELS]; updateEffectorParam(i_channel, mixer_volume, effect_params); - for (u8 i = 0; i < 6; i++) { + for (u8 i = 0; i < DSP_OUTPUT_CHANNELS; i++) { i_channel->setMixerInitVolume(i, mixer_volume[i]); } @@ -307,7 +307,7 @@ s32 JASChannel::updateDSPChannel(JASDsp::TChannel* i_channel) { mCallback(CB_PLAY, this, i_channel, mCallbackData); } - if (field_0xdc.field_0x4.field_0x20[0] == 0) { + if (field_0xdc.mWaveInfo.field_0x20[0] == 0) { JUT_WARN_DEVICE(456, 2, "%s","Lost wave data while playing"); mDspCh->free(); mDspCh = NULL; @@ -378,18 +378,18 @@ s32 JASChannel::updateDSPChannel(JASDsp::TChannel* i_channel) { return 0; } -void JASChannel::updateAutoMixer(JASDsp::TChannel* i_channel, f32 param_1, f32 param_2, - f32 param_3, f32 param_4) { - if (JASDriver::getOutputMode() == 0) { - param_1 *= 0.707f; +void JASChannel::updateAutoMixer(JASDsp::TChannel* i_channel, f32 volume, f32 pan, + f32 fxmix, f32 dolby) { + if (JASDriver::getOutputMode() == JAS_OUTPUT_MONO) { + volume *= 0.707f; } - param_1 = JASCalc::clamp01(param_1); + volume = JASCalc::clamp01(volume); - u16 r31 = param_1 * JASDriver::getChannelLevel_dsp(); - u8 r30 = param_2 * 127.5f; - u8 r29 = param_4 * 127.5f; - u8 r28 = param_3 * 127.5f; - i_channel->setAutoMixer(r31, r30, r29, r28, 0); + u16 dspVolume = volume * JASDriver::getChannelLevel_dsp(); + u8 dspPan = pan * 127.5f; + u8 dspDolby = dolby * 127.5f; + u8 dspFxMix = fxmix * 127.5f; + i_channel->setAutoMixer(dspVolume, dspPan, dspDolby, dspFxMix, 0); } void JASChannel::updateMixer(f32 i_volume, f32 i_pan, f32 i_fxmix, f32 i_dolby, u16* i_volumeOut) { @@ -429,7 +429,7 @@ void JASChannel::updateMixer(f32 i_volume, f32 i_pan, f32 i_fxmix, f32 i_dolby, volume *= scale; break; default: - if (JASDriver::getOutputMode() == 0) { + if (JASDriver::getOutputMode() == JAS_OUTPUT_MONO) { volume *= scale; } else { volume *= JMASinRadian(scale * JGeometry::TUtil::PI() * 0.5f); @@ -470,8 +470,8 @@ void JASChannel::updateMixer(f32 i_volume, f32 i_pan, f32 i_fxmix, f32 i_dolby, case 6: volume *= scale; break; - default: - if (JASDriver::getOutputMode() == 0) { + default: // 0, 1, 4, 5, 8-15 + if (JASDriver::getOutputMode() == JAS_OUTPUT_MONO) { volume *= scale; } else { volume *= JMASinRadian(scale * JGeometry::TUtil::PI() * 0.5f); diff --git a/libs/JSystem/src/JAudio2/JASDSPChannel.cpp b/libs/JSystem/src/JAudio2/JASDSPChannel.cpp index 1c5171082e..62c983248c 100644 --- a/libs/JSystem/src/JAudio2/JASDSPChannel.cpp +++ b/libs/JSystem/src/JAudio2/JASDSPChannel.cpp @@ -10,7 +10,7 @@ JASDSPChannel::JASDSPChannel() : mStatus(STATUS_INACTIVE), mPriority(-1), mFlags(0), - field_0xc(0), + mUpdateCounter(0), mCallback(NULL), mCallbackData(NULL), mChannel(NULL) @@ -42,9 +42,9 @@ void JASDSPChannel::drop() { } void JASDSPChannel::initAll() { - sDspChannels = JKR_NEW_ARRAY_ARGS(JASDSPChannel, 0x40, JASDram, 0x20); + sDspChannels = JKR_NEW_ARRAY_ARGS(JASDSPChannel, DSP_CHANNELS, JASDram, 0x20); JUT_ASSERT(102, sDspChannels); - for (int i = 0; i < 0x40; i++) { + for (int i = 0; i < DSP_CHANNELS; i++) { sDspChannels[i].mChannel = JASDsp::getDSPHandle(i); } } @@ -56,7 +56,7 @@ JASDSPChannel* JASDSPChannel::alloc(u8 i_priority, Callback i_callback, void* i_ } channel->drop(); channel->mPriority = i_priority; - channel->field_0xc = 0; + channel->mUpdateCounter = 0; channel->mCallback = i_callback; channel->mCallbackData = i_callbackData; return channel; @@ -70,7 +70,7 @@ JASDSPChannel* JASDSPChannel::allocForce(u8 i_priority, Callback i_callback, voi channel->mStatus = STATUS_INACTIVE; channel->drop(); channel->mPriority = i_priority; - channel->field_0xc = 0; + channel->mUpdateCounter = 0; channel->mCallback = i_callback; channel->mCallbackData = i_callbackData; return channel; @@ -83,16 +83,16 @@ void JASDSPChannel::setPriority(u8 i_priority) { JASDSPChannel* JASDSPChannel::getLowestChannel(int i_priority) { s16 best_priority = 0xff; int best_index = -1; - int best_unknown = 0; - for (int i = 0; i < 0x40; i++) { + int best_updateCounter = 0; + for (int i = 0; i < DSP_CHANNELS; i++) { JASDSPChannel* channel = &sDspChannels[i]; s16 priority = channel->mPriority; if (priority < 0) { return &sDspChannels[i]; } if (priority <= i_priority && priority <= best_priority) { - if (priority != best_priority || channel->field_0xc > best_unknown) { - best_unknown = channel->field_0xc; + if (priority != best_priority || channel->mUpdateCounter > best_updateCounter) { + best_updateCounter = channel->mUpdateCounter; best_index = i; best_priority = priority; } @@ -107,14 +107,14 @@ JASDSPChannel* JASDSPChannel::getLowestChannel(int i_priority) { JASDSPChannel* JASDSPChannel::getLowestActiveChannel() { s16 best_priority = 0xff; int best_index = -1; - int best_unknown = 0; - for (int i = 0; i < 0x40; i++) { + int best_updateCounter = 0; + for (int i = 0; i < DSP_CHANNELS; i++) { JASDSPChannel* channel = &sDspChannels[i]; if (channel->mStatus == STATUS_ACTIVE) { s16 priority = channel->mPriority; if (priority < 0x7f && priority <= best_priority) { - if (priority != best_priority || channel->field_0xc > best_unknown) { - best_unknown = channel->field_0xc; + if (priority != best_priority || channel->mUpdateCounter > best_updateCounter) { + best_updateCounter = channel->mUpdateCounter; best_index = i; best_priority = priority; } @@ -195,7 +195,7 @@ void JASDSPChannel::updateProc() { mChannel->playStop(); mChannel->flush(); } else { - field_0xc++; + mUpdateCounter++; if (flush) { mChannel->flush(); } @@ -205,7 +205,7 @@ void JASDSPChannel::updateProc() { } void JASDSPChannel::updateAll() { - for (u32 i = 0; i < 0x40; i++) { + for (u32 i = 0; i < DSP_CHANNELS; i++) { if ((i & 0xf) == 0 && i != 0) { JASDsp::releaseHalt((i - 1) >> 4); } @@ -230,8 +230,8 @@ JASDSPChannel* JASDSPChannel::getHandle(u32 i_index) { u32 JASDSPChannel::getNumUse() { u32 count = 0; - for (int i = 0; i < 0x40; i++) { - if (sDspChannels[i].mStatus == 0) { + for (int i = 0; i < DSP_CHANNELS; i++) { + if (sDspChannels[i].mStatus == STATUS_ACTIVE) { count++; } } @@ -240,8 +240,8 @@ u32 JASDSPChannel::getNumUse() { u32 JASDSPChannel::getNumFree() { u32 count = 0; - for (int i = 0; i < 0x40; i++) { - if (sDspChannels[i].mStatus == 1) { + for (int i = 0; i < DSP_CHANNELS; i++) { + if (sDspChannels[i].mStatus == STATUS_INACTIVE) { count++; } } @@ -250,8 +250,8 @@ u32 JASDSPChannel::getNumFree() { u32 JASDSPChannel::getNumBreak() { u32 count = 0; - for (int i = 0; i < 0x40; i++) { - if (sDspChannels[i].mStatus == 2) { + for (int i = 0; i < DSP_CHANNELS; i++) { + if (sDspChannels[i].mStatus == STATUS_DROP) { count++; } } diff --git a/libs/JSystem/src/JAudio2/JASDSPInterface.cpp b/libs/JSystem/src/JAudio2/JASDSPInterface.cpp index ba2d110436..49ca691011 100644 --- a/libs/JSystem/src/JAudio2/JASDSPInterface.cpp +++ b/libs/JSystem/src/JAudio2/JASDSPInterface.cpp @@ -50,6 +50,10 @@ void JASDsp::boot(void (*param_0)(void*)) { } void JASDsp::releaseHalt(u32 param_0) { +#if TARGET_PC + // Dusk DSP does not work incrementally. + return; +#endif DSPReleaseHalt2(param_0); } @@ -72,8 +76,8 @@ f32 JASDsp::getDSPMixerLevel() { return sDSPVolume; } -JASDsp::TChannel* JASDsp::getDSPHandle(int param_0) { - return CH_BUF + param_0; +JASDsp::TChannel* JASDsp::getDSPHandle(int index) { + return CH_BUF + index; } JASDsp::TChannel* JASDsp::getDSPHandleNc(int param_0) { @@ -87,12 +91,12 @@ void JASDsp::setFilterTable(s16* param_0, s16* param_1, u32 param_2) { } void JASDsp::flushBuffer() { - DCFlushRange(CH_BUF, sizeof(TChannel) * 64); + DCFlushRange(CH_BUF, sizeof(TChannel) * DSP_CHANNELS); DCFlushRange(FX_BUF, sizeof(FxBuf) * 4); } void JASDsp::invalChannelAll() { - DCInvalidateRange(CH_BUF, sizeof(TChannel) * 64); + DCInvalidateRange(CH_BUF, sizeof(TChannel) * DSP_CHANNELS); } u8 const ATTRIBUTE_ALIGN(32) JASDsp::DSPADPCM_FILTER[64] = { @@ -426,16 +430,16 @@ u32 const ATTRIBUTE_ALIGN(32) JASDsp::DSPRES_FILTER[320] = { }; void JASDsp::initBuffer() { - CH_BUF = JKR_NEW_ARRAY_ARGS(TChannel, 64, JASDram, 0x20); + CH_BUF = JKR_NEW_ARRAY_ARGS(TChannel, DSP_CHANNELS, JASDram, 0x20); JUT_ASSERT(354, CH_BUF); FX_BUF = JKR_NEW_ARRAY_ARGS(FxBuf, 4, JASDram, 0x20); JUT_ASSERT(356, FX_BUF); - JASCalc::bzero(CH_BUF, 0x6000); + JASCalc::bzero(CH_BUF, sizeof(TChannel) * DSP_CHANNELS); JASCalc::bzero(FX_BUF, sizeof(FxBuf) * 4); for (u8 i = 0; i < 4; i++) { setFXLine(i, NULL, NULL); } - DsetupTable(0x40, uintptr_t(CH_BUF), uintptr_t(&DSPRES_FILTER), uintptr_t(&DSPADPCM_FILTER), uintptr_t(FX_BUF)); + DsetupTable(DSP_CHANNELS, uintptr_t(CH_BUF), uintptr_t(&DSPRES_FILTER), uintptr_t(&DSPADPCM_FILTER), uintptr_t(FX_BUF)); flushBuffer(); } @@ -501,8 +505,8 @@ void JASDsp::TChannel::init() { mIsFinished = 0; mForcedStop = 0; mIsActive = 0; - field_0x058 = 0; - field_0x068 = 0; + mAutoMixerBeenSet = 0; + mSamplePosition = 0; initFilter(); } @@ -510,7 +514,7 @@ void JASDsp::TChannel::playStart() { JUT_ASSERT(508, dspMutex); field_0x10c = 0; field_0x060 = 0; - field_0x008 = 1; + mResetFlag = 1; field_0x066 = 0; int i; for (i = 0; i < 4; i++) { @@ -549,41 +553,41 @@ bool JASDsp::TChannel::isFinish() const { return mIsFinished != 0; } -void JASDsp::TChannel::setWaveInfo(JASWaveInfo const& param_0, u32 param_1, u32 param_2) { +void JASDsp::TChannel::setWaveInfo(JASWaveInfo const& waveInfo, u32 aramAddress, u32 skipSamples) { int i; JUT_ASSERT(610, dspMutex); - field_0x118 = param_1; + mWaveAramAddress = aramAddress; static const u8 COMP_BLOCKSAMPLES[8] = {0x10, 0x10, 0x01, 0x01, 0x01, 0x10, 0x10, 0x01}; - field_0x064 = COMP_BLOCKSAMPLES[param_0.field_0x00]; + mSamplesPerBlock = COMP_BLOCKSAMPLES[waveInfo.mWaveFormat]; static const u8 COMP_BLOCKBYTES[8] = {0x09, 0x05, 0x08, 0x10, 0x01, 0x01, 0x01, 0x01}; - field_0x100 = COMP_BLOCKBYTES[param_0.field_0x00]; - field_0x068 = 0; - if (field_0x100 >= 4) { - field_0x11c = param_0.field_0x18; - field_0x102 = param_0.field_0x02; - if (field_0x102) { - if (param_2 == 1) { - param_2 = param_0.field_0x10; + mBytesPerBlock = COMP_BLOCKBYTES[waveInfo.mWaveFormat]; + mSamplePosition = 0; + if (mBytesPerBlock >= 4) { + mSampleCount = waveInfo.mSampleCount; + mLoopFlag = waveInfo.mLoopFlag; + if (mLoopFlag) { + if (skipSamples == 1) { + skipSamples = waveInfo.mLoopStartSample; } - field_0x110 = param_0.field_0x10; - field_0x114 = param_0.field_0x14; - field_0x104 = param_0.field_0x1c; - field_0x106 = param_0.field_0x1e; + mLoopStartSample = waveInfo.mLoopStartSample; + mEndSample = waveInfo.mLoopEndSample; + mpLast = waveInfo.mpLast; + mpPenult = waveInfo.mpPenult; } else { - field_0x114 = field_0x11c; + mEndSample = mSampleCount; } - if (param_2 && field_0x114 > param_2) { - switch (param_0.field_0x00) { - case 0: - case 1: - field_0x068 = param_2; - field_0x118 += param_2 * field_0x100 >> 4; - field_0x110 -= param_2; - field_0x114 -= param_2; + if (skipSamples && mEndSample > skipSamples) { + switch (waveInfo.mWaveFormat) { + case WAVE_FORMAT_ADPCM4: + case WAVE_FORMAT_ADPCM2: + mSamplePosition = skipSamples; + mWaveAramAddress += skipSamples * mBytesPerBlock >> 4; + mLoopStartSample -= skipSamples; + mEndSample -= skipSamples; break; - case 2: - case 3: - field_0x068 = param_2; + case WAVE_FORMAT_PCM8: + case WAVE_FORMAT_PCM16: + mSamplePosition = skipSamples; break; } } @@ -595,28 +599,27 @@ void JASDsp::TChannel::setWaveInfo(JASWaveInfo const& param_0, u32 param_1, u32 void JASDsp::TChannel::setOscInfo(u32 param_0) { JUT_ASSERT(671, dspMutex); - field_0x118 = 0; - field_0x064 = 16; - field_0x100 = param_0; + mWaveAramAddress = 0; + mSamplesPerBlock = 16; + mBytesPerBlock = param_0; } void JASDsp::TChannel::initAutoMixer() { JUT_ASSERT(688, dspMutex); - if (field_0x058) { - field_0x054 = field_0x056; + if (mAutoMixerBeenSet) { + mAutoMixerInitVolume = mAutoMixerVolume; } else { - field_0x054 = 0; - field_0x058 = 1; + mAutoMixerInitVolume = 0; + mAutoMixerBeenSet = 1; } } -void JASDsp::TChannel::setAutoMixer(u16 param_0, u8 param_1, u8 param_2, u8 param_3, - u8 param_4) { +void JASDsp::TChannel::setAutoMixer(u16 volume, u8 pan, u8 dolby, u8 fxMix, u8) { JUT_ASSERT(709, dspMutex); - field_0x050 = (param_1 << 8) | param_2; - field_0x052 = param_3 << 8 | param_3 << 1; - field_0x056 = param_0; - field_0x058 = 1; + mAutoMixerPanDolby = (pan << 8) | dolby; + mAutoMixerFxMix = fxMix << 8 | fxMix << 1; + mAutoMixerVolume = volume; + mAutoMixerBeenSet = 1; } void JASDsp::TChannel::setPitch(u16 param_0) { @@ -627,21 +630,20 @@ void JASDsp::TChannel::setPitch(u16 param_0) { mPitch = param_0; } -void JASDsp::TChannel::setMixerInitVolume(u8 param_0, s16 param_1) { +void JASDsp::TChannel::setMixerInitVolume(u8 outputChannel, s16 volume) { JUT_ASSERT(798, dspMutex); - u16* tmp = field_0x010[param_0]; - tmp[2] = param_1; - tmp[1] = param_1; - tmp[3] = 0; + OutputChannelConfig& cfg = mOutputChannels[outputChannel]; + cfg.mCurrentVolume = volume; + cfg.mTargetVolume = volume; + cfg.mVolumeProgress = 0; } -void JASDsp::TChannel::setMixerVolume(u8 param_0, s16 param_1) { - u16* tmp; +void JASDsp::TChannel::setMixerVolume(u8 outputChannel, s16 volume) { JUT_ASSERT(841, dspMutex); if (mForcedStop == 0) { - tmp = field_0x010[param_0]; - tmp[1] = param_1; - tmp[3] &= 0xff; + OutputChannelConfig& cfg = mOutputChannels[outputChannel]; + cfg.mTargetVolume = volume; + cfg.mVolumeProgress &= 0xff; } } @@ -699,16 +701,25 @@ void JASDsp::TChannel::setDistFilter(s16 param_0) { iir_filter_params[4] = param_0; } -void JASDsp::TChannel::setBusConnect(u8 param_0, u8 param_1) { +void JASDsp::TChannel::setBusConnect(u8 outputChannel, u8 param_1) { JUT_ASSERT(973, dspMutex); - u16* tmp = field_0x010[param_0]; + OutputChannelConfig& tmp = mOutputChannels[outputChannel]; +#if AVOID_UB + if (param_1 == 255) { + // Seems to happen for "dolby mode" where the mix config is 0xFFFF. + // Probably UB without side effect in the base game as afaict the DSP + // doesn't look at mix config when "dolby mode" is active. + return; + } + JUT_ASSERT(0, param_1 < 12); +#endif static u16 const connect_table[12] = { 0x0000, 0x0D00, 0x0D60, 0x0DC0, 0x0E20, 0x0E80, 0x0EE0, 0x0CA0, 0x0F40, 0x0FA0, 0x0B00, 0x09A0, }; u16 r30 = 0; r30 = connect_table[param_1]; - tmp[0] = r30; + tmp.mBusConnect = r30; } u16 DSP_CreateMap2(u32 param_0) { diff --git a/libs/JSystem/src/JAudio2/JASDriverIF.cpp b/libs/JSystem/src/JAudio2/JASDriverIF.cpp index 2c9f305b61..7d602a8856 100644 --- a/libs/JSystem/src/JAudio2/JASDriverIF.cpp +++ b/libs/JSystem/src/JAudio2/JASDriverIF.cpp @@ -23,10 +23,10 @@ f32 JASDriver::getDSPLevel() { return JASDsp::getDSPMixerLevel(); } -u32 JASDriver::JAS_SYSTEM_OUTPUT_MODE = 0x00000001; +u32 JASDriver::JAS_SYSTEM_OUTPUT_MODE = JAS_OUTPUT_STEREO; -void JASDriver::setOutputMode(u32 param_0) { - JAS_SYSTEM_OUTPUT_MODE = param_0; +void JASDriver::setOutputMode(u32 mode) { + JAS_SYSTEM_OUTPUT_MODE = mode; } u32 JASDriver::getOutputMode() { diff --git a/libs/JSystem/src/JAudio2/JASDrumSet.cpp b/libs/JSystem/src/JAudio2/JASDrumSet.cpp index a7a483fe29..8c8736451d 100644 --- a/libs/JSystem/src/JAudio2/JASDrumSet.cpp +++ b/libs/JSystem/src/JAudio2/JASDrumSet.cpp @@ -49,11 +49,11 @@ bool JASDrumSet::getParam(int key, int param_1, JASInstParam* param_2) const { static JASOscillator::Data osc; osc.mTarget = 0; - osc._04 = 1.0f; + osc.mRate = 1.0f; osc.mTable = NULL; osc.rel_table = NULL; osc.mScale = 1.0f; - osc._14 = 0.0f; + osc.mVertex = 0.0f; static JASOscillator::Data* oscp = &osc; diff --git a/libs/JSystem/src/JAudio2/JASOscillator.cpp b/libs/JSystem/src/JAudio2/JASOscillator.cpp index 4073af7424..f4bf2ade6f 100644 --- a/libs/JSystem/src/JAudio2/JASOscillator.cpp +++ b/libs/JSystem/src/JAudio2/JASOscillator.cpp @@ -4,9 +4,9 @@ JASOscillator::JASOscillator() { mData = NULL; - _14 = 0; + mCurPoint = 0; mDirectRelease = 0; - _18 = 0; + mEnvelopeMode = 0; _1C = 0; _04 = _08 = _10 = _0C = 0.0f; } @@ -17,7 +17,7 @@ void JASOscillator::initStart(JASOscillator::Data const* data) { _04 = 0.0f; _08 = 0.0f; _0C = 0.0f; - _14 = 0; + mCurPoint = 0; mDirectRelease = 0; if (!data) { _1C = 0; @@ -30,8 +30,8 @@ void JASOscillator::initStart(JASOscillator::Data const* data) { return; } - _10 = mData->mTable[0]._4 / 32768.0f; - _18 = mData->mTable[0]._0; + _10 = mData->mTable[0].mValue / 32768.0f; + mEnvelopeMode = mData->mTable[0].mEnvelopeMode; _1C = 1; } @@ -44,13 +44,13 @@ void JASOscillator::incCounter(f32 param_0) { case 1: break; } - _04 += param_0 * mData->_04; + _04 += param_0 * mData->mRate; update(); } f32 JASOscillator::getValue() const { JUT_ASSERT(120, mData); - return _08 * mData->mScale + mData->_14; + return _08 * mData->mScale + mData->mVertex; } void JASOscillator::release() { @@ -63,8 +63,8 @@ void JASOscillator::release() { _04 = 0.0f; _0C = _08; _10 = 0.0f; - _14 = 0; - _18 = (mDirectRelease >> 14) & 3; + mCurPoint = 0; + mEnvelopeMode = (mDirectRelease >> 14) & 3; _1C = 4; update(); return; @@ -74,9 +74,9 @@ void JASOscillator::release() { JUT_ASSERT(157, mData->rel_table != NULL); _04 = 0.0f; _0C = _08; - _10 = mData->rel_table[0]._4 / 32768.0f; - _14 = 0; - _18 = mData->rel_table[0]._0; + _10 = mData->rel_table[0].mValue / 32768.0f; + mCurPoint = 0; + mEnvelopeMode = mData->rel_table[0].mEnvelopeMode; } _1C = 3; @@ -104,31 +104,31 @@ void JASOscillator::update() { return; } - while (_04 >= psVar1[_14]._2) { - _04 -= psVar1[_14]._2; + while (_04 >= psVar1[mCurPoint].mTime) { + _04 -= psVar1[mCurPoint].mTime; _08 = _10; - _14++; + mCurPoint++; _0C = _08; - const BE(s16)* ps = &psVar1[_14]._0; - s16 r26 = ps[0]; - switch(r26) { - case 0xf: + const Point* ps = &psVar1[mCurPoint]; + s16 mode = ps->mEnvelopeMode; + switch(mode) { + case ENVELOPE_STOP: _1C = 0; return; - case 0xe: + case ENVELOPE_HOLD: _1C = 2; return; - case 0xd: - _14 = ps[2]; + case ENVELOPE_LOOP: + mCurPoint = ps->mValue; break; default: - _18 = r26; - _10 = ps[2] / 32768.0f; + mEnvelopeMode = mode; + _10 = ps->mValue / 32768.0f; break; } } - updateCurrentValue(psVar1[_14]._2); + updateCurrentValue(psVar1[mCurPoint].mTime); } f32 const JASOscillator::sCurveTableLinear[17] = { @@ -163,7 +163,7 @@ static f32* table_list[4] = { }; void JASOscillator::updateCurrentValue(f32 param_0) { - f32* table = table_list[_18]; + f32* table = table_list[mEnvelopeMode]; f32 fVar1 = 16.0f * (_04 / param_0); u32 index = (u32) fVar1; f32 fVar3 = (fVar1 - index); diff --git a/libs/JSystem/src/JAudio2/JASSeqCtrl.cpp b/libs/JSystem/src/JAudio2/JASSeqCtrl.cpp index 044f3873f2..a4e4a4b441 100644 --- a/libs/JSystem/src/JAudio2/JASSeqCtrl.cpp +++ b/libs/JSystem/src/JAudio2/JASSeqCtrl.cpp @@ -34,9 +34,9 @@ void JASSeqCtrl::init() { field_0x51 = 0; } -void JASSeqCtrl::start(void* param_0, u32 param_1) { - mReader.init(param_0); - mReader.jump(param_1); +void JASSeqCtrl::start(void* base, u32 offset) { + mReader.init(base); + mReader.jump(offset); } int JASSeqCtrl::tickProc(JASTrack* param_0) { diff --git a/libs/JSystem/src/JAudio2/JASSeqParser.cpp b/libs/JSystem/src/JAudio2/JASSeqParser.cpp index bb80e583c2..b2077ce499 100644 --- a/libs/JSystem/src/JAudio2/JASSeqParser.cpp +++ b/libs/JSystem/src/JAudio2/JASSeqParser.cpp @@ -813,9 +813,15 @@ s32 JASSeqParser::cmdDump(JASTrack* param_0, u32* param_1) { } s32 JASSeqParser::cmdPrintf(JASTrack* param_0, u32* param_1) { +#if AVOID_UB + u8 stack_c[4] = {0}; + u32 stack_10[4] = {0}; + char buffer[128] = {0}; +#else u8 stack_c[4]; u32 stack_10[4]; char buffer[128]; +#endif JASSeqCtrl* seqCtrl = param_0->getSeqCtrl(); u32 r30 = 0; @@ -884,6 +890,19 @@ s32 JASSeqParser::cmdPrintf(JASTrack* param_0, u32* param_1) { s32 JASSeqParser::execNoteOnGate(JASTrack* param_0, u32 param_1, u32 param_2, u32 param_3, u32 param_4) { JASSeqCtrl* seqCtrl = param_0->getSeqCtrl(); + + int r31 = 0; + +#if TARGET_PC + // CodeWarrior on PPC allocates MSB-first for bit fields i think, which is stupid + // so in reality these are stored in bit 6 and 7 not but 0 and 1, do this to get around it + if (param_4 & 0x40) { + r31 |= 2; + } + if (param_4 & 0x80) { + r31 |= 1; + } +#else // likely fake match, this may use some actual union defined somewhere else union { u8 val; @@ -893,13 +912,13 @@ s32 JASSeqParser::execNoteOnGate(JASTrack* param_0, u32 param_1, u32 param_2, u3 } bits; } tmp; tmp.val = param_4; - int r31 = 0; if (tmp.bits.bit1) { r31 |= 2; } if (tmp.bits.bit0) { r31 |= 1; } +#endif if (param_3 == 0) { r31 |= 4; } @@ -950,7 +969,7 @@ s32 JASSeqParser::parseNoteOn(JASTrack* param_0, u8 param_1) { return 0; } -s32 JASSeqParser::parseCommand(JASTrack* param_0, u8 cmd, u16 param_2) { +s32 JASSeqParser::parseCommand(JASTrack* param_0, u8 cmd, u16 parameterTypesOverride) { JASSeqCtrl* seqCtrl = param_0->getSeqCtrl(); CmdInfo* cmdInfo = NULL; if (cmd != 0xb0) { @@ -959,32 +978,32 @@ s32 JASSeqParser::parseCommand(JASTrack* param_0, u8 cmd, u16 param_2) { } else { cmdInfo = &sExtCmdInfo[seqCtrl->readByte() & 0xff]; } - u16 r28 = (u16)cmdInfo->field_0xe; - r28 |= param_2; - u32 stack_28[8]; - for (int i = 0; i < cmdInfo->field_0xc; i++, r28 >>= 2) { - int r27 = 0; - switch (r28 & 3) { + u16 parameterTypes = (u16)cmdInfo->mParameterTypes; + parameterTypes |= parameterTypesOverride; + u32 args[8]; + for (int i = 0; i < cmdInfo->mParameterCount; i++, parameterTypes >>= 2) { + int value = 0; + switch (parameterTypes & 3) { case 0: - r27 = (u8)seqCtrl->readByte(); + value = (u8)seqCtrl->readByte(); break; case 1: - r27 = (u16)seqCtrl->read16(); + value = (u16)seqCtrl->read16(); break; case 2: - r27 = seqCtrl->read24(); + value = seqCtrl->read24(); break; case 3: - r27 = readReg(param_0, (u8)seqCtrl->readByte()); + value = readReg(param_0, (u8)seqCtrl->readByte()); break; } - stack_28[i] = r27; + args[i] = value; } - s32 (JASSeqParser::*ptr)(JASTrack*, u32*) = cmdInfo->field_0x0; + s32 (JASSeqParser::*ptr)(JASTrack*, u32*) = cmdInfo->mHandler; if (!ptr) { return 0; } - return execCommand(param_0, ptr, cmdInfo->field_0xc, stack_28); + return execCommand(param_0, ptr, cmdInfo->mParameterCount, args); } s32 JASSeqParser::parseRegCommand(JASTrack* param_0, int param_1) { @@ -1004,7 +1023,9 @@ s32 JASSeqParser::parseRegCommand(JASTrack* param_0, int param_1) { } s32 JASSeqParser::parse(JASTrack* param_0) { - u32 r31 = param_0->getSeqCtrl()->readByte(); + JASSeqCtrl* ctrl = param_0->getSeqCtrl(); + u32 base = ctrl->mReader.mCurPos - ctrl->mReader.mBase; + u32 r31 = ctrl->readByte(); s32 r30 = 0; if ((r31 & 0x80) == 0) { r30 = parseNoteOn(param_0, r31); diff --git a/libs/JSystem/src/JAudio2/JASSeqReader.cpp b/libs/JSystem/src/JAudio2/JASSeqReader.cpp index c259c57d40..459c2edeee 100644 --- a/libs/JSystem/src/JAudio2/JASSeqReader.cpp +++ b/libs/JSystem/src/JAudio2/JASSeqReader.cpp @@ -8,81 +8,81 @@ #include "JSystem/JAudio2/JASSeqReader.h" void JASSeqReader::init() { - field_0x00 = 0; - field_0x04 = 0; - field_0x08 = 0; + mBase = 0; + mCurPos = 0; + mCurStackDepth = 0; - for (int i = 0; i < 8; i++) { - field_0x0c[i] = NULL; - field_0x2c[i] = 0; + for (int i = 0; i < JAS_SEQ_STACK_SIZE; i++) { + mReturnAddr[i] = NULL; + mLoopCount[i] = 0; } } -void JASSeqReader::init(void* param_0) { - field_0x00 = (u8*)param_0; - field_0x04 = field_0x00; - field_0x08 = 0; +void JASSeqReader::init(void* base) { + mBase = (u8*)base; + mCurPos = mBase; + mCurStackDepth = 0; - for (int i = 0; i < 8; i++) { - field_0x0c[i] = NULL; - field_0x2c[i] = 0; + for (int i = 0; i < JAS_SEQ_STACK_SIZE; i++) { + mReturnAddr[i] = NULL; + mLoopCount[i] = 0; } } bool JASSeqReader::call(u32 param_0) { - if (field_0x08 >= 8) { + if (mCurStackDepth >= JAS_SEQ_STACK_SIZE) { JUT_WARN(42, "%s", "Cannot exec call command"); return false; } - field_0x0c[field_0x08++] = (u16*)field_0x04; - field_0x04 = field_0x00 + param_0; + mReturnAddr[mCurStackDepth++] = (u16*)mCurPos; + mCurPos = mBase + param_0; return true; } bool JASSeqReader::loopStart(u32 param_0) { - if (8 <= field_0x08) { + if (JAS_SEQ_STACK_SIZE <= mCurStackDepth) { JUT_WARN(53, "%s", "Cannot exec loopStart command"); return false; } - field_0x0c[field_0x08] = (u16*)field_0x04; - field_0x2c[field_0x08++] = param_0; + mReturnAddr[mCurStackDepth] = (u16*)mCurPos; + mLoopCount[mCurStackDepth++] = param_0; return true; } bool JASSeqReader::loopEnd() { - if (field_0x08 == 0) { + if (mCurStackDepth == 0) { JUT_WARN(65, "%s", "cannot loopE for call-stack is NULL"); return false; } - u16 tmp = field_0x2c[field_0x08 - 1]; + u16 tmp = mLoopCount[mCurStackDepth - 1]; if (tmp != 0) { tmp--; } if (!tmp) { - field_0x08--; + mCurStackDepth--; return true; } - field_0x2c[field_0x08 - 1] = tmp; - field_0x04 = (u8*)field_0x0c[field_0x08 - 1]; + mLoopCount[mCurStackDepth - 1] = tmp; + mCurPos = (u8*)mReturnAddr[mCurStackDepth - 1]; return true; } bool JASSeqReader::ret() { - if (field_0x08 == 0) { + if (mCurStackDepth == 0) { return false; } - field_0x04 = (u8*)field_0x0c[--field_0x08]; + mCurPos = (u8*)mReturnAddr[--mCurStackDepth]; return true; } diff --git a/libs/JSystem/src/JAudio2/JASSimpleWaveBank.cpp b/libs/JSystem/src/JAudio2/JASSimpleWaveBank.cpp index 8bfcc2c460..52935324d8 100644 --- a/libs/JSystem/src/JAudio2/JASSimpleWaveBank.cpp +++ b/libs/JSystem/src/JAudio2/JASSimpleWaveBank.cpp @@ -44,7 +44,7 @@ intptr_t JASSimpleWaveBank::TWaveHandle::getWavePtr() const { if (base == NULL) { return 0; } - return (intptr_t)base + mWaveInfo.field_0x08; + return (intptr_t)base + mWaveInfo.mOffsetStart; } JASSimpleWaveBank::TWaveHandle::TWaveHandle() { diff --git a/libs/JSystem/src/JAudio2/JASTaskThread.cpp b/libs/JSystem/src/JAudio2/JASTaskThread.cpp index 30a6d07a98..d5dfd089ea 100644 --- a/libs/JSystem/src/JAudio2/JASTaskThread.cpp +++ b/libs/JSystem/src/JAudio2/JASTaskThread.cpp @@ -26,7 +26,7 @@ JASTaskThread::~JASTaskThread() { void* JASTaskThread::allocCallStack(JASThreadCallback callback, const void* msg, u32 msgSize) { ThreadMemPool* heap; - u32 size = msgSize + 8; + u32 size = msgSize + offsetof(JASThreadCallStack, msg); JASThreadCallStack *callStack = (JASThreadCallStack*) JASKernel::getCommandHeap()->alloc(size); if (callStack == NULL) { return NULL; @@ -40,7 +40,7 @@ void* JASTaskThread::allocCallStack(JASThreadCallback callback, const void* msg, void* JASTaskThread::allocCallStack(JASThreadCallback callback, void* msg) { JASThreadCallStack *callStack; - callStack = (JASThreadCallStack*)JASKernel::getCommandHeap()->alloc(12); + callStack = (JASThreadCallStack*)JASKernel::getCommandHeap()->alloc(offsetof(JASThreadCallStack, msg) + sizeof(void*)); if (callStack == NULL) { return NULL; } @@ -85,7 +85,15 @@ void* JASTaskThread::run() { JASThreadCallStack* callstack; OSInitFastCast(); do { +#ifdef TARGET_PC + BOOL received = FALSE; + callstack = static_cast(waitMessageBlock(&received)); + if (!received) { + break; + } +#else callstack = static_cast(waitMessageBlock()); +#endif if (field_0x84) { OSSleepThread(&threadQueue_); } @@ -98,6 +106,9 @@ void* JASTaskThread::run() { JASKernel::getCommandHeap()->free(callstack); } while (true); +#ifdef TARGET_PC + return NULL; +#endif } void JASTaskThread::pause(bool param_0) { diff --git a/libs/JSystem/src/JAudio2/JASTrack.cpp b/libs/JSystem/src/JAudio2/JASTrack.cpp index de070adde3..68fbee63e5 100644 --- a/libs/JSystem/src/JAudio2/JASTrack.cpp +++ b/libs/JSystem/src/JAudio2/JASTrack.cpp @@ -171,9 +171,9 @@ void JASTrack::assignExtBuffer(u32 index, JASSoundParams* i_soundParams) { mChannelMgrs[index]->mSoundParams = i_soundParams; } -void JASTrack::setSeqData(void* param_0, u32 param_1) { +void JASTrack::setSeqData(void* base, u32 offset) { JUT_ASSERT(257, mStatus == STATUS_FREE); - mSeqCtrl.start(param_0, param_1); + mSeqCtrl.start(base, offset); } void JASTrack::startSeq() { @@ -356,7 +356,7 @@ int JASTrack::gateOn(u32 param_0, u32 i_velocity, f32 i_time, u32 i_flags) { } else { JASChannel* channel = channel_mgr->mChannels[0]; if (channel != NULL) { - channel->setKey(uvar7 - channel->field_0xdc.field_0x4.field_0x01); + channel->setKey(uvar7 - channel->field_0xdc.mWaveInfo.mBaseKey); channel->setVelocity(i_velocity); channel->setUpdateTimer(update_timer); } @@ -545,10 +545,10 @@ void JASTrack::setOscTable(u32 osc_no, JASOscillator::Point const* i_table) { void JASTrack::setOscAdsr(s16 param_0, s16 param_1, s16 param_2, s16 param_3, u16 i_directRelease) { mOscParam[0] = sEnvOsc; mOscParam[0].mTable = mOscPoint; - mOscPoint[0]._2 = param_0; - mOscPoint[1]._2 = param_1; - mOscPoint[2]._2 = param_2; - mOscPoint[2]._4 = param_3; + mOscPoint[0].mTime = param_0; + mOscPoint[1].mTime = param_1; + mOscPoint[2].mTime = param_2; + mOscPoint[2].mValue = param_3; mDirectRelease = i_directRelease; } diff --git a/libs/JSystem/src/JAudio2/JASTrackPort.cpp b/libs/JSystem/src/JAudio2/JASTrackPort.cpp index e822212ec9..bde86b37f9 100644 --- a/libs/JSystem/src/JAudio2/JASTrackPort.cpp +++ b/libs/JSystem/src/JAudio2/JASTrackPort.cpp @@ -3,8 +3,8 @@ #include "JSystem/JAudio2/JASTrackPort.h" void JASTrackPort::init() { - for (int i = 0; i < 16; i++) { - field_0x4[i] = 0; + for (int i = 0; i < MAX_PORTS; i++) { + mPortValues[i] = 0; } field_0x0 = 0; field_0x2 = 0; @@ -13,25 +13,25 @@ void JASTrackPort::init() { u16 JASTrackPort::readImport(u32 port_num) { JUT_ASSERT(27, port_num < MAX_PORTS); field_0x0 = field_0x0 & ~(1 << port_num); - return field_0x4[port_num]; + return mPortValues[port_num]; } u16 JASTrackPort::readExport(u32 port_num) { JUT_ASSERT(34, port_num < MAX_PORTS); field_0x2 = field_0x2 & ~(1 << port_num); - return field_0x4[port_num]; + return mPortValues[port_num]; } void JASTrackPort::writeImport(u32 port_num, u16 param_1) { JUT_ASSERT(41, port_num < MAX_PORTS); field_0x0 = field_0x0 | (1 << port_num); - field_0x4[port_num] = param_1; + mPortValues[port_num] = param_1; } void JASTrackPort::writeExport(u32 port_num, u16 param_1) { JUT_ASSERT(47, port_num < MAX_PORTS); field_0x2 = field_0x2 | (1 << port_num); - field_0x4[port_num] = param_1; + mPortValues[port_num] = param_1; } u32 JASTrackPort::checkImport(u32 param_0) const { diff --git a/libs/JSystem/src/JAudio2/JASWSParser.cpp b/libs/JSystem/src/JAudio2/JASWSParser.cpp index 35ec9526ed..4288377548 100644 --- a/libs/JSystem/src/JAudio2/JASWSParser.cpp +++ b/libs/JSystem/src/JAudio2/JASWSParser.cpp @@ -48,17 +48,17 @@ JASBasicWaveBank* JASWSParser::createBasicWaveBank(void const* stream, JKRHeap* for (int j = 0; j < ctrl->mWaveCount; j++) { TWave* wave = archive->mWaveOffsets[j].ptr(header); JASWaveInfo wave_info; - wave_info.field_0x00 = wave->_01; - wave_info.field_0x01 = wave->_02; - wave_info.field_0x04 = wave->_04; - wave_info.field_0x08 = wave->mOffset; - wave_info.field_0x0c = wave->_0C; - wave_info.field_0x02 = wave->_10 == 0 ? 0 : 0xff; - wave_info.field_0x10 = wave->_14; - wave_info.field_0x14 = wave->_18; - wave_info.field_0x18 = wave->_1C; - wave_info.field_0x1c = wave->_20; - wave_info.field_0x1e = wave->_22; + wave_info.mWaveFormat = wave->mWaveFormat; + wave_info.mBaseKey = wave->mBaseKey; + wave_info.mSampleRate = wave->mSampleRate; + wave_info.mOffsetStart = wave->mAWOffsetStart; + wave_info.mOffsetLength = wave->mAWOffsetEnd; + wave_info.mLoopFlag = wave->mLoopFlags == 0 ? 0 : 0xff; + wave_info.mLoopStartSample = wave->mLoopStartSample; + wave_info.mLoopEndSample = wave->mLoopEndSample; + wave_info.mSampleCount = wave->mSampleCount; + wave_info.mpLast = wave->mpLast; + wave_info.mpPenult = wave->mpPenult; TCtrlWave* ctrl_wave = ctrl->mCtrlWaveOffsets[j].ptr(header); u16 local_74 = JSULoHalf(ctrl_wave->_00); wave_bank->setWaveInfo(wave_group, j, local_74, wave_info); @@ -104,17 +104,17 @@ JASSimpleWaveBank* JASWSParser::createSimpleWaveBank(void const* stream, JKRHeap for (int i = 0; i < ctrl->mWaveCount; i++) { TWave* wave = archive->mWaveOffsets[i].ptr(header); JASWaveInfo wave_info; - wave_info.field_0x00 = wave->_01; - wave_info.field_0x01 = wave->_02; - wave_info.field_0x04 = wave->_04; - wave_info.field_0x08 = wave->mOffset; - wave_info.field_0x0c = wave->_0C; - wave_info.field_0x02 = wave->_10 == 0 ? 0 : 0xff; - wave_info.field_0x10 = wave->_14; - wave_info.field_0x14 = wave->_18; - wave_info.field_0x18 = wave->_1C; - wave_info.field_0x1c = wave->_20; - wave_info.field_0x1e = wave->_22; + wave_info.mWaveFormat = wave->mWaveFormat; + wave_info.mBaseKey = wave->mBaseKey; + wave_info.mSampleRate = wave->mSampleRate; + wave_info.mOffsetStart = wave->mAWOffsetStart; + wave_info.mOffsetLength = wave->mAWOffsetEnd; + wave_info.mLoopFlag = wave->mLoopFlags == 0 ? 0 : 0xff; + wave_info.mLoopStartSample = wave->mLoopStartSample; + wave_info.mLoopEndSample = wave->mLoopEndSample; + wave_info.mSampleCount = wave->mSampleCount; + wave_info.mpLast = wave->mpLast; + wave_info.mpPenult = wave->mpPenult; TCtrlWave* ctrl_wave = ctrl->mCtrlWaveOffsets[i].ptr(header); u32 tmp = JSULoHalf(ctrl_wave->_00); wave_bank->setWaveInfo(tmp, wave_info); diff --git a/libs/JSystem/src/JAudio2/JASWaveArcLoader.cpp b/libs/JSystem/src/JAudio2/JASWaveArcLoader.cpp index 54018a9e25..d14ff70298 100644 --- a/libs/JSystem/src/JAudio2/JASWaveArcLoader.cpp +++ b/libs/JSystem/src/JAudio2/JASWaveArcLoader.cpp @@ -99,7 +99,7 @@ bool JASWaveArc::sendLoadCmd() { _5a++; - if (JASDvd::getThreadPointer()->sendCmdMsg(loadToAramCallback, &commandInfo, 0x10) == 0) { + if (JASDvd::getThreadPointer()->sendCmdMsg(loadToAramCallback, &commandInfo, sizeof(commandInfo)) == 0) { JUT_WARN(193, "%s", "sendCmdMsg loadToAramCallback Failed"); mHeap.free(); return false; diff --git a/libs/JSystem/src/JAudio2/JAUInitializer.cpp b/libs/JSystem/src/JAudio2/JAUInitializer.cpp index 3800170f77..0cc3fcbb62 100644 --- a/libs/JSystem/src/JAudio2/JAUInitializer.cpp +++ b/libs/JSystem/src/JAudio2/JAUInitializer.cpp @@ -15,6 +15,8 @@ #include "JSystem/JKernel/JKRSolidHeap.h" #include "JSystem/JKernel/JKRThread.h" +#include "dusk/audio/DuskAudioSystem.h" + JAU_JASInitializer::JAU_JASInitializer() { audioMemory_ = 0; audioMemSize_ = 0; @@ -27,7 +29,7 @@ JAU_JASInitializer::JAU_JASInitializer() { #endif dvdThreadPriority_ = 3; audioThreadPriority_ = 2; - field_0x1c = 0x80; + mJasTrackPoolSize = 0x80; dspLevel_ = 1.0f; aramBlockSize_ = 0x2760; aramChannelNum_ = 2; @@ -54,13 +56,17 @@ void JAU_JASInitializer::initJASystem(JKRSolidHeap* heap) { JASKernel::setupAramHeap(audioMemory_, audioMemSize_); - JASTrack::newMemPool(field_0x1c); + JASTrack::newMemPool(mJasTrackPoolSize); if (field_0x20 > 0) { JASTrack::TChannelMgr::newMemPool(field_0x20); } JASDvd::createThread(dvdThreadPriority_, 0x80, 0x1000); +#if TARGET_PC + dusk::audio::Initialize(); +#else JASAudioThread::create(audioThreadPriority_); +#endif JKRThreadSwitch* threadSwitch = JKRThreadSwitch::getManager(); if (threadSwitch) { if (dvdThreadId_ >= 0) { @@ -80,33 +86,33 @@ void JAU_JASInitializer::initJASystem(JKRSolidHeap* heap) { } #if PLATFORM_SHIELD - JASDriver::setOutputMode(1); + JASDriver::setOutputMode(JAS_OUTPUT_STEREO); #else switch (OSGetSoundMode()) { - case 0: - JASDriver::setOutputMode(0); + case OS_SOUND_MODE_MONO: + JASDriver::setOutputMode(JAS_OUTPUT_MONO); break; - case 1: - JASDriver::setOutputMode(1); + case OS_SOUND_MODE_STEREO: + JASDriver::setOutputMode(JAS_OUTPUT_STEREO); break; } #endif } JAU_JAIInitializer::JAU_JAIInitializer() { - field_0x0 = 100; - field_0x4 = 4; - field_0x8 = 2; - field_0xc = 16; + mJaiSePoolSize = 100; + mJaiSeqPoolSize = 4; + mJaiStreamPoolSize = 2; + mJaiSoundChildPoolSize = 16; } // NONMATCHING JASPoolAllocObject<_> locations void JAU_JAIInitializer::initJAInterface() { s32 r30 = JASDram->getFreeSize(); - JAIStream::newMemPool(field_0x8); - JAISeq::newMemPool(field_0x4); - JAISe::newMemPool(field_0x0); - JAISoundChild::newMemPool(field_0xc); + JAIStream::newMemPool(mJaiStreamPoolSize); + JAISeq::newMemPool(mJaiSeqPoolSize); + JAISe::newMemPool(mJaiSePoolSize); + JAISoundChild::newMemPool(mJaiSoundChildPoolSize); s32 r29 = JASDram->getFreeSize(); OS_REPORT("JAU_JAIInitializer uses %d bytes\n", r30 - r29); } diff --git a/libs/JSystem/src/JAudio2/JAUSectionHeap.cpp b/libs/JSystem/src/JAudio2/JAUSectionHeap.cpp index 8207c21f2f..e1f45de1ae 100644 --- a/libs/JSystem/src/JAudio2/JAUSectionHeap.cpp +++ b/libs/JSystem/src/JAudio2/JAUSectionHeap.cpp @@ -245,11 +245,11 @@ u8* JAUSection::newStaticSeqDataBlock_(JAISoundID param_0, u32 size) { return NULL; } -bool JAUSection::newStaticSeqData(JAISoundID param_0, void const* param_1, u32 param_2) { +bool JAUSection::newStaticSeqData(JAISoundID param_0, void const* param_1, u32 size) { { - u8* r30 = newStaticSeqDataBlock_(param_0, param_2); + u8* r30 = newStaticSeqDataBlock_(param_0, size); if (r30) { - memcpy(r30, param_1, param_2); + memcpy(r30, param_1, size); return true; } } diff --git a/libs/JSystem/src/JAudio2/JAUSeqCollection.cpp b/libs/JSystem/src/JAudio2/JAUSeqCollection.cpp index 1301cbc4fd..a6071a75e6 100644 --- a/libs/JSystem/src/JAudio2/JAUSeqCollection.cpp +++ b/libs/JSystem/src/JAudio2/JAUSeqCollection.cpp @@ -4,39 +4,39 @@ #include "JSystem/JUtility/JUTAssert.h" JAUSeqCollection::JAUSeqCollection() { - field_0x8 = NULL; + mHeader = NULL; } void JAUSeqCollection::init(void const* param_0) { - field_0x8 = (const JAUSeqCollectionData*)param_0; - if (field_0x8->field_0x0 != 0x53 || field_0x8->field_0x1 != 0x43) { - field_0x8 = NULL; + mHeader = (const JAUSeqCollectionData*)param_0; + if (mHeader->mMagic1 != 0x53 || mHeader->mMagic2 != 0x43) { + mHeader = NULL; return; } - field_0x0 = field_0x8->field_0x2; - field_0xc = field_0x8->field_0x4; - field_0x4 = &field_0x8->field_0x8; + mNumSoundCategories = mHeader->mNumSoundCategories; + mSectionSize = mHeader->mSectionSize; + mTableOffsets = mHeader->mTableOffsets; } bool JAUSeqCollection::getSeqData(int param_0, int param_1, JAISeqData* param_2) { - if (param_0 >= field_0x0) { + if (param_0 >= mNumSoundCategories) { return false; } - u32 r29 = field_0x4[param_0]; - BE(u32)* puVar2 = (BE(u32)*)((u8*)field_0x8 + r29); + u32 r29 = mTableOffsets[param_0]; + BE(u32)* puVar2 = (BE(u32)*)((u8*)mHeader + r29); if (param_1 >= puVar2[0]) { return false; } - param_2->set((void*)field_0x8, puVar2[param_1 + 1]); + param_2->set((void*)mHeader, puVar2[param_1 + 1]); return true; } bool JAUSeqCollection::getSeqDataRegion(JAISeqDataRegion* param_0) { if (isValid()) { - param_0->addr = (u8*)field_0x8; - param_0->size = field_0xc; + param_0->addr = (u8*)mHeader; + param_0->size = mSectionSize; return true; } return false; diff --git a/libs/JSystem/src/JAudio2/JAUSeqDataBlockMgr.cpp b/libs/JSystem/src/JAudio2/JAUSeqDataBlockMgr.cpp index 2fafe9a4bc..698c4aff65 100644 --- a/libs/JSystem/src/JAudio2/JAUSeqDataBlockMgr.cpp +++ b/libs/JSystem/src/JAudio2/JAUSeqDataBlockMgr.cpp @@ -87,8 +87,8 @@ s32 JAUDynamicSeqDataBlocks::getSeqData(JAISoundID param_0, JAISeqDataUser* para u8* seqData = mLoadedBlocks.getSeqData(param_0); if (seqData != NULL) { - param_2->field_0x0 = seqData; - param_2->field_0x4 = 0; + param_2->mBase = seqData; + param_2->mOffset = 0; return 2; } diff --git a/libs/JSystem/src/JAudio2/dspproc.cpp b/libs/JSystem/src/JAudio2/dspproc.cpp index a9c08e37ff..891722b7f4 100644 --- a/libs/JSystem/src/JAudio2/dspproc.cpp +++ b/libs/JSystem/src/JAudio2/dspproc.cpp @@ -20,10 +20,14 @@ static void setup_callback(u16 param_0) { flag = FALSE; } -void DsetupTable(u32 param_0, u32 param_1, u32 param_2, u32 param_3, u32 param_4) { +void DsetupTable(u32 channelCount, u32 channelBufferAddress, u32 param_2, u32 param_3, u32 param_4) { +#if TARGET_PC + return; +#endif + u32 table[5]; - table[0] = (param_0 & 0xFFFF) | 0x81000000; - table[1] = param_1; + table[0] = (channelCount & 0xFFFF) | 0x81000000; + table[1] = channelBufferAddress; table[2] = param_2; table[3] = param_3; table[4] = param_4; diff --git a/libs/JSystem/src/JAudio2/dsptask.cpp b/libs/JSystem/src/JAudio2/dsptask.cpp index 86d6323333..7d2e8dd2ad 100644 --- a/libs/JSystem/src/JAudio2/dsptask.cpp +++ b/libs/JSystem/src/JAudio2/dsptask.cpp @@ -4,6 +4,7 @@ #include "JSystem/JAudio2/osdsp.h" #include "global.h" #include "os_report.h" +#include "dusk/logging.h" static void DspInitWork(); static void DspHandShake(void* param_0); @@ -527,7 +528,7 @@ static DSPTaskInfo audio_task ATTRIBUTE_ALIGN(32); static u8 AUDIO_YIELD_BUFFER[8192] ATTRIBUTE_ALIGN(32); -void DspBoot(void (*param_0)(void*)) { +void DspBoot(void (*requestCallback)(void*)) { DspInitWork(); OS_REPORT("Dsp をブートします\n"); audio_task.priority = 0xf0; @@ -542,13 +543,16 @@ void DspBoot(void (*param_0)(void*)) { audio_task.init_cb = DspHandShake; audio_task.res_cb = NULL; audio_task.done_cb = NULL; - audio_task.req_cb = param_0; + audio_task.req_cb = requestCallback; DSPInit(); DSPAddPriorTask(&audio_task); OS_REPORT("Dspブートしました\n"); } int DSPSendCommands2(u32* param_1, u32 param_2, void (*callBack)(u16)) { +#if TARGET_PC + OSPanic(__FILE__, __LINE__, "We do not have a DSP"); +#endif s32 i; BOOL interruptFlag; s32 startWorkStatus; diff --git a/libs/JSystem/src/JAudio2/osdsp_task.cpp b/libs/JSystem/src/JAudio2/osdsp_task.cpp index d9f4973880..7ec8f3f855 100644 --- a/libs/JSystem/src/JAudio2/osdsp_task.cpp +++ b/libs/JSystem/src/JAudio2/osdsp_task.cpp @@ -12,7 +12,7 @@ extern "C" void __DSP_remove_task(DSPTaskInfo* task); static void Dsp_Update_Request(); -static vu8 struct_80451308; +static vu8 DspRunningStatus; static u8 struct_80451309; DSPTaskInfo* DSP_prior_task; @@ -23,7 +23,7 @@ extern "C" void __DSPHandler(__OSInterrupt interrupt, OSContext* context) { OSClearContext(&funcContext); OSSetCurrentContext(&funcContext); - if (struct_80451308 == 1 || struct_80451308 == 0) { + if (DspRunningStatus == 1 || DspRunningStatus == 0) { __DSP_curr_task = DSP_prior_task; } @@ -38,7 +38,7 @@ extern "C" void __DSPHandler(__OSInterrupt interrupt, OSContext* context) { case 0xDCD10000: __DSP_curr_task->state = 1; if (__DSP_curr_task == DSP_prior_task) { - struct_80451308 = 1; + DspRunningStatus = 1; } if (__DSP_curr_task->init_cb != NULL) { __DSP_curr_task->init_cb(__DSP_curr_task); @@ -47,7 +47,7 @@ extern "C" void __DSPHandler(__OSInterrupt interrupt, OSContext* context) { case 0xDCD10001: __DSP_curr_task->state = 1; if (__DSP_curr_task == DSP_prior_task) { - struct_80451308 = 1; + DspRunningStatus = 1; Dsp_Update_Request(); } if (__DSP_curr_task->res_cb != NULL) { @@ -97,7 +97,7 @@ extern "C" void __DSPHandler(__OSInterrupt interrupt, OSContext* context) { __DSP_curr_task = DSP_prior_task; Dsp_Update_Request(); } else { - struct_80451308 = 3; + DspRunningStatus = 3; DSPSendMailToDSP(0xCDD10001); while (DSPCheckMailToDSP() != 0); __DSP_exec_task(DSP_prior_task, __DSP_first_task); @@ -113,7 +113,7 @@ extern "C" void __DSPHandler(__OSInterrupt interrupt, OSContext* context) { static u32 sync_stack[5]; void DsyncFrame2(u32 param_0, u32 param_1, u32 param_2) { - if (struct_80451308 != 1) { + if (DspRunningStatus != 1) { sync_stack[0] = param_0; struct_80451309 = 1; sync_stack[1] = param_1; @@ -125,7 +125,7 @@ void DsyncFrame2(u32 param_0, u32 param_1, u32 param_2) { } static void DsyncFrame3(u32 param_0, u32 param_1, u32 param_2, u32 param_3, u32 param_4) { - if (struct_80451308 != 1) { + if (DspRunningStatus != 1) { sync_stack[0] = param_0; struct_80451309 = 2; sync_stack[1] = param_1; @@ -152,9 +152,9 @@ static void Dsp_Update_Request() { } int Dsp_Running_Check() { - return struct_80451308 == 1 ? TRUE : FALSE; + return DspRunningStatus == 1 ? TRUE : FALSE; } void Dsp_Running_Start() { - struct_80451308 = 1; + DspRunningStatus = 1; } diff --git a/libs/JSystem/src/JFramework/JFWDisplay.cpp b/libs/JSystem/src/JFramework/JFWDisplay.cpp index b55649a1bc..27873ecbe3 100644 --- a/libs/JSystem/src/JFramework/JFWDisplay.cpp +++ b/libs/JSystem/src/JFramework/JFWDisplay.cpp @@ -5,6 +5,7 @@ #include #include #include +#include "SDL3/SDL_timer.h" #include "JSystem/J2DGraph/J2DOrthoGraph.h" #include "JSystem/JFramework/JFWDisplay.h" #include "JSystem/JKernel/JKRHeap.h" @@ -13,9 +14,12 @@ #include "JSystem/JUtility/JUTDbPrint.h" #include "JSystem/JUtility/JUTProcBar.h" #include "aurora/aurora.h" +#include "dusk/dusk.h" #include "dusk/gx_helper.h" #include "dusk/logging.h" +#include "dusk/settings.h" #include "global.h" +#include "tracy/Tracy.hpp" void JFWDisplay::ctor_subroutine(bool enableAlpha) { mEnableAlpha = enableAlpha; @@ -347,16 +351,23 @@ void JFWDisplay::waitBlanking(int param_0) { } static void waitForTick(u32 p1, u16 p2) { - + ZoneScopedC(tracy::Color::DimGray); + #if TARGET_PC + if (dusk::getTransientSettings().skipFrameRateLimit) { + p1 = OS_TIMER_CLOCK / 120; + } + #endif if (p1 != 0) { static OSTime nextTick = OSGetTime(); OSTime time = OSGetTime(); + OSTime waitTime = (nextTick > time) ? (nextTick - time) : 0; while (time < nextTick) { JFWDisplay::getManager()->threadSleep((nextTick - time)); time = OSGetTime(); } + dusk::frameUsagePct = 100.0f * (1.0f - (float)waitTime / (float)p1); nextTick = time + p1; } else { static u32 nextCount = VIGetRetraceCount(); @@ -369,12 +380,19 @@ static void waitForTick(u32 p1, u16 p2) { msg = 0; } } while (((intptr_t)msg - (intptr_t)nextCount) < 0); + dusk::frameUsagePct = 100.0f; nextCount = (intptr_t)msg + uVar1; } } JSUList JFWAlarm::sList(false); +#if TARGET_PC +void JFWDisplay::threadSleep(s64 time) { + SDL_DelayNS(OSTicksToMicroseconds(time) * 1'000); +} +#else + static void JFWThreadAlarmHandler(OSAlarm* p_alarm, OSContext* p_ctx) { JFWAlarm* alarm = static_cast(p_alarm); alarm->removeLink(); @@ -392,6 +410,7 @@ void JFWDisplay::threadSleep(s64 time) { OSSuspendThread(alarm.getThread()); OSRestoreInterrupts(status); } +#endif static void dummy() { JUTXfb::getManager()->setDisplayingXfbIndex(0); diff --git a/libs/JSystem/src/JFramework/JFWSystem.cpp b/libs/JSystem/src/JFramework/JFWSystem.cpp index e84d19a824..d6322f34c9 100644 --- a/libs/JSystem/src/JFramework/JFWSystem.cpp +++ b/libs/JSystem/src/JFramework/JFWSystem.cpp @@ -79,11 +79,15 @@ void JFWSystem::init() { JUTGamePad::init(); +#ifndef TARGET_PC JUTDirectPrint* dbPrint = JUTDirectPrint::start(); +#endif JUTAssertion::create(); +#ifndef TARGET_PC JUTException::create(dbPrint); +#endif systemFont = JKR_NEW JUTResFont(CSetUpParam::systemFontRes, NULL); @@ -112,3 +116,9 @@ void JFWSystem::init() { void* buffer = systemHeap->alloc(CSetUpParam::exConsoleBufferSize, 4); JUTException::createConsole(buffer, CSetUpParam::exConsoleBufferSize); } + +#if TARGET_PC +void JFWSystem::shutdown() { + JKRAram::destroy(); +} +#endif diff --git a/libs/JSystem/src/JGadget/linklist.cpp b/libs/JSystem/src/JGadget/linklist.cpp index 366a8db320..b9593c31c6 100644 --- a/libs/JSystem/src/JGadget/linklist.cpp +++ b/libs/JSystem/src/JGadget/linklist.cpp @@ -8,7 +8,7 @@ namespace { template class TPRIsEqual_pointer_ { public: - TPRIsEqual_pointer_(const T* p) { this->p_ = p; } + TPRIsEqual_pointer_(const T* p) { this->p_ = p; } bool operator()(const T& rSrc) const { return &rSrc == this->p_; } diff --git a/libs/JSystem/src/JKernel/JKRAram.cpp b/libs/JSystem/src/JKernel/JKRAram.cpp index 8049ee0069..2770328afa 100644 --- a/libs/JSystem/src/JKernel/JKRAram.cpp +++ b/libs/JSystem/src/JKernel/JKRAram.cpp @@ -42,6 +42,12 @@ JKRAram* JKRAram::create(u32 aram_audio_buffer_size, u32 aram_audio_graph_size, return sAramObject; } +#if TARGET_PC +void JKRAram::destroy() { + JKRDecomp::destroy(); +} +#endif + OSMessage JKRAram::sMessageBuffer[4] = { NULL, NULL, @@ -94,7 +100,13 @@ void* JKRAram::run(void) { OSInitMessageQueue(&sMessageQueue, sMessageBuffer, 4); do { OSMessage msg; +#ifdef TARGET_PC + if (!OSReceiveMessage(&sMessageQueue, &msg, OS_MESSAGE_BLOCK)) { + break; + } +#else OSReceiveMessage(&sMessageQueue, &msg, OS_MESSAGE_BLOCK); +#endif JKRAramCommand* message = (JKRAramCommand*)msg; int result = message->field_0x00; JKRAMCommand* command = (JKRAMCommand*)message->command; @@ -106,6 +118,9 @@ void* JKRAram::run(void) { break; } } while (true); +#ifdef TARGET_PC + return NULL; +#endif } void JKRAram::checkOkAddress(u8* addr, u32 size, JKRAramBlock* block, u32 param_4) { diff --git a/libs/JSystem/src/JKernel/JKRAramPiece.cpp b/libs/JSystem/src/JKernel/JKRAramPiece.cpp index f01b530cfe..0946275b83 100644 --- a/libs/JSystem/src/JKernel/JKRAramPiece.cpp +++ b/libs/JSystem/src/JKernel/JKRAramPiece.cpp @@ -27,6 +27,10 @@ JSUList JKRAramPiece::sAramPieceCommandList; OSMutex JKRAramPiece::mMutex; +#if DEBUG && TARGET_PC +volatile u8 forceRead; +#endif + JKRAMCommand* JKRAramPiece::orderAsync(int direction, uintptr_t source, uintptr_t destination, u32 length, JKRAramBlock* block, JKRAMCommand::AsyncCallback callback) { lock(); @@ -45,6 +49,12 @@ JKRAMCommand* JKRAramPiece::orderAsync(int direction, uintptr_t source, uintptr_ JKRAramPiece::prepareCommand(direction, source, destination, length, block, callback); message->setting(1, command); +#if DEBUG && TARGET_PC + if (direction == ARAM_DIR_MRAM_TO_ARAM) { + forceRead = *reinterpret_cast(source); + } +#endif + OSSendMessage(&JKRAram::sMessageQueue, message, OS_MESSAGE_BLOCK); if (command->mCallback != NULL) { sAramPieceCommandList.append(&command->mPieceLink); diff --git a/libs/JSystem/src/JKernel/JKRAramStream.cpp b/libs/JSystem/src/JKernel/JKRAramStream.cpp index a9dc570ae0..a30f23dfaa 100644 --- a/libs/JSystem/src/JKernel/JKRAramStream.cpp +++ b/libs/JSystem/src/JKernel/JKRAramStream.cpp @@ -43,7 +43,13 @@ void* JKRAramStream::run() { for (;;) { OSMessage message; +#ifdef TARGET_PC + if (!OSReceiveMessage(&sMessageQueue, &message, OS_MESSAGE_BLOCK)) { + break; + } +#else OSReceiveMessage(&sMessageQueue, &message, OS_MESSAGE_BLOCK); +#endif JKRAramStreamCommand* command = (JKRAramStreamCommand*)message; switch (command->mType) { @@ -55,6 +61,9 @@ void* JKRAramStream::run() { break; } } +#ifdef TARGET_PC + return NULL; +#endif } s32 JKRAramStream::readFromAram() { diff --git a/libs/JSystem/src/JKernel/JKRDecomp.cpp b/libs/JSystem/src/JKernel/JKRDecomp.cpp index 3f01e60e15..a97edea0a3 100644 --- a/libs/JSystem/src/JKernel/JKRDecomp.cpp +++ b/libs/JSystem/src/JKernel/JKRDecomp.cpp @@ -20,6 +20,15 @@ JKRDecomp* JKRDecomp::create(s32 priority) { return sDecompObject; } +#if TARGET_PC +void JKRDecomp::destroy() { + if (sDecompObject) { + OSSendMessage(&sMessageQueue, nullptr, OS_MESSAGE_NOBLOCK); + OSJoinThread(sDecompObject->getThreadRecord(), nullptr); + } +} +#endif + OSMessage JKRDecomp::sMessageBuffer[8] = {0}; OSMessageQueue JKRDecomp::sMessageQueue = {0}; @@ -37,6 +46,12 @@ void* JKRDecomp::run() { OSReceiveMessage(&sMessageQueue, &message, OS_MESSAGE_BLOCK); JKRDecompCommand* command = (JKRDecompCommand*)message; +#if TARGET_PC + if (!command) { + break; + } +#endif + decode(command->mSrcBuffer, command->mDstBuffer, command->mSrcLength, command->mDstLength); if (command->field_0x20 != 0) { @@ -57,6 +72,9 @@ void* JKRDecomp::run() { OSSendMessage(&command->mMessageQueue, (OSMessage)1, OS_MESSAGE_NOBLOCK); } } +#ifdef TARGET_PC + return NULL; +#endif } JKRDecompCommand* JKRDecomp::prepareCommand(u8* srcBuffer, u8* dstBuffer, u32 srcLength, diff --git a/libs/JSystem/src/JKernel/JKRDvdRipper.cpp b/libs/JSystem/src/JKernel/JKRDvdRipper.cpp index ae644ee9e1..ae65f42ba3 100644 --- a/libs/JSystem/src/JKernel/JKRDvdRipper.cpp +++ b/libs/JSystem/src/JKernel/JKRDvdRipper.cpp @@ -13,6 +13,8 @@ #include #include +#include "JSystem/JKernel/JKRExpHeap.h" + static int JKRDecompressFromDVD(JKRDvdFile*, void*, u32, u32, u32, u32, u32*); static int decompSZS_subroutine(u8*, u8*); static u8* firstSrcData(); @@ -240,6 +242,8 @@ static OSMutex decompMutex; u32 JKRDvdRipper::sSZSBufferSize = 0x00000400; +JKRHeap* JKRDvdRipper::sHeap = NULL; + static u8* szpBuf; static u8* szpEnd; @@ -282,12 +286,20 @@ static int JKRDecompressFromDVD(JKRDvdFile* dvdFile, void* dst, u32 fileSize, u3 OSLockMutex(&decompMutex); u32 result = 0; u32 szsBufferSize = JKRDvdRipper::getSZSBufferSize(); +#if TARGET_PC + szpBuf = (u8 *)JKRAllocFromHeap(JKRDvdRipper::getHeap(), szsBufferSize, -0x20); +#else szpBuf = (u8 *)JKRAllocFromSysHeap(szsBufferSize, -0x20); +#endif JUT_ASSERT(909, szpBuf != NULL); szpEnd = szpBuf + szsBufferSize; if (inFileOffset != 0) { +#if TARGET_PC + refBuf = (u8 *)JKRAllocFromHeap(JKRDvdRipper::getHeap(), 0x1120, -4); +#else refBuf = (u8 *)JKRAllocFromSysHeap(0x1120, -4); +#endif JUT_ASSERT(918, refBuf != NULL); refEnd = refBuf + 0x1120; refCurrent = refBuf; diff --git a/libs/JSystem/src/JKernel/JKRExpHeap.cpp b/libs/JSystem/src/JKernel/JKRExpHeap.cpp index 3ec15cd161..4a6712cb65 100644 --- a/libs/JSystem/src/JKernel/JKRExpHeap.cpp +++ b/libs/JSystem/src/JKernel/JKRExpHeap.cpp @@ -214,9 +214,33 @@ void* JKRExpHeap::do_alloc(u32 size, int alignment) { #endif #if TARGET_PC - JUT_ASSERT_MSG_F(__LINE__, ptr != nullptr, - "Failed to alloc memory! (%s) (0x%X bytes).\n Heap size: %u\n Used size: %u", - this->getName(), size, getSize(), getTotalUsedSize()); + if (!ptr) { + // Allocation failed. + OSReport_Error( + "Failed to alloc memory! (%s) (0x%X bytes).\n Heap size: 0x%X\n Used size: 0x%X\n", + this->getName(), size, getSize(), getTotalUsedSize()); + OSReport_Error("Free block list as follows:\n"); + OSReport_Error("Start | End | Size \n"); + + int i = 0; + for (const CMemBlock* block = mHeadFreeList; block; block = block->mNext) { + if (block->mMagic) { + // Allocated, ignore. + continue; + } + if (i++ > 10) { + OSReport_Error("\n"); + break; + } + + auto blockStart = (uintptr_t)block - (uintptr_t)mStart; + auto blockEnd = (uintptr_t)block + block->size - (uintptr_t)mStart; + auto blockSize = block->size; + OSReport_Error("%08X | %08X | %08X\n", (u32) blockStart, (u32) blockEnd, (u32) blockSize); + } + + CRASH("Aborting due to allocation failure!"); + } #else if (ptr == NULL) { JUTWarningConsole_f(":::cannot alloc memory (0x%x byte).\n", size); @@ -472,7 +496,7 @@ void JKRExpHeap::do_freeAll() { JKRHeap::callAllDisposer(); mHeadFreeList = (CMemBlock*)mStart; mTailFreeList = mHeadFreeList; - mHeadFreeList->initiate(NULL, NULL, mSize - 0x10, 0, 0); + mHeadFreeList->initiate(NULL, NULL, mSize - sizeof(CMemBlock), 0, 0); mHeadUsedList = NULL; mTailUsedList = NULL; #if DEBUG diff --git a/libs/JSystem/src/JKernel/JKRHeap.cpp b/libs/JSystem/src/JKernel/JKRHeap.cpp index bc02d877fb..ce1899a4ba 100644 --- a/libs/JSystem/src/JKernel/JKRHeap.cpp +++ b/libs/JSystem/src/JKernel/JKRHeap.cpp @@ -15,6 +15,7 @@ #include "JSystem/JUtility/JUTAssert.h" #include "JSystem/JUtility/JUTException.h" +#include "dusk/string.hpp" #ifdef __MWERKS__ #include #else @@ -585,7 +586,13 @@ void* operator new(size_t size JKR_HEAP_TOKEN_PARAM, int alignment) { #endif void* operator new(size_t size JKR_HEAP_TOKEN_PARAM, JKRHeap* heap, int alignment) { - return JKRHeap::alloc(size, alignment, heap); + void* mem = JKRHeap::alloc(size, alignment, heap); +#if TARGET_PC + if (mem == nullptr) { + return fallback_alloc(size, abs(alignment), true); + } +#endif + return mem; } #if !TARGET_PC @@ -695,9 +702,7 @@ JKRHeap* JKRHeap::getCurrentHeap() { } void JKRHeap::setName(const char* name) { - size_t len = strlen(name); - strncpy(mName, name, sizeof(mName) - 1); - mName[sizeof(mName) - 1] = '\0'; + dusk::SafeStringCopyTruncate(mName, name); } void JKRHeap::setNamef(const char* fmt, ...) { diff --git a/libs/JSystem/src/JKernel/JKRThread.cpp b/libs/JSystem/src/JKernel/JKRThread.cpp index 96dfd53499..31c2cbe6e5 100644 --- a/libs/JSystem/src/JKernel/JKRThread.cpp +++ b/libs/JSystem/src/JKernel/JKRThread.cpp @@ -7,6 +7,10 @@ #include "global.h" #include +#if TARGET_PC +#include "dusk/os.h" +#endif + JSUList JKRThread::sThreadList(0); void* JKRIdleThread::sThread; @@ -84,10 +88,22 @@ void JKRThread::setCommon_heapSpecified(JKRHeap* heap, u32 stack_size, int param mThreadRecord = (OSThread*)JKRAllocFromHeap(mHeap, sizeof(OSThread), 0x20); JUT_ASSERT(168, mThreadRecord); - OSCreateThread(mThreadRecord, start, this, (u8*)mStackMemory + mStackSize, mStackSize, param_3, 1); +#if TARGET_PC + OSCreateThread(mThreadRecord, start, this, (u8*)mStackMemory + mStackSize, mStackSize, param_3, 0); +#else + OSCreateThread(mThreadRecord, start, this, (u8*)mStackMemory + mStackSize, mStackSize, param_3, OS_THREAD_ATTR_DETACH); +#endif } void* JKRThread::start(void* thread) { +#if TARGET_PC + auto& thd = *static_cast(thread); + if (thd.mThreadName == nullptr) { + thd.mThreadName = typeid(thd).name(); + } + OSSetCurrentThreadName(thd.mThreadName); +#endif + return ((JKRThread*)thread)->run(); } @@ -297,7 +313,15 @@ void* JKRTask::run() { }; OSInitFastCast(); while (true) { +#ifdef TARGET_PC + BOOL received = FALSE; + TaskMessage* msg = (TaskMessage*)waitMessageBlock(&received); + if (!received) { + break; + } +#else TaskMessage* msg = (TaskMessage*)waitMessageBlock(); +#endif if (msg->field_0x0) { msg->field_0x0(msg->field_0x4); check(); @@ -307,6 +331,9 @@ void* JKRTask::run() { } msg->field_0x0 = NULL; } +#ifdef TARGET_PC + return NULL; +#endif } int JKRTask::check() { diff --git a/libs/JSystem/src/JMath/JMath.cpp b/libs/JSystem/src/JMath/JMath.cpp index 43b9680308..899210e293 100644 --- a/libs/JSystem/src/JMath/JMath.cpp +++ b/libs/JSystem/src/JMath/JMath.cpp @@ -77,8 +77,6 @@ void JMAFastVECNormalize(__REGISTER const Vec* src, __REGISTER Vec* dst) { dst->y = src->y * length; dst->z = src->z * length; #endif // clang-format on - - OSPanic(__FILE__, __LINE__, "UNIMPLEMENTED"); } void JMAVECScaleAdd(__REGISTER const Vec* vec1, __REGISTER const Vec* vec2, __REGISTER Vec* dst, diff --git a/libs/JSystem/src/JParticle/JPABaseShape.cpp b/libs/JSystem/src/JParticle/JPABaseShape.cpp index f28add564e..178606a687 100644 --- a/libs/JSystem/src/JParticle/JPABaseShape.cpp +++ b/libs/JSystem/src/JParticle/JPABaseShape.cpp @@ -9,6 +9,8 @@ #include #include +#include "tracy/Tracy.hpp" + void JPASetPointSize(JPAEmitterWorkData* work) { GXSetPointSize((u8)(25.0f * work->mGlobalPtclScl.x), GX_TO_ONE); } @@ -684,6 +686,8 @@ void JPADrawDirection(JPAEmitterWorkData* param_0, JPABaseParticle* param_1) { return; } + ZoneScoped; + JGeometry::TVec3 local_6c; JGeometry::TVec3 local_78; p_direction[param_0->mDirType](param_0, param_1, &local_6c); @@ -729,6 +733,8 @@ void JPADrawRotDirection(JPAEmitterWorkData* param_0, JPABaseParticle* param_1) return; } + ZoneScoped; + f32 sinRot = JMASSin(param_1->mRotateAngle); f32 cosRot = JMASCos(param_1->mRotateAngle); JGeometry::TVec3 local_6c; @@ -779,6 +785,8 @@ void JPADrawDBillboard(JPAEmitterWorkData* param_0, JPABaseParticle* param_1) { return; } + ZoneScoped; + JGeometry::TVec3 local_70; p_direction[param_0->mDirType](param_0, param_1, &local_70); JGeometry::TVec3 aTStack_7c(param_0->mPosCamMtx[2][0], param_0->mPosCamMtx[2][1], param_0->mPosCamMtx[2][2]); @@ -814,6 +822,8 @@ void JPADrawRotation(JPAEmitterWorkData* param_0, JPABaseParticle* param_1) { return; } + ZoneScoped; + f32 sinRot = JMASSin(param_1->mRotateAngle); f32 cosRot = JMASCos(param_1->mRotateAngle); f32 particleX = param_0->mGlobalPtclScl.x * param_1->mParticleScaleX; @@ -835,6 +845,8 @@ void JPADrawPoint(JPAEmitterWorkData* work, JPABaseParticle* ptcl) { return; } + ZoneScoped; + GXSetVtxDesc(GX_VA_POS, GX_DIRECT); GXSetVtxDesc(GX_VA_TEX0, GX_DIRECT); GXBegin(GX_POINTS, GX_VTXFMT1, 1); @@ -850,6 +862,8 @@ void JPADrawLine(JPAEmitterWorkData* param_0, JPABaseParticle* param_1) { return; } + ZoneScoped; + JGeometry::TVec3 local_1c(param_1->mPosition); JGeometry::TVec3 local_28; param_1->getVelVec(&local_28); @@ -883,6 +897,8 @@ JPANode* getPrev(JPANode* param_0) { typedef JPANode* (*getNodeFunc)(JPANode*); void JPADrawStripe(JPAEmitterWorkData* param_0) { + ZoneScoped; + JPABaseShape* shape = param_0->mpRes->getBsp(); u32 ptcl_num = param_0->mpAlivePtcl->getNum(); if (ptcl_num < 2) { @@ -969,6 +985,8 @@ void JPADrawStripe(JPAEmitterWorkData* param_0) { } void JPADrawStripeX(JPAEmitterWorkData* param_0) { + ZoneScoped; + JPABaseShape* shape = param_0->mpRes->getBsp(); u32 ptcl_num = param_0->mpAlivePtcl->getNum(); if (ptcl_num < 2) { diff --git a/libs/JSystem/src/JParticle/JPAEmitterManager.cpp b/libs/JSystem/src/JParticle/JPAEmitterManager.cpp index 5cefe85329..3a793000ed 100644 --- a/libs/JSystem/src/JParticle/JPAEmitterManager.cpp +++ b/libs/JSystem/src/JParticle/JPAEmitterManager.cpp @@ -8,6 +8,8 @@ #include "JSystem/JUtility/JUTAssert.h" #include +#include "tracy/Tracy.hpp" + JPAEmitterManager::JPAEmitterManager(u32 i_ptclNum, u32 i_emtrNum, JKRHeap* pHeap, u8 i_gidMax, u8 i_ridMax) { emtrNum = i_emtrNum; @@ -85,6 +87,7 @@ void JPAEmitterManager::calc(u8 group_id) { } void JPAEmitterManager::draw(JPADrawInfo const* drawInfo, u8 group_id) { + ZoneScoped; JUT_ASSERT(192, group_id < gidMax); drawInfo->getCamMtx(pWd->mPosCamMtx); drawInfo->getPrjMtx(pWd->mPrjMtx); diff --git a/libs/JSystem/src/JParticle/JPAResource.cpp b/libs/JSystem/src/JParticle/JPAResource.cpp index 5c232a09f3..2ae4709fc3 100644 --- a/libs/JSystem/src/JParticle/JPAResource.cpp +++ b/libs/JSystem/src/JParticle/JPAResource.cpp @@ -16,6 +16,7 @@ #include "JSystem/JParticle/JPAParticle.h" #include "JSystem/JParticle/JPAResourceManager.h" #include "global.h" +#include "tracy/Tracy.hpp" JPAResource::JPAResource() { mpCalcEmitterFuncList = mpDrawEmitterFuncList = mpDrawEmitterChildFuncList = NULL; @@ -782,6 +783,7 @@ bool JPAResource::calc(JPAEmitterWorkData* work, JPABaseEmitter* emtr) { } void JPAResource::draw(JPAEmitterWorkData* work, JPABaseEmitter* emtr) { + ZoneScoped; work->mpEmtr = emtr; work->mpRes = this; work->mDrawCount = 0; @@ -798,6 +800,7 @@ void JPAResource::draw(JPAEmitterWorkData* work, JPABaseEmitter* emtr) { } void JPAResource::drawP(JPAEmitterWorkData* work) { + ZoneScoped; work->mpEmtr->clearStatus(0x80); work->mGlobalPtclScl.x = work->mpEmtr->mGlobalPScl.x * pBsp->getBaseSizeX(); @@ -860,6 +863,7 @@ void JPAResource::drawP(JPAEmitterWorkData* work) { } void JPAResource::drawC(JPAEmitterWorkData* work) { + ZoneScoped; work->mpEmtr->setStatus(0x80); if (pCsp->isScaleInherited()) { @@ -932,8 +936,8 @@ void JPAResource::setPTev() { int center_offset = pEsp != NULL ? (pEsp->getScaleCenterX() + 3 * pEsp->getScaleCenterY()) * 0xC : 0x30; int pos_offset = center_offset + base_plane_type * 0x6C; int crd_offset = (pBsp->getTilingS() + 2 * pBsp->getTilingT()) * 8; - GXSETARRAY(GX_VA_POS, jpa_pos + pos_offset, ARRAY_SIZEU(jpa_pos) - pos_offset, 3); - GXSETARRAY(GX_VA_TEX0, jpa_crd + crd_offset, ARRAY_SIZEU(jpa_crd) - crd_offset, 2); + GXSETARRAY(GX_VA_POS, jpa_pos + pos_offset, ARRAY_SIZEU(jpa_pos) - pos_offset, 3, true); + GXSETARRAY(GX_VA_TEX0, jpa_crd + crd_offset, ARRAY_SIZEU(jpa_crd) - crd_offset, 2, true); GXSetTevOrder(GX_TEVSTAGE0, GX_TEXCOORD0, GX_TEXMAP0, GX_COLOR_NULL); if (pEts != NULL) { @@ -978,8 +982,8 @@ void JPAResource::setCTev(JPAEmitterWorkData* work) { int base_plane_type = (pCsp->getType() == 3 || pCsp->getType() == 7) ? pCsp->getBasePlaneType() : 0; int pos_offset = 0x30 + base_plane_type * 0x6C; - GXSETARRAY(GX_VA_POS, jpa_pos + pos_offset, ARRAY_SIZEU(jpa_pos) - pos_offset, 3); - GXSETARRAY(GX_VA_TEX0, jpa_crd, ARRAY_SIZEU(jpa_crd), 2); + GXSETARRAY(GX_VA_POS, jpa_pos + pos_offset, ARRAY_SIZEU(jpa_pos) - pos_offset, 3, true); + GXSETARRAY(GX_VA_TEX0, jpa_crd, ARRAY_SIZEU(jpa_crd), 2, true); GXSetTevOrder(GX_TEVSTAGE0, GX_TEXCOORD0, GX_TEXMAP1, GX_COLOR_NULL); GXSetTexCoordGen(GX_TEXCOORD0, GX_TG_MTX2x4, GX_TG_TEX0, 0x3C); GXSetTevDirect(GX_TEVSTAGE0); diff --git a/libs/JSystem/src/JStudio/JStudio_JAudio2/object-sound.cpp b/libs/JSystem/src/JStudio/JStudio_JAudio2/object-sound.cpp index e4ce109f09..9bdde8b5cc 100644 --- a/libs/JSystem/src/JStudio/JStudio_JAudio2/object-sound.cpp +++ b/libs/JSystem/src/JStudio/JStudio_JAudio2/object-sound.cpp @@ -225,7 +225,9 @@ void JStudio_JAudio2::TAdaptor_sound::adaptor_do_PARENT_NODE(JStudio::data::TEOp case JStudio::data::UNK_0x18: if (field_0x13c != NULL) { JUT_ASSERT(431, pContent!=NULL); +#if DUSK_SUSPICIOUS_ASSERTS JUT_ASSERT(432, uSize==0); +#endif field_0x140 = field_0x13c->JSGFindNodeID((char*)pContent); if (field_0x140 == -1) { return; diff --git a/libs/JSystem/src/JUtility/JUTException.cpp b/libs/JSystem/src/JUtility/JUTException.cpp index 509acbfb3e..514ec6dd8a 100644 --- a/libs/JSystem/src/JUtility/JUTException.cpp +++ b/libs/JSystem/src/JUtility/JUTException.cpp @@ -101,6 +101,9 @@ JUTException* JUTException::create(JUTDirectPrint* directPrint) { OSMessage JUTException::sMessageBuffer[1] = {0}; void* JUTException::run() { +#ifdef TARGET_PC + return NULL; +#else u32 msr = PPCMfmsr(); msr &= ~0x0900; PPCMtmsr(msr); @@ -132,6 +135,7 @@ void* JUTException::run() { sErrorManager->mDirectPrint->changeFrameBuffer(mFrameMemory); sErrorManager->printContext(error, context, r24, r23); } +#endif } void* JUTException::sConsoleBuffer; @@ -145,6 +149,7 @@ u32 JUTException::msr; u32 JUTException::fpscr; void JUTException::errorHandler(OSError error, OSContext* context, u32 param_3, u32 param_4) { +#ifndef TARGET_PC msr = PPCMfmsr(); fpscr = context->fpscr; OSFillFPUContext(context); @@ -165,6 +170,7 @@ void JUTException::errorHandler(OSError error, OSContext* context, u32 param_3, OSSendMessage(&sMessageQueue, &exCallbackObject, OS_MESSAGE_BLOCK); OSEnableScheduler(); OSYieldThread(); +#endif } void JUTException::panic_f_va(char const* file, int line, char const* format, va_list args) { @@ -234,6 +240,7 @@ void JUTException::showFloatSub(int index, f32 value) { } void JUTException::showFloat(OSContext* context) { +#ifndef TARGET_PC if (!sConsole) { return; } @@ -251,6 +258,7 @@ void JUTException::showFloat(OSContext* context) { sConsole->print(" "); showFloatSub(21, context->fpr[21]); sConsole->print("\n"); +#endif } bool JUTException::searchPartialModule(u32 address, u32* module_id, u32* section_id, @@ -333,6 +341,7 @@ void JUTException::showStack(OSContext* context) { } void JUTException::showMainInfo(u16 error, OSContext* context, u32 dsisr, u32 dar) { +#ifndef TARGET_PC if (!sConsole) { return; } @@ -391,9 +400,11 @@ void JUTException::showMainInfo(u16 error, OSContext* context, u32 dsisr, u32 da } sConsole->print_f("SRR0: %08XH SRR1:%08XH\n", context->srr0, context->srr1); sConsole->print_f("DSISR: %08XH DAR: %08XH\n", dsisr, dar); +#endif } void JUTException::showGPR(OSContext* context) { +#ifndef TARGET_PC if (!sConsole) { return; } @@ -404,6 +415,7 @@ void JUTException::showGPR(OSContext* context) { context->gpr[i + 11], i + 22, context->gpr[i + 22]); } sConsole->print_f("R%02d:%08XH R%02d:%08XH\n", 10, context->gpr[10], 21, context->gpr[21]); +#endif } bool JUTException::showMapInfo_subroutine(u32 address, bool begin_with_newline) { @@ -454,6 +466,7 @@ bool JUTException::showMapInfo_subroutine(u32 address, bool begin_with_newline) } void JUTException::showGPRMap(OSContext* context) { +#ifndef TARGET_PC if (!sConsole) { return; } @@ -480,9 +493,11 @@ void JUTException::showGPRMap(OSContext* context) { if (!found_address_register) { sConsole->print(" no register which seem to address.\n"); } +#endif } void JUTException::showSRR0Map(OSContext* context) { +#ifndef TARGET_PC if (!sConsole) { return; } @@ -497,6 +512,7 @@ void JUTException::showSRR0Map(OSContext* context) { } JUTConsoleManager::getManager()->drawDirect(true); } +#endif } void JUTException::printDebugInfo(JUTException::EInfoPage page, OSError error, OSContext* context, diff --git a/libs/JSystem/src/JUtility/JUTGamePad.cpp b/libs/JSystem/src/JUtility/JUTGamePad.cpp index 31b8d59f1a..091cc382d1 100644 --- a/libs/JSystem/src/JUtility/JUTGamePad.cpp +++ b/libs/JSystem/src/JUtility/JUTGamePad.cpp @@ -535,6 +535,14 @@ void JUTGamePad::CRumble::stopPatternedRumble(s16 port) { } void JUTGamePad::CRumble::stopPatternedRumbleAtThePeriod() { +#if TARGET_PC + if (mFrameCount == 0) { + // Does not trap on hardware + // PowerPC spec says result is "undefined". Let's just write zero. + mLength = 0; + return; + } +#endif u32 r31 = mFrame % mFrameCount; mLength = (mFrame + mFrameCount - 1) % mFrameCount; } diff --git a/libs/JSystem/src/JUtility/JUTResFont.cpp b/libs/JSystem/src/JUtility/JUTResFont.cpp index e6410defdc..10443d6404 100644 --- a/libs/JSystem/src/JUtility/JUTResFont.cpp +++ b/libs/JSystem/src/JUtility/JUTResFont.cpp @@ -6,19 +6,39 @@ #include "JSystem/JUtility/JUTAssert.h" #include "JSystem/JUtility/JUTConsole.h" #include +#include "absl/container/node_hash_map.h" + +#if TARGET_PC +struct GlyphTextures { + absl::node_hash_map textures; +}; +#endif JUTResFont::JUTResFont() { +#if TARGET_PC + mGlyphTextures = new GlyphTextures(); +#endif initialize_state(); JUTFont::initialize_state(); } JUTResFont::JUTResFont(const ResFONT* pFont, JKRHeap* pHeap) { +#if TARGET_PC + mGlyphTextures = new GlyphTextures(); +#endif initialize_state(); JUTFont::initialize_state(); initiate(pFont, pHeap); } JUTResFont::~JUTResFont() { +#if TARGET_PC + for (auto& pair : mGlyphTextures->textures) { + pair.second.reset(); + } + delete mGlyphTextures; +#endif + if (mValid) { delete_and_initialize(); JUTFont::initialize_state(); @@ -414,12 +434,30 @@ void JUTResFont::loadImage(int code, GXTexMapID id){ mWidth = cellCol * cellW; mHeight = cellRow * cellH; +#if TARGET_PC + const auto found = mGlyphTextures->textures.find(code); + GXTexObj* texObj; + if (found == mGlyphTextures->textures.end()) { + texObj = &mGlyphTextures->textures[code]; + void* pImg = &mpGlyphBlocks[i]->data[pageIdx * mpGlyphBlocks[i]->textureSize]; + GXInitTexObj(texObj, pImg, mpGlyphBlocks[i]->textureWidth, + mpGlyphBlocks[i]->textureHeight, (GXTexFmt)(u16)mpGlyphBlocks[i]->textureFormat, + GX_CLAMP, GX_CLAMP, 0); + + GXInitTexObjLOD(texObj, GX_LINEAR, GX_LINEAR, 0.0f, 0.0f, 0.0f, 0U, 0U, GX_ANISO_1); + } else { + texObj = &found->second; + } + + GXLoadTexObj(texObj, id); + + // Gets used by some other code. + mTexPageIdx = pageIdx; + field_0x66 = i; +#else if (pageIdx != mTexPageIdx || i != field_0x66) { void* pImg = &mpGlyphBlocks[i]->data[pageIdx * mpGlyphBlocks[i]->textureSize]; -#ifdef TARGET_PC - mTexObj.reset(); -#endif GXInitTexObj(&mTexObj, pImg, mpGlyphBlocks[i]->textureWidth, mpGlyphBlocks[i]->textureHeight, (GXTexFmt)(u16)mpGlyphBlocks[i]->textureFormat, GX_CLAMP, GX_CLAMP, 0); @@ -430,6 +468,7 @@ void JUTResFont::loadImage(int code, GXTexMapID id){ } GXLoadTexObj(&mTexObj, id); +#endif } } diff --git a/libs/JSystem/src/JUtility/JUTVideo.cpp b/libs/JSystem/src/JUtility/JUTVideo.cpp index 1656aa7e0f..bb1f2cee3b 100644 --- a/libs/JSystem/src/JUtility/JUTVideo.cpp +++ b/libs/JSystem/src/JUtility/JUTVideo.cpp @@ -81,12 +81,14 @@ void JUTVideo::preRetraceProc(u32 retrace_count) { static void* frameBuffer = NULL; +#ifndef TARGET_PC if (frameBuffer) { const GXRenderModeObj* renderMode = JUTGetVideoManager()->getRenderMode(); u16 width = renderMode->fbWidth; u16 height = renderMode->efbHeight; JUTDirectPrint::getManager()->changeFrameBuffer(frameBuffer, width, height); } +#endif if (getManager()->mSetBlack == 1) { s32 frame_count = getManager()->mSetBlackFrameCount; diff --git a/libs/freeverb/CMakeLists.txt b/libs/freeverb/CMakeLists.txt new file mode 100644 index 0000000000..c0c12da293 --- /dev/null +++ b/libs/freeverb/CMakeLists.txt @@ -0,0 +1,9 @@ +cmake_minimum_required(VERSION 3.10) + +project(freeverb LANGUAGES CXX) + +add_library(freeverb + comb.cpp + allpass.cpp + revmodel.cpp +) diff --git a/libs/freeverb/allpass.cpp b/libs/freeverb/allpass.cpp new file mode 100644 index 0000000000..5d80eda2bd --- /dev/null +++ b/libs/freeverb/allpass.cpp @@ -0,0 +1,36 @@ +// Allpass filter implementation +// +// Written by Jezar at Dreampoint, June 2000 +// http://www.dreampoint.co.uk +// This code is public domain + +#include "allpass.hpp" + +allpass::allpass() +{ + bufidx = 0; +} + +void allpass::setbuffer(float *buf, int size) +{ + buffer = buf; + bufsize = size; +} + +void allpass::mute() +{ + for (int i=0; i=bufsize) bufidx = 0; + + return -input + bufout; +} + +#endif//_allpass + +//ends \ No newline at end of file diff --git a/libs/freeverb/comb.cpp b/libs/freeverb/comb.cpp new file mode 100644 index 0000000000..c05f5069c8 --- /dev/null +++ b/libs/freeverb/comb.cpp @@ -0,0 +1,48 @@ +// Comb filter implementation +// +// Written by Jezar at Dreampoint, June 2000 +// http://www.dreampoint.co.uk +// This code is public domain + +#include "comb.hpp" + +comb::comb() +{ + filterstore = 0; + bufidx = 0; +} + +void comb::setbuffer(float *buf, int size) +{ + buffer = buf; + bufsize = size; +} + +void comb::mute() +{ + for (int i=0; i=bufsize) bufidx = 0; + + return output; +} + +#endif //_comb_ + +//ends diff --git a/libs/freeverb/denormals.h b/libs/freeverb/denormals.h new file mode 100644 index 0000000000..d68cb444f7 --- /dev/null +++ b/libs/freeverb/denormals.h @@ -0,0 +1,58 @@ +#ifndef _denormals_ +#define _denormals_ + +#if defined(__x86_64__) || defined(_M_X64) || defined(__i386__) || defined(_M_IX86) + +#include +using denormal_state = unsigned int; +inline denormal_state denormals_enable() +{ + denormal_state saved = _mm_getcsr(); + _mm_setcsr(saved | 0x8040); // FTZ (0x8000) | DAZ (0x0040) + return saved; +} +inline void denormals_restore(denormal_state saved) { _mm_setcsr(saved); } + +#elif defined(__aarch64__) || defined(_M_ARM64) + +#include +using denormal_state = uint64_t; +inline denormal_state denormals_enable() +{ + denormal_state saved; + asm volatile("mrs %0, fpcr" : "=r"(saved)); + asm volatile("msr fpcr, %0" :: "r"(saved | (1ULL << 24))); // FZ + return saved; +} +inline void denormals_restore(denormal_state saved) +{ + asm volatile("msr fpcr, %0" :: "r"(saved)); +} + +#elif defined(__arm__) || defined(_M_ARM) + +#include +using denormal_state = uint32_t; +inline denormal_state denormals_enable() +{ + denormal_state saved; + asm volatile("vmrs %0, fpscr" : "=r"(saved)); + asm volatile("vmsr fpscr, %0" :: "r"(saved | (1U << 24))); // FZ + return saved; +} +inline void denormals_restore(denormal_state saved) +{ + asm volatile("vmsr fpscr, %0" :: "r"(saved)); +} + +#else + +// unknown platform so denormals will be preserved +#warning "This platform is not supported for denormals, reverb will be very slow!" +using denormal_state = int; +inline denormal_state denormals_enable() { return 0; } +inline void denormals_restore(denormal_state) {} + +#endif + +#endif diff --git a/libs/freeverb/revmodel.cpp b/libs/freeverb/revmodel.cpp new file mode 100644 index 0000000000..d4f9cf2513 --- /dev/null +++ b/libs/freeverb/revmodel.cpp @@ -0,0 +1,275 @@ +// Reverb model implementation +// +// Written by Jezar at Dreampoint, June 2000 +// http://www.dreampoint.co.uk +// This code is public domain + +#include "revmodel.hpp" +#include "denormals.h" + +revmodel::revmodel() +{ + // Tie the components to their buffers + combL[0].setbuffer(bufcombL1,combtuningL1); + combR[0].setbuffer(bufcombR1,combtuningR1); + combL[1].setbuffer(bufcombL2,combtuningL2); + combR[1].setbuffer(bufcombR2,combtuningR2); + combL[2].setbuffer(bufcombL3,combtuningL3); + combR[2].setbuffer(bufcombR3,combtuningR3); + combL[3].setbuffer(bufcombL4,combtuningL4); + combR[3].setbuffer(bufcombR4,combtuningR4); + combL[4].setbuffer(bufcombL5,combtuningL5); + combR[4].setbuffer(bufcombR5,combtuningR5); + combL[5].setbuffer(bufcombL6,combtuningL6); + combR[5].setbuffer(bufcombR6,combtuningR6); + combL[6].setbuffer(bufcombL7,combtuningL7); + combR[6].setbuffer(bufcombR7,combtuningR7); + combL[7].setbuffer(bufcombL8,combtuningL8); + combR[7].setbuffer(bufcombR8,combtuningR8); + allpassL[0].setbuffer(bufallpassL1,allpasstuningL1); + allpassR[0].setbuffer(bufallpassR1,allpasstuningR1); + allpassL[1].setbuffer(bufallpassL2,allpasstuningL2); + allpassR[1].setbuffer(bufallpassR2,allpasstuningR2); + allpassL[2].setbuffer(bufallpassL3,allpasstuningL3); + allpassR[2].setbuffer(bufallpassR3,allpasstuningR3); + allpassL[3].setbuffer(bufallpassL4,allpasstuningL4); + allpassR[3].setbuffer(bufallpassR4,allpasstuningR4); + + // Set default values + allpassL[0].setfeedback(0.5f); + allpassR[0].setfeedback(0.5f); + allpassL[1].setfeedback(0.5f); + allpassR[1].setfeedback(0.5f); + allpassL[2].setfeedback(0.5f); + allpassR[2].setfeedback(0.5f); + allpassL[3].setfeedback(0.5f); + allpassR[3].setfeedback(0.5f); + setwet(initialwet); + setroomsize(initialroom); + setdry(initialdry); + setdamp(initialdamp); + setwidth(initialwidth); + setmode(initialmode); + + // Buffer will be full of rubbish - so we MUST mute them + mute(); +} + +void revmodel::mute() +{ + if (getmode() >= freezemode) + return; + + for (int i=0;i 0) + { + outL = outR = 0; + float input = (*inputL + *inputR) * gain * inputGain; + + // Accumulate comb filters in parallel + for(int i=0; i 0) + { + outL = outR = 0; + float input = (*inputL + *inputR) * gain * inputGain; + + // Accumulate comb filters in parallel + for(int i=0; i= freezemode) + { + roomsize1 = 1; + damp1 = 0; + gain = muted; + } + else + { + roomsize1 = roomsize; + damp1 = damp; + gain = fixedgain; + } + + for(i=0; i= freezemode) + return 1; + else + return 0; +} + +//ends diff --git a/libs/freeverb/revmodel.hpp b/libs/freeverb/revmodel.hpp new file mode 100644 index 0000000000..5668ea599c --- /dev/null +++ b/libs/freeverb/revmodel.hpp @@ -0,0 +1,87 @@ +// Reverb model declaration +// +// Written by Jezar at Dreampoint, June 2000 +// http://www.dreampoint.co.uk +// This code is public domain + +#ifndef _revmodel_ +#define _revmodel_ + +#include "comb.hpp" +#include "allpass.hpp" +#include "tuning.h" + +class revmodel +{ +public: + revmodel(); + void mute(); + float processmix(float *inputL, float *inputR, float *outputL, float *outputR, long numsamples, int skip, float inputGain); + float processreplace(float *inputL, float *inputR, float *outputL, float *outputR, long numsamples, int skip, float inputGain); + void setroomsize(float value); + float getroomsize(); + void setdamp(float value); + float getdamp(); + void setwet(float value); + float getwet(); + void setdry(float value); + float getdry(); + void setwidth(float value); + float getwidth(); + void setmode(float value); + float getmode(); +private: + void update(); +private: + float gain; + float roomsize,roomsize1; + float damp,damp1; + float wet,wet1,wet2; + float dry; + float width; + float mode; + + // The following are all declared inline + // to remove the need for dynamic allocation + // with its subsequent error-checking messiness + + // Comb filters + comb combL[numcombs]; + comb combR[numcombs]; + + // Allpass filters + allpass allpassL[numallpasses]; + allpass allpassR[numallpasses]; + + // Buffers for the combs + float bufcombL1[combtuningL1]; + float bufcombR1[combtuningR1]; + float bufcombL2[combtuningL2]; + float bufcombR2[combtuningR2]; + float bufcombL3[combtuningL3]; + float bufcombR3[combtuningR3]; + float bufcombL4[combtuningL4]; + float bufcombR4[combtuningR4]; + float bufcombL5[combtuningL5]; + float bufcombR5[combtuningR5]; + float bufcombL6[combtuningL6]; + float bufcombR6[combtuningR6]; + float bufcombL7[combtuningL7]; + float bufcombR7[combtuningR7]; + float bufcombL8[combtuningL8]; + float bufcombR8[combtuningR8]; + + // Buffers for the allpasses + float bufallpassL1[allpasstuningL1]; + float bufallpassR1[allpasstuningR1]; + float bufallpassL2[allpasstuningL2]; + float bufallpassR2[allpasstuningR2]; + float bufallpassL3[allpasstuningL3]; + float bufallpassR3[allpasstuningR3]; + float bufallpassL4[allpasstuningL4]; + float bufallpassR4[allpasstuningR4]; +}; + +#endif//_revmodel_ + +//ends diff --git a/libs/freeverb/tuning.h b/libs/freeverb/tuning.h new file mode 100644 index 0000000000..baaa9ce004 --- /dev/null +++ b/libs/freeverb/tuning.h @@ -0,0 +1,60 @@ +// Reverb model tuning values +// +// Written by Jezar at Dreampoint, June 2000 +// http://www.dreampoint.co.uk +// This code is public domain + +#ifndef _tuning_ +#define _tuning_ + +const int numcombs = 8; +const int numallpasses = 4; +const float muted = 0; +const float fixedgain = 0.015f; +const float scalewet = 3; +const float scaledry = 2; +const float scaledamp = 0.4f; +const float scaleroom = 0.28f; +const float offsetroom = 0.7f; +const float initialroom = 0.5f; +const float initialdamp = 0.5f; +const float initialwet = 1/scalewet; +const float initialdry = 0; +const float initialwidth = 1; +const float initialmode = 0; +const float freezemode = 0.5f; +const int stereospread = 23; + +// These values assume 44.1KHz sample rate +// they will probably be OK for 48KHz sample rate +// but would need scaling for 96KHz (or other) sample rates. +// The values were obtained by listening tests. +const int combtuningL1 = 1116; +const int combtuningR1 = 1116+stereospread; +const int combtuningL2 = 1188; +const int combtuningR2 = 1188+stereospread; +const int combtuningL3 = 1277; +const int combtuningR3 = 1277+stereospread; +const int combtuningL4 = 1356; +const int combtuningR4 = 1356+stereospread; +const int combtuningL5 = 1422; +const int combtuningR5 = 1422+stereospread; +const int combtuningL6 = 1491; +const int combtuningR6 = 1491+stereospread; +const int combtuningL7 = 1557; +const int combtuningR7 = 1557+stereospread; +const int combtuningL8 = 1617; +const int combtuningR8 = 1617+stereospread; +const int allpasstuningL1 = 556; +const int allpasstuningR1 = 556+stereospread; +const int allpasstuningL2 = 441; +const int allpasstuningR2 = 441+stereospread; +const int allpasstuningL3 = 341; +const int allpasstuningR3 = 341+stereospread; +const int allpasstuningL4 = 225; +const int allpasstuningR4 = 225+stereospread; + +#endif//_tuning_ + +//ends + diff --git a/libs/revolution/src/homebuttonLib/nw4hbm/math/triangular.h b/libs/revolution/src/homebuttonLib/nw4hbm/math/triangular.h index 27be799ff6..d4c45733c6 100644 --- a/libs/revolution/src/homebuttonLib/nw4hbm/math/triangular.h +++ b/libs/revolution/src/homebuttonLib/nw4hbm/math/triangular.h @@ -19,7 +19,7 @@ namespace nw4hbm { inline f32 TanFIdx(f32 fidx) { // They were just like "Ah fuck it we already got too many tables" haha lol - return std::tanf(fidx * convert::FIdx2Rad); + return tanf(fidx * convert::FIdx2Rad); } inline f32 CosRad(f32 rad) { diff --git a/platforms/freedesktop/1024x1024/apps/dusk.png b/platforms/freedesktop/1024x1024/apps/dusk.png new file mode 100644 index 0000000000..862cbed0d8 Binary files /dev/null and b/platforms/freedesktop/1024x1024/apps/dusk.png differ diff --git a/platforms/freedesktop/128x128/apps/dusk.png b/platforms/freedesktop/128x128/apps/dusk.png new file mode 100644 index 0000000000..aaf38689d2 Binary files /dev/null and b/platforms/freedesktop/128x128/apps/dusk.png differ diff --git a/platforms/freedesktop/16x16/apps/dusk.png b/platforms/freedesktop/16x16/apps/dusk.png new file mode 100644 index 0000000000..21b653c63d Binary files /dev/null and b/platforms/freedesktop/16x16/apps/dusk.png differ diff --git a/platforms/freedesktop/256x256/apps/dusk.png b/platforms/freedesktop/256x256/apps/dusk.png new file mode 100644 index 0000000000..1f4677878a Binary files /dev/null and b/platforms/freedesktop/256x256/apps/dusk.png differ diff --git a/platforms/freedesktop/32x32/apps/dusk.png b/platforms/freedesktop/32x32/apps/dusk.png new file mode 100644 index 0000000000..b879a01602 Binary files /dev/null and b/platforms/freedesktop/32x32/apps/dusk.png differ diff --git a/platforms/freedesktop/48x48/apps/dusk.png b/platforms/freedesktop/48x48/apps/dusk.png new file mode 100644 index 0000000000..4f3744ab89 Binary files /dev/null and b/platforms/freedesktop/48x48/apps/dusk.png differ diff --git a/platforms/freedesktop/512x512/apps/dusk.png b/platforms/freedesktop/512x512/apps/dusk.png new file mode 100644 index 0000000000..6334f80e81 Binary files /dev/null and b/platforms/freedesktop/512x512/apps/dusk.png differ diff --git a/platforms/freedesktop/64x64/apps/dusk.png b/platforms/freedesktop/64x64/apps/dusk.png new file mode 100644 index 0000000000..067a83da90 Binary files /dev/null and b/platforms/freedesktop/64x64/apps/dusk.png differ diff --git a/platforms/freedesktop/dusk.desktop b/platforms/freedesktop/dusk.desktop new file mode 100644 index 0000000000..2e19d7ea26 --- /dev/null +++ b/platforms/freedesktop/dusk.desktop @@ -0,0 +1,9 @@ +[Desktop Entry] +Name=Dusk +GenericName=Dusk +Comment=The Legend of Zelda: Twilight Princess +Exec=dusk +Icon=dusk +Terminal=false +Type=Application +Categories=Graphics;3DGraphics;Game diff --git a/platforms/ios/Base.lproj/LaunchScreen.storyboardc/01J-lp-oVM-view-Ze5-6b-2t3.nib b/platforms/ios/Base.lproj/LaunchScreen.storyboardc/01J-lp-oVM-view-Ze5-6b-2t3.nib new file mode 100644 index 0000000000..15a4af7811 Binary files /dev/null and b/platforms/ios/Base.lproj/LaunchScreen.storyboardc/01J-lp-oVM-view-Ze5-6b-2t3.nib differ diff --git a/platforms/ios/Base.lproj/LaunchScreen.storyboardc/Info.plist b/platforms/ios/Base.lproj/LaunchScreen.storyboardc/Info.plist new file mode 100644 index 0000000000..32288e88f6 Binary files /dev/null and b/platforms/ios/Base.lproj/LaunchScreen.storyboardc/Info.plist differ diff --git a/platforms/ios/Base.lproj/LaunchScreen.storyboardc/UIViewController-01J-lp-oVM.nib b/platforms/ios/Base.lproj/LaunchScreen.storyboardc/UIViewController-01J-lp-oVM.nib new file mode 100644 index 0000000000..1b57c9a2f5 Binary files /dev/null and b/platforms/ios/Base.lproj/LaunchScreen.storyboardc/UIViewController-01J-lp-oVM.nib differ diff --git a/platforms/ios/Info.plist.in b/platforms/ios/Info.plist.in new file mode 100644 index 0000000000..54dfc5179a --- /dev/null +++ b/platforms/ios/Info.plist.in @@ -0,0 +1,79 @@ + + + + + CFBundleDevelopmentRegion + en-US + CFBundleInfoDictionaryVersion + 6.0 + CFBundlePackageType + APPL + CFBundleSignature + ???? + CFBundleExecutable + ${MACOSX_BUNDLE_EXECUTABLE_NAME} + CFBundleIdentifier + ${MACOSX_BUNDLE_GUI_IDENTIFIER} + CFBundleName + ${MACOSX_BUNDLE_BUNDLE_NAME} + CFBundleDisplayName + ${MACOSX_BUNDLE_BUNDLE_NAME} + CFBundleVersion + ${MACOSX_BUNDLE_BUNDLE_VERSION} + CFBundleShortVersionString + ${MACOSX_BUNDLE_SHORT_VERSION_STRING} + CFBundleSupportedPlatforms + + iPhoneOS + + CFBundleIcons + + CFBundlePrimaryIcon + + CFBundleIconFiles + + AppIcon60x60 + + CFBundleIconName + AppIcon + + + CFBundleIcons~ipad + + CFBundlePrimaryIcon + + CFBundleIconFiles + + AppIcon60x60 + AppIcon76x76 + + CFBundleIconName + AppIcon + + + MinimumOSVersion + ${DEPLOYMENT_TARGET} + LSRequiresIPhoneOS + + LSApplicationCategoryType + public.app-category.adventure-games + UILaunchStoryboardName + LaunchScreen + UIRequiresFullScreen + + UIStatusBarHidden + + UIStatusBarStyle + UIStatusBarStyleDarkContent + UISupportedInterfaceOrientations + + UIInterfaceOrientationLandscapeLeft + UIInterfaceOrientationLandscapeRight + + UIDeviceFamily + + 1 + 2 + + + diff --git a/platforms/macos/Info.plist.in b/platforms/macos/Info.plist.in new file mode 100644 index 0000000000..c91435dc2e --- /dev/null +++ b/platforms/macos/Info.plist.in @@ -0,0 +1,30 @@ + + + + + CFBundleDevelopmentRegion + en-US + CFBundleInfoDictionaryVersion + 6.0 + CFBundlePackageType + APPL + CFBundleSignature + ???? + CFBundleExecutable + ${MACOSX_BUNDLE_EXECUTABLE_NAME} + CFBundleIconFile + mainicon.icns + CFBundleIdentifier + ${MACOSX_BUNDLE_GUI_IDENTIFIER} + CFBundleName + ${MACOSX_BUNDLE_BUNDLE_NAME} + CFBundleDisplayName + ${MACOSX_BUNDLE_BUNDLE_NAME} + CFBundleVersion + ${MACOSX_BUNDLE_BUNDLE_VERSION} + CFBundleShortVersionString + ${MACOSX_BUNDLE_SHORT_VERSION_STRING} + NSHighResolutionCapable + + + diff --git a/platforms/tvos/Base.lproj/LaunchScreen.storyboardc/BYZ-38-t0r-view-8bC-Xf-vdC.nib b/platforms/tvos/Base.lproj/LaunchScreen.storyboardc/BYZ-38-t0r-view-8bC-Xf-vdC.nib new file mode 100644 index 0000000000..ff0fd7b09a Binary files /dev/null and b/platforms/tvos/Base.lproj/LaunchScreen.storyboardc/BYZ-38-t0r-view-8bC-Xf-vdC.nib differ diff --git a/platforms/tvos/Base.lproj/LaunchScreen.storyboardc/Info.plist b/platforms/tvos/Base.lproj/LaunchScreen.storyboardc/Info.plist new file mode 100644 index 0000000000..9a41f2cb91 Binary files /dev/null and b/platforms/tvos/Base.lproj/LaunchScreen.storyboardc/Info.plist differ diff --git a/platforms/tvos/Base.lproj/LaunchScreen.storyboardc/UIViewController-BYZ-38-t0r.nib b/platforms/tvos/Base.lproj/LaunchScreen.storyboardc/UIViewController-BYZ-38-t0r.nib new file mode 100644 index 0000000000..f2fed880d8 Binary files /dev/null and b/platforms/tvos/Base.lproj/LaunchScreen.storyboardc/UIViewController-BYZ-38-t0r.nib differ diff --git a/platforms/tvos/Info.plist.in b/platforms/tvos/Info.plist.in new file mode 100644 index 0000000000..841d120cc2 --- /dev/null +++ b/platforms/tvos/Info.plist.in @@ -0,0 +1,49 @@ + + + + + CFBundleDevelopmentRegion + en-US + CFBundleInfoDictionaryVersion + 6.0 + CFBundlePackageType + APPL + CFBundleSignature + ???? + CFBundleExecutable + ${MACOSX_BUNDLE_EXECUTABLE_NAME} + CFBundleIdentifier + ${MACOSX_BUNDLE_GUI_IDENTIFIER} + CFBundleName + ${MACOSX_BUNDLE_BUNDLE_NAME} + CFBundleDisplayName + ${MACOSX_BUNDLE_BUNDLE_NAME} + CFBundleVersion + ${MACOSX_BUNDLE_BUNDLE_VERSION} + CFBundleShortVersionString + ${MACOSX_BUNDLE_SHORT_VERSION_STRING} + CFBundleSupportedPlatforms + + AppleTVOS + + CFBundleIcons + + CFBundlePrimaryIcon + App Icon + + MinimumOSVersion + ${DEPLOYMENT_TARGET} + LSRequiresIPhoneOS + + LSApplicationCategoryType + public.app-category.adventure-games + NSHumanReadableCopyright + ${MACOSX_BUNDLE_COPYRIGHT} + NSHighResolutionCapable + + UILaunchStoryboardName + LaunchScreen + UIUserInterfaceStyle + Automatic + + diff --git a/res/NotoMono-Regular.ttf b/res/NotoMono-Regular.ttf new file mode 100644 index 0000000000..3560a3a0c8 Binary files /dev/null and b/res/NotoMono-Regular.ttf differ diff --git a/src/SSystem/SComponent/c_cc_d.cpp b/src/SSystem/SComponent/c_cc_d.cpp index 569d64e5e7..76c4920b8f 100644 --- a/src/SSystem/SComponent/c_cc_d.cpp +++ b/src/SSystem/SComponent/c_cc_d.cpp @@ -6,6 +6,7 @@ #include "SSystem/SComponent/c_cc_d.h" #include "JSystem/JUtility/JUTAssert.h" #include +#include "dusk/logging.h" #define CHECK_FLOAT_RANGE(line, x) JUT_ASSERT(line, -1.0e32f < x && x < 1.0e32f); @@ -65,9 +66,23 @@ void cCcD_DivideArea::CalcDivideInfo(cCcD_DivideInfo* pDivideInfo, const cM3dGAa if (!mXDiffIsZero) { s32 var1 = mInvScaledXDiff * (aab.GetMinP()->x - GetMinP()->x); s32 var3 = mInvScaledXDiff * (aab.GetMaxP()->x - GetMinP()->x); +#if TARGET_PC + // yDiv seems to be the problematic part here, but I clamped xDiv and zDiv too just in case. + // Unlike var1, var3 being greater than 31 isn't logged because it is every frame and the original code accounted for that. + // This goes for yDiv and zDiv as well. + if (var1 < 0 || var1 > 31) { + DuskLog.warn("CalcDivideInfo: xDiv var1 out of range: {}", var1); + } + if (var3 < 0) { + DuskLog.warn("CalcDivideInfo: xDiv var3 out of range: {}", var3); + } + var1 = var1 < 0 ? 0 : var1 > 31 ? 31 : var1; + var3 = var3 < 0 ? 0 : var3 > 31 ? 31 : var3; +#else if (31 < var3) { var3 = 31; } +#endif xDivInfo = l_base[var3]; if (0 < var1) { @@ -81,9 +96,22 @@ void cCcD_DivideArea::CalcDivideInfo(cCcD_DivideInfo* pDivideInfo, const cM3dGAa if (!mYDiffIsZero) { s32 var1 = mInvScaledYDiff * (aab.GetMinP()->y - GetMinP()->y); s32 var3 = mInvScaledYDiff * (aab.GetMaxP()->y - GetMinP()->y); +#if TARGET_PC + // When the Epona taming minigame starts as Wolf Link, yDiv var1 can be 32. + // When the Epona taming minigame ends, yDiv var1 and var3 can both be INT_MIN. + if (var1 < 0 || var1 > 31) { + DuskLog.warn("CalcDivideInfo: yDiv var1 out of range: {}", var1); + } + if (var3 < 0) { + DuskLog.warn("CalcDivideInfo: yDiv var3 out of range: {}", var3); + } + var1 = var1 < 0 ? 0 : var1 > 31 ? 31 : var1; + var3 = var3 < 0 ? 0 : var3 > 31 ? 31 : var3; +#else if (31 < var3) { var3 = 31; } +#endif yDivInfo = l_base[var3]; if (0 < var1) { @@ -97,9 +125,20 @@ void cCcD_DivideArea::CalcDivideInfo(cCcD_DivideInfo* pDivideInfo, const cM3dGAa if (!mZDiffIsZero) { s32 var1 = mInvScaledZDiff * (aab.GetMinP()->z - GetMinP()->z); s32 var3 = mInvScaledZDiff * (aab.GetMaxP()->z - GetMinP()->z); +#if TARGET_PC + if (var1 < 0 || var1 > 31) { + DuskLog.warn("CalcDivideInfo: zDiv var1 out of range: {}", var1); + } + if (var3 < 0) { + DuskLog.warn("CalcDivideInfo: zDiv var3 out of range: {}", var3); + } + var1 = var1 < 0 ? 0 : var1 > 31 ? 31 : var1; + var3 = var3 < 0 ? 0 : var3 > 31 ? 31 : var3; +#else if (31 < var3) { var3 = 31; } +#endif zDivInfo = l_base[var3]; if (0 < var1) { diff --git a/src/SSystem/SComponent/c_m3d_g_cyl.cpp b/src/SSystem/SComponent/c_m3d_g_cyl.cpp index 19bf8d795c..c2f292e08d 100644 --- a/src/SSystem/SComponent/c_m3d_g_cyl.cpp +++ b/src/SSystem/SComponent/c_m3d_g_cyl.cpp @@ -6,6 +6,8 @@ #include "SSystem/SComponent/c_m3d_g_cyl.h" #include "SSystem/SComponent/c_m3d.h" +#include "JSystem/JUtility/JUTAssert.h" + cM3dGCyl::cM3dGCyl(const cXyz* center, f32 radius, f32 height) { SetC(*center); SetR(radius); @@ -24,21 +26,30 @@ void cM3dGCyl::Set(const cXyz& center, f32 radius, f32 height) { SetH(height); } -void cM3dGCyl::SetC(const cXyz& center) { - mCenter = center; +void cM3dGCyl::SetC(const cXyz& pos) { + JUT_ASSERT(67, !isnan(pos.x)); + JUT_ASSERT(68, !isnan(pos.y)); + JUT_ASSERT(69, !isnan(pos.z)); + + JUT_ASSERT(72, -1.0e32f < pos.x && pos.x < 1.0e32f && -1.0e32f < pos.y && pos.y < 1.0e32f && -1.0e32f < pos.z && pos.z < 1.0e32f); + + mCenter = pos; } -void cM3dGCyl::SetH(f32 height) { - mHeight = height; +void cM3dGCyl::SetH(f32 h) { + JUT_ASSERT(82, !isnan(h)); + JUT_ASSERT(83, -1.0e32f < h && h < 1.0e32f); + mHeight = h; } -void cM3dGCyl::SetR(f32 radius) { - mRadius = radius; +void cM3dGCyl::SetR(f32 r) { + JUT_ASSERT(106, !isnan(r)); + JUT_ASSERT(107, -1.0e32f < r && r < 1.0e32f); + mRadius = r; } bool cM3dGCyl::cross(const cM3dGSph* other, cXyz* out) const { - f32 f; - return cM3d_Cross_CylSph(this, other, out, &f); + return cM3d_Cross_CylSph(this, other, out); } bool cM3dGCyl::cross(const cM3dGCyl* other, cXyz* out) const { diff --git a/src/SSystem/SComponent/c_m3d_g_sph.cpp b/src/SSystem/SComponent/c_m3d_g_sph.cpp index 3fd65af53a..9d730b0579 100644 --- a/src/SSystem/SComponent/c_m3d_g_sph.cpp +++ b/src/SSystem/SComponent/c_m3d_g_sph.cpp @@ -6,8 +6,16 @@ #include "SSystem/SComponent/c_m3d_g_sph.h" #include "SSystem/SComponent/c_m3d.h" -void cM3dGSph::SetC(const cXyz& center) { - mCenter = center; +#include "JSystem/JUtility/JUTAssert.h" + +void cM3dGSph::SetC(const cXyz& p) { + JUT_ASSERT(19, !isnan(p.x)); + JUT_ASSERT(20, !isnan(p.y)); + JUT_ASSERT(21, !isnan(p.z)); + + JUT_ASSERT(24, -1.0e32f < p.x && p.x < 1.0e32f && -1.0e32f < p.y && p.y < 1.0e32f && -1.0e32f < p.z && p.z < 1.0e32f); + + mCenter = p; } void cM3dGSph::Set(const cXyz& center, f32 radius) { @@ -20,8 +28,10 @@ void cM3dGSph::Set(const cM3dGSphS& other) { SetR(other.mRadius); } -void cM3dGSph::SetR(f32 radius) { - mRadius = radius; +void cM3dGSph::SetR(f32 r) { + JUT_ASSERT(54, !isnan(r)); + JUT_ASSERT(55, -1.0e32f < r && r < 1.0e32f); + mRadius = r; } bool cM3dGSph::cross(const cM3dGSph* other, cXyz* out) const { diff --git a/src/SSystem/SComponent/c_math.cpp b/src/SSystem/SComponent/c_math.cpp index 2cc54fece9..7baeea689c 100644 --- a/src/SSystem/SComponent/c_math.cpp +++ b/src/SSystem/SComponent/c_math.cpp @@ -7,6 +7,7 @@ #include "SSystem/SComponent/c_m3d.h" #include #include +#include "dusk/logging.h" s16 cM_rad2s(f32 rad) { s32 s = (std::fmod(rad, 2 * M_PI) * (0x8000 / M_PI)); @@ -109,6 +110,13 @@ static u16 atntable[1025] = { u16 U_GetAtanTable(f32 f0, f32 f1) { int idx = f0 / f1 * 0x400; +#if TARGET_PC + // When Wolf Link is playing a Human Link animation, idx can be INT_MIN every frame + if (idx < 0 || idx > 0x400) { + DuskLog.warn("U_GetAtanTable: idx out of range: {}", idx); + } + idx = idx < 0 ? 0 : idx > 0x400 ? 0x400 : idx; +#endif return atntable[idx]; } diff --git a/src/Z2AudioCS/Z2AudioCS.cpp b/src/Z2AudioCS/Z2AudioCS.cpp index 3a85e7adf1..992eb30a96 100644 --- a/src/Z2AudioCS/Z2AudioCS.cpp +++ b/src/Z2AudioCS/Z2AudioCS.cpp @@ -127,12 +127,12 @@ SpkSoundHandle* Z2AudioCS::startLevel(s32 id, s32 chan) { return handle; } -s32 Z2AudioCS::getName(s32 num) { +const char* Z2AudioCS::getName(s32 num) { if (JASGlobalInstance::getInstance() == NULL) { - return 0; + return NULL; } if (JASGlobalInstance::getInstance()->getData() == NULL) { - return 0; + return NULL; } return JASGlobalInstance::getInstance()->getData()->getTableMgr().getName(num); diff --git a/src/Z2AudioLib/Z2Audience.cpp b/src/Z2AudioLib/Z2Audience.cpp index be7bd4b126..5bb91eef31 100644 --- a/src/Z2AudioLib/Z2Audience.cpp +++ b/src/Z2AudioLib/Z2Audience.cpp @@ -552,7 +552,11 @@ JAIAudible* Z2Audience::newAudible(const JGeometry::TVec3& pos, JAISoundID } void Z2Audience::deleteAudible(JAIAudible* audible) { +#if TARGET_PC + JKR_DELETE(static_cast(audible)); +#else JKR_DELETE(audible); +#endif } Z2Audible::~Z2Audible() {} @@ -798,7 +802,7 @@ f32 Z2Audience::calcFxMix_(f32 param_0, int distVolBit) const { f32 Z2Audience::calcPitch_(Z2AudibleChannel* channel, const Z2Audible* audible, const Z2AudioCamera* camera) const { JAUAudibleParam audParam = *audible->getAudibleParam(); - if ((*(u8*)&audParam.field_0x0.raw >> 4) & 0xf) { + if (audParam.field_0x0.bytes.b0_0) { JGeometry::TVec3 aTStack_4c; aTStack_4c.normalize(channel->field_0x14.field_0x00); JAUAudibleParam audParam = *audible->getAudibleParam(); diff --git a/src/Z2AudioLib/Z2AudioMgr.cpp b/src/Z2AudioLib/Z2AudioMgr.cpp index 3ef726dda7..d6d78fb4b7 100644 --- a/src/Z2AudioLib/Z2AudioMgr.cpp +++ b/src/Z2AudioLib/Z2AudioMgr.cpp @@ -31,15 +31,15 @@ Z2AudioMgr::Z2AudioMgr() : mSoundStarter(true) { void Z2AudioMgr::init(JKRSolidHeap* heap, u32 memSize, void* baaData, JKRArchive* seqArc) { JAU_JASInitializer JASInitializer; JASInitializer.audioMemSize_ = memSize; - JASInitializer.field_0x1c = 140; + JASInitializer.mJasTrackPoolSize = 140; JASInitializer.dspLevel_ = 1.3f; JASInitializer.waveArcDir_ = "Audiores/Waves/"; JASInitializer.initJASystem(heap); JAU_JAIInitializer JAIInitializer; - JAIInitializer.field_0x0 = 78; - JAIInitializer.field_0x4 = 4; - JAIInitializer.field_0xc = 48; + JAIInitializer.mJaiSePoolSize = 78; + JAIInitializer.mJaiSeqPoolSize = 4; + JAIInitializer.mJaiSoundChildPoolSize = 48; JAIInitializer.initJAInterface(); JAISeMgr* seMgr = mSoundMgr.getSeMgr(); @@ -107,19 +107,6 @@ void Z2AudioMgr::init(JKRSolidHeap* heap, u32 memSize, void* baaData, JKRArchive JASPoolAllocObject::newMemPool(0x4e); OS_REPORT("[Z2AudioMgr::init]before Create Section: %d\n", heap->getFreeSize()); -#if TARGET_PC - // Fix a race condition with OS threading where JAUNewSectionHeap will use all the remaining - // space in the JASDram heap before JASAudioThread has finished initializing. - - OSLockMutex(&JASAudioThread::sThreadInitCompleteMutex); - while (!JASAudioThread::sThreadInitComplete) { - OSWaitCond( - &JASAudioThread::sThreadInitCompleteCond, - &JASAudioThread::sThreadInitCompleteMutex); - } - OSUnlockMutex(&JASAudioThread::sThreadInitCompleteMutex); -#endif - JAUSectionHeap* sectionHeap = JAUNewSectionHeap(true); sectionHeap->setSeqDataArchive(seqArc); size_t resMaxSize = JASResArcLoader::getResMaxSize(seqArc); @@ -158,7 +145,7 @@ void Z2AudioMgr::init(JKRSolidHeap* heap, u32 memSize, void* baaData, JKRArchive } void Z2AudioMgr::setOutputMode(u32 mode) { - if (mode <= 2) { + if (mode <= JAS_OUTPUT_SURROUND) { JAISetOutputMode(mode); } } @@ -168,7 +155,14 @@ void Z2AudioMgr::zeldaGFrameWork() { mSpeechMgr.framework(); processSeFramework(); processBgmFramework(); + + #if TARGET_PC + if (!dusk::getSettings().game.noLowHpSound) { + processHeartGaugeSound(); + } + #else processHeartGaugeSound(); + #endif #if DEBUG mDebugSys.debugframework(); diff --git a/src/Z2AudioLib/Z2Creature.cpp b/src/Z2AudioLib/Z2Creature.cpp index a17e3d516c..7a27e9e9c4 100644 --- a/src/Z2AudioLib/Z2Creature.cpp +++ b/src/Z2AudioLib/Z2Creature.cpp @@ -211,11 +211,6 @@ Z2SoundHandlePool* Z2Creature::startCreatureSoundLevel(JAISoundID soundID, u32 m } Z2SoundHandlePool* Z2Creature::startCreatureVoice(JAISoundID soundID, s8 reverb) { - #if TARGET_PC - // stubbed - return nullptr; - #endif - switch (soundID) { case Z2SE_MDN_V_FLY_OUT: case Z2SE_MDN_V_MGN_TAME: diff --git a/src/Z2AudioLib/Z2SceneMgr.cpp b/src/Z2AudioLib/Z2SceneMgr.cpp index a31cd534ca..1b2152fcb7 100644 --- a/src/Z2AudioLib/Z2SceneMgr.cpp +++ b/src/Z2AudioLib/Z2SceneMgr.cpp @@ -2018,10 +2018,6 @@ bool Z2SceneMgr::loadSceneWave(u32 wave, u32 bank) { #endif bool Z2SceneMgr::loadSeWave(u32 wave) { - return 0; -} - -/* //lw stub lw JAUSectionHeap* sectionHeap = JASGlobalInstance::getInstance(); JUT_ASSERT(3030, sectionHeap); @@ -2036,13 +2032,8 @@ bool Z2SceneMgr::loadSeWave(u32 wave) { JUT_WARN_DEVICE(3038, 1, "Z2SceneMgr::cannot load SE wave:%d\n", wave); return false; } -*/ + bool Z2SceneMgr::loadBgmWave(u32 wave) { - return true; -} - - /* //lw stub lw - JAUSectionHeap* sectionHeap = JASGlobalInstance::getInstance(); JUT_ASSERT(3047, sectionHeap); @@ -2056,4 +2047,4 @@ bool Z2SceneMgr::loadBgmWave(u32 wave) { JUT_WARN_DEVICE(3055, 1, "Z2SceneMgr::cannot load BGM wave:%d\n", wave); return false; -} */ +} diff --git a/src/Z2AudioLib/Z2SeView.cpp b/src/Z2AudioLib/Z2SeView.cpp new file mode 100644 index 0000000000..e69de29bb2 diff --git a/src/Z2AudioLib/Z2SoundHandles.cpp b/src/Z2AudioLib/Z2SoundHandles.cpp index 9b6aa5a9ba..de7e265ae7 100644 --- a/src/Z2AudioLib/Z2SoundHandles.cpp +++ b/src/Z2AudioLib/Z2SoundHandles.cpp @@ -40,7 +40,7 @@ Z2SoundHandlePool* Z2SoundHandles::getHandleSoundID(JAISoundID soundID) { return NULL; } -Z2SoundHandlePool* Z2SoundHandles::getHandleUserData(u32 userData) { +Z2SoundHandlePool* Z2SoundHandles::getHandleUserData(uintptr_t userData) { JSULink* i; for (i = getFirst(); i != NULL; i = i->getNext()) { Z2SoundHandlePool* handle = i->getObject(); diff --git a/src/Z2AudioLib/Z2SoundObjMgr.cpp b/src/Z2AudioLib/Z2SoundObjMgr.cpp index 6b080134fb..19099c7675 100644 --- a/src/Z2AudioLib/Z2SoundObjMgr.cpp +++ b/src/Z2AudioLib/Z2SoundObjMgr.cpp @@ -107,6 +107,15 @@ static Z2EnemyInfo mEnemyInfo[64] = { void Z2SoundObjMgr::searchEnemy() { twilightBattle_ = 0; + #if TARGET_PC + if (Z2GetSeqMgr()->checkBgmIDPlaying(Z2BGM_MIDNA_SOS) && + dusk::getSettings().game.midnasLamentNonStop) + { + Z2GetSeqMgr()->changeSubBgmStatus(0); + return; + } + #endif + if (!Z2GetLink()) { Z2GetSeqMgr()->stopBattleBgm(1, 1); return; diff --git a/src/Z2AudioLib/Z2SoundObject.cpp b/src/Z2AudioLib/Z2SoundObject.cpp index 93d40c95cf..1c81be0f17 100644 --- a/src/Z2AudioLib/Z2SoundObject.cpp +++ b/src/Z2AudioLib/Z2SoundObject.cpp @@ -502,7 +502,7 @@ void Z2SoundObjAnime::startSoundInner(const JGeometry::TVec3& pos, f32 para JUT_ASSERT(747, curSoundIndex_ < animation_->getNumSounds()); const JAUSoundAnimationSound* animationSound = animation_->getSound(curSoundIndex_); - u32 user_data = (uintptr_t)animationSound; + uintptr_t user_data = (uintptr_t)animationSound; if (reverse_) { curSoundIndex_--; } else { diff --git a/src/Z2AudioLib/Z2SoundPlayer.cpp b/src/Z2AudioLib/Z2SoundPlayer.cpp index d2d6fdecf3..1302d07674 100644 --- a/src/Z2AudioLib/Z2SoundPlayer.cpp +++ b/src/Z2AudioLib/Z2SoundPlayer.cpp @@ -1,46 +1,55 @@ #include "Z2AudioLib/Z2SoundPlayer.h" -#include "Z2AudioLib/Z2SeqMgr.h" +#include "Z2AudioLib/Z2AudioMgr.h" +#include "Z2AudioCS/Z2AudioCS.h" +#include "JSystem/JUtility/JUTGamePad.h" -Z2SoundPlayer::Z2SoundPlayer(const char* param_1) : JAWWindow("Player for JAudio2", 500, 140), field_0x48c(field_0x46c, 8) { - field_0x3ed = 0; - field_0x3ee = 0; - field_0x3ef = 0; - field_0x3f0 = 0; - field_0x3f4 = param_1; +Z2SoundPlayer::Z2SoundPlayer(const char* projectName) + : JAWWindow("Player for JAudio2", 500, 140), + field_0x48c(field_0x46c, 8) +{ + field_0x3ed = false; + field_0x3ee = false; + field_0x3ef = false; + field_0x3f0 = false; + + m_name = projectName; field_0x3f8 = 0; field_0x3fc = 0; field_0x3fa = 0; field_0x3fe = 0; field_0x400 = 0; - field_0x402 = 0; - field_0x444 = 0; + m_portNum = 0; + m_portVal = 0; field_0x446 = 0; - field_0x404 = "CMD_PORT"; - field_0x408 = "END_PORT"; - field_0x40c = "STA_PORT"; - field_0x410 = "WAIT_PORT"; - field_0x414 = "NUM_PORT"; - field_0x418 = "PORT_5"; - field_0x41c = "MAP_PORT"; - field_0x420 = "NOTE_PORT"; - field_0x424 = "SE_SELECT_PORT"; - field_0x428 = "BGM_STATUS_PORT"; - field_0x42c = "BGM_PORT2"; - field_0x430 = "BGM_PORT3"; - field_0x434 = "PORT12"; - field_0x438 = "PORT13"; - field_0x43c = "FILTER_PORT"; - field_0x440 = "FX_PORT"; + + m_portNames[0] = "CMD_PORT"; + m_portNames[1] = "END_PORT"; + m_portNames[2] = "STA_PORT"; + m_portNames[3] = "WAIT_PORT"; + m_portNames[4] = "NUM_PORT"; + m_portNames[5] = "PORT_5"; + m_portNames[6] = "MAP_PORT"; + m_portNames[7] = "NOTE_PORT"; + m_portNames[8] = "SE_SELECT_PORT"; + m_portNames[9] = "BGM_STATUS_PORT"; + m_portNames[10] = "BGM_PORT2"; + m_portNames[11] = "BGM_PORT3"; + m_portNames[12] = "PORT12"; + m_portNames[13] = "PORT13"; + m_portNames[14] = "FILTER_PORT"; + m_portNames[15] = "FX_PORT"; + u8 r30 = 0; field_0x448[r30++] = &field_0x3f8; field_0x448[r30++] = &field_0x3fa; field_0x448[r30++] = &field_0x3fc; field_0x448[r30++] = &field_0x3fe; field_0x448[r30++] = &field_0x400; - field_0x448[r30++] = &field_0x402; - field_0x448[r30] = &field_0x444; - field_0x464 = 0; - field_0x468 = 7; + field_0x448[r30++] = &m_portNum; + field_0x448[r30] = &m_portVal; + + m_cursorY = 0; + m_cursorMax = 7; field_0x4a0 = 0; field_0x4a4 = 1.0f; field_0x4a8 = 0.5f; @@ -48,65 +57,446 @@ Z2SoundPlayer::Z2SoundPlayer(const char* param_1) : JAWWindow("Player for JAudio field_0x4b0 = 0.0f; field_0x4b4 = 0.0f; field_0x4b8 = 1.0f; - field_0x498 = Z2GetSeqMgr()->getSubBgmHandle(); + + mp_subBgmHandle = Z2GetSeqMgr()->getSubBgmHandle(); } -void Z2SoundPlayer::onDraw(JAWGraphContext*) { +void Z2SoundPlayer::onDraw(JAWGraphContext* graf) { + JAUSoundNameTable* soundTable = JASGlobalInstance::getInstance(); + + int var_r27 = 0; + if (field_0x3ed) { + var_r27 = 2; + } + u8 cursorY = 0; + + graf->color(JUtility::TColor(0, 0x7F, 0xFF, 0xFF), JUtility::TColor(0, 0xFF, 0x7F, 0xFF)); + graf->print(1, cursorY++, "Project: %s", m_name); + + graf->color(0xFF >> (u8)var_r27, 0xFF >> (u8)var_r27, 0xFF >> (u8)var_r27, 0xFF); + graf->print(0, m_cursorY + 1, ">"); + + JUtility::TColor sp28(0xFF >> (u8)var_r27, 0xFF >> (u8)var_r27, 0xFF >> (u8)var_r27, 0xFF); + JUtility::TColor sp24(0, 0xFF >> (u8)var_r27, 0, 0xFF); + + onDrawSoundItem(graf, soundTable, cursorY++, + sp28, + sp24, + "SEQ NUM ", + 1, 0, field_0x3f8 + ); + + graf->color(sp28); + const char* cateName; + if (soundTable != NULL) { + cateName = soundTable->getGroupName(JAISoundID(0, field_0x3fa & 0xFF, 0)); + } else { + cateName = ""; + } + graf->print(1, cursorY++, "SE CATE %03x %s", field_0x3fa, cateName); + + onDrawSoundItem(graf, soundTable, cursorY++, + sp28, + sp24, + "SE NUM ", + 0, field_0x3fa & 0xFF, field_0x3fc + ); + onDrawSoundItem(graf, soundTable, cursorY++, + sp28, + sp24, + "STRM NUM", + 2, 0, field_0x3fe + ); + + graf->color(sp28); + graf->print(1, cursorY++, "CORE_SPK %03x %s", field_0x400, Z2AudioCS::getName(field_0x400)); + + graf->color(field_0x446 + 0xC0, 0xC0, 0xC0, 0xFF); + graf->print(1, cursorY++, "PORT NUM %03x %s", m_portNum, m_portNames[m_portNum]); + graf->print(1, cursorY++, "PORT VAL %03x", m_portVal); + + graf->color(0, 0x50, 0xC8, 0xFF); + if (field_0x3ee) { + graf->print(1, cursorY, "DOLBY ON\n"); + } + + graf->color(0xC8, 0x50, 0, 0xFF); + if (field_0x3f0) { + graf->print(10, cursorY, "LEVEL SE CALL"); + } + + graf->color(0xFF, 0, 0, 0xFF); + graf->print(0x16, cursorY, "%s", field_0x3ed ? "PAUSE ON" : ""); + + graf->color(0, 0xC8, (field_0x4a0 * 200) / 30, 0xFF); + if (field_0x3ef) { + graf->print(0x16, cursorY, "RESET %d\n", field_0x4a0); + } } -void Z2SoundPlayer::onTrigA(const JUTGamePad&) { +void Z2SoundPlayer::onTrigA(const JUTGamePad& pad) { + switch (m_cursorY) { + case 0: { + JAISoundID sp24(1, 0, (u16)field_0x3f8); + switch (sp24) { + case 0x100000a: + case 0x100000b: + case 0x100000f: + case 0x1000012: + case 0x1000014: + case 0x100001b: + case 0x100001c: + case 0x1000024: + Z2GetSoundMgr()->startSound(sp24, mp_subBgmHandle, NULL); + break; + default: + Z2GetSoundMgr()->startSound(sp24, &field_0x494, NULL); + break; + } + break; + } + case 1: + case 2: + if (!field_0x3f0) { + JAISoundHandle* handle = field_0x48c.getFreeHandle(); + JAISoundID sp20(0, field_0x3fa & 0xFF, (u16)field_0x3fc); + if (handle != NULL) { + Z2GetSoundStarter()->startSound(sp20, handle, NULL); + if (*handle) { + Z2GetSoundStarter()->setPortData(handle, m_portNum, m_portVal, -1); + } + } + } + break; + case 3: + Z2GetSoundMgr()->startSound(JAISoundID(2, 0, (u16)field_0x3fe), &field_0x49c, NULL); + break; + case 4: + if (!field_0x3f0) { + Z2AudioCS::start(field_0x400, 0); + } + break; + case 5: + case 6: + field_0x446 = 64; + if (m_portNum < 9) { + JAISoundHandle* handle = field_0x48c.getFreeHandle(); + JAISoundID sp1C(0, field_0x3fa & 0xFF, (u16)field_0x3fc); + if (handle != NULL) { + Z2GetSoundStarter()->startSound(sp1C, handle, NULL); + if (*handle) { + Z2GetSoundStarter()->setPortData(handle, m_portNum, m_portVal, -1); + } + } + } else { + if (field_0x494) { + Z2GetSoundStarter()->setPortData(&field_0x494, m_portNum, m_portVal, -1); + } + if (mp_subBgmHandle->isSoundAttached()) { + Z2GetSoundStarter()->setPortData(mp_subBgmHandle, m_portNum, m_portVal, -1); + } + } + break; + } } -void Z2SoundPlayer::onTrigB(const JUTGamePad&) { +void Z2SoundPlayer::onTrigB(const JUTGamePad& pad) { + switch (m_cursorY) { + case 0: { + if (field_0x494) { + field_0x494->stop(0); + } + field_0x494.releaseSound(); + + if (mp_subBgmHandle->isSoundAttached()) { + (*mp_subBgmHandle)->stop(); + } + break; + } + case 1: + case 2: { + JAISoundHandle* handle = field_0x48c.getHandleSoundID(JAISoundID(0, field_0x3fa & 0xFF, (u16)field_0x3fc)); + if (handle) { + (*handle)->stop(); + handle->releaseSound(); + } + break; + } + case 3: + if (field_0x49c) { + field_0x49c->stop(); + } + + field_0x49c.releaseSound(); + break; + case 4: + Z2AudioCS::stop(0); + break; + case 5: + case 6: + m_portVal = 0; + field_0x446 = 0; + + if (field_0x494) { + Z2GetSoundStarter()->setPortData(&field_0x494, m_portNum, m_portVal, -1); + } + + if (mp_subBgmHandle->isSoundAttached()) { + Z2GetSoundStarter()->setPortData(mp_subBgmHandle, m_portNum, m_portVal, -1); + } + break; + } } void Z2SoundPlayer::frameWork() { + switch (m_cursorY) { + case 0: + case 1: + case 2: + case 3: + case 4: + break; + } + if (field_0x3ef) { + field_0x4a0++; + + if (Z2GetAudioMgr()->hasReset()) { + Z2GetAudioMgr()->resetRecover(); + field_0x3ef = false; + OS_REPORT("RESET END \n"); + } + } } -void Z2SoundPlayer::onPadProc(const JUTGamePad&) { +void Z2SoundPlayer::onPadProc(const JUTGamePad& pad) { + if (field_0x3f0 && pad.testButton(PAD_BUTTON_A)) { + switch (m_cursorY) { + case 2: { + JAISoundID sp14(0, field_0x3fa & 0xFF, (u16)field_0x3fc); + JAISoundHandle* handle = field_0x48c.getHandleSoundID(sp14); + if (handle == NULL) { + handle = field_0x48c.getFreeHandle(); + } + if (handle != NULL) { + Z2GetAudioMgr()->startLevelSound(sp14, handle, NULL); + } + + if (*handle) { + Z2GetSoundStarter()->setPortData(handle, m_portNum, m_portVal, -1); + } + break; + } + case 4: + Z2AudioCS::startLevel(field_0x400, 0); + break; + } + } } -void Z2SoundPlayer::onTrigX(const JUTGamePad&) { +void Z2SoundPlayer::onTrigX(const JUTGamePad& pad) { + switch (m_cursorY) { + case 0: { + if (field_0x494) { + field_0x494->pause(!field_0x494->isPaused()); + } + if (mp_subBgmHandle->isSoundAttached()) { + (*mp_subBgmHandle)->pause(!(*mp_subBgmHandle)->isPaused()); + } + break; + } + case 1: + case 2: { + JAISoundHandle* handle = field_0x48c.getHandleSoundID(JAISoundID(0, field_0x3fa & 0xFF, (u16)field_0x3fc)); + if (handle) { + (*handle)->pause(!(*handle)->isPaused()); + } + break; + } + case 3: + if (field_0x49c) { + (field_0x49c)->pause(!(field_0x49c)->isPaused()); + } + break; + case 4: + Z2AudioCS::stop(0); + break; + } } -void Z2SoundPlayer::onTrigY(const JUTGamePad&) { - - -} -void Z2SoundPlayer::onTrigZ(const JUTGamePad&) { - - -} -void Z2SoundPlayer::onTrigL(const JUTGamePad&) { - +void Z2SoundPlayer::onTrigY(const JUTGamePad& pad) { + if (!field_0x3ef) { + Z2GetAudioMgr()->resetProcess(30, false); + field_0x3ef = true; + field_0x4a0 = 0; + } } -void Z2SoundPlayer::onKeyLeft(const JUTGamePad&) { - +void Z2SoundPlayer::onTrigZ(const JUTGamePad& pad) { + bool* pvar = &field_0x3f0; + bool newValue = *pvar ^ 1; + *pvar = newValue; } -void Z2SoundPlayer::onKeyRight(const JUTGamePad&) { +void Z2SoundPlayer::onTrigL(const JUTGamePad& pad) { + bool* pvar = &field_0x3ee; + bool newValue = *pvar ^ 1; + *pvar = newValue; + if (field_0x3ee) { + Z2GetAudioMgr()->setOutputMode(2); + } else { + Z2GetAudioMgr()->setOutputMode(1); + } } -void Z2SoundPlayer::onKeyUp(const JUTGamePad&) { +void Z2SoundPlayer::onKeyLeft(const JUTGamePad& pad) { + int moveMax = getCursorMoveMax(pad); + int menuMax = getMenuNumberMax(); + if (moveMax >= menuMax) { + moveMax = 1; + } + + if (*field_0x448[m_cursorY] > moveMax - 1) { + *field_0x448[m_cursorY] -= (s16)moveMax; + } else { + *field_0x448[m_cursorY] = (*field_0x448[m_cursorY] + menuMax) - moveMax; + } + + if (m_cursorY == 1) { + correctSeNumber(); + } } -void Z2SoundPlayer::onKeyDown(const JUTGamePad&) { +void Z2SoundPlayer::onKeyRight(const JUTGamePad& pad) { + int moveMax = getCursorMoveMax(pad); + int menuMax = getMenuNumberMax(); + if (moveMax >= menuMax) { + moveMax = 1; + } + + if (*field_0x448[m_cursorY] < menuMax - moveMax) { + *field_0x448[m_cursorY] += (s16)moveMax; + } else { + *field_0x448[m_cursorY] = (*field_0x448[m_cursorY] + moveMax) - menuMax; + } + + if (m_cursorY == 1) { + correctSeNumber(); + } } -void Z2SoundPlayer::onKeyMenu(const JUTGamePad&) { - +void Z2SoundPlayer::onKeyUp(const JUTGamePad& pad) { + if (m_cursorY != 0) { + m_cursorY--; + } else { + m_cursorY = m_cursorMax - 1; + } } -u32 Z2SoundPlayer::getCursorMoveMax(const JUTGamePad&) { - +void Z2SoundPlayer::onKeyDown(const JUTGamePad& pad) { + if (m_cursorY < m_cursorMax - 1) { + m_cursorY++; + } else { + m_cursorY = 0; + } +} + +void Z2SoundPlayer::onKeyMenu(const JUTGamePad& pad) { + bool* pvar = &field_0x3ed; + bool newValue = *pvar ^ 1; + *pvar = newValue; + + Z2GetSoundMgr()->pauseAllGameSound(field_0x3ed); +} + +u32 Z2SoundPlayer::getCursorMoveMax(const JUTGamePad& pad) { + u32 num = 1; + + if (pad.testButton(PAD_TRIGGER_Z) && pad.testButton(PAD_BUTTON_X)) { + num = 128; + } else if (pad.testButton(PAD_TRIGGER_Z)) { + num = 16; + } else if (pad.testButton(PAD_BUTTON_X)) { + num = 8; + } + + return num; +} + +int Z2SoundPlayer::getMenuNumberMax() { + JAUSoundTable* soundTable = JASGlobalInstance::getInstance(); + JUT_ASSERT(550, soundTable); + + int num = 0; + switch (m_cursorY) { + case 0: + num = soundTable->getNumItems_inGroup(1, 0); + break; + case 1: + num = soundTable->getNumGroups_inSection(0); + break; + case 2: + num = soundTable->getNumItems_inGroup(0, field_0x3fa); + break; + case 3: + num = soundTable->getNumItems_inGroup(2, 0); + break; + case 4: + num = Z2AudioCS::getNumOfSound(); + break; + case 5: + num = 16; + break; + case 6: + num = 128; + break; + } + + return num; +} + +void Z2SoundPlayer::correctSeNumber() { + JAUSoundTable* soundTable = JASGlobalInstance::getInstance(); + JUT_ASSERT(594, soundTable); + + int num = soundTable->getNumItems_inGroup(0, field_0x3fa); + if (num == 0) { + field_0x3fc = 0; + } else if (field_0x3fc >= num) { + field_0x3fc = num - 1; + } +} + +void Z2SoundPlayer::onDrawSoundItem(JAWGraphContext* graf, JAUSoundNameTable* nameTable, int cursorY, + const JUtility::TColor& color0, const JUtility::TColor& color1, + const char* label, u32 sectionID, u32 groupID, u32 waveID) +{ + static const char szNoEntry[] = "(NO ENTRY)"; + + const char* soundName = ""; + if (nameTable != NULL) { + soundName = nameTable->getName(JAISoundID(sectionID, groupID, waveID)); + if (*soundName == 0) { + soundName = szNoEntry; + } + } else { + soundName = ""; + } + + // !@bug comparing strings directly instead of using strcmp + if (soundName == szNoEntry) { + graf->color(color1); + } else { + graf->color(color0); + } + + graf->print(1, cursorY, "%s %03x %s", label, waveID, soundName); } diff --git a/src/Z2AudioLib/Z2TrackView.cpp b/src/Z2AudioLib/Z2TrackView.cpp new file mode 100644 index 0000000000..e69de29bb2 diff --git a/src/Z2AudioLib/Z2WaveArcLoader.cpp b/src/Z2AudioLib/Z2WaveArcLoader.cpp new file mode 100644 index 0000000000..2522f4a877 --- /dev/null +++ b/src/Z2AudioLib/Z2WaveArcLoader.cpp @@ -0,0 +1,335 @@ +#include "Z2AudioLib/Z2WaveArcLoader.h" +#include "JSystem/JAudio2/JAUSectionHeap.h" +#include "JSystem/JAudio2/JASWaveInfo.h" + +#include + +static f32 cStatusBar_X1 = 8.0f; +static f32 cStatusBar_X2 = 16.0f; +static f32 cWaveBar_X1 = 30.0f; +static f32 cWaveBar_X2 = 80.0f; +static f32 cBar_Y = 5.0f; +static f32 cBarHeight = 310.0f; + +static u8 lbl_8074A738 = 10; +static u8 lbl_8074A739 = 23; + +static u32 cWaveArcListSize = 10; + +Z2WaveArcLoader::Z2WaveArcLoader() : + JAWWindow("Z2WaveArcLoader", 420, 365) +{ + setWindowColor(0, 0, 0x50, 0xFF); + + mpWaveBank = NULL; + mpWaveArc = NULL; + mWaveUsedSize = 0; + mTotalUsedSize = 0; + mBankNo = 0; + mArcCount = 0; + field_0x408 = 0; + field_0x40c = 0; + field_0x410 = 0; + field_0x414 = 0; + mIsLoadTail = false; + + checkWaveBank(); + checkWaveArc(); +} + +Z2WaveArcLoader::~Z2WaveArcLoader() {} + +// nonmatching with tree iterator stuff +void Z2WaveArcLoader::onDraw(JAWGraphContext* graf) { + int cursorX = 8; + JASHeap* rootheap = JASWaveArcLoader::getRootHeap(); + u32 aramsize = JASKernel::getAramSize(); + + mWaveUsedSize = 0; + + for (u32 i = 0; i < 255; i++) { + JASWaveBank* bank = JASGlobalInstance::getInstance()->getWaveBankTable().getWaveBank(i); + if (bank != NULL) { + u32 arcCount = bank->getArcCount(); + for (int j = 0; j < arcCount; j++) { + JASWaveArc* arc = bank->getWaveArc(j); + if (arc != NULL && arc->getStatus() == 2) { + mWaveUsedSize += arc->getFileSize(); + } + } + } + } + + u32 otherUsedSize = mTotalUsedSize - mWaveUsedSize; + u32 totalFree = rootheap->getTotalFreeSize(); + u32 linearFreeSize = rootheap->getFreeSize(); + u32 sp54 = totalFree - linearFreeSize; + + graf->color(JUtility::TColor(0x32, 0x96, 0xFF, 0xFF), JUtility::TColor(0xC8, 0xC8, 0xFF, 0xFF)); + graf->print(cursorX, 0, "ARAM STATUS\n"); + + graf->color(0xFF, 0xFF, 0xFF, 0xFF); + graf->print(cursorX, 1, " total used : %8d\n", mTotalUsedSize); + + graf->color(0xFF, 0x40, 0x40, 0xFF); + graf->print(cursorX, 2, " wave used : %8d\n", mWaveUsedSize); + + graf->color(0xFF, 0xFF, 0x40, 0xFF); + graf->print(cursorX, 3, " other used : %8d\n", otherUsedSize); + + graf->color(0x40, 0xFF, 0x40, 0xFF); + graf->print(cursorX, 4, " linear free : %8d\n", linearFreeSize); + + graf->color(0xFF, 0xFF, 0xFF, 0xFF); + graf->print(cursorX, 5, " total free : %8d\n", totalFree); + graf->print(cursorX, 6, " ------------------------\n"); + graf->print(cursorX, 7, " aram size : %8d\n", aramsize); + + graf->color(0xFF, 0xFF, 0x20, 0xFF); + f32 var_f30 = cBar_Y; + f32 var_f31 = var_f30 + (((f32)otherUsedSize / (f32)aramsize) * cBarHeight); + graf->fillBox(JGeometry::TBox2(cStatusBar_X1, var_f30, cStatusBar_X2, var_f31)); + + graf->color(0xFF, 0x20, 0x20, 0xFF); + var_f30 = var_f31; + var_f31 += ((f32)mWaveUsedSize / (f32)aramsize) * cBarHeight; + graf->fillBox(JGeometry::TBox2(cStatusBar_X1, var_f30, cStatusBar_X2, var_f31)); + + graf->color(0x20, 0xFF, 0x20, 0xFF); + var_f30 = var_f31; + var_f31 += ((f32)linearFreeSize / (f32)aramsize) * cBarHeight; + graf->fillBox(JGeometry::TBox2(cStatusBar_X1, var_f30, cStatusBar_X2, var_f31)); + + graf->color(0x20, 0x20, 0xFF, 0xFF); + var_f30 = var_f31; + var_f31 += ((f32)sp54 / (f32)aramsize) * cBarHeight; + graf->fillBox(JGeometry::TBox2(cStatusBar_X1, var_f30, cStatusBar_X2, var_f31)); + + graf->color(0x40, 0x40, 0xFF, 0xFF); + graf->fillBox(JGeometry::TBox2(cWaveBar_X1, cBar_Y, cWaveBar_X2, cBar_Y + cBarHeight)); + + void* pbase = rootheap->getBase(); + u32 heapSize = rootheap->getSize(); + int sp48 = 0; + + mTotalUsedSize = 0; + + for (JSUTreeIterator i = rootheap->getFirstChild(); (int)i != (int)rootheap->getEndChild(); ++i) { + intptr_t sp40 = (char*)i->getBase() - (char*)pbase; + u32 sp3C = i->getSize(); + mTotalUsedSize += sp3C; + + int sp38 = (sp40 * cBarHeight) / heapSize; + int sp34 = (sp3C * cBarHeight) / heapSize; + JGeometry::TBox2 spD0(cWaveBar_X1, cBar_Y + (f32)sp38, cWaveBar_X2, (f32)sp34 + (cBar_Y + (f32)sp38)); + u8 sp9 = 0xFF; + sp9 = sp48 % 2 ? (u8)0xC0 : (u8)0x80; + graf->color(0xFF, sp9, 0x40, 0xFF); + graf->fillBox(spD0); + + if (mpWaveArc != NULL) { + if (mpWaveArc->getHeap() == i.getObject()) { + graf->color(0xFF, 0xFF, 0xFF, 0xFF); + graf->lineWidth(15); + graf->drawFrame(spD0); + } + } + + sp48++; + } + + graf->color(JUtility::TColor(0xC8, 0xC8, 0xFF, 0xFF), JUtility::TColor(0x32, 0x96, 0xFF, 0xFF)); + if (mIsLoadTail) { + graf->print(cursorX, 9, "WAVE BANK LOAD:Tail"); + } else { + graf->print(cursorX, 9, "WAVE BANK LOAD:Linear"); + } + + int var_r26 = lbl_8074A738; + + if (mpWaveBank == NULL) { + graf->color(0x64, 0x64, 0x64, 0xFF); + graf->print(cursorX, var_r26, " ws:%3d Not Registerd", mBankNo); + + graf->color(0xFF, 0xFF, 0xFF, 0xFF); + graf->print(cursorX, var_r26, ">"); + } else { + graf->color(0xFF, 0xFF, 0xFF, 0xFF); + if (field_0x414 < 2) { + graf->print(cursorX, field_0x414 + var_r26, ">"); + } else { + graf->print(cursorX, field_0x414 + (var_r26 + 1), ">"); + } + + graf->print(cursorX, var_r26++, " ws:%3d", mBankNo); + graf->print(cursorX, var_r26++, " aw:%3d-%3d /%3d", field_0x40c, field_0x410, mArcCount - 1); + + graf->color(0xFF, 0xA0, 0x64, 0xFF); + graf->print(cursorX, var_r26++, " aw_status aw_size"); + + graf->color(0xFF, 0xFF, 0xFF, 0xFF); + + for (int i = field_0x40c; i < field_0x410 + 1; i++) { + JASWaveArc* arc = mpWaveBank->getWaveArc(i); + if (arc == NULL) { + break; + } + + switch (arc->getStatus()) { + case 0: + graf->color(0x64, 0x64, 0x64, 0xFF); + graf->print(cursorX, var_r26, "%3d: NOT_LOAD %8d", i, arc->getFileSize()); + break; + case 1: + graf->color(0xFF, 0x64, 0x64, 0xFF); + graf->print(cursorX, var_r26, "%3d: WAIT_LOAD %8d", i, arc->getFileSize()); + break; + case 2: + graf->color(0xFF, 0xFF, 0xC8, 0xFF); + graf->print(cursorX, var_r26, "%3d: LOAD %8d", i, arc->getFileSize()); + break; + } + + var_r26++; + } + } + + var_r26 = lbl_8074A739; + graf->color(0x96, 0x96, 0xE1, 0xFF); + graf->print(cursorX, var_r26++, "-----------------"); + graf->print(cursorX, var_r26++, " A -> LOAD WAVE"); + graf->print(cursorX, var_r26++, " B -> ERASE WAVE"); + graf->print(cursorX, var_r26++, "-----------------"); +} + +void Z2WaveArcLoader::checkWaveBank() { + JAUSectionHeap* sectionHeap = JASGlobalInstance::getInstance(); + const JAUSectionHeap::TSectionHeapData& heapData = sectionHeap->getSectionHeapData(); + const JAUSection::TSectionData& sectionData = sectionHeap->getSectionData(); + + if (sectionData.registeredWaveBankTables.test(mBankNo)) { + mpWaveBank = heapData.waveBankTable.getWaveBank(mBankNo); + mArcCount = mpWaveBank->getArcCount(); + } else { + mpWaveBank = NULL; + mArcCount = 0; + } + + if (mBankNo == 1) { + mIsLoadTail = true; + } else { + mIsLoadTail = false; + } +} + +void Z2WaveArcLoader::checkWaveArc() { + field_0x40c = field_0x408 * cWaveArcListSize; + if (field_0x40c > mArcCount - 1) { + field_0x408--; + field_0x40c = field_0x408 * cWaveArcListSize; + } + + field_0x410 = (field_0x408 + 1) * cWaveArcListSize - 1; + + if (field_0x410 > mArcCount - 1) { + field_0x410 = mArcCount - 1; + } + + if (field_0x414 > 1) { + if ((field_0x40c + field_0x414) - 2 > field_0x410) { + field_0x414 = (field_0x410 - field_0x40c) + 2; + } + + mpWaveArc = mpWaveBank->getWaveArc(field_0x40c + field_0x414 - 2); + } else { + mpWaveArc = NULL; + } +} + +void Z2WaveArcLoader::onKeyUp(const JUTGamePad&) { + if (mpWaveBank == NULL) { + field_0x414 = 0; + } else { + if (field_0x414 != 0) { + field_0x414--; + } else { + field_0x414 = 11; + } + + checkWaveArc(); + } +} + +void Z2WaveArcLoader::onKeyDown(const JUTGamePad&) { + if (mpWaveBank == NULL) { + field_0x414 = 0; + } else { + if (field_0x414 < 11) { + field_0x414++; + } else { + field_0x414 = 0; + } + + checkWaveArc(); + } +} + +void Z2WaveArcLoader::onKeyLeft(const JUTGamePad&) { + if (field_0x414 == 0) { + if (mBankNo != 0) { + mBankNo--; + } else { + mBankNo = 0; + } + + checkWaveBank(); + } else if (mpWaveBank != NULL) { + if (field_0x408 != 0) { + field_0x408--; + } else { + field_0x408 = 0; + } + + checkWaveArc(); + } +} + +void Z2WaveArcLoader::onKeyRight(const JUTGamePad&) { + if (field_0x414 == 0) { + if (mBankNo < 255) { + mBankNo++; + } else { + mBankNo = 255; + } + + checkWaveBank(); + } else if (mpWaveBank != NULL) { + if (field_0x408 < 255) { + field_0x408++; + } else { + field_0x408 = 255; + } + + checkWaveArc(); + } +} + +void Z2WaveArcLoader::onTrigA(const JUTGamePad&) { + if (mpWaveArc != NULL && mpWaveArc->getStatus() == 0) { + if (mIsLoadTail) { + mpWaveArc->loadTail(NULL); + } else { + mpWaveArc->load(NULL); + } + } +} + +void Z2WaveArcLoader::onTrigB(const JUTGamePad&) { + if (mpWaveArc != NULL && mpWaveArc->getStatus() == 2) { + mpWaveArc->erase(); + } +} + +void Z2WaveArcLoader::onTrigZ(const JUTGamePad&) { + mIsLoadTail = !mIsLoadTail; +} diff --git a/src/d/actor/d_a_alink.cpp b/src/d/actor/d_a_alink.cpp index 58e8935e7d..670dd169c3 100644 --- a/src/d/actor/d_a_alink.cpp +++ b/src/d/actor/d_a_alink.cpp @@ -1467,7 +1467,7 @@ static f32 l_ladderAnmBaseTransY = 102.00054168701172f; static dCcD_SrcCyl l_cylSrc = { { - {0, {{AT_TYPE_WOLF_ATTACK, 3, 0x1A}, {0xD8FFFDFF, 5}, 0x73}}, + {0, {{(u32)AT_TYPE_WOLF_ATTACK, 3, 0x1A}, {0xD8FFFDFF, 5}, 0x73}}, {dCcD_SE_WOLF_BITE, 3, 1, 0, {1}}, {dCcD_SE_NONE, 6, 0, 0, {0}}, {0}, @@ -7509,6 +7509,11 @@ void daAlink_c::setBlendMoveAnime(f32 i_morf) { f32 sp28 = mpHIO->mMove.m.mFootPositionRatio; BOOL sp24 = checkEventRun(); BOOL sp20 = checkBootsMoveAnime(1); +#if TARGET_PC + if (dusk::getSettings().game.enableFastIronBoots) { + sp20 = FALSE; + } +#endif f32 var_f29; @@ -9469,6 +9474,11 @@ void daAlink_c::setStickData() { } else { mHeavySpeedMultiplier = mpHIO->mItem.mIronBoots.m.mInputFactor; } +#if TARGET_PC + if (dusk::getSettings().game.enableFastIronBoots) { + mHeavySpeedMultiplier = 1.0f; + } +#endif mStickValue *= mHeavySpeedMultiplier; } else if (checkBootsOrArmorHeavy()) { if (checkZoraWearAbility()) { @@ -9476,6 +9486,11 @@ void daAlink_c::setStickData() { } else { mHeavySpeedMultiplier = mpHIO->mItem.mIronBoots.m.mWaterInputFactor; } +#if TARGET_PC + if (dusk::getSettings().game.enableFastIronBoots) { + mHeavySpeedMultiplier = 1.0f; + } +#endif mStickValue *= mHeavySpeedMultiplier; } else if ((checkWolf() && field_0x2fbc == 11 && checkWaterPolygonUnder()) || mGndPolyAtt0 == 11) @@ -12662,7 +12677,11 @@ void daAlink_c::setMagicArmorBrk(int i_status) { } BOOL daAlink_c::checkMagicArmorHeavy() const { +#if TARGET_PC + return checkMagicArmorWearAbility() && (dComIfGs_getRupee() == 0 && !dusk::getSettings().game.freeMagicArmor); +#else return checkMagicArmorWearAbility() && dComIfGs_getRupee() == 0; +#endif } BOOL daAlink_c::checkBootsOrArmorHeavy() const { @@ -18568,7 +18587,13 @@ int daAlink_c::execute() { field_0x372c = cXyz::Zero; field_0x2fb8 = 0; +#if TARGET_PC + // This handles rupee drain and transitions between rupees/no rupees + // We can skip all of that if the magic armor doesn't use rupees + if (!dusk::getSettings().game.freeMagicArmor && checkMagicArmorWearAbility() && mClothesChangeWaitTimer == 0) { +#else if (checkMagicArmorWearAbility() && mClothesChangeWaitTimer == 0) { +#endif if (checkMagicArmorNoDamage() && !checkEventRun()) { if (field_0x2fc3 == 0) { field_0x2fc3 = 10; diff --git a/src/d/actor/d_a_alink_cut.inc b/src/d/actor/d_a_alink_cut.inc index 4e9dd18aee..8e61a262cb 100644 --- a/src/d/actor/d_a_alink_cut.inc +++ b/src/d/actor/d_a_alink_cut.inc @@ -7,6 +7,8 @@ #include "d/actor/d_a_b_gnd.h" #include "SSystem/SComponent/c_math.h" +#include "dusk/settings.h" + enum daAlink_CutNmParamType { CUT_NM_PARAM_VERTICAL, CUT_NM_PARAM_LEFT, @@ -369,6 +371,12 @@ BOOL daAlink_c::changeCutReverseProc(daAlink_c::daAlink_ANM i_anmID) { return procCutReverseInit(i_anmID); } + #if TARGET_PC + if (dusk::getSettings().game.noSwordRecoil) { + return FALSE; + } + #endif + if (checkNoResetFlg0(FLG0_CUT_AT_FLG) || mEquipItem == dItemNo_COPY_ROD_e) { cXyz sp28; Vec sp1C; diff --git a/src/d/actor/d_a_alink_damage.inc b/src/d/actor/d_a_alink_damage.inc index 122bf8f248..ac5175e314 100644 --- a/src/d/actor/d_a_alink_damage.inc +++ b/src/d/actor/d_a_alink_damage.inc @@ -152,6 +152,13 @@ f32 daAlink_c::damageMagnification(BOOL i_checkZoraMag, int param_1) { base_mag = 1.0f; } + #if TARGET_PC + base_mag *= dusk::getSettings().game.damageMultiplier; + if (dusk::getSettings().game.instantDeath) { + base_mag = 9999.0f; + } + #endif + if (checkWolf() && !checkCargoCarry() && param_1 == 0) { return 2.0f * base_mag; } @@ -180,6 +187,11 @@ int daAlink_c::setDamagePoint(int i_dmgAmount, BOOL i_checkZoraMag, BOOL i_setDm } if (checkMagicArmorNoDamage()) { +#if TARGET_PC + if(dusk::getSettings().game.freeMagicArmor) { + i_dmgAmount = 0; + } +#endif dComIfGp_setItemRupeeCount(-i_dmgAmount * 10); } else #if DEBUG diff --git a/src/d/actor/d_a_alink_demo.inc b/src/d/actor/d_a_alink_demo.inc index 462c35d4e8..aa77b24129 100644 --- a/src/d/actor/d_a_alink_demo.inc +++ b/src/d/actor/d_a_alink_demo.inc @@ -23,6 +23,8 @@ #include "d/actor/d_a_npc_tkc.h" #include +#include "dusk/settings.h" + BOOL daAlink_c::checkEventRun() const { return dComIfGp_event_runCheck() || checkPlayerDemoMode(); } @@ -2230,6 +2232,12 @@ void daAlink_c::setGetSubBgm(int i_itemNo) { } BOOL daAlink_c::checkTreasureRupeeReturn(int i_itemNo) const { + #if TARGET_PC + if (dusk::getSettings().game.noReturnRupees) { + return FALSE; + } + #endif + static const int dummy = 0; if (i_itemNo == dItemNo_LINKS_SAVINGS_e) { @@ -4290,7 +4298,7 @@ static fopAc_ac_c* daAlink_searchPortal(fopAc_ac_c* i_actor, void* i_data) { } bool daAlink_c::checkAcceptWarp() { - #if VERSION != VERSION_WII_USA_R0 + #if TARGET_PC || VERSION != VERSION_WII_USA_R0 cM3dGPla plane; #endif @@ -4298,7 +4306,9 @@ bool daAlink_c::checkAcceptWarp() { * Fixed in versions above Wii USA Rev 0 by checking FLG0_WATER_IN_MOVE */ if (mLinkAcch.ChkGroundHit() && !checkModeFlg(MODE_PLAYER_FLY) - #if VERSION != VERSION_WII_USA_R0 + #if TARGET_PC + && (dusk::getSettings().game.restoreWiiGlitches || !checkNoResetFlg0(FLG0_WATER_IN_MOVE)) + #elif VERSION != VERSION_WII_USA_R0 && !checkNoResetFlg0(FLG0_WATER_IN_MOVE) #endif ) @@ -4307,7 +4317,9 @@ bool daAlink_c::checkAcceptWarp() { * Fixed in versions above Wii USA Rev 0 by checking getSlidePolygon */ if ( - #if VERSION != VERSION_WII_USA_R0 + #if TARGET_PC + (dusk::getSettings().game.restoreWiiGlitches || !getSlidePolygon(&plane)) && + #elif VERSION != VERSION_WII_USA_R0 !getSlidePolygon(&plane) && #endif !checkForestOldCentury() diff --git a/src/d/actor/d_a_alink_dusk.cpp b/src/d/actor/d_a_alink_dusk.cpp new file mode 100644 index 0000000000..95218268ac --- /dev/null +++ b/src/d/actor/d_a_alink_dusk.cpp @@ -0,0 +1,78 @@ +#include "d/actor/d_a_alink.h" +#include "d/actor/d_a_midna.h" +#include "d/d_meter2.h" +#include "d/d_meter2_draw.h" +#include "d/d_meter2_info.h" + +void daAlink_c::handleQuickTransform() { + if (!dusk::getSettings().game.enableQuickTransform) { + return; + } + + // Ensure that link is not in a cutscene. + if (checkEventRun()) { + return; + } + + // Check to see if Link has the ability to transform. + if (!dComIfGs_isEventBit(dSv_event_flag_c::M_077)) { + return; + } + + // Ensure there is a proper pointer to the mMeterClass and mpMeterDraw structs in g_meter2_info. + const auto meterClassPtr = g_meter2_info.getMeterClass(); + if (!meterClassPtr) { + return; + } + + const auto meterDrawPtr = meterClassPtr->getMeterDrawPtr(); + if (!meterDrawPtr) { + return; + } + + mDoCPd_c::getCpadInfo(PAD_1).mPressedButtonFlags = 0; + + // Ensure that the Z Button is not dimmed + if (meterDrawPtr->getButtonZAlpha() != 1.f) { + Z2GetAudioMgr()->seStart(Z2SE_SYS_ERROR, NULL, 0, 0, 1.0f, 1.0f, -1.0f, -1.0f, 0); + return; + } + + // The game will crash if trying to quick transform while holding the Ball and Chain + if (mEquipItem == dItemNo_IRONBALL_e) { + Z2GetAudioMgr()->seStart(Z2SE_SYS_ERROR, NULL, 0, 0, 1.0f, 1.0f, -1.0f, -1.0f, 0); + return; + } + + // Use the game's default checks for if the player can currently transform + if (!m_midnaActor->checkMetamorphoseEnableBase()) { + Z2GetAudioMgr()->seStart(Z2SE_SYS_ERROR, NULL, 0, 0, 1.0f, 1.0f, -1.0f, -1.0f, 0); + return; + } + + bool canTransform = false; + + if (mLinkAcch.ChkGroundHit() && !checkModeFlg(MODE_PLAYER_FLY) && !checkMagneBootsOn()) { + if (!checkForestOldCentury()) { + if (checkMidnaRide()) { + if ((checkWolf() && + (checkModeFlg(MODE_UNK_1000) || dComIfGp_checkPlayerStatus0(0, 0x10))) || + (!checkWolf() && + (checkEventRun() || getMidnaActor()->checkMetamorphoseEnable()) && + (checkModeFlg(4) || dComIfGp_checkPlayerStatus0(0, 0x10)))) + { + canTransform = true; + } + } + } + } + + if (!canTransform) + { + Z2GetAudioMgr()->seStart(Z2SE_SYS_ERROR, NULL, 0, 0, 1.0f, 1.0f, -1.0f, -1.0f, 0); + return; + } + + OSReport("Running quick transform!"); + procCoMetamorphoseInit(); +} diff --git a/src/d/actor/d_a_alink_effect.inc b/src/d/actor/d_a_alink_effect.inc index 6e76280ff6..d595cd4293 100644 --- a/src/d/actor/d_a_alink_effect.inc +++ b/src/d/actor/d_a_alink_effect.inc @@ -1562,6 +1562,10 @@ void daAlink_c::setMetamorphoseEffectStartLink() { emitter->setGlobalParticleScale(effScale); } #endif + + #if TARGET_PC + emitter->setGlobalParticleScale(mDoGph_gInf_c::getScale(), 1.0f); + #endif } void daAlink_c::setMetamorphoseEffect() { diff --git a/src/d/actor/d_a_alink_hang.inc b/src/d/actor/d_a_alink_hang.inc index b99fe71c85..89f11fc940 100644 --- a/src/d/actor/d_a_alink_hang.inc +++ b/src/d/actor/d_a_alink_hang.inc @@ -13,8 +13,15 @@ #include "d/actor/d_a_obj_swhang.h" f32 daAlink_c::getHangMoveAnmSpeed() { + #if TARGET_PC + return getAnmSpeedStickRate( + dusk::getSettings().game.fastClimbing ? 2.0f : mpHIO->mWallHang.mWallMove.m.mMinAnmSpeed, + dusk::getSettings().game.fastClimbing ? 2.0f : mpHIO->mWallHang.mWallMove.m.mMaxAnmSpeed + ); + #else return getAnmSpeedStickRate(mpHIO->mWallHang.mWallMove.m.mMinAnmSpeed, mpHIO->mWallHang.mWallMove.m.mMaxAnmSpeed); + #endif } int daAlink_c::getHangDirectionFromAngle() { @@ -278,7 +285,11 @@ int daAlink_c::procHangStartInit() { offNoResetFlg2(FLG2_UNK_2000); if (checkHangFootWall()) { + #if TARGET_PC + if (!is_prev_hangReady && cM_rnd() < 0.7f && !dusk::getSettings().game.noMissClimbing) { + #else if (!is_prev_hangReady && cM_rnd() < 0.7f) { + #endif setSingleAnimeParam(ANM_CLIMB_HANG_MISS, &mpHIO->mLadder.m.mWallAttachMissAnm); field_0x3478 = mpHIO->mLadder.m.mWallAttachMissAnm.mCancelFrame; voiceStart(Z2SE_AL_V_FOOT_MISS); @@ -1209,7 +1220,12 @@ void daAlink_c::setLadderPos(int param_0) { f32 daAlink_c::getLadderMoveAnmSpeed() { return getAnmSpeedStickRate(mpHIO->mLadder.m.mMoveMinASpeed, - mpHIO->mLadder.m.mMoveMaxSpeed); + #if TARGET_PC + dusk::getSettings().game.fastClimbing ? 1.575f : mpHIO->mLadder.m.mMoveMaxSpeed + #else + mpHIO->mLadder.m.mMoveMaxSpeed + #endif + ); } int daAlink_c::changeLadderMoveProc(int param_0) { @@ -1304,8 +1320,14 @@ int daAlink_c::procLadderUpStartInit() { mNormalSpeed = 0.0f; speedF = 0.0f; - setSingleAnimeBaseSpeed(ANM_LADDER_UP_START, mpHIO->mLadder.m.mClimbUpStartASpeed, - mpHIO->mLadder.m.mClimbUpStartInterp); + setSingleAnimeBaseSpeed(ANM_LADDER_UP_START, + #if TARGET_PC + dusk::getSettings().game.fastClimbing ? 1.8f : mpHIO->mLadder.m.mClimbUpStartASpeed, + #else + mpHIO->mLadder.m.mClimbUpStartASpeed, + #endif + mpHIO->mLadder.m.mClimbUpStartInterp); + field_0x2f99 = 0x10; field_0x3588 = l_waitBaseAnime; dComIfGp_setPlayerStatus0(0, 0x2000000); @@ -1354,8 +1376,14 @@ int daAlink_c::procLadderUpEndInit(BOOL param_0) { anm_id = ANM_LADDER_UP_END_RIGHT; } - setSingleAnimeBaseSpeed(anm_id, mpHIO->mLadder.m.mClimbUpEndASpeed, - mpHIO->mLadder.m.mClimbUpEndInterp); + setSingleAnimeBaseSpeed(anm_id, + #if TARGET_PC + dusk::getSettings().game.fastClimbing ? 1.765f : mpHIO->mLadder.m.mClimbUpEndASpeed, + #else + mpHIO->mLadder.m.mClimbUpEndASpeed, + #endif + mpHIO->mLadder.m.mClimbUpEndInterp); + field_0x2f99 = 14; setSpecialGravity(0.0f, maxFallSpeed, 0); @@ -1413,8 +1441,14 @@ int daAlink_c::procLadderDownStartInit() { shape_angle.y = field_0x306e + 0x8000; current.angle.y = field_0x306e; - setSingleAnimeBaseSpeed(ANM_LADDER_DOWN_START, mpHIO->mLadder.m.mClimbDownStartASpeed, - mpHIO->mLadder.m.mClimbDownStartInterp); + setSingleAnimeBaseSpeed(ANM_LADDER_DOWN_START, + #if TARGET_PC + dusk::getSettings().game.fastClimbing ? 1.8f : mpHIO->mLadder.m.mClimbDownStartASpeed, + #else + mpHIO->mLadder.m.mClimbDownStartASpeed, + #endif + mpHIO->mLadder.m.mClimbDownStartInterp); + field_0x2f99 = 0x10; field_0x3588 = l_waitBaseAnime; dComIfGp_setPlayerStatus0(0, 0x2000000); @@ -1469,8 +1503,14 @@ int daAlink_c::procLadderDownEndInit(BOOL param_0) { anm_id = ANM_LADDER_DOWN_END_RIGHT; } - setSingleAnimeBaseSpeed(anm_id, mpHIO->mLadder.m.mClimbDownEndASpeed, - mpHIO->mLadder.m.mClimbDownEndInterp); + setSingleAnimeBaseSpeed(anm_id, + #if TARGET_PC + dusk::getSettings().game.fastClimbing ? 1.8f : mpHIO->mLadder.m.mClimbDownEndASpeed, + #else + mpHIO->mLadder.m.mClimbDownEndASpeed, + #endif + mpHIO->mLadder.m.mClimbDownEndInterp); + field_0x2f99 = 14; setSpecialGravity(0.0f, maxFallSpeed, 0); @@ -1602,12 +1642,22 @@ int daAlink_c::procLadderMove() { f32 daAlink_c::getClimbMoveUpDownAnmSpeed() { return getAnmSpeedStickRate(mpHIO->mLadder.m.mWallVerticalMinAnmSpeed, - mpHIO->mLadder.m.mWallVerticalMaxAnmSpeed); + #if TARGET_PC + dusk::getSettings().game.fastClimbing ? 1.875f : mpHIO->mLadder.m.mWallVerticalMaxAnmSpeed + #else + mpHIO->mLadder.m.mWallVerticalMaxAnmSpeed + #endif + ); } f32 daAlink_c::getClimbMoveSideAnmSpeed() { return getAnmSpeedStickRate(mpHIO->mLadder.m.mWallHorizontalMinAnmSpeed, - mpHIO->mLadder.m.mWallHorizontalMaxAnmSpeed); + #if TARGET_PC + dusk::getSettings().game.fastClimbing ? 2.0f : mpHIO->mLadder.m.mWallHorizontalMaxAnmSpeed + #else + mpHIO->mLadder.m.mWallHorizontalMaxAnmSpeed + #endif + ); } BOOL daAlink_c::checkClimbCode(cBgS_PolyInfo& i_polyinfo) { @@ -2038,7 +2088,11 @@ int daAlink_c::procClimbUpStartInit(int param_0) { speed.y = 0.0f; mNormalSpeed = 0.0f; + #if TARGET_PC + if (param_0 || var_r29 || cM_rnd() < 0.3f || dusk::getSettings().game.noMissClimbing) { + #else if (param_0 || var_r29 || cM_rnd() < 0.3f) { + #endif setSingleAnimeParam(ANM_CLIMB_HANG, &mpHIO->mLadder.m.mWallAttachAnm); field_0x3478 = mpHIO->mLadder.m.mWallAttachAnm.mCancelFrame; voiceStart(Z2SE_AL_V_JUMP_HANG); @@ -2115,7 +2169,11 @@ int daAlink_c::procClimbDownStartInit(s16 param_0) { deleteEquipItem(TRUE, FALSE); + #if TARGET_PC + if (cM_rnd() < 0.7f || dusk::getSettings().game.noMissClimbing) { + #else if (cM_rnd() < 0.7f) { + #endif setSingleAnimeParam(ANM_CLIMB_HANG, &mpHIO->mLadder.m.mWallAttachAnm); field_0x3478 = mpHIO->mLadder.m.mWallAttachAnm.mCancelFrame; mProcVar0.field_0x3008 = 0; diff --git a/src/d/actor/d_a_alink_hvyboots.inc b/src/d/actor/d_a_alink_hvyboots.inc index 0edee19cf2..6f7fa8da40 100644 --- a/src/d/actor/d_a_alink_hvyboots.inc +++ b/src/d/actor/d_a_alink_hvyboots.inc @@ -348,7 +348,9 @@ int daAlink_c::procMagneBootsFly() { * Fixed in GCN and Wii KOR versions by adding a checkEquipHeavyBoots check */ if (dComIfG_Bgsp().ChkPolySafe(mPolyInfo2) - #if PLATFORM_GCN || VERSION == VERSION_WII_KOR + #if TARGET_PC + && (dusk::getSettings().game.restoreWiiGlitches || checkEquipHeavyBoots()) + #elif PLATFORM_GCN || VERSION == VERSION_WII_KOR && checkEquipHeavyBoots() #endif ) diff --git a/src/d/actor/d_a_alink_kandelaar.inc b/src/d/actor/d_a_alink_kandelaar.inc index 339ff90ce6..88c2152e03 100644 --- a/src/d/actor/d_a_alink_kandelaar.inc +++ b/src/d/actor/d_a_alink_kandelaar.inc @@ -180,7 +180,12 @@ void daAlink_c::preKandelaarDraw() { mat_p->setTevColor(2, &color); cXyz proj; + + #if TARGET_PC + mDoLib_project(&mKandelaarFlamePos, &proj, {0, 0, FB_WIDTH, FB_HEIGHT}); + #else mDoLib_project(&mKandelaarFlamePos, &proj); + #endif camera_process_class* camera_p = dComIfGp_getCamera(0); f32 trimHeight; diff --git a/src/d/actor/d_a_alink_swindow.inc b/src/d/actor/d_a_alink_swindow.inc index cf3593dfce..81c7a1ca18 100644 --- a/src/d/actor/d_a_alink_swindow.inc +++ b/src/d/actor/d_a_alink_swindow.inc @@ -40,6 +40,9 @@ void daAlink_c::setOriginalHeap(JKRExpHeap** i_ppheap, u32 i_size) { u32 var_r29 = 0x90; u32 var_r28 = 0x10; u32 size = ROUND(i_size, 16); +#if TARGET_PC + size *= 2; +#endif JKRHeap* parent = mDoExt_getGameHeap(); JKRExpHeap* heap = JKRExpHeap::create(size + (var_r29 + var_r28), parent, true); diff --git a/src/d/actor/d_a_alink_wolf.inc b/src/d/actor/d_a_alink_wolf.inc index 2bf1129f17..2e38298090 100644 --- a/src/d/actor/d_a_alink_wolf.inc +++ b/src/d/actor/d_a_alink_wolf.inc @@ -313,7 +313,12 @@ void daAlink_c::changeLink(int param_0) { mpLinkHandModel = initModel(static_cast(dComIfG_getObjectRes(l_mArcName, "al_hands.bmd")), 0); - if (dComIfGs_getRupee() != 0) { +#if TARGET_PC + if (dComIfGs_getRupee() != 0 || dusk::getSettings().game.freeMagicArmor) +#else + if (dComIfGs_getRupee() != 0) +#endif + { setMagicArmorBrk(1); } else { setMagicArmorBrk(0); @@ -398,7 +403,11 @@ void daAlink_c::changeLink(int param_0) { field_0x06ec = field_0x064C->getMaterialNodePointer(1)->getShape(); field_0x06f0 = field_0x064C->getMaterialNodePointer(2)->getShape(); +#if TARGET_PC + if (dComIfGs_getRupee() != 0 || dusk::getSettings().game.freeMagicArmor) { +#else if (dComIfGs_getRupee() != 0) { +#endif var_r27 = 4; } else { var_r27 = 5; diff --git a/src/d/actor/d_a_b_bq.cpp b/src/d/actor/d_a_b_bq.cpp index f109c11509..70ab84705b 100644 --- a/src/d/actor/d_a_b_bq.cpp +++ b/src/d/actor/d_a_b_bq.cpp @@ -1444,11 +1444,11 @@ static void demo_camera(b_bq_class* i_this) { i_this->mDemoCamEyeTarget.set(240.0f, 274.0f, 2075.0f); i_this->field_0x1288.x = - std::fabsf(i_this->mDemoCamCenterTarget.x - i_this->mDemoCamCenter.x); + fabsf(i_this->mDemoCamCenterTarget.x - i_this->mDemoCamCenter.x); i_this->field_0x1288.y = - std::fabsf(i_this->mDemoCamCenterTarget.y - i_this->mDemoCamCenter.y); + fabsf(i_this->mDemoCamCenterTarget.y - i_this->mDemoCamCenter.y); i_this->field_0x1288.z = - std::fabsf(i_this->mDemoCamCenterTarget.z - i_this->mDemoCamCenter.z); + fabsf(i_this->mDemoCamCenterTarget.z - i_this->mDemoCamCenter.z); } spFC.set(0.0f, 0.0f, 1700.0f); @@ -1478,16 +1478,16 @@ static void demo_camera(b_bq_class* i_this) { i_this->mDemoCamCenterTarget.set(76.0f, 204.0f, 1782.0f); i_this->mDemoCamEyeTarget.set(-41.0f, 261.0f, 2095.0f); - i_this->field_0x127c.x = std::fabsf(i_this->mDemoCamEyeTarget.x - i_this->mDemoCamEye.x); - i_this->field_0x127c.y = std::fabsf(i_this->mDemoCamEyeTarget.y - i_this->mDemoCamEye.y); - i_this->field_0x127c.z = std::fabsf(i_this->mDemoCamEyeTarget.z - i_this->mDemoCamEye.z); + i_this->field_0x127c.x = fabsf(i_this->mDemoCamEyeTarget.x - i_this->mDemoCamEye.x); + i_this->field_0x127c.y = fabsf(i_this->mDemoCamEyeTarget.y - i_this->mDemoCamEye.y); + i_this->field_0x127c.z = fabsf(i_this->mDemoCamEyeTarget.z - i_this->mDemoCamEye.z); i_this->field_0x1288.x = - std::fabsf(i_this->mDemoCamCenterTarget.x - i_this->mDemoCamCenter.x); + fabsf(i_this->mDemoCamCenterTarget.x - i_this->mDemoCamCenter.x); i_this->field_0x1288.y = - std::fabsf(i_this->mDemoCamCenterTarget.y - i_this->mDemoCamCenter.y); + fabsf(i_this->mDemoCamCenterTarget.y - i_this->mDemoCamCenter.y); i_this->field_0x1288.z = - std::fabsf(i_this->mDemoCamCenterTarget.z - i_this->mDemoCamCenter.z); + fabsf(i_this->mDemoCamCenterTarget.z - i_this->mDemoCamCenter.z); i_this->field_0x129c = 0.0f; i_this->mDemoMode = 12; @@ -1584,16 +1584,16 @@ static void demo_camera(b_bq_class* i_this) { i_this->mDemoCamCenterTarget.set(0.0f, 278.0f, 1252.0f); i_this->mDemoCamEyeTarget.set(0.0f, 86.0f, 2167.0f); - i_this->field_0x127c.x = std::fabsf(i_this->mDemoCamEyeTarget.x - i_this->mDemoCamEye.x); - i_this->field_0x127c.y = std::fabsf(i_this->mDemoCamEyeTarget.y - i_this->mDemoCamEye.y); - i_this->field_0x127c.z = std::fabsf(i_this->mDemoCamEyeTarget.z - i_this->mDemoCamEye.z); + i_this->field_0x127c.x = fabsf(i_this->mDemoCamEyeTarget.x - i_this->mDemoCamEye.x); + i_this->field_0x127c.y = fabsf(i_this->mDemoCamEyeTarget.y - i_this->mDemoCamEye.y); + i_this->field_0x127c.z = fabsf(i_this->mDemoCamEyeTarget.z - i_this->mDemoCamEye.z); i_this->field_0x1288.x = - std::fabsf(i_this->mDemoCamCenterTarget.x - i_this->mDemoCamCenter.x); + fabsf(i_this->mDemoCamCenterTarget.x - i_this->mDemoCamCenter.x); i_this->field_0x1288.y = - std::fabsf(i_this->mDemoCamCenterTarget.y - i_this->mDemoCamCenter.y); + fabsf(i_this->mDemoCamCenterTarget.y - i_this->mDemoCamCenter.y); i_this->field_0x1288.z = - std::fabsf(i_this->mDemoCamCenterTarget.z - i_this->mDemoCamCenter.z); + fabsf(i_this->mDemoCamCenterTarget.z - i_this->mDemoCamCenter.z); i_this->field_0x129c = 0.0f; i_this->mDemoMode = 14; @@ -1741,16 +1741,16 @@ static void demo_camera(b_bq_class* i_this) { i_this->mDemoCamCenterTarget.set(-2243.0f, 1340.0f, 977.0f); i_this->mDemoCamEyeTarget.set(-1226.0f, 980.0f, 1350.0f); - i_this->field_0x127c.x = std::fabsf(i_this->mDemoCamEyeTarget.x - i_this->mDemoCamEye.x); - i_this->field_0x127c.y = std::fabsf(i_this->mDemoCamEyeTarget.y - i_this->mDemoCamEye.y); - i_this->field_0x127c.z = std::fabsf(i_this->mDemoCamEyeTarget.z - i_this->mDemoCamEye.z); + i_this->field_0x127c.x = fabsf(i_this->mDemoCamEyeTarget.x - i_this->mDemoCamEye.x); + i_this->field_0x127c.y = fabsf(i_this->mDemoCamEyeTarget.y - i_this->mDemoCamEye.y); + i_this->field_0x127c.z = fabsf(i_this->mDemoCamEyeTarget.z - i_this->mDemoCamEye.z); i_this->field_0x1288.x = - std::fabsf(i_this->mDemoCamCenterTarget.x - i_this->mDemoCamCenter.x); + fabsf(i_this->mDemoCamCenterTarget.x - i_this->mDemoCamCenter.x); i_this->field_0x1288.y = - std::fabsf(i_this->mDemoCamCenterTarget.y - i_this->mDemoCamCenter.y); + fabsf(i_this->mDemoCamCenterTarget.y - i_this->mDemoCamCenter.y); i_this->field_0x1288.z = - std::fabsf(i_this->mDemoCamCenterTarget.z - i_this->mDemoCamCenter.z); + fabsf(i_this->mDemoCamCenterTarget.z - i_this->mDemoCamCenter.z); i_this->field_0x129c = 0.0f; i_this->mDemoMode = 34; @@ -1814,9 +1814,9 @@ static void demo_camera(b_bq_class* i_this) { i_this->mDemoCamEye.set(95.0f, 50.0f, 2800.0f); i_this->mDemoCamEyeTarget.set(72.0f, 52.0f, 2153.0f); - i_this->field_0x127c.x = std::fabsf(i_this->mDemoCamEyeTarget.x - i_this->mDemoCamEye.x); - i_this->field_0x127c.y = std::fabsf(i_this->mDemoCamEyeTarget.y - i_this->mDemoCamEye.y); - i_this->field_0x127c.z = std::fabsf(i_this->mDemoCamEyeTarget.z - i_this->mDemoCamEye.z); + i_this->field_0x127c.x = fabsf(i_this->mDemoCamEyeTarget.x - i_this->mDemoCamEye.x); + i_this->field_0x127c.y = fabsf(i_this->mDemoCamEyeTarget.y - i_this->mDemoCamEye.y); + i_this->field_0x127c.z = fabsf(i_this->mDemoCamEyeTarget.z - i_this->mDemoCamEye.z); i_this->field_0x1288.set(0.0f, 0.0f, 0.0f); i_this->field_0x129c = 0.0f; @@ -1973,18 +1973,18 @@ static void demo_camera(b_bq_class* i_this) { i_this->mDemoCamEyeTarget.set(1214.0f, 350.0f, 2696.0f); i_this->field_0x127c.x = - std::fabsf(i_this->mDemoCamEyeTarget.x - i_this->mDemoCamEye.x); + fabsf(i_this->mDemoCamEyeTarget.x - i_this->mDemoCamEye.x); i_this->field_0x127c.y = - std::fabsf(i_this->mDemoCamEyeTarget.y - i_this->mDemoCamEye.y); + fabsf(i_this->mDemoCamEyeTarget.y - i_this->mDemoCamEye.y); i_this->field_0x127c.z = - std::fabsf(i_this->mDemoCamEyeTarget.z - i_this->mDemoCamEye.z); + fabsf(i_this->mDemoCamEyeTarget.z - i_this->mDemoCamEye.z); i_this->field_0x1288.x = - std::fabsf(i_this->mDemoCamCenterTarget.x - i_this->mDemoCamCenter.x); + fabsf(i_this->mDemoCamCenterTarget.x - i_this->mDemoCamCenter.x); i_this->field_0x1288.y = - std::fabsf(i_this->mDemoCamCenterTarget.y - i_this->mDemoCamCenter.y); + fabsf(i_this->mDemoCamCenterTarget.y - i_this->mDemoCamCenter.y); i_this->field_0x1288.z = - std::fabsf(i_this->mDemoCamCenterTarget.z - i_this->mDemoCamCenter.z); + fabsf(i_this->mDemoCamCenterTarget.z - i_this->mDemoCamCenter.z); i_this->field_0x129c = 0.0f; } else if (i_this->mDemoModeTimer < 140) { @@ -1993,18 +1993,18 @@ static void demo_camera(b_bq_class* i_this) { i_this->mDemoCamEyeTarget.set(23.0f, 108.0f, 2155.0f); i_this->field_0x127c.x = - std::fabsf(i_this->mDemoCamEyeTarget.x - i_this->mDemoCamEye.x); + fabsf(i_this->mDemoCamEyeTarget.x - i_this->mDemoCamEye.x); i_this->field_0x127c.y = - std::fabsf(i_this->mDemoCamEyeTarget.y - i_this->mDemoCamEye.y); + fabsf(i_this->mDemoCamEyeTarget.y - i_this->mDemoCamEye.y); i_this->field_0x127c.z = - std::fabsf(i_this->mDemoCamEyeTarget.z - i_this->mDemoCamEye.z); + fabsf(i_this->mDemoCamEyeTarget.z - i_this->mDemoCamEye.z); i_this->field_0x1288.x = - std::fabsf(i_this->mDemoCamCenterTarget.x - i_this->mDemoCamCenter.x); + fabsf(i_this->mDemoCamCenterTarget.x - i_this->mDemoCamCenter.x); i_this->field_0x1288.y = - std::fabsf(i_this->mDemoCamCenterTarget.y - i_this->mDemoCamCenter.y); + fabsf(i_this->mDemoCamCenterTarget.y - i_this->mDemoCamCenter.y); i_this->field_0x1288.z = - std::fabsf(i_this->mDemoCamCenterTarget.z - i_this->mDemoCamCenter.z); + fabsf(i_this->mDemoCamCenterTarget.z - i_this->mDemoCamCenter.z); } cam_3d_morf(i_this, 0.1f); @@ -2042,18 +2042,18 @@ static void demo_camera(b_bq_class* i_this) { i_this->mDemoCamEyeTarget.set(953.0f, 997.0f, -36.0f); i_this->field_0x127c.x = - std::fabsf(i_this->mDemoCamEyeTarget.x - i_this->mDemoCamEye.x); + fabsf(i_this->mDemoCamEyeTarget.x - i_this->mDemoCamEye.x); i_this->field_0x127c.y = - std::fabsf(i_this->mDemoCamEyeTarget.y - i_this->mDemoCamEye.y); + fabsf(i_this->mDemoCamEyeTarget.y - i_this->mDemoCamEye.y); i_this->field_0x127c.z = - std::fabsf(i_this->mDemoCamEyeTarget.z - i_this->mDemoCamEye.z); + fabsf(i_this->mDemoCamEyeTarget.z - i_this->mDemoCamEye.z); i_this->field_0x1288.x = - std::fabsf(i_this->mDemoCamCenterTarget.x - i_this->mDemoCamCenter.x); + fabsf(i_this->mDemoCamCenterTarget.x - i_this->mDemoCamCenter.x); i_this->field_0x1288.y = - std::fabsf(i_this->mDemoCamCenterTarget.y - i_this->mDemoCamCenter.y); + fabsf(i_this->mDemoCamCenterTarget.y - i_this->mDemoCamCenter.y); i_this->field_0x1288.z = - std::fabsf(i_this->mDemoCamCenterTarget.z - i_this->mDemoCamCenter.z); + fabsf(i_this->mDemoCamCenterTarget.z - i_this->mDemoCamCenter.z); cXyz pos(0.0f, 0.0f, 0.0f); for (int i = 0; i < 5; i++) { diff --git a/src/d/actor/d_a_b_ob.cpp b/src/d/actor/d_a_b_ob.cpp index e697b180ac..5622375fec 100644 --- a/src/d/actor/d_a_b_ob.cpp +++ b/src/d/actor/d_a_b_ob.cpp @@ -2462,12 +2462,12 @@ static void demo_camera(b_ob_class* i_this) { i_this->mDemoCamCenterTarget.set(80.0f, -24093.0f, 160.0f); i_this->mDemoCamEyeTarget.set(-447.0f, -22850.0f, -718.0f); - i_this->field_0x5cb4 = std::fabsf(i_this->mDemoCamEyeTarget.x - i_this->mDemoCamEye.x); - i_this->field_0x5cb8 = std::fabsf(i_this->mDemoCamEyeTarget.y - i_this->mDemoCamEye.y); - i_this->field_0x5cbc = std::fabsf(i_this->mDemoCamEyeTarget.z - i_this->mDemoCamEye.z); - i_this->field_0x5cc0 = std::fabsf(i_this->mDemoCamCenterTarget.x - i_this->mDemoCamCenter.x); - i_this->field_0x5cc4 = std::fabsf(i_this->mDemoCamCenterTarget.y - i_this->mDemoCamCenter.y); - i_this->field_0x5cc8 = std::fabsf(i_this->mDemoCamCenterTarget.z - i_this->mDemoCamCenter.z); + i_this->field_0x5cb4 = fabsf(i_this->mDemoCamEyeTarget.x - i_this->mDemoCamEye.x); + i_this->field_0x5cb8 = fabsf(i_this->mDemoCamEyeTarget.y - i_this->mDemoCamEye.y); + i_this->field_0x5cbc = fabsf(i_this->mDemoCamEyeTarget.z - i_this->mDemoCamEye.z); + i_this->field_0x5cc0 = fabsf(i_this->mDemoCamCenterTarget.x - i_this->mDemoCamCenter.x); + i_this->field_0x5cc4 = fabsf(i_this->mDemoCamCenterTarget.y - i_this->mDemoCamCenter.y); + i_this->field_0x5cc8 = fabsf(i_this->mDemoCamCenterTarget.z - i_this->mDemoCamCenter.z); i_this->field_0x5cd0 = 0.0f; daPy_getPlayerActorClass()->changeDemoMode(0x17, 0, 0, 0); @@ -2590,12 +2590,12 @@ static void demo_camera(b_ob_class* i_this) { i_this->mDemoCamCenterTarget.set(-6378.0f, -21886.0f, 7150.0f); i_this->mDemoCamEyeTarget.set(-6961.0f, -21727.0f, 7278.0f); - i_this->field_0x5cb4 = std::fabsf(i_this->mDemoCamEyeTarget.x - i_this->mDemoCamEye.x); - i_this->field_0x5cb8 = std::fabsf(i_this->mDemoCamEyeTarget.y - i_this->mDemoCamEye.y); - i_this->field_0x5cbc = std::fabsf(i_this->mDemoCamEyeTarget.z - i_this->mDemoCamEye.z); - i_this->field_0x5cc0 = std::fabsf(i_this->mDemoCamCenterTarget.x - i_this->mDemoCamCenter.x); - i_this->field_0x5cc4 = std::fabsf(i_this->mDemoCamCenterTarget.y - i_this->mDemoCamCenter.y); - i_this->field_0x5cc8 = std::fabsf(i_this->mDemoCamCenterTarget.z - i_this->mDemoCamCenter.z); + i_this->field_0x5cb4 = fabsf(i_this->mDemoCamEyeTarget.x - i_this->mDemoCamEye.x); + i_this->field_0x5cb8 = fabsf(i_this->mDemoCamEyeTarget.y - i_this->mDemoCamEye.y); + i_this->field_0x5cbc = fabsf(i_this->mDemoCamEyeTarget.z - i_this->mDemoCamEye.z); + i_this->field_0x5cc0 = fabsf(i_this->mDemoCamCenterTarget.x - i_this->mDemoCamCenter.x); + i_this->field_0x5cc4 = fabsf(i_this->mDemoCamCenterTarget.y - i_this->mDemoCamCenter.y); + i_this->field_0x5cc8 = fabsf(i_this->mDemoCamCenterTarget.z - i_this->mDemoCamCenter.z); i_this->field_0x5cd0 = 0.0f; i_this->mDemoAction = 46; @@ -2656,12 +2656,12 @@ static void demo_camera(b_ob_class* i_this) { i_this->mDemoCamCenterTarget.set(-2933.0f, -22626.0f, 6829.0f); i_this->mDemoCamEyeTarget.set(-3295.0f, -22459.0f, 7307.0f); - i_this->field_0x5cb4 = std::fabsf(i_this->mDemoCamEyeTarget.x - i_this->mDemoCamEye.x); - i_this->field_0x5cb8 = std::fabsf(i_this->mDemoCamEyeTarget.y - i_this->mDemoCamEye.y); - i_this->field_0x5cbc = std::fabsf(i_this->mDemoCamEyeTarget.z - i_this->mDemoCamEye.z); - i_this->field_0x5cc0 = std::fabsf(i_this->mDemoCamCenterTarget.x - i_this->mDemoCamCenter.x); - i_this->field_0x5cc4 = std::fabsf(i_this->mDemoCamCenterTarget.y - i_this->mDemoCamCenter.y); - i_this->field_0x5cc8 = std::fabsf(i_this->mDemoCamCenterTarget.z - i_this->mDemoCamCenter.z); + i_this->field_0x5cb4 = fabsf(i_this->mDemoCamEyeTarget.x - i_this->mDemoCamEye.x); + i_this->field_0x5cb8 = fabsf(i_this->mDemoCamEyeTarget.y - i_this->mDemoCamEye.y); + i_this->field_0x5cbc = fabsf(i_this->mDemoCamEyeTarget.z - i_this->mDemoCamEye.z); + i_this->field_0x5cc0 = fabsf(i_this->mDemoCamCenterTarget.x - i_this->mDemoCamCenter.x); + i_this->field_0x5cc4 = fabsf(i_this->mDemoCamCenterTarget.y - i_this->mDemoCamCenter.y); + i_this->field_0x5cc8 = fabsf(i_this->mDemoCamCenterTarget.z - i_this->mDemoCamCenter.z); i_this->field_0x5cd0 = 0.0f; i_this->mDemoAction = 48; diff --git a/src/d/actor/d_a_balloon_2D.cpp b/src/d/actor/d_a_balloon_2D.cpp index d23a64965a..957e7df281 100644 --- a/src/d/actor/d_a_balloon_2D.cpp +++ b/src/d/actor/d_a_balloon_2D.cpp @@ -304,7 +304,11 @@ void daBalloon2D_c::addScoreCount(cXyz* param_1, u32 param_2, u8 param_3) { field_0x5f8[current].field_0xf = field_0x5f8[prev].field_0xf; } cXyz acStack_2c; + #if TARGET_PC + mDoLib_project(param_1, &acStack_2c, { 0, 0, FB_WIDTH, FB_HEIGHT }); + #else mDoLib_project(param_1, &acStack_2c); + #endif field_0x5f8[0].field_0x0.set(acStack_2c); field_0x5f8[0].field_0xc = param_2; field_0x5f8[0].field_0xe = 60; diff --git a/src/d/actor/d_a_bg_obj.cpp b/src/d/actor/d_a_bg_obj.cpp index 4c7fb4d03e..7d4adb9e47 100644 --- a/src/d/actor/d_a_bg_obj.cpp +++ b/src/d/actor/d_a_bg_obj.cpp @@ -976,7 +976,7 @@ void daBgObj_c::setSe() { temp++; for (; i != 0; i--) { - fopAcM_seStart(this, *temp, 0); + fopAcM_seStart(this, *(BE(u32)*)temp, 0); temp++; } } diff --git a/src/d/actor/d_a_coach_2D.cpp b/src/d/actor/d_a_coach_2D.cpp index 7c53aa1f10..eab333cb8b 100644 --- a/src/d/actor/d_a_coach_2D.cpp +++ b/src/d/actor/d_a_coach_2D.cpp @@ -14,6 +14,8 @@ #include "JSystem/J2DGraph/J2DAnmLoader.h" #include +#include "dusk/memory.h" + class daCoach2D_HIO_c : public mDoHIO_entry_c { public: struct Param { @@ -153,7 +155,7 @@ int daCoach2D_c::createHeap() { int daCoach2D_c::create() { int phase_state = dComIfG_resLoad(this, l_arcName); if (phase_state == cPhs_COMPLEATE_e) { - if (!fopAcM_entrySolidHeap(this, daCoach2D_createHeap, 0x5050)) { + if (!fopAcM_entrySolidHeap(this, daCoach2D_createHeap, HEAP_SIZE(0x5050, 0x6000))) { return cPhs_ERROR_e; } diff --git a/src/d/actor/d_a_demo00.cpp b/src/d/actor/d_a_demo00.cpp index c0e3da3121..871e9ebca6 100644 --- a/src/d/actor/d_a_demo00.cpp +++ b/src/d/actor/d_a_demo00.cpp @@ -1096,8 +1096,14 @@ inline int daDemo00_c::execute() { case 2: { u16 sp0A = sp0E & 0x3FFF; if ((sp0E & 0xC000) == 0) { +#if !MOVIE_SUPPORT + // If movie support isn't available, automatically reset. + // TPHD-esque. Maybe not the best solution, but it works. + dComIfGp_event_reset(); +#else fopAcM_create(fpcNm_MOVIE_PLAYER_e, sp0A, NULL, fopAcM_GetRoomNo(this), NULL, NULL, 0xFF); mDoGph_gInf_c::fadeOut(1.0f); +#endif } else { switch (sp0A) { case 0: @@ -1652,7 +1658,12 @@ int daDemo00_c::draw() { MTXCopy(mModel.field_0x5d4->getAnmMtx(0), mDoMtx_stack_c::get()); spb0.set(0.0f, 0.0f, 0.0f); mDoMtx_stack_c::multVec(&spb0, &sp98); + + #if TARGET_PC + mDoLib_project(&sp98, &spa4, {0, 0, FB_WIDTH, FB_HEIGHT}); + #else mDoLib_project(&sp98, &spa4); + #endif if (spa4.x >= -700.0f && spa4.x < 1600.0f && spa4.y >= -200.0f && spa4.y < 600.0f) { if (mModel.mID.field_0x18 == 0 || mModel.mID.field_0x18 == 1) { diff --git a/src/d/actor/d_a_e_fk.cpp b/src/d/actor/d_a_e_fk.cpp index 5840df0495..87734da262 100644 --- a/src/d/actor/d_a_e_fk.cpp +++ b/src/d/actor/d_a_e_fk.cpp @@ -429,7 +429,13 @@ void daE_FK_c::DamageAction() { bool daE_FK_c::checkViewArea() { Vec proj; + + #if TARGET_PC + mDoLib_project(¤t.pos, &proj, {0, 0, FB_WIDTH, FB_HEIGHT}); + #else mDoLib_project(¤t.pos, &proj); + #endif + return (proj.x >= 0.0f && proj.x <= FB_WIDTH) && (proj.y >= 0.0f && proj.y <= FB_HEIGHT); } diff --git a/src/d/actor/d_a_e_fs.cpp b/src/d/actor/d_a_e_fs.cpp index 3ed859c686..54dd10ad81 100644 --- a/src/d/actor/d_a_e_fs.cpp +++ b/src/d/actor/d_a_e_fs.cpp @@ -463,7 +463,13 @@ static void damage_check(e_fs_class* i_this) { static bool checkViewArea(cXyz* i_pos) { Vec proj; + + #if TARGET_PC + mDoLib_project(i_pos, &proj, {0, 0, FB_WIDTH, FB_HEIGHT}); + #else mDoLib_project(i_pos, &proj); + #endif + bool ret = false; if (proj.x >= 0.0f && proj.x <= FB_WIDTH && proj.y >= 0.0f && proj.y <= FB_HEIGHT) { ret = true; diff --git a/src/d/actor/d_a_e_fz.cpp b/src/d/actor/d_a_e_fz.cpp index 6fa54a0ffe..a48c4df8f0 100644 --- a/src/d/actor/d_a_e_fz.cpp +++ b/src/d/actor/d_a_e_fz.cpp @@ -3,16 +3,17 @@ * @brief Enemy - Mini Freezard */ -#include "d/dolzel_rel.h" // IWYU pragma: keep +#include "d/dolzel_rel.h" // IWYU pragma: keep -#include "d/actor/d_a_e_fz.h" -#include "f_op/f_op_actor_enemy.h" -#include "d/actor/d_a_mirror.h" -#include "d/actor/d_a_b_yo.h" -#include "d/d_com_inf_game.h" -#include "d/d_item.h" #include "SSystem/SComponent/c_math.h" #include "SSystem/SComponent/c_xyz.h" +#include "d/actor/d_a_b_yo.h" +#include "d/actor/d_a_e_fz.h" +#include "d/actor/d_a_mirror.h" +#include "d/d_com_inf_game.h" +#include "d/d_item.h" +#include "f_op/f_op_actor_enemy.h" + class daE_FZ_HIO_c { public: @@ -42,26 +43,26 @@ namespace { static dCcD_SrcSph cc_fz_src = { { - {0x0, {{0x100, 0x1, 0x0}, {0xd0fbfdff, 0x43}, 0x65}}, // mObj - {dCcD_SE_METAL, 0x0, 0x0, 0x0, 0x0}, // mGObjAt - {dCcD_SE_NONE, 0x0, 0x0, 0x0, 0x6}, // mGObjTg - {0x0}, // mGObjCo - }, // mObjInf + {0x0, {{0x100, 0x1, 0x0}, {0xd0fbfdff, 0x43}, 0x65}}, // mObj + {dCcD_SE_METAL, 0x0, 0x0, 0x0, 0x0}, // mGObjAt + {dCcD_SE_NONE, 0x0, 0x0, 0x0, 0x6}, // mGObjTg + {0x0}, // mGObjCo + }, // mObjInf { - {{0.0f, 0.0f, 0.0f}, 40.0f} // mSph - } // mSphAttr + {{0.0f, 0.0f, 0.0f}, 40.0f} // mSph + } // mSphAttr }; static dCcD_SrcSph cc_fz_at_src = { { - {0x0, {{0x100, 0x1, 0x1d}, {0x0, 0x0}, 0x0}}, // mObj - {dCcD_SE_METAL, 0x0, 0x0, 0x0, 0x0}, // mGObjAt - {dCcD_SE_NONE, 0x0, 0x0, 0x0, 0x2}, // mGObjTg - {0x0}, // mGObjCo - }, // mObjInf + {0x0, {{0x100, 0x1, 0x1d}, {0x0, 0x0}, 0x0}}, // mObj + {dCcD_SE_METAL, 0x0, 0x0, 0x0, 0x0}, // mGObjAt + {dCcD_SE_NONE, 0x0, 0x0, 0x0, 0x2}, // mGObjTg + {0x0}, // mGObjCo + }, // mObjInf { - {{0.0f, 0.0f, 0.0f}, 40.0f} // mSph - } // mSphAttr + {{0.0f, 0.0f, 0.0f}, 40.0f} // mSph + } // mSphAttr }; } // namespace @@ -84,7 +85,7 @@ daE_FZ_HIO_c::daE_FZ_HIO_c() { } s32 daE_FZ_c::draw() { - if (field_0x714 == 2 && !checkItemGet(dItemNo_IRONBALL_e,1)) { + if (field_0x714 == 2 && !checkItemGet(dItemNo_IRONBALL_e, 1)) { return 1; } @@ -100,13 +101,13 @@ s32 daE_FZ_c::draw() { pos.set(current.pos.x, current.pos.y + 10.0f, current.pos.z); field_0x70c = dComIfGd_setShadow(field_0x70c, 1, model, &pos, 300.0f, 0.0f, current.pos.y, - mObjAcch.GetGroundH(), mObjAcch.m_gnd, &tevStr, - 0, 1.0f, &dDlst_shadowControl_c::mSimpleTexObj); + mObjAcch.GetGroundH(), mObjAcch.m_gnd, &tevStr, 0, 1.0f, + &dDlst_shadowControl_c::mSimpleTexObj); return 1; } -static void daE_FZ_Draw(daE_FZ_c* i_this) { - i_this->draw(); +static int daE_FZ_Draw(daE_FZ_c* i_this) { + return i_this->draw(); } void daE_FZ_c::setActionMode(int i_actionMode, int i_actionPhase) { @@ -136,7 +137,7 @@ void daE_FZ_c::mBoundSoundset() { if (speed < 1) speed = 1; - mCreature.startCreatureSound(Z2SE_EN_FZ_BOUND,speed,-1); + mCreature.startCreatureSound(Z2SE_EN_FZ_BOUND, speed, -1); } void daE_FZ_c::deadnextSet(bool param_0) { @@ -150,7 +151,7 @@ void daE_FZ_c::deadnextSet(bool param_0) { } mTgCoSph.ClrTgHit(); - fopAcM_OffStatus(this,0); + fopAcM_OffStatus(this, 0); attention_info.flags &= ~fopAc_AttnFlag_BATTLE_e; mAtSph.OffAtSetBit(); @@ -160,7 +161,7 @@ void daE_FZ_c::deadnextSet(bool param_0) { speedF = 0.0f; field_0x6fc = 0; - setActionMode(ACT_DAMAGE,0); + setActionMode(ACT_DAMAGE, 0); } static u8 data_806C1BA0; @@ -168,178 +169,186 @@ static u8 data_806C1BA0; static daE_FZ_HIO_c l_HIO; void daE_FZ_c::damage_check() { - csXyz s_pos; - cXyz pos; - cXyz pos2; - cXyz pos3; + csXyz s_pos; + cXyz pos; + cXyz pos2; + cXyz pos3; - if (1 < health) { - scale.set(l_HIO.field_0x0c, l_HIO.field_0x0c, l_HIO.field_0x0c); - setMidnaBindEffect(this, &mCreature, ¤t.pos, &scale); + if (1 < health) { + scale.set(l_HIO.field_0x0c, l_HIO.field_0x0c, l_HIO.field_0x0c); + setMidnaBindEffect(this, &mCreature, ¤t.pos, &scale); - if (field_0x712 == 0) { - pos.set(dComIfGp_getPlayer(0)->current.pos); - mStts.Move(); + if (field_0x712 == 0) { + pos.set(dComIfGp_getPlayer(0)->current.pos); + mStts.Move(); - if (field_0x714 == 3) { - if (mTgCoSph.ChkTgHit()) { - mAtInfo.mpCollider = mTgCoSph.GetTgHitObj(); + if (field_0x714 == 3) { + if (mTgCoSph.ChkTgHit()) { + mAtInfo.mpCollider = mTgCoSph.GetTgHitObj(); - if (mTgCoSph.GetTgHitObj()->ChkAtType(AT_TYPE_IRON_BALL)) { - deadnextSet(false); - } - } - } else { - if (mTgCoSph.ChkTgHit()) { - mAtInfo.mpCollider = mTgCoSph.GetTgHitObj(); - - if (mTgCoSph.GetTgHitObj()->ChkAtType(AT_TYPE_40) || mTgCoSph.GetTgHitObj()->ChkAtType(AT_TYPE_BOOMERANG)) { - current.angle.y = fopAcM_searchPlayerAngleY(this) + 32768; - f32 tmp_l_hio = l_HIO.field_0x28; - speedF = tmp_l_hio; - field_0x6fc = tmp_l_hio; - mBoundSoundset(); - setActionMode(ACT_DAMAGE,1); - return; - } - - pos2 = current.pos - *mTgCoSph.GetTgHitPosP(); - pos3.set(*mTgCoSph.GetTgHitPosP()); - - s_pos.x = 0; - s_pos.y = pos2.atan2sX_Z(); - s_pos.z = 0; - - if (mTgCoSph.GetTgHitObj()->ChkAtType(AT_TYPE_SPINNER) || mTgCoSph.GetTgHitObj()->ChkAtType(AT_TYPE_ARROW)) { - current.angle.y = fopAcM_searchPlayerAngleY(this) + 32768; - f32 tmp_l_hio = l_HIO.field_0x28; - speedF = tmp_l_hio; - field_0x6fc = tmp_l_hio; - mBoundSoundset(); - dComIfGp_setHitMark(2,this,&pos3,&s_pos,0,AT_TYPE_0); - setActionMode(ACT_DAMAGE,1); - return; - } - - cXyz cStack_54(l_HIO.field_0x0c, l_HIO.field_0x0c, l_HIO.field_0x0c); - dComIfGp_particle_set(0x85ba, ¤t.pos, &shape_angle, &cStack_54); - - if (mTgCoSph.GetTgHitObj()->ChkAtType(AT_TYPE_HOOKSHOT)) { - health -= 20; - - if (1 < health) { - current.angle.y = fopAcM_searchPlayerAngleY(this) + 32768; - - f32 tmp_l_hio = l_HIO.field_0x28; - speedF = tmp_l_hio; - field_0x6fc = tmp_l_hio; - mCreature.startCreatureSound(Z2SE_EN_FZ_DAMAGE,0,-1); - - f32 tmp_l_hio2 = l_HIO.field_0x28; - speedF = tmp_l_hio2; - field_0x6fc = tmp_l_hio2; - setActionMode(ACT_DAMAGE,1); - dComIfGp_setHitMark(3,this,&pos3,&s_pos,0,AT_TYPE_0); - return; - } - - deadnextSet(true); - dComIfGp_setHitMark(1,this,&pos3,&s_pos,0,AT_TYPE_0); - return; - } - - if (mTgCoSph.GetTgHitObj()->ChkAtType(AT_TYPE_IRON_BALL)) { - deadnextSet(false); - mTgCoSph.ClrTgHit(); - dComIfGp_setHitMark(3,this,&pos3,&s_pos,0,AT_TYPE_0); - return; - } - - cc_at_check(this,&mAtInfo); - - if (mAtInfo.mHitStatus == 0) { - dComIfGp_setHitMark(1,this,&pos3,&s_pos,0,AT_TYPE_0); - } else { - dComIfGp_setHitMark(3,this,&pos3,&s_pos,0,AT_TYPE_0); - } - - mLastWallHitAngle = mAtInfo.mHitDirection.y; - setReflectAngle(); - current.angle.y += -32768; - field_0x712 = 10; - - if (1 < health) { - mCreature.startCreatureSound(Z2SE_EN_FZ_DAMAGE,0,-1); - f32 tmp_l_hio = l_HIO.field_0x28; - speedF = tmp_l_hio; - field_0x6fc = tmp_l_hio; - setActionMode(ACT_DAMAGE,1); - return; - } - - deadnextSet(true); - return; - } else { - if (mObjAcch.ChkGroundHit() && mTgCoSph.ChkCoHit()) { - fopAc_ac_c* co_hit_actor = mTgCoSph.GetCoHitAc(); - - if (fopAcM_IsActor(co_hit_actor) && fopAcM_GetName(co_hit_actor) == fpcNm_E_FZ_e) { - pos = current.pos - mTgCoSph.GetCoHitAc()->current.pos; - mTgCoSph.ClrCoHit(); - f32 co_hit_actor_speed = co_hit_actor->speedF; - - if (co_hit_actor_speed > l_HIO.field_0x28 * 0.2f || speedF > l_HIO.field_0x28 * 0.2f) { - pos = current.pos - co_hit_actor->current.pos; - mLastWallHitAngle = pos.atan2sX_Z(); - setReflectAngle(); - - f32 tmp2 = speedF; - f32 tmp = co_hit_actor->speedF; - - if (speedF > tmp) { - co_hit_actor->speedF = tmp2; - static_cast(co_hit_actor)->field_0x6fc = tmp2; - } else { - speedF = tmp; - field_0x6fc = tmp; + if (mTgCoSph.GetTgHitObj()->ChkAtType(AT_TYPE_IRON_BALL)) { + deadnextSet(false); + } } - - mBoundSoundset(); - setActionMode(ACT_DAMAGE,5); - return; - } - } - } - - if (mAtSph.ChkAtHit()) { - fopAc_ac_c* player = dComIfGp_getPlayer(0); - fopAc_ac_c* at_hit_actor = mAtSph.GetAtHitAc(); - - current.angle.y = fopAcM_searchPlayerAngleY(this) + 32768; - - if (player != at_hit_actor) { - mAtSph.ClrAtHit(); } else { - if (mAtSph.ChkAtShieldHit()) { - f32 l_hio_28 = l_HIO.field_0x28; - speedF = l_hio_28; - field_0x6fc = l_hio_28; - setActionMode(ACT_DAMAGE,1); + if (mTgCoSph.ChkTgHit()) { + mAtInfo.mpCollider = mTgCoSph.GetTgHitObj(); - } else { - if (mActionMode != ACT_DAMAGE) { - field_0x712 = 10; - setActionMode(ACT_DAMAGE,3); + if (mTgCoSph.GetTgHitObj()->ChkAtType(AT_TYPE_40) || + mTgCoSph.GetTgHitObj()->ChkAtType(AT_TYPE_BOOMERANG)) + { + current.angle.y = fopAcM_searchPlayerAngleY(this) + 32768; + f32 tmp_l_hio = l_HIO.field_0x28; + speedF = tmp_l_hio; + field_0x6fc = tmp_l_hio; + mBoundSoundset(); + setActionMode(ACT_DAMAGE, 1); + return; + } + + pos2 = current.pos - *mTgCoSph.GetTgHitPosP(); + pos3.set(*mTgCoSph.GetTgHitPosP()); + + s_pos.x = 0; + s_pos.y = pos2.atan2sX_Z(); + s_pos.z = 0; + + if (mTgCoSph.GetTgHitObj()->ChkAtType(AT_TYPE_SPINNER) || + mTgCoSph.GetTgHitObj()->ChkAtType(AT_TYPE_ARROW)) + { + current.angle.y = fopAcM_searchPlayerAngleY(this) + 32768; + f32 tmp_l_hio = l_HIO.field_0x28; + speedF = tmp_l_hio; + field_0x6fc = tmp_l_hio; + mBoundSoundset(); + dComIfGp_setHitMark(2, this, &pos3, &s_pos, 0, AT_TYPE_0); + setActionMode(ACT_DAMAGE, 1); + return; + } + + cXyz cStack_54(l_HIO.field_0x0c, l_HIO.field_0x0c, l_HIO.field_0x0c); + dComIfGp_particle_set(0x85ba, ¤t.pos, &shape_angle, &cStack_54); + + if (mTgCoSph.GetTgHitObj()->ChkAtType(AT_TYPE_HOOKSHOT)) { + health -= 20; + + if (1 < health) { + current.angle.y = fopAcM_searchPlayerAngleY(this) + 32768; + + f32 tmp_l_hio = l_HIO.field_0x28; + speedF = tmp_l_hio; + field_0x6fc = tmp_l_hio; + mCreature.startCreatureSound(Z2SE_EN_FZ_DAMAGE, 0, -1); + + f32 tmp_l_hio2 = l_HIO.field_0x28; + speedF = tmp_l_hio2; + field_0x6fc = tmp_l_hio2; + setActionMode(ACT_DAMAGE, 1); + dComIfGp_setHitMark(3, this, &pos3, &s_pos, 0, AT_TYPE_0); + return; + } + + deadnextSet(true); + dComIfGp_setHitMark(1, this, &pos3, &s_pos, 0, AT_TYPE_0); + return; + } + + if (mTgCoSph.GetTgHitObj()->ChkAtType(AT_TYPE_IRON_BALL)) { + deadnextSet(false); + mTgCoSph.ClrTgHit(); + dComIfGp_setHitMark(3, this, &pos3, &s_pos, 0, AT_TYPE_0); + return; + } + + cc_at_check(this, &mAtInfo); + + if (mAtInfo.mHitStatus == 0) { + dComIfGp_setHitMark(1, this, &pos3, &s_pos, 0, AT_TYPE_0); + } else { + dComIfGp_setHitMark(3, this, &pos3, &s_pos, 0, AT_TYPE_0); + } + + mLastWallHitAngle = mAtInfo.mHitDirection.y; + setReflectAngle(); + current.angle.y += -32768; + field_0x712 = 10; + + if (1 < health) { + mCreature.startCreatureSound(Z2SE_EN_FZ_DAMAGE, 0, -1); + f32 tmp_l_hio = l_HIO.field_0x28; + speedF = tmp_l_hio; + field_0x6fc = tmp_l_hio; + setActionMode(ACT_DAMAGE, 1); + return; + } + + deadnextSet(true); + return; + } else { + if (mObjAcch.ChkGroundHit() && mTgCoSph.ChkCoHit()) { + fopAc_ac_c* co_hit_actor = mTgCoSph.GetCoHitAc(); + + if (fopAcM_IsActor(co_hit_actor) && + fopAcM_GetName(co_hit_actor) == fpcNm_E_FZ_e) + { + pos = current.pos - mTgCoSph.GetCoHitAc()->current.pos; + mTgCoSph.ClrCoHit(); + f32 co_hit_actor_speed = co_hit_actor->speedF; + + if (co_hit_actor_speed > l_HIO.field_0x28 * 0.2f || + speedF > l_HIO.field_0x28 * 0.2f) + { + pos = current.pos - co_hit_actor->current.pos; + mLastWallHitAngle = pos.atan2sX_Z(); + setReflectAngle(); + + f32 tmp2 = speedF; + f32 tmp = co_hit_actor->speedF; + + if (speedF > tmp) { + co_hit_actor->speedF = tmp2; + static_cast(co_hit_actor)->field_0x6fc = tmp2; + } else { + speedF = tmp; + field_0x6fc = tmp; + } + + mBoundSoundset(); + setActionMode(ACT_DAMAGE, 5); + return; + } + } + } + + if (mAtSph.ChkAtHit()) { + fopAc_ac_c* player = dComIfGp_getPlayer(0); + fopAc_ac_c* at_hit_actor = mAtSph.GetAtHitAc(); + + current.angle.y = fopAcM_searchPlayerAngleY(this) + 32768; + + if (player != at_hit_actor) { + mAtSph.ClrAtHit(); + } else { + if (mAtSph.ChkAtShieldHit()) { + f32 l_hio_28 = l_HIO.field_0x28; + speedF = l_hio_28; + field_0x6fc = l_hio_28; + setActionMode(ACT_DAMAGE, 1); + + } else { + if (mActionMode != ACT_DAMAGE) { + field_0x712 = 10; + setActionMode(ACT_DAMAGE, 3); + } + } + mBoundSoundset(); + mAtSph.ClrAtHit(); + } + } } - } - mBoundSoundset(); - mAtSph.ClrAtHit(); } - } } - } } - } } bool daE_FZ_c::way_gake_check() { @@ -350,13 +359,13 @@ bool daE_FZ_c::way_gake_check() { return false; } - cMtx_YrotS((MtxP)calc_mtx,current.angle.y); + cMtx_YrotS((MtxP)calc_mtx, current.angle.y); pos.x = 0.0f; pos.y = 300.0f; pos.z = 70.0f; - MtxPosition(&pos,&field_0x6dc); + MtxPosition(&pos, &field_0x6dc); field_0x6dc += current.pos; field_0x6e8.set(field_0x6dc); @@ -374,234 +383,231 @@ bool daE_FZ_c::way_gake_check() { } void daE_FZ_c::executeWait() { - cXyz pos; - cXyz pos2; - s16 angle; - f32 tmp = l_HIO.field_0x14; + cXyz pos; + cXyz pos2; + s16 angle; + f32 tmp = l_HIO.field_0x14; - switch (mActionPhase) { - case 0: - if (fopAcM_wayBgCheck(this,200.0f,50.0f)) { - angle = cM_rndFX(10000.0f) + 32768.0f; - } else { + switch (mActionPhase) { + case 0: + if (fopAcM_wayBgCheck(this, 200.0f, 50.0f)) { + angle = cM_rndFX(10000.0f) + 32768.0f; + } else { + pos2.x = home.pos.x + cM_rndFX(l_HIO.field_0x10); + pos2.y = home.pos.y; + pos2.z = home.pos.z + cM_rndFX(l_HIO.field_0x10); - pos2.x = home.pos.x + cM_rndFX(l_HIO.field_0x10); - pos2.y = home.pos.y; - pos2.z = home.pos.z + cM_rndFX(l_HIO.field_0x10); + pos = pos2 - current.pos; - pos = pos2 - current.pos; + angle = pos.atan2sX_Z() - current.angle.y; - angle = pos.atan2sX_Z() - current.angle.y; - - if (angle > 12288) { - angle = 12288; - } - else { - if (angle < -12288) - angle = -12288; - } - } - - mAngleFromPlayer = current.angle.y + angle; - field_0x710 = l_HIO.field_0x06 + cM_rndFX(l_HIO.field_0x30); - mActionPhase = 1; - case 1: - if (way_gake_check()) { - pos2 = current.pos - home.pos; - angle = pos2.atan2sX_Z(); - mAngleFromPlayer = angle; - current.angle.y = angle; - } - - if (field_0x714 == 4) { - field_0x710 = 10; - speedF = 0.0f; - angle = fopAcM_searchPlayerAngleY(this); - mAngleFromPlayer = angle; - current.angle.y = angle; - tmp = l_HIO.field_0x18; - } - - if (mObjAcch.ChkGroundHit() && dComIfG_Bgsp().GetPolyAtt0(mObjAcch.m_gnd) == 8) { - angle = shape_angle.y - mAngleFromPlayer; - - if (abs(angle) < 512 && field_0x710 == 0) { - cLib_addCalc0(&speedF, 0.1f, 0.1f); + if (angle > 12288) { + angle = 12288; + } else { + if (angle < -12288) + angle = -12288; + } + } + + mAngleFromPlayer = current.angle.y + angle; + field_0x710 = l_HIO.field_0x06 + cM_rndFX(l_HIO.field_0x30); + mActionPhase = 1; + case 1: + if (way_gake_check()) { + pos2 = current.pos - home.pos; + angle = pos2.atan2sX_Z(); + mAngleFromPlayer = angle; + current.angle.y = angle; + } + + if (field_0x714 == 4) { + field_0x710 = 10; + speedF = 0.0f; + angle = fopAcM_searchPlayerAngleY(this); + mAngleFromPlayer = angle; + current.angle.y = angle; + tmp = l_HIO.field_0x18; + } + + if (mObjAcch.ChkGroundHit() && dComIfG_Bgsp().GetPolyAtt0(mObjAcch.m_gnd) == 8) { + angle = shape_angle.y - mAngleFromPlayer; + + if (abs(angle) < 512 && field_0x710 == 0) { + cLib_addCalc0(&speedF, 0.1f, 0.1f); + } + } else { + cLib_addCalc0(&speedF, 0.1f, l_HIO.field_0x2c); + } + + if (field_0x710 == 0 && speedF < 0.2f) { + angle = shape_angle.y - mAngleFromPlayer; + + if (abs(angle) < 512) { + current.angle.y = shape_angle.y; + setActionMode(ACT_MOVE, 0); + } } - } else { - cLib_addCalc0(&speedF,0.1f,l_HIO.field_0x2c); } - if (field_0x710 == 0 && speedF < 0.2f) { - angle = shape_angle.y - mAngleFromPlayer; + cLib_addCalcAngleS2(&shape_angle.y, mAngleFromPlayer, 8, 1280); - if (abs(angle) < 512) { - current.angle.y = shape_angle.y; - setActionMode(ACT_MOVE,0); - } + if (fopAcM_searchPlayerDistance(this) <= tmp && !way_gake_check()) { + if (!fopAcM_otherBgCheck(this, dComIfGp_getPlayer(0))) { + current.angle.y = shape_angle.y; + setActionMode(ACT_ATTACK, 0); + } } - } - - cLib_addCalcAngleS2(&shape_angle.y,mAngleFromPlayer,8,1280); - - if (fopAcM_searchPlayerDistance(this) <= tmp && !way_gake_check()) { - if (!fopAcM_otherBgCheck(this,dComIfGp_getPlayer(0))) { - current.angle.y = shape_angle.y; - setActionMode(ACT_ATTACK,0); - } - } } void daE_FZ_c::executeMove() { switch (mActionPhase) { - case 0: - field_0x710 = l_HIO.field_0x08 + cM_rndFX(l_HIO.field_0x34); - mActionPhase = 1; - case 1: - cLib_addCalcAngleS2(¤t.angle.y,mAngleFromPlayer,8,256); - cLib_addCalc2(&speedF,l_HIO.field_0x1c,1.0f,3.0f); + case 0: + field_0x710 = l_HIO.field_0x08 + cM_rndFX(l_HIO.field_0x34); + mActionPhase = 1; + case 1: + cLib_addCalcAngleS2(¤t.angle.y, mAngleFromPlayer, 8, 256); + cLib_addCalc2(&speedF, l_HIO.field_0x1c, 1.0f, 3.0f); - if (fopAcM_wayBgCheck(this, 200.0f,50.0f) != 0 || field_0x710 == 0) { - setActionMode(ACT_WAIT,0); - } - default: - if (way_gake_check()) { - speedF = 0; - setActionMode(ACT_WAIT,0); - } else { - shape_angle.y = current.angle.y; + if (fopAcM_wayBgCheck(this, 200.0f, 50.0f) != 0 || field_0x710 == 0) { + setActionMode(ACT_WAIT, 0); + } + default: + if (way_gake_check()) { + speedF = 0; + setActionMode(ACT_WAIT, 0); + } else { + shape_angle.y = current.angle.y; - if (fopAcM_searchPlayerDistance(this) <= l_HIO.field_0x14) { - setActionMode(ACT_ATTACK,0); - } + if (fopAcM_searchPlayerDistance(this) <= l_HIO.field_0x14) { + setActionMode(ACT_ATTACK, 0); } + } } } void daE_FZ_c::executeAttack() { switch (mActionPhase) { case 0: - cLib_addCalcAngleS2(¤t.angle.y,fopAcM_searchPlayerAngleY(this),8,0x300); + cLib_addCalcAngleS2(¤t.angle.y, fopAcM_searchPlayerAngleY(this), 8, 0x300); if (way_gake_check() == 0) { - cLib_addCalc2(&speedF,l_HIO.field_0x20,0.7f,1.0f); + cLib_addCalc2(&speedF, l_HIO.field_0x20, 0.7f, 1.0f); } else { speedF = 0.0f; } default: shape_angle.y = current.angle.y; if (!(fopAcM_searchPlayerDistance(this) >= l_HIO.field_0x10)) { - if (fopAcM_otherBgCheck(this,dComIfGp_getPlayer(0)) == 0) { + if (fopAcM_otherBgCheck(this, dComIfGp_getPlayer(0)) == 0) { return; } } } - setActionMode(ACT_WAIT,0); + setActionMode(ACT_WAIT, 0); } void daE_FZ_c::executeDamage() { - cXyz pos; - pos.set(l_HIO.field_0x0c, l_HIO.field_0x0c, l_HIO.field_0x0c); - f32 tmp; + cXyz pos; + pos.set(l_HIO.field_0x0c, l_HIO.field_0x0c, l_HIO.field_0x0c); + f32 tmp; - switch(mActionPhase) { - case 0: - dComIfGp_particle_set(0x85b8,¤t.pos,&shape_angle,&pos); - dComIfGp_particle_set(0x85b9,¤t.pos,&shape_angle,&pos); + switch (mActionPhase) { + case 0: + dComIfGp_particle_set(0x85b8, ¤t.pos, &shape_angle, &pos); + dComIfGp_particle_set(0x85b9, ¤t.pos, &shape_angle, &pos); - if (field_0x714 != 3) { - field_0x564 = 25; - fopAcM_createItemFromEnemyID(field_0x564,¤t.pos,-1,-1,0,0,0,0); - } else { - if (cM_rnd() < 0.2f) { - fopAcM_createItem(¤t.pos,0,-1,-1,0,0,0); - } - } - fopAcM_delete(this); - break; - case 1: - tmp = l_HIO.field_0x28; - speedF = tmp; - field_0x6fc = tmp; - case 5: - mStts.SetWeight(118); - current.angle.y < 0 ? field_0x704 = 0 : field_0x704 = 1; - mActionPhase = 2; - case 2: - if (mObjAcch.ChkGroundHit() && dComIfG_Bgsp().GetPolyAtt0(mObjAcch.m_gnd) == 8) { - tmp = 0.2f; - } else { - tmp = 1.0f; - } + if (field_0x714 != 3) { + field_0x564 = 25; + fopAcM_createItemFromEnemyID(field_0x564, ¤t.pos, -1, -1, 0, 0, 0, 0); + } else { + if (cM_rnd() < 0.2f) { + fopAcM_createItem(¤t.pos, 0, -1, -1, 0, 0, 0); + } + } + fopAcM_delete(this); + break; + case 1: + tmp = l_HIO.field_0x28; + speedF = tmp; + field_0x6fc = tmp; + case 5: + mStts.SetWeight(118); + current.angle.y < 0 ? field_0x704 = 0 : field_0x704 = 1; + mActionPhase = 2; + case 2: + if (mObjAcch.ChkGroundHit() && dComIfG_Bgsp().GetPolyAtt0(mObjAcch.m_gnd) == 8) { + tmp = 0.2f; + } else { + tmp = 1.0f; + } - cLib_addCalc0(&speedF,0.1f,tmp); + cLib_addCalc0(&speedF, 0.1f, tmp); - if (field_0x704 == 0) { - s16 value = 4096.0f - (4096.0f / field_0x6fc) * (field_0x6fc - speedF); - shape_angle.y -= value; - } else { - s16 value = 4096.0f - (4096.0f / field_0x6fc) * (field_0x6fc - speedF); - shape_angle.y += value; - } + if (field_0x704 == 0) { + s16 value = 4096.0f - (4096.0f / field_0x6fc) * (field_0x6fc - speedF); + shape_angle.y -= value; + } else { + s16 value = 4096.0f - (4096.0f / field_0x6fc) * (field_0x6fc - speedF); + shape_angle.y += value; + } - if (mObjAcch.ChkWallHit()) { - mLastWallHitAngle = mAcchCir.GetWallAngleY(); - setReflectAngle(); - mBoundSoundset(); - } + if (mObjAcch.ChkWallHit()) { + mLastWallHitAngle = mAcchCir.GetWallAngleY(); + setReflectAngle(); + mBoundSoundset(); + } - if (speedF < 0.3f) { - current.angle.y = shape_angle.y; - mStts.SetWeight(100); - setActionMode(ACT_WAIT,0); - } - break; - case 3: - mAngleFromPlayer = fopAcM_searchPlayerAngleY(this); - if (current.angle.y < 0) { - field_0x704 = 0; - } - else { - field_0x704 = 1; - } - tmp = l_HIO.field_0x24; - speedF = tmp; - field_0x6fc = tmp; - mActionPhase = 4; - case 4: - if (field_0x704 == 0) { - s16 value = 4096.0f - (4096.0f / field_0x6fc) * (field_0x6fc - speedF); - shape_angle.y -= value; - } - else { - s16 value = 4096.0f - (4096.0f / field_0x6fc) * (field_0x6fc - speedF); - shape_angle.y += value; - } + if (speedF < 0.3f) { + current.angle.y = shape_angle.y; + mStts.SetWeight(100); + setActionMode(ACT_WAIT, 0); + } + break; + case 3: + mAngleFromPlayer = fopAcM_searchPlayerAngleY(this); + if (current.angle.y < 0) { + field_0x704 = 0; + } else { + field_0x704 = 1; + } + tmp = l_HIO.field_0x24; + speedF = tmp; + field_0x6fc = tmp; + mActionPhase = 4; + case 4: + if (field_0x704 == 0) { + s16 value = 4096.0f - (4096.0f / field_0x6fc) * (field_0x6fc - speedF); + shape_angle.y -= value; + } else { + s16 value = 4096.0f - (4096.0f / field_0x6fc) * (field_0x6fc - speedF); + shape_angle.y += value; + } - cLib_addCalcAngleS2(¤t.angle.y,mAngleFromPlayer,1,512); - cLib_addCalc0(&speedF,0.1f,0.1f); + cLib_addCalcAngleS2(¤t.angle.y, mAngleFromPlayer, 1, 512); + cLib_addCalc0(&speedF, 0.1f, 0.1f); - if (mObjAcch.ChkWallHit()) { - mLastWallHitAngle = mAcchCir.GetWallAngleY(); - setReflectAngle(); - mBoundSoundset(); - } + if (mObjAcch.ChkWallHit()) { + mLastWallHitAngle = mAcchCir.GetWallAngleY(); + setReflectAngle(); + mBoundSoundset(); + } - if (speedF < 0.2f) { - current.angle.y = shape_angle.y; - setActionMode(ACT_ATTACK,0); + if (speedF < 0.2f) { + current.angle.y = shape_angle.y; + setActionMode(ACT_ATTACK, 0); + } + break; + case 6: + health = 0; + if (field_0x710 == 1 || mObjAcch.ChkGroundHit()) { + mActionPhase = 0; + } } - break; - case 6: - health = 0; - if (field_0x710 == 1 || mObjAcch.ChkGroundHit()) { - mActionPhase = 0; - } - } } void daE_FZ_c::executeRollMove() { - if (fopAcM_SearchByID(fopAcM_GetLinkId(this),&mpBlizzetaActor) == 0 || !mpBlizzetaActor) return; + if (fopAcM_SearchByID(fopAcM_GetLinkId(this), &mpBlizzetaActor) == 0 || !mpBlizzetaActor) + return; u32 model_no = static_cast(mpBlizzetaActor)->getModelNo(); if (model_no < 4 || 6 < model_no) { @@ -625,10 +631,10 @@ void daE_FZ_c::executeRollMove() { field_0x710 = (20 - field_0x715) * 2; case 1: if (field_0x710 == 0) { - cLib_chaseF(&mRadiusBase,1.0f,0.03f); + cLib_chaseF(&mRadiusBase, 1.0f, 0.03f); } - cLib_chaseAngleS(&field_0x704,1024,16); + cLib_chaseAngleS(&field_0x704, 1024, 16); pos = mpBlizzetaActor->current.pos; pos.x += (f32)(mode_rarius * cM_ssin(roll_angle + field_0x715 * 0xccc)); @@ -639,23 +645,24 @@ void daE_FZ_c::executeRollMove() { if (static_cast(mpBlizzetaActor)->getFrizadAttack() == 3) { mActionPhase = 2; speedF = 60.0f; - current.angle.y = cLib_targetAngleY(&static_cast(mpBlizzetaActor)->current.pos,¤t.pos); + current.angle.y = cLib_targetAngleY( + &static_cast(mpBlizzetaActor)->current.pos, ¤t.pos); } break; case 2: - cLib_chaseF(&mRadiusBase,1.0,0.1); - cLib_chaseAngleS(&field_0x704,512,16); + cLib_chaseF(&mRadiusBase, 1.0, 0.1); + cLib_chaseAngleS(&field_0x704, 512, 16); if (mObjAcch.ChkWallHit() || !mObjAcch.ChkGroundHit()) { - setActionMode(ACT_DAMAGE,0); - mCreature.startCreatureSound(Z2SE_EN_FZ_DEATH,0,-1); + setActionMode(ACT_DAMAGE, 0); + mCreature.startCreatureSound(Z2SE_EN_FZ_DEATH, 0, -1); return; } if (mAtSph.ChkAtHit()) { fopAc_ac_c* at_hit_actor = mAtSph.GetAtHitAc(); if ((fopAcM_GetName(at_hit_actor) == fpcNm_ALINK_e) || mAtSph.ChkAtShieldHit()) { - setActionMode(ACT_DAMAGE,0); + setActionMode(ACT_DAMAGE, 0); return; } } @@ -787,26 +794,26 @@ void daE_FZ_c::action() { } void daE_FZ_c::mtx_set() { - mDoMtx_stack_c::transS(current.pos.x,current.pos.y,current.pos.z); - mDoMtx_stack_c::ZXYrotM(shape_angle); - mDoMtx_stack_c::scaleM(l_HIO.field_0x0c,l_HIO.field_0x0c,l_HIO.field_0x0c); - mDoMtx_stack_c::scaleM(mRadiusBase,mRadiusBase,mRadiusBase); - mpModel->setBaseTRMtx(mDoMtx_stack_c::get()); + mDoMtx_stack_c::transS(current.pos.x, current.pos.y, current.pos.z); + mDoMtx_stack_c::ZXYrotM(shape_angle); + mDoMtx_stack_c::scaleM(l_HIO.field_0x0c, l_HIO.field_0x0c, l_HIO.field_0x0c); + mDoMtx_stack_c::scaleM(mRadiusBase, mRadiusBase, mRadiusBase); + mpModel->setBaseTRMtx(mDoMtx_stack_c::get()); } void daE_FZ_c::cc_set() { cXyz pos; cXyz pos2; - pos.set(0.0f,60.0f,0.0f); - mDoMtx_stack_c::multVec(&pos,&eyePos); + pos.set(0.0f, 60.0f, 0.0f); + mDoMtx_stack_c::multVec(&pos, &eyePos); attention_info.position = eyePos; attention_info.position.y += 25.0f; mDoMtx_stack_c::copy(mpModel->getBaseTRMtx()); - pos.set(0.0f,40.0f,0.0f); - mDoMtx_stack_c::multVec(&pos,&pos2); + pos.set(0.0f, 40.0f, 0.0f); + mDoMtx_stack_c::multVec(&pos, &pos2); mTgCoSph.SetC(pos2); mTgCoSph.SetR(mRadiusBase * 60.0f); @@ -815,8 +822,8 @@ void daE_FZ_c::cc_set() { mDoMtx_stack_c::copy(mpModel->getBaseTRMtx()); - pos.set(0.0f,25.0f,0.0f); - mDoMtx_stack_c::multVec(&pos,&pos2); + pos.set(0.0f, 25.0f, 0.0f); + mDoMtx_stack_c::multVec(&pos, &pos2); mAtSph.SetC(pos2); mAtSph.SetR(mRadiusBase * 40.0f); @@ -826,16 +833,16 @@ void daE_FZ_c::cc_set() { s32 daE_FZ_c::execute() { if (field_0x714 == 2) { - if (checkItemGet(dItemNo_IRONBALL_e,1) == 0) { + if (checkItemGet(dItemNo_IRONBALL_e, 1) == 0) { return 1; } if (attention_info.distances[fopAc_attn_BATTLE_e] == 0) { attention_info.distances[fopAc_attn_BATTLE_e] = 69; - fopAcM_SetGroup(this,2); - #if DEBUG - fopAcM_OnStatus(this,0); - #endif + fopAcM_SetGroup(this, 2); +#if DEBUG + fopAcM_OnStatus(this, 0); +#endif attention_info.flags |= fopAc_AttnFlag_BATTLE_e; } } @@ -849,9 +856,9 @@ s32 daE_FZ_c::execute() { if (field_0x712 != 0) field_0x712 -= 1; - action(); // set current action - mtx_set(); // update model matrix - cc_set(); // update sphere colliders + action(); // set current action + mtx_set(); // update model matrix + cc_set(); // update sphere colliders mCreature.framework(0, dComIfGp_getReverb(fopAcM_GetRoomNo(this))); @@ -875,8 +882,8 @@ s32 daE_FZ_c::execute() { return 1; } -static void daE_FZ_Execute(daE_FZ_c* i_this) { - i_this->execute(); +static int daE_FZ_Execute(daE_FZ_c* i_this) { + return i_this->execute(); } void daE_FZ_c::demoDelete() { @@ -887,12 +894,12 @@ void daE_FZ_c::demoDelete() { fopAcM_delete(this); } -static BOOL daE_FZ_IsDelete(daE_FZ_c* i_this) { - return TRUE; +static int daE_FZ_IsDelete(daE_FZ_c* i_this) { + return 1; } s32 daE_FZ_c::_delete() { - dComIfG_resDelete(&mPhaseReq,"E_FZ"); + dComIfG_resDelete(&mPhaseReq, "E_FZ"); if (field_0xc21 != 0) { data_806C1BA0 = 0; @@ -905,8 +912,8 @@ s32 daE_FZ_c::_delete() { return 1; } -static void daE_FZ_Delete(daE_FZ_c* i_this) { - i_this->_delete(); +static int daE_FZ_Delete(daE_FZ_c* i_this) { + return i_this->_delete(); } s32 daE_FZ_c::CreateHeap() { @@ -921,122 +928,120 @@ s32 daE_FZ_c::CreateHeap() { } static int useHeapInit(fopAc_ac_c* i_this) { - return static_cast(i_this)->CreateHeap(); + return static_cast(i_this)->CreateHeap(); } s32 daE_FZ_c::create() { - fopAcM_ct(this,daE_FZ_c); + fopAcM_ct(this, daE_FZ_c); - s32 phase = dComIfG_resLoad(&mPhaseReq,"E_FZ"); - if (phase == cPhs_COMPLEATE_e) { - if (!fopAcM_entrySolidHeap(this,useHeapInit,6480)) { - return cPhs_ERROR_e; - } - if (data_806C1BA0 == 0) { - data_806C1BA0 = 1; - field_0xc21 = 1; - l_HIO.field_0x04 = -1; + s32 phase = dComIfG_resLoad(&mPhaseReq, "E_FZ"); + if (phase == cPhs_COMPLEATE_e) { + if (!fopAcM_entrySolidHeap(this, useHeapInit, 6480)) { + return cPhs_ERROR_e; + } + if (data_806C1BA0 == 0) { + data_806C1BA0 = 1; + field_0xc21 = 1; + l_HIO.field_0x04 = -1; + } + + attention_info.flags = fopAc_AttnFlag_BATTLE_e; + attention_info.distances[fopAc_attn_BATTLE_e] = 69; + + fopAcM_SetMtx(this, mpModel->getBaseTRMtx()); + fopAcM_SetMin(this, -200.0f, -200.0f, -200.0f); + fopAcM_SetMax(this, 200.0f, 200.0f, 200.0f); + + mStts.Init(100, 0, this); + health = 80; + field_0x560 = 80; + + field_0x714 = fopAcM_GetParam(this); + field_0x715 = fopAcM_GetParam(this) >> 8; + + if (field_0x714 == 255) + field_0x714 = 0; + + if (field_0x714 == 1 || field_0x714 == 3) { + speed.y = cM_rndFX(10.0f) + 30.0f; + f32 rng = cM_rndFX(1.0f); + speedF = rng + 4.0f; + field_0x6fc = rng + 4.0f; + if (field_0x714 == 1) { + fopAcM_OnStatus(this, fopAcStts_UNK_0x4000_e); + } + } + + mObjAcch.Set(fopAcM_GetPosition_p(this), fopAcM_GetOldPosition_p(this), this, 1, &mAcchCir, + fopAcM_GetSpeed_p(this), 0, 0); + + if (field_0x714 == 3) { + mAcchCir.SetWall(35.0f, 70.0f); + } else { + mAcchCir.SetWall(20.0f, 60.0f); + } + + mObjAcch.CrrPos(dComIfG_Bgsp()); + + mTgCoSph.Set(cc_fz_src); + mTgCoSph.SetStts(&mStts); + + mAtSph.Set(cc_fz_at_src); + mAtSph.SetStts(&mStts); + + mCreature.init(¤t.pos, &eyePos, 3, 1); + mCreature.setEnemyName("E_fz"); + + mAtInfo.mpSound = &mCreature; + mAtInfo.mPowerType = 1; + + gravity = -5.0f; + + shape_angle.z = 0; + shape_angle.x = 0; + + s16 random = cM_rndFX(10000.0f); + shape_angle.y = random; + current.angle.y = random; + + field_0x670.set(current.pos); + + for (int i = 0; i < 4; i++) { + field_0x67c[i].set(current.pos); + } + + if (field_0x714 == 2 && !checkItemGet(dItemNo_IRONBALL_e, 1)) { + attention_info.distances[fopAc_attn_BATTLE_e] = 0; + fopAcM_SetGroup(this, 0); + fopAcM_OffStatus(this, 0); + attention_info.flags &= ~fopAc_AttnFlag_BATTLE_e; + } + + if (field_0x714 == 3) { + mRadiusBase = 0.0f; + attention_info.flags &= ~fopAc_AttnFlag_BATTLE_e; + mAtSph.SetAtType(AT_TYPE_CSTATUE_SWING); + mAtSph.SetAtSpl(dCcG_At_Spl_UNK_1); + setActionMode(ACT_ROLLMOVE, 0); + } else { + mAtSph.SetAtMtrl(dCcD_MTRL_ICE); + mRadiusBase = 1.0f; + cM_rnd() < 0.5f ? setActionMode(ACT_WAIT, 0) : setActionMode(ACT_MOVE, 0); + } + + mtx_set(); } - attention_info.flags = fopAc_AttnFlag_BATTLE_e; - attention_info.distances[fopAc_attn_BATTLE_e] = 69; - - fopAcM_SetMtx(this,mpModel->getBaseTRMtx()); - fopAcM_SetMin(this,-200.0f,-200.0f,-200.0f); - fopAcM_SetMax(this,200.0f,200.0f,200.0f); - - mStts.Init(100,0,this); - health = 80; - field_0x560 = 80; - - field_0x714 = fopAcM_GetParam(this); - field_0x715 = fopAcM_GetParam(this) >> 8; - - if (field_0x714 == 255) - field_0x714 = 0; - - if (field_0x714 == 1 || field_0x714 == 3) { - speed.y = cM_rndFX(10.0f) + 30.0f; - f32 rng = cM_rndFX(1.0f); - speedF = rng + 4.0f; - field_0x6fc = rng + 4.0f; - if (field_0x714 == 1) { - fopAcM_OnStatus(this,fopAcStts_UNK_0x4000_e); - } - } - - mObjAcch.Set(fopAcM_GetPosition_p(this),fopAcM_GetOldPosition_p(this), this, 1, &mAcchCir, fopAcM_GetSpeed_p(this), 0, 0); - - if (field_0x714 == 3) { - mAcchCir.SetWall(35.0f,70.0f); - } - else { - mAcchCir.SetWall(20.0f,60.0f); - } - - mObjAcch.CrrPos(dComIfG_Bgsp()); - - mTgCoSph.Set(cc_fz_src); - mTgCoSph.SetStts(&mStts); - - mAtSph.Set(cc_fz_at_src); - mAtSph.SetStts(&mStts); - - mCreature.init(¤t.pos,&eyePos,3,1); - mCreature.setEnemyName("E_fz"); - - mAtInfo.mpSound = &mCreature; - mAtInfo.mPowerType = 1; - - gravity = -5.0f; - - shape_angle.z = 0; - shape_angle.x = 0; - - s16 random = cM_rndFX(10000.0f); - shape_angle.y = random; - current.angle.y = random; - - field_0x670.set(current.pos); - - for (int i = 0; i < 4; i++) { - field_0x67c[i].set(current.pos); - } - - if (field_0x714 == 2 && !checkItemGet(dItemNo_IRONBALL_e,1)) { - attention_info.distances[fopAc_attn_BATTLE_e] = 0; - fopAcM_SetGroup(this,0); - fopAcM_OffStatus(this,0); - attention_info.flags &= ~fopAc_AttnFlag_BATTLE_e; - } - - if (field_0x714 == 3) { - mRadiusBase = 0.0f; - attention_info.flags &= ~fopAc_AttnFlag_BATTLE_e; - mAtSph.SetAtType(AT_TYPE_CSTATUE_SWING); - mAtSph.SetAtSpl(dCcG_At_Spl_UNK_1); - setActionMode(ACT_ROLLMOVE,0); - } else { - mAtSph.SetAtMtrl(dCcD_MTRL_ICE); - mRadiusBase = 1.0f; - cM_rnd() < 0.5f ? setActionMode(ACT_WAIT,0) : setActionMode(ACT_MOVE,0); - } - - mtx_set(); - } - - return phase; + return phase; } -static void daE_FZ_Create(daE_FZ_c* i_this) { - i_this->create(); +static int daE_FZ_Create(daE_FZ_c* i_this) { + return i_this->create(); } static actor_method_class l_daE_FZ_Method = { - (process_method_func)daE_FZ_Create, - (process_method_func)daE_FZ_Delete, - (process_method_func)daE_FZ_Execute, - (process_method_func)daE_FZ_IsDelete, + (process_method_func)daE_FZ_Create, (process_method_func)daE_FZ_Delete, + (process_method_func)daE_FZ_Execute, (process_method_func)daE_FZ_IsDelete, (process_method_func)daE_FZ_Draw, }; diff --git a/src/d/actor/d_a_e_oc.cpp b/src/d/actor/d_a_e_oc.cpp index 01f282b0ea..6f0a55f12a 100644 --- a/src/d/actor/d_a_e_oc.cpp +++ b/src/d/actor/d_a_e_oc.cpp @@ -189,8 +189,8 @@ int daE_OC_c::draw() { return 1; } -static void daE_OC_Draw(daE_OC_c* i_this) { - i_this->draw(); +static int daE_OC_Draw(daE_OC_c* i_this) { + return i_this->draw(); } daE_OC_c* E_OC_n::m_battle_oc; @@ -2639,12 +2639,12 @@ int daE_OC_c::execute() { return 1; } -static void daE_OC_Execute(daE_OC_c* i_this) { - i_this->execute(); +static int daE_OC_Execute(daE_OC_c* i_this) { + return i_this->execute(); } -static BOOL daE_OC_IsDelete(daE_OC_c* param_0) { - return TRUE; +static int daE_OC_IsDelete(daE_OC_c* param_0) { + return 1; } int daE_OC_c::_delete() { @@ -2662,9 +2662,9 @@ int daE_OC_c::_delete() { return 1; } -static void daE_OC_Delete(daE_OC_c* i_this) { +static int daE_OC_Delete(daE_OC_c* i_this) { fopAcM_RegisterDeleteID(i_this, "E_OC"); - i_this->_delete(); + return i_this->_delete(); } int daE_OC_c::CreateHeap() { @@ -2833,8 +2833,8 @@ cPhs_Step daE_OC_c::create() { return phase; } -static void daE_OC_Create(daE_OC_c* i_this) { - i_this->create(); +static int daE_OC_Create(daE_OC_c* i_this) { + return i_this->create(); } static actor_method_class l_daE_OC_Method = { diff --git a/src/d/actor/d_a_e_ph.cpp b/src/d/actor/d_a_e_ph.cpp index dc20cb2361..3213c2716e 100644 --- a/src/d/actor/d_a_e_ph.cpp +++ b/src/d/actor/d_a_e_ph.cpp @@ -1154,6 +1154,18 @@ int daE_PH_c::create() { int phase_state = dComIfG_resLoad(&mPhase, "E_PH"); if (phase_state == cPhs_COMPLEATE_e) { + +#if TARGET_PC + // Due to our loads being so much faster, peahats can initialize *before* the camera. + // This breaks the peahat used for camera focus during transition to phase 2 of Argorok. + // as it caches incorrect camera parameters in its init. + if (auto cam = dComIfGp_getCamera(0)) { + if (cam->phase_request.mpHandlerTable != nullptr) { + return cPhs_INIT_e; + } + } +#endif + mAction = fopAcM_GetParam(this) & 0xF; if (dComIfGs_isZoneSwitch(2, fopAcM_GetRoomNo(this)) && mAction == 4) { diff --git a/src/d/actor/d_a_e_sm.cpp b/src/d/actor/d_a_e_sm.cpp index b85e22e640..8894399cec 100644 --- a/src/d/actor/d_a_e_sm.cpp +++ b/src/d/actor/d_a_e_sm.cpp @@ -1362,7 +1362,13 @@ void daE_SM_c::E_SM_C_Hook() { bool daE_SM_c::CheckViewArea() { Vec vec; + + #if TARGET_PC + mDoLib_project(¤t.pos, &vec, {0, 0, FB_WIDTH, FB_HEIGHT}); + #else mDoLib_project(¤t.pos, &vec); + #endif + bool rv = false; if (vec.x >= 0.0f && vec.x <= FB_WIDTH && vec.y >= 0.0f && vec.y <= FB_HEIGHT) { diff --git a/src/d/actor/d_a_e_ws.cpp b/src/d/actor/d_a_e_ws.cpp index 2be149e917..bb5835776f 100644 --- a/src/d/actor/d_a_e_ws.cpp +++ b/src/d/actor/d_a_e_ws.cpp @@ -10,6 +10,10 @@ #include #include "f_op/f_op_actor_enemy.h" +#define PLAYER_NOT_FOUND 0 +#define PLAYER_TARGET 1 +#define PLAYER_NEAR 2 + class daE_WS_HIO_c : public JORReflexible { public: daE_WS_HIO_c(); @@ -28,6 +32,7 @@ public: /* 0x24 */ u8 debug_ON; }; + namespace { static dCcD_SrcSph cc_ws_src = { { @@ -66,13 +71,27 @@ daE_WS_HIO_c::daE_WS_HIO_c() { attack_speed = 10.0f; } +#if DEBUG +void daE_WS_HIO_c::genMessage(JORMContext* ctx) { + ctx->genLabel("スタルウォーーーーーーーール", 0x80000001); + ctx->genSlider("基本サイズ", &base_size, 0.0f, 5.0f); + ctx->genSlider("サーチ角度", &search_angle, 0.0f, 30000.0f); + ctx->genSlider("攻撃速度", &attack_speed, 0.0f, 100.0f); + ctx->genSlider("移動範囲", &move_range, 0.0f, 1000.0f); + ctx->genSlider("サーチ範囲", &search_range, 0.0f, 1000.0f); + ctx->genSlider("サーチY上下範囲", &search_y_range, 0.0f, 1000.0f); + ctx->genSlider("地面までの距離", &dist_to_ground, 0.0f, 1000.0f); + ctx->genCheckBox("デバック表示", &debug_ON, 0x1); +} +#endif + int daE_WS_c::draw() { - J3DModel* model_p = mpModelMorf->getModel(); + J3DModel* model = mAnm_p->getModel(); g_env_light.settingTevStruct(0, ¤t.pos, &tevStr); - g_env_light.setLightTevColorType_MAJI(model_p, &tevStr); + g_env_light.setLightTevColorType_MAJI(model, &tevStr); if (mDownColor) { - J3DModelData* modelData_p = model_p->getModelData(); + J3DModelData* modelData_p = model->getModelData(); for (u16 i = 0; i < modelData_p->getMaterialNum(); i++) { J3DMaterial* material_p = modelData_p->getMaterialNodePointer(i); material_p->getTevColor(0)->r = mDownColor; @@ -81,48 +100,48 @@ int daE_WS_c::draw() { } } - mpModelMorf->entryDL(); + mAnm_p->entryDL(); cXyz sp8; sp8.set(current.pos.x, 100.0f + current.pos.y, current.pos.z); - mShadowId = dComIfGd_setShadow(mShadowId, 1, model_p, &sp8, 400.0f, 0.0f, current.pos.y, mAcch.GetGroundH(), mAcch.m_gnd, &tevStr, 0, 1.0f, dDlst_shadowControl_c::getSimpleTex()); + mShadowId = dComIfGd_setShadow(mShadowId, 1, model, &sp8, 400.0f, 0.0f, current.pos.y, mAcch.GetGroundH(), mAcch.m_gnd, &tevStr, 0, 1.0f, dDlst_shadowControl_c::getSimpleTex()); return 1; } -static int daE_WS_Draw(daE_WS_c* a_this) { - return a_this->draw(); +static int daE_WS_Draw(daE_WS_c* i_this) { + return i_this->draw(); } void daE_WS_c::setBck(int i_anm, u8 i_mode, f32 i_morf, f32 i_speed) { - mpModelMorf->setAnm((J3DAnmTransform*)dComIfG_getObjectRes("E_WS", i_anm), i_mode, i_morf, i_speed, 0.0f, -1.0f); + mAnm_p->setAnm((J3DAnmTransform*)dComIfG_getObjectRes("E_WS", i_anm), i_mode, i_morf, i_speed, 0.0f, -1.0f); } void daE_WS_c::setFootSound() { - if (mpModelMorf->getAnm() == dComIfG_getObjectRes("E_WS", 7)) { - if (mpModelMorf->checkFrame(0.0f) || - mpModelMorf->checkFrame(4.5f) || - mpModelMorf->checkFrame(7.5f) || - mpModelMorf->checkFrame(9.0f) || - mpModelMorf->checkFrame(13.5f) || - mpModelMorf->checkFrame(16.0f) || - mpModelMorf->checkFrame(19.0f) || - mpModelMorf->checkFrame(23.5f) || - mpModelMorf->checkFrame(25.0f) || - mpModelMorf->checkFrame(28.0f) || - mpModelMorf->checkFrame(32.5f) || - mpModelMorf->checkFrame(36.0f) || - mpModelMorf->checkFrame(39.5f)) + if (mAnm_p->getAnm() == dComIfG_getObjectRes("E_WS", 7)) { + if (mAnm_p->checkFrame(0.0f) || + mAnm_p->checkFrame(4.5f) || + mAnm_p->checkFrame(7.5f) || + mAnm_p->checkFrame(9.0f) || + mAnm_p->checkFrame(13.5f) || + mAnm_p->checkFrame(16.0f) || + mAnm_p->checkFrame(19.0f) || + mAnm_p->checkFrame(23.5f) || + mAnm_p->checkFrame(25.0f) || + mAnm_p->checkFrame(28.0f) || + mAnm_p->checkFrame(32.5f) || + mAnm_p->checkFrame(36.0f) || + mAnm_p->checkFrame(39.5f)) { mSound.startCreatureSound(Z2SE_EN_WS_FOOTNOTE, 0, -1); } - } else if (mpModelMorf->getAnm() == dComIfG_getObjectRes("E_WS", 8)) { - if (mpModelMorf->checkFrame(0.5f) || - mpModelMorf->checkFrame(6.0f) || - mpModelMorf->checkFrame(11.0f) || - mpModelMorf->checkFrame(16.0f) || - mpModelMorf->checkFrame(21.0f) || - mpModelMorf->checkFrame(26.5f) || - mpModelMorf->checkFrame(31.0f)) + } else if (mAnm_p->getAnm() == dComIfG_getObjectRes("E_WS", 8)) { + if (mAnm_p->checkFrame(0.5f) || + mAnm_p->checkFrame(6.0f) || + mAnm_p->checkFrame(11.0f) || + mAnm_p->checkFrame(16.0f) || + mAnm_p->checkFrame(21.0f) || + mAnm_p->checkFrame(26.5f) || + mAnm_p->checkFrame(31.0f)) { mSound.startCreatureSound(Z2SE_EN_WS_FOOTNOTE, 0, -1); } @@ -141,13 +160,13 @@ f32 daE_WS_c::calcTargetDist(cXyz i_basePos, cXyz i_targetPos) { } s16 daE_WS_c::calcTargetAngle(cXyz i_basePos, cXyz i_targetPos) { - cXyz sp1C; - cXyz sp10 = i_targetPos - i_basePos; + cXyz mae; + cXyz ato = i_targetPos - i_basePos; - mDoMtx_stack_c::XrotS(-field_0x668.x); - mDoMtx_stack_c::YrotM(-field_0x668.y); - mDoMtx_stack_c::multVec(&sp10, &sp1C); - return cM_atan2s(sp1C.x, sp1C.z); + mDoMtx_stack_c::XrotS(-mTargetWallAngle.x); + mDoMtx_stack_c::YrotM(-mTargetWallAngle.y); + mDoMtx_stack_c::multVec(&ato, &mae); + return cM_atan2s(mae.x, mae.z); } static u8 hio_set; @@ -171,13 +190,13 @@ int daE_WS_c::checkPlayerPos() { dComIfGp_checkPlayerStatus1(0, 0x2000000) || dComIfGp_checkPlayerStatus1(0, 0x10000) || calcTargetDist(current.pos, player_pos) < 150.0f) && - checkInSearchRange(player_pos, field_0x65c) && checkInSearchRange(current.pos, field_0x65c)) + checkInSearchRange(player_pos, mHomePos) && checkInSearchRange(current.pos, mHomePos)) { dBgS_GndChk gndchk; cXyz gndpos; mDoMtx_stack_c::transS(current.pos); - mDoMtx_stack_c::ZXYrotM(field_0x66e); + mDoMtx_stack_c::ZXYrotM(mWallAngle); mDoMtx_stack_c::ZXYrotM(shape_angle); mDoMtx_stack_c::transM(0.0f, 100.0f, 0.0f); mDoMtx_stack_c::multVecZero(&gndpos); @@ -187,17 +206,17 @@ int daE_WS_c::checkPlayerPos() { if (current.pos.y - gndpos.y > l_HIO.dist_to_ground) { // Return 1 if walltula is looking towards player if (cLib_distanceAngleS(shape_angle.y, calcTargetAngle(current.pos, player_pos)) < l_HIO.search_angle) { - return 1; + return PLAYER_TARGET; } // otherwise return 2 if player is near the walltula if (calcTargetDist(current.pos, player_pos) < 150.0f) { - return 2; + return PLAYER_NEAR; } } } - return 0; + return PLAYER_NOT_FOUND; } bool daE_WS_c::checkAttackEnd() { @@ -205,17 +224,17 @@ bool daE_WS_c::checkAttackEnd() { mDoMtx_stack_c::copy(daPy_getLinkPlayerActorClass()->getModelJointMtx(0)); mDoMtx_stack_c::multVecZero(&player_pos); - BOOL r30 = false; + BOOL checkPlayerNear = FALSE; if ( daPy_getPlayerActorClass()->checkClimbMove() || dComIfGp_checkPlayerStatus1(0, 0x02000000) || dComIfGp_checkPlayerStatus1(0, 0x10000) || calcTargetDist(current.pos, player_pos) < 200.0f ) { - r30 = true; + checkPlayerNear = TRUE; } - if (!r30 || - !checkInSearchRange(current.pos, field_0x65c) || + if (!checkPlayerNear || + !checkInSearchRange(current.pos, mHomePos) || checkBeforeBg(shape_angle.y) ) { @@ -228,41 +247,41 @@ bool daE_WS_c::checkAttackEnd() { } void daE_WS_c::executeWait() { - int temp_r3 = checkPlayerPos(); - if (temp_r3 == 1) { + int playerCheck = checkPlayerPos(); + if (playerCheck == PLAYER_TARGET) { setActionMode(ACTION_ATTACK_e); return; } - if (temp_r3 == 2 && mMode != 3 && mMode != 4) { + if (playerCheck == PLAYER_NEAR && mMode != 3 && mMode != 4) { mMode = 2; } switch (mMode) { case 0: - mMoveWaitTimer = 50.0f + cM_rndF(50.0f); + mWaitTimer = 50.0f + cM_rndF(50.0f); setBck(9, 2, 3.0f, 1.0f); mMode = 1; /* fallthrough */ case 1: - if (mMoveWaitTimer == 0) { + if (mWaitTimer == 0) { mMode = 2; } break; case 2: speedF = 0.0f; - field_0x690 = 0; - mTargetAngle = shape_angle.y + cM_rndFX(32768.0f); + mIsReturnHome = 0; + mTargetAngle = shape_angle.y + cM_rndFX(32768.0f); // random turn up to ±180° - if (temp_r3 == 2) { - mTargetStep = 0x200; + if (playerCheck == PLAYER_NEAR) { + mStepAngle = 0x200; setBck(8, 2, 3.0f, 2.4f); } else { - if (calcTargetDist(current.pos, field_0x65c) >= l_HIO.move_range) { - mTargetAngle = calcTargetAngle(current.pos, field_0x65c); - field_0x690 = 1; + if (calcTargetDist(current.pos, mHomePos) >= l_HIO.move_range) { + mTargetAngle = calcTargetAngle(current.pos, mHomePos); + mIsReturnHome = 1; } - mTargetStep = 0x100; + mStepAngle = 0x100; setBck(8, 2, 3.0f, 1.2f); } @@ -271,37 +290,37 @@ void daE_WS_c::executeWait() { case 3: setFootSound(); - if (cLib_chaseAngleS(&shape_angle.y, mTargetAngle, mTargetStep)) { + if (cLib_chaseAngleS(&shape_angle.y, mTargetAngle, mStepAngle)) { mMode = 4; - mMoveWaitTimer = 10; + mWaitTimer = 10; setBck(9, 2, 3.0f, 1.0f); } break; case 4: - if (mMoveWaitTimer == 0) { + if (mWaitTimer == 0) { mMode = 5; } break; case 5: mMode = 6; speedF = 3.0f; - mMoveWaitTimer = 20.0f + cM_rndF(10.0f); + mWaitTimer = 20.0f + cM_rndF(10.0f); setBck(7, 2, 3.0f, 1.0f); /* fallthrough */ case 6: setFootSound(); - if (field_0x690 == 0) { - if (calcTargetDist(current.pos, field_0x65c) >= l_HIO.move_range) { - mMoveWaitTimer = 0; + if (mIsReturnHome == 0) { + if (calcTargetDist(current.pos, mHomePos) >= l_HIO.move_range) { + mWaitTimer = 0; } } if (checkBeforeBg(shape_angle.y)) { - mMoveWaitTimer = 0; + mWaitTimer = 0; } - if (mMoveWaitTimer == 0) { + if (mWaitTimer == 0) { speedF = 0.0f; mMode = 0; } @@ -333,11 +352,11 @@ void daE_WS_c::executeAttack() { mMode = 2; setBck(10, 2, 3.0f, 1.0f); mSound.startCreatureVoice(Z2SE_EN_WS_V_YOKOKU, -1); - mMoveWaitTimer = 10; + mWaitTimer = 10; } break; case 2: - if (mMoveWaitTimer == 0) { + if (mWaitTimer == 0) { speedF = l_HIO.attack_speed * mBodyScale; setBck(7, 2, 3.0f, 3.0f); mMode = 3; @@ -352,20 +371,20 @@ void daE_WS_c::executeAttack() { setFootSound(); cLib_chaseAngleS(&shape_angle.y, calcTargetAngle(current.pos, player_pos), 0x400); - BOOL r28 = false; + BOOL checkAttackStart = FALSE; if (checkBeforeBg(shape_angle.y)) { - r28 = true; + checkAttackStart = TRUE; } if (mCcSph.ChkAtHit()) { - cCcD_Obj* r27 = mCcSph.GetAtHitObj(); - if (fopAcM_GetName(dCc_GetAc(r27->GetAc())) == fpcNm_ALINK_e) { - r28 = true; + cCcD_Obj* hitObj = mCcSph.GetAtHitObj(); + if (fopAcM_GetName(dCc_GetAc(hitObj->GetAc())) == fpcNm_ALINK_e) { + checkAttackStart = TRUE; } } - if (!checkInSearchRange(current.pos, field_0x65c)) { - r28 = true; + if (!checkInSearchRange(current.pos, mHomePos)) { + checkAttackStart = TRUE; } - if (r28) { + if (checkAttackStart) { mMode = 4; speedF = 0.0f; setBck(4, 0, 3.0f, 1.0f); @@ -378,11 +397,11 @@ void daE_WS_c::executeAttack() { break; } case 4: - if (mpModelMorf->checkFrame(7.5f)) { + if (mAnm_p->checkFrame(7.5f)) { mSound.startCreatureVoice(Z2SE_EN_WS_V_ATTACK, -1); } - if (mpModelMorf->isStop()) { + if (mAnm_p->isStop()) { setActionMode(ACTION_WAIT_e); } /* fallthrough */ @@ -408,9 +427,9 @@ void daE_WS_c::executeDown() { mSound.startCreatureVoice(Z2SE_EN_WS_V_DAMAGE, -1); /* fallthrough */ case 1: - if (mpModelMorf->isStop()) { - mAcchCir.SetWall(0.0f, 4.0f); - current.angle.y = field_0x668.y; + if (mAnm_p->isStop()) { + mBgc.SetWall(0.0f, 4.0f); + current.angle.y = mTargetWallAngle.y; setBck(6, 0, 3.0f, 0.0f); mSound.startCreatureVoice(Z2SE_EN_WS_V_DEATH, -1); speedF = 5.0f; @@ -433,7 +452,7 @@ void daE_WS_c::executeDown() { speedF = 3.0f + cM_rndF(2.0f); speed.y = 12.0f; mMode = 3; - mMoveWaitTimer = 30; + mWaitTimer = 30; setBck(6, 0, 5.0f, 1.0f); mSound.startCreatureSound(Z2SE_CM_BODYFALL_S, 0, -1); } @@ -467,8 +486,8 @@ void daE_WS_c::executeDown() { case 4: cLib_addCalc2(&mDownColor, -20.0f, 1.0f, 0.4f); - if (mpModelMorf->isStop()) { - mMoveWaitTimer = 15; + if (mAnm_p->isStop()) { + mWaitTimer = 15; mMode = 5; return; } @@ -476,12 +495,12 @@ void daE_WS_c::executeDown() { case 5: cLib_addCalc2(&mDownColor, -20.0f, 1.0f, 0.4f); - if (mMoveWaitTimer == 0) { + if (mWaitTimer == 0) { fopAcM_delete(this); fopAcM_createDisappear(this, ¤t.pos, 7, 0, 7); - if (mSwbit != 0xFF && !dComIfGs_isSwitch(mSwbit, fopAcM_GetRoomNo(this))) { - dComIfGs_onSwitch(mSwbit, fopAcM_GetRoomNo(this)); + if (bitSw != 0xFF && !dComIfGs_isSwitch(bitSw, fopAcM_GetRoomNo(this))) { + dComIfGs_onSwitch(bitSw, fopAcM_GetRoomNo(this)); } } break; @@ -497,36 +516,36 @@ void daE_WS_c::executeWindDown() { mCcSph.OffTgSetBit(); mCcBokkuriSph.OffTgSetBit(); - mAcchCir.SetWall(0.0f, 4.0f); + mBgc.SetWall(0.0f, 4.0f); mMode = 1; setBck(7, 2, 3.0f, 1.0f); mSound.startCreatureVoice(Z2SE_EN_WS_V_DAMAGE, -1); - mMoveWaitTimer = 5; + mWaitTimer = 5; mAcch.SetGroundUpY(20.0f); attention_info.flags = 0; speed.y = 0.0f; speedF = 5.0f; - current.angle.y = field_0x668.y; - mTargetStep = -0x800; + current.angle.y = mTargetWallAngle.y; + mStepAngle = -0x800; break; case 1: - shape_angle.y += mTargetStep; - cLib_chaseAngleS(&field_0x66e.y, 0, 0x400); - cLib_chaseAngleS(&field_0x66e.x, 0, 0x400); + shape_angle.y += mStepAngle; + cLib_chaseAngleS(&mWallAngle.y, 0, 0x400); + cLib_chaseAngleS(&mWallAngle.x, 0, 0x400); shape_angle.x += 0x800; shape_angle.z += 0x800; speed.y = 30.0f; - if (mMoveWaitTimer == 0) { + if (mWaitTimer == 0) { mMode = 2; gravity = -3.0f; } break; case 2: - shape_angle.y += mTargetStep; - cLib_chaseAngleS(&field_0x66e.y, 0, 0x400); - cLib_chaseAngleS(&field_0x66e.x, 0, 0x400); + shape_angle.y += mStepAngle; + cLib_chaseAngleS(&mWallAngle.y, 0, 0x400); + cLib_chaseAngleS(&mWallAngle.x, 0, 0x400); cLib_chaseAngleS(&shape_angle.x, -0x8000, 0x400); cLib_chaseAngleS(&shape_angle.z, 0, 0x400); @@ -534,15 +553,15 @@ void daE_WS_c::executeWindDown() { speedF = 3.0f + cM_rndF(2.0f); speed.y = 12.0f; mMode = 3; - mMoveWaitTimer = 30; + mWaitTimer = 30; setBck(6, 0, 5.0f, 1.0f); mSound.startCreatureVoice(Z2SE_EN_WS_V_DEATH, -1); mSound.startCreatureSound(Z2SE_CM_BODYFALL_S, 0, -1); } break; case 3: - shape_angle.y += mTargetStep; - cLib_chaseAngleS(&mTargetStep, 0, 0x80); + shape_angle.y += mStepAngle; + cLib_chaseAngleS(&mStepAngle, 0, 0x80); cLib_chaseAngleS(&shape_angle.x, -0x8000, 0x400); cLib_chaseAngleS(&shape_angle.z, 0, 0x400); @@ -556,23 +575,23 @@ void daE_WS_c::executeWindDown() { break; case 4: cLib_addCalc2(&mDownColor, -20.0f, 1.0f, 0.4f); - shape_angle.y += mTargetStep; - cLib_chaseAngleS(&mTargetStep, 0, 0x80); - shape_angle.y += mTargetStep; + shape_angle.y += mStepAngle; + cLib_chaseAngleS(&mStepAngle, 0, 0x80); + shape_angle.y += mStepAngle; - if (mpModelMorf->isStop()) { - mMoveWaitTimer = 15; + if (mAnm_p->isStop()) { + mWaitTimer = 15; mMode = 5; } break; case 5: cLib_addCalc2(&mDownColor, -20.0f, 1.0f, 0.4f); - if (mMoveWaitTimer == 0) { + if (mWaitTimer == 0) { fopAcM_delete(this); fopAcM_createDisappear(this, ¤t.pos, 7, 0, 7); - if (mSwbit != 0xFF && !dComIfGs_isSwitch(mSwbit, fopAcM_GetRoomNo(this))) { - dComIfGs_onSwitch(mSwbit, fopAcM_GetRoomNo(this)); + if (bitSw != 0xFF && !dComIfGs_isSwitch(bitSw, fopAcM_GetRoomNo(this))) { + dComIfGs_onSwitch(bitSw, fopAcM_GetRoomNo(this)); } } break; @@ -653,47 +672,47 @@ void daE_WS_c::action() { mSound.setLinkSearch(field_0x566); if (mAction != ACTION_DOWN_e && mAction != ACTION_WIND_DOWN_e) { - cXyz sp14; - mDoMtx_stack_c::YrotS(field_0x668.y); - mDoMtx_stack_c::XrotM(field_0x668.x); + cXyz ato; + mDoMtx_stack_c::YrotS(mTargetWallAngle.y); + mDoMtx_stack_c::XrotM(mTargetWallAngle.x); mDoMtx_stack_c::YrotM(current.angle.y); - cXyz sp8(0.0f, 0.0f, speedF); - mDoMtx_stack_c::multVec(&sp8, &sp14); - speed = sp14; + cXyz mae(0.0f, 0.0f, speedF); + mDoMtx_stack_c::multVec(&mae, &ato); + speed = ato; current.pos += speed; } else { fopAcM_posMoveF(this, NULL); } mAcch.CrrPos(dComIfG_Bgsp()); - mpModelMorf->play(0, dComIfGp_getReverb(fopAcM_GetRoomNo(this))); + mAnm_p->play(0, dComIfGp_getReverb(fopAcM_GetRoomNo(this))); } void daE_WS_c::mtx_set() { mDoMtx_stack_c::transS(current.pos); - mDoMtx_stack_c::ZXYrotM(field_0x66e); + mDoMtx_stack_c::ZXYrotM(mWallAngle); mDoMtx_stack_c::ZXYrotM(shape_angle); mDoMtx_stack_c::scaleM(mBodyScale, mBodyScale, mBodyScale); - J3DModel* model_p = mpModelMorf->getModel(); + J3DModel* model_p = mAnm_p->getModel(); model_p->setBaseTRMtx(mDoMtx_stack_c::get()); - mpModelMorf->modelCalc(); + mAnm_p->modelCalc(); } void daE_WS_c::cc_set() { cXyz mae; cXyz ato; - J3DModel* model_p = mpModelMorf->getModel(); + J3DModel* model = mAnm_p->getModel(); - mDoMtx_stack_c::YrotS(field_0x668.y); - mDoMtx_stack_c::XrotM(field_0x668.x); + mDoMtx_stack_c::YrotS(mTargetWallAngle.y); + mDoMtx_stack_c::XrotM(mTargetWallAngle.x); mae.set(0.0f, 15.0f + nREG_F(10), 0.0f); mDoMtx_stack_c::multVec(&mae, &ato); attention_info.position = current.pos + ato; attention_info.position.y += 90.0f * mBodyScale; - MTXCopy(model_p->getAnmMtx(1), mDoMtx_stack_c::get()); + MTXCopy(model->getAnmMtx(1), mDoMtx_stack_c::get()); mae.set(-15.0f + nREG_F(5), -10.0f + nREG_F(6), nREG_F(7)); mDoMtx_stack_c::multVec(&mae, &eyePos); @@ -707,8 +726,8 @@ void daE_WS_c::cc_set() { } int daE_WS_c::execute() { - if (mMoveWaitTimer != 0) { - mMoveWaitTimer--; + if (mWaitTimer != 0) { + mWaitTimer--; } if (mInvulnerabilityTimer != 0) { @@ -725,8 +744,8 @@ int daE_WS_c::execute() { return 1; } -static int daE_WS_Execute(daE_WS_c* a_this) { - return a_this->execute(); +static int daE_WS_Execute(daE_WS_c* i_this) { + return i_this->execute(); } void daE_WS_c::checkInitialWall() { @@ -739,7 +758,7 @@ void daE_WS_c::checkInitialWall() { linchk.Set(¤t.pos, &endpos, NULL); if (dComIfG_Bgsp().LineCross(&linchk)) { - if (field_0x691 == 0 && dComIfG_Bgsp().GetWallCode(linchk) != 1 && dComIfG_Bgsp().GetWallCode(linchk) != 4) { + if (arg0 == 0 && dComIfG_Bgsp().GetWallCode(linchk) != 1 && dComIfG_Bgsp().GetWallCode(linchk) != 4) { return; } @@ -749,9 +768,9 @@ void daE_WS_c::checkInitialWall() { dComIfG_Bgsp().GetTriPla(linchk, &tri); cXyz* tri_np = tri.GetNP(); - field_0x668.y = cM_atan2s(tri_np->x, tri_np->z); - field_0x668.x = cM_atan2s(tri_np->absXZ(), tri_np->y); - field_0x66e = field_0x668; + mTargetWallAngle.y = cM_atan2s(tri_np->x, tri_np->z); + mTargetWallAngle.x = cM_atan2s(tri_np->absXZ(), tri_np->y); + mWallAngle = mTargetWallAngle; return; } } @@ -759,8 +778,8 @@ void daE_WS_c::checkInitialWall() { bool daE_WS_c::checkBeforeBg(s16 i_angle) { dBgS_LinChk linchk; - cXyz sp68; - cXyz sp5C; + cXyz mae; + cXyz ato; cXyz endpos; cXyz startpos; @@ -768,56 +787,56 @@ bool daE_WS_c::checkBeforeBg(s16 i_angle) { return false; } - mDoMtx_stack_c::YrotS(field_0x668.y); - mDoMtx_stack_c::XrotM(field_0x668.x); + mDoMtx_stack_c::YrotS(mTargetWallAngle.y); + mDoMtx_stack_c::XrotM(mTargetWallAngle.x); mDoMtx_stack_c::YrotM(i_angle); - sp68.set(0.0f, 50.0f * mBodyScale, 0.0f); - mDoMtx_stack_c::multVec(&sp68, &startpos); + mae.set(0.0f, 50.0f * mBodyScale, 0.0f); + mDoMtx_stack_c::multVec(&mae, &startpos); startpos += current.pos; - mDoMtx_stack_c::YrotS(field_0x668.y); - mDoMtx_stack_c::XrotM(field_0x668.x); + mDoMtx_stack_c::YrotS(mTargetWallAngle.y); + mDoMtx_stack_c::XrotM(mTargetWallAngle.x); mDoMtx_stack_c::YrotM(i_angle); - sp68.set(0.0f, 0.0f, 50.0f * mBodyScale); - mDoMtx_stack_c::multVec(&sp68, &sp5C); + mae.set(0.0f, 0.0f, 50.0f * mBodyScale); + mDoMtx_stack_c::multVec(&mae, &ato); - sp68.set(sp5C.x, 0.0f, sp5C.z); - endpos = startpos + sp68; + mae.set(ato.x, 0.0f, ato.z); + endpos = startpos + mae; linchk.Set(&startpos, &endpos, NULL); if (dComIfG_Bgsp().LineCross(&linchk)) { return 1; } - if (sp5C.y > 0.0f) { - sp68.set(0.0f, 50.0f * mBodyScale, 0.0f); + if (ato.y > 0.0f) { + mae.set(0.0f, 50.0f * mBodyScale, 0.0f); } else { - sp68.set(0.0f, -l_HIO.dist_to_ground, 0.0f); + mae.set(0.0f, -l_HIO.dist_to_ground, 0.0f); } - endpos = startpos + sp68; + endpos = startpos + mae; linchk.Set(&startpos, &endpos, NULL); if (dComIfG_Bgsp().LineCross(&linchk)) { return true; } - mDoMtx_stack_c::YrotS(field_0x668.y); - mDoMtx_stack_c::XrotM(field_0x668.x); + mDoMtx_stack_c::YrotS(mTargetWallAngle.y); + mDoMtx_stack_c::XrotM(mTargetWallAngle.x); mDoMtx_stack_c::YrotM(i_angle); - sp68.set(0.0f, 50.0f * mBodyScale, 100.0f * mBodyScale); - mDoMtx_stack_c::multVec(&sp68, &sp5C); - startpos = current.pos + sp5C; + mae.set(0.0f, 50.0f * mBodyScale, 100.0f * mBodyScale); + mDoMtx_stack_c::multVec(&mae, &ato); + startpos = current.pos + ato; cXyz sp38(0.0f, -40.0f * mBodyScale, 100.0f * mBodyScale); - mDoMtx_stack_c::multVec(&sp38, &sp5C); - endpos = current.pos + sp5C; + mDoMtx_stack_c::multVec(&sp38, &ato); + endpos = current.pos + ato; linchk.Set(&startpos, &endpos, NULL); if (!dComIfG_Bgsp().LineCross(&linchk)) { return true; } - if (field_0x691 == 0 && dComIfG_Bgsp().GetWallCode(linchk) != 1 && dComIfG_Bgsp().GetWallCode(linchk) != 4) { + if (arg0 == 0 && dComIfG_Bgsp().GetWallCode(linchk) != 1 && dComIfG_Bgsp().GetWallCode(linchk) != 4) { return true; } @@ -825,7 +844,7 @@ bool daE_WS_c::checkBeforeBg(s16 i_angle) { dComIfG_Bgsp().GetTriPla(linchk, &tri); cXyz* tri_np = tri.GetNP(); - cLib_chaseAngleS(&field_0x66e.y, cM_atan2s(tri_np->x, tri_np->z), 0x100); + cLib_chaseAngleS(&mWallAngle.y, cM_atan2s(tri_np->x, tri_np->z), 0x100); checkWall(); return false; } @@ -834,7 +853,7 @@ bool daE_WS_c::checkWall() { cXyz startpos; cXyz endpos; mDoMtx_stack_c::transS(current.pos); - mDoMtx_stack_c::ZXYrotM(field_0x66e); + mDoMtx_stack_c::ZXYrotM(mWallAngle); mDoMtx_stack_c::ZXYrotM(shape_angle); mDoMtx_stack_c::transM(0.0f, 100.0f, 0.0f); @@ -846,7 +865,7 @@ bool daE_WS_c::checkWall() { dBgS_LinChk linchk; linchk.Set(&startpos, &endpos, NULL); if (dComIfG_Bgsp().LineCross(&linchk)) { - if (field_0x691 == 0 && dComIfG_Bgsp().GetWallCode(linchk) != 1 && dComIfG_Bgsp().GetWallCode(linchk) != 4) { + if (arg0 == 0 && dComIfG_Bgsp().GetWallCode(linchk) != 1 && dComIfG_Bgsp().GetWallCode(linchk) != 4) { return false; } @@ -856,8 +875,8 @@ bool daE_WS_c::checkWall() { dComIfG_Bgsp().GetTriPla(linchk, &tri); cXyz* tri_np = tri.GetNP(); - field_0x668.y = cM_atan2s(tri_np->x, tri_np->z); - field_0x668.x = cM_atan2s(tri_np->absXZ(), tri_np->y); + mTargetWallAngle.y = cM_atan2s(tri_np->x, tri_np->z); + mTargetWallAngle.x = cM_atan2s(tri_np->absXZ(), tri_np->y); return true; } @@ -871,8 +890,8 @@ static int daE_WS_IsDelete(daE_WS_c* a_this) { int daE_WS_c::_delete() { dComIfG_resDelete(&mPhase, "E_WS"); - if (mHIOInit) { - hio_set = false; + if (mHioSet) { + hio_set = FALSE; mDoHIO_DELETE_CHILD(l_HIO.id); } @@ -883,24 +902,25 @@ int daE_WS_c::_delete() { return 1; } -static int daE_WS_Delete(daE_WS_c* a_this) { - return a_this->_delete(); +static int daE_WS_Delete(daE_WS_c* i_this) { + fopAcM_RegisterDeleteID(i_this, "E_WS"); + return i_this->_delete(); } int daE_WS_c::CreateHeap() { J3DModelData* modelData = (J3DModelData*)dComIfG_getObjectRes("E_WS", 0xD); JUT_ASSERT(1401, modelData != NULL); - mpModelMorf = JKR_NEW mDoExt_McaMorfSO(modelData, NULL, NULL, (J3DAnmTransform*)dComIfG_getObjectRes("E_WS", 7), 0, 1.0f, 0, -1, &mSound, 0x80000, 0x11000084); - if (mpModelMorf == NULL || mpModelMorf->getModel() == NULL) { + mAnm_p = JKR_NEW mDoExt_McaMorfSO(modelData, NULL, NULL, (J3DAnmTransform*)dComIfG_getObjectRes("E_WS", 7), 0, 1.0f, 0, -1, &mSound, 0x80000, 0x11000084); + if (mAnm_p == NULL || mAnm_p->getModel() == NULL) { return 0; } return 1; } -static int useHeapInit(fopAc_ac_c* i_this) { - return ((daE_WS_c*)i_this)->CreateHeap(); +static int useHeapInit(fopAc_ac_c* actor) { + return ((daE_WS_c*)actor)->CreateHeap(); } int daE_WS_c::create() { @@ -910,8 +930,8 @@ int daE_WS_c::create() { if (phase_state == cPhs_COMPLEATE_e) { OS_REPORT("E_WS PARAM %x\n", fopAcM_GetParam(this)); - mSwbit = (fopAcM_GetParam(this) & 0xFF00) >> 8; - if (mSwbit != 0xFF && dComIfGs_isSwitch(mSwbit, fopAcM_GetRoomNo(this))) { + bitSw = (fopAcM_GetParam(this) & 0xFF00) >> 8; + if (bitSw != 0xFF && dComIfGs_isSwitch(bitSw, fopAcM_GetRoomNo(this))) { OS_REPORT("E_WS やられ後なので再セットしません\n"); return cPhs_ERROR_e; } @@ -922,13 +942,13 @@ int daE_WS_c::create() { if (!hio_set) { hio_set = true; - mHIOInit = true; + mHioSet = true; l_HIO.id = mDoHIO_CREATE_CHILD("スタルウォール", &l_HIO); } - field_0x691 = fopAcM_GetParam(this); - if (field_0x691 == 0xFF) { - field_0x691 = 0; + arg0 = fopAcM_GetParam(this); + if (arg0 == 0xFF) { + arg0 = 0; } if (((fopAcM_GetParam(this) & 0xFF0000) >> 0x10) == 1) { @@ -938,12 +958,12 @@ int daE_WS_c::create() { } attention_info.flags = fopAc_AttnFlag_BATTLE_e; - fopAcM_SetMtx(this, mpModelMorf->getModel()->getBaseTRMtx()); + fopAcM_SetMtx(this, mAnm_p->getModel()->getBaseTRMtx()); fopAcM_SetMin(this, -200.0f, -200.0f, -200.0f); fopAcM_SetMax(this, 200.0f, 200.0f, 200.0f); - mAcch.Set(fopAcM_GetPosition_p(this), fopAcM_GetOldPosition_p(this), this, 1, &mAcchCir, fopAcM_GetSpeed_p(this), NULL, NULL); - mAcchCir.SetWall(0.0f, 0.0f); + mAcch.Set(fopAcM_GetPosition_p(this), fopAcM_GetOldPosition_p(this), this, 1, &mBgc, fopAcM_GetSpeed_p(this), NULL, NULL); + mBgc.SetWall(0.0f, 0.0f); health = 10; field_0x560 = 10; @@ -963,7 +983,7 @@ int daE_WS_c::create() { setActionMode(ACTION_WAIT_e); checkInitialWall(); - field_0x65c = current.pos; + mHomePos = current.pos; speed.y = 0.0f; gravity = 0.0f; mtx_set(); @@ -972,8 +992,8 @@ int daE_WS_c::create() { return phase_state; } -static int daE_WS_Create(daE_WS_c* a_this) { - return a_this->create(); +static int daE_WS_Create(daE_WS_c* i_this) { + return i_this->create(); } static actor_method_class l_daE_WS_Method = { diff --git a/src/d/actor/d_a_e_ym.cpp b/src/d/actor/d_a_e_ym.cpp index a5544b4041..758bec6269 100644 --- a/src/d/actor/d_a_e_ym.cpp +++ b/src/d/actor/d_a_e_ym.cpp @@ -16,6 +16,8 @@ #include "f_op/f_op_camera_mng.h" #include +#include "dusk/settings.h" + class daE_YM_HIO_c: public JORReflexible { public: daE_YM_HIO_c(); @@ -1066,7 +1068,11 @@ void daE_YM_c::executeDown() { } if (mAcch.ChkGroundHit()) { if (mFlyType != 1) { + #if TARGET_PC + bckSet(6, 0, 0.0f, dusk::getSettings().game.fastTears && dComIfGp_event_getMode() == 0 ? 2.0f : 1.0f); + #else bckSet(6, 0, 0.0f, 1.0f); + #endif } if (mMode == 1) { mSound.startCreatureSound(Z2SE_EN_YM_LAND, 0, -1); @@ -1086,7 +1092,11 @@ void daE_YM_c::executeDown() { if (current.pos.y < gnd_cross) { mSound.startCreatureSound(Z2SE_CM_BODYFALL_WATER_M, 0, -1); mSound.startCreatureSound(Z2SE_EN_YM_MOGAKU, 0, -1); + #if TARGET_PC + bckSet(6, 0, 0.0f, dusk::getSettings().game.fastTears && dComIfGp_event_getMode() == 0 ? 2.0f : 1.0f); + #else bckSet(6, 0, 0.0f, 1.0f); + #endif speedF = 0.0f; speed.y = gravity = 0.0f; current.pos.y = gnd_cross; @@ -1102,8 +1112,13 @@ void daE_YM_c::executeDown() { f32 gnd_cross_2 = dComIfG_Bgsp().GroundCross(&gnd_chk); if (gnd_cross_2 == -G_CM3D_F_INF || std::abs(gnd_cross_2 - current.pos.y) > 1000.0f || dComIfG_Bgsp().GetGroundCode(gnd_chk) == 4 || dComIfG_Bgsp().GetGroundCode(gnd_chk) == 10 - || dComIfG_Bgsp().GetGroundCode(gnd_chk) == 5) { + || dComIfG_Bgsp().GetGroundCode(gnd_chk) == 5) + { + #if TARGET_PC + bckSet(6, 0, 0.0f, dusk::getSettings().game.fastTears && dComIfGp_event_getMode() == 0 ? 2.0f : 1.0f); + #else bckSet(6, 0, 0.0f, 1.0f); + #endif mMode = 3; speedF = 0.0f; shape_angle.x = -0x8000; diff --git a/src/d/actor/d_a_e_ymb.cpp b/src/d/actor/d_a_e_ymb.cpp index e107b2a8b9..2604b06480 100644 --- a/src/d/actor/d_a_e_ymb.cpp +++ b/src/d/actor/d_a_e_ymb.cpp @@ -516,7 +516,7 @@ void daE_YMB_c::checkWaterPos() { field_0x6cc = wtr_pos; field_0x69c.y = wtr_pos + 1000.0f + l_HIO.fly_height_adjust; - UNUSED(std::fabsf(field_0x6cc - current.pos.y)); + UNUSED(fabsf(field_0x6cc - current.pos.y)); if (current.pos.y < (200.0f + field_0x6cc)) { if (field_0x715 == 0) { setWaterEffect1(); diff --git a/src/d/actor/d_a_e_zs.cpp b/src/d/actor/d_a_e_zs.cpp index 46a1050855..cd57ffdd51 100644 --- a/src/d/actor/d_a_e_zs.cpp +++ b/src/d/actor/d_a_e_zs.cpp @@ -495,8 +495,8 @@ int daE_ZS_c::CreateHeap() { return 1; } -static void useHeapInit(fopAc_ac_c* i_this) { - static_cast(i_this)->CreateHeap(); +static int useHeapInit(fopAc_ac_c* i_this) { + return static_cast(i_this)->CreateHeap(); } int daE_ZS_c::create() { @@ -504,7 +504,7 @@ int daE_ZS_c::create() { int phase = dComIfG_resLoad(&mPhase, "E_ZS"); if (phase == cPhs_COMPLEATE_e) { OS_REPORT("E_ZS PARAM %x\n", fopAcM_GetParam(this)); - if (!fopAcM_entrySolidHeap(this, (heapCallbackFunc)useHeapInit, 0xFC0)) { + if (!fopAcM_entrySolidHeap(this, useHeapInit, 0xFC0)) { return cPhs_ERROR_e; } diff --git a/src/d/actor/d_a_grass.cpp b/src/d/actor/d_a_grass.cpp index 1668386edf..f04d5cfcd2 100644 --- a/src/d/actor/d_a_grass.cpp +++ b/src/d/actor/d_a_grass.cpp @@ -80,12 +80,7 @@ void daGrass_c::deleteGrass() { } } -dGrass_packet_c::~dGrass_packet_c() { -#if TARGET_PC - GXDestroyTexObj(&mTexObj_l_M_kusa05_RGBATEX); - GXDestroyTexObj(&mTexObj_l_M_Hijiki00TEX); -#endif -} +dGrass_packet_c::~dGrass_packet_c() {} void daGrass_c::executeGrass() { if (m_grass != NULL) { diff --git a/src/d/actor/d_a_mant.cpp b/src/d/actor/d_a_mant.cpp index c1c5e4b297..bcd7f05986 100644 --- a/src/d/actor/d_a_mant.cpp +++ b/src/d/actor/d_a_mant.cpp @@ -10,11 +10,21 @@ #include "d/actor/d_a_b_gnd.h" #include "d/d_com_inf_game.h" +#if TARGET_PC +#include "dusk/dvd_asset.hpp" +static u8* l_Egnd_mantTEX_get() { alignas(32) static u8 buf[0x4000]; static bool _ = (dusk::LoadRelAsset(buf, "/rel/Final/Release/d_a_mant.rel", 0x1C00, 0x4000), true); return buf; } +static u8* l_Egnd_mantTEX_U_get() { alignas(32) static u8 buf[0x4000]; static bool _ = (dusk::LoadRelAsset(buf, "/rel/Final/Release/d_a_mant.rel", 0x5C00, 0x4000), true); return buf; } +static u8* l_Egnd_mantPAL_get() { alignas(32) static u8 buf[0x60]; static bool _ = (dusk::LoadRelAsset(buf, "/rel/Final/Release/d_a_mant.rel", 0x9C00, 0x60), true); return buf; } +#define l_Egnd_mantTEX (l_Egnd_mantTEX_get()) +#define l_Egnd_mantTEX_U (l_Egnd_mantTEX_U_get()) +#define l_Egnd_mantPAL (l_Egnd_mantPAL_get()) +#else #include "assets/l_Egnd_mantTEX.h" #include "assets/l_Egnd_mantTEX_U.h" #include "assets/l_Egnd_mantPAL.h" +#endif #include "d/d_s_play.h" static u32 l_pos[507] = { @@ -239,20 +249,32 @@ static u32 l_texCoord[338] = { 0x3F800000, 0x00000000, }; +#if TARGET_PC +static u8* l_Egnd_mantDL_get() { alignas(32) static u8 buf[0x3EC]; static bool _ = (dusk::LoadRelAsset(buf, "/rel/Final/Release/d_a_mant.rel", 0xA9A0, 0x3EC), true); return buf; } +#define l_Egnd_mantDL (l_Egnd_mantDL_get()) +#else #include "assets/l_Egnd_mantDL.h" +#endif +#if !TARGET_PC static void* pal_d = (void*)&l_Egnd_mantPAL; static void* tex_d[2] = { (void*)&l_Egnd_mantTEX, (void*)&l_Egnd_mantTEX_U, }; +#endif static char lbl_277_bss_0; void daMant_packet_c::draw() { +#if TARGET_PC + void* image = l_Egnd_mantTEX; + void* lut = l_Egnd_mantPAL; +#else void* image = tex_d[0]; void* lut = pal_d; +#endif j3dSys.reinitGX(); GXSetNumIndStages(0); @@ -268,9 +290,9 @@ void daMant_packet_c::draw() { GXSetVtxAttrFmt(GX_VTXFMT0, GX_VA_NRM, GX_CLR_RGB, GX_F32, 0); GXSetVtxAttrFmt(GX_VTXFMT0, GX_VA_TEX0, GX_CLR_RGBA, GX_F32, 0); - GXSETARRAY(GX_VA_POS, this->getPos(), sizeof(mPos[0]), 12); - GXSETARRAY(GX_VA_NRM, this->getNrm(), sizeof(mNrm[0]), 12); - GXSETARRAY(GX_VA_TEX0, &l_texCoord, sizeof(l_texCoord), 8); + GXSETARRAY(GX_VA_POS, this->getPos(), sizeof(mPos[0]), 12, true); + GXSETARRAY(GX_VA_NRM, this->getNrm(), sizeof(mNrm[0]), 12, true); + GXSETARRAY(GX_VA_TEX0, &l_texCoord, sizeof(l_texCoord), 8, false); // TODO: set to true when converted to float literals GXSetZCompLoc(0); GXSetZMode(GX_ENABLE, GX_LEQUAL, GX_ENABLE); diff --git a/src/d/actor/d_a_midna.cpp b/src/d/actor/d_a_midna.cpp index cbbf1915e2..c63f4e5251 100644 --- a/src/d/actor/d_a_midna.cpp +++ b/src/d/actor/d_a_midna.cpp @@ -1834,12 +1834,12 @@ void daMidna_c::setBckAnime(J3DAnmTransform* i_bck, int i_attr, f32 i_morf) { } } else { u8* buf = mBckHeap[0].getBuffer(); - if (*(u32*)(buf + 0x1c) == 0xffffffff) { + if (*(BE(u32)*)(buf + 0x1c) == 0xffffffff) { offStateFlg1(FLG1_UNK_800); bas = NULL; } else { onStateFlg1(FLG1_UNK_800); - bas = mBckHeap[0].getBuffer() + *(u32*)(buf + 0x1c); + bas = mBckHeap[0].getBuffer() + *(BE(u32)*)(buf + 0x1c); } } @@ -3046,12 +3046,17 @@ void daMidna_c::setMidnaNoDrawFlg() { BOOL daMidna_c::checkMetamorphoseEnableBase() { BOOL tmp; - if ( - !daAlink_getAlinkActorClass()->checkMidnaRide() || (g_env_light.mEvilInitialized & 0x80) || + if (!daAlink_getAlinkActorClass()->checkMidnaRide() || (g_env_light.mEvilInitialized & 0x80) || /* dSv_event_flag_c::M_077 - Main Event - Get shadow crystal (can now transform) */ !dComIfGs_isEventBit(0xD04) || +#if TARGET_PC + (fopAcIt_Judge((fopAcIt_JudgeFunc)daMidna_searchNpc, &tmp) && + !dusk::getSettings().game.canTransformAnywhere) +#else fopAcIt_Judge((fopAcIt_JudgeFunc)daMidna_searchNpc, &tmp) - ) { +#endif + ) + { return FALSE; } return TRUE; diff --git a/src/d/actor/d_a_movie_player.cpp b/src/d/actor/d_a_movie_player.cpp index c2d1c394c0..c3074ac877 100644 --- a/src/d/actor/d_a_movie_player.cpp +++ b/src/d/actor/d_a_movie_player.cpp @@ -14,21 +14,41 @@ #pragma optimization_level 4 #pragma optimize_for_size off -#include "JSystem/JKernel/JKRExpHeap.h" +#include +#include #include "JSystem/JAudio2/JASAiCtrl.h" #include "JSystem/JAudio2/JASDriverIF.h" -#include "d/actor/d_a_movie_player.h" +#include "JSystem/JKernel/JKRExpHeap.h" #include "Z2AudioLib/Z2Instances.h" +#include "d/actor/d_a_movie_player.h" + +#include + #include "f_op/f_op_overlap_mng.h" -#include #include "dusk/gx_helper.h" +#include "dusk/os.h" +#include "dusk/layout.hpp" + +#include "JSystem/JAudio2/JASCriticalSection.h" + +#if MOVIE_SUPPORT +#include "turbojpeg.h" +#endif inline s32 daMP_NEXT_READ_SIZE(daMP_THPReadBuffer* readBuf) { - return *(s32*)readBuf->ptr; + return *(BE(s32)*)readBuf->ptr; } -#ifdef __cplusplus +#if TARGET_PC +// idk what OS_THREAD_ATTR_DETACH does, and it stops OSThreadJoin() +// probably the difference doesn't matter since we are using OS threads anyways. +#define OS_THREAD_ATTR 0 +#else +#define OS_THREAD_ATTR OS_THREAD_ATTR_DETACH +#endif + +#if defined(__cplusplus) && !TARGET_PC extern "C" { #endif @@ -196,6 +216,7 @@ static void __THPAudioInitialize(THPAudioDecodeInfo* info, u8* ptr) { info->encodeData++; } +#if !TARGET_PC static u8 THPStatistics[1120] ATTRIBUTE_ALIGN(32); static THPHuffmanTab* Ydchuff ATTRIBUTE_ALIGN(32); @@ -2562,8 +2583,109 @@ static void __THPHuffDecodeDCTCompV(__REGISTER THPFileInfo* info, THPCoeff* bloc } } } +#else // !TARGET_PC + +static daMP_THPPlayer daMP_ActivePlayer; + +#if MOVIE_SUPPORT +static std::vector FixedJpegData; +static tjhandle JpegDecompressHandle; + +static const std::vector& FixJpeg(const std::span data) { + FixedJpegData.resize(0); + FixedJpegData.reserve(data.size()); + + size_t startOfScanLocation = 0; + for (; startOfScanLocation < data.size() - 1; startOfScanLocation++) { + if (data[startOfScanLocation] == 0xFF && data[startOfScanLocation + 1] == 0xDA) { + goto sosFound; + } + } + + CRASH("Unable to find SOS marker!"); + + sosFound: + + startOfScanLocation += 2; // TODO: Skip entire SOS header? + + size_t endOfImage = data.size() - 1; + for (; endOfImage > startOfScanLocation; endOfImage--) { + if (data[endOfImage] == 0xFF && data[endOfImage + 1] == 0xD9) { + goto eoiFound; + } + } + + CRASH("Unable to find EOI marker!"); + eoiFound: + + // Copy data before SOS + for (size_t i = 0; i < startOfScanLocation; i++) { + FixedJpegData.push_back(data[i]); + } + + // Copy data inside SOS, fixing up lacking of "byte shuffling" + for (size_t i = startOfScanLocation; i < endOfImage; i++) { + u8 value = data[i]; + FixedJpegData.push_back(value); + if (value == 0xFF) { + FixedJpegData.push_back(0x00); + } + } + + // Copy data after SOS. + for (size_t i = endOfImage; i < data.size(); i++) { + FixedJpegData.push_back(data[i]); + } + + return FixedJpegData; +} + +static s32 THPVideoDecode(void* file, size_t fileSize, void* tileY, void* tileU, void* tileV, void*) { + assert(JpegDecompressHandle); + + const auto handle = JpegDecompressHandle; + const auto fixedData = FixJpeg(std::span(static_cast(file), fileSize)); + + auto ret = tj3DecompressHeader(handle, fixedData.data(), fixedData.size()); + if (ret == -1) { + OSReport_Error("Parsing JPEG header failed: %s", tj3GetErrorStr(handle)); + return 1; + } + + if (tj3Get(handle, TJPARAM_JPEGWIDTH) != daMP_ActivePlayer.videoInfo.xSize) { + OSReport_Error("Invalid width in video frame!"); + return 1; + } + + if (tj3Get(handle, TJPARAM_JPEGHEIGHT) != daMP_ActivePlayer.videoInfo.ySize) { + OSReport_Error("Invalid height in video frame!"); + return 1; + } + + ret = tj3Set(handle, TJPARAM_SUBSAMP, TJSAMP_420); + if (ret != 0) { + OSReport_Error("Failed to set subsampling mode: %s", tj3GetErrorStr(handle)); + return 1; + } + + u8* planes[3] = {static_cast(tileY), static_cast(tileU), static_cast(tileV)}; + ret = tj3DecompressToYUVPlanes8(handle, fixedData.data(), fixedData.size(), planes, nullptr); + if (ret != 0) { + OSReport_Error("Image decompression failed: %s", tj3GetErrorStr(handle)); + return 1; + } + + return 0; +} +#else // MOVIE_SUPPORT +static s32 THPVideoDecode(void*, size_t, void*, void*, void*, void*) { + return 1; // Immediate error. +} +#endif +#endif static BOOL THPInit() { +#if !TARGET_PC u8* base; base = (u8*)(0xE000 << 16); @@ -2585,15 +2707,21 @@ static BOOL THPInit() { OSInitFastCast(); __THPInitFlag = TRUE; +#endif return TRUE; } -#ifdef __cplusplus +#if defined(__cplusplus) && !TARGET_PC } #endif +#if !TARGET_PC // Defined earlier in file. static daMP_THPPlayer daMP_ActivePlayer; +#endif +#if TARGET_PC +static BOOL ReadThreadCancelled; +#endif static BOOL daMP_ReadThreadCreated; static OSMessageQueue daMP_FreeReadBufferQueue; @@ -2648,12 +2776,23 @@ void daMP_ReadThreadStart() { void daMP_ReadThreadCancel() { if (daMP_ReadThreadCreated) { +#if TARGET_PC + ReadThreadCancelled = TRUE; + OSReceiveMessage(&daMP_ReadedBufferQueue, nullptr, OS_MESSAGE_NOBLOCK); + OSSendMessage(&daMP_FreeReadBufferQueue, nullptr, OS_MESSAGE_NOBLOCK); + OSJoinThread(&daMP_ReadThread, nullptr); +#else OSCancelThread(&daMP_ReadThread); +#endif daMP_ReadThreadCreated = FALSE; } } void* daMP_Reader(void*) { +#if TARGET_PC + OSSetCurrentThreadName("movie player reader"); +#endif + daMP_THPReadBuffer* buf; s32 curFrame; s32 status; @@ -2664,8 +2803,17 @@ void* daMP_Reader(void*) { offset = daMP_ActivePlayer.initOffset; initReadSize = daMP_ActivePlayer.initReadSize; +#if TARGET_PC + while (!ReadThreadCancelled) { +#else while (TRUE) { +#endif buf = (daMP_THPReadBuffer*)daMP_PopFreeReadBuffer(); +#if TARGET_PC + if (!buf) { + return nullptr; + } +#endif status = DVDReadPrio(&daMP_ActivePlayer.fileInfo, buf->ptr, initReadSize, offset, 2); if (status != initReadSize) { if (status == -1) @@ -2673,7 +2821,11 @@ void* daMP_Reader(void*) { if (frame == 0) daMP_PrepareReady(FALSE); +#if TARGET_PC + return nullptr; +#else OSSuspendThread(&daMP_ReadThread); +#endif } buf->frameNumber = frame; @@ -2686,20 +2838,35 @@ void* daMP_Reader(void*) { if (curFrame == daMP_ActivePlayer.header.numFrames - 1) { if (daMP_ActivePlayer.playFlag & 1) offset = daMP_ActivePlayer.header.movieDataOffsets; - else - OSSuspendThread(&daMP_ReadThread); + else { +#if TARGET_PC + return nullptr; +#else + OSSuspendThread(&daMP_ReadThread); +#endif + } } frame++; } + +#if TARGET_PC + return nullptr; +#endif } static u8 daMP_ReadThreadStack[0x2000]; +#if TARGET_PC +static BOOL VideoThreadCancelled; +#endif static BOOL daMP_VideoDecodeThreadCreated; static BOOL daMP_CreateReadThread(s32 param_0) { - if (!OSCreateThread(&daMP_ReadThread, daMP_Reader, 0, daMP_ReadThreadStack + sizeof(daMP_ReadThreadStack), sizeof(daMP_ReadThreadStack), param_0, 1)) { +#if TARGET_PC + ReadThreadCancelled = FALSE; +#endif + if (!OSCreateThread(&daMP_ReadThread, daMP_Reader, 0, daMP_ReadThreadStack + sizeof(daMP_ReadThreadStack), sizeof(daMP_ReadThreadStack), param_0, OS_THREAD_ATTR)) { OSReport("Can't create read thread\n"); return FALSE; } @@ -2751,19 +2918,30 @@ static BOOL daMP_First; static void daMP_VideoDecode(daMP_THPReadBuffer* readBuffer) { THPTextureSet* textureSet; s32 i; - u32* tileOffsets; + BE(u32)* tileOffsets; u8* tile; - tileOffsets = (u32*)(readBuffer->ptr + 8); + tileOffsets = (BE(u32)*)(readBuffer->ptr + 8); tile = &readBuffer->ptr[daMP_ActivePlayer.compInfo.numComponents * 4] + 8; textureSet = (THPTextureSet*)daMP_PopFreeTextureSet(); +#if TARGET_PC + if (textureSet == nullptr) { + return; + } +#endif + for (i = 0; i < daMP_ActivePlayer.compInfo.numComponents; i++) { switch (daMP_ActivePlayer.compInfo.frameComp[i]) { case 0: { if ((daMP_ActivePlayer.videoError = THPVideoDecode( - tile, textureSet->ytexture, textureSet->utexture, - textureSet->vtexture, daMP_ActivePlayer.thpWork))) { + tile, +#if TARGET_PC + *tileOffsets, +#endif + textureSet->ytexture, textureSet->utexture, + textureSet->vtexture, + daMP_ActivePlayer.thpWork))) { if (daMP_First) { daMP_PrepareReady(FALSE); daMP_First = FALSE; @@ -2789,12 +2967,24 @@ static void daMP_VideoDecode(daMP_THPReadBuffer* readBuffer) { } static void* daMP_VideoDecoder(void* param_0) { - daMP_THPReadBuffer* thpBuffer; +#if TARGET_PC + OSSetCurrentThreadName("movie video decoder"); +#endif + daMP_THPReadBuffer* thpBuffer; +#if TARGET_PC + while (!VideoThreadCancelled) { +#else while (TRUE) { +#endif if (daMP_ActivePlayer.audioExist) { for (; daMP_ActivePlayer.videoDecodeCount < 0;) { thpBuffer = (daMP_THPReadBuffer*)daMP_PopReadedBuffer2(); +#if TARGET_PC + if (thpBuffer == nullptr) { + goto exit; + } +#endif s32 remaining = ((thpBuffer->frameNumber + daMP_ActivePlayer.initReadFrame) % daMP_ActivePlayer.header.numFrames); @@ -2814,12 +3004,26 @@ static void* daMP_VideoDecoder(void* param_0) { else thpBuffer = (daMP_THPReadBuffer*)daMP_PopReadedBuffer(); +#if TARGET_PC + if (thpBuffer == nullptr) { + goto exit; + } +#endif + daMP_VideoDecode(thpBuffer); daMP_PushFreeReadBuffer(thpBuffer); } +#if TARGET_PC + exit:; + return nullptr; +#endif } static void* daMP_VideoDecoderForOnMemory(void* param_0) { +#if TARGET_PC + OSSetCurrentThreadName("movie video decoder"); +#endif + daMP_THPReadBuffer readBuffer; s32 readSize; s32 frame; @@ -2876,13 +3080,17 @@ static void* daMP_VideoDecoderForOnMemory(void* param_0) { } static BOOL daMP_CreateVideoDecodeThread(OSPriority prio, u8* param_1) { +#if TARGET_PC + VideoThreadCancelled = FALSE; +#endif + if (param_1 != NULL) { - if (!OSCreateThread(&daMP_VideoDecodeThread, daMP_VideoDecoderForOnMemory, param_1, daMP_VideoDecodeThreadStack + sizeof(daMP_VideoDecodeThreadStack), sizeof(daMP_VideoDecodeThreadStack), prio, 1)) { + if (!OSCreateThread(&daMP_VideoDecodeThread, daMP_VideoDecoderForOnMemory, param_1, daMP_VideoDecodeThreadStack + sizeof(daMP_VideoDecodeThreadStack), sizeof(daMP_VideoDecodeThreadStack), prio, OS_THREAD_ATTR)) { OSReport("Can't create video decode thread\n"); return FALSE; } } else { - if (!OSCreateThread(&daMP_VideoDecodeThread, daMP_VideoDecoder, NULL, daMP_VideoDecodeThreadStack + sizeof(daMP_VideoDecodeThreadStack), sizeof(daMP_VideoDecodeThreadStack), prio, 1)) { + if (!OSCreateThread(&daMP_VideoDecodeThread, daMP_VideoDecoder, NULL, daMP_VideoDecodeThreadStack + sizeof(daMP_VideoDecodeThreadStack), sizeof(daMP_VideoDecodeThreadStack), prio, OS_THREAD_ATTR)) { OSReport("Can't create video decode thread\n"); return FALSE; } @@ -2903,12 +3111,24 @@ static void daMP_VideoDecodeThreadStart() { void daMP_VideoDecodeThreadCancel() { if (daMP_VideoDecodeThreadCreated) { +#if TARGET_PC + VideoThreadCancelled = TRUE; + // Push junk into the queues so the thread unblocks and can exit cleanly. + daMP_PushFreeTextureSet(nullptr); + daMP_PushReadedBuffer(nullptr); + daMP_PushReadedBuffer2(nullptr); + OSJoinThread(&daMP_VideoDecodeThread, nullptr); +#else OSCancelThread(&daMP_VideoDecodeThread); +#endif daMP_VideoDecodeThreadCreated = FALSE; } } static BOOL daMP_AudioDecodeThreadCreated; +#if TARGET_PC +static BOOL AudioThreadCancelled; +#endif static OSThread daMP_AudioDecodeThread; @@ -2944,12 +3164,17 @@ static void daMP_PushDecodedAudioBuffer(void* buffer) { static void daMP_AudioDecode(daMP_THPReadBuffer* readBuffer) { THPAudioBuffer* audioBuf; s32 i; - u32* offsets; + BE(u32)* offsets; u8* audioData; - offsets = (u32*)(readBuffer->ptr + 8); + offsets = (BE(u32)*)(readBuffer->ptr + 8); audioData = &readBuffer->ptr[daMP_ActivePlayer.compInfo.numComponents * 4] + 8; audioBuf = (THPAudioBuffer*)daMP_PopFreeAudioBuffer(); +#if TARGET_PC + if (!audioBuf) { + return; + } +#endif for (i = 0; i < daMP_ActivePlayer.compInfo.numComponents; i++) { switch (daMP_ActivePlayer.compInfo.frameComp[i]) { @@ -2969,16 +3194,34 @@ static void daMP_AudioDecode(daMP_THPReadBuffer* readBuffer) { } static void* daMP_AudioDecoder(void* param_0) { +#if TARGET_PC + OSSetCurrentThreadName("movie audio decoder"); +#endif + daMP_THPReadBuffer* buf; +#if TARGET_PC + while (!AudioThreadCancelled) { +#else while (TRUE) { +#endif buf = (daMP_THPReadBuffer*)daMP_PopReadedBuffer(); +#if TARGET_PC + if (!buf) { + return nullptr; + } +#endif daMP_AudioDecode(buf); daMP_PushReadedBuffer2(buf); } + return nullptr; } static void* daMP_AudioDecoderForOnMemory(void* param_0) { +#if TARGET_PC + OSSetCurrentThreadName("movie audio decoder"); +#endif + s32 size; s32 readSize; daMP_THPReadBuffer readBuffer; @@ -2989,7 +3232,11 @@ static void* daMP_AudioDecoderForOnMemory(void* param_0) { readBuffer.ptr = (u8*)param_0; frame = 0; +#if TARGET_PC + while (!AudioThreadCancelled) { +#else while (TRUE) { +#endif readBuffer.frameNumber = frame; daMP_AudioDecode(&readBuffer); @@ -2999,7 +3246,11 @@ static void* daMP_AudioDecoderForOnMemory(void* param_0) { readSize = *(s32*)readBuffer.ptr; readBuffer.ptr = daMP_ActivePlayer.movieData; } else { +#if TARGET_PC + return nullptr; +#else OSSuspendThread(&daMP_AudioDecodeThread); +#endif } } else { size = *(s32*)readBuffer.ptr; @@ -3008,6 +3259,7 @@ static void* daMP_AudioDecoderForOnMemory(void* param_0) { } frame++; } + return nullptr; } static OSMessage daMP_FreeAudioBufferMessage[3]; @@ -3015,13 +3267,16 @@ static OSMessage daMP_FreeAudioBufferMessage[3]; static OSMessage daMP_DecodedAudioBufferMessage[3]; static BOOL daMP_CreateAudioDecodeThread(OSPriority prio, u8* param_1) { +#if TARGET_PC + AudioThreadCancelled = FALSE; +#endif if (param_1 != NULL) { - if (!OSCreateThread(&daMP_AudioDecodeThread, daMP_AudioDecoderForOnMemory, param_1, daMP_AudioDecodeThreadStack + sizeof(daMP_AudioDecodeThreadStack), sizeof(daMP_AudioDecodeThreadStack), prio, 1)) { + if (!OSCreateThread(&daMP_AudioDecodeThread, daMP_AudioDecoderForOnMemory, param_1, daMP_AudioDecodeThreadStack + sizeof(daMP_AudioDecodeThreadStack), sizeof(daMP_AudioDecodeThreadStack), prio, OS_THREAD_ATTR)) { OS_REPORT("Can't create audio decode thread\n"); return FALSE; } } else { - if (!OSCreateThread(&daMP_AudioDecodeThread, daMP_AudioDecoder, NULL, daMP_AudioDecodeThreadStack + sizeof(daMP_AudioDecodeThreadStack), sizeof(daMP_AudioDecodeThreadStack), prio, 1)) { + if (!OSCreateThread(&daMP_AudioDecodeThread, daMP_AudioDecoder, NULL, daMP_AudioDecodeThreadStack + sizeof(daMP_AudioDecodeThreadStack), sizeof(daMP_AudioDecodeThreadStack), prio, OS_THREAD_ATTR)) { OSReport("Can't create audio decode thread\n"); return FALSE; } @@ -3042,7 +3297,17 @@ void daMP_AudioDecodeThreadStart() { void daMP_AudioDecodeThreadCancel() { if (daMP_AudioDecodeThreadCreated) { +#if TARGET_PC + AudioThreadCancelled = TRUE; + // Push junk into the queues so the thread unblocks and can exit cleanly. + OSSendMessage(&daMP_ReadedBufferQueue, nullptr, OS_MESSAGE_NOBLOCK); + daMP_PushFreeAudioBuffer(nullptr); + OSReceiveMessage(&daMP_ReadedBufferQueue2, nullptr, OS_MESSAGE_NOBLOCK); + OSReceiveMessage(&daMP_DecodedAudioBufferQueue, nullptr, OS_MESSAGE_NOBLOCK); + OSJoinThread(&daMP_AudioDecodeThread, nullptr); +#else OSCancelThread(&daMP_AudioDecodeThread); +#endif daMP_AudioDecodeThreadCreated = FALSE; } } @@ -3077,8 +3342,13 @@ static void daMP_THPGXYuv2RgbSetup(const GXRenderModeObj* rmode) { Mtx44 m; Mtx e_m; +#if TARGET_PC + w = JUTVideo::getManager()->getFbWidth(); + h = JUTVideo::getManager()->getEfbHeight(); +#else w = rmode->fbWidth; h = rmode->efbHeight; +#endif var_f31 = 0.0f; #if WIDESCREEN_SUPPORT @@ -3168,19 +3438,26 @@ static void daMP_THPGXYuv2RgbDraw(u8* y_data, u8* u_data, u8* v_data, s16 x, TGXTexObj tobj0; TGXTexObj tobj1; TGXTexObj tobj2; +#if TARGET_PC +#define FMT (GXTexFmt)GX_TF_R8_PC +#else +#define FMT GX_TF_I8 +#endif - GXInitTexObj(&tobj0, y_data, textureWidth, textureHeight, GX_TF_I8, GX_CLAMP, GX_CLAMP, GX_FALSE); + GXInitTexObj(&tobj0, y_data, textureWidth, textureHeight, FMT, GX_CLAMP, GX_CLAMP, GX_FALSE); GXInitTexObjLOD(&tobj0, GX_NEAR, GX_NEAR, 0.0f, 0.0f, 0.0f, 0, 0, GX_ANISO_1); GXLoadTexObj(&tobj0, GX_TEXMAP0); - GXInitTexObj(&tobj1, u_data, textureWidth >> 1, textureHeight >> 1, GX_TF_I8, GX_CLAMP, GX_CLAMP, GX_FALSE); + GXInitTexObj(&tobj1, u_data, textureWidth >> 1, textureHeight >> 1, FMT, GX_CLAMP, GX_CLAMP, GX_FALSE); GXInitTexObjLOD(&tobj1, GX_NEAR, GX_NEAR, 0.0f, 0.0f, 0.0f, 0, 0, GX_ANISO_1); GXLoadTexObj(&tobj1, GX_TEXMAP1); - GXInitTexObj(&tobj2, v_data, textureWidth >> 1, textureHeight >> 1, GX_TF_I8, GX_CLAMP, GX_CLAMP, GX_FALSE); + GXInitTexObj(&tobj2, v_data, textureWidth >> 1, textureHeight >> 1, FMT, GX_CLAMP, GX_CLAMP, GX_FALSE); GXInitTexObjLOD(&tobj2, GX_NEAR, GX_NEAR, 0.0f, 0.0f, 0.0f, 0, 0, GX_ANISO_1); GXLoadTexObj(&tobj2, GX_TEXMAP2); +#undef FMT + GXBegin(GX_QUADS, GX_VTXFMT7, 4); GXPosition3s16(x, y, 0); GXTexCoord2u16(0, 0); @@ -3191,6 +3468,12 @@ static void daMP_THPGXYuv2RgbDraw(u8* y_data, u8* u_data, u8* v_data, s16 x, GXPosition3s16(x, y + polygonHeight, 0); GXTexCoord2u16(0, 1); GXEnd(); + +#if TARGET_PC + GXDestroyTexObj(&tobj0); + GXDestroyTexObj(&tobj1); + GXDestroyTexObj(&tobj2); +#endif } static u16 daMP_VolumeTable[] = { @@ -3268,7 +3551,7 @@ static void daMP_MixAudio(s16* destination, s16*, u32 sample) { if (r_mix > 32767) r_mix = 32767; - if (JASDriver::getOutputMode() == 0) { + if (JASDriver::getOutputMode() == JAS_OUTPUT_MONO) { l_mix = r_mix = ((r_mix >> 1) + (l_mix >> 1)); r_mix = (s16)r_mix; l_mix = (s16)l_mix; @@ -3495,6 +3778,13 @@ static BOOL daMP_THPPlayerOpen(char const* filename, BOOL onMemory) { } static BOOL daMP_THPPlayerClose() { +#if TARGET_PC && MOVIE_SUPPORT + tj3Destroy(JpegDecompressHandle); + JpegDecompressHandle = nullptr; + + FixedJpegData.clear(); +#endif + if (daMP_ActivePlayer.open && daMP_ActivePlayer.state == 0) { daMP_ActivePlayer.open = 0; DVDClose(&daMP_ActivePlayer.fileInfo); @@ -3546,6 +3836,11 @@ static BOOL daMP_THPPlayerSetBuffer(u8* buffer) { ysize = ALIGN_NEXT(daMP_ActivePlayer.videoInfo.xSize * daMP_ActivePlayer.videoInfo.ySize, 32); uvsize = ALIGN_NEXT(daMP_ActivePlayer.videoInfo.xSize * daMP_ActivePlayer.videoInfo.ySize / 4, 32); +#if TARGET_PC + assert(ysize >= tj3YUVPlaneSize(0, daMP_ActivePlayer.videoInfo.xSize, 0, daMP_ActivePlayer.videoInfo.ySize, TJSAMP_420)); + assert(uvsize >= tj3YUVPlaneSize(1, daMP_ActivePlayer.videoInfo.xSize, 0, daMP_ActivePlayer.videoInfo.ySize, TJSAMP_420)); + assert(uvsize >= tj3YUVPlaneSize(2, daMP_ActivePlayer.videoInfo.xSize, 0, daMP_ActivePlayer.videoInfo.ySize, TJSAMP_420)); +#endif for (i = 0; i < ARRAY_SIZE(daMP_ActivePlayer.textureSet); i++) { daMP_ActivePlayer.textureSet[i].ytexture = ptr; @@ -3623,6 +3918,12 @@ static BOOL daMP_ProperTimingForGettingNextFrame() { } } else { s32 frameRate = daMP_ActivePlayer.header.frameRate * 100.0f; +#if TARGET_PC + // DUSK HACK: We only fire retrace callbacks *half* as often as the game expects, + // because we only run them once per frame, and normally there should be two scans + // per game frame. + frameRate *= 2; +#endif if (VIGetTvFormat() == VI_PAL) { daMP_ActivePlayer.curCount = daMP_ActivePlayer.retaceCount * frameRate / 5000; } else { @@ -3951,6 +4252,9 @@ static BOOL daMP_THPPlayerSetVolume(s32 vol, s32 duration) { if (duration < 0) duration = 0; +#if TARGET_PC + JASCriticalSection section; +#endif interrupt = OSDisableInterrupts(); daMP_ActivePlayer.targetVolume = vol; @@ -3994,11 +4298,14 @@ static BOOL daMP_ActivePlayer_Init(char const* moviePath) { daMP_THPPlayerGetVideoInfo(&daMP_videoInfo); daMP_THPPlayerGetAudioInfo(&daMP_audioInfo); +#if !TARGET_PC + // Window can be resized during playback, update this during draw. u16 width = JUTVideo::getManager()->getRenderMode()->fbWidth; u16 height = JUTVideo::getManager()->getRenderMode()->efbHeight; daMP_DrawPosX = (width - daMP_videoInfo.xSize) >> 1; daMP_DrawPosY = (height - daMP_videoInfo.ySize) >> 1; +#endif // "The memory needed for this THP movie is %d bytes\n" OS_REPORT("このTHPムービーが必要なメモリは%dバイトです\n", daMP_THPPlayerCalcNeedMemory()); @@ -4015,6 +4322,15 @@ static BOOL daMP_ActivePlayer_Init(char const* moviePath) { daMP_THPPlayerSetBuffer((u8*)daMP_buffer); +#if TARGET_PC && MOVIE_SUPPORT + assert(JpegDecompressHandle == nullptr); + JpegDecompressHandle = tj3Init(TJINIT_DECOMPRESS); + if (JpegDecompressHandle == nullptr) { + OSReport_Error("Failed to create turbojpeg handle: %s", tj3GetErrorStr(nullptr)); + return 0; + } +#endif + if (!daMP_THPPlayerPrepare(0, 0, daMP_audioInfo.sndNumTracks != 1 ? OSGetTick() % daMP_audioInfo.sndNumTracks : 0)) { OSReport("Fail to prepare\n"); #if DEBUG @@ -4050,14 +4366,55 @@ static void daMP_ActivePlayer_Main() { } } +#if TARGET_PC && 0 +#include "imgui.h" +#endif + static void daMP_ActivePlayer_Draw() { - int frame = daMP_THPPlayerDrawCurrentFrame(JUTVideo::getManager()->getRenderMode(), daMP_DrawPosX, daMP_DrawPosY, daMP_videoInfo.xSize, daMP_videoInfo.ySize); +#if TARGET_PC + u16 width = JUTVideo::getManager()->getFbWidth(); + u16 height = JUTVideo::getManager()->getEfbHeight(); + + const auto rect = dusk::LayoutRect::FitRectInRect( + width, + height, + static_cast(daMP_videoInfo.xSize), + static_cast(daMP_videoInfo.ySize)); + + daMP_DrawPosX = static_cast(rect.PosX); + daMP_DrawPosY = static_cast(rect.PosY); +#endif + + int frame = daMP_THPPlayerDrawCurrentFrame( + JUTVideo::getManager()->getRenderMode(), + daMP_DrawPosX, daMP_DrawPosY, +#if TARGET_PC + static_cast(rect.Width()), + static_cast(rect.Height())); +#else + daMP_videoInfo.xSize, + daMP_videoInfo.ySize); +#endif daMP_THPPlayerDrawDone(); if (!fopOvlpM_IsPeek() && frame > 0 && (cAPICPad_ANY_BUTTON(0) || !daMP_c::daMP_c_Get_MovieRestFrame())) { dComIfGp_event_reset(); daMP_c::daMP_c_Set_PercentMovieVolume(0.0f); } + +#if TARGET_PC && 0 + if (ImGui::Begin("Movie player")) { + ImGui::Text("daMP_ReadedBufferQueue: %d", daMP_ReadedBufferQueue.usedCount); + ImGui::Text("daMP_ReadedBufferQueue2: %d", daMP_ReadedBufferQueue2.usedCount); + ImGui::Text("daMP_FreeReadBufferQueue: %d", daMP_FreeReadBufferQueue.usedCount); + ImGui::Text("daMP_DecodedTextureSetQueue: %d", daMP_DecodedTextureSetQueue.usedCount); + ImGui::Text("daMP_FreeTextureSetQueue: %d", daMP_FreeTextureSetQueue.usedCount); + ImGui::Text("daMP_DecodedAudioBufferQueue: %d", daMP_DecodedAudioBufferQueue.usedCount); + ImGui::Text("daMP_FreeAudioBufferQueue: %d", daMP_FreeAudioBufferQueue.usedCount); + } + + ImGui::End(); +#endif } static BOOL daMP_Fail_alloc; @@ -4116,7 +4473,9 @@ int daMP_c::daMP_c_Get_arg_movieNo() { int daMP_c::daMP_c_Init() { JUT_ASSERT(9469, m_myObj == NULL); +#if !TARGET_PC // We don't properly simulate retrace interval so this doesn't work. mDoGph_gInf_c::setFrameRate(1); +#endif daMP_Fail_alloc = FALSE; int demoNo = daMP_c_Get_arg_demoNo(); diff --git a/src/d/actor/d_a_myna.cpp b/src/d/actor/d_a_myna.cpp index af26d5e3a2..b23845a922 100644 --- a/src/d/actor/d_a_myna.cpp +++ b/src/d/actor/d_a_myna.cpp @@ -74,9 +74,9 @@ static char* l_bckFileNameTBL[] = { static char* l_btpFileNameTBL[] = {"MYNA.btp"}; -static void createHeapCallBack(fopAc_ac_c* i_this) { +static int createHeapCallBack(fopAc_ac_c* i_this) { daMyna_c* a_this = static_cast(i_this); - a_this->createHeap(); + return a_this->createHeap(); } static int jntNodeCallBack(J3DJoint* i_jnt, int param_1) { @@ -339,7 +339,7 @@ int daMyna_c::create() { return phase; } - if (!fopAcM_entrySolidHeap(this, (heapCallbackFunc)&createHeapCallBack, 0x21F0)) { + if (!fopAcM_entrySolidHeap(this, createHeapCallBack, 0x21F0)) { return cPhs_ERROR_e; } diff --git a/src/d/actor/d_a_npc.cpp b/src/d/actor/d_a_npc.cpp index b903ce8c8f..6ec2fbe7a9 100644 --- a/src/d/actor/d_a_npc.cpp +++ b/src/d/actor/d_a_npc.cpp @@ -2694,16 +2694,15 @@ BOOL daNpcT_chkActorInScreen(fopAc_ac_c* i_ActorP, f32 param_1, f32 param_2, f32 } for (int i = 0; i < 8; i++) { + #if TARGET_PC + mDoLib_project(&pos_array[i], &proj, {0, 0, FB_WIDTH, FB_HEIGHT}); + #else mDoLib_project(&pos_array[i], &proj); -#if TARGET_PC - if (0.0f < proj.x && proj.x < mDoGph_gInf_c::getWidth() && 0.0f < proj.y && proj.y < mDoGph_gInf_c::getHeight()) { - continue; - } -#else + #endif + if (0.0f < proj.x && proj.x < FB_WIDTH && 0.0f < proj.y && proj.y < FB_HEIGHT) { continue; } -#endif return false; } diff --git a/src/d/actor/d_a_npc_grz.cpp b/src/d/actor/d_a_npc_grz.cpp index c245340c4c..104c0c4756 100644 --- a/src/d/actor/d_a_npc_grz.cpp +++ b/src/d/actor/d_a_npc_grz.cpp @@ -1363,7 +1363,15 @@ void daNpc_Grz_c::playExpression() { daNpcF_anmPlayData dat7 = {ANM_LIEDOWN, mpHIO->m.common.morf_frame, 0}; daNpcF_anmPlayData* pDat7[1] = {&dat7}; daNpcF_anmPlayData dat8 = {ANM_GETUP, mpHIO->m.common.morf_frame, 1}; - daNpcF_anmPlayData* pDat8[1] = {&dat8}; +#if TARGET_PC + // BUG: If mNumLoops is non-zero, the data array MUST be null-terminated to prevent + // playExpression from reading junk when it increments the index. + // For some reason this doesn't crash on hardware, but it triggers a segfault on PC + // when first talking to Fyrus after defating him. + daNpcF_anmPlayData* pDat8[2] = {&dat8, NULL}; +#else + daNpcF_anmPlayData* pDat8[2] = {&dat8}; +#endif daNpcF_anmPlayData dat9 = {ANM_F_WEAK_WAIT, mpHIO->m.common.morf_frame, 0}; daNpcF_anmPlayData* pDat9[1] = {&dat9}; daNpcF_anmPlayData dat10 = {ANM_NONE, mpHIO->m.common.morf_frame, 0}; diff --git a/src/d/actor/d_a_npc_henna.cpp b/src/d/actor/d_a_npc_henna.cpp index 59f13ceabe..339d5ee82c 100644 --- a/src/d/actor/d_a_npc_henna.cpp +++ b/src/d/actor/d_a_npc_henna.cpp @@ -2709,6 +2709,14 @@ static int daNpc_Henna_Create(fopAc_ac_c* i_this) { } i_this->attention_info.flags = (fopAc_AttnFlag_SPEAK_e | fopAc_AttnFlag_TALK_e); a_this->action = 0; + +#if AVOID_UB + a_this->field_0x654 = 0; + a_this->field_0x658 = 0; + a_this->field_0x662 = 0; + a_this->field_0x664 = 0; +#endif + fopAcM_SetMtx(i_this, a_this->mpMorf->getModel()->getBaseTRMtx()); lbl_82_bss_90 = 0; if (a_this->arg0 == 1) { diff --git a/src/d/actor/d_a_npc_sola.cpp b/src/d/actor/d_a_npc_sola.cpp index 49568095bc..a8fb79593c 100644 --- a/src/d/actor/d_a_npc_sola.cpp +++ b/src/d/actor/d_a_npc_sola.cpp @@ -194,14 +194,13 @@ int daNpc_solA_c::Execute() { return execute(); } -void daNpc_solA_c::Draw() { +int daNpc_solA_c::Draw() { if (mpMatAnm[0] != NULL) { J3DModelData* mdlData_p = mpMorf[0]->getModel()->getModelData(); mdlData_p->getMaterialNodePointer(getEyeballMaterialNo())->setMaterialAnm(mpMatAnm[0]); } - draw(FALSE, FALSE, mpHIO->m.common.real_shadow_size, NULL, 100.0f, FALSE, FALSE, - FALSE); - return; + + return draw(FALSE, FALSE, mpHIO->m.common.real_shadow_size, NULL, 100.0f, FALSE, FALSE, FALSE); } BOOL daNpc_solA_c::createHeapCallBack(fopAc_ac_c* a_this) { @@ -481,12 +480,12 @@ static int daNpc_solA_Execute(void* param_0) { return static_cast(param_0)->Execute(); } -static void daNpc_solA_Draw(void* param_0) { +static int daNpc_solA_Draw(void* param_0) { return static_cast(param_0)->Draw(); } -static BOOL daNpc_solA_IsDelete(void* param_0) { - return TRUE; +static int daNpc_solA_IsDelete(void* param_0) { + return 1; } static actor_method_class daNpc_solA_MethodTable = { diff --git a/src/d/actor/d_a_npc_tk.cpp b/src/d/actor/d_a_npc_tk.cpp index c31c0c052c..0349f8ebc0 100644 --- a/src/d/actor/d_a_npc_tk.cpp +++ b/src/d/actor/d_a_npc_tk.cpp @@ -2014,7 +2014,7 @@ void daNPC_TK_c::executeWolfPerch() { mWolfPathData = dPath_GetRoomPath(mpPath1->m_nextID, fopAcM_GetRoomNo(this)); JUT_ASSERT(2498, mWolfPathData != NULL); - field_0x6ea = mWolfPathData->field_0x6; + field_0x6ea = mWolfPathData->swbit; field_0x6e8 = mWolfPathData->field_0x4; field_0x6e9 = mWolfPathData->field_0x7; field_0x6d0.Init(mWolfPathData); @@ -2518,7 +2518,7 @@ void daNPC_TK_c::executeResistanceDemo() { 0x200, 0x10); shape_angle.x = -current.angle.x; - cLib_addCalcAngleS(¤t.angle.y, cLib_targetAngleY((Vec*)¤t, &posWithOffset), 8, + cLib_addCalcAngleS(¤t.angle.y, cLib_targetAngleY(¤t.pos, &posWithOffset), 8, 0x400, 0x10); shape_angle.y = current.angle.y; diff --git a/src/d/actor/d_a_npc_tks.cpp b/src/d/actor/d_a_npc_tks.cpp index f1c33003f8..9b0ee4af70 100644 --- a/src/d/actor/d_a_npc_tks.cpp +++ b/src/d/actor/d_a_npc_tks.cpp @@ -824,9 +824,11 @@ void daNpcTks_c::playMotion() { daNpcF_anmPlayData dat4b = {ANM_FLY, 0.0f, 0}; daNpcF_anmPlayData* pDat4[2] = {&dat4a, &dat4b}; - #if TARGET_PC - // Note: this fixes a crash in the cutscene after entering city and likely needs to be revisited as its - // unclear why this was 1 in the first place and unclear why this fixes it +#if TARGET_PC + // BUG: If mNumLoops is non-zero, the data array MUST be null-terminated to prevent + // playExpression from reading junk when it increments the index. + // For some reason this doesn't crash on hardware, but it triggers a segfault on PC + // in the cutscene after entering city. daNpcF_anmPlayData dat5 = {ANM_JUMP_E, 0.0f, 0}; #else daNpcF_anmPlayData dat5 = {ANM_JUMP_E, 0.0f, 1}; diff --git a/src/d/actor/d_a_obj_Y_taihou.cpp b/src/d/actor/d_a_obj_Y_taihou.cpp index ab9d2bf4cf..61f96a12ab 100644 --- a/src/d/actor/d_a_obj_Y_taihou.cpp +++ b/src/d/actor/d_a_obj_Y_taihou.cpp @@ -356,21 +356,21 @@ int daObjYtaihou_c::Delete() { return 1; } -static void daObjYtaihou_create1st(daObjYtaihou_c* i_this) { +static int daObjYtaihou_create1st(daObjYtaihou_c* i_this) { fopAcM_ct(i_this, daObjYtaihou_c); - i_this->create1st(); + return i_this->create1st(); } -static void daObjYtaihou_MoveBGDelete(daObjYtaihou_c* i_this) { - i_this->MoveBGDelete(); +static int daObjYtaihou_MoveBGDelete(daObjYtaihou_c* i_this) { + return i_this->MoveBGDelete(); } -static void daObjYtaihou_MoveBGExecute(daObjYtaihou_c* i_this) { - i_this->MoveBGExecute(); +static int daObjYtaihou_MoveBGExecute(daObjYtaihou_c* i_this) { + return i_this->MoveBGExecute(); } -static void daObjYtaihou_MoveBGDraw(daObjYtaihou_c* i_this) { - i_this->Draw(); +static int daObjYtaihou_MoveBGDraw(daObjYtaihou_c* i_this) { + return i_this->Draw(); } static actor_method_class daObjYtaihou_METHODS = { diff --git a/src/d/actor/d_a_obj_ari.cpp b/src/d/actor/d_a_obj_ari.cpp index 267b0003af..3e2727e2f2 100644 --- a/src/d/actor/d_a_obj_ari.cpp +++ b/src/d/actor/d_a_obj_ari.cpp @@ -499,7 +499,13 @@ void daObjARI_c::Z_BufferChk() { cXyz vec2, vec1; vec1 = current.pos; vec1.y += 20.0f; + + #if TARGET_PC + mDoLib_project(&vec1, &vec2, {0, 0, FB_WIDTH, FB_HEIGHT}); + #else mDoLib_project(&vec1, &vec2); + #endif + f32 trim_height; camera_process_class* camera = dComIfGp_getCamera(0); if (camera != NULL) { diff --git a/src/d/actor/d_a_obj_bhashi.cpp b/src/d/actor/d_a_obj_bhashi.cpp index 00a35bc158..33595c7a77 100644 --- a/src/d/actor/d_a_obj_bhashi.cpp +++ b/src/d/actor/d_a_obj_bhashi.cpp @@ -285,7 +285,13 @@ bool Hahen_c::CheckCull() { bool Hahen_c::checkViewArea() { Vec proj; + + #if TARGET_PC + mDoLib_project(&pos, &proj, {0, 0, FB_WIDTH, FB_HEIGHT}); + #else mDoLib_project(&pos, &proj); + #endif + return (proj.x >= -50.0f && proj.x <= 658.0f) && (proj.y >= -50.0f && proj.y <= 498.0f); } diff --git a/src/d/actor/d_a_obj_brg.cpp b/src/d/actor/d_a_obj_brg.cpp index b2acca8f98..5615a79622 100644 --- a/src/d/actor/d_a_obj_brg.cpp +++ b/src/d/actor/d_a_obj_brg.cpp @@ -16,6 +16,8 @@ #include "f_op/f_op_camera_mng.h" #include +#include "dusk/logging.h" + static void ride_call_back(dBgW* i_bgw, fopAc_ac_c* i_bgActor, fopAc_ac_c* i_rideActor) { obj_brg_class* a_this = (obj_brg_class*)i_bgActor; @@ -588,8 +590,6 @@ static void cut_control2(obj_brg_class* i_this, br_s* i_part) { } static void himo_cut_control1(obj_brg_class* i_this, cXyz* param_1, f32 param_2) { - STUB_RET(); - cXyz sp74 = {}; cXyz sp80 = {}; cXyz sp8C = {}; @@ -1794,6 +1794,10 @@ static int daObj_Brg_Create(fopAc_ac_c* i_this) { cXyz(334.0f, 85.0f, -16054.0f), cXyz(334.0f, 150.0f, -16270.0f), cXyz(334.0f, 216.0f, -16485.0f), +#ifdef TARGET_PC + // Avoids out-of-bounds index (n=22) + cXyz(0.f, 0.f, 0.f), +#endif }; for (brno = 0; brno < a_this->field_0xb1ea; brno++) { diff --git a/src/d/actor/d_a_obj_cho.cpp b/src/d/actor/d_a_obj_cho.cpp index 8fbc2dbde8..27b0b8ce0e 100644 --- a/src/d/actor/d_a_obj_cho.cpp +++ b/src/d/actor/d_a_obj_cho.cpp @@ -289,7 +289,13 @@ void daObjCHO_c::Z_BufferChk() { cXyz vec2, vec1; vec1 = current.pos; vec1.y += 20.0f; + + #if TARGET_PC + mDoLib_project(&vec1, &vec2, {0, 0, FB_WIDTH, FB_HEIGHT}); + #else mDoLib_project(&vec1, &vec2); + #endif + f32 trim_height; camera_process_class* camera = dComIfGp_getCamera(0); if (camera != NULL) { diff --git a/src/d/actor/d_a_obj_crvfence.cpp b/src/d/actor/d_a_obj_crvfence.cpp index 9712205ea3..03ff2b1d6a 100644 --- a/src/d/actor/d_a_obj_crvfence.cpp +++ b/src/d/actor/d_a_obj_crvfence.cpp @@ -224,7 +224,13 @@ void daObjCRVFENCE_c::NormalAction() { bool daObjCRVFENCE_c::checkViewArea(cXyz* param_1) { Vec sp24; + + #if TARGET_PC + mDoLib_project(param_1, &sp24, {0, 0, FB_WIDTH, FB_HEIGHT}); + #else mDoLib_project(param_1, &sp24); + #endif + bool rv = false; bool bVar1 = false; diff --git a/src/d/actor/d_a_obj_crvhahen.cpp b/src/d/actor/d_a_obj_crvhahen.cpp index 52d180f547..0b44a57ec8 100644 --- a/src/d/actor/d_a_obj_crvhahen.cpp +++ b/src/d/actor/d_a_obj_crvhahen.cpp @@ -137,7 +137,12 @@ void daObjCRVHAHEN_c::CheckCull() { bool daObjCRVHAHEN_c::checkViewArea(cXyz* i_this) { Vec proj; + + #if TARGET_PC + mDoLib_project(i_this, &proj, {0, 0, FB_WIDTH, FB_HEIGHT}); + #else mDoLib_project(i_this, &proj); + #endif bool ret = false; diff --git a/src/d/actor/d_a_obj_dan.cpp b/src/d/actor/d_a_obj_dan.cpp index cc176b9a20..53dbf4e1e4 100644 --- a/src/d/actor/d_a_obj_dan.cpp +++ b/src/d/actor/d_a_obj_dan.cpp @@ -267,7 +267,13 @@ void daObjDAN_c::Z_BufferChk() { cXyz vec2, vec1; vec1 = current.pos; vec1.y += 20.0f; + + #if TARGET_PC + mDoLib_project(&vec1, &vec2, {0, 0, FB_WIDTH, FB_HEIGHT}); + #else mDoLib_project(&vec1, &vec2); + #endif + f32 trim_height; camera_process_class* camera = dComIfGp_getCamera(0); if (camera != NULL) { diff --git a/src/d/actor/d_a_obj_drop.cpp b/src/d/actor/d_a_obj_drop.cpp index 64fc1f537d..275a3d6e12 100644 --- a/src/d/actor/d_a_obj_drop.cpp +++ b/src/d/actor/d_a_obj_drop.cpp @@ -20,6 +20,8 @@ #include "d/actor/d_a_e_ymb.h" #include "f_op/f_op_camera_mng.h" +#include "dusk/settings.h" + #if DEBUG daObjDrop_HIO_c l_HIO; #endif @@ -261,8 +263,18 @@ int daObjDrop_c::modeParentWait() { } mModeAction = 1; + +#if TARGET_PC + mModeTimer = dusk::getSettings().game.fastTears && dComIfGp_event_getMode() == 0 ? 20 : 40; + if (dusk::getSettings().game.fastTears && dComIfGp_event_getMode() == 0) { + current.pos.y += 100.0f; + } else { + current.pos.y += 300.0f; + } +#else mModeTimer = 40; current.pos.y += 300.0f; +#endif mSound.startSound(Z2SE_OBJ_LIGHTDROP_APPEAR, 0, -1); break; case 1: @@ -272,7 +284,11 @@ int daObjDrop_c::modeParentWait() { break; case 2: createBodyEffect(); +#if TARGET_PC + mModeTimer = dusk::getSettings().game.fastTears && dComIfGp_event_getMode() == 0 ? 5 : 45; +#else mModeTimer = 45; +#endif mModeAction = 0; setMode(MODE_WAIT_e); break; @@ -281,6 +297,18 @@ int daObjDrop_c::modeParentWait() { return 1; } +#if TARGET_PC +static inline BOOL checkGetCargoRide() { + if ((daPy_getPlayerActorClass()->checkCargoCarry() && strcmp(dComIfGp_getStartStageName(), "F_SP112") == 0) || + dComIfGs_isLightDropGetFlag(dComIfGp_getStartStageDarkArea())) + { + return true; + } + + return false; +} +#endif + int daObjDrop_c::modeWait() { daPy_py_c* pplayer = daPy_getPlayerActorClass(); @@ -302,7 +330,32 @@ int daObjDrop_c::modeWait() { case 1: case 2: case 50: + #if TARGET_PC + if (dusk::getSettings().game.fastTears && dComIfGp_event_getMode() == 0) { + f32 player_dist = current.pos.abs(daPy_getPlayerActorClass()->current.pos); + f32 home_dist = current.pos.abs(home.pos); + + if (checkGetCargoRide() && player_dist < 1000.0f) { + mTargetPos = pplayer->current.pos; + mTargetPos.y += 100.0f; + + f32 temp = 3000.0f - home_dist; + if (temp < 0.0f) { + temp = 0.0f; + } + + cLib_chaseF(&speedF, (temp / 3000.0f) * 10.0f * (temp / 3000.0f), 1.0f); + } else { + mTargetPos = home.pos; + cLib_chaseF(&speedF, 2.0f, 0.5f); + } + } else { + cLib_chaseF(&speedF, 7.5f, 0.4f); + } + #else cLib_chaseF(&speedF, 7.5f, 0.4f); + #endif + if (mModeAction == 1) { cLib_chasePos(¤t.pos, mTargetPos, speedF); } diff --git a/src/d/actor/d_a_obj_fan.cpp b/src/d/actor/d_a_obj_fan.cpp index bf221bd8aa..dfe413c5b9 100644 --- a/src/d/actor/d_a_obj_fan.cpp +++ b/src/d/actor/d_a_obj_fan.cpp @@ -310,9 +310,9 @@ int daObjFan_c::Delete() { return 1; } -static void daObjFan_create1st(daObjFan_c* param_0) { +static int daObjFan_create1st(daObjFan_c* param_0) { fopAcM_ct(param_0, daObjFan_c); - param_0->create1st(); + return param_0->create1st(); } static int daObjFan_MoveBGDelete(daObjFan_c* param_0) { diff --git a/src/d/actor/d_a_obj_flag.cpp b/src/d/actor/d_a_obj_flag.cpp index 9e4d238fed..b3f55ff1d2 100644 --- a/src/d/actor/d_a_obj_flag.cpp +++ b/src/d/actor/d_a_obj_flag.cpp @@ -16,7 +16,7 @@ daObjFlag_c::M_attrs const daObjFlag_c::M_attr = { }; void daObjFlag_c::create_init() { - field_0x5dc = (*(u32*)dComIfG_getObjectRes(daSetBgObj_c::getArcName(this), "spec.dat")) & 0xffff; + field_0x5dc = (*(BE(u32)*)dComIfG_getObjectRes(daSetBgObj_c::getArcName(this), "spec.dat")) & 0xffff; mPos = cXyz(current.pos.x, current.pos.y + field_0x5dc, current.pos.z); mFlagJoints[0].mRv = (short)(cM_rnd() * 65535.0f); mFlagJoints[1].mRv = (short)(cM_rnd() * 65535.0f); diff --git a/src/d/actor/d_a_obj_flag2.cpp b/src/d/actor/d_a_obj_flag2.cpp index b4f89cd39a..4741f4d5a3 100644 --- a/src/d/actor/d_a_obj_flag2.cpp +++ b/src/d/actor/d_a_obj_flag2.cpp @@ -274,9 +274,9 @@ void FlagCloth_c::draw() { GXSetVtxAttrFmt(GX_VTXFMT0, GX_VA_POS, GX_CLR_RGBA, GX_F32, 0); GXSetVtxAttrFmt(GX_VTXFMT0, GX_VA_NRM, GX_CLR_RGB, GX_F32, 0); GXSetVtxAttrFmt(GX_VTXFMT0, GX_VA_TEX0, GX_CLR_RGBA, GX_F32, 0); - GXSETARRAY(GX_VA_POS, getPos(), sizeof(mPositions), sizeof(cXyz)); - GXSETARRAY(GX_VA_NRM, getNormal(), sizeof(mNormals), sizeof(cXyz)); - GXSETARRAY(GX_VA_TEX0, mpTexCoord, sizeof(mpTexCoord), 8); + GXSETARRAY(GX_VA_POS, getPos(), sizeof(mPositions), sizeof(cXyz), true); + GXSETARRAY(GX_VA_NRM, getNormal(), sizeof(mNormals), sizeof(cXyz), true); + GXSETARRAY(GX_VA_TEX0, mpTexCoord, sizeof(l_texCoord), 8, true); GXSetZCompLoc(GX_FALSE); GXSetZMode(GX_TRUE, GX_LEQUAL, GX_TRUE); GXLoadTexObj(&mTexObj, GX_TEXMAP0); @@ -304,7 +304,7 @@ void FlagCloth_c::draw() { GXSetClipMode(GX_CLIP_ENABLE); GXSetCullMode(GX_CULL_BACK); GXCallDisplayList(l_pennant_flagDL, 0x80); - GXSETARRAY(GX_VA_NRM, getNormalBack(), sizeof(mNormalBacks), sizeof(cXyz)); + GXSETARRAY(GX_VA_NRM, getNormalBack(), sizeof(mNormalBacks), sizeof(cXyz), true); GXSetCullMode(GX_CULL_FRONT); GXCallDisplayList(l_pennant_flagDL, 0x80); J3DShape::resetVcdVatCache(); diff --git a/src/d/actor/d_a_obj_flag3.cpp b/src/d/actor/d_a_obj_flag3.cpp index 7337a4b97d..fc696db1ab 100644 --- a/src/d/actor/d_a_obj_flag3.cpp +++ b/src/d/actor/d_a_obj_flag3.cpp @@ -233,9 +233,9 @@ inline void FlagCloth2_c::draw() { GXSetVtxAttrFmt(GX_VTXFMT0, GX_VA_POS, GX_CLR_RGBA, GX_F32, 0); GXSetVtxAttrFmt(GX_VTXFMT0, GX_VA_NRM, GX_CLR_RGB, GX_F32, 0); GXSetVtxAttrFmt(GX_VTXFMT0, GX_VA_TEX0, GX_CLR_RGBA, GX_F32, 0); - GXSETARRAY(GX_VA_POS, getPos(), sizeof(mPositions), sizeof(cXyz)); - GXSETARRAY(GX_VA_NRM, getNormal(), sizeof(mNormals), sizeof(cXyz)); - GXSETARRAY(GX_VA_TEX0, mTexCoord, sizeof(mTexCoord), 8); + GXSETARRAY(GX_VA_POS, getPos(), sizeof(mPositions), sizeof(cXyz), true); + GXSETARRAY(GX_VA_NRM, getNormal(), sizeof(mNormals), sizeof(cXyz), true); + GXSETARRAY(GX_VA_TEX0, mTexCoord, sizeof(mTexCoord), 8, true); GXSetZCompLoc(GX_FALSE); GXSetZMode(GX_TRUE, GX_LEQUAL, GX_TRUE); GXLoadTexObj(&mTexObj, GX_TEXMAP0); @@ -276,7 +276,7 @@ inline void FlagCloth2_c::draw() { GXEnd(); } - GXSETARRAY(GX_VA_NRM, getNormalBack(), sizeof(mNormalBacks), sizeof(cXyz)); + GXSETARRAY(GX_VA_NRM, getNormalBack(), sizeof(mNormalBacks), sizeof(cXyz), true); GXSetCullMode(GX_CULL_FRONT); for (int i = 0; i < 5; i++) { diff --git a/src/d/actor/d_a_obj_gomikabe.cpp b/src/d/actor/d_a_obj_gomikabe.cpp index 66963f0efd..a5b58a44a5 100644 --- a/src/d/actor/d_a_obj_gomikabe.cpp +++ b/src/d/actor/d_a_obj_gomikabe.cpp @@ -201,7 +201,13 @@ void daObjGOMIKABE_c::CheckCull() { bool daObjGOMIKABE_c::checkViewArea(cXyz param_1) { Vec local_24; + + #if TARGET_PC + mDoLib_project(¶m_1, &local_24, {0, 0, FB_WIDTH, FB_HEIGHT}); + #else mDoLib_project(¶m_1, &local_24); + #endif + bool rv = false; if (local_24.x >= 0.0f && local_24.x <= FB_WIDTH && local_24.y >= 0.0f && local_24.y <= FB_HEIGHT) { rv = true; diff --git a/src/d/actor/d_a_obj_groundwater.cpp b/src/d/actor/d_a_obj_groundwater.cpp index 2d3d05a36c..ab6b7af922 100644 --- a/src/d/actor/d_a_obj_groundwater.cpp +++ b/src/d/actor/d_a_obj_groundwater.cpp @@ -300,11 +300,19 @@ int daGrdWater_c::Draw() { J3DTexMtxInfo* mtxInfo = &material->getTexGenBlock()->getTexMtx(0)->getTexMtxInfo(); if (mtxInfo != NULL) { Mtx afStack_50; + + #if TARGET_PC + C_MTXLightPerspective(afStack_50, dComIfGd_getView()->fovy, dComIfGd_getView()->aspect, + 1.0f, 1.0f, dusk::getSettings().game.useWaterProjectionOffset ? -0.01f : 0.0f, 0.0f); + #else C_MTXLightPerspective(afStack_50, dComIfGd_getView()->fovy, dComIfGd_getView()->aspect, 1.0f, 1.0f, -0.01f, 0.0f); + #endif + #if WIDESCREEN_SUPPORT mDoGph_gInf_c::setWideZoomLightProjection(afStack_50); #endif + mtxInfo->setEffectMtx(afStack_50); modelData2->simpleCalcMaterial(0, (MtxP)j3dDefaultMtx); } diff --git a/src/d/actor/d_a_obj_hhashi.cpp b/src/d/actor/d_a_obj_hhashi.cpp index d5ab5558b0..ea45fa5ea1 100644 --- a/src/d/actor/d_a_obj_hhashi.cpp +++ b/src/d/actor/d_a_obj_hhashi.cpp @@ -214,7 +214,13 @@ void daObjHHASHI_c::CheckCull() { bool daObjHHASHI_c::checkViewArea(int param_1) { Vec local_20; + + #if TARGET_PC + mDoLib_project(&field_0x5b0[param_1], &local_20, {0, 0, FB_WIDTH, FB_HEIGHT}); + #else mDoLib_project(&field_0x5b0[param_1], &local_20); + #endif + bool rv = false; if (local_20.x >= 0.0f && local_20.x <= FB_WIDTH && local_20.y >= 0.0f && local_20.y <= FB_HEIGHT) { rv = true; diff --git a/src/d/actor/d_a_obj_inobone.cpp b/src/d/actor/d_a_obj_inobone.cpp index d73c5e5f9f..2076405828 100644 --- a/src/d/actor/d_a_obj_inobone.cpp +++ b/src/d/actor/d_a_obj_inobone.cpp @@ -89,8 +89,8 @@ static void* s_boar_sub(void* i_actor, void* i_data) { return NULL; } -static void CheckCreateHeap(fopAc_ac_c* i_this) { - static_cast(i_this)->CreateHeap(); +static int CheckCreateHeap(fopAc_ac_c* i_this) { + return static_cast(i_this)->CreateHeap(); } void daObjIBone_c::initBaseMtx() { @@ -150,7 +150,7 @@ int daObjIBone_c::create() { int result = dComIfG_resLoad(&mPhase, l_arcName); if (result == cPhs_COMPLEATE_e) { - if (!fopAcM_entrySolidHeap(this, (heapCallbackFunc)CheckCreateHeap, 0x860)) { + if (!fopAcM_entrySolidHeap(this, CheckCreateHeap, 0x860)) { return cPhs_ERROR_e; } else if (!Create()) { return cPhs_ERROR_e; diff --git a/src/d/actor/d_a_obj_kamakiri.cpp b/src/d/actor/d_a_obj_kamakiri.cpp index 2b641d7769..daa6560e6f 100644 --- a/src/d/actor/d_a_obj_kamakiri.cpp +++ b/src/d/actor/d_a_obj_kamakiri.cpp @@ -517,7 +517,13 @@ void daObjKAM_c::Z_BufferChk() { cXyz currentOffset; currentOffset = current.pos; currentOffset.y += 20.0f; + + #if TARGET_PC + mDoLib_project(¤tOffset, ¤tProj, {0, 0, FB_WIDTH, FB_HEIGHT}); + #else mDoLib_project(¤tOffset, ¤tProj); + #endif + camera_process_class* camera = dComIfGp_getCamera(0); f32 cameraHeight; if (camera != NULL) { diff --git a/src/d/actor/d_a_obj_katatsumuri.cpp b/src/d/actor/d_a_obj_katatsumuri.cpp index 8b85644d80..03d40a1066 100644 --- a/src/d/actor/d_a_obj_katatsumuri.cpp +++ b/src/d/actor/d_a_obj_katatsumuri.cpp @@ -611,7 +611,12 @@ void daObjKAT_c::Z_BufferChk() { cXyz curWithOff; curWithOff = current.pos; curWithOff.y += 20.0f; + + #if TARGET_PC + mDoLib_project(&curWithOff, &projected, {0, 0, FB_WIDTH, FB_HEIGHT}); + #else mDoLib_project(&curWithOff, &projected); + #endif camera_process_class* camera = dComIfGp_getCamera(0); f32 unkFloat1; diff --git a/src/d/actor/d_a_obj_kuwagata.cpp b/src/d/actor/d_a_obj_kuwagata.cpp index ddb00d443d..914e25dfb1 100644 --- a/src/d/actor/d_a_obj_kuwagata.cpp +++ b/src/d/actor/d_a_obj_kuwagata.cpp @@ -528,7 +528,12 @@ void daObjKUW_c::Z_BufferChk() { cStack_68 = current.pos; cStack_68.y += 20.0f; + + #if TARGET_PC + mDoLib_project(&cStack_68, &local_5c, {0, 0, FB_WIDTH, FB_HEIGHT}); + #else mDoLib_project(&cStack_68, &local_5c); + #endif camera_process_class* cc = dComIfGp_getCamera(0); f32 trimHeight; diff --git a/src/d/actor/d_a_obj_lv3Water.cpp b/src/d/actor/d_a_obj_lv3Water.cpp index a228b2cbc8..934cb3140d 100644 --- a/src/d/actor/d_a_obj_lv3Water.cpp +++ b/src/d/actor/d_a_obj_lv3Water.cpp @@ -371,8 +371,14 @@ int daLv3Water_c::Draw() { texMtxInfo = &material->getTexGenBlock()->getTexMtx(0)->getTexMtxInfo(); if (texMtxInfo != NULL) { Mtx lightProjMtx; + + #if TARGET_PC + C_MTXLightPerspective(lightProjMtx, dComIfGd_getView()->fovy, + dComIfGd_getView()->aspect, 1.0f, 1.0f, dusk::getSettings().game.useWaterProjectionOffset ? -0.01f : 0.0f, 0.0f); + #else C_MTXLightPerspective(lightProjMtx, dComIfGd_getView()->fovy, dComIfGd_getView()->aspect, 1.0f, 1.0f, -0.01f, 0.0f); + #endif #if WIDESCREEN_SUPPORT mDoGph_gInf_c::setWideZoomLightProjection(lightProjMtx); diff --git a/src/d/actor/d_a_obj_lv3Water2.cpp b/src/d/actor/d_a_obj_lv3Water2.cpp index b6814875cc..55fc94d605 100644 --- a/src/d/actor/d_a_obj_lv3Water2.cpp +++ b/src/d/actor/d_a_obj_lv3Water2.cpp @@ -197,7 +197,13 @@ int daLv3Water2_c::Draw() { texMtxInfo = &btkMaterial->getTexGenBlock()->getTexMtx(0)->getTexMtxInfo(); if(texMtxInfo) { Mtx lightProjMtx; + + #if TARGET_PC + C_MTXLightPerspective(lightProjMtx, dComIfGd_getView()->fovy, + dComIfGd_getView()->aspect, 1.0f, 1.0f, dusk::getSettings().game.useWaterProjectionOffset ? -0.01f : 0.0f, 0); + #else C_MTXLightPerspective(lightProjMtx, dComIfGd_getView()->fovy, dComIfGd_getView()->aspect, 1.0f, 1.0f, -0.01f, 0); + #endif #if WIDESCREEN_SUPPORT mDoGph_gInf_c::setWideZoomLightProjection(lightProjMtx); diff --git a/src/d/actor/d_a_obj_lv3WaterB.cpp b/src/d/actor/d_a_obj_lv3WaterB.cpp index f4ad49685d..33285d975f 100644 --- a/src/d/actor/d_a_obj_lv3WaterB.cpp +++ b/src/d/actor/d_a_obj_lv3WaterB.cpp @@ -27,8 +27,15 @@ static int daObj_Lv3waterB_Draw(obj_lv3WaterB_class* i_this) { J3DTexMtxInfo* tex_mtx_info = &material_p->getTexGenBlock()->getTexMtx(0)->getTexMtxInfo(); if (tex_mtx_info != NULL) { Mtx m; + + #if TARGET_PC + C_MTXLightPerspective(m, dComIfGd_getView()->fovy, dComIfGd_getView()->aspect, 1.0f, 1.0f, + dusk::getSettings().game.useWaterProjectionOffset ? -0.015f : 0.0f, 0.0f); + #else C_MTXLightPerspective(m, dComIfGd_getView()->fovy, dComIfGd_getView()->aspect, 1.0f, 1.0f, -0.015f, 0.0f); + #endif + #if WIDESCREEN_SUPPORT mDoGph_gInf_c::setWideZoomLightProjection(m); #endif diff --git a/src/d/actor/d_a_obj_rstair.cpp b/src/d/actor/d_a_obj_rstair.cpp index 609a0cf7b8..7e44cc3700 100644 --- a/src/d/actor/d_a_obj_rstair.cpp +++ b/src/d/actor/d_a_obj_rstair.cpp @@ -313,8 +313,15 @@ int daObjRotStair_c::Draw() { J3DTexMtxInfo* texMtxInfo = &material->getTexGenBlock()->getTexMtx(0)->getTexMtxInfo(); if (texMtxInfo != NULL) { Mtx lightMtx; + + #if TARGET_PC + C_MTXLightPerspective(lightMtx, dComIfGd_getView()->fovy, + dComIfGd_getView()->aspect, 1.0f, 1.0f, dusk::getSettings().game.useWaterProjectionOffset ? -0.01f : 0.0f, 0); + #else C_MTXLightPerspective(lightMtx, dComIfGd_getView()->fovy, dComIfGd_getView()->aspect, 1.0f, 1.0f, -0.01f, 0); + #endif + #if WIDESCREEN_SUPPORT mDoGph_gInf_c::setWideZoomLightProjection(lightMtx); #endif diff --git a/src/d/actor/d_a_obj_stick.cpp b/src/d/actor/d_a_obj_stick.cpp index 2e448c1579..d6aa8d1e22 100644 --- a/src/d/actor/d_a_obj_stick.cpp +++ b/src/d/actor/d_a_obj_stick.cpp @@ -198,24 +198,24 @@ void daObj_Stick_c::setMtx() { mpModel->setBaseTRMtx(mDoMtx_stack_c::get()); } -static u32 daObj_Stick_Create(void* i_this) { +static int daObj_Stick_Create(void* i_this) { return static_cast(i_this)->create(); } -static void daObj_Stick_Delete(void* param_0) { - static_cast(param_0)->Delete(); +static int daObj_Stick_Delete(void* param_0) { + return static_cast(param_0)->Delete(); } -static void daObj_Stick_Execute(void* param_0) { - static_cast(param_0)->Execute(); +static int daObj_Stick_Execute(void* param_0) { + return static_cast(param_0)->Execute(); } -static void daObj_Stick_Draw(void* param_0) { - static_cast(param_0)->Draw(); +static int daObj_Stick_Draw(void* param_0) { + return static_cast(param_0)->Draw(); } -static BOOL daObj_Stick_IsDelete(void* param_0) { - return TRUE; +static int daObj_Stick_IsDelete(void* param_0) { + return 1; } static actor_method_class daObj_Stick_MethodTable = { diff --git a/src/d/actor/d_a_obj_stone.cpp b/src/d/actor/d_a_obj_stone.cpp index 5cf5716873..f74adf12a7 100644 --- a/src/d/actor/d_a_obj_stone.cpp +++ b/src/d/actor/d_a_obj_stone.cpp @@ -126,7 +126,7 @@ static f32 bound(cXyz* param_0, cBgS_PolyInfo const& param_1, f32 param_2) { cXyz pos; f32 abs = param_0->abs(); - C_VECReflect(param_0, (Vec*)&plane, &pos); + C_VECReflect(param_0, &plane.mNormal, &pos); *param_0 = pos * abs * param_2; return param_0->absXZ(); diff --git a/src/d/actor/d_a_obj_ten.cpp b/src/d/actor/d_a_obj_ten.cpp index fbedd6a8c9..1efe358607 100644 --- a/src/d/actor/d_a_obj_ten.cpp +++ b/src/d/actor/d_a_obj_ten.cpp @@ -593,7 +593,13 @@ void daObjTEN_c::Z_BufferChk() { cXyz cStack_68; cStack_68 = current.pos; cStack_68.y += 20.0f; + + #if TARGET_PC + mDoLib_project(&cStack_68, &local_5c, {0, 0, FB_WIDTH, FB_HEIGHT}); + #else mDoLib_project(&cStack_68, &local_5c); + #endif + camera_process_class* camera = dComIfGp_getCamera(0); f32 trimHeight; if (camera != NULL) { diff --git a/src/d/actor/d_a_obj_tombo.cpp b/src/d/actor/d_a_obj_tombo.cpp index 092b1c46c3..48db14ac92 100644 --- a/src/d/actor/d_a_obj_tombo.cpp +++ b/src/d/actor/d_a_obj_tombo.cpp @@ -504,7 +504,13 @@ void daObjTOMBO_c::Z_BufferChk() { cXyz cStack_68; cStack_68 = current.pos; cStack_68.y += 20.0f; + + #if TARGET_PC + mDoLib_project(&cStack_68, &local_5c, {0, 0, FB_WIDTH, FB_HEIGHT}); + #else mDoLib_project(&cStack_68, &local_5c); + #endif + camera_process_class* pCamera = dComIfGp_getCamera(0); f32 trimHeight; if (pCamera != NULL) { diff --git a/src/d/actor/d_a_obj_tp.cpp b/src/d/actor/d_a_obj_tp.cpp index 2690de3e04..e2ede47b15 100644 --- a/src/d/actor/d_a_obj_tp.cpp +++ b/src/d/actor/d_a_obj_tp.cpp @@ -36,8 +36,15 @@ static int daObj_Tp_Draw(obj_tp_class* i_this) { &material->getTexGenBlock()->getTexMtx(0)->getTexMtxInfo(); if (texMtxInfo != NULL) { Mtx lightProjMtx; + + #if TARGET_PC + C_MTXLightPerspective(lightProjMtx, dComIfGd_getView()->fovy, + dComIfGd_getView()->aspect, 1.0f, 1.0f, dusk::getSettings().game.useWaterProjectionOffset ? -0.01f : 0.0f, 0); + #else C_MTXLightPerspective(lightProjMtx, dComIfGd_getView()->fovy, dComIfGd_getView()->aspect, 1.0f, 1.0f, -0.01f, 0); + #endif + #if WIDESCREEN_SUPPORT mDoGph_gInf_c::setWideZoomLightProjection(lightProjMtx); #endif diff --git a/src/d/actor/d_a_obj_zra_freeze.cpp b/src/d/actor/d_a_obj_zra_freeze.cpp index 1525bdb572..08932c439d 100644 --- a/src/d/actor/d_a_obj_zra_freeze.cpp +++ b/src/d/actor/d_a_obj_zra_freeze.cpp @@ -38,7 +38,12 @@ BOOL daZraFreeze_c::chkActorInScreen() { mDoMtx_stack_c::transM(0.0f, 0.0f, 0.0f); PSMTXMultVecArray(mDoMtx_stack_c::get(), vec, vec, 8); for (int i = 0; i < 8; i++) { + #if TARGET_PC + mDoLib_project(&vec[i], &proj, {0, 0, FB_WIDTH, FB_HEIGHT}); + #else mDoLib_project(&vec[i], &proj); + #endif + if (0.0f < proj.x && proj.x < FB_WIDTH && 0.0f < proj.y && proj.y < FB_HEIGHT) { continue; } diff --git a/src/d/actor/d_a_peru.cpp b/src/d/actor/d_a_peru.cpp index 7d2a7c39bb..b02c740c06 100644 --- a/src/d/actor/d_a_peru.cpp +++ b/src/d/actor/d_a_peru.cpp @@ -59,7 +59,7 @@ static daNpcT_motionAnmData_c l_motionAnmData[11] = { static daNpcT_MotionSeqMngr_c::sequenceStepData_c l_faceMotionSequenceData[20] = { {1, -1, 1}, {-1, 0, 0}, {-1, 0, 0}, {-1, 0, 0}, {2, -1, 0}, {-1, 0, 0}, {-1, 0, 0}, {-1, 0, 0}, {0, -1, 0}, {-1, 0, 0}, {-1, 0, 0}, {-1, 0, 0}, {3, -1, 0}, {-1, 0, 0}, {-1, 0, 0}, {-1, 0, 0}, - {4, -1, 0}, {-1, 0, 0}, {-1, 0, 0}, {-1, 0, 0}, + {4, -1, 0}, {-1, 0, 0}, {-1, 0, 0}, {-1, 0, 0}, }; static daNpcT_MotionSeqMngr_c::sequenceStepData_c l_motionSequenceData[40] = { diff --git a/src/d/actor/d_a_player.cpp b/src/d/actor/d_a_player.cpp index f38fe15a3b..4c8b31c4c6 100644 --- a/src/d/actor/d_a_player.cpp +++ b/src/d/actor/d_a_player.cpp @@ -237,11 +237,7 @@ void* daPy_anmHeap_c::mallocBuffer() { return mBuffer; } -#if TARGET_PC void daPy_anmHeap_c::createHeap(daPy_anmHeap_c::daAlinkHEAP_TYPE i_heapType, const char* name) { -#else -void daPy_anmHeap_c::createHeap(daPy_anmHeap_c::daAlinkHEAP_TYPE i_heapType, const char* name) { -#endif u32 size; if (i_heapType == 4) { @@ -255,6 +251,9 @@ void daPy_anmHeap_c::createHeap(daPy_anmHeap_c::daAlinkHEAP_TYPE i_heapType, con } else { size = 0xA0; } +#if TARGET_PC + size *= 2; +#endif char* tmpWork; mDoExt_transAnmBas* tmpTransBas; @@ -368,7 +367,30 @@ JKRHeap* daPy_anmHeap_c::setAnimeHeap() { } #if !PLATFORM_WII +#if TARGET_PC +#include "dusk/dvd_asset.hpp" +static const u8* l_sightDL_get() { + static u8 buf[0x89]; + static bool _ = ( + dusk::LoadDolAsset( + buf, + #if VERSION == VERSION_GCN_PAL + 0x803BBDA0, + #elif VERSION == VERSION_GCN_JPN + 0x803B4220, + #elif VERSION == VERSION_GCN_USA + 0x803BA0C0, + #endif + 0x89 + ), + true + ); + return buf; +} +#define l_sightDL (l_sightDL_get()) +#else #include "assets/l_sightDL__d_a_player.h" +#endif void daPy_sightPacket_c::draw() { TGXTexObj texObj; diff --git a/src/d/actor/d_a_tag_magne.cpp b/src/d/actor/d_a_tag_magne.cpp index 8b47511eeb..ca74c0655a 100644 --- a/src/d/actor/d_a_tag_magne.cpp +++ b/src/d/actor/d_a_tag_magne.cpp @@ -44,15 +44,15 @@ int daTagMagne_c::_delete() { return 1; } -static void daTagMagne_Delete(daTagMagne_c* i_this) { +static int daTagMagne_Delete(daTagMagne_c* i_this) { int id = fopAcM_GetID(i_this); - i_this->_delete(); + return i_this->_delete(); } -static void daTagMagne_Create(fopAc_ac_c* i_this) { +static int daTagMagne_Create(fopAc_ac_c* i_this) { daTagMagne_c* magne = static_cast(i_this); int id = fopAcM_GetID(i_this); - magne->create(); + return magne->create(); } static actor_method_class l_daTagMagne_Method = { diff --git a/src/d/actor/d_a_tag_sppath.cpp b/src/d/actor/d_a_tag_sppath.cpp index 81fbe04184..9fdb00fe55 100644 --- a/src/d/actor/d_a_tag_sppath.cpp +++ b/src/d/actor/d_a_tag_sppath.cpp @@ -189,7 +189,7 @@ int daTagSppath_c::execute() { } if (mpBestPath->field_0x4 == 0) { - if (mpBestPath->field_0x6 == 0xff || fopAcM_isSwitch(this, mpBestPath->field_0x6) == 0) { + if (mpBestPath->swbit == 0xff || fopAcM_isSwitch(this, mpBestPath->swbit) == 0) { field_0x6e8 = 1; } else { field_0x6e8 = 2; diff --git a/src/d/actor/d_a_tbox.cpp b/src/d/actor/d_a_tbox.cpp index b936b9b6e7..6cad41b4e3 100644 --- a/src/d/actor/d_a_tbox.cpp +++ b/src/d/actor/d_a_tbox.cpp @@ -650,7 +650,7 @@ void daTbox_c::dropProcInit() { field_0x97c = false; f32 delta_y = pos.y - pnt1.y; - f32 abs_gravity = std::fabsf(fopAcM_GetGravity(this)); + f32 abs_gravity = fabsf(fopAcM_GetGravity(this)); var_f30 = JMAFastSqrt(2.0f * delta_y / abs_gravity); speedF = pos.absXZ(pnt1) / var_f30; diff --git a/src/d/actor/d_flower.inc b/src/d/actor/d_flower.inc index 13bc1ad251..4fb53ffaa7 100644 --- a/src/d/actor/d_flower.inc +++ b/src/d/actor/d_flower.inc @@ -5,9 +5,21 @@ #include "JSystem/J3DGraphBase/J3DDrawBuffer.h" #include "SSystem/SComponent/c_counter.h" +#if TARGET_PC +const u16 l_J_Ohana00_64TEX__width = 64; +const u16 l_J_Ohana00_64TEX__height = 64; +#else const u16 l_J_Ohana00_64TEX__width = 63; const u16 l_J_Ohana00_64TEX__height = 63; +#endif + +#if TARGET_PC +#include "dusk/dvd_asset.hpp" +static u8* l_J_Ohana00_64TEX_get() { static u8 buf[0x800]; static bool _ = (dusk::LoadArchivedRelAsset(buf, 'AMEM', "d_a_grass.rel", 0x9060, 0x800), true); return buf; } +#define l_J_Ohana00_64TEX (l_J_Ohana00_64TEX_get()) +#else #include "assets/l_J_Ohana00_64TEX.h" +#endif static u8 l_flowerPos[708] = { 0xC0, 0x8C, 0x2C, 0xF7, 0x42, 0x05, 0xBC, 0xDF, 0xC1, 0xA1, 0x00, 0x70, 0xBF, 0x50, 0x51, 0xB9, @@ -72,8 +84,8 @@ static u8 l_flowerNormal[180] = { 0x46, 0x54, 0x0D, 0x3C, 0x4B, 0xEE, 0x80, 0x3F, 0x7F, 0xF5, 0xF9, 0x3C, 0x49, 0x81, 0xBF, }; -static u8 l_flowerColor[8] = { - 0xFF, 0xFF, 0xFF, 0xFF, 0xB2, 0xB2, 0xB2, 0xFF, +static GXColor l_flowerColor[2] = { + {0xFF, 0xFF, 0xFF, 0xFF}, {0xB2, 0xB2, 0xB2, 0xFF} }; static u8 l_flowerTexCoord[] = { @@ -98,6 +110,16 @@ static u8 l_flowerTexCoord[] = { 0x3E, 0xA7, 0x67, 0x4D, 0x3C, 0x14, 0x46, 0x74, 0x3E, 0xA7, 0x73, 0xE2, 0xBC, 0x2F, 0x46, 0xAA, 0x3E, 0xA7, 0x72, 0xD6, 0xBD, 0x2F, 0x46, 0xAA}; +#if TARGET_PC +static u8* l_J_hana00DL_get() { static u8 buf[0x150]; static bool _ = (dusk::LoadArchivedRelAsset(buf, 'AMEM', "d_a_grass.rel", 0x9D20, 0x150), true); return buf; } +static u8* l_J_hana00_cDL_get() { static u8 buf[0xDE]; static bool _ = (dusk::LoadArchivedRelAsset(buf, 'AMEM', "d_a_grass.rel", 0x9E80, 0xDE), true); return buf; } +static u8* l_matDL_get() { static u8 buf[0x99]; static bool _ = (dusk::LoadArchivedRelAsset(buf, 'AMEM', "d_a_grass.rel", 0x9F60, 0x99), true); return buf; } +static u8* l_matLight4DL_get() { static u8 buf[0x99]; static bool _ = (dusk::LoadArchivedRelAsset(buf, 'AMEM', "d_a_grass.rel", 0xA000, 0x99), true); return buf; } +#define l_J_hana00DL (l_J_hana00DL_get()) +#define l_J_hana00_cDL (l_J_hana00_cDL_get()) +#define l_matDL (l_matDL_get()) +#define l_matLight4DL (l_matLight4DL_get()) +#else #include "assets/l_J_hana00DL.h" #include "assets/l_J_hana00_cDL.h" @@ -107,10 +129,22 @@ l_matDL__d_a_grass(l_J_Ohana00_64TEX) #include "assets/l_matLight4DL.h" l_matLight4DL(l_J_Ohana00_64TEX) +#endif +#if TARGET_PC +const u16 l_J_Ohana01_64128_0419TEX__width = 64; +const u16 l_J_Ohana01_64128_0419TEX__height = 128; +#else const u16 l_J_Ohana01_64128_0419TEX__width = 63; const u16 l_J_Ohana01_64128_0419TEX__height = 127; +#endif + +#if TARGET_PC +static u8* l_J_Ohana01_64128_0419TEX_get() { static u8 buf[0x1000]; static bool _ = (dusk::LoadArchivedRelAsset(buf, 'AMEM', "d_a_grass.rel", 0xA0A0, 0x1000), true); return buf; } +#define l_J_Ohana01_64128_0419TEX (l_J_Ohana01_64128_0419TEX_get()) +#else #include "assets/l_J_Ohana01_64128_0419TEX.h" +#endif static u8 l_flowerPos2[1224] = { 0x40, 0x25, 0x9F, 0x34, 0x42, 0xC2, 0x95, 0x72, 0xC1, 0x22, 0x34, 0x78, 0x41, 0x4D, 0xF9, 0x63, @@ -213,8 +247,8 @@ static u8 l_flowerNormal2[288] = { 0x3B, 0x76, 0x7B, 0x1C, 0x3B, 0x99, 0x6B, 0x76, 0x3F, 0x7F, 0xF5, 0xF9, 0xBC, 0x8A, 0x1D, 0xFC, }; -static u8 l_flowerColor2[8] = { - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xB2, 0xFF, +static GXColor l_flowerColor2[2] = { + {0xFF, 0xFF, 0xFF, 0xFF}, {0xFF, 0xFF, 0xB2, 0xFF} }; static u8 l_flowerTexCoord2[] = { @@ -237,6 +271,18 @@ static u8 l_flowerTexCoord2[] = { 0x40, 0x1B, 0x7D, 0x52, 0x3F, 0x97, 0xF6, 0xBA, 0x40, 0x04, 0x26, 0x74, 0x3F, 0x80, 0x3F, 0x79, 0x40, 0x1B, 0x7D, 0x52, 0x3F, 0x80, 0x3F, 0x79, 0x40, 0x1B, 0x7D, 0x52, 0x3F, 0x51, 0x10, 0x6F}; +#if TARGET_PC +static u8* l_J_hana01DL_get() { static u8 buf[0x138]; static bool _ = (dusk::LoadArchivedRelAsset(buf, 'AMEM', "d_a_grass.rel", 0xB7C0, 0x138), true); return buf; } +static u8* l_J_hana01_c_00DL_get() { static u8 buf[0xDE]; static bool _ = (dusk::LoadArchivedRelAsset(buf, 'AMEM', "d_a_grass.rel", 0xB900, 0xDE), true); return buf; } +static u8* l_J_hana01_c_01DL_get() { static u8 buf[0x128]; static bool _ = (dusk::LoadArchivedRelAsset(buf, 'AMEM', "d_a_grass.rel", 0xB9E0, 0x128), true); return buf; } +static u8* l_mat2DL_get() { static u8 buf[0x99]; static bool _ = (dusk::LoadArchivedRelAsset(buf, 'AMEM', "d_a_grass.rel", 0xBB20, 0x99), true); return buf; } +static u8* l_mat2Light4DL_get() { static u8 buf[0x99]; static bool _ = (dusk::LoadArchivedRelAsset(buf, 'AMEM', "d_a_grass.rel", 0xBBC0, 0x99), true); return buf; } +#define l_J_hana01DL (l_J_hana01DL_get()) +#define l_J_hana01_c_00DL (l_J_hana01_c_00DL_get()) +#define l_J_hana01_c_01DL (l_J_hana01_c_01DL_get()) +#define l_mat2DL (l_mat2DL_get()) +#define l_mat2Light4DL (l_mat2Light4DL_get()) +#else #include "assets/l_J_hana01DL.h" #include "assets/l_J_hana01_c_00DL.h" @@ -248,6 +294,7 @@ l_mat2DL__d_a_grass(l_J_Ohana01_64128_0419TEX) #include "assets/l_mat2Light4DL.h" l_mat2Light4DL(l_J_Ohana01_64128_0419TEX) +#endif void dFlower_data_c::WorkCo(fopAc_ac_c* i_hitActor, u32 i_massFlg, int i_roomNo) { cXyz sp8; @@ -509,6 +556,42 @@ dFlower_packet_c::dFlower_packet_c() { unused += 0x2000; } +#if TARGET_LITTLE_ENDIAN + static bool initialized = false; + if (!initialized) { + for (int i = 0; i < (ARRAY_SIZE(l_flowerPos) / sizeof(Vec)); i++) { + be_swap(((Vec*)l_flowerPos)[i]); + } + for (int i = 0; i < (ARRAY_SIZE(l_flowerTexCoord) / sizeof(Vec)); i++) { + be_swap(((Vec*)l_flowerTexCoord)[i]); + } + for (int i = 0; i < (ARRAY_SIZE(l_flowerPos2) / sizeof(Vec)); i++) { + be_swap(((Vec*)l_flowerPos2)[i]); + } + for (int i = 0; i < (ARRAY_SIZE(l_flowerTexCoord2) / sizeof(Vec)); i++) { + be_swap(((Vec*)l_flowerTexCoord2)[i]); + } + for (int i = 0; i < (ARRAY_SIZE(l_flowerNormal) / sizeof(Vec)); i++) { + be_swap(((Vec*)l_flowerNormal)[i]); + } + for (int i = 0; i < (ARRAY_SIZE(l_flowerNormal2) / sizeof(Vec)); i++) { + be_swap(((Vec*)l_flowerNormal2)[i]); + } + + initialized = true; + } +#endif + +#if TARGET_PC + GXInitTexObj(&mTexObj_l_J_Ohana00_64TEX, l_J_Ohana00_64TEX, + l_J_Ohana00_64TEX__width, l_J_Ohana00_64TEX__height, GX_TF_CMPR, GX_MIRROR, GX_MIRROR, GX_FALSE + ); + + GXInitTexObj(&mTexObj_l_J_Ohana01_64128_0419TEX, l_J_Ohana01_64128_0419TEX, + l_J_Ohana01_64128_0419TEX__width, l_J_Ohana01_64128_0419TEX__height, GX_TF_CMPR, GX_MIRROR, GX_MIRROR, GX_FALSE + ); +#endif + m_deleteRoom = &dFlower_packet_c::deleteRoom; #if AVOID_UB @@ -531,10 +614,10 @@ void dFlower_packet_c::draw() { GXSetVtxAttrFmt(GX_VTXFMT0, GX_VA_NRM, GX_NRM_XYZ, GX_F32, 0); GXSetVtxAttrFmt(GX_VTXFMT0, GX_VA_CLR0, GX_CLR_RGBA, GX_RGBA8, 0); GXSetVtxAttrFmt(GX_VTXFMT0, GX_VA_TEX0, GX_TEX_ST, GX_F32, 0); - GXSETARRAY(GX_VA_POS, &l_flowerPos, sizeof(l_flowerPos), 0xC); - GXSETARRAY(GX_VA_NRM, &l_flowerNormal, sizeof(l_flowerNormal), 0xC); - GXSETARRAY(GX_VA_CLR0, &l_flowerColor, sizeof(l_flowerColor), 4); - GXSETARRAY(GX_VA_TEX0, &l_flowerTexCoord, sizeof(l_flowerTexCoord), 8); + GXSETARRAY(GX_VA_POS, &l_flowerPos, sizeof(l_flowerPos), sizeof(Vec), true); + GXSETARRAY(GX_VA_NRM, &l_flowerNormal, sizeof(l_flowerNormal), sizeof(Vec), true); + GXSETARRAY(GX_VA_CLR0, &l_flowerColor, sizeof(l_flowerColor), sizeof(GXColor), true); + GXSETARRAY(GX_VA_TEX0, &l_flowerTexCoord, sizeof(l_flowerTexCoord), 8, true); GXColor sp64; dFlower_room_c* sp5C = m_room; @@ -562,9 +645,9 @@ void dFlower_packet_c::draw() { } if (sp4C <= 2) { - GXCallDisplayList(&l_matLight4DL, 0x80); + GXCallDisplayList(l_matLight4DL, 0x80); } else { - GXCallDisplayList(&l_matDL, 0x80); + GXCallDisplayList(l_matDL, 0x80); } GXSetTevColorS10(GX_TEVREG0, sp80); @@ -615,10 +698,14 @@ void dFlower_packet_c::draw() { GXLoadPosMtxImm(sp44->m_modelMtx, 0); GXLoadNrmMtxImm(j3dSys.getViewMtx(), 0); +#if TARGET_PC + GXLoadTexObj(&mTexObj_l_J_Ohana00_64TEX, GX_TEXMAP0); +#endif + if (!cLib_checkBit(sp44->m_state, 8)) { - GXCallDisplayList(&l_J_hana00DL, 0x140); + GXCallDisplayList(l_J_hana00DL, 0x140); } else { - GXCallDisplayList(&l_J_hana00_cDL, 0xC0); + GXCallDisplayList(l_J_hana00_cDL, 0xC0); } } } @@ -626,10 +713,10 @@ void dFlower_packet_c::draw() { sp5C++; } - GXSETARRAY(GX_VA_POS, mp_pos, sizeof(l_flowerPos2), 0xC); - GXSETARRAY(GX_VA_NRM, &l_flowerNormal2, sizeof(l_flowerNormal2), 0xC); - GXSETARRAY(GX_VA_CLR0, mp_colors, sizeof(l_flowerColor2), 4); - GXSETARRAY(GX_VA_TEX0, mp_texCoords, sizeof(l_flowerTexCoord2), 8); + GXSETARRAY(GX_VA_POS, mp_pos, sizeof(l_flowerPos2), sizeof(Vec), true); + GXSETARRAY(GX_VA_NRM, &l_flowerNormal2, sizeof(l_flowerNormal2), sizeof(Vec), true); + GXSETARRAY(GX_VA_CLR0, mp_colors, sizeof(l_flowerColor2), sizeof(GXColor), true); + GXSETARRAY(GX_VA_TEX0, mp_texCoords, sizeof(l_flowerTexCoord2), 8, true); sp5C = m_room; @@ -757,11 +844,15 @@ void dFlower_packet_c::draw() { GXLoadPosMtxImm(sp34->m_modelMtx, 0); GXLoadNrmMtxImm(j3dSys.getViewMtx(), 0); +#if TARGET_PC + GXLoadTexObj(&mTexObj_l_J_Ohana01_64128_0419TEX, GX_TEXMAP0); +#endif + if (!cLib_checkBit(sp34->m_state, 8)) { if (!cLib_checkBit(sp34->m_state, 0x10)) { GXCallDisplayList(mp_Jhana01DL, m_Jhana01DL_size); } else { - GXCallDisplayList(&l_J_hana01_c_00DL, 0xC0); + GXCallDisplayList(l_J_hana01_c_00DL, 0xC0); } } else { GXCallDisplayList(mp_Jhana01_cDL, m_Jhana01_cDL_size); diff --git a/src/d/actor/d_grass.inc b/src/d/actor/d_grass.inc index 2078e917ad..3645488b0f 100644 --- a/src/d/actor/d_grass.inc +++ b/src/d/actor/d_grass.inc @@ -13,11 +13,19 @@ const u16 l_M_Hijiki00TEX__width = 31; const u16 l_M_Hijiki00TEX__height = 31; -#include "assets/l_M_kusa05_RGBATEX.h" // ALIGN 32 - const u16 l_M_kusa05_RGBATEX__width = 31; const u16 l_M_kusa05_RGBATEX__height = 31; -#include "assets/l_M_Hijiki00TEX.h" // ALIGN 32 + +#if TARGET_PC +#include "dusk/dvd_asset.hpp" +static u8* l_M_kusa05_RGBATEX_get() { static u8 buf[0x800]; static bool _ = (dusk::LoadArchivedRelAsset(buf, 'AMEM', "d_a_grass.rel", 0x7680, 0x800), true); return buf; } +static u8* l_M_Hijiki00TEX_get() { static u8 buf[0x800]; static bool _ = (dusk::LoadArchivedRelAsset(buf, 'AMEM', "d_a_grass.rel", 0x7E80, 0x800), true); return buf; } +#define l_M_kusa05_RGBATEX (l_M_kusa05_RGBATEX_get()) +#define l_M_Hijiki00TEX (l_M_Hijiki00TEX_get()) +#else +#include "assets/l_M_kusa05_RGBATEX.h" // ALIGN 32 +#include "assets/l_M_Hijiki00TEX.h" // ALIGN 32 +#endif static u8 l_pos[960] = { 0x3F, 0x4A, 0x56, 0xEF, 0xC2, 0x20, 0x00, 0x00, 0x41, 0xFB, 0x17, 0xE4, 0x41, 0xAA, 0xBB, 0xEA, @@ -102,6 +110,20 @@ static u8 l_texCoord[160] = { 0x3F, 0x94, 0x00, 0x00, 0x3F, 0x80, 0x00, 0x00, 0xBD, 0xC0, 0x00, 0x00, 0x3F, 0x80, 0x00, 0x00, }; +#if TARGET_PC +static u8* l_M_Kusa_9qDL_get() { static u8 buf[0xCB]; static bool _ = (dusk::LoadArchivedRelAsset(buf, 'AMEM', "d_a_grass.rel", 0x8B00, 0xCB), true); return buf; } +static u8* l_M_Kusa_9q_cDL_get() { static u8 buf[0xCB]; static bool _ = (dusk::LoadArchivedRelAsset(buf, 'AMEM', "d_a_grass.rel", 0x8BE0, 0xCB), true); return buf; } +static u8* l_M_TenGusaDL_get() { static u8 buf[0xD4]; static bool _ = (dusk::LoadArchivedRelAsset(buf, 'AMEM', "d_a_grass.rel", 0x8CC0, 0xD4), true); return buf; } +static u8* l_Tengusa_matDL_get() { static u8 buf[0xA8]; static bool _ = (dusk::LoadArchivedRelAsset(buf, 'AMEM', "d_a_grass.rel", 0x8DA0, 0xA8), true); return buf; } +static u8* l_kusa9q_matDL_get() { static u8 buf[0xA8]; static bool _ = (dusk::LoadArchivedRelAsset(buf, 'AMEM', "d_a_grass.rel", 0x8E60, 0xA8), true); return buf; } +static u8* l_kusa9q_l4_matDL_get() { static u8 buf[0xA8]; static bool _ = (dusk::LoadArchivedRelAsset(buf, 'AMEM', "d_a_grass.rel", 0x8F20, 0xA8), true); return buf; } +#define l_M_Kusa_9qDL (l_M_Kusa_9qDL_get()) +#define l_M_Kusa_9q_cDL (l_M_Kusa_9q_cDL_get()) +#define l_M_TenGusaDL (l_M_TenGusaDL_get()) +#define l_Tengusa_matDL (l_Tengusa_matDL_get()) +#define l_kusa9q_matDL (l_kusa9q_matDL_get()) +#define l_kusa9q_l4_matDL (l_kusa9q_l4_matDL_get()) +#else #include "assets/l_M_Kusa_9qDL.h" #include "assets/l_M_Kusa_9q_cDL.h" @@ -117,6 +139,7 @@ l_kusa9q_matDL(l_M_kusa05_RGBATEX) #include "assets/l_kusa9q_l4_matDL.h" l_kusa9q_l4_matDL(l_M_kusa05_RGBATEX) +#endif void dGrass_data_c::WorkCo(fopAc_ac_c* i_hitActor, u32 i_massFlg, int i_roomNo) { cXyz sp18; @@ -536,10 +559,10 @@ void dGrass_packet_c::draw() { GXSetVtxDescv(l_vtxDescList); GXSetVtxAttrFmtv(GX_VTXFMT0, l_vtxAttrFmtList); - GXSETARRAY(GX_VA_POS, mp_pos, sizeof(l_pos), sizeof(Vec)); - GXSETARRAY(GX_VA_NRM, mp_normal, sizeof(l_normal), sizeof(Vec)); - GXSETARRAY(GX_VA_CLR0, mp_colors, sizeof(l_color), sizeof(GXColor)); - GXSETARRAY(GX_VA_TEX0, mp_texCoords, sizeof(l_texCoord), 8); + GXSETARRAY(GX_VA_POS, mp_pos, sizeof(l_pos), sizeof(Vec), true); + GXSETARRAY(GX_VA_NRM, mp_normal, sizeof(l_normal), sizeof(Vec), true); + GXSETARRAY(GX_VA_CLR0, mp_colors, sizeof(l_color), sizeof(GXColor), true); + GXSETARRAY(GX_VA_TEX0, mp_texCoords, sizeof(l_texCoord), 8, true); GXColorS10 spA0 = {0, 0, 0, 0}; GXColorS10 sp98 = {0, 0, 0, 0}; diff --git a/src/d/d_bg_parts.cpp b/src/d/d_bg_parts.cpp index 930c3f63b1..3c378bf325 100644 --- a/src/d/d_bg_parts.cpp +++ b/src/d/d_bg_parts.cpp @@ -106,7 +106,7 @@ void dBgp_c::modelMaterial_c::set(J3DModelData* i_modelData, J3DMaterial* i_mate void dBgp_c::model_c::create(J3DModelData* i_modelData, Mtx i_mtx) { const void* binary = i_modelData->getBinary(); - mId = *(u32*)((char*)binary + 0x1C); + mId = *(BE(u32)*)((char*)binary + 0x1C); if (mId != 0xFFFF) { addShare(mId); } diff --git a/src/d/d_bg_s.cpp b/src/d/d_bg_s.cpp index f218424d30..f48c58fead 100644 --- a/src/d/d_bg_s.cpp +++ b/src/d/d_bg_s.cpp @@ -10,12 +10,14 @@ #include "d/d_bg_w.h" #include "d/d_com_inf_game.h" #include "f_op/f_op_actor_mng.h" -#include "dusk/offset_ptr.h" #include "d/d_debug_viewer.h" #include "d/d_bg_s_capt_poly.h" -#include "dusk/imgui/ImGuiConsole.hpp" +#if TARGET_PC +#include "dusk/offset_ptr.h" +#include "dusk/settings.h" +#endif #if DEBUG int g_ground_counter; @@ -619,8 +621,8 @@ static int poly_draw(dBgS_CaptPoly* capt, cBgD_Vtx_t* vtxList, int v0, int v1, i GXColor wall_color = {0, 0xFF, 0, 0xFF}; #if TARGET_PC - dusk::ImGuiMenuTools::CollisionViewSettings collisionViewSettings = dusk::g_imguiConsole.getCollisionViewSettings(); - f32 view_opacity = 255 * (collisionViewSettings.m_terrainViewOpacity / 100.0f); + const auto& collisionViewSettings = dusk::getTransientSettings().collisionView; + f32 view_opacity = 255 * (collisionViewSettings.terrainViewOpacity / 100.0f); ground_color.a = view_opacity; roof_color.a = view_opacity; wall_color.a = view_opacity; @@ -658,16 +660,16 @@ void dBgS::Draw() { cBgS::Draw(); #if TARGET_PC - #define IMGUI_TOGGLE_HIO_FLAG(status, flag) \ + #define DUSK_TOGGLE_HIO_FLAG(status, flag) \ if (status) { \ s_InsideHio.m_flags |= flag; \ } else { \ s_InsideHio.m_flags &= ~flag; \ } - dusk::ImGuiMenuTools::CollisionViewSettings collisionViewSettings = dusk::g_imguiConsole.getCollisionViewSettings(); - IMGUI_TOGGLE_HIO_FLAG(collisionViewSettings.m_enableTerrainView, dBgS_InsideHIO::FLAG_DISP_POLY_e); - IMGUI_TOGGLE_HIO_FLAG(collisionViewSettings.m_enableWireframe, dBgS_InsideHIO::FLAG_WHITE_WIRE_e); + const auto& collisionViewSettings = dusk::getTransientSettings().collisionView; + DUSK_TOGGLE_HIO_FLAG(collisionViewSettings.enableTerrainView, dBgS_InsideHIO::FLAG_DISP_POLY_e); + DUSK_TOGGLE_HIO_FLAG(collisionViewSettings.enableWireframe, dBgS_InsideHIO::FLAG_WHITE_WIRE_e); #endif if (s_InsideHio.ChkDispPoly()) { @@ -680,8 +682,7 @@ void dBgS::Draw() { f32 var_f31 = fabsf(s_InsideHio.m_p0.x); #if TARGET_PC - dusk::ImGuiMenuTools::CollisionViewSettings collisionViewSettings = dusk::g_imguiConsole.getCollisionViewSettings(); - var_f31 = collisionViewSettings.m_drawRange; + var_f31 = collisionViewSettings.drawRange; #endif min.x = player->current.pos.x - var_f31; diff --git a/src/d/d_bright_check.cpp b/src/d/d_bright_check.cpp index 36f24ebd72..ac28e46838 100644 --- a/src/d/d_bright_check.cpp +++ b/src/d/d_bright_check.cpp @@ -143,7 +143,56 @@ void dBrightCheck_c::modeMove() { } } +#if TARGET_PC +void dBrightCheck_c::brightCheckWide() { + // Main Canvas + mBrightCheck.Scr->scale(mDoGph_gInf_c::hudAspectScaleUp, 1.0f); + mBrightCheck.Scr->translate(mDoGph_gInf_c::getMinXF(), 0.0f); + + // Right Square + mBrightCheck.Scr->search(MULTI_CHAR('fuchi_1'))->scale(mDoGph_gInf_c::hudAspectScaleDown, 1.0f); + mBrightCheck.Scr->search(MULTI_CHAR('big_squa'))->scale(mDoGph_gInf_c::hudAspectScaleDown, 1.0f); + + // Middle Square + mBrightCheck.Scr->search(MULTI_CHAR('fuchi_3'))->scale(mDoGph_gInf_c::hudAspectScaleDown, 1.0f); + mBrightCheck.Scr->search(MULTI_CHAR('big_squ1'))->scale(mDoGph_gInf_c::hudAspectScaleDown, 1.0f); + + // Left Square + mBrightCheck.Scr->search(MULTI_CHAR('fuchi_4'))->scale(mDoGph_gInf_c::hudAspectScaleDown, 1.0f); + mBrightCheck.Scr->search(MULTI_CHAR('big_squ2'))->scale(mDoGph_gInf_c::hudAspectScaleDown, 1.0f); + + // Gray Squares + mBrightCheck.Scr->search(MULTI_CHAR('gray_n'))->scale(mDoGph_gInf_c::hudAspectScaleDown, 1.0f); + mBrightCheck.Scr->search(MULTI_CHAR('fuchi_2'))->scale(mDoGph_gInf_c::hudAspectScaleDown, 1.0f); + + // Confirm A Button + mBrightCheck.Scr->search(MULTI_CHAR('abtn_n'))->scale(mDoGph_gInf_c::hudAspectScaleDown, 1.0f); + mBrightCheck.Scr->search(MULTI_CHAR('gcabtn_n'))->scale(mDoGph_gInf_c::hudAspectScaleDown, 1.0f); + + // Text + mBrightCheck.Scr->search(MULTI_CHAR('menu_6n'))->scale(mDoGph_gInf_c::hudAspectScaleDown, 1.0f); + mBrightCheck.Scr->search(MULTI_CHAR('menu_9n'))->scale(mDoGph_gInf_c::hudAspectScaleDown, 1.0f); + mBrightCheck.Scr->search(MULTI_CHAR('menu_10n'))->scale(mDoGph_gInf_c::hudAspectScaleDown, 1.0f); + mBrightCheck.Scr->search(MULTI_CHAR('menu_7n'))->scale(mDoGph_gInf_c::hudAspectScaleDown, 1.0f); + mBrightCheck.Scr->search(MULTI_CHAR('menu_8n'))->scale(mDoGph_gInf_c::hudAspectScaleDown, 1.0f); + mBrightCheck.Scr->search(MULTI_CHAR('fmenu_8n'))->scale(mDoGph_gInf_c::hudAspectScaleDown, 1.0f); + mBrightCheck.Scr->search(MULTI_CHAR('fmenu_7n'))->scale(mDoGph_gInf_c::hudAspectScaleDown, 1.0f); + mBrightCheck.Scr->search(MULTI_CHAR('fmenu_10'))->scale(mDoGph_gInf_c::hudAspectScaleDown, 1.0f); + mBrightCheck.Scr->search(MULTI_CHAR('fmenu_6n'))->scale(mDoGph_gInf_c::hudAspectScaleDown, 1.0f); + mBrightCheck.Scr->search(MULTI_CHAR('fmenu_9n'))->scale(mDoGph_gInf_c::hudAspectScaleDown, 1.0f); + mBrightCheck.Scr->search(MULTI_CHAR('t_t00'))->scale(mDoGph_gInf_c::hudAspectScaleDown, 1.0f); + mBrightCheck.Scr->search(MULTI_CHAR('f_t00'))->scale(mDoGph_gInf_c::hudAspectScaleDown, 1.0f); + + // Spirals + mBrightCheck.Scr->search(MULTI_CHAR('t_mo_l_n'))->scale(mDoGph_gInf_c::hudAspectScaleDown, 1.0f); + mBrightCheck.Scr->search(MULTI_CHAR('t_mo_r_n'))->scale(mDoGph_gInf_c::hudAspectScaleDown, 1.0f); +} +#endif + void dBrightCheck_c::_draw() { + #if TARGET_PC + brightCheckWide(); + #endif dComIfGd_set2DOpa(&mBrightCheck); } diff --git a/src/d/d_camera.cpp b/src/d/d_camera.cpp index ad12a4b773..70e8c105bb 100644 --- a/src/d/d_camera.cpp +++ b/src/d/d_camera.cpp @@ -762,6 +762,13 @@ void dCamera_c::updatePad() { var_f29 = 0.0f; } else { var_f31 = mDoCPd_c::getSubStickX3D(mPadID); + + #if TARGET_PC + if (dusk::getSettings().game.invertCameraXAxis) { + var_f31 *= -1.0f; + } + #endif + var_f30 = mDoCPd_c::getSubStickY(mPadID); var_f29 = mDoCPd_c::getSubStickValue(mPadID); } @@ -2410,10 +2417,18 @@ f32 dCamera_c::radiusActorInSight(fopAc_ac_c* i_actor1, fopAc_ac_c* i_actor2, cX dDlst_window_c* window = get_window(field_0x0); scissor_class* scissor = window->getScissor(); f32 var_f29 = cAngle::d2r(i_fovY) * 0.5f; +#if TARGET_PC + view_port_class* viewport = window->getViewPort(); + f32 var_f28 = (scissor->height - mTrimHeight * 2.0f) / viewport->height; + f32 sp34 = var_f29 * var_f28 * (mTrimHeight < 0.01f ? 0.95f : 1.0f); + var_f29 *= mWindowAspect; + var_f28 = scissor->width / viewport->width; +#else f32 var_f28 = (scissor->height - mTrimHeight * 2.0f) / FB_HEIGHT; f32 sp34 = var_f29 * var_f28 * (mTrimHeight < 0.01f ? 0.95f : 1.0f); var_f29 *= mWindowAspect; var_f28 = scissor->width / FB_WIDTH; +#endif f32 sp30 = var_f29 * var_f28 * 0.85f; cXyz pos1 = attentionPos(i_actor1); @@ -2443,8 +2458,8 @@ f32 dCamera_c::radiusActorInSight(fopAc_ac_c* i_actor1, fopAc_ac_c* i_actor2, cX int bVar2 = 0; - var_f29 = std::fabsf(cM_atan2f(pos1.x, -pos1.z)); - var_f28 = std::fabsf(cM_atan2f(pos1.y, -pos1.z)); + var_f29 = fabsf(cM_atan2f(pos1.x, -pos1.z)); + var_f28 = fabsf(cM_atan2f(pos1.y, -pos1.z)); if (var_f29 > sp30) { bVar2 |= 1; } @@ -2452,8 +2467,8 @@ f32 dCamera_c::radiusActorInSight(fopAc_ac_c* i_actor1, fopAc_ac_c* i_actor2, cX bVar2 |= 2; } - var_f29 = std::fabsf(cM_atan2f(pos2.x, -pos2.z)); - var_f28 = std::fabsf(cM_atan2f(pos2.y, -pos2.z)); + var_f29 = fabsf(cM_atan2f(pos2.x, -pos2.z)); + var_f28 = fabsf(cM_atan2f(pos2.y, -pos2.z)); if (var_f29 > sp30) { bVar2 |= 4; } @@ -2478,25 +2493,25 @@ f32 dCamera_c::radiusActorInSight(fopAc_ac_c* i_actor1, fopAc_ac_c* i_actor2, cX f32 var_f31; if (bVar2 & 1) { - var_f31 = pos1.z + std::fabsf(pos1.x) / local_12c; + var_f31 = pos1.z + fabsf(pos1.x) / local_12c; if (var_f31 > ret) { ret = var_f31; } } if (bVar2 & 2) { - var_f31 = pos1.z + std::fabsf(pos1.y) / local_130; + var_f31 = pos1.z + fabsf(pos1.y) / local_130; if (var_f31 > ret) { ret = var_f31; } } if (bVar2 & 4) { - var_f31 = pos2.z + std::fabsf(pos2.x) / local_12c; + var_f31 = pos2.z + fabsf(pos2.x) / local_12c; if (var_f31 > ret) { ret = var_f31; } } if (bVar2 & 8) { - var_f31 = pos2.z + std::fabsf(pos2.y) / local_130; + var_f31 = pos2.z + fabsf(pos2.y) / local_130; if (var_f31 > ret) { ret = var_f31; } @@ -2784,7 +2799,7 @@ bool dCamera_c::bumpCheck(u32 i_flags) { } wind_pow -= 0.3f; cSAngle angle = wind_globe.U() - mViewCache.mDirection.U(); - mFovy += mCamSetup.WindShakeGap4Fvy() * cM_rndFX(wind_pow / 0.7f) * (1.0f - std::fabsf(angle.Norm())); + mFovy += mCamSetup.WindShakeGap4Fvy() * cM_rndFX(wind_pow / 0.7f) * (1.0f - fabsf(angle.Norm())); #if DEBUG dDbVw_Report(300, 180, "wind %f %f", wind_pow, angle.Norm()); @@ -2928,7 +2943,7 @@ bool dCamera_c::bumpCheck(u32 i_flags) { cXyz cross; f32 dot = VECDotProduct(normal1, normal2); VECCrossProduct(normal1, normal2, &cross); - if (chkCornerCos(dot) && std::fabsf(cross.y) > 0.5f + if (chkCornerCos(dot) && fabsf(cross.y) > 0.5f && cBgW_CheckBWall(normal2->y)) { var_r27 = 5; } else { @@ -3041,7 +3056,7 @@ bool dCamera_c::bumpCheck(u32 i_flags) { field_0x96c += (1.0f - field_0x96c) * 0.1f; } if (sp0C || !(mMonitor.field_0xc < 5.0f) - || !(std::fabsf(mPadInfo.mCStick.mLastPosX) < 0.05f)) { + || !(fabsf(mPadInfo.mCStick.mLastPosX) < 0.05f)) { field_0x968 = 0.2f; } else { field_0x968 *= mMonitor.field_0xc / 5.0f; @@ -3984,7 +3999,7 @@ bool dCamera_c::chaseCamera(s32 param_0) { } cSAngle ang; - if ((chkFlag(0x100000) || sp1C || bVar6) && std::fabsf(mPadInfo.mCStick.mLastPosX) < 0.05f) { + if ((chkFlag(0x100000) || sp1C || bVar6) && fabsf(mPadInfo.mCStick.mLastPosX) < 0.05f) { ang.Val(directionOf(mpPlayerActor).Inv()); } else { ang.Val(mViewCache.mDirection.U()); @@ -3999,13 +4014,13 @@ bool dCamera_c::chaseCamera(s32 param_0) { pos3 = pos; pos.y += dist; sp1AC = cXyz(mCenter - pos3).abs() * 8.0f; - sp1BC = std::fabsf(dist1 > sp1AC ? dist1 : sp1AC); + sp1BC = fabsf(dist1 > sp1AC ? dist1 : sp1AC); dist1 = val18 + (val17 - val18) * chase->field_0xa4; - sp1AC = std::fabsf(mFovy - dist1); + sp1AC = fabsf(mFovy - dist1); f32 sin = cSAngle(mFovy > dist1 ? mFovy : dist1).Sin(); sp1AC = 100.0f * (sin * sin) * sp1AC; - sp1BC = std::fabsf(sp1BC > sp1AC ? sp1BC : sp1AC); + sp1BC = fabsf(sp1BC > sp1AC ? sp1BC : sp1AC); sp1BC *= 1.2f; sp1BC *= 0.00625f; chase->field_0x4 = (int)(JMAFastSqrt(sp1BC) * 2.2f) + 1; @@ -4113,7 +4128,7 @@ bool dCamera_c::chaseCamera(s32 param_0) { mViewCache.mCenter += (pos - mViewCache.mCenter) * rate; f32 dist = dCamMath::xyzHorizontalDistance(pos, chase->field_0x58); - if (dist < std::fabsf(vec.x > vec.z ? vec.x : vec.z) + 20.0f) { + if (dist < fabsf(vec.x > vec.z ? vec.x : vec.z) + 20.0f) { cXyz attention_pos = attentionPos(mpPlayerActor); attention_pos.y -= 15.0f; dBgS_CamLinChk lin_chk; @@ -4279,7 +4294,7 @@ bool dCamera_c::chaseCamera(s32 param_0) { cSAngle ang = -mViewCache.mDirection.U(); delta = dCamMath::xyzRotateY(delta, ang); cXyz vec5 = delta; - if (std::fabsf(vec5.y) < 200.0f) { + if (fabsf(vec5.y) < 200.0f) { vec5.y = 0.0f; vec5.x *= 0.5f; f32 sp16C = vec5.abs(); @@ -4400,17 +4415,17 @@ bool dCamera_c::chaseCamera(s32 param_0) { bool sp11 = false; f32 sp140 = 0.05f; f32 last_pos_x = mPadInfo.mCStick.mLastPosX; - f32 sp138 = std::fabsf(last_pos_x); + f32 sp138 = fabsf(last_pos_x); f32 sp134 = mPadInfo.mCStick.mLastPosY; - f32 sp130 = std::fabsf(sp134); + f32 sp130 = fabsf(sp134); f32 sp12C = 8.0f; f32 sp128 = 12.0f; chase->field_0x93 = false; - if (sp11 || (!mCamParam.Flag(param_0, 0x40) && std::fabsf(last_pos_x) > sp140)) { + if (sp11 || (!mCamParam.Flag(param_0, 0x40) && fabsf(last_pos_x) > sp140)) { chase->field_0xac += (dCamMath::rationalBezierRatio(last_pos_x, 0.5f) * sp12C - chase->field_0xac) * chase->field_0x4c; ang3 = globe.U() + cSAngle(chase->field_0xac); - sp148 = std::fabsf(last_pos_x) - 0.05f; + sp148 = fabsf(last_pos_x) - 0.05f; if (mCamSetup.CheckFlag(0x1000) && mFakeAngleSys.field_0x0 == 0) { setUSOAngle(); } @@ -4846,6 +4861,15 @@ bool dCamera_c::lockonCamera(s32 param_0) { } } +#if TARGET_PC + f32 sp194 = 1.0f; + if (mCurCamStyleTimer < lockon_change_timer && !lockon->field_0x2a) { + sp194 = dCamMath::rationalBezierRatio((f32)mCurCamStyleTimer / lockon_change_timer, 0.5f); + ang2 *= sp194; + } else if (mCurCamStyleTimer >= lockon_change_timer) { + lockon->field_0x2a = true; + } +#else f32 sp194; if (mCurCamStyleTimer < lockon_change_timer && !lockon->field_0x2a) { sp194 = dCamMath::rationalBezierRatio((f32)mCurCamStyleTimer / lockon_change_timer, 0.5f); @@ -4854,7 +4878,7 @@ bool dCamera_c::lockonCamera(s32 param_0) { lockon->field_0x2a = true; sp194 = 1.0f; } - +#endif cSAngle ang3(mViewCache.mDirection.U().Inv() - ang1); if (mCurCamStyleTimer != 0 && mCurCamStyleTimer < lockon_change_timer) { @@ -4898,7 +4922,7 @@ bool dCamera_c::lockonCamera(s32 param_0) { sp0C = true; } - f32 fVar43 = 1.0f - std::fabsf(mPadInfo.mCStick.mLastPosY); + f32 fVar43 = 1.0f - fabsf(mPadInfo.mCStick.mLastPosY); f32 fVar44; if (bVar1) { @@ -4957,12 +4981,12 @@ bool dCamera_c::lockonCamera(s32 param_0) { cSAngle u, v; cSAngle ang5 = globe.V() - lockon->field_0x34.V(); if (sp0C) { - r = lockon->field_0x34.R() * 0.75f * std::fabsf(ang5.Cos()); + r = lockon->field_0x34.R() * 0.75f * fabsf(ang5.Cos()); u.Val(lockon->field_0x34.U() + (ang4 - lockon->field_0x34.U()) * lockon->field_0x58); v.Val(lockon->field_0x34.V() + ang5 * 0.05f); } else { r = lockon->field_0x34.R() + (sp184 - lockon->field_0x34.R()) * - lockon->field_0x54 * std::fabsf(ang5.Cos()); + lockon->field_0x54 * fabsf(ang5.Cos()); u.Val(lockon->field_0x34.U() + (ang4 - lockon->field_0x34.U()) * lockon->field_0x58); v.Val(lockon->field_0x34.V() + ang5 * lockon->field_0x58); } @@ -4998,7 +5022,11 @@ bool dCamera_c::lockonCamera(s32 param_0) { f32 sp160; cSAngle ang6 = ang3 - ang2; curveWeight = mCamSetup.CurveWeight(); + #if AVOID_UB + f32 sp15C = 0.0f; + #else f32 sp15C; + #endif f32 sp158 = mPadInfo.mCStick.mLastPosX; if (mCamParam.Flag(param_0, 0x40)) { sp158 = 0.0f; @@ -5015,9 +5043,9 @@ bool dCamera_c::lockonCamera(s32 param_0) { } bool bVar3 = false; - if (std::fabsf(sp158) > 0.05f) { + if (fabsf(sp158) > 0.05f) { cSAngle ang = globe2.U() + cSAngle(dCamMath::rationalBezierRatio(sp158, 0.5f) * 7.5f); - sp15C = std::fabsf(sp158) - 0.05f; + sp15C = fabsf(sp158) - 0.05f; lockon->field_0x42 = ang; lockon->field_0x4c = 0.0f; bVar3 = true; @@ -5081,7 +5109,7 @@ bool dCamera_c::lockonCamera(s32 param_0) { } ang6 = ang1.Inv() - mViewCache.mDirection.U(); - if (std::fabsf(ang6.Degree()) < 2.0f && false) { + if (fabsf(ang6.Degree()) < 2.0f && false) { lockon->field_0x2a = true; } u2 += ang6 * sp15C * lockon->field_0x4c; @@ -5109,7 +5137,7 @@ bool dCamera_c::lockonCamera(s32 param_0) { } else { lockon->field_0xc = 0; if (!mBG.field_0xc0.field_0x44 && !bVar1) { - v2 += (globe2.V() - v2) * fVar43 * std::fabsf(mViewCache.mDirection.V().Cos()); + v2 += (globe2.V() - v2) * fVar43 * fabsf(mViewCache.mDirection.V().Cos()); } else { cSAngle ang7 = lockon->field_0x34.V(); ang7 *= cSAngle(lockon->field_0x34.U() - mViewCache.mDirection.U()).Cos(); @@ -5441,7 +5469,7 @@ bool dCamera_c::talktoCamera(s32 param_0) { if (talk->field_0x84 != 0) { talk->field_0x48 = 1; } else { - talk->field_0x48 = (int)(JMAFastSqrt(std::fabsf(mViewCache.mDirection.R() - talk->field_0x28.R())) / 2.0f); + talk->field_0x48 = (int)(JMAFastSqrt(fabsf(mViewCache.mDirection.R() - talk->field_0x28.R())) / 2.0f); if (talk->field_0x48 < 2) { talk->field_0x48 = 2; } @@ -5581,7 +5609,7 @@ bool dCamera_c::talktoCamera(s32 param_0) { for (i = 0; i < 36; i++) { sp26C = talk->field_0x28.U() - talk->field_0x30.U(); - if (std::fabsf(sp26C.Degree()) < 10.0f) { + if (fabsf(sp26C.Degree()) < 10.0f) { talk->field_0x28.U(talk->field_0x28.U() + sp270); } else { if (!sp5B) { @@ -7144,7 +7172,7 @@ bool dCamera_c::subjectCamera(s32 param_0) { f32 zoom_fovy = dCamMath::zoomFovy(val17 * 0.5f, tmp2) * 2.0f; mViewCache.mFovy += (zoom_fovy - mViewCache.mFovy) * val22; setComZoomScale(tmp2); - setComZoomForcus(1.0f - std::fabsf(sp88 - sp84) * -511.0f); + setComZoomForcus(1.0f - fabsf(sp88 - sp84) * -511.0f); if (check_owner_action(mPadID, 0x200000)) { setComStat(8); } @@ -7235,12 +7263,12 @@ bool dCamera_c::magneCamera(s32 param_0) { cSAngle stack_238; if (mCurMode == 1) { stack_238 = sp54.Inv(); - } else if (std::fabsf(cstick_x) > 0.05f) { + } else if (fabsf(cstick_x) > 0.05f) { stack_238 = magne->field_0x1c.U() + cSAngle(dCamMath::rationalBezierRatio(cstick_x, 0.5f) * 10.0f); } else { cSAngle stack_23c = sp54.Inv() - stack_230.U(); f32 sin = stack_23c.Sin(); - f32 tmp = std::fabsf(sin * mPadInfo.mMainStick.mLastValue); + f32 tmp = fabsf(sin * mPadInfo.mMainStick.mLastValue); f32 tmp2 = stack_23c.Cos() > 0.0f ? 8.0f : 4.0f; stack_238 = stack_230.U() + cSAngle(sin * tmp2 * dCamMath::rationalBezierRatio(tmp, 1.0f)); } @@ -7556,7 +7584,7 @@ bool dCamera_c::towerCamera(s32 param_0) { cXyz stack_21c = relationalPos(mpPlayerActor, &stack_210); f32 sp1A8 = cXyz(mEye - stack_21c).abs() - val7; f32 sp1A4 = cXyz(mCenter - stack_21c).abs() - val7; - f32 sp1A0 = std::fabsf(sp1A8 > sp1A4 ? sp1A8 : sp1A4); + f32 sp1A0 = fabsf(sp1A8 > sp1A4 ? sp1A8 : sp1A4); sp1A8 = heightOf(mpPlayerActor); sp1A0 /= (sp1A8 < 10.0f ? 10.0f : sp1A8); tower->field_0x4 = (int)(JMAFastSqrt(sp1A0) * sp220) + 1; @@ -7678,9 +7706,9 @@ bool dCamera_c::towerCamera(s32 param_0) { cSAngle sp108; cSAngle sp104 = stack_454 + (stack_454 - stack_458) * sp188; - if (!mCamParam.Flag(param_0, 0x40) && std::fabsf(sp18C) > sp184) { + if (!mCamParam.Flag(param_0, 0x40) && fabsf(sp18C) > sp184) { cSAngle sp100 = mViewCache.mDirection.U() + cSAngle(dCamMath::rationalBezierRatio(sp18C, 0.5f) * sp180); - f32 sp17C = std::fabsf(sp18C) - sp184; + f32 sp17C = fabsf(sp18C) - sp184; sp108.Val(mViewCache.mDirection.U() + (sp100 - mViewCache.mDirection.U()) * sp17C); tower->field_0x6a = true; tower->field_0x78 += (0.8f - tower->field_0x78) * 0.05f; @@ -10140,9 +10168,9 @@ bool dCamera_c::eventCamera(s32 param_0) { mEye = mCenter + mDirection.Xyz(); } - int* sp90_i; + BE(int)* sp90_i; if (getEvStringData(sp90, "Trim", "DEFAULT") != false) { - sp90_i = (int*)sp90; + sp90_i = (BE(int)*)sp90; if (*sp90_i == 'STAN') { mEventData.field_0x1c = 0; } else if (*sp90_i == 'VIST') { @@ -10523,6 +10551,10 @@ int dCamera_c::StartShake(s32 i_length, u8* i_pattern, s32 i_flags, cXyz i_pos) #define PATTERN_LENGTH_MAX 4 #endif + #if TARGET_PC + *(u32*)i_pattern = BSWAP32(*(u32*)i_pattern); + #endif + if (i_length < 0 || i_length > PATTERN_LENGTH_MAX << 3) { OS_REPORT("camera: shake: too long data\n"); i_length = PATTERN_LENGTH_MAX << 3; diff --git a/src/d/d_cc_s.cpp b/src/d/d_cc_s.cpp index ab71f08aaa..2a19de3dda 100644 --- a/src/d/d_cc_s.cpp +++ b/src/d/d_cc_s.cpp @@ -9,8 +9,9 @@ #include "d/d_com_inf_game.h" #include "d/d_jnt_col.h" #include "f_op/f_op_actor_mng.h" - -#include "dusk/imgui/ImGuiConsole.hpp" +#if TARGET_PC +#include "dusk/settings.h" +#endif class dCcS_HIO : public JORReflexible { public: @@ -770,19 +771,19 @@ void dCcS::Draw() { #endif #if TARGET_PC -#define IMGUI_TOGGLE_HIO_FLAG(status, flag) \ +#define DUSK_TOGGLE_HIO_FLAG(status, flag) \ if (status) { \ s_Hio.m_flags |= flag; \ } else { \ s_Hio.m_flags &= ~flag; \ } - dusk::ImGuiMenuTools::CollisionViewSettings collisionViewSettings = dusk::g_imguiConsole.getCollisionViewSettings(); - IMGUI_TOGGLE_HIO_FLAG(collisionViewSettings.m_enableAtView, dCcS_HIO::FLAG_AT_ON_e); - IMGUI_TOGGLE_HIO_FLAG(collisionViewSettings.m_enableTgView, dCcS_HIO::FLAG_TG_ON_e); - IMGUI_TOGGLE_HIO_FLAG(collisionViewSettings.m_enableCoView, dCcS_HIO::FLAG_CO_ON_e); + const auto& collisionViewSettings = dusk::getTransientSettings().collisionView; + DUSK_TOGGLE_HIO_FLAG(collisionViewSettings.enableAtView, dCcS_HIO::FLAG_AT_ON_e); + DUSK_TOGGLE_HIO_FLAG(collisionViewSettings.enableTgView, dCcS_HIO::FLAG_TG_ON_e); + DUSK_TOGGLE_HIO_FLAG(collisionViewSettings.enableCoView, dCcS_HIO::FLAG_CO_ON_e); - f32 view_opacity = 255 * (collisionViewSettings.m_colliderViewOpacity / 100.0f); + f32 view_opacity = 255 * (collisionViewSettings.colliderViewOpacity / 100.0f); #endif if (s_Hio.CheckAtOn()) { diff --git a/src/d/d_cursor_mng.cpp b/src/d/d_cursor_mng.cpp index 0d3fd4345e..230b4e740e 100644 --- a/src/d/d_cursor_mng.cpp +++ b/src/d/d_cursor_mng.cpp @@ -318,7 +318,7 @@ void dCsr_mng_c::bloObj_c::calcPaneObjNum(J2DPane* i_pane) { } JSUTreeIterator iter = i_pane->getPaneTree()->getFirstChild(); - while (iter != NULL) { + while (iter) { calcPaneObjNum(*iter); ++iter; } @@ -334,7 +334,7 @@ void dCsr_mng_c::bloObj_c::createPaneObj(paneObj_c** i_panes, J2DPane* i_pane) { } JSUTreeIterator iter = i_pane->getPaneTree()->getFirstChild(); - while (iter != NULL) { + while (iter) { createPaneObj(i_panes, *iter); ++iter; } diff --git a/src/d/d_drawlist.cpp b/src/d/d_drawlist.cpp index ee6b01f9fd..8b7457637d 100644 --- a/src/d/d_drawlist.cpp +++ b/src/d/d_drawlist.cpp @@ -1398,11 +1398,20 @@ void dDlst_shadowSimple_c::set(cXyz* param_0, f32 param_1, f32 param_2, cXyz* pa } void dDlst_shadowControl_c::init() { +#if TARGET_PC + // Increase shadow map resolution + static u16 l_realImageSize[2] = {1024, 512}; +#else static u16 l_realImageSize[2] = {192, 64}; +#endif for (int i = 0; i < 2; i++) { u16 size = l_realImageSize[i]; +#ifdef TARGET_PC + u32 buffer_size = 0x20; // No need to allocate memory for texture +#else u32 buffer_size = GXGetTexBufferSize(size, size, 5, GX_DISABLE, 0); +#endif field_0x15ef0[i] = JKR_NEW_ARRAY_ARGS(u8, buffer_size, 0x20); GXInitTexObj(&field_0x15eb0[i], field_0x15ef0[i], size, size, GX_TF_RGB5A3, GX_CLAMP, GX_CLAMP, GX_DISABLE); @@ -1467,11 +1476,18 @@ void dDlst_shadowControl_c::imageDraw(Mtx param_0) { int tex = 0; u16 r27; u16 r26; +#ifdef TARGET_PC + bool needsRestore = false; +#endif for (; shadowReal; shadowReal = shadowReal->getZsortNext()) { if (shadowReal->isUse()) { if (r29 == 0) { r27 = GXGetTexObjWidth(field_0x15eb0 + tex); r26 = r27 * 2; +#ifdef TARGET_PC + GXCreateFrameBuffer(r26, r26); + needsRestore = true; +#endif GXSetViewport(0.0f, 0.0f, r26, r26, 0.0f, 1.0f); GXSetScissor(0, 0, r26, r26); } @@ -1499,6 +1515,11 @@ void dDlst_shadowControl_c::imageDraw(Mtx param_0) { GXPixModeSync(); GXSetAlphaUpdate(GX_DISABLE); } +#ifdef TARGET_PC + if (needsRestore) { + GXRestoreFrameBuffer(); + } +#endif GXSetClipMode(GX_CLIP_ENABLE); GXSetDither(GX_TRUE); } @@ -1516,7 +1537,7 @@ void dDlst_shadowControl_c::draw(Mtx param_0) { dKy_GxFog_set(); GXSetChanCtrl(GX_ALPHA0, GX_DISABLE, GX_SRC_REG, GX_SRC_REG, GX_LIGHT_NULL, GX_DF_NONE, GX_AF_NONE); - GXSETARRAY(GX_VA_POS, l_shadowVolPos, sizeof(l_shadowVolPos), sizeof(l_shadowVolPos[0])); + GXSETARRAY(GX_VA_POS, l_shadowVolPos, sizeof(l_shadowVolPos), sizeof(l_shadowVolPos[0]), true); GXSetTexCoordGen(GX_TEXCOORD0, GX_TG_MTX3x4, GX_TG_POS, GX_TEXMTX0); GXSetNumTevStages(1); GXSetVtxAttrFmt(GX_VTXFMT0, GX_VA_POS, GX_POS_XYZ, GX_F32, 0); @@ -1548,7 +1569,7 @@ void dDlst_shadowControl_c::draw(Mtx param_0) { GXSetTevSwapModeTable(GX_TEV_SWAP0, GX_CH_RED, GX_CH_GREEN, GX_CH_BLUE, GX_CH_ALPHA); GXSetVtxAttrFmt(GX_VTXFMT0, GX_VA_TEX0, GX_CLR_RGBA, GX_RGB8, 0); - GXSETARRAY(GX_VA_POS, l_simpleShadowPos, sizeof(l_simpleShadowPos), sizeof(l_simpleShadowPos[0])); + GXSETARRAY(GX_VA_POS, l_simpleShadowPos, sizeof(l_simpleShadowPos), sizeof(l_simpleShadowPos[0]), true); GXSetTexCoordGen(GX_TEXCOORD0, GX_TG_MTX2x4, GX_TG_TEX0, GX_IDENTITY); GXSetTevOrder(GX_TEVSTAGE0, GX_TEXCOORD0, GX_TEXMAP0, GX_COLOR_NULL); GXSetAlphaCompare(GX_ALWAYS, 0, GX_AOP_OR, GX_ALWAYS, 0); @@ -1636,7 +1657,7 @@ int dDlst_shadowControl_c::setReal(u32 param_1, s8 param_2, J3DModel* param_3, c u32 rv = pdVar12->set(mNextID, param_3, param_4, param_5, param_6, param_7, dVar17, dVar16); if (!rv) { return 0; - } + } mRealNum++; if (pdVar10 == NULL) { if (pdVar11 == NULL) { @@ -1860,6 +1881,12 @@ int dDlst_list_c::set(dDlst_base_c**& p_start, dDlst_base_c**& p_end, dDlst_base void dDlst_list_c::draw(dDlst_base_c** p_start, dDlst_base_c** p_end) { for (; p_start < p_end; p_start++) { dDlst_base_c* dlst = *p_start; + +#if DEBUG && TARGET_PC + char buf[64]; + snprintf(buf, sizeof(buf), "%s::draw()", typeid(dlst).name()); + GXScopedDebugGroup scope(buf); +#endif dlst->draw(); } } diff --git a/src/d/d_error_msg.cpp b/src/d/d_error_msg.cpp index b0274b8583..efd2512c11 100644 --- a/src/d/d_error_msg.cpp +++ b/src/d/d_error_msg.cpp @@ -15,6 +15,7 @@ #include "m_Do/m_Do_Reset.h" #include "m_Do/m_Do_graphic.h" +#if !TARGET_PC #include "assets/black_tex.h" #include "assets/msg_data.h" #if VERSION == VERSION_GCN_PAL @@ -24,6 +25,7 @@ #include "assets/msg_data_it.h" #endif #include "assets/font_data.h" +#endif #define MSG_READING_DISC 0 #define MSG_COVER_OPEN 1 @@ -49,6 +51,7 @@ struct BMG_INF1 : JUTDataBlockHeader { #endif static void messageSet(u32 status, bool i_drawBg) { + #if !TARGET_PC BMG_INF1* inf1; const char* msg_p; @@ -177,9 +180,11 @@ static void messageSet(u32 status, bool i_drawBg) { tpane.draw(x, y + 10.0f, FB_WIDTH, HBIND_LEFT); #endif #endif + #endif } void dDvdErrorMsg_c::draw(s32 status) { + #if !TARGET_PC JUtility::TColor backColor = g_clearColor; JFWDisplay::getManager()->setClearColor(backColor); mDoGph_gInf_c::beginRender(); @@ -207,6 +212,7 @@ void dDvdErrorMsg_c::draw(s32 status) { mDoGph_gInf_c::endRender(); JFWDisplay::getManager()->resetFader(); + #endif } bool dDvdErrorMsg_c::execute() { @@ -237,6 +243,7 @@ bool dDvdErrorMsg_c::execute() { static u8 l_captureAlpha = 0xFF; static void drawCapture(u8 alpha) { + #if !TARGET_PC static bool l_texCopied = false; if (!l_texCopied) { @@ -251,9 +258,6 @@ static void drawCapture(u8 alpha) { GXSetAlphaUpdate(GX_FALSE); j3dSys.drawInit(); -#ifdef TARGET_PC - mDoGph_gInf_c::getFrameBufferTexObj()->reset(); -#endif GXInitTexObj(mDoGph_gInf_c::getFrameBufferTexObj(), mDoGph_gInf_c::getFrameBufferTex(), FB_WIDTH / 2, FB_HEIGHT / 2, (GXTexFmt)mDoGph_gInf_c::getFrameBufferTimg()->format, GX_CLAMP, GX_CLAMP, GX_FALSE); GXInitTexObjLOD(mDoGph_gInf_c::getFrameBufferTexObj(), GX_LINEAR, GX_LINEAR, 0.0f, 0.0f, 0.0f, GX_FALSE, GX_FALSE, GX_ANISO_1); GXLoadTexObj(mDoGph_gInf_c::getFrameBufferTexObj(), GX_TEXMAP0); @@ -293,6 +297,7 @@ static void drawCapture(u8 alpha) { mDoGph_drawFilterQuad(1, 1); mDoGph_gInf_c::endRender(); JFWDisplay::getManager()->resetFader(); + #endif } bool dShutdownErrorMsg_c::execute() { @@ -320,6 +325,5 @@ bool dShutdownErrorMsg_c::execute() { mDoRst_reset(1, 1, 1); } } - return true; } diff --git a/src/d/d_file_select.cpp b/src/d/d_file_select.cpp index 16aafb721f..8d4f98187b 100644 --- a/src/d/d_file_select.cpp +++ b/src/d/d_file_select.cpp @@ -70,7 +70,11 @@ dFs_HIO_c::dFs_HIO_c() { select_icon_appear_frames = 5; appear_display_wait_frames = 15; field_0x000d = 15; + #if TARGET_PC + card_wait_frames = 0; + #else card_wait_frames = 90; + #endif test_frame_counts[0] = 1.11f; test_frame_counts[1] = 1.11f; test_frame_counts[2] = 1.11f; @@ -1189,7 +1193,13 @@ void dFile_select_c::menuSelect() { // Handles copy / start / delete actions depending on which menu is selected from menuSelect void dFile_select_c::menuSelectStart() { - mDoAud_seStart(Z2SE_SY_CURSOR_OK, NULL, 0, 0); + #if TARGET_PC + if (!dusk::getSettings().game.hideTvSettingsScreen || mSelectMenuNum != 1) { + mDoAud_seStart(Z2SE_SY_CURSOR_OK, NULL, 0, 0); + } + #else + mDoAud_seStart(Z2SE_SY_CURSOR_OK, NULL, 0, 0); + #endif if (mSelectMenuNum == 1) { dComIfGs_setCardToMemory((u8*)mSaveData, mSelectNum); @@ -2091,7 +2101,12 @@ void dFile_select_c::yesnoCursorShow() { Vec pos = mYnSelPane[field_0x0268]->getGlobalVtxCenter(0, 0); mSelIcon->setPos(pos.x, pos.y, mYnSelPane[field_0x0268]->getPanePtr(), true); mSelIcon->setAlphaRate(1.0f); + + #if TARGET_PC + mSelIcon->setParam(0.96f * mDoGph_gInf_c::hudAspectScaleUp, 0.84f, 0.06f, 0.5f, 0.5f); + #else mSelIcon->setParam(0.96f, 0.84f, 0.06f, 0.5f, 0.5f); + #endif } } @@ -2243,7 +2258,12 @@ void dFile_select_c::YesNoCancelMove() { mSelIcon->setPos(vtxCenter.x, vtxCenter.y, m3mSelPane[mSelectMenuNum]->getPanePtr(), true); mSelIcon->setAlphaRate(1.0f); + + #if TARGET_PC + mSelIcon->setParam(0.96f * mDoGph_gInf_c::hudAspectScaleUp, 0.84f, 0.06f, 0.5f, 0.5f); + #else mSelIcon->setParam(0.96f, 0.84f, 0.06f, 0.5f, 0.5f); + #endif #if PLATFORM_WII || PLATFORM_SHIELD field_0x4333 = mSelectMenuNum; @@ -3126,7 +3146,13 @@ void dFile_select_c::screenSet() { mSelIcon = JKR_NEW dSelect_cursor_c(0, 1.0f, NULL); JUT_ASSERT(5209, mSelIcon != NULL); + + #if TARGET_PC + mSelIcon->setParam(0.96f * mDoGph_gInf_c::hudAspectScaleUp, 0.94f, 0.03f, 0.7f, 0.7f); + #else mSelIcon->setParam(0.96f, 0.94f, 0.03f, 0.7f, 0.7f); + #endif + Vec vtxCenter; vtxCenter = mSelFilePanes[mSelectNum]->getGlobalVtxCenter(false, 0); mSelIcon->setPos(vtxCenter.x, vtxCenter.y, mSelFilePanes[mSelectNum]->getPanePtr(), true); @@ -3257,7 +3283,13 @@ void dFile_select_c::screenSetCopySel() { mSelIcon2 = JKR_NEW dSelect_cursor_c(0, 1.0f, NULL); JUT_ASSERT(5406, mSelIcon2 != NULL); + + #if TARGET_PC + mSelIcon2->setParam(0.96f * mDoGph_gInf_c::hudAspectScaleUp, 0.94f, 0.03f, 0.7f, 0.7f); + #else mSelIcon2->setParam(0.96f, 0.94f, 0.03f, 0.7f, 0.7f); + #endif + Vec center = mCpSelPane[0]->getGlobalVtxCenter(false, 0); mSelIcon2->setPos(center.x, center.y, mCpSelPane[0]->getPanePtr(), true); mSelIcon2->setAlphaRate(0.0f); @@ -3647,7 +3679,12 @@ void dFile_select_c::selFileCursorShow() { Vec local_1c = mSelFilePanes[mSelectNum]->getGlobalVtxCenter(false, 0); mSelIcon->setPos(local_1c.x, local_1c.y, mSelFilePanes[mSelectNum]->getPanePtr(), true); mSelIcon->setAlphaRate(1.0f); + + #if TARGET_PC + mSelIcon->setParam(0.96f * mDoGph_gInf_c::hudAspectScaleUp, 0.94f, 0.03f, 0.7f, 0.7f); + #else mSelIcon->setParam(0.96f, 0.94f, 0.03f, 0.7f, 0.7f); + #endif } void dFile_select_c::menuWakuAlpahAnmInit(u8 i_idx, u8 param_1, u8 param_2, u8 param_3) { @@ -3689,7 +3726,12 @@ void dFile_select_c::menuCursorShow() { Vec local_24 = m3mSelPane[mSelectMenuNum]->getGlobalVtxCenter(false, 0); mSelIcon->setPos(local_24.x, local_24.y, m3mSelPane[mSelectMenuNum]->getPanePtr(), true); mSelIcon->setAlphaRate(1.0f); + + #if TARGET_PC + mSelIcon->setParam(0.96f * mDoGph_gInf_c::hudAspectScaleUp, 0.84f, 0.06f, 0.5f, 0.5f); + #else mSelIcon->setParam(0.96f, 0.84f, 0.06f, 0.5f, 0.5f); + #endif } } @@ -3731,7 +3773,74 @@ bool dFile_select_c::yesnoWakuAlpahAnm(u8 param_1) { return rv; } +#if TARGET_PC +void dFile_select_c::fileSelectWide() { + mYnSel.ScrYn->scale(mDoGph_gInf_c::hudAspectScaleUp, 1.0f); + mYnSel.ScrYn->translate(mDoGph_gInf_c::getMinXF(), 0.0f); + + mYnSel.ScrYn->search(MULTI_CHAR('w_no_t'))->scale(mDoGph_gInf_c::hudAspectScaleDown, 1.0f); + mYnSel.ScrYn->search(MULTI_CHAR('f_no_t'))->scale(mDoGph_gInf_c::hudAspectScaleDown, 1.0f); + mYnSel.ScrYn->search(MULTI_CHAR('w_yes_t'))->scale(mDoGph_gInf_c::hudAspectScaleDown, 1.0f); + mYnSel.ScrYn->search(MULTI_CHAR('f_yes_t'))->scale(mDoGph_gInf_c::hudAspectScaleDown, 1.0f); + + m3mSel.Scr3m->scale(mDoGph_gInf_c::hudAspectScaleUp, 1.0f); + m3mSel.Scr3m->translate(mDoGph_gInf_c::getMinXF(), 0.0f); + + m3mSel.Scr3m->search(MULTI_CHAR('w_sta'))->scale(mDoGph_gInf_c::hudAspectScaleDown, 1.0f); + m3mSel.Scr3m->search(MULTI_CHAR('f_sta'))->scale(mDoGph_gInf_c::hudAspectScaleDown, 1.0f); + m3mSel.Scr3m->search(MULTI_CHAR('w_del'))->scale(mDoGph_gInf_c::hudAspectScaleDown, 1.0f); + m3mSel.Scr3m->search(MULTI_CHAR('f_del'))->scale(mDoGph_gInf_c::hudAspectScaleDown, 1.0f); + m3mSel.Scr3m->search(MULTI_CHAR('w_cop_t'))->scale(mDoGph_gInf_c::hudAspectScaleDown, 1.0f); + m3mSel.Scr3m->search(MULTI_CHAR('f_cop_t'))->scale(mDoGph_gInf_c::hudAspectScaleDown, 1.0f); + + fileSel.Scr->scale(mDoGph_gInf_c::hudAspectScaleUp, 1.0f); + fileSel.Scr->translate(mDoGph_gInf_c::getMinXF(), 0.0f); + + fileSel.Scr->search(MULTI_CHAR('t_for'))->scale(mDoGph_gInf_c::hudAspectScaleDown, 1.0f); + fileSel.Scr->search(MULTI_CHAR('t_for1'))->scale(mDoGph_gInf_c::hudAspectScaleDown, 1.0f); + + fileSel.Scr->search(MULTI_CHAR('w_btn_n'))->scale(mDoGph_gInf_c::hudAspectScaleDown, 1.0f); + + fileSel.Scr->search(MULTI_CHAR('w_n_bk00'))->scale(mDoGph_gInf_c::hudAspectScaleDown, 1.0f); + fileSel.Scr->search(MULTI_CHAR('w_n_bk01'))->scale(mDoGph_gInf_c::hudAspectScaleDown, 1.0f); + fileSel.Scr->search(MULTI_CHAR('w_n_bk02'))->scale(mDoGph_gInf_c::hudAspectScaleDown, 1.0f); + + fileSel.Scr->search(MULTI_CHAR('w_dat_i0'))->scale(mDoGph_gInf_c::hudAspectScaleDown, 1.0f); + fileSel.Scr->search(MULTI_CHAR('w_dat_i1'))->scale(mDoGph_gInf_c::hudAspectScaleDown, 1.0f); + fileSel.Scr->search(MULTI_CHAR('w_dat_i2'))->scale(mDoGph_gInf_c::hudAspectScaleDown, 1.0f); + + mCpSel.Scr->search(MULTI_CHAR('w_dat_i1'))->scale(mDoGph_gInf_c::hudAspectScaleDown, 1.0f); + mCpSel.Scr->search(MULTI_CHAR('w_dat_i2'))->scale(mDoGph_gInf_c::hudAspectScaleDown, 1.0f); + mCpSel.Scr->search(MULTI_CHAR('w_n_bk01'))->scale(mDoGph_gInf_c::hudAspectScaleDown, 1.0f); + mCpSel.Scr->search(MULTI_CHAR('w_n_bk02'))->scale(mDoGph_gInf_c::hudAspectScaleDown, 1.0f); + + mSelDt.ScrDt->search(MULTI_CHAR('tate_n0'))->scale(mDoGph_gInf_c::hudAspectScaleDown, 1.0f); + mSelDt.ScrDt->search(MULTI_CHAR('tate_n1'))->scale(mDoGph_gInf_c::hudAspectScaleDown, 1.0f); + mSelDt.ScrDt->search(MULTI_CHAR('ken_n0'))->scale(mDoGph_gInf_c::hudAspectScaleDown, 1.0f); + mSelDt.ScrDt->search(MULTI_CHAR('ken_n1'))->scale(mDoGph_gInf_c::hudAspectScaleDown, 1.0f); + mSelDt.ScrDt->search(MULTI_CHAR('fuku_n0'))->scale(mDoGph_gInf_c::hudAspectScaleDown, 1.0f); + mSelDt.ScrDt->search(MULTI_CHAR('fuku_n1'))->scale(mDoGph_gInf_c::hudAspectScaleDown, 1.0f); + mSelDt.ScrDt->search(MULTI_CHAR('fuku_n2'))->scale(mDoGph_gInf_c::hudAspectScaleDown, 1.0f); + + // Spirals + fileSel.Scr->search(MULTI_CHAR('w_uzu00'))->scale(mDoGph_gInf_c::hudAspectScaleDown, 1.0f); + fileSel.Scr->search(MULTI_CHAR('w_uzu01'))->scale(mDoGph_gInf_c::hudAspectScaleDown, 1.0f); + fileSel.Scr->search(MULTI_CHAR('w_uzu02'))->scale(mDoGph_gInf_c::hudAspectScaleDown, 1.0f); + fileSel.Scr->search(MULTI_CHAR('w_uzu03'))->scale(mDoGph_gInf_c::hudAspectScaleDown, 1.0f); + fileSel.Scr->search(MULTI_CHAR('w_uzu04'))->scale(mDoGph_gInf_c::hudAspectScaleDown, 1.0f); + fileSel.Scr->search(MULTI_CHAR('w_uzu05'))->scale(mDoGph_gInf_c::hudAspectScaleDown, 1.0f); + fileSel.Scr->search(MULTI_CHAR('w_uzu06'))->scale(mDoGph_gInf_c::hudAspectScaleDown, 1.0f); + fileSel.Scr->search(MULTI_CHAR('w_uzu07'))->scale(mDoGph_gInf_c::hudAspectScaleDown, 1.0f); + fileSel.Scr->search(MULTI_CHAR('w_uzu08'))->scale(mDoGph_gInf_c::hudAspectScaleDown, 1.0f); + fileSel.Scr->search(MULTI_CHAR('w_uzu09'))->scale(mDoGph_gInf_c::hudAspectScaleDown, 1.0f); +} +#endif + void dFile_select_c::_draw() { + #if TARGET_PC + fileSelectWide(); + #endif + if (!mHasDrawn) { dComIfGd_set2DOpa(&fileSel); diff --git a/src/d/d_gameover.cpp b/src/d/d_gameover.cpp index 236cad603c..baec970a32 100644 --- a/src/d/d_gameover.cpp +++ b/src/d/d_gameover.cpp @@ -37,8 +37,13 @@ void dDlst_Gameover_CAPTURE_c::draw() { TGXTexObj tex_obj; Mtx44 m; +#if TARGET_PC + GXSetTexCopySrc(0, 0, mDoGph_gInf_c::getWidth(), mDoGph_gInf_c::getHeight()); + GXSetTexCopyDst(mDoGph_gInf_c::getWidth(), mDoGph_gInf_c::getHeight(), GX_TF_RGB565, GX_TRUE); +#else GXSetTexCopySrc(0, 0, FB_WIDTH, FB_HEIGHT); - GXSetTexCopyDst(FB_WIDTH / 2, FB_HEIGHT / 2, GX_TF_RGB565, 1); + GXSetTexCopyDst(FB_WIDTH / 2, FB_HEIGHT / 2, GX_TF_RGB565, GX_TRUE); +#endif GXCopyTex(mDoGph_gInf_c::mZbufferTex, 0); GXPixModeSync(); GXInitTexObj(&tex_obj, mDoGph_gInf_c::mFrameBufferTex, FB_WIDTH / 2, FB_HEIGHT / 2, @@ -427,7 +432,14 @@ void dDlst_GameOverScrnDraw_c::draw() { img_white.a = 255; mpBackImg->setBlackWhite(img_black, img_white); + + #if TARGET_PC + mpBackImg->draw(mDoGph_gInf_c::getMinXF(), mDoGph_gInf_c::getMinYF(), + mDoGph_gInf_c::getWidthF(), mDoGph_gInf_c::getHeightF(), false, false, + false); + #else mpBackImg->draw(0.0f, 0.0f, FB_WIDTH, FB_HEIGHT, false, false, false); + #endif } else { JUtility::TColor img_black; JUtility::TColor img_white; @@ -442,7 +454,13 @@ void dDlst_GameOverScrnDraw_c::draw() { img_white.b = l_HIO.mWhite.b; img_white.a = l_HIO.mWhite.a; + #if TARGET_PC + mpBackImg->draw(mDoGph_gInf_c::getMinXF(), mDoGph_gInf_c::getMinYF(), + mDoGph_gInf_c::getWidthF(), mDoGph_gInf_c::getHeightF(), false, false, + false); + #else mpBackImg->draw(0.0f, 0.0f, FB_WIDTH, FB_HEIGHT, false, false, false); + #endif static f32 offset[8] = {-138.0f, -96.0f, -56.0f, -18.0f, 42.0f, 75.0f, 110.0f, 143.0f}; diff --git a/src/d/d_insect.cpp b/src/d/d_insect.cpp index 3f1d2fae11..380f545bd3 100644 --- a/src/d/d_insect.cpp +++ b/src/d/d_insect.cpp @@ -82,7 +82,11 @@ void dInsect_c::CalcZBuffer(f32 param_0) { pos = current.pos; pos.y += 20.0f; + #if TARGET_PC + mDoLib_project(&pos, &pos_projected, {0, 0, FB_WIDTH, FB_HEIGHT}); + #else mDoLib_project(&pos, &pos_projected); + #endif if (dComIfGp_getCamera(0)) { camera_trim_height = dComIfGp_getCamera(0)->mCamera.mTrimHeight; diff --git a/src/d/d_k_wmark.cpp b/src/d/d_k_wmark.cpp index 379b55f532..b93ab14211 100644 --- a/src/d/d_k_wmark.cpp +++ b/src/d/d_k_wmark.cpp @@ -6,6 +6,7 @@ #include "d/dolzel.h" // IWYU pragma: keep #include "d/d_k_wmark.h" +#include "dusk/memory.h" #include "JSystem/J3DGraphBase/J3DMaterial.h" #include "SSystem/SComponent/c_math.h" #include "d/actor/d_a_player.h" @@ -33,7 +34,7 @@ int dkWmark_c::create() { mColorType = this->parameters; } - mpHeap = mDoExt_createSolidHeapFromGameToCurrent(0x880, 0x20); + mpHeap = mDoExt_createSolidHeapFromGameToCurrent(HEAP_SIZE(0x880, 0x1100), 0x20); if (mpHeap != NULL) { JKRHEAP_NAME(mpHeap, "dkWmark_c::mpHeap"); J3DModelData* modelData = (J3DModelData*)dComIfG_getObjectRes("Alink", 0x23); diff --git a/src/d/d_kankyo.cpp b/src/d/d_kankyo.cpp index e6d076c05f..8644d433aa 100644 --- a/src/d/d_kankyo.cpp +++ b/src/d/d_kankyo.cpp @@ -1,6 +1,7 @@ #include "d/dolzel.h" // IWYU pragma: keep #include "d/d_kankyo.h" +#include "dusk/memory.h" #ifdef __REVOLUTION_SDK__ #include #else @@ -32,7 +33,7 @@ #include #include #if TARGET_PC -#include "dusk/imgui/ImGuiConsole.hpp" +#include "dusk/settings.h" #endif static void GxXFog_set(); @@ -775,7 +776,7 @@ static void dKy_FiveSenses_fullthrottle_dark_static1() { particle_size.y = 1.0f; particle_size.z = 1.0f; - #if !PLATFORM_GCN + #if !PLATFORM_GCN || TARGET_PC particle_size.x *= mDoGph_gInf_c::getScale(); #endif @@ -820,12 +821,20 @@ static void dKy_FiveSenses_fullthrottle_dark_static1() { } if (kankyo->senses_ef_emitter1 != NULL) { + #if TARGET_PC + kankyo->senses_ef_emitter1->setGlobalParticleScale(mDoGph_gInf_c::getScale(), 1.0f); + #endif + kankyo->senses_ef_emitter1->setGlobalTranslation(particle_pos.x, particle_pos.y, particle_pos.z); kankyo->senses_ef_emitter1->setGlobalAlpha(kankyo->senses_effect_strength * 255.0f); } if (kankyo->senses_ef_emitter2 != NULL) { + #if TARGET_PC + kankyo->senses_ef_emitter2->setGlobalParticleScale(mDoGph_gInf_c::getScale(), 1.0f); + #endif + kankyo->senses_ef_emitter2->setGlobalTranslation(particle_pos.x, particle_pos.y, particle_pos.z); @@ -1175,7 +1184,7 @@ static void undwater_init() { J3DModelData* modelData2 = (J3DModelData*)dComIfG_getObjectRes("Always", 0x1D); JUT_ASSERT(1867, modelData2 != NULL); - g_env_light.undwater_ef_heap = mDoExt_createSolidHeapFromGameToCurrent(0x600, 0x20); + g_env_light.undwater_ef_heap = mDoExt_createSolidHeapFromGameToCurrent(HEAP_SIZE(0x600, 0xC00), 0x20); JKRHEAP_NAME(g_env_light.undwater_ef_heap, "g_env_light.undwater_ef_heap"); if (g_env_light.undwater_ef_heap != NULL) { @@ -9696,7 +9705,7 @@ void dKy_ParticleColor_get_base(cXyz* param_0, dKy_tevstr_c* param_1, GXColor* p f32 var_f31; #if AVOID_UB - var_f31 = 0; + var_f31 = 100000000.0f; #endif if (dKy_SunMoon_Light_Check() == TRUE && i <= 1) { @@ -10977,7 +10986,11 @@ void dKy_depth_dist_set(void* process_p) { f32 var_f31 = sp24.abs(camera_p->view.lookat.eye); if (var_f31 < 2000.0f && var_f31 < kankyo->field_0x1268) { + #if TARGET_PC + mDoLib_project(&actor_p->eyePos, &sp30, {0, 0, FB_WIDTH, FB_HEIGHT}); + #else mDoLib_project(&actor_p->eyePos, &sp30); + #endif if ((sp30.x >= 0.0f && sp30.x < FB_WIDTH) && (sp30.y >= 0.0f && #if DEBUG @@ -11381,7 +11394,7 @@ void dKy_bg_MAxx_proc(void* bg_model_p) { C_MTXLightPerspective(sp1D8, dComIfGd_getView()->fovy, camera_p->view.aspect, 1.0f, 1.0f, #if TARGET_PC - dusk::g_imguiConsole.isWaterProjectionOffsetEnabled() ? -0.01f : 0.0f, 0.0f); + dusk::getSettings().game.useWaterProjectionOffset ? -0.01f : 0.0f, 0.0f); #else -0.01f, 0.0f); #endif diff --git a/src/d/d_kankyo_debug.cpp b/src/d/d_kankyo_debug.cpp index 7fdad26ed2..03bfeac196 100644 --- a/src/d/d_kankyo_debug.cpp +++ b/src/d/d_kankyo_debug.cpp @@ -915,7 +915,12 @@ void dKydb_dungeonlight_draw() { rot.y = 0; dDbVw_drawCubeXlu(player->current.pos, size, rot, color); + #if TARGET_PC + mDoLib_project(&g_env_light.dungeonlight[i].mPosition, &proj, {0, 0, FB_WIDTH, FB_HEIGHT}); + #else mDoLib_project(&g_env_light.dungeonlight[i].mPosition, &proj); + #endif + if (proj.x > 30.0f) { proj.x -= 30.0f; } diff --git a/src/d/d_kankyo_rain.cpp b/src/d/d_kankyo_rain.cpp index 019f30f101..d91e0c03ba 100644 --- a/src/d/d_kankyo_rain.cpp +++ b/src/d/d_kankyo_rain.cpp @@ -113,7 +113,12 @@ void dKyr_lenzflare_move() { cXyz vect; cXyz proj; cXyz center; + + #if TARGET_PC + mDoLib_project(lenz_packet->mPositions, &proj, {0, 0, FB_WIDTH, FB_HEIGHT}); + #else mDoLib_project(lenz_packet->mPositions, &proj); + #endif center.x = FB_WIDTH / 2; center.y = FB_HEIGHT / 2; @@ -213,7 +218,12 @@ void dKyr_sun_move() { } cXyz proj; + + #if TARGET_PC + mDoLib_project(sun_packet->mPos, &proj, {0, 0, FB_WIDTH, FB_HEIGHT}); + #else mDoLib_project(sun_packet->mPos, &proj); + #endif for (int i = 0; i < 5; i++) { cXyz chkpnt = proj; @@ -4031,6 +4041,7 @@ void dKyr_drawSnow(Mtx drawMtx, u8** tex) { } void dKyr_drawStar(Mtx drawMtx, u8** tex) { + ZoneScoped; dScnKy_env_light_c* envlight = dKy_getEnvlight(); dKankyo_star_Packet* star_packet = g_env_light.mpStarPacket; camera_class* camera = (camera_class*)dComIfGp_getCamera(0); @@ -4111,7 +4122,11 @@ void dKyr_drawStar(Mtx drawMtx, u8** tex) { } } + #if TARGET_PC + mDoLib_project(&moon_pos, &moon_proj, {0, 0, FB_WIDTH, FB_HEIGHT}); + #else mDoLib_project(&moon_pos, &moon_proj); + #endif GXSetNumChans(1); GXSetChanCtrl(GX_COLOR0, GX_DISABLE, GX_SRC_REG, GX_SRC_REG, GX_LIGHT_NULL, GX_DF_CLAMP, GX_AF_NONE); @@ -4248,7 +4263,11 @@ void dKyr_drawStar(Mtx drawMtx, u8** tex) { sp68.y = spBC.y + star_pos.y; sp68.z = spBC.z + star_pos.z; + #if TARGET_PC + mDoLib_project(&sp68, &star_proj, {0, 0, FB_WIDTH, FB_HEIGHT}); + #else mDoLib_project(&sp68, &star_proj); + #endif moon_proj.z = 0.0f; star_proj.z = 0.0f; @@ -4630,7 +4649,11 @@ void drawVrkumo(Mtx drawMtx, GXColor& color, u8** tex) { } if (g_env_light.daytime > 105.0f && g_env_light.daytime < 240.0f && !dComIfGp_event_runCheck() && sun_packet != NULL && sun_packet->mSunAlpha > 0.0f) { + #if TARGET_PC + mDoLib_project(&sun_packet->mPos[0], &proj, {0, 0, FB_WIDTH, FB_HEIGHT}); + #else mDoLib_project(&sun_packet->mPos[0], &proj); + #endif if (proj.x > 0.0f && proj.x < FB_WIDTH && proj.y > spC4 && proj.y < (458.0f - spC4)) { pass = 0; } @@ -4895,7 +4918,12 @@ void drawVrkumo(Mtx drawMtx, GXColor& color, u8** tex) { x = 100.0f; y = 100.0f; z = 100.0f; + + #if TARGET_PC + mDoLib_project(&spF0, &proj, {0, 0, FB_WIDTH, FB_HEIGHT}); + #else mDoLib_project(&spF0, &proj); + #endif if (proj.x > -x && proj.x < (FB_WIDTH + x) && proj.y > -y && proj.y < (458.0f + z)) { break; @@ -4945,7 +4973,12 @@ void drawVrkumo(Mtx drawMtx, GXColor& color, u8** tex) { x = 100.0f; y = 100.0f; z = 100.0f; + + #if TARGET_PC + mDoLib_project(&spE4, &proj, {0, 0, FB_WIDTH, FB_HEIGHT}); + #else mDoLib_project(&spE4, &proj); + #endif if (proj.x > -x && proj.x < (FB_WIDTH + x) && proj.y > -y && proj.y < (458.0f + z)) { break; @@ -5986,21 +6019,18 @@ static void dKyr_evil_draw2(Mtx drawMtx, u8** tex) { sp34.y = 80.0f; sp34.z = 80.0f; + #if TARGET_PC + mDoLib_project(&sp7C, &proj, {0, 0, FB_WIDTH, FB_HEIGHT}); + #else mDoLib_project(&sp7C, &proj); + #endif -#if TARGET_PC - if (!(proj.x > -sp34.x) || !(proj.x < (dComIfGd_getViewport()->width + sp34.x)) || - !(proj.y > -sp34.y) || !(proj.y < (dComIfGd_getViewport()->height + sp34.z))) - { - continue; - } -#else if (!(proj.x > -sp34.x) || !(proj.x < (FB_WIDTH + sp34.x)) || !(proj.y > -sp34.y) || !(proj.y < (458.0f + sp34.z))) { continue; } -#endif + } f32 sp40; @@ -6219,21 +6249,17 @@ void dKyr_evil_draw(Mtx drawMtx, u8** tex) { sp44.y = 80.0f; sp44.z = 80.0f; + #if TARGET_PC + mDoLib_project(&spA4, &proj, {0, 0, FB_WIDTH, FB_HEIGHT}); + #else mDoLib_project(&spA4, &proj); + #endif -#if TARGET_PC - if (!(proj.x > -sp44.x) || !(proj.x < (dComIfGd_getViewport()->width + sp44.x)) || - !(proj.y > -sp44.y) || !(proj.y < (dComIfGd_getViewport()->height + sp44.z))) - { - continue; - } -#else if (!(proj.x > -sp44.x) || !(proj.x < (FB_WIDTH + sp44.x)) || !(proj.y > -sp44.y) || !(proj.y < (458.0f + sp44.z))) { continue; } -#endif } f32 sp5C; diff --git a/src/d/d_map.cpp b/src/d/d_map.cpp index 76289d52dd..7dc5187a88 100644 --- a/src/d/d_map.cpp +++ b/src/d/d_map.cpp @@ -341,7 +341,6 @@ inline u8 twoValueLineInterpolation(u8 param_0, u8 param_1, f32 param_2) { } void renderingAmap_c::draw() { - #if REQUIRES_GX_LINES f32 tmp = ((f32)(g_Counter.mCounter0 % dMap_HIO_prm_res_dst_s::m_res->field_0x1aa) / (f32)dMap_HIO_prm_res_dst_s::m_res->field_0x1aa); tmp = tmp; @@ -376,8 +375,7 @@ void renderingAmap_c::draw() { dMap_HIO_prm_res_dst_s::m_res->field_0x1a7, tmp); setAmapPaletteColor(0x2E, temp_r31, temp_r30, temp_r29, temp_r28); - renderingDAmap_c::draw(); - #endif + GX_DEBUG_GROUP(renderingDAmap_c::draw); } int renderingAmap_c::getDispType() const { @@ -541,9 +539,19 @@ void renderingAmap_c::rendering(dDrawPath_c::poly_class const* i_poly) { } } +/* Enabling the following definition will modify the following function to + * make the map look worse for extra speed in the emulator, especially in large + * areas such as hyrule field. + */ +#define HYRULE_FIELD_SPEEDHACK + bool renderingAmap_c::isDrawOutSideTrim() { bool rt = false; + #ifdef HYRULE_FIELD_SPEEDHACK + return 0; + #endif + if (getDispType() == 0 || getDispType() == 4 || getDispType() == 3 || getDispType() == 2 || getDispType() == 5) { @@ -1099,7 +1107,7 @@ void dMap_c::resCopy() { } } -dMap_c::dMap_c(int param_0, int param_1, int param_2, int param_3) { +dMap_c::dMap_c(int width, int height, int param_2, int param_3) { m_res_src = NULL; m_res = NULL; mResTIMG = NULL; @@ -1171,8 +1179,8 @@ dMap_c::dMap_c(int param_0, int param_1, int param_2, int param_3) { resCopy(); - mTexSizeX = param_0; - mTexSizeY = param_1; + mTexSizeX = width; + mTexSizeY = height; if (dMap_HIO_prm_res_dst_s::m_res->field_0x1ae > 0) { field_0x74 = dMap_HIO_prm_res_dst_s::m_res->field_0x1b0 / 6; diff --git a/src/d/d_map_path.cpp b/src/d/d_map_path.cpp index 47f0f1e43c..f7ce0f1a51 100644 --- a/src/d/d_map_path.cpp +++ b/src/d/d_map_path.cpp @@ -14,6 +14,14 @@ #include "m_Do/m_Do_lib.h" #include +#ifdef TARGET_PC +constexpr u16 kMapResolutionMultiplier = 4; +// Line widths are relative to the framebuffer size. Since we're rendering to a separate +// framebuffer, we have to scale them accordingly. The original game used about half of the +// EFB for the map rendering, so this is a reasonable approximation. +constexpr u8 kMapLineWidthMultiplier = 2; +#endif + void dMpath_n::dTexObjAggregate_c::create() { static int const data[7] = { 79, 80, 77, 78, 76, 81, 82, @@ -234,7 +242,11 @@ void dDrawPath_c::rendering(dDrawPath_c::line_class const* p_line) { int width = getLineWidth(p_line->field_0x1); if (width > 0 && p_line->mDataNum >= 2) { - GXSetLineWidth(width, GX_TO_ZERO); +#ifdef TARGET_PC + GXSetLineWidth(width * kMapLineWidthMultiplier, GX_TO_ZERO); +#else + GXSetLineWidth(width * 2, GX_TO_ZERO); +#endif GXSetTevColor(GX_TEVREG0, *getLineColor(p_line->field_0x0 & 0x3F, p_line->field_0x1)); GXBegin(GX_LINESTRIP, GX_VTXFMT0, p_line->mDataNum); @@ -292,11 +304,22 @@ void dDrawPath_c::rendering(dDrawPath_c::floor_class const* p_floor) { } } +#ifdef TARGET_PC +static u32 getRoomPosArraySize(const dDrawPath_c::room_class* room) { + if (room->mpFloor == NULL || room->mpFloatData == NULL || room->mFloorNum == 0) { + return 0; + } + const dDrawPath_c::group_class* firstGroup = room->mpFloor[0].mpGroup; + JUT_ASSERT(0, firstGroup != NULL); + JUT_ASSERT(0, (const u8*)firstGroup >= (const u8*)room->mpFloatData); + return (const u8*)firstGroup - (const u8*)room->mpFloatData; +} +#endif + void dDrawPath_c::rendering(dDrawPath_c::room_class const* room) { JUT_ASSERT(1043, room != NULL); if (room != NULL) { - // TODO: FILL IN SIZE. - GXSETARRAY(GX_VA_POS, room->mpFloatData, 0, 8); + GXSetArray(GX_VA_POS, room->mpFloatData, getRoomPosArraySize(room), 8, false); floor_class* floor = room->mpFloor; if (floor != NULL) { @@ -322,8 +345,14 @@ void dRenderingMap_c::makeResTIMG(ResTIMG* p_image, u16 width, u16 height, u8* p u8* p_palette, u16 param_5) const { p_image->format = GX_TF_C8; p_image->alphaEnabled = 2; +#ifdef TARGET_PC + // Increase map render resolution + p_image->width = width * kMapResolutionMultiplier; + p_image->height = height * kMapResolutionMultiplier; +#else p_image->width = width; p_image->height = height; +#endif p_image->wrapS = GX_CLAMP; p_image->wrapT = GX_CLAMP; p_image->indexTexture = true; @@ -346,13 +375,11 @@ void dRenderingMap_c::makeResTIMG(ResTIMG* p_image, u16 width, u16 height, u8* p void dRenderingMap_c::renderingMap() { preRenderingMap(); if (isDrawPath()) { - #if REQUIRES_GX_LINES preDrawPath(); beforeDrawPath(); drawPath(); afterDrawPath(); postDrawPath(); - #endif } postRenderingMap(); } @@ -403,8 +430,17 @@ void dRenderingFDAmap_c::drawBack() const { } void dRenderingFDAmap_c::preRenderingMap() { +#ifdef TARGET_PC + // Increase map render resolution + const u16 w = mTexWidth * kMapResolutionMultiplier; + const u16 h = mTexHeight * kMapResolutionMultiplier; + GXCreateFrameBuffer(w, h); + GXSetViewport(0.0f, 0.0f, w, h, 0.0f, 1.0f); + GXSetScissor(0, 0, w, h); +#else GXSetViewport(0.0f, 0.0f, mTexWidth, mTexHeight, 0.0f, 1.0f); GXSetScissor(0, 0, mTexWidth, mTexHeight); +#endif GXSetNumChans(1); GXSetNumTevStages(1); GXSetChanCtrl(GX_COLOR0A0, GX_FALSE, GX_SRC_REG, GX_SRC_REG, GX_LIGHT_NULL, GX_DF_NONE, @@ -431,9 +467,19 @@ void dRenderingFDAmap_c::preRenderingMap() { void dRenderingFDAmap_c::postRenderingMap() { GXSetCopyFilter(GX_FALSE, NULL, GX_FALSE, NULL); +#ifdef TARGET_PC + // Increase map render resolution + const u16 w = mTexWidth * kMapResolutionMultiplier; + const u16 h = mTexHeight * kMapResolutionMultiplier; + GXSetTexCopySrc(0, 0, w, h); + GXSetTexCopyDst(w, h, GX_CTF_R8, GX_FALSE); + GXCopyTex(field_0x4, GX_TRUE); + GXRestoreFrameBuffer(); +#else GXSetTexCopySrc(0, 0, mTexWidth, mTexHeight); GXSetTexCopyDst(mTexWidth, mTexHeight, GX_CTF_R8, GX_FALSE); GXCopyTex(field_0x4, GX_TRUE); +#endif GXPixModeSync(); GXSetClipMode(GX_CLIP_ENABLE); GXSetDither(GX_TRUE); @@ -446,7 +492,7 @@ dMpath_n::dTexObjAggregate_c dMpath_n::m_texObjAgg; * make the map look worse for extra speed in the emulator, especially in large * areas such as hyrule field. */ -// #define HYRULE_FIELD_SPEEDHACK +#define HYRULE_FIELD_SPEEDHACK void dRenderingFDAmap_c::renderingDecoration(dDrawPath_c::line_class const* p_line) { s32 width = getDecorationLineWidth(p_line->field_0x1); @@ -465,15 +511,19 @@ void dRenderingFDAmap_c::renderingDecoration(dDrawPath_c::line_class const* p_li BE(u16)* data_p = p_line->mpData; s32 data_num = p_line->mDataNum; +#ifdef TARGET_PC + GXSetLineWidth(width * kMapLineWidthMultiplier, GX_TO_ZERO); + GXSetPointSize(width * kMapLineWidthMultiplier, GX_TO_ONE); +#else GXSetLineWidth(width, GX_TO_ONE); GXSetPointSize(width, GX_TO_ONE); +#endif GXColor lineColor = *getDecoLineColor(p_line->field_0x0 & 0x3f, p_line->field_0x1); GXSetTevColor(GX_TEVREG0, lineColor); lineColor.r = lineColor.r - 4; GXSetTevColor(GX_TEVREG1, lineColor); for (int i = 0; i < data_num; i++) { -#if REQUIRES_GX_LINES #ifndef HYRULE_FIELD_SPEEDHACK if (i < data_num - 1) { GXSetTevColorIn(GX_TEVSTAGE0, GX_CC_ZERO, GX_CC_ZERO, GX_CC_ZERO, GX_CC_C0); @@ -494,7 +544,7 @@ void dRenderingFDAmap_c::renderingDecoration(dDrawPath_c::line_class const* p_li GXSetTevAlphaIn(GX_TEVSTAGE0, GX_CA_ZERO, GX_CA_ZERO, GX_CA_ZERO, GX_CA_TEXA); GXSetTevAlphaOp(GX_TEVSTAGE0, GX_TEV_ADD, GX_TB_ZERO, GX_CS_SCALE_1, GX_TRUE, GX_TEVPREV); #endif -#endif + GXBegin(GX_POINTS, GX_VTXFMT0, 1); GXPosition1x16(data_p[0]); GXTexCoord2f32(0, 0); diff --git a/src/d/d_map_path_dmap.cpp b/src/d/d_map_path_dmap.cpp index cd76155327..f2a41e8fd3 100644 --- a/src/d/d_map_path_dmap.cpp +++ b/src/d/d_map_path_dmap.cpp @@ -617,10 +617,7 @@ bool renderingDAmap_c::isSwitch(dDrawPath_c::group_class const* i_group) { } void renderingDAmap_c::draw() { -#if !TARGET_PC - // Currently breaks Aurora. renderingMap(); -#endif mIsDraw = true; } @@ -851,7 +848,7 @@ void renderingPlusDoor_c::drawDoorCommon(stage_tgsc_data_class const* i_doorData GXSetVtxDesc(GX_VA_TEX0, GX_INDEX8); GXSetVtxAttrFmt(GX_VTXFMT0, GX_VA_POS, GX_CLR_RGBA, GX_F32, 0); GXSetVtxAttrFmt(GX_VTXFMT0, GX_VA_TEX0, GX_CLR_RGBA, GX_RGB565, 0); - GXSETARRAY(GX_VA_TEX0, (void*)l_tex0, sizeof(l_tex0), 2); + GXSETARRAY(GX_VA_TEX0, l_tex0, sizeof(l_tex0), 2, true); setTevSettingIntensityTextureToCI(); @@ -1010,7 +1007,7 @@ void renderingPlusDoorAndCursor_c::drawTreasure() { GXSetVtxDesc(GX_VA_TEX0, GX_INDEX8); GXSetVtxAttrFmt(GX_VTXFMT0, GX_VA_POS, GX_CLR_RGB, GX_F32, 0); GXSetVtxAttrFmt(GX_VTXFMT0, GX_VA_TEX0, GX_CLR_RGBA, GX_RGB565, 0); - GXSETARRAY(GX_VA_TEX0, (void*)l_iconTex0, sizeof(l_iconTex0), 2); + GXSETARRAY(GX_VA_TEX0, l_iconTex0, sizeof(l_iconTex0), 2, true); setTevSettingIntensityTextureToCI(); @@ -1084,7 +1081,7 @@ void renderingPlusDoorAndCursor_c::drawTreasureAfterPlayer() { GXSetVtxDesc(GX_VA_TEX0, GX_INDEX8); GXSetVtxAttrFmt(GX_VTXFMT0, GX_VA_POS, GX_CLR_RGB, GX_F32, 0); GXSetVtxAttrFmt(GX_VTXFMT0, GX_VA_TEX0, GX_CLR_RGBA, GX_RGB565, 0); - GXSETARRAY(GX_VA_TEX0, (void*)l_iconTex0, sizeof(l_iconTex0), 2); + GXSETARRAY(GX_VA_TEX0, l_iconTex0, sizeof(l_iconTex0), 2, true); setTevSettingIntensityTextureToCI(); diff --git a/src/d/d_menu_collect.cpp b/src/d/d_menu_collect.cpp index c1281a86c2..72a390a0cc 100644 --- a/src/d/d_menu_collect.cpp +++ b/src/d/d_menu_collect.cpp @@ -95,6 +95,78 @@ dMenu_Collect2D_c::~dMenu_Collect2D_c() { } } +#if TARGET_PC +void dMenu_Collect2D_c::menuCollectWide() { + // Main Canvas + mpScreen->scale(mDoGph_gInf_c::hudAspectScaleUp, 1.0f); + mpScreen->translate(mDoGph_gInf_c::getMinXF(), 0.0f); + + // Pieces of Heart + mpScreen->search(MULTI_CHAR('heart_n'))->scale(mDoGph_gInf_c::hudAspectScaleDown, 1.0f); + + // Scents + mpScreen->search(MULTI_CHAR('wolf_n'))->scale(mDoGph_gInf_c::hudAspectScaleDown, 1.0f); + + // Quiver + mpScreen->search(MULTI_CHAR('item_0_n'))->scale(mDoGph_gInf_c::hudAspectScaleDown, 1.0f); + + // Wallet + mpScreen->search(MULTI_CHAR('item_1_n'))->scale(mDoGph_gInf_c::hudAspectScaleDown, 1.0f); + + // Poes + mpScreen->search(MULTI_CHAR('item_2_n'))->scale(mDoGph_gInf_c::hudAspectScaleDown, 1.0f); + + // Fish Bestiary + mpScreen->search(MULTI_CHAR('fish_3_n'))->scale(mDoGph_gInf_c::hudAspectScaleDown, 1.0f); + + // Letters + mpScreen->search(MULTI_CHAR('lett_4_n'))->scale(mDoGph_gInf_c::hudAspectScaleDown, 1.0f); + + // Hidden Skills + mpScreen->search(MULTI_CHAR('maki_5_n'))->scale(mDoGph_gInf_c::hudAspectScaleDown, 1.0f); + + // Green Tunic + mpScreen->search(MULTI_CHAR('fuku_n0'))->scale(mDoGph_gInf_c::hudAspectScaleDown, 1.0f); + + // Zora Armor + mpScreen->search(MULTI_CHAR('fuku_n1'))->scale(mDoGph_gInf_c::hudAspectScaleDown, 1.0f); + + // Magic Armor + mpScreen->search(MULTI_CHAR('fuku_n2'))->scale(mDoGph_gInf_c::hudAspectScaleDown, 1.0f); + + // Ordon Shield + mpScreen->search(MULTI_CHAR('tate_n0'))->scale(mDoGph_gInf_c::hudAspectScaleDown, 1.0f); + + // Hylian Shield + mpScreen->search(MULTI_CHAR('tate_n1'))->scale(mDoGph_gInf_c::hudAspectScaleDown, 1.0f); + + // Ordon Sword + mpScreen->search(MULTI_CHAR('ken_n0'))->scale(mDoGph_gInf_c::hudAspectScaleDown, 1.0f); + + // Master Sword + mpScreen->search(MULTI_CHAR('ken_n1'))->scale(mDoGph_gInf_c::hudAspectScaleDown, 1.0f); + + // Bugs + mpScreen->search(MULTI_CHAR('kabu_6n'))->scale(mDoGph_gInf_c::hudAspectScaleDown, 1.0f); + + // "Collection" Text + mpScreen->search(MULTI_CHAR('t_t00'))->scale(mDoGph_gInf_c::hudAspectScaleDown, 1.0f); + mpScreen->search(MULTI_CHAR('f_t00'))->scale(mDoGph_gInf_c::hudAspectScaleDown, 1.0f); + + // "Save" Text + mpScreen->search(MULTI_CHAR('sa_tex_n'))->scale(mDoGph_gInf_c::hudAspectScaleDown, 1.0f); + + // "Options" Text + mpScreen->search(MULTI_CHAR('op_tex_n'))->scale(mDoGph_gInf_c::hudAspectScaleDown, 1.0f); + + // Item Name Text + mpScreen->search(MULTI_CHAR('itemn_n'))->scale(mDoGph_gInf_c::hudAspectScaleDown, 1.0f); + + // Item Description Text + mpScreen->search(MULTI_CHAR('infotxtn'))->scale(mDoGph_gInf_c::hudAspectScaleDown, 1.0f); +} +#endif + void dMenu_Collect2D_c::_create() { mpHeap->getTotalFreeSize(); mpScreen = JKR_NEW J2DScreen(); @@ -108,7 +180,17 @@ void dMenu_Collect2D_c::_create() { mpButtonAB[i] = NULL; mpButtonText[i] = NULL; } + + #if TARGET_PC + mpScreenIcon->translate(-mDoGph_gInf_c::getMinXF(), 0.0f); + #endif + dPaneClass_showNullPane(mpScreenIcon); + + #if TARGET_PC + menuCollectWide(); + #endif + mpDraw2DTop = JKR_NEW dMenu_Collect2DTop_c(this); ResTIMG* image = (ResTIMG*)dComIfGp_getMain2DArchive()->getResource('TIMG', "tt_block8x8.bti"); mpBlackTex = JKR_NEW J2DPicture(image); @@ -508,6 +590,15 @@ void dMenu_Collect2D_c::screenSet() { field_0x184[4][2] = 0x196; field_0x184[5][2] = 0x195; field_0x184[6][2] = 0; +#if TARGET_PC // Since we allow changing wallet sizes, do something more robust. + if (dComIfGs_getWalletSize() == WALLET) { + field_0x184[0][3] = 0x199; + } else if (dComIfGs_getWalletSize() == BIG_WALLET) { + field_0x184[0][3] = 0x19a; + } else { + field_0x184[0][3] = 0x19b; + } +#else if (dComIfGs_getRupeeMax() == WALLET_MAX) { field_0x184[0][3] = 0x199; } else if (dComIfGs_getRupeeMax() == BIG_WALLET_MAX) { @@ -515,6 +606,7 @@ void dMenu_Collect2D_c::screenSet() { } else { field_0x184[0][3] = 0x19b; } +#endif if (dComIfGs_getArrowMax() == QUIVER_MAX) { field_0x184[1][3] = 0x1b9; } else if (dComIfGs_getArrowMax() == BIG_QUIVER_MAX) { @@ -675,7 +767,11 @@ void dMenu_Collect2D_c::screenSet() { setItemNameString(mCursorX, mCursorY); cursorPosSet(); setArrowMaxNum(dComIfGs_getArrowMax()); +#if TARGET_PC + setWalletSizeNum(dComIfGs_getWalletSize()); +#else setWalletMaxNum(dComIfGs_getRupeeMax()); +#endif setSmellType(); setHeartPiece(); setPohMaxNum(dComIfGs_getPohSpiritNum()); @@ -1004,11 +1100,23 @@ void dMenu_Collect2D_c::cursorPosSet() { Vec pos = mpSelPm[mCursorX][mCursorY]->getGlobalVtxCenter(false, 0); mpDrawCursor->setPos(pos.x, pos.y, mpSelPm[mCursorX][mCursorY]->getPanePtr(), false); if (mCursorY == 5) { + #if TARGET_PC + mpDrawCursor->setParam(1.1f * mDoGph_gInf_c::hudAspectScaleUp, 0.85f, 0.05f, 0.5f, 0.5f); + #else mpDrawCursor->setParam(1.1f, 0.85f, 0.05f, 0.5f, 0.5f); + #endif } else if (mCursorX == 6 && mCursorY == 0) { + #if TARGET_PC + mpDrawCursor->setParam(0.6f * mDoGph_gInf_c::hudAspectScaleUp, 0.85f, 0.03f, 0.6f, 0.6f); + #else mpDrawCursor->setParam(0.6f, 0.85f, 0.03f, 0.6f, 0.6f); + #endif } else { + #if TARGET_PC + mpDrawCursor->setParam(1.0f * mDoGph_gInf_c::hudAspectScaleUp, 1.0f, 0.1f, 0.7f, 0.7f); + #else mpDrawCursor->setParam(1.0f, 1.0f, 0.1f, 0.7f, 0.7f); + #endif } } @@ -1148,6 +1256,27 @@ void dMenu_Collect2D_c::setArrowMaxNum(u8 param_0) { } } +#if TARGET_PC +void dMenu_Collect2D_c::setWalletSizeNum(u16 i_walletSize) { + switch (i_walletSize) { + case WALLET: + mpScreen->search(MULTI_CHAR('item_1_0'))->show(); + mpScreen->search(MULTI_CHAR('item_1_1'))->hide(); + mpScreen->search(MULTI_CHAR('item_1_2'))->hide(); + break; + case BIG_WALLET: + mpScreen->search(MULTI_CHAR('item_1_0'))->hide(); + mpScreen->search(MULTI_CHAR('item_1_1'))->show(); + mpScreen->search(MULTI_CHAR('item_1_2'))->hide(); + break; + case GIANT_WALLET: + mpScreen->search(MULTI_CHAR('item_1_0'))->hide(); + mpScreen->search(MULTI_CHAR('item_1_1'))->hide(); + mpScreen->search(MULTI_CHAR('item_1_2'))->show(); + break; + } +} +#else void dMenu_Collect2D_c::setWalletMaxNum(u16 i_walletSize) { switch (i_walletSize) { case 300: @@ -1167,6 +1296,7 @@ void dMenu_Collect2D_c::setWalletMaxNum(u16 i_walletSize) { break; } } +#endif void dMenu_Collect2D_c::setSmellType() { static const u64 smell_tag[5] = { @@ -2028,6 +2158,10 @@ void dMenu_Collect2D_c::_move() { void dMenu_Collect2D_c::_draw() { + #if TARGET_PC + menuCollectWide(); + #endif + J2DGrafContext* grafPort = dComIfGp_getCurrentGrafPort(); grafPort->setup2D(); mpScreen->draw(0.0f, 0.0f, grafPort); @@ -2555,7 +2689,7 @@ f32 dMenu_Collect3D_c::mViewOffsetY = -100.0f; void dMenu_Collect3D_c::setupItem3D(Mtx param_0) { #if TARGET_PC - f32 scaleFactor = mDoGph_gInf_c::getWidth() / FB_WIDTH; // TODO: get display pixel density from aurora + f32 scaleFactor = mDoGph_gInf_c::getHeight() / FB_HEIGHT; GXSetViewport(0.0f, mViewOffsetY * scaleFactor, mDoGph_gInf_c::getWidth(), mDoGph_gInf_c::getHeight(), 0.0f, 1.0f); #else GXSetViewport(0.0f, mViewOffsetY, FB_WIDTH, FB_HEIGHT, 0.0f, 1.0f); diff --git a/src/d/d_menu_dmap.cpp b/src/d/d_menu_dmap.cpp index 97721d9dd2..739dfc7843 100644 --- a/src/d/d_menu_dmap.cpp +++ b/src/d/d_menu_dmap.cpp @@ -864,7 +864,16 @@ void dMenu_DmapBg_c::draw() { J2DOrthoGraph* grafContext = (J2DOrthoGraph*)dComIfGp_getCurrentGrafPort(); grafContext->setup2D(); +#if TARGET_PC + // GXGetScissor uses 11-bit GC register fields (max 2047) which overflow + // at window widths > ~1705px, producing garbage values on restore. + scissor_left = 0; + scissor_top = 0; + scissor_width = (u32)mDoGph_gInf_c::getWidth(); + scissor_height = (u32)mDoGph_gInf_c::getHeight(); +#else GXGetScissor(&scissor_left, &scissor_top, &scissor_width, &scissor_height); +#endif #if TARGET_PC grafContext->scissor(field_0xd94, 0.0f, mDoGph_gInf_c::getWidth(), mDoGph_gInf_c::getHeight()); #else @@ -876,8 +885,8 @@ void dMenu_DmapBg_c::draw() { dMenu_Dmap_c::myclass->drawFloorScreenBack(mFloorScreen, field_0xd94, field_0xd98, grafContext); #if TARGET_PC - f32 dVar21 = mDoGph_gInf_c::getWidth() / FB_WIDTH; - f32 dVar16 = mDoGph_gInf_c::getHeight() / FB_HEIGHT; + f32 dVar21 = mDoGph_gInf_c::getWidthF() / mDoGph_gInf_c::getWidth(); + f32 dVar16 = mDoGph_gInf_c::getHeightF() / mDoGph_gInf_c::getHeight(); #else f32 dVar21 = mDoGph_gInf_c::getWidthF() / FB_WIDTH; f32 dVar16 = mDoGph_gInf_c::getHeightF() / FB_HEIGHT; @@ -890,8 +899,15 @@ void dMenu_DmapBg_c::draw() { Mtx mtx; Vec local_200 = pane.getGlobalVtx(center_pane, &mtx, 0, false, 0); Vec local_20c = pane.getGlobalVtx(center_pane, &mtx, 3, false, 0); +#if TARGET_PC + grafContext->scissor(((local_200.x - mDoGph_gInf_c::getMinXF()) / dVar21), + ((local_200.y - mDoGph_gInf_c::getMinYF()) / dVar16), + ((local_20c.x - local_200.x) / dVar21), + (2.0f + (local_20c.y - local_200.y)) / dVar16); +#else grafContext->scissor(((local_200.x - mDoGph_gInf_c::getMinXF()) / dVar21), ((local_200.y / dVar16) / dVar16), ((local_20c.x - local_200.x) / dVar21), 2.0f + (local_20c.y - local_200.y)); +#endif grafContext->setScissor(); f32 dVar17 = field_0xd8c / 255.0f; @@ -925,10 +941,17 @@ void dMenu_DmapBg_c::draw() { Mtx local_110; Vec local_218 = pane.getGlobalVtx(center_pane, &local_110, 0, false, 0); Vec local_224 = pane.getGlobalVtx(center_pane, &local_110, 3, false, 0); +#if TARGET_PC + f32 local_294 = ((local_218.x - mDoGph_gInf_c::getMinXF()) / dVar21); + f32 local_298 = ((local_218.y - mDoGph_gInf_c::getMinYF()) / dVar16); + f32 local_29c = ((local_224.x - local_218.x) / dVar21); + f32 local_2a0 = (2.0f + (local_224.y - local_218.y)) / dVar16; +#else f32 local_294 = ((local_218.x - mDoGph_gInf_c::getMinXF()) / dVar21); f32 local_298 = ((local_218.y / dVar16) / dVar16); f32 local_29c = ((local_224.x - local_218.x) / dVar21); f32 local_2a0 = 2.0f + (local_224.y - local_218.y); +#endif grafContext->scissor(local_294, local_298, local_29c, local_2a0); grafContext->setScissor(); diff --git a/src/d/d_menu_dmap_map.cpp b/src/d/d_menu_dmap_map.cpp index 0754bf7e35..8971b2630d 100644 --- a/src/d/d_menu_dmap_map.cpp +++ b/src/d/d_menu_dmap_map.cpp @@ -300,16 +300,20 @@ void dMenu_DmapMap_c::_delete() { } } -void dMenu_DmapMap_c::setTexture(u16 param_0, u16 param_1, u16 param_2, u16 param_3) { +void dMenu_DmapMap_c::setTexture(u16 width, u16 height, u16 param_2, u16 param_3) { for (int lp1 = 0; lp1 < 2; lp1++) { - u32 var_r27 = GXGetTexBufferSize(param_0, param_1, 9, 0, 0); - mMapImage_p[lp1] = JKR_NEW_ARRAY_ARGS(u8, var_r27, 0x20); +#ifdef TARGET_PC + u32 sz = 0x20; // No need to allocate memory for texture +#else + u32 sz = GXGetTexBufferSize(width, height, 9, 0, 0); +#endif + mMapImage_p[lp1] = JKR_NEW_ARRAY_ARGS(u8, sz, 0x20); JUT_ASSERT(1672, mMapImage_p[lp1] != NULL); - mRend[lp1].init(mMapImage_p[lp1], param_0, param_1, param_2, param_3); + mRend[lp1].init(mMapImage_p[lp1], width, height, param_2, param_3); mResTIMG[lp1] = JKR_NEW_ARGS (0x20) ResTIMG; JUT_ASSERT(1687, mResTIMG[lp1] != NULL); - mRend[lp1].makeResTIMG(mResTIMG[lp1], param_0, param_1, mMapImage_p[lp1], (u8*)dMdm_HIO_prm_res_dst_s::m_res, 30); + mRend[lp1].makeResTIMG(mResTIMG[lp1], width, height, mMapImage_p[lp1], (u8*)dMdm_HIO_prm_res_dst_s::m_res, 30); } } @@ -929,7 +933,7 @@ f32 dMenu_StageMapCtrl_c::m_zoomCenterMinZ; f32 dMenu_StageMapCtrl_c::m_zoomCenterMaxZ; -void dMenu_StageMapCtrl_c::_create(u16 param_0, u16 param_1, u16 param_2, u16 param_3, +void dMenu_StageMapCtrl_c::_create(u16 width, u16 height, u16 param_2, u16 param_3, s8 param_4, void* param_5) { field_0xe6 = dComIfGp_roomControl_getStayNo(); field_0xe7 = param_4; @@ -946,7 +950,7 @@ void dMenu_StageMapCtrl_c::_create(u16 param_0, u16 param_1, u16 param_2, u16 pa field_0x98 = param_3; f32 var_f26 = field_0x98 > field_0x94 ? field_0x98 : field_0x94; - dMenu_DmapMap_c::_create(param_0, param_1, param_2, param_3, param_5); + dMenu_DmapMap_c::_create(width, height, param_2, param_3, param_5); getInitDispCenter(&field_0x9c, &field_0xa0); field_0xa4 = field_0x9c; diff --git a/src/d/d_menu_fishing.cpp b/src/d/d_menu_fishing.cpp index 189ce57e0f..615323767b 100644 --- a/src/d/d_menu_fishing.cpp +++ b/src/d/d_menu_fishing.cpp @@ -114,7 +114,14 @@ void dMenu_Fishing_c::_draw() { if (mpArchive) { J2DGrafContext* grafPort = dComIfGp_getCurrentGrafPort(); mpBlackTex->setAlpha(0xff); + + #if TARGET_PC + mpBlackTex->draw(mDoGph_gInf_c::getMinXF(), mDoGph_gInf_c::getMinYF(), + mDoGph_gInf_c::getWidthF(), mDoGph_gInf_c::getHeightF(), 0, 0, 0); + #else mpBlackTex->draw(0.0f, 0.0f, FB_WIDTH, FB_HEIGHT, 0, 0, 0); + #endif + mpScreen->draw(0.0f, 0.0f, grafPort); mpIconScreen->draw(0.0f, 0.0f, grafPort); } diff --git a/src/d/d_menu_fmap.cpp b/src/d/d_menu_fmap.cpp index c8969f2ac3..851e22b7c7 100644 --- a/src/d/d_menu_fmap.cpp +++ b/src/d/d_menu_fmap.cpp @@ -2278,7 +2278,7 @@ void dMenu_Fmap_c::decodeFieldMapData() { dMenuMapCommon_c::Stage_c* stage_data = (dMenuMapCommon_c::Stage_c*)(field_data + mpFieldDat->mStageDataOffset); mDataNumMax = stage_data->mCount; - mAllTitleName = *(u16*)(field_data + 0x16); + mAllTitleName = *(BE(u16)*)(field_data + 0x16); setTitleName(mAllTitleName); dMenu_Fmap_field_region_data_c::data* regions = region_data->mData; char tex_path[20]; diff --git a/src/d/d_menu_fmap2D.cpp b/src/d/d_menu_fmap2D.cpp index 29ec5db854..c9ab812400 100644 --- a/src/d/d_menu_fmap2D.cpp +++ b/src/d/d_menu_fmap2D.cpp @@ -359,7 +359,11 @@ void dMenu_Fmap2DBack_c::draw() { drawDebugRegionArea(); } +#if TARGET_PC + grafPort->scissor(scissorLeft, scissorTop, mDoGph_gInf_c::getWidth(), mDoGph_gInf_c::getHeight()); +#else grafPort->scissor(scissorLeft, scissorTop, scissorWidth, scissorHeight); +#endif grafPort->setScissor(); if (isArrowDrawFlag()) { @@ -1191,7 +1195,7 @@ f32 dMenu_Fmap2DBack_c::getMapScissorAreaSizeX() { } f32 dMenu_Fmap2DBack_c::getMapScissorAreaSizeRealX() { -#if PLATFORM_GCN +#if PLATFORM_GCN && !TARGET_PC return getMapScissorAreaSizeX(); #else return getMapScissorAreaSizeX() * mDoGph_gInf_c::getScale(); diff --git a/src/d/d_menu_fmap_map.cpp b/src/d/d_menu_fmap_map.cpp index fbbd9267e5..3d1a9e2523 100644 --- a/src/d/d_menu_fmap_map.cpp +++ b/src/d/d_menu_fmap_map.cpp @@ -659,7 +659,11 @@ const GXColor* dMenu_FmapMap_c::getColor(int param_0) { void dMenu_FmapMap_c::setTexture(u16 i_width, u16 i_height, u16 param_2, u16 param_3) { mMapImage_p = NULL; mResTIMG = NULL; +#ifdef TARGET_PC + int size = 0x20; // No need to allocate memory for texture +#else int size = GXGetTexBufferSize(i_width, i_height, GX_TF_C8, 0, 0); +#endif mMapImage_p = JKR_NEW_ARRAY_ARGS(u8, size, 0x20); init(mMapImage_p, i_width, i_height, param_2, param_3); mResTIMG = JKR_NEW_ARGS (0x20) ResTIMG; diff --git a/src/d/d_menu_insect.cpp b/src/d/d_menu_insect.cpp index 82be9287b6..7558fe61b4 100644 --- a/src/d/d_menu_insect.cpp +++ b/src/d/d_menu_insect.cpp @@ -161,12 +161,26 @@ void dMenu_Insect_c::_draw() { if (mpArchive != NULL) { J2DGrafContext* grafPort = dComIfGp_getCurrentGrafPort(); mpBlackTex->setAlpha(0xff); + + #if TARGET_PC + mpBlackTex->draw(mDoGph_gInf_c::getMinXF(), mDoGph_gInf_c::getMinYF(), + mDoGph_gInf_c::getWidthF(), mDoGph_gInf_c::getHeightF(), 0, 0, 0); + #else mpBlackTex->draw(0.0f, 0.0f, FB_WIDTH, FB_HEIGHT, 0, 0, 0); + #endif + mpScreen->draw(0.0f, 0.0f, grafPort); mpDrawCursor->draw(); field_0xfc = mpExpParent->getAlphaRate() * 150.0f; mpBlackTex->setAlpha(field_0xfc); + + #if TARGET_PC + mpBlackTex->draw(mDoGph_gInf_c::getMinXF(), mDoGph_gInf_c::getMinYF(), + mDoGph_gInf_c::getWidthF(), mDoGph_gInf_c::getHeightF(), 0, 0, 0); + #else mpBlackTex->draw(0.0f, 0.0f, FB_WIDTH, FB_HEIGHT, 0, 0, 0); + #endif + mpExpScreen->draw(0.0f, 0.0f, grafPort); mpSelect_c->setOffsetX(g_drawHIO.mInsectListScreen.mConfirmOptionPosX_4x3); mpSelect_c->translate(g_drawHIO.mInsectListScreen.mConfirmOptionPosX_4x3 + 486.0f, diff --git a/src/d/d_menu_item_explain.cpp b/src/d/d_menu_item_explain.cpp index 21a3a32fdd..c106b4bd8c 100644 --- a/src/d/d_menu_item_explain.cpp +++ b/src/d/d_menu_item_explain.cpp @@ -310,7 +310,12 @@ void dMenu_ItemExplain_c::draw(J2DOrthoGraph* i_graph) { mpLabel->scale(g_ringHIO.mItemDescTitleScale, g_ringHIO.mItemDescTitleScale); mpLabel->paneTrans(g_ringHIO.mItemDescTitlePosX, g_ringHIO.mItemDescTitlePosY); if (mpBackTex != NULL) { + #if TARGET_PC + mpBackTex->draw(mDoGph_gInf_c::ScaleHUDXLeft(0.0f), 0.0f, mDoGph_gInf_c::getWidthF(), + FB_HEIGHT, false, false, false); + #else mpBackTex->draw(0.0f, 0.0f, FB_WIDTH, FB_HEIGHT, false, false, false); + #endif } if (field_0xc8 != field_0xd0) { field_0xd0 = field_0xc8; diff --git a/src/d/d_menu_letter.cpp b/src/d/d_menu_letter.cpp index d0017558b3..f393fb0785 100644 --- a/src/d/d_menu_letter.cpp +++ b/src/d/d_menu_letter.cpp @@ -223,8 +223,13 @@ void dMenu_Letter_c::_draw() { f32 y1 = local_178.y; Vec local_184; local_184 = afStack_138.getGlobalVtx(field_0x1ec, &mtx, 3, false, 0); +#if TARGET_PC + f32 dVar17 = mDoGph_gInf_c::getWidthF() / mDoGph_gInf_c::getWidth(); + f32 dVar16 = mDoGph_gInf_c::getHeightF() / mDoGph_gInf_c::getHeight(); +#else f32 dVar17 = mDoGph_gInf_c::getWidthF() / FB_WIDTH; f32 dVar16 = mDoGph_gInf_c::getHeightF() / FB_HEIGHT; +#endif f32 fVar1 = (x1 - mDoGph_gInf_c::getMinXF()) / dVar17; f32 fVar2 = y1 / dVar16; grafContext->scissor(fVar1, fVar2, diff --git a/src/d/d_menu_option.cpp b/src/d/d_menu_option.cpp index 5e00afe208..9384bc06b9 100644 --- a/src/d/d_menu_option.cpp +++ b/src/d/d_menu_option.cpp @@ -24,6 +24,8 @@ #include "m_Do/m_Do_graphic.h" #include +#include "JSystem/JAudio2/JASDriverIF.h" + typedef void (dMenu_Option_c::*initFunc)(); static initFunc init[] = { &dMenu_Option_c::atten_init, @@ -89,7 +91,7 @@ dMenu_Option_c::dMenu_Option_c(JKRArchive* i_archive, STControl* i_stick) { dMenu_Option_c::~dMenu_Option_c() {} -static const u32 dMo_soundMode[3] = {0, 1, 2}; +static const u32 dMo_soundMode[3] = {JAS_OUTPUT_MONO, JAS_OUTPUT_STEREO, JAS_OUTPUT_SURROUND}; void dMenu_Option_c::_create() { static const u64 text_a_tag[5] = {MULTI_CHAR('atext1_1'), MULTI_CHAR('atext1_2'), MULTI_CHAR('atext1_3'), MULTI_CHAR('atext1_4'), MULTI_CHAR('atext1_5')}; @@ -553,13 +555,25 @@ void dMenu_Option_c::_draw() { #endif mpBlackTex->setAlpha(0xff); +#if TARGET_PC + mpBlackTex->draw(mDoGph_gInf_c::getMinXF(), mDoGph_gInf_c::getMinYF(), mDoGph_gInf_c::getWidthF(), mDoGph_gInf_c::getHeightF(), 0, 0, 0); +#else mpBlackTex->draw(0.0f, 0.0f, FB_WIDTH, FB_HEIGHT, 0, 0, 0); +#endif mpBackScreen->draw(0.0f, 0.0f, ctx); f32 alpha = (f32)g_drawHIO.mOptionScreen.mBackgroundAlpha * (f32)field_0x374; mpBlackTex->setAlpha(alpha); +#if TARGET_PC + mpBlackTex->draw(mDoGph_gInf_c::getMinXF(), mDoGph_gInf_c::getMinYF(), mDoGph_gInf_c::getWidthF(), mDoGph_gInf_c::getHeightF(), 0, 0, 0); +#else mpBlackTex->draw(0.0f, 0.0f, FB_WIDTH, FB_HEIGHT, 0, 0, 0); +#endif mpScreen->draw(0.0f, 0.0f, ctx); mpClipScreen->draw(0.0f, 0.0f, ctx); +#if TARGET_PC + ctx->scissor(0.0f, 0.0f, mDoGph_gInf_c::getWidth(), mDoGph_gInf_c::getHeight()); + ctx->setScissor(); +#endif mpShadowScreen->draw(0.0f, 0.0f, ctx); if (field_0x3f3 == 1 || field_0x3f3 == 2 || field_0x3f3 == 3) { mpTVScreen->draw(0.0f, 0.0f, ctx); @@ -1755,13 +1769,13 @@ void dMenu_Option_c::screenSet() { } } -void dMenu_Option_c::setSoundMode(u32 param_0) { - switch (param_0) { - case 0: +void dMenu_Option_c::setSoundMode(u32 soundMode) { + switch (soundMode) { + case JAS_OUTPUT_MONO: OSSetSoundMode(OS_SOUND_MODE_MONO); break; - case 1: - case 2: + case JAS_OUTPUT_STEREO: + case JAS_OUTPUT_SURROUND: // Via dolby pro logic 2, so it's over 2 output channels. OSSetSoundMode(OS_SOUND_MODE_STEREO); break; } diff --git a/src/d/d_menu_ring.cpp b/src/d/d_menu_ring.cpp index cad04d6ab6..3949adffed 100644 --- a/src/d/d_menu_ring.cpp +++ b/src/d/d_menu_ring.cpp @@ -1262,10 +1262,8 @@ void dMenu_Ring_c::drawItem() { (g_ringHIO.mItemAlphaMin + fVar16 * (g_ringHIO.mItemAlphaMax - g_ringHIO.mItemAlphaMin)); for (int i = 0; i < mItemsTotal; i++) { if (i != mCurrentSlot || (mStatus != STATUS_WAIT && mStatus != STATUS_EXPLAIN && mStatus != STATUS_EXPLAIN_FORCE)) { - #if REQUIRES_GX_LINES J2DDrawFrame(mItemSlotPosX[i] - 24.0f + mCenterPosX, mItemSlotPosY[i] - 24.0f + mCenterPosY, 48.0f, 48.0f, g_ringHIO.mItemFrame[g_ringHIO.UNSELECT_FRAME], 6); - #endif f32 fVar17 = 1.0f; if (i != mCurrentSlot) { fVar17 = ringAlpha / 255.0f; @@ -1308,10 +1306,8 @@ void dMenu_Ring_c::drawItem() { void dMenu_Ring_c::drawItem2() { s32 idx = mCurrentSlot; if (mStatus == STATUS_WAIT || mStatus == STATUS_EXPLAIN || mStatus == STATUS_EXPLAIN_FORCE) { - #if REQUIRES_GX_LINES J2DDrawFrame(mItemSlotPosX[idx] - 24.0f + mCenterPosX, mItemSlotPosY[idx] - 24.0f + mCenterPosY, 48.0f, 48.0f, g_ringHIO.mItemFrame[g_ringHIO.SELECT_FRAME], 6); - #endif for (int i = 0; i < 3; i++) { if (mpItemTex[idx][i] != NULL) { diff --git a/src/d/d_menu_save.cpp b/src/d/d_menu_save.cpp index ef1fb9d61e..618677866b 100644 --- a/src/d/d_menu_save.cpp +++ b/src/d/d_menu_save.cpp @@ -18,6 +18,7 @@ #include "m_Do/m_Do_controller_pad.h" #include "m_Do/m_Do_graphic.h" #include "d/d_msg_scrn_explain.h" +#include "dusk/settings.h" #include "JSystem/J2DGraph/J2DAnmLoader.h" #include "f_op/f_op_msg_mng.h" @@ -384,7 +385,12 @@ void dMenu_save_c::screenSet() { mSelectedFile = dComIfGs_getDataNum(); mSelIcon = JKR_NEW dSelect_cursor_c(0, 1.0f, NULL); + + #if TARGET_PC + mSelIcon->setParam(0.96f * mDoGph_gInf_c::hudAspectScaleUp, 0.94f, 0.03f, 0.7f, 0.7f); + #else mSelIcon->setParam(0.96f, 0.94f, 0.03f, 0.7f, 0.7f); + #endif Vec pos; pos = mpSelData[mSelectedFile]->getGlobalVtxCenter(false, 0); @@ -1177,7 +1183,7 @@ void dMenu_save_c::cardFormatYesSel2Disp() { bool moveAnm = yesnoMenuMoveAnm(); if (txtChangeAnm == true && moveAnm == true) { - mWaitTimer = g_msHIO.mCardWaitFrames; + mWaitTimer = dusk::getSettings().game.instantSaves ? 0 : g_msHIO.mCardWaitFrames; g_mDoMemCd_control.command_format(); mMenuProc = PROC_MEMCARD_FORMAT; } @@ -1249,7 +1255,7 @@ void dMenu_save_c::makeGameFileDisp() { bool ketteiDispAnm = ketteiTxtDispAnm(); if (txtChangeAnm == true && moveAnm == true && ketteiDispAnm == true) { - mWaitTimer = g_msHIO.mCardWaitFrames; + mWaitTimer = dusk::getSettings().game.instantSaves ? 0 : g_msHIO.mCardWaitFrames; setInitSaveData(); dataSave(); mMenuProc = PROC_MEMCARD_MAKE_GAME_FILE; @@ -1943,7 +1949,7 @@ void dMenu_save_c::saveMoveDisp() { if (headerTxtChanged == true && yesnoAnmComplete == true && ketteiAnmComplete == true && modoruAnmComplete == 1 && check == 1) { - mWaitTimer = g_msHIO.mCardWaitFrames; + mWaitTimer = dusk::getSettings().game.instantSaves ? 0 : g_msHIO.mCardWaitFrames; dataWrite(); mMenuProc = PROC_MEMCARD_DATA_SAVE_WAIT; } @@ -1961,7 +1967,7 @@ void dMenu_save_c::saveMoveDisp2() { if (headerTxtChanged == true && dataMoveAnm == true && wakuAnmComplete == true && ketteiAnmComplete == true && modoruAnmComplete == 1 && check == 1) { - mWaitTimer = g_msHIO.mCardWaitFrames; + mWaitTimer = dusk::getSettings().game.instantSaves ? 0 : g_msHIO.mCardWaitFrames; dataWrite(); mMenuProc = PROC_MEMCARD_DATA_SAVE_WAIT; } @@ -2516,7 +2522,12 @@ void dMenu_save_c::yesnoCursorShow() { Vec pos = mpNoYes[mYesNoCursor]->getGlobalVtxCenter(false, 0); mSelIcon->setPos(pos.x, pos.y, mpNoYes[mYesNoCursor]->getPanePtr(), true); mSelIcon->setAlphaRate(1.0f); + + #if TARGET_PC + mSelIcon->setParam(0.96f * mDoGph_gInf_c::hudAspectScaleUp, 0.84f, 0.06f, 0.5f, 0.5f); + #else mSelIcon->setParam(0.96f, 0.84f, 0.06f, 0.5f, 0.5f); + #endif } } @@ -2664,7 +2675,12 @@ void dMenu_save_c::selFileCursorShow() { Vec pos = mpSelData[mSelectedFile]->getGlobalVtxCenter(false, 0); mSelIcon->setPos(pos.x, pos.y, mpSelData[mSelectedFile]->getPanePtr(), true); mSelIcon->setAlphaRate(1.0f); + + #if TARGET_PC + mSelIcon->setParam(0.96f * mDoGph_gInf_c::hudAspectScaleUp, 0.94f, 0.03f, 0.7f, 0.7f); + #else mSelIcon->setParam(0.96f, 0.94f, 0.03f, 0.7f, 0.7f); + #endif } void dMenu_save_c::yesnoWakuAlpahAnmInit(u8 yesnoIdx, u8 startAlpha, u8 endAlpha, u8 anmTimer) { @@ -2763,6 +2779,43 @@ void dMenu_save_c::_draw() { } } +#if TARGET_PC +void dMenu_save_c::menuSaveWide() { + mSaveSel.Scr->scale(mDoGph_gInf_c::hudAspectScaleUp, 1.0f); + mSaveSel.Scr->translate(mDoGph_gInf_c::getMinXF(), 0.0f); + + mSaveSel.Scr->search(MULTI_CHAR('t_for'))->scale(mDoGph_gInf_c::hudAspectScaleDown, 1.0f); + mSaveSel.Scr->search(MULTI_CHAR('t_for1'))->scale(mDoGph_gInf_c::hudAspectScaleDown, 1.0f); + + mSaveSel.Scr->search(MULTI_CHAR('w_btn_n'))->scale(mDoGph_gInf_c::hudAspectScaleDown, 1.0f); + + mSaveSel.Scr->search(MULTI_CHAR('w_n_bk00'))->scale(mDoGph_gInf_c::hudAspectScaleDown, 1.0f); + mSaveSel.Scr->search(MULTI_CHAR('w_n_bk01'))->scale(mDoGph_gInf_c::hudAspectScaleDown, 1.0f); + mSaveSel.Scr->search(MULTI_CHAR('w_n_bk02'))->scale(mDoGph_gInf_c::hudAspectScaleDown, 1.0f); + + mSaveSel.Scr->search(MULTI_CHAR('w_dat_i0'))->scale(mDoGph_gInf_c::hudAspectScaleDown, 1.0f); + mSaveSel.Scr->search(MULTI_CHAR('w_dat_i1'))->scale(mDoGph_gInf_c::hudAspectScaleDown, 1.0f); + mSaveSel.Scr->search(MULTI_CHAR('w_dat_i2'))->scale(mDoGph_gInf_c::hudAspectScaleDown, 1.0f); + + mSaveSel.Scr->search(MULTI_CHAR('w_no_t'))->scale(mDoGph_gInf_c::hudAspectScaleDown, 1.0f); + mSaveSel.Scr->search(MULTI_CHAR('f_no_t'))->scale(mDoGph_gInf_c::hudAspectScaleDown, 1.0f); + mSaveSel.Scr->search(MULTI_CHAR('w_yes_t'))->scale(mDoGph_gInf_c::hudAspectScaleDown, 1.0f); + mSaveSel.Scr->search(MULTI_CHAR('f_yes_t'))->scale(mDoGph_gInf_c::hudAspectScaleDown, 1.0f); + + // Spirals + mSaveSel.Scr->search(MULTI_CHAR('w_uzu00'))->scale(mDoGph_gInf_c::hudAspectScaleDown, 1.0f); + mSaveSel.Scr->search(MULTI_CHAR('w_uzu01'))->scale(mDoGph_gInf_c::hudAspectScaleDown, 1.0f); + mSaveSel.Scr->search(MULTI_CHAR('w_uzu02'))->scale(mDoGph_gInf_c::hudAspectScaleDown, 1.0f); + mSaveSel.Scr->search(MULTI_CHAR('w_uzu03'))->scale(mDoGph_gInf_c::hudAspectScaleDown, 1.0f); + mSaveSel.Scr->search(MULTI_CHAR('w_uzu04'))->scale(mDoGph_gInf_c::hudAspectScaleDown, 1.0f); + mSaveSel.Scr->search(MULTI_CHAR('w_uzu05'))->scale(mDoGph_gInf_c::hudAspectScaleDown, 1.0f); + mSaveSel.Scr->search(MULTI_CHAR('w_uzu06'))->scale(mDoGph_gInf_c::hudAspectScaleDown, 1.0f); + mSaveSel.Scr->search(MULTI_CHAR('w_uzu07'))->scale(mDoGph_gInf_c::hudAspectScaleDown, 1.0f); + mSaveSel.Scr->search(MULTI_CHAR('w_uzu08'))->scale(mDoGph_gInf_c::hudAspectScaleDown, 1.0f); + mSaveSel.Scr->search(MULTI_CHAR('w_uzu09'))->scale(mDoGph_gInf_c::hudAspectScaleDown, 1.0f); +} +#endif + void dMenu_save_c::_draw2() { if (field_0x21a1 == 0) { if (mpScrnExplain != NULL) { @@ -2770,6 +2823,10 @@ void dMenu_save_c::_draw2() { } if (mDisplayMenu) { + #if TARGET_PC + menuSaveWide(); + #endif + dComIfGd_set2DOpa(&mSaveSel); for (int i = 0; i < 3; i++) { diff --git a/src/d/d_menu_skill.cpp b/src/d/d_menu_skill.cpp index cc22e136c7..78ab82af94 100644 --- a/src/d/d_menu_skill.cpp +++ b/src/d/d_menu_skill.cpp @@ -143,12 +143,26 @@ void dMenu_Skill_c::_draw() { J2DGrafContext* context = dComIfGp_getCurrentGrafPort(); u8 alpha = mpBlackTex->mAlpha; mpBlackTex->setAlpha(0xff); + + #if TARGET_PC + mpBlackTex->draw(mDoGph_gInf_c::getMinXF(), mDoGph_gInf_c::getMinYF(), + mDoGph_gInf_c::getWidthF(), mDoGph_gInf_c::getHeightF(), 0, 0, 0); + #else mpBlackTex->draw(0.0f, 0.0f, FB_WIDTH, FB_HEIGHT, 0, 0, 0); + #endif + mpBlackTex->setAlpha(alpha); mpMenuScreen->draw(mPosX, 0.0f, context); mpDrawCursor->draw(); if (mProcess == 1 || mProcess == 2 || mProcess == 3) { + + #if TARGET_PC + mpBlackTex->draw(mDoGph_gInf_c::getMinXF(), mDoGph_gInf_c::getMinYF(), + mDoGph_gInf_c::getWidthF(), mDoGph_gInf_c::getHeightF(), 0, 0, 0); + #else mpBlackTex->draw(0.0f, 0.0f, FB_WIDTH, FB_HEIGHT, 0, 0, 0); + #endif + mpLetterScreen->draw(0.0f, 0.0f, context); if (mStringID != 0) { mpString->getString(mStringID, (J2DTextBox*)mpTextPane->getPanePtr(), NULL, NULL, diff --git a/src/d/d_menu_window.cpp b/src/d/d_menu_window.cpp index 2244be6797..7fd5ea31a2 100644 --- a/src/d/d_menu_window.cpp +++ b/src/d/d_menu_window.cpp @@ -32,22 +32,37 @@ public: if (getDrawFlag() == 1) { setDrawFlag(); dComIfGp_onPauseFlag(); - + #if TARGET_PC GXSetTexCopySrc(0, 0, mDoGph_gInf_c::getWidth(), mDoGph_gInf_c::getHeight()); #else GXSetTexCopySrc(0, 0, FB_WIDTH, FB_HEIGHT); #endif +#if TARGET_PC + GXSetTexCopyDst(mDoGph_gInf_c::getWidth(), mDoGph_gInf_c::getHeight(), (GXTexFmt)mDoGph_gInf_c::getFrameBufferTimg()->format, GX_ENABLE); +#else GXSetTexCopyDst(FB_WIDTH / 2, FB_HEIGHT / 2, (GXTexFmt)mDoGph_gInf_c::getFrameBufferTimg()->format, GX_ENABLE); +#endif GXCopyTex(mDoGph_gInf_c::getFrameBufferTex(), GX_FALSE); GXPixModeSync(); +#if TARGET_PC + // init mTexObj at capture time so the gpu ref survives window resizes + GXInitTexObj(&mTexObj, mDoGph_gInf_c::getFrameBufferTex(), mDoGph_gInf_c::getWidth(), mDoGph_gInf_c::getHeight(), + (GXTexFmt)mDoGph_gInf_c::getFrameBufferTimg()->format, GX_CLAMP, GX_CLAMP, GX_FALSE); + GXInitTexObjLOD(&mTexObj, GX_LINEAR, GX_LINEAR, 0.0f, 0.0f, 0.0f, GX_FALSE, GX_FALSE, GX_ANISO_1); +#endif } else { +#if TARGET_PC + // reuse the persistent mTexObj + GXLoadTexObj(&mTexObj, GX_TEXMAP0); +#else TGXTexObj tex; GXInitTexObj(&tex, mDoGph_gInf_c::getFrameBufferTex(), FB_WIDTH / 2, FB_HEIGHT / 2, (GXTexFmt)mDoGph_gInf_c::getFrameBufferTimg()->format, GX_CLAMP, GX_CLAMP, GX_FALSE); GXInitTexObjLOD(&tex, GX_LINEAR, GX_LINEAR, 0.0f, 0.0f, 0.0f, GX_FALSE, GX_FALSE, GX_ANISO_1); GXLoadTexObj(&tex, GX_TEXMAP0); +#endif GXSetNumChans(0); GXSetNumTexGens(1); GXSetTexCoordGen2(GX_TEXCOORD0, GX_TG_MTX2x4, GX_TG_TEX0, 60, GX_FALSE, 125); @@ -110,6 +125,9 @@ private: /* 0x4 */ u8 mFlag; /* 0x5 */ u8 mAlpha; /* 0x6 */ u8 mTopFlag; +#if TARGET_PC + TGXTexObj mTexObj; +#endif }; BOOL dMw_UP_TRIGGER() { @@ -1498,7 +1516,11 @@ void dMw_c::checkMemSize() { OS_REPORT("memory check ===> diff ==> %d, start ==> %d, now ==> %d\n", diff, mMemSize, now_size); +#if TARGET_PC + if (diff > 0x40) { +#else if (diff > 0x20) { +#endif OSReport_Error("memory free error!!\n"); } mMemSize = 0; diff --git a/src/d/d_meter2_draw.cpp b/src/d/d_meter2_draw.cpp index f222ee752a..58c6e24dc9 100644 --- a/src/d/d_meter2_draw.cpp +++ b/src/d/d_meter2_draw.cpp @@ -564,6 +564,7 @@ void dMeter2Draw_c::exec(u32 i_status) { { mButtonsPosX = g_drawHIO.mMainHUDButtonsPosX; mButtonsPosY = g_drawHIO.mMainHUDButtonsPosY; + mpButtonParent->paneTrans(g_drawHIO.mMainHUDButtonsPosX, g_drawHIO.mMainHUDButtonsPosY); } @@ -1589,7 +1590,9 @@ void dMeter2Draw_c::drawKanteraScreen(u8 i_meterType) { mpMagicFrameR->move(field_0x59c[i_meterType], field_0x5a8[i_meterType]); mpMagicBase->resize(field_0x5b4[i_meterType], field_0x5c0[i_meterType]); mpMagicParent->scale(field_0x5cc[i_meterType], field_0x5d8[i_meterType]); + mpMagicParent->paneTrans(field_0x5e4[i_meterType], field_0x5f0[i_meterType]); + mpKanteraScreen->draw(0.0f, 0.0f, graf_ctx); } @@ -1854,6 +1857,7 @@ void dMeter2Draw_c::drawLightDrop(u8 i_num, u8 i_needNum, f32 i_posX, f32 i_posY mLightDropVesselScale = i_vesselScale; mpLightDropParent->scale(mLightDropVesselScale * field_0x6f8, mLightDropVesselScale * field_0x6f8); + mpLightDropParent->paneTrans(i_posX, i_posY); } @@ -2001,6 +2005,7 @@ void dMeter2Draw_c::drawRupee(s16 i_rupeeNum) { mpRupeeKeyParent->scale(g_drawHIO.mRupeeKeyScale * field_0x718, g_drawHIO.mRupeeKeyScale * field_0x718); + mpRupeeKeyParent->paneTrans(g_drawHIO.mRupeeKeyPosX, g_drawHIO.mRupeeKeyPosY); mpRupeeParent[0]->scale(g_drawHIO.mRupeeScale, g_drawHIO.mRupeeScale); @@ -2582,6 +2587,7 @@ void dMeter2Draw_c::drawButtonCross(f32 i_posX, f32 i_posY) { mpButtonCrossParent->scale(g_drawHIO.mButtonCrossScale, g_drawHIO.mButtonCrossScale); mpTextI->scale(g_drawHIO.mButtonCrossTextScale, g_drawHIO.mButtonCrossTextScale); mpTextM->scale(g_drawHIO.mButtonCrossTextScale, g_drawHIO.mButtonCrossTextScale); + mpButtonCrossParent->paneTrans(i_posX, i_posY); } diff --git a/src/d/d_meter2_info.cpp b/src/d/d_meter2_info.cpp index 61cf7ae5ee..7307755c04 100644 --- a/src/d/d_meter2_info.cpp +++ b/src/d/d_meter2_info.cpp @@ -11,6 +11,8 @@ #include "d/d_meter_map.h" #include "d/d_msg_class.h" #include "d/d_msg_object.h" +#include "d/d_meter_HIO.h" + #include enum ITEMICON_RES_FILE_ID { @@ -362,19 +364,18 @@ void dMeter2Info_c::getString(u32 i_stringID, char* o_string, JMSMesgEntry_c* i_ } JMSMesgInfo_c* bmg_inf = (JMSMesgInfo_c*)(msgRes + sizeof(bmg_header_t)); - u8* bmg_data = (u8*)bmg_inf + bmg_inf->header.size + sizeof(bmg_section_t); // pointer to start of message data + u8* bmg_data = (u8*)bmg_inf + bmg_inf->header.size; + u8* string_data = bmg_data + sizeof(bmg_section_t); // pointer to start of message data char* string_ptr = NULL; for (u16 i = 0; i < bmg_inf->entry_num; i++) { - u8* entry = ((u8*)bmg_inf + (i * sizeof(JMSMesgEntry_c))); - // check if i_stringID equals the message entry "Message ID" - if (i_stringID == *(BE(u16)*)(entry + 0x14)) { - string_ptr = (char*)(bmg_data + *(BE(u32)*)(entry + 0x10)); // use entry "String Offset" to get string pointer + if (i_stringID == bmg_inf->entries[i].message_id) { + string_ptr = (char*)(string_data + bmg_inf->entries[i].string_offset); // use entry "String Offset" to get string pointer strcpy(o_string, string_ptr); if (i_msgEntry != NULL) { - memcpy(i_msgEntry, entry + 0x10, sizeof(JMSMesgEntry_c)); + memcpy(i_msgEntry, &bmg_inf->entries[i], sizeof(JMSMesgEntry_c)); } return; @@ -508,6 +509,10 @@ void dMeter2Info_c::getStringKanji(u32 i_stringID, char* o_string, JMSMesgEntry_ } } +static void dummyString() { + OS_REPORT("レボ用ID=====>%d, %d\n"); +} + f32 dMeter2Info_c::getStringLength(J2DTextBox* i_textbox, char* i_string) { f32 str_width = 0.0f; f32 str_len = 0.0f; @@ -1003,6 +1008,104 @@ s16 dMeter2Info_c::get4thTexture(u8 i_itemType) { } void dMeter2Info_c::set1stColor(u8 i_itemType, J2DPicture* i_pic) { + // TODO: probably some way to rectify this for both versions + #if VERSION == VERSION_SHIELD_DEBUG + static JUtility::TColor const black_color[37] = { + JUtility::TColor(0x00, 0x00, 0x00, 0x00), JUtility::TColor(0x00, 0x60, 0x00, 0x00), JUtility::TColor(0x00, 0x00, 0xC0, 0x00), + JUtility::TColor(0xA0, 0x60, 0x00, 0x00), JUtility::TColor(0xA0, 0x00, 0x00, 0x00), JUtility::TColor(0x40, 0x00, 0x60, 0x00), + JUtility::TColor(0xE0, 0x00, 0x00, 0x00), JUtility::TColor(0x40, 0x40, 0x40, 0x00), JUtility::TColor(0x6E, 0x6E, 0x64, 0x00), + JUtility::TColor(0x32, 0x00, 0x00, 0x00), JUtility::TColor(0x00, 0x7F, 0x00, 0x00), JUtility::TColor(0x00, 0x00, 0x7F, 0x00), + JUtility::TColor(0xAF, 0x9B, 0x6E, 0x00), JUtility::TColor(0xAA, 0x9B, 0x6E, 0x00), JUtility::TColor(0x55, 0x37, 0x14, 0x00), + JUtility::TColor(0x6E, 0x6E, 0x6E, 0x00), JUtility::TColor(0x6E, 0x6E, 0x6E, 0x00), JUtility::TColor(0xFF, 0x58, 0x00, 0x00), + JUtility::TColor(0x6C, 0x3E, 0x00, 0x00), JUtility::TColor(0x00, 0x00, 0x00, 0x00), JUtility::TColor(0x32, 0x00, 0x00, 0x00), + JUtility::TColor(0x00, 0x00, 0x7F, 0x00), JUtility::TColor(0x00, 0x7F, 0x00, 0x00), JUtility::TColor(0x55, 0x37, 0x14, 0x00), + JUtility::TColor(0x00, 0x00, 0x22, 0x00), JUtility::TColor(0x2B, 0x18, 0x22, 0x00), JUtility::TColor(0x00, 0x00, 0x00, 0x00), + JUtility::TColor(0x46, 0x46, 0x41, 0x00), JUtility::TColor(0x46, 0x46, 0x41, 0x00), JUtility::TColor(0x46, 0x46, 0x41, 0x00), + JUtility::TColor(0x46, 0x46, 0x41, 0x00), JUtility::TColor(0x00, 0x00, 0x00, 0x00), JUtility::TColor(0x00, 0x00, 0x00, 0x00), + JUtility::TColor(0x00, 0x00, 0x00, 0x00), JUtility::TColor(0x00, 0x00, 0x00, 0x00), JUtility::TColor(0x00, 0x00, 0x00, 0x00), + JUtility::TColor(0x00, 0x00, 0x00, 0x00), + }; + + static JUtility::TColor const white_color[37] = { + JUtility::TColor(0xFF, 0xFF, 0xFF, 0xFF), JUtility::TColor(0x60, 0xFF, 0x00, 0xFF), JUtility::TColor(0x00, 0xFF, 0xFF, 0xFF), + JUtility::TColor(0xFF, 0xFF, 0x00, 0xFF), JUtility::TColor(0xFF, 0x80, 0x80, 0xFF), JUtility::TColor(0xBE, 0x40, 0xFF, 0xFF), + JUtility::TColor(0xFF, 0xC0, 0x00, 0xFF), JUtility::TColor(0xC0, 0xC0, 0xC0, 0xFF), JUtility::TColor(0xF5, 0xF5, 0xFF, 0xFF), + JUtility::TColor(0xFF, 0xD2, 0xAA, 0xFF), JUtility::TColor(0xEF, 0xF5, 0xC9, 0xFF), JUtility::TColor(0xB0, 0xFF, 0xFF, 0xFF), + JUtility::TColor(0xFF, 0xFF, 0xF0, 0xFF), JUtility::TColor(0xFF, 0xFF, 0xF0, 0xFF), JUtility::TColor(0xFF, 0xFF, 0xD7, 0xFF), + JUtility::TColor(0xF5, 0xF5, 0xFF, 0xFF), JUtility::TColor(0xF5, 0xF5, 0xFF, 0xFF), JUtility::TColor(0xFF, 0xFF, 0xC2, 0xFF), + JUtility::TColor(0xFF, 0x9D, 0x00, 0xFF), JUtility::TColor(0xC8, 0xC8, 0xC8, 0xFF), JUtility::TColor(0xFF, 0xD2, 0xAA, 0xFF), + JUtility::TColor(0xB0, 0xFF, 0xFF, 0xFF), JUtility::TColor(0xEF, 0xF5, 0xC9, 0xFF), JUtility::TColor(0xFF, 0xFF, 0xD7, 0xFF), + JUtility::TColor(0xD7, 0xCF, 0xF5, 0xFF), JUtility::TColor(0xFF, 0xFF, 0x33, 0xFF), JUtility::TColor(0xC8, 0xC8, 0xC8, 0xFF), + JUtility::TColor(0xF5, 0xF5, 0xFF, 0xFF), JUtility::TColor(0xF5, 0xF5, 0xFF, 0xFF), JUtility::TColor(0xF5, 0xF5, 0xFF, 0xFF), + JUtility::TColor(0xF5, 0xF5, 0xFF, 0xFF), JUtility::TColor(0xFF, 0xFF, 0xFF, 0xFF), JUtility::TColor(0xFF, 0xFF, 0xFF, 0xFF), + JUtility::TColor(0xFF, 0xFF, 0xFF, 0xFF), JUtility::TColor(0xFF, 0xFF, 0xFF, 0xFF), JUtility::TColor(0xFF, 0xFF, 0xFF, 0xFF), + JUtility::TColor(0xFF, 0xFF, 0xFF, 0xFF), + }; + + static JUtility::TColor const vertex_color_lu[37] = { + JUtility::TColor(0xFF, 0xFF, 0xFF, 0xFF), JUtility::TColor(0xFF, 0xFF, 0xFF, 0xFF), JUtility::TColor(0xFF, 0xFF, 0xFF, 0xFF), + JUtility::TColor(0xFF, 0xFF, 0xFF, 0xFF), JUtility::TColor(0xFF, 0xFF, 0xFF, 0xFF), JUtility::TColor(0xFF, 0xFF, 0xFF, 0xFF), + JUtility::TColor(0xFF, 0xFF, 0xFF, 0xFF), JUtility::TColor(0xFF, 0xFF, 0xFF, 0xFF), JUtility::TColor(0xFF, 0xFF, 0xFF, 0x00), + JUtility::TColor(0xFF, 0x78, 0xAF, 0xFF), JUtility::TColor(0x5C, 0xB4, 0x16, 0xFF), JUtility::TColor(0xA4, 0xFF, 0x00, 0xFF), + JUtility::TColor(0xFF, 0xFF, 0xFF, 0xFF), JUtility::TColor(0xFF, 0xFF, 0xFF, 0xFF), JUtility::TColor(0xFF, 0xFF, 0x00, 0xFF), + JUtility::TColor(0xFF, 0xFF, 0xFF, 0xFF), JUtility::TColor(0xFF, 0xFF, 0xFF, 0xFF), JUtility::TColor(0xFF, 0xFF, 0xFF, 0xFF), + JUtility::TColor(0xFF, 0xFF, 0xFF, 0xFF), JUtility::TColor(0xFF, 0xFF, 0xFF, 0xFF), JUtility::TColor(0xFF, 0x78, 0xAF, 0xFF), + JUtility::TColor(0xA4, 0xFF, 0x00, 0xFF), JUtility::TColor(0x5C, 0xB4, 0x16, 0xFF), JUtility::TColor(0xFF, 0xFF, 0x00, 0xFF), + JUtility::TColor(0xC9, 0xB4, 0xFF, 0xFF), JUtility::TColor(0x3C, 0x0A, 0x00, 0xFF), JUtility::TColor(0xFF, 0xFF, 0xFF, 0xFF), + JUtility::TColor(0xFF, 0xFF, 0xFF, 0x00), JUtility::TColor(0xFF, 0xFF, 0xFF, 0x00), JUtility::TColor(0xFF, 0xFF, 0xFF, 0x00), + JUtility::TColor(0xFF, 0xFF, 0xFF, 0x00), JUtility::TColor(0xFF, 0xA0, 0xFF, 0xFF), JUtility::TColor(0xFF, 0xFF, 0xFF, 0xFF), + JUtility::TColor(0xFF, 0xFF, 0xFF, 0xFF), JUtility::TColor(0xFF, 0xFF, 0xFF, 0xFF), JUtility::TColor(0xFF, 0xFF, 0xFF, 0xFF), + JUtility::TColor(0xFF, 0xFF, 0xFF, 0xFF), + }; + + static JUtility::TColor const vertex_color_ru[37] = { + JUtility::TColor(0xFF, 0xFF, 0xFF, 0xFF), JUtility::TColor(0xFF, 0xFF, 0xFF, 0xFF), JUtility::TColor(0xFF, 0xFF, 0xFF, 0xFF), + JUtility::TColor(0xFF, 0xFF, 0xFF, 0xFF), JUtility::TColor(0xFF, 0xFF, 0xFF, 0xFF), JUtility::TColor(0xFF, 0xFF, 0xFF, 0xFF), + JUtility::TColor(0xFF, 0xFF, 0xFF, 0xFF), JUtility::TColor(0xFF, 0xFF, 0xFF, 0xFF), JUtility::TColor(0xFF, 0xFF, 0xFF, 0x00), + JUtility::TColor(0xFF, 0xFF, 0x73, 0xFF), JUtility::TColor(0xFF, 0xFF, 0x2A, 0xFF), JUtility::TColor(0x98, 0xFF, 0x00, 0xFF), + JUtility::TColor(0xFF, 0xFF, 0xFF, 0xFF), JUtility::TColor(0xFF, 0xFF, 0xFF, 0xFF), JUtility::TColor(0xFF, 0xFF, 0xFF, 0xFF), + JUtility::TColor(0xFF, 0xFF, 0xFF, 0xFF), JUtility::TColor(0xFF, 0xFF, 0xFF, 0xFF), JUtility::TColor(0xFF, 0xFF, 0xFF, 0xFF), + JUtility::TColor(0xFF, 0xFF, 0xFF, 0xFF), JUtility::TColor(0xFF, 0xFF, 0xFF, 0xFF), JUtility::TColor(0xFF, 0xFF, 0x73, 0xFF), + JUtility::TColor(0x98, 0xFF, 0x00, 0xFF), JUtility::TColor(0xFF, 0xFF, 0x2A, 0xFF), JUtility::TColor(0xFF, 0xFF, 0xFF, 0xFF), + JUtility::TColor(0xFF, 0xFF, 0x39, 0xFF), JUtility::TColor(0xFF, 0xFF, 0x00, 0xFF), JUtility::TColor(0xFF, 0xFF, 0xFF, 0xFF), + JUtility::TColor(0xFF, 0xFF, 0xFF, 0x00), JUtility::TColor(0xFF, 0xFF, 0xFF, 0x00), JUtility::TColor(0xFF, 0xFF, 0xFF, 0x00), + JUtility::TColor(0xFF, 0xFF, 0xFF, 0x00), JUtility::TColor(0xFF, 0xA0, 0xFF, 0xFF), JUtility::TColor(0xFF, 0xFF, 0xFF, 0xFF), + JUtility::TColor(0xFF, 0xFF, 0xFF, 0xFF), JUtility::TColor(0xFF, 0xFF, 0xFF, 0xFF), JUtility::TColor(0xFF, 0xFF, 0xFF, 0xFF), + JUtility::TColor(0xFF, 0xFF, 0xFF, 0xFF), + }; + + static JUtility::TColor const vertex_color_ld[37] = { + JUtility::TColor(0xFF, 0xFF, 0xFF, 0xFF), JUtility::TColor(0xFF, 0xFF, 0xFF, 0xFF), JUtility::TColor(0xFF, 0xFF, 0xFF, 0xFF), + JUtility::TColor(0xFF, 0xFF, 0xFF, 0xFF), JUtility::TColor(0xFF, 0xFF, 0xFF, 0xFF), JUtility::TColor(0xFF, 0xFF, 0xFF, 0xFF), + JUtility::TColor(0xFF, 0xFF, 0xFF, 0xFF), JUtility::TColor(0xFF, 0xFF, 0xFF, 0xFF), JUtility::TColor(0x78, 0x6E, 0x3C, 0xFF), + JUtility::TColor(0xFF, 0x00, 0x00, 0xFF), JUtility::TColor(0x3C, 0x32, 0x50, 0xFF), JUtility::TColor(0x00, 0x00, 0x74, 0xFF), + JUtility::TColor(0xFA, 0xC8, 0x9B, 0xFF), JUtility::TColor(0xFA, 0xC8, 0x9B, 0xFF), JUtility::TColor(0x46, 0x87, 0x00, 0xFF), + JUtility::TColor(0x5A, 0xB4, 0xB4, 0xFF), JUtility::TColor(0x5A, 0xB4, 0xB4, 0xFF), JUtility::TColor(0xFF, 0xFF, 0xFF, 0xFF), + JUtility::TColor(0xFF, 0xFF, 0xFF, 0xFF), JUtility::TColor(0x00, 0x00, 0x00, 0xFF), JUtility::TColor(0xFF, 0x00, 0x00, 0xFF), + JUtility::TColor(0x00, 0x00, 0x74, 0xFF), JUtility::TColor(0x3C, 0x32, 0x50, 0xFF), JUtility::TColor(0x46, 0x87, 0x00, 0xFF), + JUtility::TColor(0x3C, 0x32, 0x50, 0x49), JUtility::TColor(0xFF, 0xFF, 0x00, 0xFF), JUtility::TColor(0x00, 0x00, 0x00, 0xFF), + JUtility::TColor(0x00, 0x00, 0x00, 0xFF), JUtility::TColor(0x00, 0x00, 0x00, 0xFF), JUtility::TColor(0x00, 0x00, 0x00, 0xFF), + JUtility::TColor(0x00, 0x00, 0x00, 0xFF), JUtility::TColor(0xE0, 0x00, 0xE0, 0xFF), JUtility::TColor(0xFF, 0xFF, 0xFF, 0xFF), + JUtility::TColor(0xFF, 0xFF, 0xFF, 0xFF), JUtility::TColor(0xFF, 0xFF, 0xFF, 0xFF), JUtility::TColor(0xFF, 0xFF, 0xFF, 0xFF), + JUtility::TColor(0xFF, 0xFF, 0xFF, 0xFF), + }; + + static JUtility::TColor const vertex_color_rd[37] = { + JUtility::TColor(0xFF, 0xFF, 0xFF, 0xFF), JUtility::TColor(0xFF, 0xFF, 0xFF, 0xFF), JUtility::TColor(0xFF, 0xFF, 0xFF, 0xFF), + JUtility::TColor(0xFF, 0xFF, 0xFF, 0xFF), JUtility::TColor(0xFF, 0xFF, 0xFF, 0xFF), JUtility::TColor(0xFF, 0xFF, 0xFF, 0xFF), + JUtility::TColor(0xFF, 0xFF, 0xFF, 0xFF), JUtility::TColor(0xFF, 0xFF, 0xFF, 0xFF), JUtility::TColor(0x78, 0x6E, 0x3C, 0xFF), + JUtility::TColor(0xFF, 0x96, 0x00, 0xFF), JUtility::TColor(0x55, 0x42, 0x00, 0xFF), JUtility::TColor(0x61, 0x48, 0xFF, 0xFF), + JUtility::TColor(0xFF, 0xFF, 0xAA, 0xFF), JUtility::TColor(0xFF, 0xFF, 0xAA, 0xFF), JUtility::TColor(0xAF, 0x91, 0x23, 0xFF), + JUtility::TColor(0xE6, 0xFA, 0xFF, 0xFF), JUtility::TColor(0xE6, 0xFA, 0xFF, 0xFF), JUtility::TColor(0xFF, 0xFF, 0xFF, 0xFF), + JUtility::TColor(0xFF, 0xFF, 0xFF, 0xFF), JUtility::TColor(0x00, 0x00, 0x00, 0xFF), JUtility::TColor(0xFF, 0x96, 0x00, 0xFF), + JUtility::TColor(0x61, 0x48, 0xFF, 0xFF), JUtility::TColor(0x55, 0x42, 0x00, 0xFF), JUtility::TColor(0xAF, 0x91, 0x23, 0xFF), + JUtility::TColor(0x3C, 0x09, 0x4E, 0xFF), JUtility::TColor(0xBA, 0x98, 0x00, 0xFF), JUtility::TColor(0x00, 0x00, 0x00, 0xFF), + JUtility::TColor(0x00, 0x00, 0x00, 0xFF), JUtility::TColor(0x00, 0x00, 0x00, 0xFF), JUtility::TColor(0x00, 0x00, 0x00, 0xFF), + JUtility::TColor(0x00, 0x00, 0x00, 0xFF), JUtility::TColor(0xE0, 0x00, 0xE0, 0xFF), JUtility::TColor(0xFF, 0xFF, 0xFF, 0xFF), + JUtility::TColor(0xFF, 0xFF, 0xFF, 0xFF), JUtility::TColor(0xFF, 0xFF, 0xFF, 0xFF), JUtility::TColor(0xFF, 0xFF, 0xFF, 0xFF), + JUtility::TColor(0xFF, 0xFF, 0xFF, 0xFF), + }; + #else static GXColor const black_color[37] = { {0x00, 0x00, 0x00, 0x00}, {0x00, 0x60, 0x00, 0x00}, {0x00, 0x00, 0xC0, 0x00}, {0xA0, 0x60, 0x00, 0x00}, {0xA0, 0x00, 0x00, 0x00}, {0x40, 0x00, 0x60, 0x00}, @@ -1098,6 +1201,7 @@ void dMeter2Info_c::set1stColor(u8 i_itemType, J2DPicture* i_pic) { {0xFF, 0xFF, 0xFF, 0xFF}, {0xFF, 0xFF, 0xFF, 0xFF}, {0xFF, 0xFF, 0xFF, 0xFF}, {0xFF, 0xFF, 0xFF, 0xFF}, }; + #endif i_pic->setBlackWhite(*(JUtility::TColor*)&black_color[i_itemType], *(JUtility::TColor*)&white_color[i_itemType]); @@ -1108,6 +1212,104 @@ void dMeter2Info_c::set1stColor(u8 i_itemType, J2DPicture* i_pic) { } void dMeter2Info_c::set2ndColor(u8 i_itemType, J2DPicture* i_pic) { + // TODO: probably some way to rectify this for both versions + #if VERSION == VERSION_SHIELD_DEBUG + static JUtility::TColor const black_color[37] = { + JUtility::TColor(0x00, 0x00, 0x00, 0x00), JUtility::TColor(0x00, 0x00, 0x00, 0x00), JUtility::TColor(0x00, 0x00, 0x00, 0x00), + JUtility::TColor(0x00, 0x00, 0x00, 0x00), JUtility::TColor(0x00, 0x00, 0x00, 0x00), JUtility::TColor(0x00, 0x00, 0x00, 0x00), + JUtility::TColor(0x00, 0x00, 0x00, 0x00), JUtility::TColor(0x00, 0x00, 0x00, 0x00), JUtility::TColor(0x00, 0x00, 0x00, 0x00), + JUtility::TColor(0x00, 0x00, 0x00, 0x00), JUtility::TColor(0x00, 0x00, 0x00, 0x00), JUtility::TColor(0x00, 0x00, 0x00, 0x00), + JUtility::TColor(0x00, 0x00, 0x00, 0x00), JUtility::TColor(0x00, 0x00, 0x00, 0x00), JUtility::TColor(0x00, 0x00, 0x00, 0x00), + JUtility::TColor(0x00, 0x00, 0x00, 0x00), JUtility::TColor(0x00, 0x00, 0x00, 0x00), JUtility::TColor(0x00, 0x00, 0x00, 0x00), + JUtility::TColor(0x00, 0x00, 0x00, 0x00), JUtility::TColor(0x00, 0x00, 0x00, 0x00), JUtility::TColor(0x00, 0x00, 0x00, 0x00), + JUtility::TColor(0x00, 0x00, 0x00, 0x00), JUtility::TColor(0x00, 0x00, 0x00, 0x00), JUtility::TColor(0x00, 0x00, 0x00, 0x00), + JUtility::TColor(0x00, 0x00, 0x00, 0x00), JUtility::TColor(0x00, 0x00, 0x00, 0x00), JUtility::TColor(0x00, 0x00, 0x00, 0x00), + JUtility::TColor(0x00, 0x86, 0xD4, 0x00), JUtility::TColor(0xE6, 0x1E, 0xFF, 0x00), JUtility::TColor(0x00, 0x00, 0x00, 0x00), + JUtility::TColor(0x00, 0x00, 0x00, 0x00), JUtility::TColor(0x00, 0x00, 0x00, 0x00), JUtility::TColor(0x00, 0x00, 0x00, 0x00), + JUtility::TColor(0x00, 0x00, 0x00, 0x00), JUtility::TColor(0x00, 0x00, 0x00, 0x00), JUtility::TColor(0x00, 0x00, 0x00, 0x00), + JUtility::TColor(0x00, 0x00, 0x00, 0x00), + }; + + static JUtility::TColor const white_color[37] = { + JUtility::TColor(0xFF, 0xFF, 0xFF, 0xFF), JUtility::TColor(0xFF, 0xFF, 0xFF, 0xFF), JUtility::TColor(0xFF, 0xFF, 0xFF, 0xFF), + JUtility::TColor(0xFF, 0xFF, 0xFF, 0xFF), JUtility::TColor(0xFF, 0xFF, 0xFF, 0xFF), JUtility::TColor(0xFF, 0xFF, 0xFF, 0xFF), + JUtility::TColor(0xFF, 0xFF, 0xFF, 0xFF), JUtility::TColor(0xFF, 0xFF, 0xFF, 0xFF), JUtility::TColor(0xFF, 0xFF, 0xFF, 0xFF), + JUtility::TColor(0xFF, 0xFF, 0xFF, 0xFF), JUtility::TColor(0xFF, 0xFF, 0xFF, 0xFF), JUtility::TColor(0xFF, 0xFF, 0xFF, 0xFF), + JUtility::TColor(0xFF, 0xFF, 0xFF, 0xFF), JUtility::TColor(0xFF, 0xFF, 0xFF, 0xFF), JUtility::TColor(0xFF, 0xFF, 0xFF, 0xFF), + JUtility::TColor(0xFF, 0xFF, 0xFF, 0xFF), JUtility::TColor(0xFF, 0xFF, 0xFF, 0xFF), JUtility::TColor(0xFF, 0xFF, 0xFF, 0xFF), + JUtility::TColor(0xFF, 0xFF, 0xFF, 0xFF), JUtility::TColor(0xFF, 0xFF, 0xFF, 0xFF), JUtility::TColor(0xFF, 0xFF, 0xFF, 0xFF), + JUtility::TColor(0xFF, 0xFF, 0xFF, 0xFF), JUtility::TColor(0xFF, 0xFF, 0xFF, 0xFF), JUtility::TColor(0xFF, 0xFF, 0xFF, 0xFF), + JUtility::TColor(0xFF, 0xFF, 0xFF, 0xFF), JUtility::TColor(0xFF, 0xFF, 0xFF, 0xFF), JUtility::TColor(0xFF, 0xFF, 0xFF, 0xFF), + JUtility::TColor(0xF5, 0xFF, 0xFF, 0xFF), JUtility::TColor(0xFF, 0xFF, 0xC8, 0xFF), JUtility::TColor(0xFF, 0xFF, 0xFF, 0xFF), + JUtility::TColor(0xFF, 0xFF, 0xFF, 0xFF), JUtility::TColor(0xFF, 0xFF, 0xFF, 0xFF), JUtility::TColor(0xFF, 0xFF, 0xFF, 0xFF), + JUtility::TColor(0xFF, 0xFF, 0xFF, 0xFF), JUtility::TColor(0xFF, 0xFF, 0xFF, 0xFF), JUtility::TColor(0xFF, 0xFF, 0xFF, 0xFF), + JUtility::TColor(0xFF, 0xFF, 0xFF, 0xFF), + }; + + static JUtility::TColor const vertex_color_lu[37] = { + JUtility::TColor(0xFF, 0xFF, 0xFF, 0xFF), JUtility::TColor(0xFF, 0xFF, 0xFF, 0xFF), JUtility::TColor(0xFF, 0xFF, 0xFF, 0xFF), + JUtility::TColor(0xFF, 0xFF, 0xFF, 0xFF), JUtility::TColor(0xFF, 0xFF, 0xFF, 0xFF), JUtility::TColor(0xFF, 0xFF, 0xFF, 0xFF), + JUtility::TColor(0xFF, 0xFF, 0xFF, 0xFF), JUtility::TColor(0xFF, 0xFF, 0xFF, 0xFF), JUtility::TColor(0xFF, 0xFF, 0xFF, 0xFF), + JUtility::TColor(0xFF, 0xFF, 0xFF, 0xFF), JUtility::TColor(0xFF, 0xFF, 0xFF, 0xFF), JUtility::TColor(0xFF, 0xFF, 0xFF, 0xFF), + JUtility::TColor(0xFF, 0xFF, 0xFF, 0xFF), JUtility::TColor(0xFF, 0xFF, 0xFF, 0xFF), JUtility::TColor(0xFF, 0xFF, 0xFF, 0xFF), + JUtility::TColor(0xFF, 0xFF, 0xFF, 0xFF), JUtility::TColor(0xFF, 0xFF, 0xFF, 0xFF), JUtility::TColor(0xFF, 0xFF, 0xFF, 0xFF), + JUtility::TColor(0xFF, 0xFF, 0xFF, 0xFF), JUtility::TColor(0xFF, 0xFF, 0xFF, 0xFF), JUtility::TColor(0xFF, 0xFF, 0xFF, 0xFF), + JUtility::TColor(0xFF, 0xFF, 0xFF, 0xFF), JUtility::TColor(0xFF, 0xFF, 0xFF, 0xFF), JUtility::TColor(0xFF, 0xFF, 0xFF, 0xFF), + JUtility::TColor(0xFF, 0xFF, 0xFF, 0xFF), JUtility::TColor(0xFF, 0xFF, 0xFF, 0xFF), JUtility::TColor(0xFF, 0xFF, 0xFF, 0xFF), + JUtility::TColor(0x00, 0x00, 0xFF, 0xFF), JUtility::TColor(0xFF, 0xFF, 0xFF, 0xFF), JUtility::TColor(0xFF, 0xFF, 0xFF, 0xFF), + JUtility::TColor(0xFF, 0xFF, 0xFF, 0xFF), JUtility::TColor(0xFF, 0xFF, 0xFF, 0xFF), JUtility::TColor(0xFF, 0xFF, 0xFF, 0xFF), + JUtility::TColor(0xFF, 0xFF, 0xFF, 0xFF), JUtility::TColor(0xFF, 0xFF, 0xFF, 0xFF), JUtility::TColor(0xFF, 0xFF, 0xFF, 0xFF), + JUtility::TColor(0xFF, 0xFF, 0xFF, 0xFF), + }; + + static JUtility::TColor const vertex_color_ru[37] = { + JUtility::TColor(0xFF, 0xFF, 0xFF, 0xFF), JUtility::TColor(0xFF, 0xFF, 0xFF, 0xFF), JUtility::TColor(0xFF, 0xFF, 0xFF, 0xFF), + JUtility::TColor(0xFF, 0xFF, 0xFF, 0xFF), JUtility::TColor(0xFF, 0xFF, 0xFF, 0xFF), JUtility::TColor(0xFF, 0xFF, 0xFF, 0xFF), + JUtility::TColor(0xFF, 0xFF, 0xFF, 0xFF), JUtility::TColor(0xFF, 0xFF, 0xFF, 0xFF), JUtility::TColor(0xFF, 0xFF, 0xFF, 0xFF), + JUtility::TColor(0xFF, 0xFF, 0xFF, 0xFF), JUtility::TColor(0xFF, 0xFF, 0xFF, 0xFF), JUtility::TColor(0xFF, 0xFF, 0xFF, 0xFF), + JUtility::TColor(0xFF, 0xFF, 0xFF, 0xFF), JUtility::TColor(0xFF, 0xFF, 0xFF, 0xFF), JUtility::TColor(0xFF, 0xFF, 0xFF, 0xFF), + JUtility::TColor(0xFF, 0xFF, 0xFF, 0xFF), JUtility::TColor(0xFF, 0xFF, 0xFF, 0xFF), JUtility::TColor(0xFF, 0xFF, 0xFF, 0xFF), + JUtility::TColor(0xFF, 0xFF, 0xFF, 0xFF), JUtility::TColor(0xFF, 0xFF, 0xFF, 0xFF), JUtility::TColor(0xFF, 0xFF, 0xFF, 0xFF), + JUtility::TColor(0xFF, 0xFF, 0xFF, 0xFF), JUtility::TColor(0xFF, 0xFF, 0xFF, 0xFF), JUtility::TColor(0xFF, 0xFF, 0xFF, 0xFF), + JUtility::TColor(0xFF, 0xFF, 0xFF, 0xFF), JUtility::TColor(0xFF, 0xFF, 0xFF, 0xFF), JUtility::TColor(0xFF, 0xFF, 0xFF, 0xFF), + JUtility::TColor(0x00, 0xFF, 0xFF, 0x58), JUtility::TColor(0xFF, 0xFF, 0xFF, 0x58), JUtility::TColor(0xFF, 0xFF, 0xFF, 0x58), + JUtility::TColor(0xFF, 0xFF, 0xFF, 0x58), JUtility::TColor(0xFF, 0xFF, 0xFF, 0xFF), JUtility::TColor(0xFF, 0xFF, 0xFF, 0xFF), + JUtility::TColor(0xFF, 0xFF, 0xFF, 0xFF), JUtility::TColor(0xFF, 0xFF, 0xFF, 0xFF), JUtility::TColor(0xFF, 0xFF, 0xFF, 0xFF), + JUtility::TColor(0xFF, 0xFF, 0xFF, 0xFF), + }; + + static JUtility::TColor const vertex_color_ld[37] = { + JUtility::TColor(0xFF, 0xFF, 0xFF, 0xFF), JUtility::TColor(0xFF, 0xFF, 0xFF, 0xFF), JUtility::TColor(0xFF, 0xFF, 0xFF, 0xFF), + JUtility::TColor(0xFF, 0xFF, 0xFF, 0xFF), JUtility::TColor(0xFF, 0xFF, 0xFF, 0xFF), JUtility::TColor(0xFF, 0xFF, 0xFF, 0xFF), + JUtility::TColor(0xFF, 0xFF, 0xFF, 0xFF), JUtility::TColor(0xFF, 0xFF, 0xFF, 0xFF), JUtility::TColor(0xFF, 0xFF, 0xFF, 0xFF), + JUtility::TColor(0xFF, 0xFF, 0xFF, 0xFF), JUtility::TColor(0xFF, 0xFF, 0xFF, 0xFF), JUtility::TColor(0xFF, 0xFF, 0xFF, 0xFF), + JUtility::TColor(0xFF, 0xFF, 0xFF, 0xFF), JUtility::TColor(0xFF, 0xFF, 0xFF, 0xFF), JUtility::TColor(0xFF, 0xFF, 0xFF, 0xFF), + JUtility::TColor(0xFF, 0xFF, 0xFF, 0xFF), JUtility::TColor(0xFF, 0xFF, 0xFF, 0xFF), JUtility::TColor(0xFF, 0xFF, 0xFF, 0xFF), + JUtility::TColor(0xFF, 0xFF, 0xFF, 0xFF), JUtility::TColor(0xFF, 0xFF, 0xFF, 0xFF), JUtility::TColor(0xFF, 0xFF, 0xFF, 0xFF), + JUtility::TColor(0xFF, 0xFF, 0xFF, 0xFF), JUtility::TColor(0xFF, 0xFF, 0xFF, 0xFF), JUtility::TColor(0xFF, 0xFF, 0xFF, 0xFF), + JUtility::TColor(0xFF, 0xFF, 0xFF, 0xFF), JUtility::TColor(0xFF, 0xFF, 0xFF, 0xFF), JUtility::TColor(0xFF, 0xFF, 0xFF, 0xFF), + JUtility::TColor(0xFF, 0xFF, 0xFF, 0xFF), JUtility::TColor(0xFF, 0xFF, 0xFF, 0xFF), JUtility::TColor(0xFF, 0xFF, 0xFF, 0xFF), + JUtility::TColor(0xFF, 0xFF, 0xFF, 0xFF), JUtility::TColor(0xFF, 0xFF, 0xFF, 0xFF), JUtility::TColor(0xFF, 0xFF, 0xFF, 0xFF), + JUtility::TColor(0xFF, 0xFF, 0xFF, 0xFF), JUtility::TColor(0xFF, 0xFF, 0xFF, 0xFF), JUtility::TColor(0xFF, 0xFF, 0xFF, 0xFF), + JUtility::TColor(0xFF, 0xFF, 0xFF, 0xFF), + }; + + static JUtility::TColor const vertex_color_rd[37] = { + JUtility::TColor(0xFF, 0xFF, 0xFF, 0xFF), JUtility::TColor(0xFF, 0xFF, 0xFF, 0xFF), JUtility::TColor(0xFF, 0xFF, 0xFF, 0xFF), + JUtility::TColor(0xFF, 0xFF, 0xFF, 0xFF), JUtility::TColor(0xFF, 0xFF, 0xFF, 0xFF), JUtility::TColor(0xFF, 0xFF, 0xFF, 0xFF), + JUtility::TColor(0xFF, 0xFF, 0xFF, 0xFF), JUtility::TColor(0xFF, 0xFF, 0xFF, 0xFF), JUtility::TColor(0xFF, 0xFF, 0xFF, 0xFF), + JUtility::TColor(0xFF, 0xFF, 0xFF, 0xFF), JUtility::TColor(0xFF, 0xFF, 0xFF, 0xFF), JUtility::TColor(0xFF, 0xFF, 0xFF, 0xFF), + JUtility::TColor(0xFF, 0xFF, 0xFF, 0xFF), JUtility::TColor(0xFF, 0xFF, 0xFF, 0xFF), JUtility::TColor(0xFF, 0xFF, 0xFF, 0xFF), + JUtility::TColor(0xFF, 0xFF, 0xFF, 0xFF), JUtility::TColor(0xFF, 0xFF, 0xFF, 0xFF), JUtility::TColor(0xFF, 0xFF, 0xFF, 0xFF), + JUtility::TColor(0xFF, 0xFF, 0xFF, 0xFF), JUtility::TColor(0xFF, 0xFF, 0xFF, 0xFF), JUtility::TColor(0xFF, 0xFF, 0xFF, 0xFF), + JUtility::TColor(0xFF, 0xFF, 0xFF, 0xFF), JUtility::TColor(0xFF, 0xFF, 0xFF, 0xFF), JUtility::TColor(0xFF, 0xFF, 0xFF, 0xFF), + JUtility::TColor(0xFF, 0xFF, 0xFF, 0xFF), JUtility::TColor(0xFF, 0xFF, 0xFF, 0xFF), JUtility::TColor(0xFF, 0xFF, 0xFF, 0xFF), + JUtility::TColor(0xFF, 0xFF, 0xFF, 0xFF), JUtility::TColor(0xCD, 0xFF, 0xFF, 0xFF), JUtility::TColor(0xCD, 0xFF, 0xFF, 0xFF), + JUtility::TColor(0xFF, 0xFF, 0xFF, 0xFF), JUtility::TColor(0xFF, 0xFF, 0xFF, 0xFF), JUtility::TColor(0xFF, 0xFF, 0xFF, 0xFF), + JUtility::TColor(0xFF, 0xFF, 0xFF, 0xFF), JUtility::TColor(0xFF, 0xFF, 0xFF, 0xFF), JUtility::TColor(0xFF, 0xFF, 0xFF, 0xFF), + JUtility::TColor(0xFF, 0xFF, 0xFF, 0xFF), + }; + #else static GXColor const black_color[37] = { {0x00, 0x00, 0x00, 0x00}, {0x00, 0x00, 0x00, 0x00}, {0x00, 0x00, 0x00, 0x00}, {0x00, 0x00, 0x00, 0x00}, {0x00, 0x00, 0x00, 0x00}, {0x00, 0x00, 0x00, 0x00}, @@ -1203,6 +1405,7 @@ void dMeter2Info_c::set2ndColor(u8 i_itemType, J2DPicture* i_pic) { {0xFF, 0xFF, 0xFF, 0xFF}, {0xFF, 0xFF, 0xFF, 0xFF}, {0xFF, 0xFF, 0xFF, 0xFF}, {0xFF, 0xFF, 0xFF, 0xFF}, }; + #endif i_pic->setBlackWhite(*(JUtility::TColor*)&black_color[i_itemType], *(JUtility::TColor*)&white_color[i_itemType]); @@ -1235,6 +1438,8 @@ void dMeter2Info_c::set3rdColor(u8 i_itemType, J2DPicture* i_pic) { } void dMeter2Info_c::set4thColor(u8 i_itemType, J2DPicture* i_pic) { + UNUSED(i_itemType); + i_pic->setBlackWhite(JUtility::TColor(0, 0, 0, 0), JUtility::TColor(0xff, 0xff, 0xff, 0xff)); i_pic->setCornerColor( JUtility::TColor(0xff, 0xff, 0xff, 0xff), JUtility::TColor(0xff, 0xff, 0xff, 0xff), @@ -1434,7 +1639,7 @@ u8 dMeter2Info_getPixel(f32 i_posX, f32 i_posY, f32 param_2, f32 param_3, f32 i_ JUT_ASSERT(3074, *pixel < i_resTimg->numColors); - u16* palette_p = (u16*)((uintptr_t)i_resTimg + i_resTimg->paletteOffset); + BE(u16)* palette_p = (BE(u16)*)((uintptr_t)i_resTimg + i_resTimg->paletteOffset); u16 var_r24 = (u16)palette_p[*pixel]; if (var_r24 & 0x8000) { return 1; @@ -1443,6 +1648,18 @@ u8 dMeter2Info_getPixel(f32 i_posX, f32 i_posY, f32 param_2, f32 param_3, f32 i_ return (var_r24 & 0x7000) != 0; } +bool dMeter2Info_isNextStage(const char* i_name, s16 i_roomNo, s16 i_point, s16 i_layer) { + if (strcmp(dComIfGp_getNextStageName(), i_name) == 0 + && dComIfGp_getNextStageRoomNo() == i_roomNo + && dComIfGp_getNextStagePoint() == i_point + && dComIfGp_getNextStageLayer() == i_layer + ) { + return true; + } + + return false; +} + void dMeter2Info_setCloth(u8 i_clothId, bool i_offItemBit) { switch (i_clothId) { case dItemNo_WEAR_CASUAL_e: @@ -1586,6 +1803,7 @@ u8 dMeter2Info_getNewLetterNum() { } int dMeter2Info_setNewLetterSender() { + int ret = 0; u8 check = 0; for (int i = 0; i < 0x40; i++) { @@ -1593,10 +1811,9 @@ int dMeter2Info_setNewLetterSender() { u16 letterEvent = dMenu_Letter::getLetterEventFlag(i); if (dComIfGs_isEventBit(dSv_event_flag_c::saveBitLabels[letterEvent])) { if (check == 0) { - u16 letterName = dMenu_Letter::getLetterName(i); - dMsgObject_c::setLetterNameID(letterName); + dMsgObject_setLetterNameID(dMenu_Letter::getLetterName(i)); } else { - dMsgObject_c::setLetterNameID(0); + dMsgObject_setLetterNameID(0); return 0; } check++; @@ -1604,7 +1821,7 @@ int dMeter2Info_setNewLetterSender() { } } - return 0; + return ret; } int dMeter2Info_recieveLetter() { @@ -1636,6 +1853,37 @@ int dMeter2Info_recieveLetter() { return rv; } +#if WIDESCREEN_SUPPORT +f32 dMeter2Info_getWide2DPosX(f32* param_0) { + J2DOrthoGraph graf(0.0f, 0.0f, 640.0f, 456.0f, -1.0f, 1.0f); + graf.setOrtho(mDoGph_gInf_c::getMinXF(), mDoGph_gInf_c::getMinYF(), mDoGph_gInf_c::getWidthF(), mDoGph_gInf_c::getHeightF(), -1.0f, 1.0f); + JGeometry::TBox2* bounds = graf.getBounds(); + const JGeometry::TBox2* ortho = graf.getOrtho(); + + f32 var_f31 = 304.0f; + f32 var_f30 = 608.0f / (ortho->f.x - ortho->i.x); + f32 var_f29 = *param_0 - var_f31; + *param_0 = var_f29 * var_f30 + var_f31; + return *param_0; +} + +void dMeter2Info_onWide2D() { +#if !TARGET_PC + g_ringHIO.updateOnWide(); +#endif + g_drawHIO.updateOnWide(); +} + +void dMeter2Info_offWide2D() { +#if !TARGET_PC + g_ringHIO.updateOffWide(); +#endif + g_drawHIO.updateOffWide(); +} +#endif + +void dMeter2Info_set2DVibrationT() {} + void dMeter2Info_set2DVibration() {} void dMeter2Info_set2DVibrationM() {} diff --git a/src/d/d_meter_HIO.cpp b/src/d/d_meter_HIO.cpp index 685f9c580c..c23e6c3230 100644 --- a/src/d/d_meter_HIO.cpp +++ b/src/d/d_meter_HIO.cpp @@ -2287,7 +2287,22 @@ dMeter_drawHIO_c::dMeter_drawHIO_c() { } #if WIDESCREEN_SUPPORT -void dMeter_drawHIO_c::updateOnWide() {} +void dMeter_drawHIO_c::updateOnWide() { +#if TARGET_PC + g_drawHIO = {}; // this might be a bad idea + + g_drawHIO.mMainHUDButtonsPosX = mDoGph_gInf_c::ScaleHUDXRight(g_drawHIO.mMainHUDButtonsPosX); + g_drawHIO.mRingHUDButtonsPosX = mDoGph_gInf_c::ScaleHUDXRight(g_drawHIO.mRingHUDButtonsPosX); + g_drawHIO.mLightDrop.mVesselPosX = mDoGph_gInf_c::ScaleHUDXRight(g_drawHIO.mLightDrop.mVesselPosX); + g_drawHIO.mLightDrop.mVesselTalkPosX = mDoGph_gInf_c::ScaleHUDXRight(g_drawHIO.mLightDrop.mVesselTalkPosX); + g_drawHIO.mRupeeKeyPosX = mDoGph_gInf_c::ScaleHUDXRight(g_drawHIO.mRupeeKeyPosX); + g_drawHIO.mOxygenMeterPosX = mDoGph_gInf_c::ScaleHUDXLeft(g_drawHIO.mOxygenMeterPosX); + g_drawHIO.mButtonCrossOFFPosX = mDoGph_gInf_c::ScaleHUDXLeft(g_drawHIO.mButtonCrossOFFPosX); + g_drawHIO.mButtonCrossONPosX = mDoGph_gInf_c::ScaleHUDXLeft(g_drawHIO.mButtonCrossONPosX); + g_drawHIO.mLifeGaugePosX = mDoGph_gInf_c::ScaleHUDXLeft(g_drawHIO.mLifeGaugePosX); + g_drawHIO.mLanternMeterPosX = mDoGph_gInf_c::ScaleHUDXLeft(g_drawHIO.mLanternMeterPosX); +#endif +} void dMeter_drawHIO_c::updateOffWide() {} #endif @@ -3003,7 +3018,7 @@ void dMeter_drawHIO_c::updateFMsgDebug() { #endif dMeter_ringHIO_c::dMeter_ringHIO_c() { -#if WIDESCREEN_SUPPORT +#if WIDESCREEN_SUPPORT && !TARGET_PC updateOnWide(); #else mRingRadiusH = 175.0f; diff --git a/src/d/d_meter_map.cpp b/src/d/d_meter_map.cpp index 1e0f7e397d..419235c970 100644 --- a/src/d/d_meter_map.cpp +++ b/src/d/d_meter_map.cpp @@ -302,12 +302,12 @@ bool dMeterMap_c::isEventRunCheck() { f32 dMeterMap_c::getMapDispEdgeLeftX_Layout() { #if (PLATFORM_WII || PLATFORM_SHIELD) if (mDoGph_gInf_c::isWide()) { - return g_meter_mapHIO.mWideBottomLeftX + field_0x28; + return g_meter_mapHIO.mWideBottomLeftX + mSlidePositionOffset; } - return g_meter_mapHIO.mNormalBottomLeftX + field_0x28; + return g_meter_mapHIO.mNormalBottomLeftX + mSlidePositionOffset; #else - return field_0x28 + 35; + return mSlidePositionOffset + 35; #endif } @@ -349,14 +349,14 @@ s16 dMeterMap_c::getDispPosOutSide_OffsetX() { void dMeterMap_c::setDispPosInsideFlg_SE_On() { if (isEnableDispMapAndMapDispSizeTypeNo()) { dComIfGp_mapShow(); - field_0x2d = 1; + mMapIsInside = 1; field_0x2e = 7; } } void dMeterMap_c::setDispPosOutsideFlg_SE_On() { dComIfGp_mapHide(); - field_0x2d = 0; + mMapIsInside = 0; field_0x2e = 7; } @@ -456,44 +456,44 @@ void dMeterMap_c::_create(J2DScreen* unused) { field_0x2a = 0; if (dComIfGp_checkMapShow()) { - field_0x2d = 1; + mMapIsInside = 1; if (!isEnableDispMapAndMapDispSizeTypeNo()) { - field_0x2d = 0; + mMapIsInside = 0; } if (!isMapOpenCheck()) { - field_0x2d = 0; + mMapIsInside = 0; } } else { - field_0x2d = 0; + mMapIsInside = 0; } - if (field_0x2d != 0) { - field_0x2d = 1; - field_0x28 = getDispPosInside_OffsetX(); + if (mMapIsInside != 0) { + mMapIsInside = 1; + mSlidePositionOffset = getDispPosInside_OffsetX(); dMeter2Info_setMapStatus(1); } else { - field_0x2d = 0; - field_0x28 = getDispPosOutSide_OffsetX(); + mMapIsInside = 0; + mSlidePositionOffset = getDispPosOutSide_OffsetX(); dMeter2Info_setMapStatus(0); } field_0x2e = 0; - field_0x28 = 0; + mSlidePositionOffset = 0; field_0x30 = 0; /* dSv_event_flag_c::M_085 - Twilight Hyrule Field - Midna dialogue right before Boss Bug's Tear of Light appears */ field_0x2b = dComIfGs_isEventBit(dSv_event_flag_c::saveBitLabels[118]); } void dMeterMap_c::setDispPosOutSide() { - field_0x2d = 0; - field_0x28 = getDispPosOutSide_OffsetX(); + mMapIsInside = 0; + mSlidePositionOffset = getDispPosOutSide_OffsetX(); } void dMeterMap_c::setDispPosInSide() { - field_0x2d = 1; - field_0x28 = getDispPosInside_OffsetX(); + mMapIsInside = 1; + mSlidePositionOffset = getDispPosInside_OffsetX(); } void dMeterMap_c::_delete() { @@ -506,7 +506,7 @@ void dMeterMap_c::_delete() { } if (isEnableDispMapAndMapDispSizeTypeNo()) { - if (field_0x2d != 0) { + if (mMapIsInside != 0) { dComIfGp_mapShow(); } else { dComIfGp_mapHide(); @@ -548,16 +548,16 @@ void dMeterMap_c::_move(u32 param_0) { ctrlShowMap(); } - if (field_0x2d != 0) { - if (field_0x28 != getDispPosInside_OffsetX()) { - if (!cLib_addCalcAngleS(&field_0x28, getDispPosInside_OffsetX(), 2, 60, 10)) { + if (mMapIsInside != 0) { + if (mSlidePositionOffset != getDispPosInside_OffsetX()) { + if (!cLib_addCalcAngleS(&mSlidePositionOffset, getDispPosInside_OffsetX(), 2, 60, 10)) { #if DEBUG cLib_checkBit((int)field_0x2e, 4); #endif } } } else { - cLib_addCalcAngleS(&field_0x28, getDispPosOutSide_OffsetX(), 2, 60, 10); + cLib_addCalcAngleS(&mSlidePositionOffset, getDispPosOutSide_OffsetX(), 2, 60, 10); } Vec map_pos = dMapInfo_n::getMapPlayerPos(); @@ -579,8 +579,8 @@ void dMeterMap_c::_move(u32 param_0) { mSizeH = (s16)sizeH; #endif - field_0x18 = field_0x28 + getMapDispEdgeLeftX_Layout(); - field_0x1c = getMapDispEdgeBottomY_Layout() - mSizeH; + mDrawPosX = mSlidePositionOffset + getMapDispEdgeLeftX_Layout(); + mDrawPosY = getMapDispEdgeBottomY_Layout() - mSizeH; mMap->_move(map_pos.x, map_pos.z, stayNo, map_pos.y); field_0x30 = dComIfGp_event_runCheck(); @@ -609,8 +609,8 @@ void dMeterMap_c::draw() { graf->setup2D(); f32 sizeX = mSizeW; f32 sizeY = mSizeH; - f32 tmp2 = field_0x18; - f32 tmp3 = field_0x1c; + f32 drawPosX = mDrawPosX; + f32 drawPosY = mDrawPosY; u8 alpha = mMapAlpha; #if DEBUG @@ -620,7 +620,13 @@ void dMeterMap_c::draw() { #endif mMapJ2DPicture->setAlpha(alpha); - mMapJ2DPicture->draw(tmp2, tmp3, sizeX, sizeY, false, false, false); + #if TARGET_PC + mMapJ2DPicture->draw(mDoGph_gInf_c::ScaleHUDXLeft(drawPosX), drawPosY, sizeX, sizeY, false, + false, false); + #else + mMapJ2DPicture->draw(drawPosX, drawPosY, sizeX, sizeY, false, false, false); + #endif + mMapJ2DPicture->calcMtx(); } } @@ -640,7 +646,7 @@ void dMeterMap_c::ctrlShowMap() { dMeter2Info_getPauseStatus() == 2 || dMeter2Info_getPauseStatus() == 6) { #if !DEBUG - if (dMeter2Info_getMapStatus() == 0 && field_0x2d == 0) { + if (dMeter2Info_getMapStatus() == 0 && mMapIsInside == 0) { setDispPosInsideFlg_SE_On(); Z2GetAudioMgr()->seStart(Z2SE_SY_MAP_OPEN_S, NULL, 0, 0, 1.0f, 1.0f, -1.0f, -1.0f, 0); @@ -653,7 +659,7 @@ void dMeterMap_c::ctrlShowMap() { #if DEBUG dMeter2Info_getMapStatus() == 0 && #else - dMeter2Info_getMapStatus() == 1 && field_0x2d != 0 && + dMeter2Info_getMapStatus() == 1 && mMapIsInside != 0 && #endif isFmapScreen() ) { @@ -690,7 +696,7 @@ void dMeterMap_c::ctrlShowMap() { dMeter2Info_resetPauseStatus(); if (isDmapScreen()) { #if !DEBUG - if (dMeter2Info_getMapStatus() == 0 && field_0x2d == 0) { + if (dMeter2Info_getMapStatus() == 0 && mMapIsInside == 0) { setDispPosInsideFlg_SE_On(); Z2GetAudioMgr()->seStart(Z2SE_SY_MAP_OPEN_S, NULL, 0, 0, 1.0f, 1.0f, -1.0f, -1.0f, 0); @@ -703,7 +709,7 @@ void dMeterMap_c::ctrlShowMap() { #if DEBUG dMeter2Info_getMapStatus() == 0 #else - dMeter2Info_getMapStatus() == 1 && field_0x2d != 0 + dMeter2Info_getMapStatus() == 1 && mMapIsInside != 0 #endif ) { dMeter2Info_setMapStatus(6); diff --git a/src/d/d_msg_object.cpp b/src/d/d_msg_object.cpp index da9605c4b2..3676639908 100644 --- a/src/d/d_msg_object.cpp +++ b/src/d/d_msg_object.cpp @@ -656,7 +656,7 @@ void dMsgObject_c::setMessageIndexDemo(u32 revoMsgIndex, bool param_2) { u32 dMsgObject_c::getMessageIndex(u32 param_0) { u32 i = 0; JMSMesgInfo_c* pMsg = (JMSMesgInfo_c*)((char*)mpMsgDt + 0x20); - u32 msgIndexCount = *((u16*)((char*)mpMsgDt + 0x28)); + u32 msgIndexCount = *((BE(u16)*)((char*)mpMsgDt + 0x28)); int rv; for (; i < msgIndexCount; i++) { if (pMsg->entries[i].message_id == param_0) { @@ -683,12 +683,12 @@ u32 dMsgObject_c::getRevoMessageIndex(u32 param_1) { JUT_ASSERT(1916, groupID==s_groupID || groupID == 0) changeGroup(groupID); pMsg = (JMSMesgInfo_c*)((char*)mpMsgDt + 0x20); - msgIndexCount = *((u16*)((char*)mpMsgDt + 0x28)); + msgIndexCount = *((BE(u16)*)((char*)mpMsgDt + 0x28)); for (; i < msgIndexCount; i++) { if (pMsg->entries[i].message_id == param_1) { s8* ptr = (s8*)pMsg + pMsg->header.size + pMsg->entries[i].string_offset + 8; if (ptr[0] == 26 && ptr[2] == 3 && (s8)ptr[4] == 0) { - rv = pMsg->entries[*(int*)(ptr + 5)].message_id; + rv = pMsg->entries[*(BE(int)*)(ptr + 5)].message_id; } else { rv = param_1; } @@ -706,7 +706,7 @@ u32 dMsgObject_c::getRevoMessageIndex(u32 param_1) { u32 dMsgObject_c::getMessageIndexAlways(u32 param_0) { u32 i = 0; JMSMesgInfo_c* pMsg = (JMSMesgInfo_c*)((char*)mpMsgRes + 0x20); - u32 msgIndexCount = *((u16*)((char*)mpMsgRes + 0x28)); + u32 msgIndexCount = *((BE(u16)*)((char*)mpMsgRes + 0x28)); int rv; for (; i < msgIndexCount; i++) { if (pMsg->entries[i].message_id == param_0) { @@ -1464,12 +1464,24 @@ void dMsgObject_c::fukiPosCalc(bool param_1) { fopAc_ac_c* player = dComIfGp_getPlayer(0); cXyz local_3c; cXyz cStack_48; + + #if TARGET_PC + mDoLib_project(&player->eyePos, &cStack_48, {0, 0, FB_WIDTH, FB_HEIGHT}); + #else mDoLib_project(&player->eyePos, &cStack_48); + #endif + f32 temp; if ((field_0x100->pos == cXyz(0.0f, 0.0f, 0.0f))) { temp = cStack_48.y; } else { + + #if TARGET_PC + mDoLib_project(&field_0x100->pos, &local_3c, {0, 0, FB_WIDTH, FB_HEIGHT}); + #else mDoLib_project(&field_0x100->pos, &local_3c); + #endif + if (local_3c.x >= 0.0f && local_3c.x <= FB_WIDTH && local_3c.y >= 0.0f && local_3c.y <= FB_HEIGHT) { @@ -1634,7 +1646,12 @@ void dMsgObject_c::readMessageGroupLocal(mDoDvdThd_mountXArchive_c** p_arcMount) #elif REGION_JPN sprintf(arcName, "/res/Msgjp/bmgres%d.arc", msgGroup); #else +#if TARGET_PC + // Original game UB + snprintf(arcName, sizeof(arcName), "/res/Msgus/bmgres%d.arc", msgGroup); +#else sprintf(arcName, "/res/Msgus/bmgres%d.arc", msgGroup); +#endif #endif *p_arcMount = mDoDvdThd_mountXArchive_c::create(arcName, 0, JKRArchive::MOUNT_MEM, NULL); diff --git a/src/d/d_msg_scrn_howl.cpp b/src/d/d_msg_scrn_howl.cpp index 07018b376d..965bd25075 100644 --- a/src/d/d_msg_scrn_howl.cpp +++ b/src/d/d_msg_scrn_howl.cpp @@ -475,6 +475,10 @@ void dMsgScrnHowl_c::drawWave() { s32 local_94 = 0; Vec fVar12 = field_0x128; Vec this_02 = field_0x140; +#if TARGET_PC // TODO: make this actually use the scissor + f32 fVar1 = 1; + f32 fVar2 = 1; +#else f32 fVar1 = mDoGph_gInf_c::getWidthF() / FB_WIDTH; f32 fVar2 = mDoGph_gInf_c::getHeightF() / FB_HEIGHT; grafContext->scissor( @@ -484,6 +488,8 @@ void dMsgScrnHowl_c::drawWave() { 32.0f + ((this_02.y - fVar12.y) + 2.0f) ); grafContext->setScissor(); +#endif + bool bVar5 = true; if (field_0x2798 == 0) { if (mPlotTime != field_0x212c) { @@ -578,10 +584,17 @@ void dMsgScrnHowl_c::drawGuide() { J2DGrafContext* grafContext = dComIfGp_getCurrentGrafPort(); Vec local_b0 = field_0x128; Vec local_bc = field_0x140; +#if TARGET_PC + grafContext->scissor( + (local_b0.x - mDoGph_gInf_c::getMinXF()) / (mDoGph_gInf_c::getWidthF() / mDoGph_gInf_c::getWidth()), + field_0x2118, (local_bc.x - local_b0.x) / (mDoGph_gInf_c::getWidthF() / mDoGph_gInf_c::getWidth()), + field_0x2120); +#else grafContext->scissor( (local_b0.x - mDoGph_gInf_c::getMinXF()) / (mDoGph_gInf_c::getWidthF() / FB_WIDTH), field_0x2118, (local_bc.x - local_b0.x) / (mDoGph_gInf_c::getWidthF() / FB_WIDTH), field_0x2120); +#endif grafContext->setScissor(); f32 local_cc = mpLineH[0]->getGlobalPosX(); s16 sVar12 = 0; @@ -709,11 +722,19 @@ void dMsgScrnHowl_c::drawGuide2() { } Vec local_58 = field_0x128; Vec local_64 = field_0x140; - f32 local_70 = mDoGph_gInf_c::getHeightF() / FB_HEIGHT; +#if TARGET_PC + f32 local_70 = mDoGph_gInf_c::getHeightF() / mDoGph_gInf_c::getHeight(); + grafContext->scissor( + (local_58.x - mDoGph_gInf_c::getMinXF()) / (mDoGph_gInf_c::getWidthF() / mDoGph_gInf_c::getWidth()), + field_0x2118, (local_64.x - local_58.x) / (mDoGph_gInf_c::getWidthF() / mDoGph_gInf_c::getWidth()), + field_0x2120); +#else + f32 local_70 = mDoGph_gInf_c::getHeightF() / mDoGph_gInf_c::getHeight(); grafContext->scissor( (local_58.x - mDoGph_gInf_c::getMinXF()) / (mDoGph_gInf_c::getWidthF() / FB_WIDTH), field_0x2118, (local_64.x - local_58.x) / (mDoGph_gInf_c::getWidthF() / FB_WIDTH), field_0x2120); +#endif grafContext->setScissor(); f32 local_74 = mpLineH[0]->getGlobalPosX(); s16 local_134 = 0; @@ -815,9 +836,15 @@ void dMsgScrnHowl_c::drawEffect() { Vec vec1 = field_0x128; Vec vec2 = field_0x140; mDoGph_gInf_c::getHeightF(); +#if TARGET_PC + grafContext->scissor( + (vec1.x - mDoGph_gInf_c::getMinXF()) / (mDoGph_gInf_c::getWidthF() / mDoGph_gInf_c::getWidth()), field_0x2118, + 12.0f + ((vec2.x - vec1.x) / (mDoGph_gInf_c::getWidthF() / mDoGph_gInf_c::getWidth())), field_0x2120); +#else grafContext->scissor( (vec1.x - mDoGph_gInf_c::getMinXF()) / (mDoGph_gInf_c::getWidthF() / FB_WIDTH), field_0x2118, 12.0f + ((vec2.x - vec1.x) / (mDoGph_gInf_c::getWidthF() / FB_WIDTH)), field_0x2120); +#endif grafContext->setScissor(); u8 timer = daAlink_getAlinkActorClass()->getWolfHowlMgrP()->getReleaseTimer(); u8 screenAlpha = mpScreen->search(MULTI_CHAR('line00'))->getAlpha(); diff --git a/src/d/d_msg_scrn_item.cpp b/src/d/d_msg_scrn_item.cpp index bb4daf3927..40732eff25 100644 --- a/src/d/d_msg_scrn_item.cpp +++ b/src/d/d_msg_scrn_item.cpp @@ -411,7 +411,7 @@ void dMsgScrnItem_c::drawSelf() { f32 globalPosX = mpTm_c[0]->getGlobalPosX(); - #if WIDESCREEN_SUPPORT + #if WIDESCREEN_SUPPORT && !TARGET_PC if (mDoGph_gInf_c::isWide()) { drawOutFont(g_MsgObject_HIO_c.mBoxItemTextPosX + 7.0f + YREG_F(2), g_MsgObject_HIO_c.mBoxItemTextPosY, 1.0f); @@ -557,11 +557,22 @@ void dMsgScrnItem_c::fukiPosCalc(u8 param_1) { cXyz local_70; cXyz cStack_7c; f32 f3; + + #if TARGET_PC + mDoLib_project(&player->eyePos, &cStack_7c, {0, 0, FB_WIDTH, FB_HEIGHT}); + #else mDoLib_project(&player->eyePos, &cStack_7c); + #endif + if (iVar6->pos == cXyz(0.0f, 0.0f, 0.0f)) { f3 = cStack_7c.y; } else { + #if TARGET_PC + mDoLib_project(&iVar6->pos, &local_70, {0, 0, FB_WIDTH, FB_HEIGHT}); + #else mDoLib_project(&iVar6->pos, &local_70); + #endif + if (local_70.x >= 0.0f && local_70.x <= FB_WIDTH && local_70.y >= 0.0f && local_70.y <= FB_HEIGHT) { diff --git a/src/d/d_msg_scrn_place.cpp b/src/d/d_msg_scrn_place.cpp index 881852c259..b2c28efc95 100644 --- a/src/d/d_msg_scrn_place.cpp +++ b/src/d/d_msg_scrn_place.cpp @@ -101,13 +101,25 @@ void dMsgScrnPlace_c::exec() { mpFontParent->scale(g_MsgObject_HIO_c.mStageTitleCharSizeX, g_MsgObject_HIO_c.mStageTitleCharSizeY); + +#if TARGET_PC + mpFontParent->paneTrans(mDoGph_gInf_c::ScaleHUDXLeft(g_MsgObject_HIO_c.mStageTitleCharPosX), + g_MsgObject_HIO_c.mStageTitleCharPosY - mScaleX); +#else mpFontParent->paneTrans(g_MsgObject_HIO_c.mStageTitleCharPosX, g_MsgObject_HIO_c.mStageTitleCharPosY - mScaleX); +#endif mpBaseParent->scale(g_MsgObject_HIO_c.mStageTitleBaseSizeX, g_MsgObject_HIO_c.mStageTitleBaseSizeY); + +#if TARGET_PC + mpBaseParent->paneTrans(mDoGph_gInf_c::ScaleHUDXLeft(g_MsgObject_HIO_c.mStageTitleBasePosX), + g_MsgObject_HIO_c.mStageTitleBasePosY - mScaleY); +#else mpBaseParent->paneTrans(g_MsgObject_HIO_c.mStageTitleBasePosX, g_MsgObject_HIO_c.mStageTitleBasePosY - mScaleY); +#endif if (isTalkNow()) { fukiAlpha(1.0f); diff --git a/src/d/d_msg_scrn_talk.cpp b/src/d/d_msg_scrn_talk.cpp index 226ece0304..546e42112f 100644 --- a/src/d/d_msg_scrn_talk.cpp +++ b/src/d/d_msg_scrn_talk.cpp @@ -441,11 +441,22 @@ void dMsgScrnTalk_c::fukiPosCalc(u8 param_1) { cXyz local_70; cXyz cStack_7c; f32 f3y; + + #if TARGET_PC + mDoLib_project(&player->eyePos, &cStack_7c, {0, 0, FB_WIDTH, FB_HEIGHT}); + #else mDoLib_project(&player->eyePos, &cStack_7c); + #endif + if (msgActor->pos == cXyz(0.0f, 0.0f, 0.0f)) { f3y = cStack_7c.y; } else { - mDoLib_project(&msgActor->pos, &local_70); + #if TARGET_PC + mDoLib_project(&msgActor->pos, &local_70, {0, 0, FB_WIDTH, FB_HEIGHT}); + #else + mDoLib_project(&msgActor->pos, &local_70,); + #endif + if (local_70.x >= 0.0f && local_70.x <= 608.0f && local_70.y >= 0.0f && local_70.y <= 448.0f) { diff --git a/src/d/d_msg_unit.cpp b/src/d/d_msg_unit.cpp index bfa7d7b667..98dd33b4a8 100644 --- a/src/d/d_msg_unit.cpp +++ b/src/d/d_msg_unit.cpp @@ -9,31 +9,31 @@ // temporary until a better solution is found typedef struct dMsgUnit_inf1_entry { - u32 dat1EntryOffset; + BE(u32) dat1EntryOffset; #if REGION_JPN - u16 field_0x04; - u16 field_0x06; - u16 field_0x08; - u16 field_0x0a; - u16 field_0x0c; - u16 field_0x0e; - u16 field_0x10; - u16 field_0x12; - u16 field_0x14; - u16 field_0x16; - u16 field_0x18; + BE(u16) field_0x04; + BE(u16) field_0x06; + BE(u16) field_0x08; + BE(u16) field_0x0a; + BE(u16) field_0x0c; + BE(u16) field_0x0e; + BE(u16) field_0x10; + BE(u16) field_0x12; + BE(u16) field_0x14; + BE(u16) field_0x16; + BE(u16) field_0x18; #else - u16 startFrame; - u16 endFrame; + BE(u16) startFrame; + BE(u16) endFrame; #endif } dMsgUnit_inf1_entry; typedef struct dMsgUnit_inf1_section_t { - /* 0x00 */ u32 msgType; // sectionType - /* 0x04 */ u32 size; // total size of the section - /* 0x08 */ u16 entryCount; - /* 0x0A */ u16 entryLength; - /* 0x0C */ u16 msgArchiveId; + /* 0x00 */ BE(u32) msgType; // sectionType + /* 0x04 */ BE(u32) size; // total size of the section + /* 0x08 */ BE(u16) entryCount; + /* 0x0A */ BE(u16) entryLength; + /* 0x0C */ BE(u16) msgArchiveId; /* 0x10 */ dMsgUnit_inf1_entry entries[0]; } dMsgUnit_inf1_section_t; diff --git a/src/d/d_name.cpp b/src/d/d_name.cpp index ee51e2e583..120bcff752 100644 --- a/src/d/d_name.cpp +++ b/src/d/d_name.cpp @@ -918,6 +918,10 @@ void dName_c::selectCursorMove() { g_nmHIO.mSelCharScale); ((J2DTextBox*)mMojiIcon[mCharRow + mCharColumn * 5]->getPanePtr()) ->setWhite(JUtility::TColor(0xC8, 0xC8, 0xC8, 0xFF)); + + #if TARGET_PC + nameWide(); + #endif Vec pos = mMojiIcon[mCharRow + mCharColumn * 5]->getGlobalVtxCenter(false, 0); mSelIcon->setPos(pos.x, pos.y, mMojiIcon[mCharRow + mCharColumn * 5]->getPanePtr(), true); @@ -1281,7 +1285,58 @@ void dName_c::selectCursorPosSet(int row) { } } +#if TARGET_PC +void dName_c::nameWide() { + //Resize Select Icon + mSelIcon->setParam(0.82f * mDoGph_gInf_c::hudAspectScaleUp, 0.77f, 0.05f, 0.4f, 0.4f); + + // List of Characters Box + static u64 l_tagName[65] = { + MULTI_CHAR('m_00_0'), MULTI_CHAR('m_00_1'), MULTI_CHAR('m_00_2'), MULTI_CHAR('m_00_3'), MULTI_CHAR('m_00_4'), MULTI_CHAR('m_01_0'), MULTI_CHAR('m_01_1'), MULTI_CHAR('m_01_2'), MULTI_CHAR('m_01_3'), + MULTI_CHAR('m_01_4'), MULTI_CHAR('m_02_0'), MULTI_CHAR('m_02_1'), MULTI_CHAR('m_02_2'), MULTI_CHAR('m_02_3'), MULTI_CHAR('m_02_4'), MULTI_CHAR('m03_0'), MULTI_CHAR('m03_1'), MULTI_CHAR('m03_2'), + MULTI_CHAR('m03_3'), MULTI_CHAR('m03_4'), MULTI_CHAR('m_04_0'), MULTI_CHAR('m_04_1'), MULTI_CHAR('m_04_2'), MULTI_CHAR('m_04_3'), MULTI_CHAR('m_04_4'), MULTI_CHAR('m_05_0'), MULTI_CHAR('m_05_1'), + MULTI_CHAR('m_05_2'), MULTI_CHAR('m_05_3'), MULTI_CHAR('m_05_4'), MULTI_CHAR('m_06_0'), MULTI_CHAR('m_06_1'), MULTI_CHAR('m_06_2'), MULTI_CHAR('m_06_3'), MULTI_CHAR('m_06_4'), MULTI_CHAR('m_07_0'), + MULTI_CHAR('m_07_1'), MULTI_CHAR('m_07_2'), MULTI_CHAR('m_07_3'), MULTI_CHAR('m_07_4'), MULTI_CHAR('m_08_0'), MULTI_CHAR('m_08_1'), MULTI_CHAR('m_08_2'), MULTI_CHAR('m_08_3'), MULTI_CHAR('m_08_4'), + MULTI_CHAR('m_09_0'), MULTI_CHAR('m_09_1'), MULTI_CHAR('m_09_2'), MULTI_CHAR('m_09_3'), MULTI_CHAR('m_09_4'), MULTI_CHAR('m_10_0'), MULTI_CHAR('m_10_1'), MULTI_CHAR('m_10_2'), MULTI_CHAR('m_10_3'), + MULTI_CHAR('m_10_4'), MULTI_CHAR('m_11_0'), MULTI_CHAR('m_11_1'), MULTI_CHAR('m_11_2'), MULTI_CHAR('m_11_3'), MULTI_CHAR('m_11_4'), MULTI_CHAR('m12_0'), MULTI_CHAR('m12_1'), MULTI_CHAR('m12_2'), + MULTI_CHAR('m12_3'), MULTI_CHAR('m12_4'), + }; + + for (u32 i = 0; i < 65; i++) { + nameIn.NameInScr->search(l_tagName[i])->scale(mDoGph_gInf_c::hudAspectScaleDown, 1.0f); + } + + // "END" Text + nameIn.NameInScr->search(MULTI_CHAR('p_end_2'))->scale(mDoGph_gInf_c::hudAspectScaleDown, 1.0f); + nameIn.NameInScr->search(MULTI_CHAR('p_end_1'))->scale(mDoGph_gInf_c::hudAspectScaleDown, 1.0f); + nameIn.NameInScr->search(MULTI_CHAR('p_end_0'))->scale(mDoGph_gInf_c::hudAspectScaleDown, 1.0f); + + // Letters being typed + static u64 l_nameTagName[8] = { + MULTI_CHAR('name_00'), MULTI_CHAR('name_01'), MULTI_CHAR('name_02'), MULTI_CHAR('name_03'), MULTI_CHAR('name_04'), MULTI_CHAR('name_05'), MULTI_CHAR('name_06'), MULTI_CHAR('name_07'), + }; + + for (u32 i = 0; i < 8; i++) { + nameIn.NameInScr->search(l_nameTagName[i])->scale(mDoGph_gInf_c::hudAspectScaleDown, 1.0f); + } + + // Underscores when typing below letters + static u64 l_nameCurTagName[8] = { + MULTI_CHAR('s__n_00'), MULTI_CHAR('s__n_01'), MULTI_CHAR('s__n_02'), MULTI_CHAR('s__n_03'), MULTI_CHAR('s__n_04'), MULTI_CHAR('s__n_05'), MULTI_CHAR('s__n_06'), MULTI_CHAR('s__n_07'), + }; + + for (u32 i = 0; i < 8; i++) { + nameIn.NameInScr->search(l_nameCurTagName[i]) + ->scale(mDoGph_gInf_c::hudAspectScaleDown, 1.0f); + } +} +#endif + void dName_c::_draw() { + #if TARGET_PC + nameWide(); + #endif + dComIfGd_set2DOpa(&nameIn); dComIfGd_set2DOpa(mSelIcon); } @@ -1484,7 +1539,12 @@ void dName_c::screenSet() { mSelIcon = JKR_NEW dSelect_cursor_c(0, 1.0f, NULL); JUT_ASSERT(0, mSelIcon != NULL); + + #if TARGET_PC + mSelIcon->setParam(0.82f * mDoGph_gInf_c::hudAspectScaleUp, 0.77f, 0.05f, 0.4f, 0.4f); + #else mSelIcon->setParam(0.82f, 0.77f, 0.05f, 0.4f, 0.4f); + #endif Vec pos = mMojiIcon[mCharRow + mCharColumn * 5]->getGlobalVtxCenter(false, 0); mSelIcon->setPos(pos.x, pos.y, mMojiIcon[mCharRow + mCharColumn * 5]->getPanePtr(), true); diff --git a/src/d/d_ovlp_fade2.cpp b/src/d/d_ovlp_fade2.cpp index 093aaadddd..37dbeedba2 100644 --- a/src/d/d_ovlp_fade2.cpp +++ b/src/d/d_ovlp_fade2.cpp @@ -51,8 +51,14 @@ void dOvlpFd2_dlst_c::draw() { GXEnd(); Mtx44 m; + + #if TARGET_PC + C_MTXPerspective(m, 60.0f, 1.3571428f, 100.0f, 100000.0f); + #else C_MTXPerspective(m, 60.0f, mDoGph_gInf_c::getWidthF() / mDoGph_gInf_c::getHeightF(), 100.0f, 100000.0f); + #endif + GXSetProjection(m, GX_PERSPECTIVE); #ifdef TARGET_PC mDoGph_gInf_c::getFrameBufferTexObj()->reset(); diff --git a/src/d/d_ovlp_fade3.cpp b/src/d/d_ovlp_fade3.cpp index f5da4064a0..d6f432f3ee 100644 --- a/src/d/d_ovlp_fade3.cpp +++ b/src/d/d_ovlp_fade3.cpp @@ -13,12 +13,13 @@ #include "m_Do/m_Do_graphic.h" void dDlst_snapShot_c::draw() { - #if TARGET_PC +#if TARGET_PC GXSetTexCopySrc(0, 0, mDoGph_gInf_c::getWidth(), mDoGph_gInf_c::getHeight()); - #else + GXSetTexCopyDst(mDoGph_gInf_c::getWidth(), mDoGph_gInf_c::getHeight(), GX_TF_RGBA8, GX_TRUE); +#else GXSetTexCopySrc(0, 0, FB_WIDTH, FB_HEIGHT); - #endif GXSetTexCopyDst(FB_WIDTH / 2, FB_HEIGHT / 2, GX_TF_RGBA8, GX_TRUE); +#endif GXCopyTex(mDoGph_gInf_c::getFrameBufferTex(), GX_FALSE); GXPixModeSync(); } @@ -63,8 +64,14 @@ void dOvlpFd3_dlst_c::draw() { GXEnd(); Mtx44 m; + + #if TARGET_PC + C_MTXPerspective(m, 60.0f, 1.3571428f, 100.0f, 100000.0f); + #else C_MTXPerspective(m, 60.0f, mDoGph_gInf_c::getWidthF() / mDoGph_gInf_c::getHeightF(), 100.0f, 100000.0f); + #endif + GXSetProjection(m, GX_PERSPECTIVE); #ifdef TARGET_PC mDoGph_gInf_c::getFrameBufferTexObj()->reset(); diff --git a/src/d/d_particle.cpp b/src/d/d_particle.cpp index 6c8d6e3f75..248424e9a2 100644 --- a/src/d/d_particle.cpp +++ b/src/d/d_particle.cpp @@ -8,22 +8,23 @@ // weak data from it (unlike here). #include "d/d_particle.h" -#include "d/d_jnt_col.h" +#include +#include "JSystem/J3DGraphAnimator/J3DMaterialAnm.h" +#include "JSystem/J3DGraphBase/J3DMaterial.h" #include "JSystem/JKernel/JKRExpHeap.h" #include "JSystem/JKernel/JKRSolidHeap.h" -#include "JSystem/J3DGraphBase/J3DMaterial.h" -#include "JSystem/J3DGraphAnimator/J3DMaterialAnm.h" +#include "JSystem/JMath/JMATrigonometric.h" #include "JSystem/JParticle/JPAEmitterManager.h" #include "JSystem/JParticle/JPAResourceManager.h" -#include "JSystem/JMath/JMATrigonometric.h" -#include "d/d_s_play.h" -#include -#include "d/d_com_inf_game.h" -#include "m_Do/m_Do_lib.h" -#include "m_Do/m_Do_graphic.h" -#include "f_op/f_op_actor_mng.h" -#include "d/actor/d_a_player.h" #include "SSystem/SComponent/c_math.h" +#include "d/actor/d_a_player.h" +#include "d/d_com_inf_game.h" +#include "d/d_jnt_col.h" +#include "d/d_s_play.h" +#include "f_op/f_op_actor_mng.h" +#include "m_Do/m_Do_graphic.h" +#include "m_Do/m_Do_lib.h" +#include "tracy/Tracy.hpp" #ifndef __MWERKS__ #include "dusk/math.h" @@ -1325,6 +1326,7 @@ void dPa_control_c::cleanup() { } void dPa_control_c::calc3D() { + ZoneScoped; if (isStatus(2)) { offStatus(2); } else { @@ -1336,12 +1338,14 @@ void dPa_control_c::calc3D() { } void dPa_control_c::calc2D() { + ZoneScoped; for (u8 i = 14; i <= 16; i++) { mEmitterMng->calc(i); } } void dPa_control_c::calcMenu() { + ZoneScoped; if (mEmitterMng != NULL) { for (u8 i = 17; i <= 18; i++) { mEmitterMng->calc(i); diff --git a/src/d/d_path.cpp b/src/d/d_path.cpp index a01cfdc8a6..b1fa3b7891 100644 --- a/src/d/d_path.cpp +++ b/src/d/d_path.cpp @@ -8,7 +8,38 @@ #include "d/d_path.h" #include "d/d_com_inf_game.h" -dPnt* dPath_GetPnt(dPath const* path, int pnt_index) { +#if DEBUG +#include "d/d_debug_viewer.h" +#endif + +class dPath_HIO : public JORReflexible { +public: + dPath_HIO() {} + ~dPath_HIO(); + + void genMessage(JORMContext* mctx) { + mctx->genCheckBox("デバッグ表示", &flags, 2); + mctx->genSlider("部屋番号", &roomNo, -2, 64); + mctx->genLabel("-3=現在プレイヤーのいる部屋, -2=旧常駐、-1=常駐", 0); + } + + void Ct() { + flags = 0; + roomNo = -3; + } + + int GetRoomNo() { return roomNo; } + bool ChkDispLine() { return flags & 2; } + + /* 0x4 */ s8 id; + /* 0x6 */ u16 flags; + /* 0x8 */ s16 roomNo; +}; + +dPnt* dPath_GetPnt(const dPath* path, int pnt_index) { + JUT_ASSERT(27, path != NULL); + JUT_ASSERT(28, 0 <= pnt_index && pnt_index < path->m_num); + if (path == NULL || path->m_points == NULL || pnt_index < 0 || pnt_index >= path->m_num) { return NULL; } @@ -17,116 +48,212 @@ dPnt* dPath_GetPnt(dPath const* path, int pnt_index) { } dPath* dPath_GetRoomPath(int path_index, int room_no) { - dStage_dPath_c* path; + dStage_dPath_c* pd; if (room_no == -1) { - path = dComIfGp_getStage()->getPath2Inf(); + dStage_dt_c* stage = dComIfGp_getStage(); + pd = stage->getPath2Inf(); } else { + JUT_ASSERT(58, 0 <= room_no && room_no < 64); dStage_roomDt_c* roomDt = dComIfGp_roomControl_getStatusRoomDt(room_no); if (roomDt == NULL) { return NULL; } - path = roomDt->getPath2Inf(); + pd = roomDt->getPath2Inf(); } - if (path == NULL || path_index < 0 || path_index >= path->m_num) { + if (pd == NULL || path_index < 0 || path_index >= pd->num) { return NULL; } - return &path->m_path[path_index]; + return &pd->m_path[path_index]; } -dPath* dPath_GetNextRoomPath(dPath const* p_path, int room_no) { - dStage_dPath_c* path; +dPath* dPath_GetNextRoomPath(const dPath* path, int room_no) { + dStage_dPath_c* pd; if (room_no == -1) { - path = dComIfGp_getStage()->getPath2Inf(); + dStage_dt_c* stage = dComIfGp_getStage(); + pd = stage->getPath2Inf(); } else { dStage_roomDt_c* roomDt = dComIfGp_roomControl_getStatusRoomDt(room_no); if (roomDt == NULL) { return NULL; } - path = roomDt->getPath2Inf(); + pd = roomDt->getPath2Inf(); } - int next_id = p_path->m_nextID; - if (path == NULL || next_id == 0xFFFF) { + int next_id = path->m_nextID; + if (pd == NULL || next_id == 0xFFFF) { return NULL; } - if (next_id < 0 || next_id >= path->m_num) { + JUT_ASSERT(111, 0 <= next_id && next_id < pd->num); + if (next_id < 0 || next_id >= pd->num) { return NULL; } - return &path->m_path[next_id]; + return &pd->m_path[next_id]; } #if !PLATFORM_GCN // Fakematch due to differing return type on non-GCN platforms -int dPath_GetPolyRoomPathVec(cBgS_PolyInfo const& poly, cXyz* p_pathVec, int* param_2) { +int dPath_GetPolyRoomPathVec(const cBgS_PolyInfo& polyinfo, cXyz* vec, int* param_2) #else -u8 dPath_GetPolyRoomPathVec(cBgS_PolyInfo const& poly, cXyz* p_pathVec, int* param_2) { +u8 dPath_GetPolyRoomPathVec(const cBgS_PolyInfo& polyinfo, cXyz* vec, int* param_2) #endif - int roomId = dComIfG_Bgsp().GetRoomId(poly); - int roomPathId = dComIfG_Bgsp().GetRoomPathId(poly); +{ + int room_no = dComIfG_Bgsp().GetRoomId(polyinfo); + int path_idx = dComIfG_Bgsp().GetRoomPathId(polyinfo); - p_pathVec->x = 0.0f; - p_pathVec->y = 0.0f; - p_pathVec->z = 0.0f; + vec->x = 0.0f; + vec->y = 0.0f; + vec->z = 0.0f; *param_2 = 0; - if (roomId == -1) { + if (room_no == -1) { return 0; } - dPath* path = dPath_GetRoomPath(roomPathId, roomId); + dPath* path = dPath_GetRoomPath(path_idx, room_no); if (path == NULL) { return 0; } - if (path->field_0x6 != 0xFF && dComIfGs_isSwitch(path->field_0x6, roomId)) { + if (path->swbit != 0xFF && dComIfGs_isSwitch(path->swbit, room_no)) { return 0; } - int pnt_no = dComIfG_Bgsp().GetRoomPathPntNo(poly); + int pnt_no = dComIfG_Bgsp().GetRoomPathPntNo(polyinfo); if (pnt_no == 0xFF || pnt_no < 0 || pnt_no >= path->m_num) { return 0; } - dPnt* pnt_start = path->m_points; - dPnt* pnt_end = &pnt_start[pnt_no]; + dPnt* pnt_end = &path->m_points[pnt_no]; dPnt* pnt_begin; if (pnt_no == path->m_num - 1) { - pnt_begin = pnt_start; + pnt_begin = path->m_points; } else { - pnt_begin = &pnt_start[pnt_no + 1]; + pnt_begin = &path->m_points[pnt_no + 1]; } - p_pathVec->x = pnt_begin->m_position.x - pnt_end->m_position.x; - p_pathVec->y = pnt_begin->m_position.y - pnt_end->m_position.y; - p_pathVec->z = pnt_begin->m_position.z - pnt_end->m_position.z; + vec->x = pnt_begin->m_position.x - pnt_end->m_position.x; + vec->y = pnt_begin->m_position.y - pnt_end->m_position.y; + vec->z = pnt_begin->m_position.z - pnt_end->m_position.z; *param_2 = path->field_0x4; return 1; } +#if DEBUG +dPath_HIO::~dPath_HIO() {} + +static dPath_HIO s_hio; +#endif + #if VERSION == VERSION_SHIELD_DEBUG void dPath_Ct() { #if DEBUG + s_hio.Ct(); + s_hio.id = mDoHIO_CREATE_CHILD("レール", &s_hio); #endif } void dPath_Dt() { - #if DEBUG - #endif + mDoHIO_DELETE_CHILD(s_hio.id); } void dPath_Move() {} void dPath_Draw() { #if DEBUG + if (s_hio.ChkDispLine()) { + static int start_counter; + int counter = start_counter / 20; + dStage_dPath_c* pd; + + int hio_roomNo = s_hio.GetRoomNo(); + if (hio_roomNo == -3) { + int roomNo = dComIfGp_roomControl_getStayNo(); + dStage_roomDt_c* roomDt = dComIfGp_roomControl_getStatusRoomDt(roomNo); + if (roomDt == NULL) { + return; + } + + pd = roomDt->getPath2Inf(); + } else if (hio_roomNo == -2) { + pd = dComIfGp_getStage()->getPathInf(); + } else if (hio_roomNo == -1) { + pd = dComIfGp_getStage()->getPath2Inf(); + } else { + dStage_roomDt_c* roomDt = dComIfGp_roomControl_getStatusRoomDt(hio_roomNo); + if (roomDt == NULL) { + return; + } + + pd = roomDt->getPath2Inf(); + } + + if (pd != NULL) { + dPath* path = pd->m_path; + for (int i = 0; i < pd->num; i++) { + if (path->m_num >= 1) { + dPnt* pnt = path->m_points; + cXyz start_pos; + cXyz end_pos; + + for (int j = 0; j < path->m_num - 1; j++) { + start_pos.set(pnt[0].m_position); + end_pos.set(pnt[1].m_position); + + if (counter == 0) { + dDbVw_drawLineOpa(start_pos, end_pos, (GXColor){0xFF, 0xFF, 0xFF, 0xFF}, TRUE, 12); + } else { + dDbVw_drawLineOpa(start_pos, end_pos, (GXColor){0xFF, 0, 0, 0xFF}, TRUE, 12); + } + + counter++; + if (counter >= 8) { + counter = 0; + } + + pnt++; + } + + if (dPath_ChkClose(path)) { + start_pos.set(pnt[0].m_position); + end_pos.set(path[1].m_points->m_position); + + if (counter == 0) { + dDbVw_drawLineOpa(start_pos, end_pos, (GXColor){0xFF, 0xFF, 0xFF, 0xFF}, TRUE, 12); + } else { + dDbVw_drawLineOpa(start_pos, end_pos, (GXColor){0xFF, 0, 0, 0xFF}, TRUE, 12); + } + + counter++; + if (counter >= 8) { + counter = 0; + } + } + } + + path++; + } + } + + start_counter--; + if (start_counter < 0) { + start_counter = 160; + } + } #endif } + +static void dummy() { + cXyz pos; + GXColor color; + dDbVw_drawSphereOpa(pos, 0.0f, color, 0); +} #endif diff --git a/src/d/d_resorce.cpp b/src/d/d_resorce.cpp index 1dce982025..0bf537bfd7 100644 --- a/src/d/d_resorce.cpp +++ b/src/d/d_resorce.cpp @@ -22,6 +22,7 @@ #ifndef __MWERKS__ #include "dusk/extras.h" +#include "dusk/logging.h" #endif dRes_info_c::dRes_info_c() { @@ -100,11 +101,13 @@ static void setIndirectTex(J3DModelData* i_modelData) { if (memcmp(textureName, "dummy", 6) == 0) { texture->setResTIMG(i, *mDoGph_gInf_c::getFrameBufferTimg()); } -#if !TARGET_PC if (memcmp(textureName, "Zbuffer", 8) == 0) { +#if !TARGET_PC texture->setResTIMG(i, *mDoGph_gInf_c::getZbufferTimg()); - } +#else + DuskLog.warn("Zbuffer texture binding not yet supported"); #endif + } } } diff --git a/src/d/d_s_logo.cpp b/src/d/d_s_logo.cpp index a878de8106..6aa3778dbf 100644 --- a/src/d/d_s_logo.cpp +++ b/src/d/d_s_logo.cpp @@ -412,11 +412,11 @@ void dScnLogo_c::progOutDraw() { } #endif - mDoGph_gInf_c::startFadeIn(1); + mDoGph_gInf_c::startFadeIn(30); } else { mExecCommand = EXEC_PROG_SET; mTimer = 150; - mDoGph_gInf_c::startFadeIn(1); + mDoGph_gInf_c::startFadeIn(30); } } } @@ -427,7 +427,7 @@ void dScnLogo_c::progSetDraw() { if (mTimer == 0) { mExecCommand = EXEC_PROG_SET2; mTimer = 30; - mDoGph_gInf_c::startFadeOut(1); + mDoGph_gInf_c::startFadeOut(30); } } @@ -463,15 +463,15 @@ void dScnLogo_c::progChangeDraw() { mTimer = 90; #else if (mDoRst::getWarningDispFlag() != 0) { - mTimer = 1; + mTimer = 90; mExecCommand = EXEC_NINTENDO_IN; } else { - mTimer = 1; + mTimer = 120; mExecCommand = EXEC_WARNING_IN; } #endif - mDoGph_gInf_c::startFadeIn(1); + mDoGph_gInf_c::startFadeIn(30); } } @@ -516,8 +516,8 @@ void dScnLogo_c::warningDispDraw() { #endif { mExecCommand = EXEC_WARNING_OUT; - mTimer = 1; - mDoGph_gInf_c::startFadeOut(1); + mTimer = 30; + mDoGph_gInf_c::startFadeOut(30); mDoRst::setWarningDispFlag(1); } } @@ -526,9 +526,9 @@ void dScnLogo_c::warningOutDraw() { dComIfGd_set2DOpa(mWarning); if (mTimer == 0) { - mTimer = 1; + mTimer = 90; mExecCommand = EXEC_NINTENDO_IN; - mDoGph_gInf_c::startFadeIn(1); + mDoGph_gInf_c::startFadeIn(30); } } @@ -537,8 +537,8 @@ void dScnLogo_c::nintendoInDraw() { if (mTimer == 0) { mExecCommand = EXEC_NINTENDO_OUT; - mTimer = 1; - mDoGph_gInf_c::startFadeOut(1); + mTimer = 30; + mDoGph_gInf_c::startFadeOut(30); } } @@ -547,8 +547,8 @@ void dScnLogo_c::nintendoOutDraw() { if (mTimer == 0) { mExecCommand = EXEC_DOLBY_IN; - mTimer = 1; - mDoGph_gInf_c::startFadeIn(1); + mTimer = 30; + mDoGph_gInf_c::startFadeIn(30); } } @@ -557,8 +557,8 @@ void dScnLogo_c::dolbyInDraw() { if (mTimer == 0) { mExecCommand = EXEC_DOLBY_OUT; - mTimer = 1; - mDoGph_gInf_c::startFadeOut(1); + mTimer = 30; + mDoGph_gInf_c::startFadeOut(30); } } @@ -567,8 +567,8 @@ void dScnLogo_c::dolbyOutDraw() { if (mTimer == 0) { mExecCommand = EXEC_DOLBY_OUT2; - mTimer = 1; - mDoGph_gInf_c::startFadeIn(1); + mTimer = 30; + mDoGph_gInf_c::startFadeIn(30); } } @@ -1098,7 +1098,7 @@ int dScnLogo_c::create() { mTimer = 90; #endif - mDoGph_gInf_c::startFadeIn(1); + mDoGph_gInf_c::startFadeIn(30); #if !(PLATFORM_WII || PLATFORM_SHIELD) checkProgSelect(); @@ -1107,13 +1107,18 @@ int dScnLogo_c::create() { mTimer = 1; field_0x218 = getProgressiveMode(); } else { + #if TARGET_PC + mTimer = 0; // Possibly unnecessary but just in case + mExecCommand = EXEC_DVD_WAIT; + #else if (mDoRst::getWarningDispFlag()) { - mTimer = 1; // 90; + mTimer = 90; mExecCommand = EXEC_NINTENDO_IN; } else { - mTimer = 1; + mTimer = 120; mExecCommand = EXEC_WARNING_IN; } + #endif mDoRst::setProgSeqFlag(1); } diff --git a/src/d/d_s_name.cpp b/src/d/d_s_name.cpp index 5f22177654..735ce4d0ca 100644 --- a/src/d/d_s_name.cpp +++ b/src/d/d_s_name.cpp @@ -17,6 +17,13 @@ #include "m_Do/m_Do_main.h" #include "f_op/f_op_overlap_mng.h" #include "dusk/memory.h" +#include "dusk/settings.h" + +#if TARGET_PC +#define SHOW_TV_SETTINGS_SCREEN (this->mShowTvSettingsScreen) +#else +#define SHOW_TV_SETTINGS_SCREEN (1) +#endif static dSn_HIO_c g_snHIO; @@ -293,13 +300,27 @@ void dScnName_c::FileSelectMain() { } void dScnName_c::FileSelectMainNormal() { +#if TARGET_PC + mShowTvSettingsScreen = !dusk::getSettings().game.hideTvSettingsScreen; +#endif + switch(dFs_c->isSelectEnd()) { case 1: - mWaitTimer = 15; - mDoGph_gInf_c::setFadeColor(*(JUtility::TColor*)&g_blackColor); - mDoGph_gInf_c::startFadeOut(15); + if (SHOW_TV_SETTINGS_SCREEN) { + mWaitTimer = 15; + mDoGph_gInf_c::setFadeColor(*(JUtility::TColor*)&g_blackColor); + mDoGph_gInf_c::startFadeOut(15); + } else { + mWaitTimer = 1; + } + mProc = dScnName_PROC_FileSelectClose; field_0x420 = 1; + + if (!SHOW_TV_SETTINGS_SCREEN) { + mDoAud_seStart(Z2SE_ENTER_GAME, NULL, 0, 0); + } + break; } } @@ -308,12 +329,17 @@ void dScnName_c::FileSelectClose() { mWaitTimer--; if (mWaitTimer == 0) { - mProc = dScnName_PROC_BrightCheckOpen; - mWaitTimer = 15; - mDrawProc = 1; - mDoGph_gInf_c::setFadeColor(*(JUtility::TColor*)&g_blackColor); - mDoGph_gInf_c::startFadeIn(15); - field_0x420 = 0; + if (SHOW_TV_SETTINGS_SCREEN) { + mProc = dScnName_PROC_BrightCheckOpen; + mWaitTimer = 15; + mDrawProc = 1; + mDoGph_gInf_c::setFadeColor(*(JUtility::TColor*)&g_blackColor); + mDoGph_gInf_c::startFadeIn(15); + field_0x420 = 0; + } else { + doPreLoadSetup(); + field_0x420 = 0; + } } } @@ -330,24 +356,34 @@ void dScnName_c::brightCheck() { mBrightCheck->_move(); if (mBrightCheck->isEnd()) { - dComIfGs_setSaveTotalTime(dComIfGs_getTotalTime()); - dComIfGs_setSaveStartTime(OSGetTime()); - mDoAud_bgmStop(45); - - field_0x41f = 0; - mProc = dScnName_PROC_ChangeGameScene; - - // Reset rupee "first-time collection" flags so the collection cutscene will play again - dComIfGs_offItemFirstBit(dItemNo_GREEN_RUPEE_e); - dComIfGs_offItemFirstBit(dItemNo_BLUE_RUPEE_e); - dComIfGs_offItemFirstBit(dItemNo_YELLOW_RUPEE_e); - dComIfGs_offItemFirstBit(dItemNo_RED_RUPEE_e); - dComIfGs_offItemFirstBit(dItemNo_PURPLE_RUPEE_e); - dComIfGs_offItemFirstBit(dItemNo_ORANGE_RUPEE_e); - dComIfGs_offItemFirstBit(dItemNo_SILVER_RUPEE_e); + doPreLoadSetup(); } } +void dScnName_c::doPreLoadSetup() { + dComIfGs_setSaveTotalTime(dComIfGs_getTotalTime()); + dComIfGs_setSaveStartTime(OSGetTime()); + mDoAud_bgmStop(45); + + field_0x41f = 0; + mProc = dScnName_PROC_ChangeGameScene; + + #if TARGET_PC + if (dusk::getSettings().game.disableRupeeCutscenes) { + return; + } + #endif + + // Reset rupee "first-time collection" flags so the collection cutscene will play again + dComIfGs_offItemFirstBit(dItemNo_GREEN_RUPEE_e); + dComIfGs_offItemFirstBit(dItemNo_BLUE_RUPEE_e); + dComIfGs_offItemFirstBit(dItemNo_YELLOW_RUPEE_e); + dComIfGs_offItemFirstBit(dItemNo_RED_RUPEE_e); + dComIfGs_offItemFirstBit(dItemNo_PURPLE_RUPEE_e); + dComIfGs_offItemFirstBit(dItemNo_ORANGE_RUPEE_e); + dComIfGs_offItemFirstBit(dItemNo_SILVER_RUPEE_e); +} + void dScnName_c::changeGameScene() { if (!mDoRst::isReset() && !fopOvlpM_IsPeek()) { dComIfGs_gameStart(); diff --git a/src/d/d_save.cpp b/src/d/d_save.cpp index 06b92994db..3289a49c64 100644 --- a/src/d/d_save.cpp +++ b/src/d/d_save.cpp @@ -25,6 +25,8 @@ #include "lingcod/lingcod.h" #endif +#include "dusk/settings.h" + static u8 dSv_item_rename(u8 i_itemNo) { switch (i_itemNo) { case dItemNo_OIL_BOTTLE_2_e: @@ -111,11 +113,23 @@ u16 dSv_player_status_a_c::getRupeeMax() const { if (mWalletSize < 3) { // if you make this a default, it wont match. Compiler, pls. switch (mWalletSize) { case WALLET: + #if TARGET_PC + return dusk::getSettings().game.biggerWallets ? 500 : 300; + #else return 300; + #endif case BIG_WALLET: + #if TARGET_PC + return dusk::getSettings().game.biggerWallets ? 1000 : 600; + #else return 600; + #endif case GIANT_WALLET: + #if TARGET_PC + return dusk::getSettings().game.biggerWallets ? 2000 : 1000; + #else return 1000; + #endif } } diff --git a/src/d/d_stage.cpp b/src/d/d_stage.cpp index f6c90b0f3d..f3cdfed17b 100644 --- a/src/d/d_stage.cpp +++ b/src/d/d_stage.cpp @@ -21,6 +21,9 @@ #include "m_Do/m_Do_Reset.h" #include #include + +#include "dusk/logging.h" +#include "dusk/string.hpp" #if TARGET_PC #include #include @@ -151,7 +154,14 @@ static int dStage_RoomKeepDoorInit(dStage_dt_c* i_stage, void* i_data, int entry } void dStage_startStage_c::set(const char* i_Name, s8 i_RoomNo, s16 i_Point, s8 i_Layer) { +#if TARGET_PC + // UB fix. + if (mName != i_Name) { + dusk::SafeStringCopy(mName, i_Name); + } +#else strcpy(mName, i_Name); +#endif mRoomNo = i_RoomNo; mPoint = i_Point; mLayer = i_Layer; @@ -382,6 +392,10 @@ static void dummy1(dStage_roomControl_c* roomControl) { } JKRExpHeap* dStage_roomControl_c::createMemoryBlock(int i_blockIdx, u32 i_heapSize) { + #if TARGET_PC + i_heapSize *= 2; + #endif + if (mMemoryBlock[i_blockIdx] == NULL) { mMemoryBlock[i_blockIdx] = JKRCreateExpHeap(i_heapSize, mDoExt_getArchiveHeap(), false); JKRHEAP_NAMEF(mMemoryBlock[i_blockIdx], "Room control memory block %d", i_blockIdx); @@ -2127,7 +2141,7 @@ static int dStage_pathInfoInit(dStage_dt_c* i_stage, void* i_data, int entryNum, i_stage->setPathInfo(path_c); - for (int i = 0; i < path_c->m_num; i++) { + for (int i = 0; i < path_c->num; i++) { #if TARGET_PC path->m_points.setBase(i_stage->getPntInf()->m_pnt_offset); #else @@ -2156,7 +2170,7 @@ static int dStage_rpatInfoInit(dStage_dt_c* i_stage, void* i_data, int i_num, vo dPath* pPath = pStagePath->m_path; i_stage->setPath2Info(pStagePath); - for (s32 i = 0; i < pStagePath->m_num; pPath++, i++, (void)0) { + for (s32 i = 0; i < pStagePath->num; pPath++, i++, (void)0) { #if TARGET_PC pPath->m_points.setBase(i_stage->getPnt2Inf()->m_pnt_offset); #else diff --git a/src/d/d_vib_pattern.cpp b/src/d/d_vib_pattern.cpp index d8263b45bd..6c06016cf5 100644 --- a/src/d/d_vib_pattern.cpp +++ b/src/d/d_vib_pattern.cpp @@ -59,3 +59,30 @@ const vib_pattern dVibration_c::CQ_patt[VIBMODE_Q_MAX] = { /* VIBMODE_Q_POWER8 */ {4, 32, 0x6B6D6B6D}, /* VIBMODE_Q_HORSE */ {0, 27, 0x20201000}, }; + +const char* shock_names[VIBMODE_S_MAX] = { + "VIBMODE_S_CUSTOM", + "VIBMODE_S_POWER1", + "VIBMODE_S_POWER2", + "VIBMODE_S_POWER3", + "VIBMODE_S_POWER4", + "VIBMODE_S_POWER5", + "VIBMODE_S_POWER6", + "VIBMODE_S_POWER7", + "VIBMODE_S_POWER8", + "VIBMODE_S_DOKUTT", + "VIBMODE_S_FOR2D", +}; + +const char* quake_names[VIBMODE_Q_MAX] = { + "VIBMODE_Q_CUSTOM", + "VIBMODE_Q_POWER1", + "VIBMODE_Q_POWER2", + "VIBMODE_Q_POWER3", + "VIBMODE_Q_POWER4", + "VIBMODE_Q_POWER5", + "VIBMODE_Q_POWER6", + "VIBMODE_Q_POWER7", + "VIBMODE_Q_POWER8", + "VIBMODE_Q_HORSE", +}; diff --git a/src/d/d_vibration.cpp b/src/d/d_vibration.cpp index 70a1a04779..a145ae878c 100644 --- a/src/d/d_vibration.cpp +++ b/src/d/d_vibration.cpp @@ -5,6 +5,7 @@ #include "f_op/f_op_camera_mng.h" #include "m_Do/m_Do_controller_pad.h" #include "SSystem/SComponent/c_math.h" +#include "d/d_s_play.h" #include #define RESET_FRAME -99 @@ -21,6 +22,13 @@ u16* makedata(u16* data, u32 pattern, s32 length) { data[1] = pattern >> 16; data[2] = pattern; data[3] = 0; + +#if TARGET_PC + data[0] = BSWAP16(data[0]); + data[1] = BSWAP16(data[1]); + data[2] = BSWAP16(data[2]); +#endif + return data; } @@ -31,27 +39,30 @@ s32 rollshift(u32 pattern, s32 length, s32 index) { #else index %= length; #endif - return (pattern >> index) | (pattern << (length - index)); + u32 var_r31 = pattern; + return (var_r31 >> index) | (var_r31 << (length - index)); } u32 makebits(u32 bits, s32 length, s32 numbits) { + bits &= (-1 << (32 - length)); + u32 mask = bits; s32 i; - u32 mask = bits & (-1 << (32 - length)); - bits = mask; for (i = length; i < numbits; i += length) { - bits = mask | (bits >> length); + mask = bits | (mask >> length); } - return bits; + return mask; } u32 randombit(s32 rounds, s32 length) { u32 value = 0; + int i; - for (int i = 0; i < rounds; i++) { + for (i = 0; i < rounds; i++) { value |= 0x40000000 >> (u32)(length * cM_rnd()); } + return value; } }; @@ -70,10 +81,13 @@ int dVibration_c::Run() { mMotor.mQuake.field_0x0 |= 1; } - mMotor.mQuake.mFrame = RESET_FRAME; - mMotor.mShock.mFrame = RESET_FRAME; + mMotor.mShock.mFrame = mMotor.mQuake.mFrame = RESET_FRAME; } + #if DEBUG + testShake(); + #endif + if ((mCamera.mShock.field_0x0 & 1) && mCamera.mShock.mFrame != RESET_FRAME) { mCamera.mShock.mFrame = 0; mCamera.mShock.mVibMode = VIBMODE_S_NONE; @@ -85,6 +99,8 @@ int dVibration_c::Run() { } if (mCamera.mShock.mFrame == 0 || mCamera.mQuake.mFrame == 0) { + s32 pattern; + u32 sp1C = 0; u32 rumble = 0; if (mCamera.mShock.mVibMode == VIBMODE_S_NONE || (mCamera.mShock.field_0x0 & 1)) { mCamera.mShock.mFrame = RESET_FRAME; @@ -104,7 +120,7 @@ int dVibration_c::Run() { rumble |= RUMBLE_QUAKE; } - s32 length, pattern, bits, flags; + s32 length, bits, flags; switch (rumble) { case RUMBLE_SHOCK: length = mCamera.mShock.mLength; @@ -119,6 +135,12 @@ int dVibration_c::Run() { if (dComIfGp_getCamera(0) != NULL && dComIfGp_getCamera(0)->field_0x22f == 0x47) { dCam_getBody()->StartShake(length, (u8*)&pattern, flags, mCamera.mShock.mPos.norm()); } + + #if DEBUG + if (mVibTest.m_displayDbg & 0x8000) { + OS_REPORT("vibration: %06d: start camera(%d) %x %d\n", mFrame, rumble, pattern, length); + } + #endif break; case RUMBLE_QUAKE: length = mCamera.mQuake.mLength; @@ -133,11 +155,18 @@ int dVibration_c::Run() { if (dComIfGp_getCamera(0) != NULL && dComIfGp_getCamera(0)->field_0x22f == 0x47) { dCam_getBody()->StartShake(length, (u8*)&pattern, flags, mCamera.mQuake.mPos.norm()); } + + #if DEBUG + if (mVibTest.m_displayDbg & 0x8000) { + OS_REPORT("vibration: %06d: start camera(%d) %x %d\n", mFrame, rumble, pattern, length); + } + #endif break; case RUMBLE_SHOCK | RUMBLE_QUAKE: pattern = mCamera.mShock.mPattern << mCamera.mShock.mFrame; length = mCamera.mShock.mLength - mCamera.mShock.mFrame; - pattern |= rollshift(makebits(mCamera.mQuake.mPattern, mCamera.mQuake.mLength, length), length, mFrame); + sp1C = makebits(mCamera.mQuake.mPattern, mCamera.mQuake.mLength, length); + pattern |= rollshift(sp1C, length, mFrame); pattern |= randombit(mCamera.mShock.mRounds > mCamera.mQuake.mRounds ? mCamera.mShock.mRounds : mCamera.mQuake.mRounds, length); flags = mCamera.mShock.mFlags | mCamera.mQuake.mFlags; @@ -149,13 +178,24 @@ int dVibration_c::Run() { dCam_getBody()->StartShake(length, (u8*)&pattern, flags, cXyz(mCamera.mShock.mPos + mCamera.mQuake.mPos).norm()); } - mCamera.mQuake.mFrame = 0; - mCamera.mShock.mFrame = 0; + mCamera.mShock.mFrame = mCamera.mQuake.mFrame = 0; + + #if DEBUG + if (mVibTest.m_displayDbg & 0x8000) { + OS_REPORT("vibration: %06d: start camera(%d) %x %d\n", mFrame, rumble, pattern, length); + } + #endif break; default: if (dComIfGp_getCamera(0) != NULL && dComIfGp_getCamera(0)->field_0x22f == 0x47) { dCam_getBody()->StopShake(); } + + #if DEBUG + if (mVibTest.m_displayDbg & 0x8000) { + OS_REPORT("vibration: %06d: stop camera\n", mFrame); + } + #endif break; } } @@ -171,6 +211,7 @@ int dVibration_c::Run() { } if (mMotor.mShock.mFrame == 0 || mMotor.mQuake.mFrame == 0) { + s32 sp14 = 0; u32 rumble = 0; if (mMotor.mShock.mVibMode == VIBMODE_S_NONE || (mMotor.mShock.field_0x0 & 1)) { mMotor.mShock.mFrame = RESET_FRAME; @@ -199,39 +240,64 @@ int dVibration_c::Run() { pattern = mMotor.mShock.mPattern; pattern |= randombit(mMotor.mShock.mRounds, length); mMotor.mShock.mStopFrame = length; - mDoCPd_c::startMotorWave(PAD_1, makedata(data, pattern, length), JUTGamePad::CRumble::VAL_0, 60); + mDoCPd_c::startMotorWave(PAD_1, (u8*)makedata(data, pattern, length), JUTGamePad::CRumble::VAL_0, 60); + + #if DEBUG + if (mVibTest.m_displayDbg & 0x8000) { + OS_REPORT("vibration: %06d: start motor (%d) %x %d\n", mFrame, rumble, pattern, length); + } + #endif break; case RUMBLE_QUAKE: length = mMotor.mQuake.mLength; pattern = rollshift(mMotor.mQuake.mPattern, length, mFrame); pattern |= randombit(mMotor.mQuake.mRounds, length); mMotor.mQuake.mStopFrame = INT_MAX; - mDoCPd_c::startMotorWave(PAD_1, makedata(data, pattern, length), JUTGamePad::CRumble::VAL_1, 60); + + OS_REPORT("d_vibration mDoCPd_c::startMotorWave\n"); + + mDoCPd_c::startMotorWave(PAD_1, (u8*)makedata(data, pattern, length), JUTGamePad::CRumble::VAL_1, 60); + + #if DEBUG + if (mVibTest.m_displayDbg & 0x8000) { + OS_REPORT("vibration: %06d: start motor (%d) %x %d\n", mFrame, rumble, pattern, length); + } + #endif break; case RUMBLE_SHOCK | RUMBLE_QUAKE: pattern = mMotor.mShock.mPattern << mMotor.mShock.mFrame; length = mMotor.mShock.mLength - mMotor.mShock.mFrame; - pattern |= rollshift(makebits(mMotor.mQuake.mPattern, mMotor.mQuake.mLength, length), length, mFrame); + sp14 = makebits(mMotor.mQuake.mPattern, mMotor.mQuake.mLength, length); + pattern |= rollshift(sp14, length, mFrame); pattern |= randombit(mMotor.mShock.mRounds > mMotor.mQuake.mRounds ? mMotor.mShock.mRounds : mMotor.mQuake.mRounds, length); mMotor.mQuake.mStopFrame = length; mMotor.mShock.mStopFrame = length; - mMotor.mQuake.mFrame = 0; - mMotor.mShock.mFrame = 0; - mDoCPd_c::startMotorWave(PAD_1, makedata(data, pattern, length), JUTGamePad::CRumble::VAL_0, 60); + mMotor.mShock.mFrame = mMotor.mQuake.mFrame = 0; + + mDoCPd_c::startMotorWave(PAD_1, (u8*)makedata(data, pattern, length), JUTGamePad::CRumble::VAL_0, 60); + + #if DEBUG + if (mVibTest.m_displayDbg & 0x8000) { + OS_REPORT("vibration: %06d: start motor (%d) %x %d\n", mFrame, rumble, pattern, length); + } + #endif break; default: mDoCPd_c::stopMotorWave(PAD_1); mDoCPd_c::stopMotor(PAD_1); - mMotor.mQuake.mStopFrame = RESET_FRAME; - mMotor.mShock.mStopFrame = RESET_FRAME; + mMotor.mShock.mStopFrame = mMotor.mQuake.mStopFrame = RESET_FRAME; + + #if DEBUG + if (mVibTest.m_displayDbg & 0x8000) { + OS_REPORT("vibration: %06d: stop motor\n", mFrame); + } + #endif break; } } - mCamera.mQuake.field_0x0 = 0; - mCamera.mShock.field_0x0 = 0; - mMotor.mQuake.field_0x0 = 0; - mMotor.mShock.field_0x0 = 0; + mCamera.mShock.field_0x0 = mCamera.mQuake.field_0x0 = 0; + mMotor.mShock.field_0x0 = mMotor.mQuake.field_0x0 = 0; if (mCamera.mShock.mFrame >= 0) { mCamera.mShock.mFrame++; @@ -259,9 +325,22 @@ int dVibration_c::Run() { if (mMotor.mQuake.mFrame >= 930) { mMotor.mQuake.mFrame = 0; + + #if DEBUG + if (mVibTest.m_displayDbg & 0x8000) { + OS_REPORT("vibration: %06d: stop motor @ limit restart\n", mFrame); + } + #endif } else if (mMotor.mQuake.mFrame >= 900) { mDoCPd_c::stopMotorWave(PAD_1); mDoCPd_c::stopMotor(PAD_1); + + #if DEBUG + if ((mVibTest.m_displayDbg & 0x8000) && mMotor.mQuake.mFrame == 900) { + OS_REPORT("vibration: %06d: stop motor @ limit\n", mFrame); + } + #endif + mMotor.mQuake.mFrame++; } else if (mMotor.mQuake.mFrame >= 0) { mMotor.mQuake.mFrame++; @@ -297,6 +376,12 @@ bool dVibration_c::StartShock(int i_vibmode, int i_flags, cXyz i_pos) { ret = true; } + #if DEBUG + if ((mVibTest.m_displayDbg & 0x8000) && ret) { + OS_REPORT("vibration: %06d: start shock %d %d\n", mFrame, i_vibmode, i_flags); + } + #endif + return ret; } @@ -322,6 +407,12 @@ bool dVibration_c::StartQuake(int i_vibmode, int i_flags, cXyz i_pos) { ret = true; } + #if DEBUG + if ((mVibTest.m_displayDbg & 0x8000) && ret) { + OS_REPORT("vibration: %06d: start quake %d %d\n", mFrame, i_vibmode, i_flags); + } + #endif + return ret; } @@ -354,6 +445,12 @@ bool dVibration_c::StartQuake(const u8* i_pattern, int i_rounds, int i_flags, cX ret = true; } + #if DEBUG + if ((mVibTest.m_displayDbg & 0x8000) && ret) { + OS_REPORT("vibration: %06d: start quake %x %d %d\n", mFrame, bits, i_rounds, i_flags); + } + #endif + return ret; } @@ -374,9 +471,114 @@ int dVibration_c::StopQuake(int i_flags) { ret = TRUE; } + #if DEBUG + if ((mVibTest.m_displayDbg & 0x8000) && ret) { + OS_REPORT("vibration: %06d: stop quake %d\n", mFrame, i_flags); + } + #endif + return ret; } +#if DEBUG +int dVibration_c::testShake() { + int var_r29, var_r28; + int ret = FALSE; + s32 cam_bits, cam_len, cam_rounds; + s32 motor_bits, motor_len, motor_rounds; + + switch (mVibTest.field_0x10) { + case 10: + if (mVibTest.m_vibswitch >= 1 && mVibTest.m_vibswitch < 100) { + var_r29 = mVibTest.m_vibswitch; + cam_bits = CS_patt[var_r29].bits; + cam_len = CS_patt[var_r29].length; + cam_rounds = CS_patt[var_r29].rounds; + + motor_bits = MS_patt[var_r29].bits; + motor_len = MS_patt[var_r29].length; + motor_rounds = MS_patt[var_r29].rounds; + + OS_REPORT("vibration: TEST C b %x l %d r %d\n", cam_bits, cam_len, cam_rounds); + OS_REPORT("(SHOCK) m %2d M b %x l %d r %d\n", motor_bits, motor_len, motor_rounds); + } else { + motor_bits = cam_bits = (mVibTest.m_pattern << 0x10) | mVibTest.m_pattern2; + motor_len = cam_len = mVibTest.m_length; + motor_rounds = cam_rounds = mVibTest.m_randombit; + } + + if (mVibTest.field_0xa & 0x7E) { + mCamera.mShock.mVibMode = 0; + mCamera.mShock.mFrame = 0; + mCamera.mShock.mFlags = mVibTest.field_0xa; + mCamera.mShock.mPos = cXyz(0.0f, 1.0f, 0.0f); + mCamera.mShock.mPattern = cam_bits; + mCamera.mShock.mLength = cam_len; + mCamera.mShock.mRounds = cam_rounds; + } + + if (mVibTest.field_0xa & 1) { + mMotor.mShock.mVibMode = 0; + mMotor.mShock.mFrame = 0; + mMotor.mShock.mPattern = motor_bits; + mMotor.mShock.mLength = motor_len; + mMotor.mShock.mRounds = motor_rounds; + } + + mVibTest.field_0x10 = 0; + ret = TRUE; + break; + case 20: + if (mVibTest.m_vibswitch >= 100 && mVibTest.m_vibswitch < 200) { + var_r28 = mVibTest.m_vibswitch - 100; + cam_bits = CQ_patt[var_r28].bits; + cam_len = CQ_patt[var_r28].length; + cam_rounds = CQ_patt[var_r28].rounds; + + motor_bits = MQ_patt[var_r28].bits; + motor_len = MQ_patt[var_r28].length; + motor_rounds = MQ_patt[var_r28].rounds; + + OS_REPORT("vibration: TEST C b %x l %d r %d\n", cam_bits, cam_len, cam_rounds); + OS_REPORT("(QUAKE) m %2d M b %x l %d r %d\n", motor_bits, motor_len, motor_rounds); + } else { + motor_bits = cam_bits = (mVibTest.m_pattern << 0x10) | mVibTest.m_pattern2; + motor_len = cam_len = mVibTest.m_length; + motor_rounds = cam_rounds = mVibTest.m_randombit; + } + + if (mVibTest.field_0xa & 0x7E) { + mCamera.mQuake.mVibMode = 0; + mCamera.mQuake.mFrame = 0; + mCamera.mQuake.mFlags = mVibTest.field_0xa; + mCamera.mQuake.mPos = cXyz(0.0f, 1.0f, 0.0f); + mCamera.mQuake.mPattern = cam_bits; + mCamera.mQuake.mLength = cam_len; + mCamera.mQuake.mRounds = cam_rounds; + } + + if (mVibTest.field_0xa & 1) { + mMotor.mQuake.mVibMode = 0; + mMotor.mQuake.mFrame = 0; + mMotor.mQuake.mPattern = motor_bits; + mMotor.mQuake.mLength = motor_len; + mMotor.mQuake.mRounds = motor_rounds; + } + + mVibTest.field_0x10 = 0; + ret = TRUE; + break; + case 21: + OS_REPORT("vibration: TEST STOP\n"); + StopQuake(0x1F); + mVibTest.field_0x10 = 0; + break; + } + + return ret; +} +#endif + void dVibration_c::Kill() { mDoCPd_c::stopMotorWaveHard(PAD_1); mDoCPd_c::stopMotorHard(PAD_1); @@ -388,30 +590,18 @@ bool dVibration_c::CheckQuake() { } void dVibration_c::setDefault() { - mMotor.mShock.mVibMode = VIBMODE_S_NONE; - mCamera.mShock.mVibMode = VIBMODE_S_NONE; - mMotor.mQuake.mVibMode = VIBMODE_Q_NONE; - mCamera.mQuake.mVibMode = VIBMODE_Q_NONE; - mMotor.mShock.field_0x0 = 0; - mCamera.mShock.field_0x0 = 0; - mMotor.mQuake.field_0x0 = 0; - mCamera.mQuake.field_0x0 = 0; - mMotor.mShock.mPattern = 0; - mCamera.mShock.mPattern = 0; - mMotor.mQuake.mPattern = 0; - mCamera.mQuake.mPattern = 0; - mMotor.mShock.mLength = 0; - mCamera.mShock.mLength = 0; - mMotor.mQuake.mLength = 0; - mCamera.mQuake.mLength = 0; - mMotor.mShock.mRounds = 0; - mCamera.mShock.mRounds = 0; - mMotor.mQuake.mRounds = 0; - mCamera.mQuake.mRounds = 0; - mMotor.mShock.mFrame = RESET_FRAME; - mCamera.mShock.mFrame = RESET_FRAME; - mMotor.mQuake.mFrame = RESET_FRAME; - mCamera.mQuake.mFrame = RESET_FRAME; + mCamera.mShock.mVibMode = mMotor.mShock.mVibMode = VIBMODE_S_NONE; + mCamera.mQuake.mVibMode = mMotor.mQuake.mVibMode = VIBMODE_Q_NONE; + mCamera.mShock.field_0x0 = mMotor.mShock.field_0x0 = 0; + mCamera.mQuake.field_0x0 = mMotor.mQuake.field_0x0 = 0; + mCamera.mShock.mPattern = mMotor.mShock.mPattern = 0; + mCamera.mQuake.mPattern = mMotor.mQuake.mPattern = 0; + mCamera.mShock.mLength = mMotor.mShock.mLength = 0; + mCamera.mQuake.mLength = mMotor.mQuake.mLength = 0; + mCamera.mShock.mRounds = mMotor.mShock.mRounds = 0; + mCamera.mQuake.mRounds = mMotor.mQuake.mRounds = 0; + mCamera.mShock.mFrame = mMotor.mShock.mFrame = RESET_FRAME; + mCamera.mQuake.mFrame = mMotor.mQuake.mFrame = RESET_FRAME; mMotor.mShock.mStopFrame = RESET_FRAME; mMotor.mQuake.mStopFrame = RESET_FRAME; mMode = MODE_WAIT; @@ -421,6 +611,10 @@ void dVibration_c::setDefault() { void dVibration_c::Init() { Kill(); setDefault(); + + #if DEBUG + mVibTest.Init(); + #endif } void dVibration_c::Pause() { @@ -430,10 +624,8 @@ void dVibration_c::Pause() { mDoCPd_c::stopMotorHard(PAD_1); } - mMotor.mShock.mVibMode = VIBMODE_S_NONE; - mCamera.mShock.mVibMode = VIBMODE_S_NONE; - mMotor.mShock.mFrame = RESET_FRAME; - mCamera.mShock.mFrame = RESET_FRAME; + mCamera.mShock.mVibMode = mMotor.mShock.mVibMode = VIBMODE_S_NONE; + mCamera.mShock.mFrame = mMotor.mShock.mFrame = RESET_FRAME; if (mCamera.mQuake.mVibMode != VIBMODE_Q_NONE) { mCamera.mQuake.mFrame = 0; @@ -449,3 +641,133 @@ void dVibration_c::Pause() { void dVibration_c::Remove() { Kill(); } + +#if DEBUG +void dVibTest_c::setDefault() { + m_pattern = m_pattern2 = 0; + field_0xa = 0; + field_0x10 = 0; + m_randombit = 0; + m_vibswitch = 0; + m_displayDbg = 0; + m_length = 32; +} + +dVibTest_c::dVibTest_c() { + setDefault(); + id = mDoHIO_CREATE_CHILD("振動処理", this); +} + +dVibTest_c::~dVibTest_c() { + mDoHIO_DELETE_CHILD(id); +} + +void dVibTest_c::Init() { + setDefault(); +} + +void dVibTest_c::genMessage(JORMContext* mctx) { + int i; + + mctx->genLabel("- パターン", 0, 0); + mctx->genCheckBox(" ", &m_pattern, 0x8000, 0, NULL, 10, 0x14, 0x14, 0x14); + mctx->genCheckBox(" ", &m_pattern, 0x4000, 0, NULL, 0x1e, 0x14, 0x14, 0x14); + mctx->genCheckBox(" ", &m_pattern, 0x2000, 0, NULL, 0x32, 0x14, 0x14, 0x14); + mctx->genCheckBox(" ", &m_pattern, 0x1000, 0, NULL, 0x46, 0x14, 0x14, 0x14); + mctx->genCheckBox(" ", &m_pattern, 0x800, 0, NULL, 0x5a, 0x14, 0x14, 0x14); + mctx->genCheckBox(" ", &m_pattern, 0x400, 0, NULL, 0x6e, 0x14, 0x14, 0x14); + mctx->genCheckBox(" ", &m_pattern, 0x200, 0, NULL, 0x82, 0x14, 0x14, 0x14); + mctx->genCheckBox(" ", &m_pattern, 0x100, 0, NULL, 0x96, 0x14, 0x14, 0x14); + mctx->genCheckBox(" ", &m_pattern, 0x80, 0, NULL, 0xaa, 0x14, 0x14, 0x14); + mctx->genCheckBox(" ", &m_pattern, 0x40, 0, NULL, 0xbe, 0x14, 0x14, 0x14); + mctx->genCheckBox(" ", &m_pattern, 0x20, 0, NULL, 0xd2, 0x14, 0x14, 0x14); + mctx->genCheckBox(" ", &m_pattern, 0x10, 0, NULL, 0xe6, 0x14, 0x14, 0x14); + mctx->genCheckBox(" ", &m_pattern, 8, 0, NULL, 0xfa, 0x14, 0x14, 0x14); + mctx->genCheckBox(" ", &m_pattern, 4, 0, NULL, 0x10e, 0x14, 0x14, 0x14); + mctx->genCheckBox(" ", &m_pattern, 2, 0, NULL, 0x122, 0x14, 0x14, 0x14); + mctx->genCheckBox(" ", &m_pattern, 1, 0, NULL, 0x136, 0x14, 0x14, 0x14); + mctx->genCheckBox(" ", &m_pattern2, 0x8000, 0, NULL, 0x14a, 0x14, 0x14, 0x14); + mctx->genCheckBox(" ", &m_pattern2, 0x4000, 0, NULL, 0x15e, 0x14, 0x14, 0x14); + mctx->genCheckBox(" ", &m_pattern2, 0x2000, 0, NULL, 0x172, 0x14, 0x14, 0x14); + mctx->genCheckBox(" ", &m_pattern2, 0x1000, 0, NULL, 0x186, 0x14, 0x14, 0x14); + mctx->genCheckBox(" ", &m_pattern2, 0x800, 0, NULL, 0x19a, 0x14, 0x14, 0x14); + mctx->genCheckBox(" ", &m_pattern2, 0x400, 0, NULL, 0x1ae, 0x14, 0x14, 0x14); + mctx->genCheckBox(" ", &m_pattern2, 0x200, 0, NULL, 0x1c2, 0x14, 0x14, 0x14); + mctx->genCheckBox(" ", &m_pattern2, 0x100, 0, NULL, 0x1d6, 0x14, 0x14, 0x14); + mctx->genCheckBox(" ", &m_pattern2, 0x80, 0, NULL, 0x1ea, 0x14, 0x14, 0x14); + mctx->genCheckBox(" ", &m_pattern2, 0x40, 0, NULL, 0x1fe, 0x14, 0x14, 0x14); + mctx->genCheckBox(" ", &m_pattern2, 0x20, 0, NULL, 0x212, 0x14, 0x14, 0x14); + mctx->genCheckBox(" ", &m_pattern2, 0x10, 0, NULL, 0x226, 0x14, 0x14, 0x14); + mctx->genCheckBox(" ", &m_pattern2, 8, 0, NULL, 0x23a, 0x14, 0x14, 0x14); + mctx->genCheckBox(" ", &m_pattern2, 4, 0, NULL, 0x24e, 0x14, 0x14, 0x14); + mctx->genCheckBox(" ", &m_pattern2, 2, 0, NULL, 0x262, 0x14, 0x14, 0x14); + mctx->genCheckBox(" ", &m_pattern2, 1, 0, NULL, 0x276, 0x14, 0x14, 0x14); + + mctx->genLabel("-", 0, 0); + mctx->startComboBox("振動切替", &m_vibswitch, 0x130); + for (i = 0; i < 11; i++) { + mctx->genComboBoxItem(shock_names[i], i); + } + for (i = 0; i < 10; i++) { + mctx->genComboBoxItem(quake_names[i], i + 100); + } + mctx->endComboBox(); + + mctx->genLabel("- VIBMODE_S_* は衝撃型用、VIBMODE_Q_* は地震型用です", 0); + mctx->genLabel("-", 0); + + mctx->genLabel("- タイプ", 0); + mctx->genCheckBox("振動パック", &field_0xa, 1, 0); + mctx->genCheckBox("座標揺れ", &field_0xa, 2, 0); + mctx->genCheckBox("座標揺れ(強)", &field_0xa, 0x40, 0); + mctx->genCheckBox("画角揺れ", &field_0xa, 4, 0); + mctx->genCheckBox("Z揺れ", &field_0xa, 8, 0); + mctx->genCheckBox("ブラー", &field_0xa, 0x10, 0); + + mctx->genLabel("-", 0); + mctx->genSlider("長さ", &m_length, 0, 0x20); + mctx->genSlider("ランダムビット", &m_randombit, 0, 0x20); + + mctx->genLabel("-", 0); + mctx->genButton("衝撃型揺れ開始", 0x12d, 0); + mctx->genButton("地震型揺れ開始", 0x12e, 0); + mctx->genButton("地震型揺れ停止", 0x12f, 0); + + mctx->genLabel("-", 0, 0); + mctx->genCheckBox(" デバッグ表示", &m_displayDbg, 0x8000); + + mctx->genLabel("-", 0, 0); + mctx->genLabel("-", 0, 0); + mctx->genButton("揺れ実験(強)", 0x131, 0); + mctx->genButton("揺れ実験(中)", 0x132, 0); + mctx->genButton("揺れ実験(弱)", 0x133, 0); + + mctx->genLabel("-", 0, 0); + mctx->genLabel("-", 0, 0); +} + +void dVibTest_c::listenPropertyEvent(const JORPropertyEvent* event) { + JORReflexible::listenPropertyEvent(event); + + switch ((int)event->id) { + case 0x12D: + field_0x10 = 10; + break; + case 0x12E: + field_0x10 = 20; + break; + case 0x12F: + field_0x10 = 21; + break; + case 0x131: + dComIfGp_getVibration().StartShock(XREG_S(1) + 8, 0x1F, cXyz(0.0f, 1.0f, 0.0f)); + break; + case 0x132: + dComIfGp_getVibration().StartShock(XREG_S(2) + 4, 0x1F, cXyz(0.0f, 1.0f, 0.0f)); + break; + case 0x133: + dComIfGp_getVibration().StartShock(XREG_S(3) + 2, 0x1F, cXyz(0.0f, 1.0f, 0.0f)); + break; + } +} +#endif diff --git a/src/dusk/OSContext.cpp b/src/dusk/OSContext.cpp index 4f54b8b963..d2bb1803ea 100644 --- a/src/dusk/OSContext.cpp +++ b/src/dusk/OSContext.cpp @@ -23,26 +23,11 @@ void OSSetCurrentContext(OSContext* context) { } void OSClearContext(OSContext* context) { - if (!context) return; - context->mode = 0; - context->state = 0; + // No-op on PC } void OSInitContext(OSContext* context, u32 pc, u32 newsp) { - if (!context) return; - memset(context, 0, sizeof(OSContext)); - context->srr0 = pc; - context->gpr[1] = newsp; -} - -u32 OSSaveContext(OSContext* context) { - // On PC we don't save PowerPC registers. - // Return 0 = "context was just saved" (as opposed to 1 = "restored from save"). - return 0; -} - -void OSLoadContext(OSContext* context) { - // No-op on PC (no PowerPC register restore) + // No-op on PC } void OSDumpContext(OSContext* context) { @@ -66,20 +51,15 @@ void OSSaveFPUContext(OSContext* fpucontext) { } u32 OSGetStackPointer(void) { - // Return approximate stack pointer - volatile u32 dummy; - return (u32)(uintptr_t)&dummy; + return 0; } u32 OSSwitchStack(u32 newsp) { - // Not meaningful on PC - return current sp - return OSGetStackPointer(); + abort(); } int OSSwitchFiber(u32 pc, u32 newsp) { - // Not meaningful on PC - OSReport("[PC] OSSwitchFiber: not supported on PC\n"); - return 0; + abort(); } void __OSContextInit(void) { diff --git a/src/dusk/OSMutex.cpp b/src/dusk/OSMutex.cpp index 8e26402e0d..ef1a528f1b 100644 --- a/src/dusk/OSMutex.cpp +++ b/src/dusk/OSMutex.cpp @@ -72,6 +72,15 @@ static PCCondData& GetCondData(OSCond* cond) { return *it->second; } +void ClearCondMap() { + std::lock_guard lock(GetCondMapMutex()); + auto& map = GetCondMap(); + for (auto& pair : map) { + pair.second->cv.notify_all(); + } + map.clear(); +} + // ============================================================================ // C API functions // ============================================================================ diff --git a/src/dusk/OSThread.cpp b/src/dusk/OSThread.cpp index c88126bd52..7b97026e13 100644 --- a/src/dusk/OSThread.cpp +++ b/src/dusk/OSThread.cpp @@ -17,6 +17,16 @@ #include #include "JSystem/JKernel/JKRHeap.h" +#include "common/TracySystem.hpp" +#include "dusk/main.h" +#include "dusk/os.h" + +#if _WIN32 +#define WIN32_LEAN_AND_MEAN 1 +#include +#elif __APPLE__ +#include +#endif // ============================================================================ // Side-table: native thread data per OSThread @@ -30,6 +40,13 @@ struct PCThreadData { void* param; bool started = false; bool suspended = false; + + ~PCThreadData() { + if (dusk::IsShuttingDown && nativeThread.joinable()) { + // Don't care about threads if we're shutting down. + nativeThread.detach(); + } + } }; // Lazy-initialized to avoid DLL static init crashes (used before DllMain completes) @@ -42,6 +59,16 @@ static std::unordered_map>& GetThreadDa return map; } +static PCThreadData* GetThreadData(OSThread* thread) { + std::lock_guard mapLock(GetThreadDataMutex()); + auto it = GetThreadDataMap().find(thread); + if (it != GetThreadDataMap().end()) { + return it->second.get(); + } + + return nullptr; +} + // Side-table for OSThreadQueue -> condition_variable (for OSSleepThread/OSWakeupThread) static std::mutex& GetQueueCvMutex() { static std::mutex mtx; @@ -75,9 +102,7 @@ static thread_local OSThread* tls_currentThread = nullptr; static OSThread sDefaultThread; static u8 sDefaultStack[64 * 1024]; -static u32 sDefaultStackEnd = OS_THREAD_STACK_MAGIC; - -OSThreadQueue __OSActiveThreadQueue; +static u8 sDefaultStackEnd = OS_THREAD_STACK_MAGIC; // Global interrupt mutex (coarse-grained lock replacing interrupt disable) // Lazy-initialized to avoid DLL static init crashes @@ -100,36 +125,6 @@ static OSSwitchThreadCallback sSwitchThreadCallback = nullptr; // Internal helpers // ============================================================================ -// Linked list macros for the active thread queue -static void EnqueueActive(OSThread* thread) { - OSThread* prev = __OSActiveThreadQueue.tail; - if (prev == nullptr) { - __OSActiveThreadQueue.head = thread; - } else { - prev->linkActive.next = thread; - } - thread->linkActive.prev = prev; - thread->linkActive.next = nullptr; - __OSActiveThreadQueue.tail = thread; -} - -static void DequeueActive(OSThread* thread) { - OSThread* next = thread->linkActive.next; - OSThread* prev = thread->linkActive.prev; - if (next == nullptr) { - __OSActiveThreadQueue.tail = prev; - } else { - next->linkActive.prev = prev; - } - if (prev == nullptr) { - __OSActiveThreadQueue.head = next; - } else { - prev->linkActive.next = next; - } - thread->linkActive.next = nullptr; - thread->linkActive.prev = nullptr; -} - // Thread entry wrapper - runs on the new std::thread static void ThreadEntryWrapper(OSThread* thread, PCThreadData* data) { // Set thread-local pointer @@ -187,8 +182,6 @@ void __OSThreadInit(void) { tls_currentThread = &sDefaultThread; // Active queue - OSInitThreadQueue(&__OSActiveThreadQueue); - EnqueueActive(&sDefaultThread); sActiveThreadCount = 1; OSReport("[PC-OSThread] Thread system initialized (multi-threaded mode)\n"); @@ -245,7 +238,7 @@ int OSCreateThread(OSThread* thread, void* (*func)(void*), void* param, // Stack (stack points to TOP on GameCube) thread->stackBase = (u8*)stack; - thread->stackEnd = (u32*)((uintptr_t)stack - stackSize); + thread->stackEnd = (u8*)((uintptr_t)stack - stackSize); *thread->stackEnd = OS_THREAD_STACK_MAGIC; OSClearContext(&thread->context); @@ -265,7 +258,6 @@ int OSCreateThread(OSThread* thread, void* (*func)(void*), void* param, } // Add to active queue - EnqueueActive(thread); sActiveThreadCount++; OSReport("[PC-OSThread] Created thread %p (priority=%d, stackSize=%u)\n", @@ -345,16 +337,7 @@ s32 OSResumeThread(OSThread* thread) { // Only wake up if suspend count drops to 0 if (thread->suspend == 0) { - PCThreadData* data = nullptr; - - // Lock the global map to safely retrieve our thread data pointer - { - std::lock_guard mapLock(GetThreadDataMutex()); - auto it = GetThreadDataMap().find(thread); - if (it != GetThreadDataMap().end()) { - data = it->second.get(); - } - } + PCThreadData* data = GetThreadData(thread); if (data) { // Lock the specific thread mutex to safely modify state and notify @@ -369,7 +352,6 @@ s32 OSResumeThread(OSThread* thread) { threadLock.unlock(); data->nativeThread = std::thread(ThreadEntryWrapper, thread, data); - data->nativeThread.detach(); OSReport("[PC-OSThread] Started thread %p\n", thread); } else { // Resume from suspension: signal the condition variable @@ -392,16 +374,7 @@ s32 OSSuspendThread(OSThread* thread) { // If transitioning from running (0) to suspended (1) if (prevSuspend == 0) { - PCThreadData* data = nullptr; - - // Lock the global map to find our thread data - { - std::lock_guard mapLock(GetThreadDataMutex()); - auto it = GetThreadDataMap().find(thread); - if (it != GetThreadDataMap().end()) { - data = it->second.get(); - } - } + PCThreadData* data = GetThreadData(thread); if (data && data->started) { std::unique_lock threadLock(data->mtx); @@ -489,7 +462,6 @@ void OSExitThread(void* val) { currentThread->val = val; if (currentThread->attr & OS_THREAD_ATTR_DETACH) { - DequeueActive(currentThread); currentThread->state = 0; } else { currentThread->state = OS_THREAD_STATE_MORIBUND; @@ -501,10 +473,10 @@ void OSExitThread(void* val) { } void OSCancelThread(OSThread* thread) { + CRASH("OSCancelThread not implemented"); if (!thread) return; if (thread->attr & OS_THREAD_ATTR_DETACH) { - DequeueActive(thread); thread->state = 0; } else { thread->state = OS_THREAD_STATE_MORIBUND; @@ -515,30 +487,27 @@ void OSCancelThread(OSThread* thread) { } void OSDetachThread(OSThread* thread) { + CRASH("OSDetachThread not implemented"); if (!thread) return; thread->attr |= OS_THREAD_ATTR_DETACH; if (thread->state == OS_THREAD_STATE_MORIBUND) { - DequeueActive(thread); thread->state = 0; } OSWakeupThread(&thread->queueJoin); } -int OSJoinThread(OSThread* thread, void* val) { +BOOL OSJoinThread(OSThread* thread, void** val) { if (!thread) return 0; - if (!(thread->attr & OS_THREAD_ATTR_DETACH) && - thread->state != OS_THREAD_STATE_MORIBUND && - thread->queueJoin.head == nullptr) { - OSSleepThread(&thread->queueJoin); + if (!(thread->attr & OS_THREAD_ATTR_DETACH)) { + GetThreadData(thread)->nativeThread.join(); } if (thread->state == OS_THREAD_STATE_MORIBUND) { if (val) { *(s32*)val = (s32)(intptr_t)thread->val; } - DequeueActive(thread); thread->state = 0; return 1; } @@ -695,6 +664,36 @@ OSInterruptMask __OSUnmaskInterrupts(OSInterruptMask mask) { return 0; } +void OSSetCurrentThreadName(const char* name) { + // "Why is this current thread only?", you might ask? + // Because macOS requires that. For some reason. + +#if TRACY_ENABLE + tracy::SetThreadName(name); +#else +#if _WIN32 + wchar_t buffer[256]; + const auto converted = MultiByteToWideChar( + CP_UTF8, + 0, + name, + -1, + buffer, + sizeof(buffer)/sizeof(wchar_t)); + if (converted == 0) { + CRASH("OSSetThreadName: MultiByteToWideChar failed"); + } + + const auto result = SetThreadDescription(GetCurrentThread(), buffer); + if (!SUCCEEDED(result)) { + CRASH("OSSetThreadName: SetThreadDescription failed"); + } +#elif __APPLE__ + pthread_setname_np(name); +#endif +#endif +} + #ifdef __cplusplus } #endif diff --git a/src/dusk/audio/Adpcm.cpp b/src/dusk/audio/Adpcm.cpp new file mode 100644 index 0000000000..67b9ac9fd3 --- /dev/null +++ b/src/dusk/audio/Adpcm.cpp @@ -0,0 +1,61 @@ +#include "Adpcm.hpp" + +#include +#include + +#include "JSystem/JAudio2/JASAramStream.h" + +// https://github.com/magcius/vgmtrans/blob/8e34ddc2fb43948dc1e1a8759c739a0c1c7b62d7/src/main/formats/JaiSeqScanner.cpp#L489-L531 +// https://github.com/XAYRGA/JaiSeqX/blob/f29c024ec3663503f506aa02bcd503ada6e7d8aa/JaiSeqXLJA/DSP/JAIDSPADPCM4.cs#L86-L87 + +static constexpr u16 Coefficient0[] = { + 0,0x0800,0,0x0400, + 0x1000,0x0e00,0x0c00,0x1200, + 0x1068,0x12c0,0x1400,0x0800, + 0x0400,0xfc00,0xfc00,0xf800 +}; + +static constexpr u16 Coefficient1[] = { + 0,0,0x0800,0x0400,0xf800, + 0xfa00,0xfc00,0xf600,0xf738, + 0xf704,0xf400,0xf800,0xfc00, + 0x0400,0,0, +}; + +constexpr int AdpcmFrameSize = 9; + +static s16 Clamp16(s32 value) { + if (value > 0x7FFF) return 0x7FFF; + if (value < -0x8000) return -0x8000; + return value; +} + +void dusk::audio::Adpcm4ToPcm16(const u8* adpcm, size_t adpcmLength, s16* pcm, size_t pcmLength, s16& hist2, s16& hist1) { + assert (adpcmLength % AdpcmFrameSize == 0 && "ADPCM must be divisible by frame size"); + + auto endPtr = pcm + pcmLength; + + for (int i = 0; i < adpcmLength; i += AdpcmFrameSize) { + u8 header = adpcm[i]; + + s32 scale = 1 << (header >> 4); + u8 coefIndex = header & 0xF; + + s16 coef0 = (s16)Coefficient0[coefIndex]; + s16 coef1 = (s16)Coefficient1[coefIndex]; + + for (int sampleIdx = 0; sampleIdx < 16; sampleIdx++) { + u8 adpcmValue = adpcm[i + 1 + sampleIdx / 2]; + u8 unsignedNibble = sampleIdx % 2 == 0 ? adpcmValue >> 4 : adpcmValue & 0xF; + s8 signedNibble = ((s8)(unsignedNibble << 4)) >> 4; + s16 sample = Clamp16((((signedNibble * scale) << 11) + (coef0 * hist1 + coef1 * hist2)) >> 11); + + hist2 = hist1; + hist1 = sample; + + *pcm++ = sample; + if (endPtr == pcm) + return; + } + } +} diff --git a/src/dusk/audio/Adpcm.hpp b/src/dusk/audio/Adpcm.hpp new file mode 100644 index 0000000000..e893d54791 --- /dev/null +++ b/src/dusk/audio/Adpcm.hpp @@ -0,0 +1,14 @@ +#ifndef DUSK_ADPCM_HPP +#define DUSK_ADPCM_HPP + +#include + +namespace dusk::audio { + constexpr u32 Adpcm4FrameSize = 9; + constexpr u32 AdpcmSampleCount = 16; + constexpr u32 Adpcm2FrameSize = 5; + + void Adpcm4ToPcm16(const u8* adpcm, size_t adpcmLength, s16* pcm, size_t pcmLength, s16& hist1, s16& hist0); +} + +#endif // DUSK_ADPCM_HPP diff --git a/src/dusk/audio/DspStub.cpp b/src/dusk/audio/DspStub.cpp new file mode 100644 index 0000000000..c2dec809f2 --- /dev/null +++ b/src/dusk/audio/DspStub.cpp @@ -0,0 +1,35 @@ +#include "JSystem/JAudio2/dspproc.h" +#include "JSystem/JAudio2/osdsp_task.h" +#include "JSystem/JAudio2/dsptask.h" +#include "global.h" +#include "os.h" + +void DSPReleaseHalt2(u32) { + CRASH("We do not directly emulate the DSP"); +} +void DsetupTable(u32, u32, u32, u32, u32) { + // Nada. +} +void DsetMixerLevel(f32) { + // Nada for now, but maybe we should care about this? +} +void DsyncFrame2ch(u32, u32, u32) { + CRASH("We do not directly emulate the DSP"); +} +void DsyncFrame4ch(u32, u32, u32, u32, u32) { + CRASH("We do not directly emulate the DSP"); +} + +void DspBoot(void (*)(void*)) { + CRASH("We do not directly emulate the DSP"); +} +void DspFinishWork(u16) { + CRASH("We do not directly emulate the DSP"); +} +int DSPSendCommands2(u32*, u32, void (*)(u16)) { + CRASH("We do not directly emulate the DSP"); +} + +void DsyncFrame2(u32, u32, u32) { + CRASH("We do not directly emulate the DSP"); +} diff --git a/src/dusk/audio/DuskAudioSystem.cpp b/src/dusk/audio/DuskAudioSystem.cpp new file mode 100644 index 0000000000..c818e46738 --- /dev/null +++ b/src/dusk/audio/DuskAudioSystem.cpp @@ -0,0 +1,162 @@ +#include "dusk/audio/DuskAudioSystem.h" + +#include +#include +#include +#include + +#include "JSystem/JAudio2/JASAiCtrl.h" +#include "JSystem/JAudio2/JASChannel.h" +#include "JSystem/JAudio2/JASCriticalSection.h" +#include "JSystem/JAudio2/JASDSPChannel.h" +#include "JSystem/JAudio2/JASHeapCtrl.h" + +#include "DuskDsp.hpp" +#include "JSystem/JAudio2/JASAudioThread.h" +#include "JSystem/JAudio2/JASDriverIF.h" +#include "tracy/Tracy.hpp" + +using namespace dusk::audio; + +static OutputSubframe OutBuffer; +static std::array OutInterleaveBuffer; + +static SDL_AudioStream* PlaybackStream; + +/** + * SDL audiostream callback to trigger rendering of new audio data. + */ +static void SDLCALL GetNewAudio( + void*, + SDL_AudioStream*, + int needed, + int); + +/** + * Render an entire new frame of audio and output it to SDL3. + * Note: "audio frames" are unrelated to video frames. + * @return Amount of audio samples rendered. + */ +static int RenderNewAudioFrame(); + +/** + * Render an audio subframe and output it to SDL3. + */ +static void RenderAudioSubframe(); + +static void InitSDL3Output() { + SDL_Init(SDL_INIT_AUDIO); + + constexpr SDL_AudioSpec spec = { + SDL_AUDIO_F32, + 2, + SampleRate, + }; + PlaybackStream = SDL_OpenAudioDeviceStream( + SDL_AUDIO_DEVICE_DEFAULT_PLAYBACK, + &spec, + &GetNewAudio, + nullptr); +} + +void dusk::audio::Initialize() { + InitSDL3Output(); + DspInit(); + + JASDsp::initBuffer(); + JASDSPChannel::initAll(); + + JASPoolAllocObject_MultiThreaded::newMemPool(0x48); + + SDL_ResumeAudioStreamDevice(PlaybackStream); +} + +void dusk::audio::SetMasterVolume(const f32 value) { + JASCriticalSection section; + + MasterVolume = value; +} + +void dusk::audio::SetEnableReverb(const bool value) { + JASCriticalSection section; + + EnableReverb = value; +} + +#ifdef TRACY_ENABLE +static auto FrameName = "GetNewAudio"; +#endif + +void SDLCALL GetNewAudio( + void*, + SDL_AudioStream*, + int needed, + int) { + FrameMarkStart(FrameName); + while (needed > 0) { + const int rendered = RenderNewAudioFrame(); + needed -= rendered; + } + FrameMarkEnd(FrameName); +} + +int RenderNewAudioFrame() { + ZoneScoped; + JASCriticalSection section; + const u32 countSubframes = JASDriver::getSubFrames(); + + JASAudioThread::setDSPSyncCount(countSubframes); + + for (u32 i = 0; i < countSubframes; i++) { + RenderAudioSubframe(); + + JASAudioThread::snIntCount -= 1; + } + + return static_cast(countSubframes) * DSP_SUBFRAME_SIZE; +} + +static void InterleaveOutputData(const OutputSubframe& data, std::span target) { + assert(target.size() >= data.channels[0].size() * OutputSubframe::NUM_CHANNELS); + + size_t outPos = 0; + for (size_t inPos = 0; inPos < data.channels[0].size(); inPos++) { + for (size_t channelIdx = 0; channelIdx < OutputSubframe::NUM_CHANNELS; channelIdx++) { + target[outPos++] = data.channels[channelIdx][inPos]; + } + } +} + +void RenderAudioSubframe() { + ZoneScoped; + OutBuffer = {}; + + JASDriver::updateDSP(); + DspRender(OutBuffer); + + InterleaveOutputData(OutBuffer, OutInterleaveBuffer); + + if (JASDriver::extMixCallback != nullptr && JASDriver::sMixMode == MIX_MODE_INTERLEAVE) { + static_assert(OutputSubframe::NUM_CHANNELS == 2); // This code only works with Stereo so far. + // NOTE: In the real game, this gets called on the entire audio frame, rather than the subframe. + // That's probably more efficient, but I didn't wanna change the code to calculate the + // entire audio buffers at once. + // This is only used for the movie player, and it seems to work fine with the smaller calls. + const auto mixData = JASDriver::extMixCallback(DSP_SUBFRAME_SIZE); + if (mixData) { + for (int i = 0; i < OutInterleaveBuffer.size(); i++) { + OutInterleaveBuffer[i] += static_cast(mixData[i]) / static_cast(0x7FFF); + } + } + } + + SDL_PutAudioStreamData(PlaybackStream, &OutInterleaveBuffer, sizeof(OutInterleaveBuffer)); +} + +u32 dusk::audio::GetResetCount(int channelIdx) { + return ChannelAux[channelIdx].resetCount; +} + +f32 dusk::audio::VolumeFromU16(u16 value) { + return static_cast(value) / static_cast(JASDriver::getChannelLevel_dsp()); +} diff --git a/src/dusk/audio/DuskDsp.cpp b/src/dusk/audio/DuskDsp.cpp new file mode 100644 index 0000000000..bcad272a47 --- /dev/null +++ b/src/dusk/audio/DuskDsp.cpp @@ -0,0 +1,607 @@ +#include +#include + +#include "DuskDsp.hpp" + +#include +#include +#include +#include + +#include "Adpcm.hpp" +#include "freeverb/revmodel.hpp" +#include "JSystem/JAudio2/JASDriverIF.h" +#include "dusk/audio/DuskAudioSystem.h" +#include "dusk/endian.h" +#include "global.h" +#include "tracy/Tracy.hpp" + +using namespace dusk::audio; + +ChannelAuxData dusk::audio::ChannelAux[DSP_CHANNELS] = {}; + +static revmodel SharedReverb; +static bool ReverbHasTail = false; + +static bool sDumpWasActive = false; +static FILE* sChannelDumpFiles[DSP_CHANNELS] = {}; + +static void OpenChannelDumpFiles() { + char name[32]; + for (int i = 0; i < DSP_CHANNELS; i++) { + snprintf(name, sizeof(name), "channel_%02d.raw", i); + sChannelDumpFiles[i] = fopen(name, "wb"); + } +} + +static void CloseChannelDumpFiles() { + for (int i = 0; i < DSP_CHANNELS; i++) { + if (sChannelDumpFiles[i]) { + fclose(sChannelDumpFiles[i]); + sChannelDumpFiles[i] = nullptr; + } + } +} + +f32 dusk::audio::MasterVolume = 1.0f; +f32 dusk::audio::PrevMasterVolume = 1.0f; +bool dusk::audio::EnableReverb = true; +bool dusk::audio::DumpAudio = false; + +/** + * Validate that a DSP channel's format is actually something we know how to play. + */ +static bool ValidateChannelWaveFormat(const JASDsp::TChannel& channel) { + if (channel.mSamplesPerBlock == AdpcmSampleCount && channel.mBytesPerBlock == Adpcm4FrameSize) + return true; + if (channel.mSamplesPerBlock == 1 && channel.mBytesPerBlock == 16) + return true; + /* + if (channel.mSamplesPerBlock == AdpcmSampleCount && channel.mBytesPerBlock == Adpcm2FrameSize) + return true; + if (channel.mSamplesPerBlock == 1 && channel.mBytesPerBlock == 8) + return true; + */ + return false; +} + +/** + * Validate that a DSP channel is actually something we know how to play. + */ +static void ValidateChannel(const JASDsp::TChannel& channel) { + if (!ValidateChannelWaveFormat(channel)) { + CRASH( + "Unable to handle channel format: %02x, %02x\n", + channel.mSamplesPerBlock, + channel.mBytesPerBlock); + } +} + +static u32 ConvertSamplesToDataLength(const JASDsp::TChannel& channel, u32 samples) { + if (samples % channel.mSamplesPerBlock != 0) { + // Ensure we round up. + samples += channel.mSamplesPerBlock; + //CRASH("Indivisible sample count: %d\n", samples); + } + + return (samples / channel.mSamplesPerBlock) * BlockBytes(channel); +} + +/** + * Render the audio data contributed by a single DSP channel. Reads & decodes new input samples. + */ +static void RenderChannel( + JASDsp::TChannel& channel, + ChannelAuxData& channelAux, + OutputSubframe& subframe); + +/** + * Converts a pitch value on a DSP channel to a sample rate. + */ +constexpr static int PitchToSampleRate(u16 value) { + return static_cast(static_cast(SampleRate) * value / 4096); +} + +/** + * Reset state for a DSP channel between independent playbacks. + */ +static void ResetChannel(JASDsp::TChannel& channel, ChannelAuxData& aux) { + aux.resetCount += 1; + + channel.mSamplesLeft = channel.mEndSample - channel.mSamplePosition; + + aux.hist0 = 0; + aux.hist1 = 0; + + aux.decodeBufCount = 0; + aux.resamplePos = 0.0; + aux.resamplePrev = 0; + + aux.prev_lp_out = 0.0f; + aux.prev_lp_in = 0.0f; + + aux.biq_in1 = 0.0f; + aux.biq_in2 = 0.0f; + aux.biq_out1 = 0.0f; + aux.biq_out2 = 0.0f; + + for (auto& volume : aux.prevVolume) { + volume = NAN; + } + + channel.mResetFlag = false; +} + +/** + * Mix subframe data from src into dst. + */ +static void MixSubframe(DspSubframe& dst, const DspSubframe& src) { + for (int i = 0; i < dst.size(); i++) { + dst[i] += src[i]; + } +} + +void dusk::audio::DspRender(OutputSubframe& subframe) { + ZoneScoped; + if (DumpAudio != sDumpWasActive) { + sDumpWasActive = DumpAudio; + if (DumpAudio) { + OpenChannelDumpFiles(); + } else { + CloseChannelDumpFiles(); + } + } + + std::span channels(JASDsp::CH_BUF, DSP_CHANNELS); + + DspSubframe reverbInputL = {}; + DspSubframe reverbInputR = {}; + bool anyReverbInput = false; + + for (int i = 0; i < channels.size(); i++) { + auto& channel = channels[i]; + auto& channelAux = ChannelAux[i]; + + if (!channel.mIsActive) { + continue; + } + else if (channel.mPauseFlag) { + // Not really sure what the practical difference between pause and + // deactivation is. Either avoids clearing state or allows the DSP to avoid popping? + continue; + } + else if (channel.mForcedStop) { + channel.mIsFinished = true; + continue; + } + else if (channel.mWaveAramAddress == 0) { + // I think these are oscillator channels? Not backed by audio. + // No idea how to implement these yet, so skip them. + channel.mIsFinished = true; + continue; + } + + ValidateChannel(channel); + + OutputSubframe channelSubframe = {}; + RenderChannel(channel, channelAux, channelSubframe); + + if (EnableReverb) { + // scale the input to the reverb rather than using wet/dry on the output. + // this way the reverb's internal buffers accumulate energy proportional to mAutoMixerFxMix, + // so any tail always decays at the correct level regardless of mAutoMixerFxMix changes + // prevents transients when the next sound starts playing with a different reverb level + // 600.0f was pulled out of my ass and just sounds good enough for console + f32 inputGain = (channel.mAutoMixerFxMix >> 8) / 600.0f; + if (inputGain > 0) { + anyReverbInput = true; + for (int j = 0; j < DSP_SUBFRAME_SIZE; j++) { + reverbInputL[j] += channelSubframe.channels[0][j] * inputGain; + reverbInputR[j] += channelSubframe.channels[1][j] * inputGain; + } + } + } + + if (DumpAudio && sChannelDumpFiles[i]) { + f32 interleaved[DSP_SUBFRAME_SIZE * 2]; + for (int j = 0; j < DSP_SUBFRAME_SIZE; j++) { + interleaved[j * 2 + 0] = channelSubframe.channels[0][j]; + interleaved[j * 2 + 1] = channelSubframe.channels[1][j]; + } + fwrite(interleaved, sizeof(f32), DSP_SUBFRAME_SIZE * 2, sChannelDumpFiles[i]); + } + + for (int o = 0; o < subframe.channels.size(); o++) { + MixSubframe(subframe.channels[o], channelSubframe.channels[o]); + } + } + + if (EnableReverb && (anyReverbInput || ReverbHasTail)) { + // Equivalent to -80 dBFS: rms = 1e-4, rms^2 = 1e-8, sumSq = 2 * N * 1e-8 + constexpr f32 REVERB_ENERGY_EPSILON = 2.0f * DSP_SUBFRAME_SIZE * 1e-8f; + f32 wetEnergy = SharedReverb.processmix( + reverbInputL.data(), reverbInputR.data(), + subframe.channels[0].data(), subframe.channels[1].data(), + DSP_SUBFRAME_SIZE, 1, 1.0f + ); + ReverbHasTail = wetEnergy >= REVERB_ENERGY_EPSILON; + } + + for (auto& channel : subframe.channels) { + ApplyVolume(channel, channel, PrevMasterVolume, MasterVolume); + } + PrevMasterVolume = MasterVolume; +} + +/** + * Actually decode samples from memory for the given audio channel. + */ +static void ReadSampleData( + const JASDsp::TChannel& channel, + ChannelAuxData& aux, + const u8* data, + size_t dataLength, + s16* pcm, + size_t pcmLength) { + if (channel.mSamplesPerBlock == 1) { + if (channel.mBytesPerBlock == 0x10) { + // PCM16 + assert(reinterpret_cast(data) % 2 == 0 && "PCM data must be aligned"); + assert(dataLength % 2 == 0 && "Data length must be multiple of 2"); + assert(dataLength * 2 >= pcmLength && "Input too small!"); + + auto srcPcm = reinterpret_cast(data); + for (size_t i = 0; i < pcmLength; i++) { + pcm[i] = srcPcm[i]; + } + } else { + CRASH("Unsupported format: PCM8"); + } + } else { + if (channel.mBytesPerBlock == 9) { + Adpcm4ToPcm16(data, dataLength, pcm, pcmLength, aux.hist1, aux.hist0); + } else { + CRASH("Unsupported format: ADPCM2"); + } + } +} + +/** + * Read a single *contiguous* chunk of sample data from a channel into outBuf + * + * @returns Amount of samples written to outBuf. May be less than desiredSamples + */ +static int ReadChannelSamplesChunk( + JASDsp::TChannel& channel, + ChannelAuxData& aux, + int desiredSamples, + s16* outBuf, + int outBufSize) { + + assert(desiredSamples >= 0); + + auto aramBase = static_cast(ARGetStorageAddress()) + channel.mWaveAramAddress; + + // Streaming logic directly modifies mSamplesLeft. + // So we use that as our tracking of where we are. + auto curSamplePosition = channel.mEndSample - channel.mSamplesLeft; + + u32 skipSamples = curSamplePosition % channel.mSamplesPerBlock; + if (skipSamples != 0) { + // We need to start reading in the middle of a block. This can happen thanks to loops. + // So we move back to the start of the block and keep track that those samples should + // *not* be emitted. + desiredSamples += static_cast(skipSamples); + curSamplePosition -= skipSamples; + + channel.mSamplesLeft += skipSamples; + channel.mSamplePosition -= skipSamples; + } + + // Pad desiredSamples so that we always leave the channel block-aligned. + desiredSamples = ALIGN_NEXT(desiredSamples, channel.mSamplesPerBlock); + + assert(curSamplePosition % channel.mSamplesPerBlock == 0); + auto dataPosition = ConvertSamplesToDataLength(channel, curSamplePosition); + + u32 renderSamples = std::min(channel.mSamplesLeft, static_cast(desiredSamples)); + + int renderSize = static_cast(sizeof(s16) * renderSamples); + auto renderData = static_cast(alloca(renderSize)); + memset(renderData, 0, renderSize); + + ReadSampleData( + channel, + aux, + aramBase + dataPosition, + ConvertSamplesToDataLength(channel, renderSamples), + renderData, + renderSamples); + + channel.mSamplesLeft -= renderSamples; + channel.mSamplePosition += renderSamples; + + int outputCount = static_cast(renderSamples - skipSamples); + + // this should never be hit with the limits on pitch shift (i think) but just in case!! + outputCount = std::min(outputCount, outBufSize); + if (outputCount > 0) { + memcpy(outBuf, renderData + skipSamples, outputCount * sizeof(s16)); + } + + assert(curSamplePosition % channel.mSamplesPerBlock == 0 || channel.mSamplesLeft == 0); + + return outputCount; +} + +/** + * Fill decodeBuf with at least `needed` samples, fewer may be written if the channel has no loop and its data ends + */ +static void FillDecodeBuf(JASDsp::TChannel& channel, ChannelAuxData& aux, int needed) { + while (aux.decodeBufCount < needed) { + if (channel.mSamplesLeft == 0) { + if (!channel.mLoopFlag) { + // we aren't a looping channel and there's no samples left, we out of this fuckin loop + break; + } else { + // we are looping, handle loop logic + channel.mSamplesLeft = channel.mEndSample - channel.mLoopStartSample; + channel.mSamplePosition = channel.mLoopStartSample; + aux.hist1 = channel.mpPenult; + aux.hist0 = channel.mpLast; + } + } + + int remainingDecodeSpace = ChannelAuxData::DECODE_BUF_SIZE - aux.decodeBufCount; + if (remainingDecodeSpace == 0) { + break; + } + + aux.decodeBufCount += ReadChannelSamplesChunk( + channel, aux, std::min(remainingDecodeSpace, needed - aux.decodeBufCount), + aux.decodeBuf + aux.decodeBufCount, remainingDecodeSpace + ); + } + + channel.mAramStreamPosition = channel.mWaveAramAddress + ConvertSamplesToDataLength(channel, channel.mSamplePosition); +} + +/** + * Get the expected BusConnect value needed to define the given output channel in a DSP channel. + */ +constexpr u16 GetBusConnect(const OutputChannel channel) { + switch (channel) { + // TODO: This is a guess for now. + case OutputChannel::LEFT: + return 0x0D00; + case OutputChannel::RIGHT: + return 0x0D60; + default: + CRASH("Invalid output channel!"); + } +} + +/** + * For a DSP channel the JASDsp::OutputChannelConfig value targeting the given output channel. + * Returns null if the DSP channel does not output to this output channel. + */ +static const JASDsp::OutputChannelConfig* GetOutputConfig( + const JASDsp::TChannel& sourceChannel, + OutputChannel channel) { + + auto busConnect = GetBusConnect(channel); + for (const auto& mOutputChannel : sourceChannel.mOutputChannels) { + auto config = &mOutputChannel; + if (config->mBusConnect == busConnect) { + return config; + } + } + + return nullptr; +} + +struct VolumeValue { + f32 Target; + f32 Init; +}; + +/** + * Get the volume that the given DSP channel should render to the given output channel at. + */ +static VolumeValue GetVolumeForOutputChannel( + const JASDsp::TChannel& sourceChannel, + OutputChannel outputChannel) { + + u16 volume; + u16 initVolume; + f32 panValue = 1; + if (sourceChannel.mAutoMixerBeenSet) { + volume = sourceChannel.mAutoMixerVolume; + initVolume = sourceChannel.mAutoMixerInitVolume; + + auto autoMixerPan = static_cast(sourceChannel.mAutoMixerPanDolby >> 8) / 127; + + switch (outputChannel) { + case OutputChannel::LEFT: + panValue = 1 - autoMixerPan; + break; + case OutputChannel::RIGHT: + panValue = autoMixerPan; + break; + default: + CRASH("Unhandled output channel: OutputChannel"); + } + + } else { + auto config = GetOutputConfig(sourceChannel, outputChannel); + if (config == nullptr) { + return {0, 0}; + } + + volume = config->mTargetVolume; + initVolume = config->mCurrentVolume; + } + + // TODO: interpolate to avoid popping. + f32 targetRatio = VolumeFromU16(volume); + targetRatio *= panValue; + + f32 initRatio = VolumeFromU16(initVolume); + initRatio *= panValue; + + return {targetRatio, initRatio}; +} + +/** + * Given decoded & resampled input samples, render a DSP channel to a given output channel. + */ +static void RenderOutputChannel( + const JASDsp::TChannel& sourceChannel, + ChannelAuxData& aux, + OutputChannel outputChannel, + const std::span inputSamples, + OutputSubframe& fullOutputSubframe) { + + auto& outputSubframe = fullOutputSubframe[outputChannel]; + assert(inputSamples.size() <= outputSubframe.size()); + + auto volume = GetVolumeForOutputChannel(sourceChannel, outputChannel); + + f32 targetVolume = volume.Target; + auto& prevVolume = aux.PrevVolume(outputChannel); + if (std::isnan(prevVolume)) { + // Initialize previous volume to new volume on first render. + prevVolume = volume.Init; + } + + if (prevVolume == 0 && targetVolume == 0) { + return; + } + + ApplyVolume(outputSubframe, inputSamples, prevVolume, targetVolume); + prevVolume = targetVolume; +} + +/** + * Fetch, decode, resample, output + */ +static void RenderChannel( + JASDsp::TChannel& channel, + ChannelAuxData& channelAux, + OutputSubframe& subframe) { + + if (channel.mResetFlag) { + ResetChannel(channel, channelAux); + } + + // how many input samples we step per output sample, aka the resampling ratio + f32 step = (f32)PitchToSampleRate(channel.mPitch) / SampleRate; + + // how many input samples to resample to DSP_SUBFRAME_SIZE output samples + int needed = static_cast(channelAux.resamplePos + DSP_SUBFRAME_SIZE * step) + 2; + + FillDecodeBuf(channel, channelAux, needed); + + // source ran dry, channel is finished + if(channelAux.decodeBufCount < needed) { + channel.mIsFinished = true; + } + + DspSubframe audioLoadBuffer = {}; + f32 pos = channelAux.resamplePos; + s16 prev = channelAux.resamplePrev; + s16 next = channelAux.decodeBufCount > 0 ? channelAux.decodeBuf[0] : prev; + int srcIdx = 0; + + // linear resampling and f32 conversion + for (int i = 0; i < DSP_SUBFRAME_SIZE; i++) { + audioLoadBuffer[i] = (prev + pos * (next - prev)) / 32768.0f; + pos += step; + while (pos >= 1.0f) { + pos -= 1.0f; + prev = next; + srcIdx++; + next = srcIdx < channelAux.decodeBufCount ? channelAux.decodeBuf[srcIdx] : prev; + } + } + + // save resampler state for the next subframe, prevents popping on pitch change + channelAux.resamplePos = pos; + channelAux.resamplePrev = prev; + + // IIR FILTER + + // IIR part 1, low-pass: out[n] = (in[n] - in[n-1]) * (coeff/128) + out[n-1] + if (s16 coeff = channel.iir_filter_params[4]; coeff != 0) { + for (f32& sample : audioLoadBuffer) { + f32 out = std::clamp( + (sample - channelAux.prev_lp_in) * ((f32)coeff / 128.0f) + channelAux.prev_lp_out, -1.0f, 1.0f + ); + + channelAux.prev_lp_in = sample; // in[n-1] = in[n] + sample = channelAux.prev_lp_out = out; // out[n-1] = out[n] + } + } + + // IIR part 2, biquad: out[n] = (b1*in[n-1] + b2*in[n-2] + a1*out[n-1] + a2*out[n-2]) / 32768 + if ((channel.mFilterMode & 0x20) != 0) { + for (f32& sample : audioLoadBuffer) { + f32 out = std::clamp(( + channel.iir_filter_params[0] * channelAux.biq_in1 + // b1 + channel.iir_filter_params[1] * channelAux.biq_in2 + // b2 + channel.iir_filter_params[2] * channelAux.biq_out1 + // a1 + channel.iir_filter_params[3] * channelAux.biq_out2 // a2 + ) / 32768.0f, -1.0f, 1.0f); + + // shift history, then store new input and output + channelAux.biq_in2 = channelAux.biq_in1; // in[n-2] = in[n-1] + channelAux.biq_in1 = sample; // in[n-1] = in[n] + channelAux.biq_out2 = channelAux.biq_out1; // out[n-2] = out[n-1] + sample = channelAux.biq_out1 = out; // out[n-1] = out[n] + } + } + + // move any remaining samples in the decode buf to the beginning + int remainingDecodeBuf = channelAux.decodeBufCount - srcIdx; + if (remainingDecodeBuf > 0) { + memmove(channelAux.decodeBuf, channelAux.decodeBuf + srcIdx, remainingDecodeBuf * sizeof(s16)); + } + + channelAux.decodeBufCount = std::max(0, remainingDecodeBuf); + + auto hasReadSamples = std::span(audioLoadBuffer).subspan(0, DSP_SUBFRAME_SIZE); + + static_assert(OutputSubframe::NUM_CHANNELS == 2, "Keep RenderChannel in sync!"); + + RenderOutputChannel(channel, channelAux, OutputChannel::LEFT, hasReadSamples, subframe); + RenderOutputChannel(channel, channelAux, OutputChannel::RIGHT, hasReadSamples, subframe); +} + +void dusk::audio::DspInit() { + SharedReverb.setwet(1.0f); + SharedReverb.setdry(0.0f); + SharedReverb.setroomsize(0.5f); + SharedReverb.setdamp(0.7f); + SharedReverb.setwidth(1.0f); + SharedReverb.setmode(0.0f); + SharedReverb.mute(); +} + +void dusk::audio::ApplyVolume( + std::span dst, + const std::span src, + const f32 startVolume, + const f32 endVolume) { + assert(dst.size() >= src.size()); + + if (startVolume == endVolume) { + for (int i = 0; i < (int)src.size(); i++) { + dst[i] = src[i] * startVolume; + } + } else { + const f32 step = (endVolume - startVolume) / static_cast(src.size()); + for (int i = 0; i < (int)src.size(); i++) { + dst[i] = src[i] * (startVolume + i * step); + } + } +} diff --git a/src/dusk/audio/DuskDsp.hpp b/src/dusk/audio/DuskDsp.hpp new file mode 100644 index 0000000000..3ca90d6311 --- /dev/null +++ b/src/dusk/audio/DuskDsp.hpp @@ -0,0 +1,133 @@ +#pragma once + +#include "JSystem/JAudio2/JASDSPInterface.h" + +#include +#include + +#include "SDL3/SDL_audio.h" +#include + +// ReSharper disable once CppUnusedIncludeDirective +#include "global.h" + +namespace dusk::audio { + constexpr int SampleRate = 32000; + + enum class OutputChannel : u8 { + LEFT, + RIGHT, + OutputChannel_MAX + }; + + /** + * Data stored by DSP implementation for each DSP channel. + */ + struct ChannelAuxData { + s16 hist1; + s16 hist0; + + // Used for debugging tools. + u32 resetCount; + + /** + * Previous volume values, per output channel. + * Used to avoid clicking when volumes change. + * Set to NaN after channel reset, indicating that initial volume value is previous. + */ + f32 prevVolume[static_cast(OutputChannel::OutputChannel_MAX)]; + + f32& PrevVolume(OutputChannel channel) { + assert(channel < OutputChannel::OutputChannel_MAX); + return prevVolume[static_cast(channel)]; + } + + // buffer for decoding before resampling, size is chosen based on how many input samples we would need to fetch for the highest possible pitch + // to fill one subframe of output samples after resampling + static constexpr int DECODE_BUF_SIZE = 2048; + s16 decodeBuf[DECODE_BUF_SIZE]; + int decodeBufCount; + + // basically stores our position between resamplePrev and decodeBuf[0] so we don't lose that fractional resampler position next subframe + f32 resamplePos; + // last consumed sample from decodeBuf + s16 resamplePrev; + + // low pass previous state + f32 prev_lp_out; // out[n-1] + f32 prev_lp_in; // in[n-1] + + // biquad state + f32 biq_in1; // in[n-1] + f32 biq_in2; // in[n-2] + f32 biq_out1; // out[n-1] + f32 biq_out2; // out[n-2] + }; + + extern ChannelAuxData ChannelAux[DSP_CHANNELS]; + + /** + * Data storage for a single subframe and output channel's worth of samples. + */ + using DspSubframe = std::array; + + /** + * Data storage for a single subframe's worth of samples, across all output channels. + */ + struct OutputSubframe { + static constexpr int NUM_CHANNELS = static_cast(OutputChannel::OutputChannel_MAX); + + std::array channels; + + DspSubframe& operator[](OutputChannel channel) { + assert(channel < OutputChannel::OutputChannel_MAX); + return channels[static_cast(channel)]; + } + }; + + /** + * Initialize the DSP system, creating data storage needed for channels and such. + */ + void DspInit(); + + /** + * Render a subframe of audio with the current DSP state. + */ + void DspRender(OutputSubframe& subframe); + + /** + * Get the amount of samples a single "block" of this channel's data has. + */ + constexpr u32 BlockSamples(const JASDsp::TChannel& channel) { + return channel.mSamplesPerBlock; + } + + /** + * Get the amount of bytes a single "block" of this channel's data has. + */ + constexpr u32 BlockBytes(const JASDsp::TChannel& channel) { + if (channel.mSamplesPerBlock == 1) { + if (channel.mBytesPerBlock == 16) { + return 2; + } + if (channel.mBytesPerBlock == 8) { + return 1; + } + + CRASH("Unknown format"); + } + + return channel.mBytesPerBlock; + } + + /** + * Apply a volume level to audio data. + * Interpolates across the two provided volume levels to avoid clicking. + */ + void ApplyVolume(std::span dst, std::span src, f32 startVolume, f32 endVolume); + + extern f32 MasterVolume; + extern f32 PrevMasterVolume; + extern bool EnableReverb; + extern bool DumpAudio; +} diff --git a/src/dusk/audio/JASCriticalSection.cpp b/src/dusk/audio/JASCriticalSection.cpp new file mode 100644 index 0000000000..9baf2d9bac --- /dev/null +++ b/src/dusk/audio/JASCriticalSection.cpp @@ -0,0 +1,15 @@ +#include "JSystem/JAudio2/JASCriticalSection.h" + +#include + +#include "tracy/Tracy.hpp" + +static TracyLockable(std::recursive_mutex, gAudioThreadMutex); + +JASCriticalSection::JASCriticalSection() { + gAudioThreadMutex.lock(); +} + +JASCriticalSection::~JASCriticalSection() { + gAudioThreadMutex.unlock(); +} diff --git a/src/dusk/config.cpp b/src/dusk/config.cpp new file mode 100644 index 0000000000..159706fac8 --- /dev/null +++ b/src/dusk/config.cpp @@ -0,0 +1,222 @@ +#include "dusk/config.hpp" +#include "fmt/format.h" +#include "nlohmann/json.hpp" +#include "absl/container/flat_hash_map.h" + +#include "aurora/lib/logging.hpp" +#include "dusk/io.hpp" + +#include +#include + +#include "dusk/dusk.h" + +using namespace dusk::config; + +constexpr auto ConfigFileName = "config.json"; + +using json = nlohmann::json; + +aurora::Module DuskConfigLog("dusk::config"); + +static absl::flat_hash_map RegisteredConfigVars; +static bool RegistrationDone; + +static std::string GetConfigJsonPath() { + return fmt::format("{}{}", configPath, ConfigFileName); +} + +ConfigVarBase::ConfigVarBase(const char* name, const ConfigImplBase* impl) : name(name), registered(false), layer(ConfigVarLayer::Default), impl(impl) { +} + +const char* ConfigVarBase::getName() const noexcept { + return name; +} + +const ConfigImplBase* ConfigVarBase::getImpl() const noexcept { + return impl; +} + +template +void ConfigImpl::loadFromJson(ConfigVar& cVar, const json& jsonValue) { + cVar.setValue(jsonValue.get(), false); +} + +template +nlohmann::json ConfigImpl::dumpToJson(const ConfigVar& cVar) { + return cVar.getValue(); +} + +template requires std::is_integral_v && std::is_signed_v +static void loadFromArgImpl(ConfigVar& cVar, const std::string_view stringValue) { + const std::string str(stringValue); + const auto result = std::stoll(str); + if (result >= std::numeric_limits::min() && result <= std::numeric_limits::max()) { + cVar.setOverrideValue(result); + } else { + throw std::out_of_range("Value is too large"); + } +} + +template requires std::is_integral_v && std::is_unsigned_v +static void loadFromArgImpl(ConfigVar& cVar, const std::string_view stringValue) { + const std::string str(stringValue); + const auto result = std::stoull(str); + if (result <= std::numeric_limits::max()) { + cVar.setOverrideValue(result); + } else { + throw std::out_of_range("Value is too large"); + } +} + +static void loadFromArgImpl(ConfigVar& cVar, const std::string_view stringValue) { + const std::string str(stringValue); + const auto result = std::stof(str); + cVar.setOverrideValue(result); +} + +static void loadFromArgImpl(ConfigVar& cVar, const std::string_view stringValue) { + const std::string str(stringValue); + const auto result = std::stod(str); + cVar.setOverrideValue(result); +} + +static void loadFromArgImpl(ConfigVar& cVar, const std::string_view stringValue) { + cVar.setOverrideValue(std::string(stringValue)); +} + +template +void ConfigImpl::loadFromArg(ConfigVar& cVar, const std::string_view stringValue) { + loadFromArgImpl(cVar, stringValue); +} + +template<> +void ConfigImpl::loadFromArg(ConfigVar& cVar, const std::string_view stringValue) { + if (stringValue == "1" || stringValue == "TRUE" || stringValue == "true" || stringValue == "True") { + cVar.setOverrideValue(true); + } else if (stringValue == "0" || stringValue == "FALSE" || stringValue == "false" || stringValue == "False") { + cVar.setOverrideValue(false); + } else { + throw InvalidConfigError("Value cannot be parsed as boolean"); + } +} + +// My IDE is convinced this namespace is necessary. It shouldn't be AFAICT? +namespace dusk::config { + template class ConfigImpl; + template class ConfigImpl; + template class ConfigImpl; + template class ConfigImpl; + template class ConfigImpl; + template class ConfigImpl; + template class ConfigImpl; + template class ConfigImpl; + template class ConfigImpl; + template class ConfigImpl; + template class ConfigImpl; + template class ConfigImpl; +} + +void dusk::config::Register(ConfigVarBase& configVar) { + const auto& name = configVar.getName(); + if (RegistrationDone) { + DuskConfigLog.fatal("Tried to register CVar {} after registrations closed!", name); + } + + if (RegisteredConfigVars.contains(name)) { + DuskConfigLog.fatal("Tried to register CVar {} twice!", name); + } + + RegisteredConfigVars[name] = &configVar; + configVar.markRegistered(); +} + +void ConfigVarBase::markRegistered() { + if (registered) + abort(); + + registered = true; +} + +void dusk::config::FinishRegistration() { + RegistrationDone = true; +} + +void dusk::config::LoadFromUserPreferences() { + const auto configJsonPath = GetConfigJsonPath(); + if (configJsonPath.empty()) { + return; + } + LoadFromFileName(configJsonPath.c_str()); +} + +static void LoadFromPath(const char* path) { + auto data = dusk::io::FileStream::ReadAllBytes(path); + + json j = json::parse(data); + if (!j.is_object()) { + DuskConfigLog.error("Config JSON is not an object!"); + return; + } + + for (const auto& el : j.items()) { + const auto& key = el.key(); + auto configVar = RegisteredConfigVars.find(key); + if (configVar == RegisteredConfigVars.end()) { + DuskConfigLog.error("Unknown key '{}' found in config!", key); + continue; + } + + try { + configVar->second->getImpl()->loadFromJson(*configVar->second, el.value()); + } catch (std::exception& e) { + DuskConfigLog.error("Failed to load key '{}' from config: {}", key, e.what()); + } + } +} + +void dusk::config::LoadFromFileName(const char* path) { + if (!RegistrationDone) { + DuskConfigLog.fatal("Registration not finished yet!"); + } + + DuskConfigLog.info("Loading config from '{}'", path); + + try { + LoadFromPath(path); + } catch (const std::system_error& e) { + if (e.code() == std::errc::no_such_file_or_directory) { + DuskConfigLog.info("Config file did not exist, staying with defaults"); + } else { + DuskConfigLog.error("Failed to load from config! {}", e.what()); + } + } +} + +void dusk::config::Save() { + const auto configJsonPath = GetConfigJsonPath(); + if (configJsonPath.empty()) { + return; + } + + DuskConfigLog.info("Saving config to '{}'", configJsonPath); + + json j; + + for (const auto& pair : RegisteredConfigVars) { + if (pair.second->getLayer() == ConfigVarLayer::Value) { + j[pair.first] = pair.second->getImpl()->dumpToJson(*pair.second); + } + } + + io::FileStream::WriteAllText(configJsonPath.c_str(), j.dump(4)); +} + +ConfigVarBase* dusk::config::GetConfigVar(std::string_view name) { + const auto configVar = RegisteredConfigVars.find(name); + if (configVar != RegisteredConfigVars.end()) { + return configVar->second; + } + + return nullptr; +} \ No newline at end of file diff --git a/src/dusk/dvd_asset.cpp b/src/dusk/dvd_asset.cpp new file mode 100644 index 0000000000..b9e0729be9 --- /dev/null +++ b/src/dusk/dvd_asset.cpp @@ -0,0 +1,125 @@ +#include "dusk/dvd_asset.hpp" +#include "dusk/logging.h" +#include "dusk/endian.h" +#include "dolphin/dvd.h" +#include "DynamicLink.h" +#include "JSystem/JKernel/JKRArchive.h" +#include "JSystem/JKernel/JKRDvdRipper.h" + +#include + +namespace dusk { + +static const u8* s_dolData = nullptr; // pointer to dol data +static size_t s_dolSize = 0; + +struct DolHeader { + BE(u32) textOffset[7]; + BE(u32) dataOffset[11]; + BE(u32) textAddr[7]; + BE(u32) dataAddr[11]; + BE(u32) textSize[7]; + BE(u32) dataSize[11]; +}; + +struct DolSection { + u32 fileOffset; + u32 vaddr; + u32 size; +}; + +static DolSection s_dolSections[18]; // 7 text + 11 data +static int s_dolSectionCount = 0; + +static bool EnsureDolParsed() { + if (s_dolData) return true; + + s32 sz = 0; + const u8* p = DVDGetDOLLocation(&sz); + if (!p || sz < 256) { + DuskLog.fatal("dvd_asset: DVDGetDOLLocation failed (size={})", sz); + return false; + } + + s_dolData = p; + s_dolSize = sz; + + const auto* hdr = (const DolHeader*)s_dolData; + s_dolSectionCount = 0; + + for (int i = 0; i < 7; i++) { + u32 off = hdr->textOffset[i]; + u32 addr = hdr->textAddr[i]; + u32 sz = hdr->textSize[i]; + if (sz > 0 && off > 0) { + s_dolSections[s_dolSectionCount++] = {off, addr, sz}; + } + } + + for (int i = 0; i < 11; i++) { + u32 off = hdr->dataOffset[i]; + u32 addr = hdr->dataAddr[i]; + u32 sz = hdr->dataSize[i]; + if (sz > 0 && off > 0) { + s_dolSections[s_dolSectionCount++] = {off, addr, sz}; + } + } + + return true; +} + +static s32 DolVaToFileOffset(u32 va) { + if (!EnsureDolParsed()) return -1; + for (int i = 0; i < s_dolSectionCount; i++) { + const auto& sec = s_dolSections[i]; + if (va >= sec.vaddr && va < sec.vaddr + sec.size) { + return static_cast(sec.fileOffset + (va - sec.vaddr)); + } + } + DuskLog.fatal("dvd_asset: VA 0x{:08X} not found in any DOL section", va); + return -1; +} + +bool LoadDolAsset(void* dst, u32 virtualAddress, s32 size) { + s32 fileOffset = DolVaToFileOffset(virtualAddress); + if (fileOffset < 0) { + return false; + } + + if (size <= 0 || (size_t)(fileOffset + size) > s_dolSize) { + DuskLog.fatal("dvd_asset: DOL read out of range (offset={:#x} size={:#x} dolSize={})", fileOffset, size, s_dolSize); + return false; + } + + std::memcpy(dst, s_dolData + fileOffset, size); + return true; +} + +bool LoadRelAsset(void* dst, const char* dvdPath, s32 offset, s32 size) { + void* p = JKRDvdRipper::loadToMainRAM(dvdPath, (u8*)dst, EXPAND_SWITCH_UNKNOWN1, (u32)size, nullptr, JKRDvdRipper::ALLOC_DIRECTION_FORWARD, (u32)offset, nullptr, nullptr); + if (!p) DuskLog.fatal("dvd_asset: failed to load {} (offset={:#x} size={:#x})", dvdPath, offset, size); + return p != nullptr; +} + +bool LoadArchivedRelAsset(void* dst, u32 memType, const char* relFileName, s32 offset, s32 size) { + // On TARGET_PC, cDyl_InitCallback skips DynamicModuleControl::initialize() due to static linking + // Mount RELS.arc on first use so sArchive is available + static bool s_mountAttempted = false; + if (!DynamicModuleControl::sArchive && !s_mountAttempted) { + s_mountAttempted = true; DynamicModuleControl::initialize(); + } + + if (!DynamicModuleControl::sArchive) { + DuskLog.fatal("dvd_asset: RELS archive not mounted"); return false; + } + + const u8* rel = static_cast(DynamicModuleControl::sArchive->getResource(memType, relFileName)); + if (!rel) { + DuskLog.fatal("dvd_asset: {} not found in RELS archive", relFileName); return false; + } + + std::memcpy(dst, rel + offset, size); + return true; +} + +} // namespace dusk diff --git a/src/dusk/imgui/ImGuiAudio.cpp b/src/dusk/imgui/ImGuiAudio.cpp new file mode 100644 index 0000000000..3328d1b97c --- /dev/null +++ b/src/dusk/imgui/ImGuiAudio.cpp @@ -0,0 +1,255 @@ +#include "ImGuiConsole.hpp" +#include "ImGuiMenuTools.hpp" +#include "JSystem/JAudio2/JAISeMgr.h" +#include "JSystem/JAudio2/JAISeqMgr.h" +#include "JSystem/JAudio2/JAIStreamMgr.h" +#include "JSystem/JAudio2/JASCriticalSection.h" +#include "JSystem/JAudio2/JASDSPChannel.h" +#include "JSystem/JAudio2/JASDSPInterface.h" +#include "JSystem/JAudio2/JASTrack.h" +#include "dusk/audio/DuskAudioSystem.h" +#include "dusk/audio/DuskDsp.hpp" + +static std::array channelSortIndices = {}; +static std::array lastResetCounts = {}; + +static bool sortUpdateCount = true; + +static void DisplayDspChannel(int i) { + using namespace dusk::audio; + + auto& channel = JASDsp::CH_BUF[i]; + auto& jasChannel = JASDSPChannel::sDspChannels[i]; + if (!channel.mIsActive) { + return; + } + + char buf[64]; + snprintf(buf, sizeof(buf), "%d", i); + + if (ImGui::BeginChild(buf, ImVec2(), ImGuiChildFlags_Border | ImGuiChildFlags_AutoResizeY)) { + ImGui::Text("[%02X]", i); + ImGui::SameLine(); + + auto resetCount = GetResetCount(i); + ImColor color = IM_COL32_WHITE; + if (lastResetCounts[i] != resetCount) { + lastResetCounts[i] = resetCount; + color = IM_COL32(0, 0xFF, 0, 0xFF); + } + ImGui::TextColored(color, "Update count: %d, reset count: %ud", jasChannel.mUpdateCounter, resetCount); + ImGui::TextUnformatted(channel.mLoopFlag ? "Loop: true" : "Loop: false"); + ImGui::SameLine(); + ImGui::Text("Priority: %hd", jasChannel.mPriority); + ImGui::Text("Format: %02X/%02X", channel.mSamplesPerBlock, channel.mBytesPerBlock); + ImGui::Text("Position: %08X/%08X", channel.mSamplePosition, channel.mEndSample); + ImGui::SameLine(); + ImGui::Text("Memory: %08X/%08X", channel.mWaveAramAddress, channel.mAramStreamPosition); + + if (channel.mAutoMixerBeenSet) { + auto pan = (channel.mAutoMixerPanDolby >> 8) / 127.5f; + auto dolby = (channel.mAutoMixerPanDolby & 0xFF) / 127.5f; + auto fxMix = (channel.mAutoMixerFxMix >> 8) / 127.5f; + auto volume = VolumeFromU16(channel.mAutoMixerVolume); + auto pitch = channel.mPitch / 4096.0f; + ImGui::Text( + "Auto mixer active (pan: %f, dolby: %f, fx: %f, volume: %f, pitch %f)", + pan, dolby, fxMix, volume, pitch); + } else { + ImGui::Text( + "Bus connect: %04X(%.2f),%04X(%.2f),%04X(%.2f),%04X(%.2f),%04X(%.2f),%04X(%.2f)", + channel.mOutputChannels[0].mBusConnect, + VolumeFromU16(channel.mOutputChannels[0].mTargetVolume), + channel.mOutputChannels[1].mBusConnect, + VolumeFromU16(channel.mOutputChannels[1].mTargetVolume), + channel.mOutputChannels[2].mBusConnect, + VolumeFromU16(channel.mOutputChannels[2].mTargetVolume), + channel.mOutputChannels[3].mBusConnect, + VolumeFromU16(channel.mOutputChannels[3].mTargetVolume), + channel.mOutputChannels[4].mBusConnect, + VolumeFromU16(channel.mOutputChannels[4].mTargetVolume), + channel.mOutputChannels[5].mBusConnect, + VolumeFromU16(channel.mOutputChannels[5].mTargetVolume)); + } + } + + ImGui::EndChild(); +} + +static void InitChannelSortIndices() { + for (int i = 0; i < channelSortIndices.size(); i++) { + channelSortIndices[i] = i; + } +} + +static void SortChannelsByUpdateCount() { + InitChannelSortIndices(); + std::ranges::stable_sort( + channelSortIndices, + [](u8 a, u8 b) { + auto& jasChannelA = JASDSPChannel::sDspChannels[a]; + auto& jasChannelB = JASDSPChannel::sDspChannels[b]; + + return jasChannelA.mUpdateCounter > jasChannelB.mUpdateCounter; + }); +} + +static void ShowAllDspChannels() { + int activeChannels = 0; + for (int i = 0; i < DSP_CHANNELS; i++) { + if (JASDsp::CH_BUF[i].mIsActive) { + activeChannels++; + } + } + + ImGui::Text("Active channels: %d", activeChannels); + ImGui::Checkbox("Dump channels to disk", &dusk::audio::DumpAudio); + ImGui::Checkbox("Sort by update count", &sortUpdateCount); + + if (sortUpdateCount) { + SortChannelsByUpdateCount(); + for (u8 index : channelSortIndices) { + DisplayDspChannel(index); + } + } else { + for (int i = 0; i < DSP_CHANNELS; i++) { + DisplayDspChannel(i); + } + } +} + +static void ShowAllTracks() { + if (ImGui::Button("Pause all")) { + for (auto& track : JASTrack::sTrackList) { + track.pause(true); + } + } + + for (auto& track : JASTrack::sTrackList) { + char buf[32]; + snprintf(buf, sizeof(buf), "%p", &track); + + if (ImGui::BeginChild(buf, ImVec2(), ImGuiChildFlags_Border | ImGuiChildFlags_AutoResizeY)) { + ImGui::Text("[%p]", &track); + bool paused = track.mFlags.pause; + ImGui::Checkbox("Paused", &paused); + track.mFlags.pause = paused; + bool muted = track.mFlags.mute; + ImGui::Checkbox("Muted", &muted); + track.mFlags.mute = muted; + + for (int i = 0; i < JASTrack::MAX_CHILDREN; i++) { + const auto child = track.getChild(i); + if (child != nullptr) { + ImGui::Text("child: [%p]", child); + } + } + } + + ImGui::EndChild(); + } +} + +static void ShowAllJAIStreams() { + auto& mgr = *JAIStreamMgr::getInstance(); + + for (auto streamLink = mgr.getStreamList()->getFirst(); streamLink != nullptr; streamLink = streamLink->getNext()) { + auto& stream = *streamLink->getObject(); + char buf[32]; + snprintf(buf, sizeof(buf), "%p", &stream); + + if (ImGui::BeginChild(buf, ImVec2(), ImGuiChildFlags_Border | ImGuiChildFlags_AutoResizeY)) { + ImGui::Text("[%p]", &stream); + bool paused = stream.status_.field_0x0.flags.paused; + ImGui::Checkbox("Paused", &paused); + stream.status_.field_0x0.flags.paused = paused; + } + + ImGui::EndChild(); + } +} + +static void ShowAllJAISes() { + auto& mgr = *JAISeMgr::getInstance(); + + for (int i = 0; i < JAISeMgr::NUM_CATEGORIES; i++) { + const auto category = mgr.getCategory(i); + + char buf[32]; + snprintf(buf, sizeof(buf), "%i", i); + + if (ImGui::BeginChild(buf, ImVec2(), ImGuiChildFlags_Border | ImGuiChildFlags_AutoResizeY)) { + ImGui::Text("Category: %i", i); + if (ImGui::Button("Pause All")) { + category->pause(true); + } + + for (auto seLink = category->getSeList()->getFirst(); seLink != nullptr; seLink = seLink->getNext()) { + const auto se = seLink->getObject(); + ImGui::Text("[%p]", se); + ImGui::Text(se->status_.field_0x0.flags.paused ? "Paused" : "Not paused"); + } + } + + ImGui::EndChild(); + } +} + + +static void ShowAllJAISeqs() { + auto& mgr = *JAISeqMgr::getInstance(); + + if (ImGui::Button("Pause")) { + mgr.pause(true); + } + ImGui::SameLine(); + if (ImGui::Button("Unpause")) { + mgr.pause(false); + } +} + +void dusk::ImGuiMenuTools::ShowAudioDebug() { + if (!ImGuiConsole::CheckMenuViewToggle(ImGuiKey_F7, m_showAudioDebug)) { + return; + } + + if (!ImGui::Begin("Audio Debug", &m_showAudioDebug)) { + ImGui::End(); + return; + } + + { + JASCriticalSection cs; + + if (ImGui::BeginTabBar("Tabs")) { + if (ImGui::BeginTabItem("DSP channels")) { + ShowAllDspChannels(); + ImGui::EndTabItem(); + } + + if (ImGui::BeginTabItem("JAITrack")) { + ShowAllTracks(); + ImGui::EndTabItem(); + } + + if (ImGui::BeginTabItem("JAIStream")) { + ShowAllJAIStreams(); + ImGui::EndTabItem(); + } + + if (ImGui::BeginTabItem("JAISe")) { + ShowAllJAISes(); + ImGui::EndTabItem(); + } + + if (ImGui::BeginTabItem("JAISeq")) { + ShowAllJAISeqs(); + ImGui::EndTabItem(); + } + + ImGui::EndTabBar(); + } + } + + ImGui::End(); +} diff --git a/src/dusk/imgui/ImGuiCameraOverlay.cpp b/src/dusk/imgui/ImGuiCameraOverlay.cpp index 58b31fe00f..599af30f37 100644 --- a/src/dusk/imgui/ImGuiCameraOverlay.cpp +++ b/src/dusk/imgui/ImGuiCameraOverlay.cpp @@ -26,7 +26,6 @@ namespace dusk { } ImGui::SetNextWindowBgAlpha(0.65f); - ImGui::SetNextWindowSizeConstraints(ImVec2(300, 0), ImVec2(FLT_MAX, FLT_MAX)); if (!ImGui::Begin("Camera Debug", nullptr, windowFlags)) { ImGui::End(); diff --git a/src/dusk/imgui/ImGuiConfig.hpp b/src/dusk/imgui/ImGuiConfig.hpp new file mode 100644 index 0000000000..e3e80b9920 --- /dev/null +++ b/src/dusk/imgui/ImGuiConfig.hpp @@ -0,0 +1,53 @@ +#ifndef DUSK_IMGUICONFIG_HPP +#define DUSK_IMGUICONFIG_HPP + +#include "dusk/config.hpp" +#include "imgui.h" + +namespace dusk::config { + inline bool ImGuiCheckbox(const char* title, ConfigVar& var) { + bool copy = var.getValue(); + if (ImGui::Checkbox(title, ©)) { + var.setValue(copy); + Save(); + return true; + } + + return false; + } + + static bool ImGuiSliderFloat(const char* label, ConfigVar& var, float v_min, float v_max, const char* format = "%.3f", ImGuiSliderFlags flags = 0) { + float val = var; + if (ImGui::SliderFloat(label, &val, v_min, v_max, format, flags)) { + var.setValue(val); + Save(); + return true; + } + + return false; + } + + static bool ImGuiSliderInt(const char* label, ConfigVar& var, int v_min, int v_max, const char* format = "%d", ImGuiSliderFlags flags = 0) { + int val = var; + if (ImGui::SliderInt(label, &val, v_min, v_max, format, flags)) { + var.setValue(val); + Save(); + return true; + } + + return false; + } + + static bool ImGuiMenuItem(const char* label, const char* shortcut, ConfigVar& p_selected, bool enabled = true) { + bool copy = p_selected.getValue(); + if (ImGui::MenuItem(label, shortcut, ©, enabled)) { + p_selected.setValue(copy); + Save(); + return true; + } + + return false; + } +} + +#endif // DUSK_IMGUICONFIG_HPP diff --git a/src/dusk/imgui/ImGuiConsole.cpp b/src/dusk/imgui/ImGuiConsole.cpp index cc8b758cb7..a238bb7c7a 100644 --- a/src/dusk/imgui/ImGuiConsole.cpp +++ b/src/dusk/imgui/ImGuiConsole.cpp @@ -1,3 +1,4 @@ +#include #include #include #include @@ -6,14 +7,20 @@ #include "fmt/format.h" #include "imgui.h" -#include "aurora/gfx.h" #include #include "ImGuiConsole.hpp" #include "JSystem/JUtility/JUTGamePad.h" +#include "SDL3/SDL_mouse.h" +#include "dusk/config.hpp" +#include "dusk/settings.h" +#include "dusk/audio/DuskAudioSystem.h" +#include "dusk/dusk.h" +#include "tracy/Tracy.hpp" #if _WIN32 +#define NOMINMAX #include "Windows.h" #endif @@ -21,6 +28,8 @@ using namespace std::string_literals; using namespace std::string_view_literals; namespace dusk { + float ImGuiScale() { return 1.0f; } + void ImGuiStringViewText(std::string_view text) { // begin()/end() do not work on MSVC ImGui::TextUnformatted(text.data(), text.data() + text.size()); @@ -47,7 +56,7 @@ namespace dusk { ImVec2 workSize = viewport->WorkSize; ImVec2 windowPos; ImVec2 windowPosPivot; - constexpr float padding = 10.0f; + const float padding = 10.0f * ImGuiScale(); windowPos.x = (corner & 1) != 0 ? (workPos.x + workSize.x - padding) : (workPos.x + padding); windowPos.y = (corner & 2) != 0 ? (workPos.y + workSize.y - padding) : (workPos.y + padding); windowPosPivot.x = (corner & 1) != 0 ? 1.0f : 0.0f; @@ -150,10 +159,13 @@ namespace dusk { auto itemMin = ImGui::GetItemRectMin(); auto itemMax = ImGui::GetItemRectMax(); + float frameSpacingY = 8.0f; + float frameBottomPadding = 10.0f; + ImVec2 halfFrame = ImVec2((frameHeight * 0.25f) * 0.5f, frameHeight * 0.5f); ImGui::GetWindowDrawList()->AddRect( - ImVec2(itemMin.x + halfFrame.x, itemMin.y + halfFrame.y), - ImVec2(itemMax.x - halfFrame.x, itemMax.y), + ImVec2(itemMin.x + halfFrame.x, itemMin.y + halfFrame.y + frameSpacingY), + ImVec2(itemMax.x - halfFrame.x, itemMax.y + frameBottomPadding), ImColor(ImGui::GetStyleColorVec4(ImGuiCol_Border)), halfFrame.x); @@ -172,21 +184,76 @@ namespace dusk { ImGuiConsole::ImGuiConsole() {} - void ImGuiConsole::draw() { + void ImGuiConsole::InitSettings() { + bool lockAspect = getSettings().video.lockAspectRatio; + if (lockAspect) { + VILockAspectRatio(defaultAspectRatioW, defaultAspectRatioH); + } else { + VIUnlockAspectRatio(); + } + + dusk::audio::SetMasterVolume(getSettings().audio.masterVolume / 100.0f); + dusk::audio::SetEnableReverb(getSettings().audio.enableReverb); + } + + void ImGuiConsole::UpdateSettings() { + getTransientSettings().skipFrameRateLimit = getSettings().game.enableTurboKeybind && ImGui::IsKeyDown(ImGuiKey_Tab); + } + + void ImGuiConsole::PreDraw() { + ZoneScoped; + if (!m_isLaunchInitialized) { + InitSettings(); + + m_toasts.emplace_back("Press F1 to toggle menu"s, 5.f); + m_isLaunchInitialized = true; + } + + UpdateSettings(); + + if ((ImGui::IsKeyDown(ImGuiKey_LeftCtrl) || ImGui::IsKeyDown(ImGuiKey_RightCtrl)) && + ImGui::IsKeyPressed(ImGuiKey_R)) + { + JUTGamePad::C3ButtonReset::sResetSwitchPushing = true; + } + + if (ImGui::IsKeyPressed(ImGuiKey_F11)) { + ImGuiMenuGame::ToggleFullscreen(); + } + if (CheckMenuViewToggle(ImGuiKey_F1, m_isHidden)) { + ShowToasts(); + ImGui::GetIO().ConfigFlags |= ImGuiConfigFlags_NoMouseCursorChange; + SDL_HideCursor(); return; } + ImGui::GetIO().ConfigFlags &= ~ImGuiConfigFlags_NoMouseCursorChange; + // Imgui will re-show cursor. + + // TODO: we need to be able to render the menu bar & any overlays separately + // The code currently ties them all together, so hiding the menu hides all windows + if (ImGui::BeginMainMenuBar()) { m_menuGame.draw(); + m_menuEnhancements.draw(); + + // Keep always last m_menuTools.draw(); - ImGui::SetCursorPosX(ImGui::GetWindowWidth() - 80.0f); + ImGui::SetCursorPosX(ImGui::GetWindowWidth() - 80.0f * ImGuiScale()); ImGuiIO& io = ImGui::GetIO(); ImGuiStringViewText(fmt::format(FMT_STRING("FPS: {:.2f}\n"), io.Framerate)); ImGui::EndMainMenuBar(); } + + ShowToasts(); + } + + void ImGuiConsole::PostDraw() { + m_menuTools.afterDraw(); + ShowPipelineProgress(); } bool ImGuiConsole::CheckMenuViewToggle(ImGuiKey key, bool& active) { @@ -219,105 +286,72 @@ namespace dusk { return "Null"sv; } } -} -class Limiter -{ - using delta_clock = std::chrono::high_resolution_clock; - using duration_t = std::chrono::nanoseconds; - -public: - void Reset() - { - m_oldTime = delta_clock::now(); - } - - void Sleep(duration_t targetFrameTime) - { - if (targetFrameTime.count() == 0) - { + void ImGuiConsole::ShowToasts() { + if (m_toasts.empty()) { return; } + auto& toast = m_toasts.front(); + const float dt = ImGui::GetIO().DeltaTime; + toast.remain -= dt; + toast.current += dt; - auto start = delta_clock::now(); - duration_t adjustedSleepTime = SleepTime(targetFrameTime); - if (adjustedSleepTime.count() > 0) + const ImGuiViewport* viewport = ImGui::GetMainViewport(); + const ImVec2 workPos = viewport->WorkPos; + const ImVec2 workSize = viewport->WorkSize; + constexpr float padding = 10.0f; + const ImVec2 windowPos{workPos.x + workSize.x / 2, workPos.y + workSize.y - padding}; + ImGui::SetNextWindowPos(windowPos, ImGuiCond_Always, ImVec2{0.5f, 1.f}); + + const float alpha = std::min({toast.remain, toast.current, 1.f}); + ImGui::SetNextWindowBgAlpha(alpha * 0.65f); + ImVec4 textColor = ImGui::GetStyleColorVec4(ImGuiCol_Text); + textColor.w *= alpha; + ImVec4 borderColor = ImGui::GetStyleColorVec4(ImGuiCol_Border); + borderColor.w *= alpha; + ImGui::PushStyleColor(ImGuiCol_Text, textColor); + ImGui::PushStyleColor(ImGuiCol_Border, borderColor); + if (ImGui::Begin("Toast", nullptr, + ImGuiWindowFlags_NoDecoration | ImGuiWindowFlags_AlwaysAutoResize | + ImGuiWindowFlags_NoSavedSettings | + ImGuiWindowFlags_NoFocusOnAppearing | ImGuiWindowFlags_NoNav | + ImGuiWindowFlags_NoMove)) { - NanoSleep(adjustedSleepTime); - duration_t overslept = TimeSince(start) - adjustedSleepTime; - if (overslept < duration_t{ targetFrameTime }) - { - m_overheadTimes[m_overheadTimeIdx] = overslept; - m_overheadTimeIdx = (m_overheadTimeIdx + 1) % m_overheadTimes.size(); - } + ImGuiStringViewText(toast.message); } - Reset(); - } + ImGui::End(); + ImGui::PopStyleColor(2); - duration_t SleepTime(duration_t targetFrameTime) - { - const auto sleepTime = duration_t{ targetFrameTime } - TimeSince(m_oldTime); - m_overhead = std::accumulate(m_overheadTimes.begin(), m_overheadTimes.end(), duration_t{}) / - m_overheadTimes.size(); - if (sleepTime > m_overhead) - { - return sleepTime - m_overhead; + if (toast.remain <= 0.f) { + m_toasts.pop_front(); } - return duration_t{ 0 }; } -private: - delta_clock::time_point m_oldTime; - std::array m_overheadTimes{}; - size_t m_overheadTimeIdx = 0; - duration_t m_overhead = duration_t{ 0 }; - - duration_t TimeSince(delta_clock::time_point start) - { - return std::chrono::duration_cast(delta_clock::now() - start); - } - -#if _WIN32 - bool m_initialized; - double m_countPerNs; - - void NanoSleep(const duration_t duration) - { - if (!m_initialized) - { - LARGE_INTEGER freq; - QueryPerformanceFrequency(&freq); - m_countPerNs = static_cast(freq.QuadPart) / 1000000000.0; - m_initialized = true; + void ImGuiConsole::ShowPipelineProgress() { + const auto* stats = aurora_get_stats(); + const u32 queuedPipelines = stats->queuedPipelines; + if (queuedPipelines == 0) { + return; } + const u32 createdPipelines = stats->createdPipelines; + const u32 totalPipelines = queuedPipelines + createdPipelines; - DWORD ms = std::chrono::duration_cast(duration).count(); - auto tickCount = - static_cast(static_cast(duration.count()) * m_countPerNs); - LARGE_INTEGER count; - QueryPerformanceCounter(&count); - if (ms > 10) - { - // Adjust for Sleep overhead - ::Sleep(ms - 10); - } - auto end = count.QuadPart + tickCount; - do - { - QueryPerformanceCounter(&count); - } while (count.QuadPart < end); + const auto* viewport = ImGui::GetMainViewport(); + const auto padding = viewport->WorkPos.y + 10.f; + const auto halfWidth = viewport->GetWorkCenter().x; + ImGui::SetNextWindowPos(ImVec2{halfWidth, padding}, ImGuiCond_Always, ImVec2{0.5f, 0.f}); + ImGui::SetNextWindowSize(ImVec2{halfWidth, 0.f}, ImGuiCond_Always); + ImGui::SetNextWindowBgAlpha(0.65f); + ImGui::Begin("Pipelines", nullptr, + ImGuiWindowFlags_NoDecoration | ImGuiWindowFlags_NoInputs | ImGuiWindowFlags_NoMove | + ImGuiWindowFlags_NoSavedSettings | ImGuiWindowFlags_NoFocusOnAppearing); + const auto percent = static_cast(createdPipelines) / static_cast(totalPipelines); + const auto progressStr = fmt::format("Processing pipelines: {} / {}", createdPipelines, totalPipelines); + const auto textSize = ImGui::CalcTextSize(progressStr.data(), progressStr.data() + progressStr.size()); + ImGui::NewLine(); + ImGui::SameLine(ImGui::GetWindowWidth() / 2.f - textSize.x + textSize.x / 2.f); + ImGuiStringViewText(progressStr); + ImGui::ProgressBar(percent); + ImGui::End(); } -#else - void NanoSleep(const duration_t duration) - { - std::this_thread::sleep_for(duration); - } -#endif -}; - -static Limiter g_frameLimiter; -void frame_limiter() -{ - g_frameLimiter.Sleep( - std::chrono::duration_cast(std::chrono::seconds{ 1 }) / 60); } diff --git a/src/dusk/imgui/ImGuiConsole.hpp b/src/dusk/imgui/ImGuiConsole.hpp index c67bb2a885..3d13e2ed6d 100644 --- a/src/dusk/imgui/ImGuiConsole.hpp +++ b/src/dusk/imgui/ImGuiConsole.hpp @@ -2,41 +2,59 @@ #define DUSK_IMGUI_HPP #include +#include #include -#include "imgui.h" +#include "ImGuiMenuEnhancements.hpp" #include "ImGuiMenuGame.hpp" #include "ImGuiMenuTools.hpp" +#include "imgui.h" namespace dusk { - class ImGuiConsole { - public: - ImGuiConsole(); - void draw(); +class ImGuiConsole { +public: + ImGuiConsole(); + void InitSettings(); + void UpdateSettings(); + void PreDraw(); + void PostDraw(); - bool isBloomEnabled() { return m_menuGame.isBloomEnabled(); } - bool isWaterProjectionOffsetEnabled() { return m_menuGame.isWaterProjectionOffsetEnabled(); } - ImGuiMenuTools::CollisionViewSettings& getCollisionViewSettings() { return m_menuTools.getCollisionViewSettings(); } + static bool CheckMenuViewToggle(ImGuiKey key, bool& active); - static bool CheckMenuViewToggle(ImGuiKey key, bool& active); +private: + struct Toast { + std::string message; + float remain; + float current = 0.f; + Toast(std::string message, float duration) noexcept : message(std::move(message)), + remain(duration) {} + }; - private: - bool m_isHidden = false; + bool m_isHidden = true; + bool m_isLaunchInitialized = false; + std::deque m_toasts; - ImGuiMenuGame m_menuGame; - ImGuiMenuTools m_menuTools; - }; + ImGuiMenuGame m_menuGame; + ImGuiMenuEnhancements m_menuEnhancements; - extern ImGuiConsole g_imguiConsole; + // Keep always last + ImGuiMenuTools m_menuTools; - std::string_view backend_name(AuroraBackend backend); - std::string BytesToString(size_t bytes); - void SetOverlayWindowLocation(int corner); - bool ShowCornerContextMenu(int& corner, int avoidCorner); - void ImGuiStringViewText(std::string_view text); - void ImGuiBeginGroupPanel(const char* name, const ImVec2& size); - void ImGuiEndGroupPanel(); -} + void ShowToasts(); + void ShowPipelineProgress(); +}; + +extern ImGuiConsole g_imguiConsole; + +std::string_view backend_name(AuroraBackend backend); +std::string BytesToString(size_t bytes); +void SetOverlayWindowLocation(int corner); +bool ShowCornerContextMenu(int& corner, int avoidCorner); +void ImGuiStringViewText(std::string_view text); +void ImGuiBeginGroupPanel(const char* name, const ImVec2& size); +void ImGuiEndGroupPanel(); +float ImGuiScale(); +} // namespace dusk void DuskDebugPad(); diff --git a/src/dusk/imgui/ImGuiControllerOverlay.cpp b/src/dusk/imgui/ImGuiControllerOverlay.cpp index 0da82ac878..306bace22a 100644 --- a/src/dusk/imgui/ImGuiControllerOverlay.cpp +++ b/src/dusk/imgui/ImGuiControllerOverlay.cpp @@ -13,8 +13,6 @@ namespace dusk { ImGui::TextUnformatted(text.c_str()); } - static inline float GetScale() { return ImGui::GetCurrentContext()->CurrentDpiScale; } - void ImGuiMenuGame::windowInputViewer() { if (!m_showInputViewer) { return; @@ -35,7 +33,7 @@ namespace dusk { ImGui::SetNextWindowBgAlpha(0.65f); if (ImGui::Begin("Input Viewer", nullptr, windowFlags)) { - float scale = GetScale(); + float scale = ImGuiScale(); if (!m_controllerName.empty()) { TextCenter(m_controllerName); ImGui::Separator(); diff --git a/src/dusk/imgui/ImGuiEngine.cpp b/src/dusk/imgui/ImGuiEngine.cpp new file mode 100644 index 0000000000..a6abc5b0b9 --- /dev/null +++ b/src/dusk/imgui/ImGuiEngine.cpp @@ -0,0 +1,201 @@ +#include "ImGuiEngine.hpp" + +#include +#include +#include +#include +#include +#include +#include + +#include "dusk/logging.h" + +#ifdef IMGUI_ENABLE_FREETYPE +#include "misc/freetype/imgui_freetype.h" +#endif + +namespace dusk { +namespace { +std::string GetAssetPath(const char* assetName) { + const char* basePath = SDL_GetBasePath(); + if (basePath != nullptr && basePath[0] != '\0') { + return std::string(basePath) + "res/" + assetName; + } + return std::string("res/") + assetName; +} + +bool AssetExists(const std::string& path) { + SDL_PathInfo pathInfo{}; + return SDL_GetPathInfo(path.c_str(), &pathInfo) && pathInfo.type == SDL_PATHTYPE_FILE; +} +} // namespace + +ImFont* ImGuiEngine::fontNormal; +ImFont* ImGuiEngine::fontLarge; +ImTextureID ImGuiEngine::duskIcon; + +void ImGuiEngine_Initialize(float scale) { + ImGui::GetCurrentContext(); + ImGuiIO& io = ImGui::GetIO(); + io.Fonts->Clear(); + io.FontGlobalScale = scale > 0.0f ? 1.0f / scale : 1.0f; + + const std::string fontPath = GetAssetPath("NotoMono-Regular.ttf"); + const bool hasFontFile = AssetExists(fontPath); + + ImFontConfig fontConfig{}; + fontConfig.SizePixels = std::floor(15.f * scale); + snprintf(static_cast(fontConfig.Name), sizeof(fontConfig.Name), + "Noto Mono Regular, %dpx", static_cast(fontConfig.SizePixels)); + ImGuiEngine::fontNormal = + hasFontFile ? + io.Fonts->AddFontFromFileTTF(fontPath.c_str(), fontConfig.SizePixels, &fontConfig) : + nullptr; + if (ImGuiEngine::fontNormal == nullptr) { + if (hasFontFile) { + DuskLog.warn("Failed to load font '{}': {}", fontPath, SDL_GetError()); + } + ImGuiEngine::fontNormal = io.Fonts->AddFontDefault(&fontConfig); + } + + fontConfig.SizePixels = std::floor(26.f * scale); +#ifdef IMGUI_ENABLE_FREETYPE + fontConfig.FontBuilderFlags |= ImGuiFreeTypeBuilderFlags_Bold; + snprintf(static_cast(fontConfig.Name), sizeof(fontConfig.Name), "Noto Mono Bold, %dpx", + static_cast(fontConfig.SizePixels)); +#else + snprintf(static_cast(fontConfig.Name), sizeof(fontConfig.Name), + "Noto Mono Regular, %dpx", static_cast(fontConfig.SizePixels)); +#endif + ImGuiEngine::fontLarge = + hasFontFile ? + io.Fonts->AddFontFromFileTTF(fontPath.c_str(), fontConfig.SizePixels, &fontConfig) : + nullptr; + if (ImGuiEngine::fontLarge == nullptr) { + if (hasFontFile) { + DuskLog.warn("Failed to load font '{}': {}", fontPath, SDL_GetError()); + } + ImGuiEngine::fontLarge = io.Fonts->AddFontDefault(&fontConfig); + } + + auto& style = ImGui::GetStyle(); + style = {}; // Reset sizes + style.WindowPadding = ImVec2(15, 15); + style.WindowRounding = 5.0f; + style.FrameBorderSize = 1.f; + style.FramePadding = ImVec2(5, 5); + style.FrameRounding = 4.0f; + style.ItemSpacing = ImVec2(12, 8); + style.ItemInnerSpacing = ImVec2(8, 6); + style.IndentSpacing = 25.0f; + style.ScrollbarSize = 15.0f; + style.ScrollbarRounding = 9.0f; + style.GrabMinSize = 5.0f; + style.GrabRounding = 3.0f; + style.PopupBorderSize = 1.f; + style.PopupRounding = 7.0; + style.TabBorderSize = 1.f; + style.TabRounding = 3.f; + + auto* colors = style.Colors; + colors[ImGuiCol_Text] = ImVec4(0.95f, 0.96f, 0.98f, 1.00f); + colors[ImGuiCol_TextDisabled] = ImVec4(0.36f, 0.42f, 0.47f, 1.00f); + colors[ImGuiCol_WindowBg] = ImVec4(0.11f, 0.15f, 0.17f, 1.00f); + colors[ImGuiCol_ChildBg] = ImVec4(0.15f, 0.18f, 0.22f, 1.00f); + colors[ImGuiCol_PopupBg] = ImVec4(0.08f, 0.08f, 0.08f, 0.94f); + colors[ImGuiCol_Border] = ImVec4(0.08f, 0.10f, 0.12f, 1.00f); + colors[ImGuiCol_BorderShadow] = ImVec4(0.00f, 0.00f, 0.00f, 0.00f); + colors[ImGuiCol_FrameBg] = ImVec4(0.20f, 0.25f, 0.29f, 1.00f); + colors[ImGuiCol_FrameBgHovered] = ImVec4(0.12f, 0.20f, 0.28f, 1.00f); + colors[ImGuiCol_FrameBgActive] = ImVec4(0.09f, 0.12f, 0.14f, 1.00f); + colors[ImGuiCol_TitleBg] = ImVec4(0.09f, 0.12f, 0.14f, 0.65f); + colors[ImGuiCol_TitleBgActive] = ImVec4(0.08f, 0.10f, 0.12f, 1.00f); + colors[ImGuiCol_TitleBgCollapsed] = ImVec4(0.00f, 0.00f, 0.00f, 0.51f); + colors[ImGuiCol_MenuBarBg] = ImVec4(0.15f, 0.18f, 0.22f, 1.00f); + colors[ImGuiCol_ScrollbarBg] = ImVec4(0.02f, 0.02f, 0.02f, 0.39f); + colors[ImGuiCol_ScrollbarGrab] = ImVec4(0.20f, 0.25f, 0.29f, 1.00f); + colors[ImGuiCol_ScrollbarGrabHovered] = ImVec4(0.18f, 0.22f, 0.25f, 1.00f); + colors[ImGuiCol_ScrollbarGrabActive] = ImVec4(0.09f, 0.21f, 0.31f, 1.00f); + colors[ImGuiCol_CheckMark] = ImVec4(0.28f, 0.56f, 1.00f, 1.00f); + colors[ImGuiCol_SliderGrab] = ImVec4(0.28f, 0.56f, 1.00f, 1.00f); + colors[ImGuiCol_SliderGrabActive] = ImVec4(0.37f, 0.61f, 1.00f, 1.00f); + colors[ImGuiCol_Button] = ImVec4(0.20f, 0.25f, 0.29f, 1.00f); + colors[ImGuiCol_ButtonHovered] = ImVec4(0.28f, 0.56f, 1.00f, 1.00f); + colors[ImGuiCol_ButtonActive] = ImVec4(0.06f, 0.53f, 0.98f, 1.00f); + colors[ImGuiCol_Header] = ImVec4(0.20f, 0.25f, 0.29f, 0.55f); + colors[ImGuiCol_HeaderHovered] = ImVec4(0.26f, 0.59f, 0.98f, 0.80f); + colors[ImGuiCol_HeaderActive] = ImVec4(0.26f, 0.59f, 0.98f, 1.00f); + colors[ImGuiCol_Separator] = ImVec4(0.20f, 0.25f, 0.29f, 1.00f); + colors[ImGuiCol_SeparatorHovered] = ImVec4(0.10f, 0.40f, 0.75f, 0.78f); + colors[ImGuiCol_SeparatorActive] = ImVec4(0.10f, 0.40f, 0.75f, 1.00f); + colors[ImGuiCol_ResizeGrip] = ImVec4(0.26f, 0.59f, 0.98f, 0.25f); + colors[ImGuiCol_ResizeGripHovered] = ImVec4(0.26f, 0.59f, 0.98f, 0.67f); + colors[ImGuiCol_ResizeGripActive] = ImVec4(0.26f, 0.59f, 0.98f, 0.95f); + colors[ImGuiCol_Tab] = ImVec4(0.11f, 0.15f, 0.17f, 1.00f); + colors[ImGuiCol_TabHovered] = ImVec4(0.26f, 0.59f, 0.98f, 0.80f); + colors[ImGuiCol_TabActive] = ImVec4(0.20f, 0.25f, 0.29f, 1.00f); + colors[ImGuiCol_TabUnfocused] = ImVec4(0.11f, 0.15f, 0.17f, 1.00f); + colors[ImGuiCol_TabUnfocusedActive] = ImVec4(0.11f, 0.15f, 0.17f, 1.00f); + colors[ImGuiCol_PlotLines] = ImVec4(0.61f, 0.61f, 0.61f, 1.00f); + colors[ImGuiCol_PlotLinesHovered] = ImVec4(1.00f, 0.43f, 0.35f, 1.00f); + colors[ImGuiCol_PlotHistogram] = ImVec4(0.06f, 0.53f, 0.98f, 1.00f); + colors[ImGuiCol_PlotHistogramHovered] = ImVec4(0.28f, 0.56f, 1.00f, 1.00f); + colors[ImGuiCol_TextSelectedBg] = ImVec4(0.26f, 0.59f, 0.98f, 0.35f); + colors[ImGuiCol_DragDropTarget] = ImVec4(1.00f, 1.00f, 0.00f, 0.90f); + colors[ImGuiCol_NavHighlight] = ImVec4(0.26f, 0.59f, 0.98f, 1.00f); + colors[ImGuiCol_NavWindowingHighlight] = ImVec4(1.00f, 1.00f, 1.00f, 0.70f); + colors[ImGuiCol_NavWindowingDimBg] = ImVec4(0.80f, 0.80f, 0.80f, 0.20f); + colors[ImGuiCol_ModalWindowDimBg] = ImVec4(0.80f, 0.80f, 0.80f, 0.35f); + +} + +Icon GetIcon() { + const std::string iconPath = GetAssetPath("icon.png"); + if (!AssetExists(iconPath)) { + return {}; + } + + SDL_Surface* loadedSurface = SDL_LoadPNG(iconPath.c_str()); + if (loadedSurface == nullptr) { + DuskLog.warn("Failed to load icon '{}': {}", iconPath, SDL_GetError()); + return {}; + } + + SDL_Surface* rgbaSurface = SDL_ConvertSurface(loadedSurface, SDL_PIXELFORMAT_RGBA32); + SDL_DestroySurface(loadedSurface); + if (rgbaSurface == nullptr) { + DuskLog.warn("Failed to convert icon '{}': {}", iconPath, SDL_GetError()); + return {}; + } + + const auto iconWidth = static_cast(rgbaSurface->w); + const auto iconHeight = static_cast(rgbaSurface->h); + const size_t rowSize = static_cast(iconWidth) * 4; + const size_t size = rowSize * static_cast(iconHeight); + auto ptr = std::make_unique(size); + for (uint32_t row = 0; row < iconHeight; ++row) { + const auto* src = static_cast(rgbaSurface->pixels) + + static_cast(row) * static_cast(rgbaSurface->pitch); + auto* dst = ptr.get() + static_cast(row) * rowSize; + std::memcpy(dst, src, rowSize); + } + + SDL_DestroySurface(rgbaSurface); + return Icon{ + std::move(ptr), + size, + iconWidth, + iconHeight, + }; +} + +void ImGuiEngine_AddTextures() { + auto icon = GetIcon(); + if (icon.data == nullptr || icon.width == 0 || icon.height == 0) { + ImGuiEngine::duskIcon = 0; + return; + } + + ImGuiEngine::duskIcon = aurora_imgui_add_texture(icon.width, icon.height, icon.data.get()); +} +} // namespace dusk diff --git a/src/dusk/imgui/ImGuiEngine.hpp b/src/dusk/imgui/ImGuiEngine.hpp new file mode 100644 index 0000000000..18e49c2a47 --- /dev/null +++ b/src/dusk/imgui/ImGuiEngine.hpp @@ -0,0 +1,25 @@ +#pragma once + +#include +#include "imgui.h" +#include "misc/cpp/imgui_stdlib.h" + +namespace dusk { +class ImGuiEngine { +public: + static ImFont* fontNormal; + static ImFont* fontLarge; + static ImTextureID duskIcon; +}; + +void ImGuiEngine_Initialize(float scale); +void ImGuiEngine_AddTextures(); + +struct Icon { + std::unique_ptr data; + size_t size; + uint32_t width; + uint32_t height; +}; +Icon GetIcon(); +} // namespace dusk diff --git a/src/dusk/imgui/ImGuiHeapOverlay.cpp b/src/dusk/imgui/ImGuiHeapOverlay.cpp index 588857cedb..577db12fc1 100644 --- a/src/dusk/imgui/ImGuiHeapOverlay.cpp +++ b/src/dusk/imgui/ImGuiHeapOverlay.cpp @@ -1,14 +1,25 @@ #include #include -#include "JSystem/JFramework/JFWSystem.h" -#include "JSystem/JKernel/JKRHeap.h" -#include "imgui.h" #include "ImGuiConsole.hpp" #include "ImGuiMenuTools.hpp" +#include "JSystem/JFramework/JFWSystem.h" +#include "JSystem/JKernel/JKRExpHeap.h" +#include "JSystem/JKernel/JKRHeap.h" +#include "absl/container/flat_hash_map.h" +#include "imgui.h" + +struct OpenHeapData { + bool Safe; + bool HeapCheckRan; + bool HeapCheckFailed; +}; + +static absl::flat_hash_map OpenHeapWindows; namespace dusk { static void DrawTableCore(); + void ShowHeapDetailed(JKRHeap* heap, OpenHeapData& data, bool& open); void ImGuiMenuTools::ShowHeapOverlay() { if (!ImGuiConsole::CheckMenuViewToggle(ImGuiKey_F4, m_showHeapOverlay)) { @@ -16,9 +27,13 @@ namespace dusk { } if (ImGui::Begin("Heaps", &m_showHeapOverlay)) { + for (auto& x : OpenHeapWindows) { + x.second.Safe = false; + } + if (ImGui::BeginTable( "heaps", - 5, + 6, ImGuiTableFlags_RowBg | ImGuiTableFlags_Resizable)) { DrawTableCore(); @@ -28,6 +43,19 @@ namespace dusk { } ImGui::End(); + + std::vector closeQueue; + for (auto& [heap, safe] : OpenHeapWindows) { + auto open = true; + ShowHeapDetailed(heap, safe, open); + if (!open) { + closeQueue.push_back(heap); + } + } + + for (auto toRemove : closeQueue) { + OpenHeapWindows.erase(toRemove); + } } static void DrawHeap(JKRHeap* heap, int depth = 0); @@ -44,6 +72,7 @@ namespace dusk { ImGui::TextUnformatted("Total"); ImGui::TableNextColumn(); ImGui::TextUnformatted("Type"); + ImGui::TableNextColumn(); DrawHeap(reinterpret_cast(JFWSystem::rootHeap)); } @@ -70,8 +99,15 @@ namespace dusk { static void DrawHeap(JKRHeap* heap, const int depth) { ImGui::TableNextRow(); + char idBuf[32]; + snprintf(idBuf, sizeof(idBuf), "%p", heap); + ImGui::PushID(idBuf); ImGui::TableNextColumn(); + if (OpenHeapWindows.find(heap) != OpenHeapWindows.end()) { + OpenHeapWindows[heap].Safe = true; + } + auto indentSize = depth * 16; if (indentSize != 0) ImGui::Indent(indentSize); @@ -103,9 +139,134 @@ namespace dusk { auto typeString = GetHeapType(heap); ImGui::TextUnformatted(typeString.data(), typeString.data() + 4); + ImGui::TableNextColumn(); + if (ImGui::Button("View")) { + OpenHeapWindows[heap].Safe = true; + } + const JSUTree& tree = heap->getHeapTree(); for (JSUTreeIterator iter(tree.getFirstChild()); iter != tree.getEndChild(); ++iter) { DrawHeap(*iter, depth + 1); } + + ImGui::PopID(); + } + + struct MemBlockPair { + JKRExpHeap::CMemBlock* block; + bool used; + + auto& operator->() { + return block; + } + }; + + static std::vector FindAllHeapBlocks(JKRExpHeap* heap) { + std::vector result; + + for (JKRExpHeap::CMemBlock* b = heap->getFreeHead(); b; b = b->getNextBlock()) { + result.push_back({b, false}); + } + + for (JKRExpHeap::CMemBlock* b = heap->getUsedHead(); b; b = b->getNextBlock()) { + result.push_back({b, true}); + } + + std::ranges::sort(result, [](auto a, auto b) { return a.block < b.block; }); + + return result; + } + + void ShowHeapDetailed(JKRHeap* heap, OpenHeapData& data, bool& open) { + char title[128]; + const char* name = data.Safe ? heap->getName() : "INVALID"; + snprintf(title, sizeof(title), "Heap %s##%p", heap->getName(), static_cast(heap)); + + if (!ImGui::Begin(name, &open)) { + ImGui::End(); + return; + } + + if (!data.Safe) { + ImGui::TextUnformatted("Heap no longer exists"); + ImGui::End(); + return; + } + + heap->lock(); + + ImGui::Text("Name: %s", heap->getName()); + const auto size = BytesToString(heap->getSize()); + const auto freeSize = BytesToString(heap->getFreeSize()); + ImGui::Text("Size: %08X (%s), free: %08X (%s)", heap->getSize(), size.c_str(), heap->getFreeSize(), freeSize.c_str()); + + if (ImGui::Button("Check")) { + data.HeapCheckFailed = !heap->check(); + data.HeapCheckRan = true; + } + + if (data.HeapCheckFailed) { + ImGui::SameLine(); + ImColor red = IM_COL32(0xFF, 0, 0, 0xFF); + ImGui::TextColored(red, "Heap check failed"); + } else if (data.HeapCheckRan) { + ImGui::SameLine(); + ImColor red = IM_COL32(0, 0xFF, 0, 0xFF); + ImGui::TextColored(red, "Heap check passed"); + } + + if (heap->getHeapType() == 'EXPH') { + auto expHeap = dynamic_cast(heap); + + ImGui::SeparatorText("Blocks"); + + if (ImGui::BeginTable("Blocks", 5, ImGuiTableFlags_RowBg | ImGuiTableFlags_Resizable)) { + ImGui::TableSetupColumn("Start", ImGuiTableColumnFlags_WidthFixed); + ImGui::TableSetupColumn("End", ImGuiTableColumnFlags_WidthFixed); + ImGui::TableSetupColumn("Size"); + ImGui::TableSetupColumn("Allocated", ImGuiTableColumnFlags_WidthFixed, ImGui::CalcTextSize("Allocated").x); + ImGui::TableSetupColumn("IsValid", ImGuiTableColumnFlags_WidthFixed, ImGui::CalcTextSize("IsValid").x); + ImGui::TableHeadersRow(); + + const auto blocks = FindAllHeapBlocks(expHeap); + + for (auto block : blocks) { + assert(block->getSize() != 0); + ImGui::TableNextRow(); + + if (block.used) { + ImGui::TableSetBgColor(ImGuiTableBgTarget_RowBg1, IM_COL32(0xFF, 0, 0, 0x44)); + } else { + ImGui::TableSetBgColor(ImGuiTableBgTarget_RowBg1, IM_COL32(0, 0xFF, 0, 0x44)); + } + + char bufId[32]; + snprintf(bufId, sizeof(bufId), "%p", block.block); + ImGui::PushID(bufId); + ImGui::TableNextColumn(); + ImGui::Text("%08X", (u32)((uintptr_t)block.block - (uintptr_t)expHeap->getStartAddr())); + ImGui::TableNextColumn(); + ImGui::Text("%08X", (u32)((uintptr_t)block.block + block->getSize() - (uintptr_t)expHeap->getStartAddr())); + ImGui::TableNextColumn(); + auto sizeNice = BytesToString(block->getSize()); + ImGui::Text("%08X (%s)", block->getSize(), sizeNice.c_str()); + ImGui::TableNextColumn(); + ImGui::TextUnformatted(block.used ? "True" : "False"); + ImGui::TableNextColumn(); + ImGui::TextUnformatted(block->isValid() ? "True" : "False"); + if (block->isValid() != block.used) { + ImGui::SameLine(); + ImGui::TextUnformatted("(!!!)"); + } + ImGui::PopID(); + } + + ImGui::EndTable(); + } + } + + ImGui::End(); + + heap->unlock(); } } diff --git a/src/dusk/imgui/ImGuiMapLoader.cpp b/src/dusk/imgui/ImGuiMapLoader.cpp index 89ab6aa120..428d458903 100644 --- a/src/dusk/imgui/ImGuiMapLoader.cpp +++ b/src/dusk/imgui/ImGuiMapLoader.cpp @@ -5,6 +5,7 @@ #include "ImGuiConsole.hpp" #include "ImGuiMenuTools.hpp" #include "dusk/map_loader_definitions.h" +#include "fmt/format.h" namespace dusk { void ImGuiMenuTools::ShowMapLoader() { @@ -16,7 +17,6 @@ namespace dusk { ImGuiWindowFlags_NoFocusOnAppearing | ImGuiWindowFlags_NoNav; ImGui::SetNextWindowBgAlpha(0.65f); - ImGui::SetNextWindowSizeConstraints(ImVec2(300, 0), ImVec2(FLT_MAX, FLT_MAX)); if (!ImGui::Begin("Map Loader", &m_showMapLoader, windowFlags)) { ImGui::End(); diff --git a/src/dusk/imgui/ImGuiMenuEnhancements.cpp b/src/dusk/imgui/ImGuiMenuEnhancements.cpp new file mode 100644 index 0000000000..c623a910e0 --- /dev/null +++ b/src/dusk/imgui/ImGuiMenuEnhancements.cpp @@ -0,0 +1,152 @@ +#include "imgui.h" + +#include "ImGuiMenuEnhancements.hpp" +#include "ImGuiConfig.hpp" +#include "dusk/settings.h" + +namespace dusk { + ImGuiMenuEnhancements::ImGuiMenuEnhancements() {} + + void ImGuiMenuEnhancements::draw() { + if (ImGui::BeginMenu("Enhancements")) { + if (ImGui::BeginMenu("Quality of Life")) { + config::ImGuiCheckbox("Quick Transform (R+Y)", getSettings().game.enableQuickTransform); + + config::ImGuiCheckbox("Bigger Wallets", getSettings().game.biggerWallets); + if (ImGui::IsItemHovered()) { + ImGui::SetTooltip("Wallet sizes are like in the HD version (500, 1000, 2000)"); + } + + config::ImGuiCheckbox("No Rupee Returns", getSettings().game.noReturnRupees); + if (ImGui::IsItemHovered()) { + ImGui::SetTooltip("Always collect Rupees even if your Wallet is too full"); + } + + config::ImGuiCheckbox("Disable Rupee Cutscenes", getSettings().game.disableRupeeCutscenes); + if (ImGui::IsItemHovered()) { + ImGui::SetTooltip("Rupees won't play cutscenes after you've collected them the first time"); + } + + config::ImGuiCheckbox("No Sword Recoil", getSettings().game.noSwordRecoil); + if (ImGui::IsItemHovered()) { + ImGui::SetTooltip("Link won't recoil when his sword hits walls"); + } + + config::ImGuiCheckbox("Faster Climbing", getSettings().game.fastClimbing); + if (ImGui::IsItemHovered()) { + ImGui::SetTooltip("Quicker climbing on ladders and vines like the HD version"); + } + + config::ImGuiCheckbox("No Climbing Miss Animation", getSettings().game.noMissClimbing); + if (ImGui::IsItemHovered()) { + ImGui::SetTooltip("Prevents Link from playing a struggle animation\n" + "when using the Clawshot on vines at a weird angle"); + } + + config::ImGuiCheckbox("Faster Tears of Light", getSettings().game.fastTears); + if (ImGui::IsItemHovered()) { + ImGui::SetTooltip("Tears of Light dropped by Shadow Insects pop out faster like the HD version"); + } + + config::ImGuiCheckbox("Hide TV Settings Screen", getSettings().game.hideTvSettingsScreen); + if (ImGui::IsItemHovered()) { + ImGui::SetTooltip("Hides the TV calibration screen shown when loading a save"); + } + + config::ImGuiCheckbox("Instant Saves", getSettings().game.instantSaves); + if (ImGui::IsItemHovered()) { + ImGui::SetTooltip("Skip the delay when writing to the Memory Card"); + } + + ImGui::EndMenu(); + } + + if (ImGui::BeginMenu("Preferences")) { + config::ImGuiCheckbox("Mirror Mode", getSettings().game.enableMirrorMode); + if (ImGui::IsItemHovered()) { + ImGui::SetTooltip("Mirrors the world, matching the Wii version of the game"); + } + + config::ImGuiCheckbox("Invert Camera X Axis", getSettings().game.invertCameraXAxis); + + ImGui::EndMenu(); + } + + if (ImGui::BeginMenu("Graphics")) { + config::ImGuiCheckbox("Native Bloom", getSettings().game.enableBloom); + + config::ImGuiCheckbox("Water Projection Offset", getSettings().game.useWaterProjectionOffset); + if (ImGui::IsItemHovered()) { + ImGui::SetTooltip("Adds GC-specific -0.01 transS offset\n" + "that causes ~6px ghost artifacts in water reflections"); + } + + ImGui::EndMenu(); + } + + if (ImGui::BeginMenu("Audio")) { + config::ImGuiCheckbox("No Low HP Sound", getSettings().game.noLowHpSound); + if (ImGui::IsItemHovered()) { + ImGui::SetTooltip("Disable the beeping sound when having low health"); + } + + config::ImGuiCheckbox("Non-Stop Midna's Lament", getSettings().game.midnasLamentNonStop); + if (ImGui::IsItemHovered()) { + ImGui::SetTooltip("Prevents enemy music while Midna's Lament is playing"); + } + + ImGui::EndMenu(); + } + + if (ImGui::BeginMenu("Cheats")) { + config::ImGuiCheckbox("Fast Iron Boots", getSettings().game.enableFastIronBoots); + + config::ImGuiCheckbox("Can Transform Anywhere", getSettings().game.canTransformAnywhere); + if (ImGui::IsItemHovered()) { + ImGui::SetTooltip("Allows you to transform even if NPCs are looking"); + } + + config::ImGuiCheckbox("Fast Spinner", getSettings().game.fastSpinner); + if (ImGui::IsItemHovered()) { + ImGui::SetTooltip("Speeds up Spinner movement when holding R."); + } + + config::ImGuiCheckbox("Free Magic Armor", getSettings().game.freeMagicArmor); + if (ImGui::IsItemHovered()) { + ImGui::SetTooltip("Makes the magic armor work without rupees."); + } + + ImGui::EndMenu(); + } + + if (ImGui::BeginMenu("Difficulty")) { + config::ImGuiSliderInt("Damage Multiplier", getSettings().game.damageMultiplier, 1, 8, "x%d"); + + config::ImGuiCheckbox("Instant Death", getSettings().game.instantDeath); + if (ImGui::IsItemHovered()) { + ImGui::SetTooltip("Any hit will instantly kill you"); + } + + ImGui::EndMenu(); + } + + if (ImGui::BeginMenu("Technical")) { + config::ImGuiCheckbox("Restore Wii 1.0 Glitches", getSettings().game.restoreWiiGlitches); + if (ImGui::IsItemHovered()) { + ImGui::SetTooltip("Restores patched glitches from Wii USA 1.0,\n" + "the first released version"); + } + + ImGui::EndMenu(); + } + + if (ImGui::BeginMenu("Tools")) { + config::ImGuiCheckbox("Enable Turbo Key", getSettings().game.enableTurboKeybind); + + ImGui::EndMenu(); + } + + ImGui::EndMenu(); + } + } +} diff --git a/src/dusk/imgui/ImGuiMenuEnhancements.hpp b/src/dusk/imgui/ImGuiMenuEnhancements.hpp new file mode 100644 index 0000000000..f40baaad65 --- /dev/null +++ b/src/dusk/imgui/ImGuiMenuEnhancements.hpp @@ -0,0 +1,18 @@ +#ifndef DUSK_IMGUI_MENUENHANCEMENTS_HPP +#define DUSK_IMGUI_MENUENHANCEMENTS_HPP + +#include +#include +#include + +#include "imgui.h" + +namespace dusk { + class ImGuiMenuEnhancements { + public: + ImGuiMenuEnhancements(); + void draw(); + }; +} + +#endif // DUSK_IMGUI_MENUENHANCEMENTS_HPP diff --git a/src/dusk/imgui/ImGuiMenuGame.cpp b/src/dusk/imgui/ImGuiMenuGame.cpp index 22225eb9dc..925f4875d9 100644 --- a/src/dusk/imgui/ImGuiMenuGame.cpp +++ b/src/dusk/imgui/ImGuiMenuGame.cpp @@ -1,57 +1,102 @@ #include "fmt/format.h" #include "imgui.h" -#include "aurora/gfx.h" #include "ImGuiConsole.hpp" #include "ImGuiMenuGame.hpp" +#include "ImGuiConfig.hpp" #include #include "JSystem/JUtility/JUTGamePad.h" +#include "dusk/audio/DuskAudioSystem.h" +#include "dusk/audio/DuskDsp.hpp" +#include "dusk/dusk.h" +#include "dusk/hotkeys.h" +#include "dusk/settings.h" #include "m_Do/m_Do_controller_pad.h" -#include "m_Do/m_Do_audio.h" +#include "m_Do/m_Do_graphic.h" + +#include #include namespace dusk { + void ImGuiMenuGame::ToggleFullscreen() { + getSettings().video.enableFullscreen.setValue(!getSettings().video.enableFullscreen); + VISetWindowFullscreen(getSettings().video.enableFullscreen); + config::Save(); + } + ImGuiMenuGame::ImGuiMenuGame() {} void ImGuiMenuGame::draw() { if (ImGui::BeginMenu("Game")) { - if (ImGui::MenuItem("Reset", "Ctrl+R")) { + if (ImGui::MenuItem("Reset", hotkeys::DO_RESET)) { JUTGamePad::C3ButtonReset::sResetSwitchPushing = true; } ImGui::Separator(); if (ImGui::BeginMenu("Graphics")) { - ImGui::Checkbox("Native Bloom", &m_graphicsSettings.m_enableBloom); - ImGui::Checkbox("Water Projection Offset", &m_graphicsSettings.m_waterProjectionOffset); - if (ImGui::IsItemHovered()) { - ImGui::SetTooltip("Adds GC-specific -0.01 transS offset\n" - "that causes ~6px ghost artifacts in water reflections"); + if (ImGui::MenuItem("Toggle Fullscreen", hotkeys::TOGGLE_FULLSCREEN)) { + ToggleFullscreen(); } + + if (ImGui::MenuItem("Default Window Size")) { + getSettings().video.enableFullscreen.setValue(false); + VISetWindowFullscreen(false); + VISetWindowSize(FB_WIDTH * 2, FB_HEIGHT * 2); + VICenterWindow(); + } + + bool vsync = getSettings().video.enableVsync; + if (ImGui::Checkbox("Enable Vsync", &vsync)) { + getSettings().video.enableVsync.setValue(vsync); + aurora_enable_vsync(vsync); + config::Save(); + } + + bool lockAspect = getSettings().video.lockAspectRatio; + if (ImGui::Checkbox("Force 4:3 Aspect Ratio", &lockAspect)) { + getSettings().video.lockAspectRatio.setValue(lockAspect); + + if (lockAspect) { + VILockAspectRatio(defaultAspectRatioW, defaultAspectRatioH); + } else { + VIUnlockAspectRatio(); + } + + config::Save(); + } + ImGui::EndMenu(); } if (ImGui::BeginMenu("Audio")) { ImGui::Text("Master Volume"); - ImGui::SliderFloat("##m_masterVolume", &m_audioSettings.m_masterVolume, 0.0f, 1.0f, ""); + if (config::ImGuiSliderInt("##masterVolume", getSettings().audio.masterVolume, 0, 100)) { + dusk::audio::SetMasterVolume(getSettings().audio.masterVolume / 100.0f); + } + if (config::ImGuiCheckbox("Enable Reverb", getSettings().audio.enableReverb)) { + dusk::audio::SetEnableReverb(getSettings().audio.enableReverb); + } + /* + // TODO: Implement additional settings ImGui::Text("Main Music Volume"); - ImGui::SliderFloat("##m_mainMusicVolume", &m_audioSettings.m_mainMusicVolume, 0.0f, 1.0f, ""); + ImGui::SliderFloat("##mainMusicVolume", &getSettings().audio.mainMusicVolume, 0, 100); ImGui::Text("Sub Music Volume"); - ImGui::SliderFloat("##m_subMusicVolume", &m_audioSettings.m_subMusicVolume, 0.0f, 1.0f, ""); + ImGui::SliderFloat("##subMusicVolume", &getSettings().audio.subMusicVolume, 0, 100); ImGui::Text("Sound Effects Volume"); - ImGui::SliderFloat("##m_soundEffectsVolume", &m_audioSettings.m_soundEffectsVolume, 0.0f, 1.0f, ""); + ImGui::SliderFloat("##soundEffectsVolume", &getSettings().audio.soundEffectsVolume, 0, 100); ImGui::Text("Fanfare Volume"); - ImGui::SliderFloat("##m_fanfareVolume", &m_audioSettings.m_fanfareVolume, 0.0f, 1.0f, ""); + ImGui::SliderFloat("##fanfareVolume", &getSettings().audio.fanfareVolume, 0, 100); Z2AudioMgr* audioMgr = Z2AudioMgr::getInterface(); if (audioMgr != nullptr) { - // TODO: actually apply volume settings } + */ ImGui::EndMenu(); } @@ -68,20 +113,17 @@ namespace dusk { windowInputViewer(); windowControllerConfig(); - - if ((ImGui::IsKeyDown(ImGuiKey_LeftCtrl) || ImGui::IsKeyDown(ImGuiKey_RightCtrl)) && ImGui::IsKeyPressed(ImGuiKey_R)) { - JUTGamePad::C3ButtonReset::sResetSwitchPushing = true; - } } static void drawVirtualStick(const char* id, const ImVec2& stick) { - ImGui::SetCursorPos(ImVec2(ImGui::GetCursorPos().x + 5, ImGui::GetCursorPos().y)); + float scale = ImGuiScale(); + ImGui::SetCursorPos(ImVec2(ImGui::GetCursorPos().x + 45 * scale, ImGui::GetCursorPos().y + 10)); - ImGui::BeginChild(id, ImVec2(80, 80)); + ImGui::BeginChild(id, ImVec2(80 * scale, 80 * scale), 0, ImGuiWindowFlags_NoBackground); ImDrawList* dl = ImGui::GetWindowDrawList(); ImVec2 p = ImGui::GetCursorScreenPos(); - float radius = ImGui::GetCurrentContext()->CurrentDpiScale * 30.0f; + float radius = 30.0f * scale; ImVec2 pos = ImVec2(p.x + radius, p.y + radius); constexpr ImU32 stickGray = IM_COL32(150, 150, 150, 255); @@ -89,7 +131,7 @@ namespace dusk { constexpr ImU32 red = IM_COL32(230, 0, 0, 255); dl->AddCircleFilled(pos, radius, stickGray, 8); - dl->AddCircleFilled(ImVec2(pos.x + stick.x * (radius), pos.y + -stick.y * (radius)), 3, red); + dl->AddCircleFilled(ImVec2(pos.x + stick.x * (radius), pos.y + -stick.y * (radius)), 3 * scale, red); ImGui::EndChild(); } @@ -155,6 +197,10 @@ namespace dusk { // clang-format on static const char* GetNameForGamepadButton(SDL_Gamepad* gamepad, u32 buttonUntyped) { + if (buttonUntyped == PAD_NATIVE_BUTTON_INVALID) { + return "Not bound"; + } + auto button = static_cast(buttonUntyped); auto label = SDL_GetGamepadButtonLabel(gamepad, button); @@ -210,23 +256,44 @@ namespace dusk { return; } - // if pending for an input mapping, check to set new input - if (m_controllerConfig.m_pendingMapping != nullptr) { + // if pending for a button mapping, check to set new input + if (m_controllerConfig.m_pendingButtonMapping != nullptr) { s32 nativeButton = PADGetNativeButtonPressed(m_controllerConfig.m_pendingPort); if (nativeButton != -1) { - m_controllerConfig.m_pendingMapping->nativeButton = nativeButton; - m_controllerConfig.m_pendingMapping = nullptr; + m_controllerConfig.m_pendingButtonMapping->nativeButton = nativeButton; + m_controllerConfig.m_pendingButtonMapping = nullptr; m_controllerConfig.m_pendingPort = -1; PADBlockInput(false); } } + // if pending for an axis mapping, check to set new input + if (m_controllerConfig.m_pendingAxisMapping != nullptr) { + auto nativeAxis = PADGetNativeAxisPulled(m_controllerConfig.m_pendingPort); + if (nativeAxis.nativeAxis != -1) { + m_controllerConfig.m_pendingAxisMapping->nativeAxis = nativeAxis; + m_controllerConfig.m_pendingAxisMapping->nativeButton = -1; + m_controllerConfig.m_pendingAxisMapping = nullptr; + m_controllerConfig.m_pendingPort = -1; + PADBlockInput(false); + } else { + auto nativeButton = PADGetNativeButtonPressed(m_controllerConfig.m_pendingPort); + if (nativeButton != -1) { + m_controllerConfig.m_pendingAxisMapping->nativeAxis = {-1, AXIS_SIGN_POSITIVE}; + m_controllerConfig.m_pendingAxisMapping->nativeButton = nativeButton; + m_controllerConfig.m_pendingAxisMapping = nullptr; + m_controllerConfig.m_pendingPort = -1; + PADBlockInput(false); + } + } + } + + float scale = ImGuiScale(); ImGuiWindowFlags windowFlags = ImGuiWindowFlags_NoResize | ImGuiWindowFlags_AlwaysAutoResize; ImGui::SetNextWindowBgAlpha(0.65f); - ImGui::SetNextWindowSizeConstraints(ImVec2(850, 400), ImVec2(850, 400)); if (!ImGui::Begin("Controller Config", &m_showControllerConfig, windowFlags)) { ImGui::End(); @@ -244,10 +311,12 @@ namespace dusk { ImGui::EndTabBar(); // if tab is changed while waiting for input, cancel pending - if (m_controllerConfig.m_pendingMapping != nullptr && + if ((m_controllerConfig.m_pendingButtonMapping != nullptr || + m_controllerConfig.m_pendingAxisMapping != nullptr) && m_controllerConfig.m_pendingPort != m_controllerConfig.m_selectedPort) { - m_controllerConfig.m_pendingMapping = nullptr; + m_controllerConfig.m_pendingButtonMapping = nullptr; + m_controllerConfig.m_pendingAxisMapping = nullptr; m_controllerConfig.m_pendingPort = -1; PADBlockInput(false); } @@ -270,6 +339,7 @@ namespace dusk { // controller selection combo box bool changedController = false; int changedControllerIndex = 0; + ImGui::SetNextItemWidth(400.0f * scale); if (ImGui::BeginCombo("##ControllerDeviceList", currentName.c_str())) { for (int i = 0; const auto& name : controllerList) { if (ImGui::Selectable(name.c_str(), currentName == name)) { @@ -305,35 +375,39 @@ namespace dusk { } // buttons panel - constexpr float buttonSize = 40; + const float uiButtonSize = 40 * scale; - ImGuiBeginGroupPanel("Buttons", ImVec2(150, 20)); + ImGuiBeginGroupPanel("Buttons", ImVec2(150 * scale, 20 * scale)); SDL_Gamepad* gamepad = PADGetSDLGamepadForIndex(PADGetIndexForPort(m_controllerConfig.m_selectedPort)); u32 buttonCount; - PADButtonMapping* mappingList = PADGetButtonMappings(m_controllerConfig.m_selectedPort, &buttonCount); - if (mappingList != nullptr) { + PADButtonMapping* btnMappingList = PADGetButtonMappings(m_controllerConfig.m_selectedPort, &buttonCount); + if (btnMappingList != nullptr) { for (int i = 0; i < buttonCount; i++) { - const char* btnName = PADGetButtonName(mappingList[i].padButton); + const char* btnName = PADGetButtonName(btnMappingList[i].padButton); ImVec2 len = ImGui::CalcTextSize(btnName); ImVec2 pos = ImGui::GetCursorPos(); ImGui::SetCursorPosY(pos.y + len.y / 4); - ImGui::SetCursorPosX(pos.x + abs(len.x - buttonSize)); + ImGui::SetCursorPosX(pos.x + abs(len.x - uiButtonSize)); ImGui::Text("%s", btnName); ImGui::SameLine(); ImGui::SetCursorPosY(pos.y); - bool pressed = ImGui::Button(m_controllerConfig.m_isReading && m_controllerConfig.m_pendingMapping == &mappingList[i] - ? fmt::format("Press a Key...##{}", btnName).c_str() - : fmt::format("{0}##-{1}", GetNameForGamepadButton(gamepad, mappingList[i].nativeButton), i).c_str(), - ImVec2(100.0f, 20.0f)); + std::string dispName; + if (m_controllerConfig.m_isReading && m_controllerConfig.m_pendingButtonMapping == &btnMappingList[i]) { + dispName = fmt::format("Press a Key...##{}", btnName); + } else { + dispName = fmt::format("{0}##-{1}", GetNameForGamepadButton(gamepad, btnMappingList[i].nativeButton), i); + } + bool pressed = ImGui::Button(dispName.c_str(), + ImVec2(100.0f * scale, 20.0f * scale)); if (pressed) { m_controllerConfig.m_isReading = true; m_controllerConfig.m_pendingPort = m_controllerConfig.m_selectedPort; - m_controllerConfig.m_pendingMapping = &mappingList[i]; + m_controllerConfig.m_pendingButtonMapping = &btnMappingList[i]; PADBlockInput(true); } } @@ -342,39 +416,120 @@ namespace dusk { ImGuiEndGroupPanel(); ImGui::SameLine(); - int port = m_controllerConfig.m_selectedPort; + uint32_t axisCount; + PADAxisMapping* axisMappingList = PADGetAxisMappings(m_controllerConfig.m_selectedPort, &axisCount); - const char* stickDirections[] = { - "Up", - "Down", - "Left", - "Right", - }; + ImGuiBeginGroupPanel("Analog Triggers", ImVec2(150 * scale, 20 * scale)); + + PADAxis triggers[] = {PAD_AXIS_TRIGGER_L, PAD_AXIS_TRIGGER_R}; + if (axisMappingList != nullptr) { + for (PADAxis trigger : triggers) { + const char* axisName = PADGetAxisName(axisMappingList[trigger].padAxis); + ImVec2 len = ImGui::CalcTextSize(axisName); + ImVec2 pos = ImGui::GetCursorPos(); + + ImGui::SetCursorPosY(pos.y + len.y / 4); + ImGui::SetCursorPosX(pos.x + abs(len.x - uiButtonSize)); + ImGui::Text("%s", axisName); + ImGui::SameLine(); + + ImGui::SetCursorPosY(pos.y); + + std::string dispName; + if (m_controllerConfig.m_isReading && m_controllerConfig.m_pendingAxisMapping == &axisMappingList[trigger]) { + dispName = fmt::format("Press a Key...##{}", axisName); + } else { + dispName = fmt::format("{0}##-{1}", PADGetNativeAxisName(axisMappingList[trigger].nativeAxis), trigger); + } + bool pressed = ImGui::Button(dispName.c_str(), + ImVec2(100.0f * scale, 20.0f * scale)); + + if (pressed) { + m_controllerConfig.m_isReading = true; + m_controllerConfig.m_pendingPort = m_controllerConfig.m_selectedPort; + m_controllerConfig.m_pendingAxisMapping = &axisMappingList[trigger]; + PADBlockInput(true); + } + } + } + + int port = m_controllerConfig.m_selectedPort; + PADDeadZones* deadZones = PADGetDeadZones(port); + + if (deadZones != nullptr) { + ImGui::Text("L Threshold"); + ImGui::SameLine(); + { + float tmp = static_cast(deadZones->leftTriggerActivationZone * 100.f) / 32767.f; + if (ImGui::DragFloat("##LThreshold", &tmp, 0.5f, 0.f, 100.f, "%.3f%%")) { + deadZones->leftTriggerActivationZone = static_cast((tmp / 100.f) * 32767); + } + } + } + + if (deadZones != nullptr) { + ImGui::Text("R Threshold"); + ImGui::SameLine(); + { + float tmp = static_cast(deadZones->rightTriggerActivationZone * 100.f) / 32767.f; + if (ImGui::DragFloat("##RThreshold", &tmp, 0.5f, 0.f, 100.f, "%.3f%%")) { + deadZones->rightTriggerActivationZone = static_cast((tmp / 100.f) * 32767); + } + } + } + + ImGuiEndGroupPanel(); + ImGui::SameLine(); // main stick panel - ImGuiBeginGroupPanel("Control Stick", ImVec2(150, 20)); + ImGuiBeginGroupPanel("Control Stick", ImVec2(150 * scale, 20 * scale)); drawVirtualStick("##mainStick", ImVec2{ mDoCPd_c::getStickX(port), mDoCPd_c::getStickY(port) }); - { - for (int i = 0; i < 4; i++) { - const char* label = stickDirections[i]; + if (axisMappingList != nullptr) { + const PADAxis lStickAxes[] = {PAD_AXIS_LEFT_Y_POS, PAD_AXIS_LEFT_Y_NEG, PAD_AXIS_LEFT_X_NEG, PAD_AXIS_LEFT_X_POS}; + for (auto axis : lStickAxes) { + const char* label = PADGetAxisDirectionLabel(axis); ImVec2 len = ImGui::CalcTextSize(label); ImVec2 pos = ImGui::GetCursorPos(); ImGui::SetCursorPosY(pos.y + len.y / 4); - ImGui::SetCursorPosX(pos.x + abs(len.x - buttonSize)); + ImGui::SetCursorPosX(pos.x + abs(len.x - uiButtonSize)); ImGui::Text("%s", label); ImGui::SameLine(); ImGui::SetCursorPosY(pos.y); - bool pressed = ImGui::Button(fmt::format("Temp##{}", label).c_str(), ImVec2(100.0f, 20.0f)); + std::string dispName; + if (m_controllerConfig.m_isReading && m_controllerConfig.m_pendingAxisMapping == &axisMappingList[axis]) { + dispName = fmt::format("Press a Key...##{}", label); + } else { + if (axisMappingList[axis].nativeAxis.nativeAxis != -1) { + const char* signStr; + if (axis == PAD_AXIS_TRIGGER_L || axis == PAD_AXIS_TRIGGER_R) { + signStr = ""; + } else if (axisMappingList[axis].nativeAxis.sign == AXIS_SIGN_POSITIVE) { + signStr = "+"; + } else { + signStr = "-"; + } + dispName = fmt::format("{0}{1}##-{2}", PADGetNativeAxisName(axisMappingList[axis].nativeAxis), signStr, axis); + } else { + assert(axisMappingList[axis].nativeButton != -1); + dispName = fmt::format("{0}##-{1}", PADGetNativeButtonName(axisMappingList[axis].nativeButton), axis); + } + } + bool pressed = ImGui::Button(dispName.c_str(), ImVec2(100.0f * scale, 20.0f * scale)); + + if (pressed) { + m_controllerConfig.m_isReading = true; + m_controllerConfig.m_pendingPort = m_controllerConfig.m_selectedPort; + m_controllerConfig.m_pendingAxisMapping = &axisMappingList[axis]; + PADBlockInput(true); + } } } - PADDeadZones* deadZones = PADGetDeadZones(port); - if (deadZones != nullptr) { ImGui::Text("Dead Zone"); { @@ -389,24 +544,51 @@ namespace dusk { ImGui::SameLine(); // sub stick panel - ImGuiBeginGroupPanel("C Stick", ImVec2(150, 20)); + ImGuiBeginGroupPanel("C Stick", ImVec2(150 * scale, 20 * scale)); drawVirtualStick("##subStick", ImVec2{ mDoCPd_c::getSubStickX(port), mDoCPd_c::getSubStickY(port) }); - { - for (int i = 0; i < 4; i++) { - const char* label = stickDirections[i]; + if (axisMappingList != nullptr) { + const PADAxis rStickAxes[] = {PAD_AXIS_RIGHT_Y_POS, PAD_AXIS_RIGHT_Y_NEG, PAD_AXIS_RIGHT_X_NEG, PAD_AXIS_RIGHT_X_POS}; + for (auto axis : rStickAxes) { + const char* label = PADGetAxisDirectionLabel(axisMappingList[axis].padAxis); ImVec2 len = ImGui::CalcTextSize(label); ImVec2 pos = ImGui::GetCursorPos(); ImGui::SetCursorPosY(pos.y + len.y / 4); - ImGui::SetCursorPosX(pos.x + abs(len.x - buttonSize)); + ImGui::SetCursorPosX(pos.x + abs(len.x - uiButtonSize)); ImGui::Text("%s", label); ImGui::SameLine(); ImGui::SetCursorPosY(pos.y); - bool pressed = ImGui::Button(fmt::format("Temp##sub{}", label).c_str(), ImVec2(100.0f, 20.0f)); + std::string dispName; + if (m_controllerConfig.m_isReading && m_controllerConfig.m_pendingAxisMapping == &axisMappingList[axis]) { + dispName = fmt::format("Press a Key...##sub{}", label); + } else { + if (axisMappingList[axis].nativeAxis.nativeAxis != -1) { + const char* signStr; + if (axis == PAD_AXIS_TRIGGER_L || axis == PAD_AXIS_TRIGGER_R) { + signStr = ""; + } else if (axisMappingList[axis].nativeAxis.sign == AXIS_SIGN_POSITIVE) { + signStr = "+"; + } else { + signStr = "-"; + } + dispName = fmt::format("{0}{1}##-{2}", PADGetNativeAxisName(axisMappingList[axis].nativeAxis), signStr, axis); + } else { + assert(axisMappingList[axis].nativeButton != -1); + dispName = fmt::format("{0}##-{1}", PADGetNativeButtonName(axisMappingList[axis].nativeButton), axis); + } + } + bool pressed = ImGui::Button(fmt::format("{0}##sub{1}", dispName, label).c_str(), ImVec2(100.0f * scale, 20.0f * scale)); + + if (pressed) { + m_controllerConfig.m_isReading = true; + m_controllerConfig.m_pendingPort = m_controllerConfig.m_selectedPort; + m_controllerConfig.m_pendingAxisMapping = &axisMappingList[axis]; + PADBlockInput(true); + } } } @@ -423,34 +605,8 @@ namespace dusk { ImGuiEndGroupPanel(); ImGui::SameLine(); - // Triggers Panel - ImGuiBeginGroupPanel("Triggers", ImVec2(150, 20)); - - if (deadZones != nullptr) { - ImGui::Text("L Threshold"); - { - float tmp = static_cast(deadZones->leftTriggerActivationZone * 100.f) / 32767.f; - if (ImGui::DragFloat("##LThreshold", &tmp, 0.5f, 0.f, 100.f, "%.3f%%")) { - deadZones->leftTriggerActivationZone = static_cast((tmp / 100.f) * 32767); - } - } - } - - if (deadZones != nullptr) { - ImGui::Text("R Threshold"); - { - float tmp = static_cast(deadZones->rightTriggerActivationZone * 100.f) / 32767.f; - if (ImGui::DragFloat("##RThreshold", &tmp, 0.5f, 0.f, 100.f, "%.3f%%")) { - deadZones->rightTriggerActivationZone = static_cast((tmp / 100.f) * 32767); - } - } - } - - ImGuiEndGroupPanel(); - ImGui::SameLine(); - // Options panel - ImGuiBeginGroupPanel("Options", ImVec2(150, 20)); + ImGuiBeginGroupPanel("Options", ImVec2(150 * scale, 20 * scale)); if (deadZones != nullptr) { ImGui::Checkbox("Enable Dead Zones", &deadZones->useDeadzones); diff --git a/src/dusk/imgui/ImGuiMenuGame.hpp b/src/dusk/imgui/ImGuiMenuGame.hpp index 35e7e397aa..77e5952d1a 100644 --- a/src/dusk/imgui/ImGuiMenuGame.hpp +++ b/src/dusk/imgui/ImGuiMenuGame.hpp @@ -12,33 +12,21 @@ namespace dusk { public: ImGuiMenuGame(); void draw(); - bool isBloomEnabled() { return m_graphicsSettings.m_enableBloom; } - bool isWaterProjectionOffsetEnabled() { return m_graphicsSettings.m_waterProjectionOffset; } void windowInputViewer(); void windowControllerConfig(); - private: - struct { - float m_masterVolume = 1.0f; - float m_mainMusicVolume = 1.0f; - float m_subMusicVolume = 1.0f; - float m_soundEffectsVolume = 1.0f; - float m_fanfareVolume = 1.0f; - } m_audioSettings; + static void ToggleFullscreen(); + private: struct { int m_selectedPort = 0; bool m_isReading = false; - PADButtonMapping* m_pendingMapping = nullptr; + PADButtonMapping* m_pendingButtonMapping = nullptr; + PADAxisMapping* m_pendingAxisMapping = nullptr; int m_pendingPort = -1; } m_controllerConfig; - struct { - bool m_enableBloom = 1; - bool m_waterProjectionOffset = false; - } m_graphicsSettings; - bool m_showControllerConfig = false; bool m_showInputViewer = false; diff --git a/src/dusk/imgui/ImGuiMenuTools.cpp b/src/dusk/imgui/ImGuiMenuTools.cpp index e84dbc1f08..44e92a4082 100644 --- a/src/dusk/imgui/ImGuiMenuTools.cpp +++ b/src/dusk/imgui/ImGuiMenuTools.cpp @@ -2,13 +2,16 @@ #include "imgui.h" #include "aurora/gfx.h" +#include "dusk/hotkeys.h" +#include "dusk/settings.h" #include "ImGuiConsole.hpp" #include "ImGuiMenuTools.hpp" -#include "m_Do/m_Do_main.h" -#include "d/d_com_inf_game.h" #include "d/actor/d_a_alink.h" #include "d/actor/d_a_horse.h" +#include "d/d_com_inf_game.h" +#include "dusk/dusk.h" +#include "m_Do/m_Do_main.h" namespace dusk { ImGuiMenuTools::ImGuiMenuTools() {} @@ -16,35 +19,37 @@ namespace dusk { void ImGuiMenuTools::draw() { bool isToggleDevelopmentMode = false; - if (ImGui::BeginMenu("Tools")) { + if (ImGui::BeginMenu("Debug")) { if (ImGui::Checkbox("Development Mode", &m_isDevelopmentMode)) { isToggleDevelopmentMode = true; } - + ImGui::Separator(); + auto& collisionView = getTransientSettings().collisionView; if (ImGui::BeginMenu("Collision View")) { - ImGui::Checkbox("Enable Terrain view", &m_collisionViewSettings.m_enableTerrainView); - // can't use wireframe atm because aurora doesn't support GX_LINES - //ImGui::Checkbox("Enable wireframe view", &m_collisionViewSettings.m_enableWireframe); - ImGui::SliderFloat("Opacity##terrain", &m_collisionViewSettings.m_terrainViewOpacity, 0.0f, 100.0f); - ImGui::SliderFloat("Draw Range", &m_collisionViewSettings.m_drawRange, 0.0f, 1000.0f); + ImGui::Checkbox("Enable Terrain view", &collisionView.enableTerrainView); + ImGui::Checkbox("Enable wireframe view", &collisionView.enableWireframe); + ImGui::SliderFloat("Opacity##terrain", &collisionView.terrainViewOpacity, 0.0f, 100.0f); + ImGui::SliderFloat("Draw Range", &collisionView.drawRange, 0.0f, 1000.0f); ImGui::Separator(); - ImGui::Checkbox("Enable Attack Collider view", &m_collisionViewSettings.m_enableAtView); - ImGui::Checkbox("Enable Target Collider view", &m_collisionViewSettings.m_enableTgView); - ImGui::Checkbox("Enable Push Collider view", &m_collisionViewSettings.m_enableCoView); - ImGui::SliderFloat("Opacity##colliders", &m_collisionViewSettings.m_colliderViewOpacity, 0.0f, 100.0f); + ImGui::Checkbox("Enable Attack Collider view", &collisionView.enableAtView); + ImGui::Checkbox("Enable Target Collider view", &collisionView.enableTgView); + ImGui::Checkbox("Enable Push Collider view", &collisionView.enableCoView); + ImGui::SliderFloat("Opacity##colliders", &collisionView.colliderViewOpacity, 0.0f, 100.0f); ImGui::EndMenu(); } - ImGui::MenuItem("Process Management", "F2", &m_showProcessManagement); - ImGui::MenuItem("Debug Overlay", "F3", &m_showDebugOverlay); - ImGui::MenuItem("Heap Viewer", "F4", &m_showHeapOverlay); - ImGui::MenuItem("Stub Log", "F5", &m_showStubLog); - ImGui::MenuItem("Debug Camera", "F6", &m_showCameraOverlay); + ImGui::MenuItem("Process Management", hotkeys::SHOW_PROCESS_MANAGEMENT, &m_showProcessManagement); + ImGui::MenuItem("Debug Overlay", hotkeys::SHOW_DEBUG_OVERLAY, &m_showDebugOverlay); + ImGui::MenuItem("Heap Viewer", hotkeys::SHOW_HEAP_VIEWER, &m_showHeapOverlay); + ImGui::MenuItem("Stub Log", hotkeys::SHOW_STUB_LOG, &m_showStubLog); + ImGui::MenuItem("Debug Camera", hotkeys::SHOW_CAMERA_DEBUG, &m_showCameraOverlay); ImGui::MenuItem("Map Loader", nullptr, &m_showMapLoader); ImGui::MenuItem("Player Info", nullptr, &m_showPlayerInfo); ImGui::MenuItem("Save Editor", nullptr, &m_showSaveEditor); + ImGui::MenuItem("Audio Debug", hotkeys::SHOW_AUDIO_DEBUG, &m_showAudioDebug); + ImGui::MenuItem("OSReport Force", nullptr, &OSReportReallyForceEnable); ImGui::EndMenu(); } @@ -59,6 +64,7 @@ namespace dusk { ShowStubLog(); ShowMapLoader(); ShowPlayerInfo(); + ShowAudioDebug(); if (m_showSaveEditor) { m_saveEditor.draw(m_showSaveEditor); @@ -91,6 +97,7 @@ namespace dusk { hasPrevious = true; ImGuiStringViewText(fmt::format(FMT_STRING("FPS: {:.2f}\n"), io.Framerate)); + ImGuiStringViewText(fmt::format(FMT_STRING("Frame usage: {:.1f}%\n"), frameUsagePct)); if (hasPrevious) { ImGui::Separator(); @@ -104,28 +111,34 @@ namespace dusk { } hasPrevious = true; - AuroraStats const* stats = aurora_get_stats(); + const auto& stats = lastFrameAuroraStats; ImGuiStringViewText( - fmt::format(FMT_STRING("Queued pipelines: {}\n"), stats->queuedPipelines)); + fmt::format(FMT_STRING("Queued pipelines: {}\n"), stats.queuedPipelines)); ImGuiStringViewText( - fmt::format(FMT_STRING("Done pipelines: {}\n"), stats->createdPipelines)); + fmt::format(FMT_STRING("Done pipelines: {}\n"), stats.createdPipelines)); ImGuiStringViewText( - fmt::format(FMT_STRING("Draw call count: {}\n"), stats->drawCallCount)); + fmt::format(FMT_STRING("Draw call count: {}\n"), stats.drawCallCount)); ImGuiStringViewText(fmt::format(FMT_STRING("Merged draw calls: {}\n"), - stats->mergedDrawCallCount)); + stats.mergedDrawCallCount)); ImGuiStringViewText(fmt::format(FMT_STRING("Vertex size: {}\n"), - BytesToString(stats->lastVertSize))); + BytesToString(stats.lastVertSize))); ImGuiStringViewText(fmt::format(FMT_STRING("Uniform size: {}\n"), - BytesToString(stats->lastUniformSize))); + BytesToString(stats.lastUniformSize))); ImGuiStringViewText(fmt::format(FMT_STRING("Index size: {}\n"), - BytesToString(stats->lastIndexSize))); + BytesToString(stats.lastIndexSize))); ImGuiStringViewText(fmt::format(FMT_STRING("Storage size: {}\n"), - BytesToString(stats->lastStorageSize))); + BytesToString(stats.lastStorageSize))); + ImGuiStringViewText(fmt::format(FMT_STRING("Tex upload size: {}\n"), + BytesToString(stats.lastTextureUploadSize))); ImGuiStringViewText(fmt::format( FMT_STRING("Total: {}\n"), - BytesToString(stats->lastVertSize + stats->lastUniformSize + - stats->lastIndexSize + stats->lastStorageSize))); + BytesToString(stats.lastVertSize + stats.lastUniformSize + + stats.lastIndexSize + stats.lastStorageSize + + stats.lastTextureUploadSize))); + + // TODO: persist to config + ShowCornerContextMenu(m_debugOverlayCorner, m_cameraOverlayCorner); } ImGui::End(); } @@ -136,10 +149,10 @@ namespace dusk { } ImGuiIO& io = ImGui::GetIO(); - ImGuiWindowFlags windowFlags = ImGuiWindowFlags_NoResize; + ImGuiWindowFlags windowFlags = + ImGuiWindowFlags_NoResize | ImGuiWindowFlags_AlwaysAutoResize; ImGui::SetNextWindowBgAlpha(0.65f); - ImGui::SetNextWindowSizeConstraints(ImVec2(300, 200), ImVec2(300, 200)); if (ImGui::Begin("Player Info", &m_showPlayerInfo, windowFlags)) { daAlink_c* player = (daAlink_c*)dComIfGp_getPlayer(0); @@ -187,4 +200,4 @@ namespace dusk { ImGui::End(); } -} \ No newline at end of file +} diff --git a/src/dusk/imgui/ImGuiMenuTools.hpp b/src/dusk/imgui/ImGuiMenuTools.hpp index 325181268a..35604e0c93 100644 --- a/src/dusk/imgui/ImGuiMenuTools.hpp +++ b/src/dusk/imgui/ImGuiMenuTools.hpp @@ -10,19 +10,9 @@ namespace dusk { class ImGuiMenuTools { public: - struct CollisionViewSettings { - bool m_enableTerrainView = false; - bool m_enableWireframe = false; - bool m_enableAtView = false; - bool m_enableTgView = false; - bool m_enableCoView = false; - float m_terrainViewOpacity = 50.0f; - float m_colliderViewOpacity = 50.0f; - float m_drawRange = 100.0f; - }; - ImGuiMenuTools(); void draw(); + void afterDraw(); void ShowDebugOverlay(); void ShowCameraOverlay(); @@ -31,12 +21,11 @@ namespace dusk { void ShowStubLog(); void ShowMapLoader(); void ShowPlayerInfo(); - - CollisionViewSettings& getCollisionViewSettings() { return m_collisionViewSettings; } + void ShowAudioDebug(); private: bool m_showDebugOverlay = false; - int m_debugOverlayCorner = 0; // top-left + int m_debugOverlayCorner = 2; // bottom-left bool m_showCameraOverlay = false; int m_cameraOverlayCorner = 3; @@ -48,6 +37,8 @@ namespace dusk { bool m_showStubLog = false; bool m_showMapLoader = false; + + bool m_showAudioDebug = false; struct { int mapIdx = -1; int regionIdx = -1; @@ -63,8 +54,6 @@ namespace dusk { bool m_isDevelopmentMode = false; bool m_showPlayerInfo = false; - CollisionViewSettings m_collisionViewSettings; - bool m_showSaveEditor = false; ImGuiSaveEditor m_saveEditor; }; diff --git a/src/dusk/imgui/ImGuiSaveEditor.cpp b/src/dusk/imgui/ImGuiSaveEditor.cpp index ff04b1f1a2..9748893571 100644 --- a/src/dusk/imgui/ImGuiSaveEditor.cpp +++ b/src/dusk/imgui/ImGuiSaveEditor.cpp @@ -284,10 +284,10 @@ namespace dusk { void ImGuiSaveEditor::draw(bool& open) { ImGuiIO& io = ImGui::GetIO(); - ImGuiWindowFlags windowFlags = ImGuiWindowFlags_NoResize; + ImGuiWindowFlags windowFlags = + ImGuiWindowFlags_NoResize | ImGuiWindowFlags_AlwaysAutoResize; ImGui::SetNextWindowBgAlpha(0.65f); - ImGui::SetNextWindowSizeConstraints(ImVec2(600, 700), ImVec2(600, 700)); if (ImGui::Begin("Save Editor", &open, windowFlags)) { if (ImGui::BeginTabBar("SaveEditorTabBar", ImGuiTabBarFlags_NoCloseWithMiddleMouseButton)) { @@ -823,7 +823,7 @@ namespace dusk { for (int e = 0; e < 255; e++) { ImGui::Text("%03d ", e); ImGui::SameLine(); - for (int i = 8; i >= 0; i--) { + for (int i = 7; i >= 0; i--) { bool flag = event.mEvent[e] & (1 << i); if (ImGui::Checkbox(fmt::format("##event{0}{1}", e, i).c_str(), &flag)) { if (flag) diff --git a/src/dusk/imgui/ImGuiStubLog.cpp b/src/dusk/imgui/ImGuiStubLog.cpp index 0876125865..d8638da297 100644 --- a/src/dusk/imgui/ImGuiStubLog.cpp +++ b/src/dusk/imgui/ImGuiStubLog.cpp @@ -1,4 +1,5 @@ #include +#include #include "dusk/logging.h" #include "imgui.h" @@ -9,6 +10,7 @@ namespace dusk { static ImGuiTextBuffer StubLogBuffer; static std::vector LineOffsets; static bool StubLogPaused; + static std::mutex StubLogMutex; const char* LogLevelName(const AuroraLogLevel level) { switch (level) { @@ -32,16 +34,22 @@ namespace dusk { return; } + std::lock_guard lock(StubLogMutex); + + if (StubLogBuffer.size() > 1024 * 1024) { + DuskLog.warn("Stub log FULL. Dropping logs!"); + return; + } + LineOffsets.push_back(StubLogBuffer.size()); const auto levelName = LogLevelName(level); StubLogBuffer.appendf("[%s | %s] %s\n", levelName, module, message); } - static void ClearPastFrame(); - void ImGuiMenuTools::ShowStubLog() { + std::lock_guard lock(StubLogMutex); + if (!ImGuiConsole::CheckMenuViewToggle(ImGuiKey_F5, m_showStubLog)) { - ClearPastFrame(); return; } @@ -56,7 +64,7 @@ namespace dusk { if (ImGui::BeginChild("scrolling")) { ImGuiListClipper clipper; - clipper.Begin(LineOffsets.size()); + clipper.Begin(static_cast(LineOffsets.size())); while (clipper.Step()) { for (int idx = clipper.DisplayStart; idx < clipper.DisplayEnd; idx++) { const char* lineStart = StubLogBuffer.begin() + LineOffsets[idx]; @@ -72,7 +80,6 @@ namespace dusk { } ImGui::End(); - ClearPastFrame(); } void ClearPastFrame() { @@ -82,4 +89,10 @@ namespace dusk { StubLogBuffer.clear(); LineOffsets.clear(); } + + void ImGuiMenuTools::afterDraw() { + std::lock_guard lock(StubLogMutex); + + ClearPastFrame(); + } } diff --git a/src/dusk/io.cpp b/src/dusk/io.cpp new file mode 100644 index 0000000000..50b5cab5bd --- /dev/null +++ b/src/dusk/io.cpp @@ -0,0 +1,147 @@ +#include "dusk/io.hpp" +#include +#include + +using namespace dusk::io; + +#if _WIN32 +#define MODE_TYPE wchar_t +#define MODE(val) L##val +#define ftell(file) _ftelli64(file) +#define fseek(a, b, c) _fseeki64(a, b, c) +#else +#define MODE_TYPE char +#if _MSVC_VER +#define MODE(val) ##val +#else +#define MODE(val) val +#endif +#endif + +static FILE* ThrowIfNotOpen(const FileStream& file) { + if (!file.GetFileHandle()) { + throw std::runtime_error("Invalid file handle!"); + } + + return static_cast(file.GetFileHandle()); +} + +[[noreturn]] static void ThrowForError(int code) { + throw std::system_error(std::make_error_code(static_cast(code))); +} + +static FILE* OpenCore(const std::filesystem::path& path, const MODE_TYPE* mode) { + FILE* file; + + int err; +#if _WIN32 + static_assert(std::is_same_v); + err = _wfopen_s(&file, path.c_str(), mode); +#else + errno = 0; + static_assert(std::is_same_v); + file = fopen(path.c_str(), mode); + err = errno; +#endif + + if (!file) { + ThrowForError(err); + } + + return file; +} + +static FILE* OpenCore(const char* path, const MODE_TYPE* mode) { + return OpenCore(reinterpret_cast(path), mode); +} + +FileStream::FileStream() noexcept : file(nullptr) { +} + +FileStream::FileStream(void* file) : file(file) { + if (!file) { + CRASH("Invalid file handle"); + } +} + +FileStream::FileStream(FileStream&& other) noexcept { + file = other.file; + other.file = nullptr; +} + +FileStream::~FileStream() { + if (file) + fclose(static_cast(file)); +} + +FileStream FileStream::OpenRead(const char* utf8Path) { + return FileStream(OpenCore(utf8Path, MODE("rb"))); +} + +FileStream FileStream::Create(const char* utf8Path) { + return FileStream(OpenCore(utf8Path, MODE("wb"))); +} + +std::vector FileStream::ReadFull() { + const auto fileHandle = ThrowIfNotOpen(*this); + + std::vector result; + + const auto startPos = ftell(fileHandle); + if (startPos == -1) { + ThrowForError(errno); + } + + auto seekRes = fseek(fileHandle, 0, SEEK_END); + if (seekRes != 0) { + ThrowForError(errno); + } + + const auto endPos = ftell(fileHandle); + if (endPos == -1) { + ThrowForError(errno); + } + + seekRes = fseek(fileHandle, startPos, SEEK_SET); + if (seekRes != 0) { + ThrowForError(errno); + } + + result.resize(endPos - startPos); + + if (result.empty()) { + return result; + } + + auto ret = fread(result.data(), 1, result.size(), fileHandle); + if (ret < result.size()) { + int err = errno; + // Error or EOF + if (feof(fileHandle)) { + result.resize(ret); + } else { + ThrowForError(err); + } + } + + return result; +} + +std::vector FileStream::ReadAllBytes(const char* utf8Path) { + auto handle = OpenRead(utf8Path); + return std::move(handle.ReadFull()); +} + +void FileStream::Write(const char* data, size_t dataLen) { + FILE* fileHandle = ThrowIfNotOpen(*this); + + const auto ret = fwrite(data, 1, dataLen, fileHandle); + if (ret < dataLen) { + ThrowForError(errno); + } +} + +void FileStream::WriteAllText(const char* utf8Path, const std::string_view text) { + auto handle = Create(utf8Path); + handle.Write(text.data(), text.size()); +} diff --git a/src/dusk/layout.cpp b/src/dusk/layout.cpp new file mode 100644 index 0000000000..11185debd6 --- /dev/null +++ b/src/dusk/layout.cpp @@ -0,0 +1,25 @@ +#include "dusk/layout.hpp" + +using namespace dusk; + +LayoutRect LayoutRect::FitRectInRect( + const f32 widthOuter, + const f32 heightOuter, + const f32 widthInner, + const f32 heightInner) { + + // Try as if constrained vertically first. + auto width = widthInner * (heightOuter / heightInner); + auto height = heightOuter; + if (width > widthOuter) { + // Otherwise, constrained horizontally. + width = widthOuter; + height = heightOuter * (widthOuter / widthInner); + } + + // Center it + const auto posX = (widthOuter - width) / 2; + const auto posY = (heightOuter - height) / 2; + + return {posX, posY, posX + width, posY + height}; +} diff --git a/src/dusk/logging.cpp b/src/dusk/logging.cpp index 1a92f9ac37..37d1d4f55f 100644 --- a/src/dusk/logging.cpp +++ b/src/dusk/logging.cpp @@ -2,6 +2,8 @@ #include #include +#include "tracy/Tracy.hpp" + bool StubLogEnabled = true; using namespace std::literals::string_view_literals; @@ -32,6 +34,7 @@ static bool IsForStubLog(const char* message) { void aurora_log_callback(AuroraLogLevel level, const char* module, const char* message, unsigned int len) { + ZoneScoped; if (StubLogEnabled && level != LOG_FATAL && IsForStubLog(message)) { dusk::SendToStubLog(level, module, message); return; diff --git a/src/dusk/main.cpp b/src/dusk/main.cpp index 4155482488..7d19325f8f 100644 --- a/src/dusk/main.cpp +++ b/src/dusk/main.cpp @@ -3,6 +3,8 @@ #include #endif +#include + int game_main(int argc, char* argv[]); void WindowsSetupConsole(); diff --git a/src/dusk/settings.cpp b/src/dusk/settings.cpp new file mode 100644 index 0000000000..cf76ed9025 --- /dev/null +++ b/src/dusk/settings.cpp @@ -0,0 +1,128 @@ +#include "dusk/settings.h" +#include "dusk/config.hpp" + +namespace dusk { + +UserSettings g_userSettings = { + .video = { + .enableFullscreen {"video.enableFullscreen", false}, + .enableVsync {"video.enableVsync", true}, + .lockAspectRatio {"video.lockAspectRatio", false}, + }, + + .audio = { + .masterVolume {"audio.masterVolume", 80}, + .mainMusicVolume {"audio.mainMusicVolume", 100}, + .subMusicVolume {"audio.subMusicVolume", 100}, + .soundEffectsVolume {"audio.soundEffectsVolume", 100}, + .fanfareVolume {"audio.fanfareVolume", 100}, + .enableReverb {"audio.enableReverb", true}, + }, + + .game = { + // Quality of Life + .enableQuickTransform {"game.enableQuickTransform", false}, + .hideTvSettingsScreen {"game.hideTvSettingsScreen", false}, + .biggerWallets {"game.biggerWallets", false}, + .noReturnRupees {"game.noReturnRupees", false}, + .disableRupeeCutscenes {"game.disableRupeeCutscenes", false}, + .noSwordRecoil {"game.noSwordRecoil", false}, + .damageMultiplier {"game.damageMultiplier", 1}, + .instantDeath {"game.instantDeath", false}, + .fastClimbing {"game.fastClimbing", false}, + .noMissClimbing {"game.noMissClimbing", false}, + .fastTears {"game.fastTears", false}, + .instantSaves {"game.instantSaves", false}, + + // Preferences + .enableMirrorMode {"game.enableMirrorMode", false}, + .invertCameraXAxis {"game.invertCameraXAxis", false}, + + // Graphics + .enableBloom {"game.enableBloom", true}, + .useWaterProjectionOffset {"game.useWaterProjectionOffset", false}, + + // Audio + .noLowHpSound {"game.noLowHpSound", false}, + .midnasLamentNonStop {"game.midnasLamentNonStop", false}, + + // Cheats + .enableFastIronBoots {"game.enableFastIronBoots", false}, + .canTransformAnywhere {"game.canTransformAnywhere", false}, + .fastSpinner {"game.fastSpinner", false}, + .freeMagicArmor {"game.freeMagicArmor", false}, + + // Technical + .restoreWiiGlitches {"game.restoreWiiGlitches", false}, + + // Controls + .enableTurboKeybind {"game.enableTurboKeybind", true}, + }, +}; + +UserSettings& getSettings() { + return g_userSettings; +} + +void registerSettings() { + // Video + Register(g_userSettings.video.enableFullscreen); + Register(g_userSettings.video.enableVsync); + Register(g_userSettings.video.lockAspectRatio); + + // Audio + Register(g_userSettings.audio.masterVolume); + Register(g_userSettings.audio.mainMusicVolume); + Register(g_userSettings.audio.subMusicVolume); + Register(g_userSettings.audio.soundEffectsVolume); + Register(g_userSettings.audio.fanfareVolume); + Register(g_userSettings.audio.enableReverb); + + // Game + Register(g_userSettings.game.enableQuickTransform); + Register(g_userSettings.game.hideTvSettingsScreen); + Register(g_userSettings.game.biggerWallets); + Register(g_userSettings.game.noReturnRupees); + Register(g_userSettings.game.disableRupeeCutscenes); + Register(g_userSettings.game.noSwordRecoil); + Register(g_userSettings.game.damageMultiplier); + Register(g_userSettings.game.instantDeath); + Register(g_userSettings.game.fastClimbing); + Register(g_userSettings.game.fastTears); + Register(g_userSettings.game.instantSaves); + Register(g_userSettings.game.enableMirrorMode); + Register(g_userSettings.game.invertCameraXAxis); + Register(g_userSettings.game.enableBloom); + Register(g_userSettings.game.useWaterProjectionOffset); + Register(g_userSettings.game.enableFastIronBoots); + Register(g_userSettings.game.canTransformAnywhere); + Register(g_userSettings.game.freeMagicArmor); + Register(g_userSettings.game.restoreWiiGlitches); + Register(g_userSettings.game.noMissClimbing); + Register(g_userSettings.game.noLowHpSound); + Register(g_userSettings.game.midnasLamentNonStop); + Register(g_userSettings.game.enableTurboKeybind); + Register(g_userSettings.game.fastSpinner); +} + +// Transient settings + +static TransientSettings g_transientSettings = { + .collisionView = { + .enableTerrainView = false, + .enableWireframe = false, + .enableAtView = false, + .enableTgView = false, + .enableCoView = false, + .terrainViewOpacity = 50.0f, + .colliderViewOpacity = 50.0f, + .drawRange = 100.0f, + }, + .skipFrameRateLimit = false, +}; + +TransientSettings& getTransientSettings() { + return g_transientSettings; +} + +} diff --git a/src/dusk/stubs.cpp b/src/dusk/stubs.cpp index 6a5a8f86e1..668541f49c 100644 --- a/src/dusk/stubs.cpp +++ b/src/dusk/stubs.cpp @@ -11,7 +11,9 @@ #include #include #include +#include +#include "tracy/Tracy.hpp" #ifndef _WIN32 #include @@ -84,7 +86,17 @@ static PCMessageQueueData& GetMsgQueueData(OSMessageQueue* mq) { return *it->second; } -void OSInitMessageQueue(OSMessageQueue* mq, void* msgArray, s32 msgCount) { +static void ClearMsgQueueMap() { + std::lock_guard lock(GetMsgQueueMapMutex()); + auto& map = GetMsgQueueMap(); + for (auto & [_, value] : map) { + value->cvReceive.notify_all(); + value->cvSend.notify_all(); + } + map.clear(); +} + +void OSInitMessageQueue(OSMessageQueue* mq, OSMessage* msgArray, s32 msgCount) { if (!mq) return; mq->queueSend.head = mq->queueSend.tail = nullptr; mq->queueReceive.head = mq->queueReceive.tail = nullptr; @@ -104,7 +116,10 @@ int OSSendMessage(OSMessageQueue* mq, void* msg, s32 flags) { if (mq->usedCount >= mq->msgCount) { if (flags == OS_MESSAGE_NOBLOCK) return 0; // BLOCK: wait until space is available - data.cvSend.wait(lock, [mq]() { return mq->usedCount < mq->msgCount; }); + data.cvSend.wait(lock, [mq] { return mq->usedCount < mq->msgCount || dusk::IsShuttingDown; }); + } + if (dusk::IsShuttingDown) { + return 0; } s32 idx = (mq->firstIndex + mq->usedCount) % mq->msgCount; @@ -115,7 +130,7 @@ int OSSendMessage(OSMessageQueue* mq, void* msg, s32 flags) { return 1; } -int OSReceiveMessage(OSMessageQueue* mq, void* msg, s32 flags) { +BOOL OSReceiveMessage(OSMessageQueue* mq, OSMessage* msg, s32 flags) { if (!mq) return 0; PCMessageQueueData& data = GetMsgQueueData(mq); @@ -124,7 +139,10 @@ int OSReceiveMessage(OSMessageQueue* mq, void* msg, s32 flags) { if (mq->usedCount == 0) { if (flags == OS_MESSAGE_NOBLOCK) return 0; // BLOCK: wait until a message arrives - data.cvReceive.wait(lock, [mq]() { return mq->usedCount > 0; }); + data.cvReceive.wait(lock, [mq] { return mq->usedCount > 0 || dusk::IsShuttingDown; }); + } + if (dusk::IsShuttingDown) { + return 0; } if (msg) { @@ -146,7 +164,10 @@ int OSJamMessage(OSMessageQueue* mq, void* msg, s32 flags) { if (mq->usedCount >= mq->msgCount) { if (flags == OS_MESSAGE_NOBLOCK) return 0; // BLOCK: wait until space is available - data.cvSend.wait(lock, [mq]() { return mq->usedCount < mq->msgCount; }); + data.cvSend.wait(lock, [mq] { return mq->usedCount < mq->msgCount || dusk::IsShuttingDown; }); + } + if (dusk::IsShuttingDown) { + return 0; } // Jam inserts at the front of the queue @@ -185,8 +206,12 @@ BOOL OSGetResetButtonState() { return FALSE; } BOOL OSInitFont(OSFontHeader* fontData) { return FALSE; } BOOL OSLink(OSModuleInfo* newModule, void* bss) { return TRUE; } +void ClearCondMap(); void OSResetSystem(int reset, u32 resetCode, BOOL forceMenu) { OSReport("[PC] OSResetSystem called (reset=%d, code=%u)\n", reset, resetCode); + dusk::IsShuttingDown = true; + ClearMsgQueueMap(); + ClearCondMap(); } void OSSetStringTable(void* stringTable) {} @@ -332,6 +357,7 @@ void VISetNextFrameBuffer(void* fb) { } void VIWaitForRetrace() { + ZoneScoped; sRetraceCount++; if (sVIPreRetraceCallback) { sVIPreRetraceCallback(sRetraceCount); @@ -367,46 +393,6 @@ VIRetraceCallback VISetPreRetraceCallback(VIRetraceCallback cb) { } // extern "C" -#pragma mark DSP -#include -extern "C" void __DSP_insert_task(DSPTaskInfo* task) { - STUB_LOG(); -} - -extern "C" void __DSP_boot_task(DSPTaskInfo*) { - STUB_LOG(); -} - -extern "C" void __DSP_exec_task(DSPTaskInfo*, DSPTaskInfo*) { - STUB_LOG(); -} - -extern "C" void __DSP_remove_task(DSPTaskInfo* task) { - STUB_LOG(); -} - -void DSPAssertInt(void) { - STUB_LOG(); -} -u32 DSPCheckMailFromDSP(void) { - STUB_LOG(); - return 0; -} -u32 DSPCheckMailToDSP(void) { - STUB_LOG(); - return 0; -} -void DSPInit(void) { - STUB_LOG(); -} -u32 DSPReadMailFromDSP(void) { - STUB_LOG(); - return 0; -} -void DSPSendMailToDSP(u32 mail) { - STUB_LOG(); -} - #pragma mark Z2Audio class Z2AudioCS { public: @@ -1038,7 +1024,7 @@ f32 GXGetYScaleFactor(u16 efbHeight, u16 xfbHeight) { void GXInitTexCacheRegion(GXTexRegion* region, GXBool is_32b_mipmap, u32 tmem_even, GXTexCacheSize size_even, u32 tmem_odd, GXTexCacheSize size_odd) { STUB_LOG(); -} +} // XXX, this should be some struct? // GXRenderModeObj GXNtsc480IntDf; //GXRenderModeObj GXNtsc480Int; @@ -1079,22 +1065,15 @@ extern "C" void KPADEnableDPD(s32) { void LCDisable(void) { STUB_LOG(); } -void LCQueueWait(__REGISTER u32 len) { - STUB_LOG(); -} -u32 LCStoreData(void* destAddr, void* srcAddr, u32 nBytes) { - STUB_LOG(); - return 0; -} #pragma mark PPC Arch // MSR stuff? void PPCHalt() { - STUB_LOG(); + abort(); } extern "C" void PPCSync(void) { - STUB_LOG(); + // Does nothing on PC } u32 PPCMfhid2() { diff --git a/src/f_ap/f_ap_game.cpp b/src/f_ap/f_ap_game.cpp index 520d85d20f..180e6bc361 100644 --- a/src/f_ap/f_ap_game.cpp +++ b/src/f_ap/f_ap_game.cpp @@ -1,26 +1,27 @@ #include "f_ap/f_ap_game.h" +#include +#include "DynamicLink.h" +#include "JSystem/J3DGraphLoader/J3DModelLoader.h" +#include "JSystem/J3DGraphLoader/J3DModelSaver.h" +#include "JSystem/JHostIO/JORFile.h" +#include "JSystem/JKernel/JKRAram.h" +#include "JSystem/JKernel/JKRAramArchive.h" +#include "JSystem/JKernel/JKRSolidHeap.h" +#include "JSystem/JUtility/JUTDbPrint.h" #include "SSystem/SComponent/c_counter.h" +#include "d/actor/d_a_alink.h" +#include "d/actor/d_a_grass.h" +#include "d/actor/d_a_midna.h" +#include "d/d_model.h" +#include "d/d_tresure.h" +#include "dusk/logging.h" #include "f_op/f_op_camera_mng.h" #include "f_op/f_op_draw_tag.h" #include "f_op/f_op_overlap_mng.h" #include "f_op/f_op_scene_mng.h" -#include "m_Do/m_Do_main.h" #include "m_Do/m_Do_graphic.h" -#include "DynamicLink.h" -#include "JSystem/JKernel/JKRSolidHeap.h" -#include "JSystem/JKernel/JKRAram.h" -#include "JSystem/JKernel/JKRAramArchive.h" -#include "JSystem/JUtility/JUTDbPrint.h" -#include "JSystem/JHostIO/JORFile.h" -#include "JSystem/J3DGraphLoader/J3DModelLoader.h" -#include "JSystem/J3DGraphLoader/J3DModelSaver.h" -#include "d/actor/d_a_alink.h" -#include "d/actor/d_a_midna.h" -#include "d/d_model.h" -#include "d/actor/d_a_grass.h" -#include "d/d_tresure.h" -#include -#include "dusk/logging.h" +#include "m_Do/m_Do_main.h" +#include "tracy/Tracy.hpp" fapGm_HIO_c::fapGm_HIO_c() { mUsingHostIO = true; @@ -722,6 +723,7 @@ void fapGm_After() { } void fapGm_Execute() { + ZoneScoped; static u32 sExecCount = 0; if (sExecCount < 10 || (sExecCount % 300 == 0)) { DuskLog.debug("fapGm_Execute frame={}", sExecCount); @@ -732,6 +734,24 @@ void fapGm_Execute() { JUTDbPrint::getManager()->setCharColor(g_HIO.mColor); #endif +#if TARGET_PC + if (mDoCPd_c::getHoldR(PAD_1) && mDoCPd_c::getTrigY(PAD_1)) { + if (const auto link = g_dComIfG_gameInfo.play.getPlayer(0)) { + dynamic_cast(link)->handleQuickTransform(); + } + } + + if (dusk::getSettings().game.fastSpinner && mDoCPd_c::getHoldR(PAD_1)) { + if (const auto link = g_dComIfG_gameInfo.play.getPlayer(0)) { + auto spinnerActor = (fopAc_ac_c*)dynamic_cast(link)->getSpinnerActor(); + if (spinnerActor) { + if (spinnerActor->speedF < 60.f) + spinnerActor->speedF += 2.f; + } + } + } +#endif + fpcM_Management(NULL, fapGm_After); cCt_Counter(0); } diff --git a/src/f_op/f_op_actor_mng.cpp b/src/f_op/f_op_actor_mng.cpp index 79795d3bfe..dca07f98ba 100644 --- a/src/f_op/f_op_actor_mng.cpp +++ b/src/f_op/f_op_actor_mng.cpp @@ -730,6 +730,9 @@ u8 var_r30 = fopAcM::HeapAdjustEntry; #endif u32 size = i_size & 0xFFFFFF; +#if TARGET_PC + size *= 2; +#endif bool result = fopAcM_entrySolidHeap_(i_actor, i_heapCallback, size); #if DEBUG fopAcM::HeapDummyCheck = var_r29; @@ -1019,10 +1022,15 @@ cull_sphere l_cullSizeSphere[fopAc_CULLSPHERE_MAX_e] = { s32 fopAcM_cullingCheck(fopAc_ac_c const* i_actor) { MtxP mtx_p; +#if AVOID_UB + Mtx concat_mtx; +#endif if (fopAcM_GetMtx(i_actor) == NULL) { mtx_p = j3dSys.getViewMtx(); } else { +#if !AVOID_UB Mtx concat_mtx; +#endif cMtx_concat(j3dSys.getViewMtx(), fopAcM_GetMtx(i_actor), concat_mtx); mtx_p = concat_mtx; } diff --git a/src/f_pc/f_pc_manager.cpp b/src/f_pc/f_pc_manager.cpp index 4f676c242f..a3d85d4df6 100644 --- a/src/f_pc/f_pc_manager.cpp +++ b/src/f_pc/f_pc_manager.cpp @@ -22,6 +22,8 @@ #include "m_Do/m_Do_controller_pad.h" #include +#include "tracy/Tracy.hpp" + void fpcM_Draw(void* i_proc) { fpcDw_Execute((base_process_class*)i_proc); } @@ -43,6 +45,7 @@ BOOL fpcM_IsCreating(fpc_ProcID i_id) { } void fpcM_Management(fpcM_ManagementFunc i_preExecuteFn, fpcM_ManagementFunc i_postExecuteFn) { + ZoneScoped; MtxInit(); if (!fapGm_HIO_c::isCaptureScreen()) { dComIfGd_peekZdata(); diff --git a/src/m_Do/m_Do_DVDError.cpp b/src/m_Do/m_Do_DVDError.cpp index 4984ea22c7..2cfef5fbb4 100644 --- a/src/m_Do/m_Do_DVDError.cpp +++ b/src/m_Do/m_Do_DVDError.cpp @@ -5,15 +5,11 @@ #include "m_Do/m_Do_DVDError.h" #include "JSystem/JKernel/JKRAssertHeap.h" -#include +#include #include "m_Do/m_Do_dvd_thread.h" #include "m_Do/m_Do_ext.h" #include "m_Do/m_Do_Reset.h" -// Added for the sleep workaround -#include -#include - #if PLATFORM_GCN const int stack_size = 3072; #else @@ -29,24 +25,25 @@ static OSThread DvdErr_thread; static u8 DvdErr_stack[stack_size] ATTRIBUTE_ALIGN(16); #pragma pop -// Alarm is not needed for the PC workaround -// static OSAlarm Alarm; +static OSAlarm Alarm; void mDoDvdErr_ThdInit() { +#ifdef TARGET_PC + // Thread is not necessary on PC + return; +#endif + if (mDoDvdErr_initialized) { return; } - // OSTime time = OSGetTime(); // Unused in workaround + OSTime time = OSGetTime(); - OSCreateThread(&DvdErr_thread, (void* (*)(void*))mDoDvdErr_Watch, NULL, - DvdErr_stack + sizeof(DvdErr_stack), sizeof(DvdErr_stack), - OSGetThreadPriority(OSGetCurrentThread()) - 3, 1); + OSCreateThread(&DvdErr_thread, (void*(*)(void*))mDoDvdErr_Watch, NULL, DvdErr_stack + sizeof(DvdErr_stack), + sizeof(DvdErr_stack), OSGetThreadPriority(OSGetCurrentThread()) - 3, 1); OSResumeThread(&DvdErr_thread); - - // PC Workaround: Disable Alarm logic. The thread will sleep itself. - // OSCreateAlarm(&Alarm); - // OSSetPeriodicAlarm(&Alarm, time, OS_BUS_CLOCK / 4, AlarmHandler); + OSCreateAlarm(&Alarm); + OSSetPeriodicAlarm(&Alarm, time, OS_BUS_CLOCK / 4, AlarmHandler); mDoDvdErr_initialized = true; } @@ -54,16 +51,14 @@ void mDoDvdErr_ThdInit() { void mDoDvdErr_ThdCleanup() { if (mDoDvdErr_initialized) { OSCancelThread(&DvdErr_thread); - // OSCancelAlarm(&Alarm); // Disable Alarm cancel + OSCancelAlarm(&Alarm); mDoDvdErr_initialized = false; } } static void mDoDvdErr_Watch(void*) { #if PLATFORM_GCN -#ifndef TARGET_PC OSDisableInterrupts(); -#endif #endif JKRThread(OSGetCurrentThread(), 0); @@ -75,20 +70,10 @@ static void mDoDvdErr_Watch(void*) { if (status == DVD_STATE_FATAL_ERROR) { mDoDvdThd::suspend(); } - - // PC Workaround: - // Instead of suspending and waiting for an Alarm (which might not be implemented), - // we simply sleep for a short duration. - // OS_BUS_CLOCK / 4 corresponds to roughly 1/4th of a second on GC. - // We use 250ms here to simulate the periodic check. - - // OSSuspendThread(&DvdErr_thread); // <-- Original causing deadlock without Alarm - std::this_thread::sleep_for(std::chrono::milliseconds(250)); - + OSSuspendThread(&DvdErr_thread); } while (true); } static void AlarmHandler(OSAlarm*, OSContext*) { - // This handler is no longer called in the PC workaround OSResumeThread(&DvdErr_thread); } \ No newline at end of file diff --git a/src/m_Do/m_Do_MemCard.cpp b/src/m_Do/m_Do_MemCard.cpp index 919774d2e0..36de5480e5 100644 --- a/src/m_Do/m_Do_MemCard.cpp +++ b/src/m_Do/m_Do_MemCard.cpp @@ -10,6 +10,8 @@ #include "m_Do/m_Do_MemCardRWmng.h" #include "m_Do/m_Do_Reset.h" #include "os_report.h" +#include "dusk/os.h" +#include "dusk/main.h" #if PLATFORM_WII || PLATFORM_SHIELD #include @@ -102,11 +104,21 @@ void mDoMemCd_Ctrl_c::ThdInit() { void mDoMemCd_Ctrl_c::main() { do { OSLockMutex(&mMutex); - while (mCardCommand == COMM_NONE_e) { + while (mCardCommand == COMM_NONE_e +#ifdef TARGET_PC + && !dusk::IsShuttingDown +#endif + ) { OSWaitCond(&mCond, &mMutex); } OSUnlockMutex(&mMutex); +#ifdef TARGET_PC + if (dusk::IsShuttingDown) { + break; + } +#endif + switch (mCardCommand) { #if PLATFORM_GCN || PLATFORM_WII case COMM_RESTORE_e: @@ -866,6 +878,10 @@ mDoMemCd_Ctrl_c g_mDoMemCd_control; static int mDoMemCd_main(void*) { JKRThread(OSGetCurrentThread(), 0); +#if TARGET_PC + OSSetCurrentThreadName("MemCardThread"); +#endif + JKRSetCurrentHeap(mDoExt_getAssertHeap()); g_mDoMemCd_control.main(); diff --git a/src/m_Do/m_Do_audio.cpp b/src/m_Do/m_Do_audio.cpp index fc386bda88..fc44eb7fb6 100644 --- a/src/m_Do/m_Do_audio.cpp +++ b/src/m_Do/m_Do_audio.cpp @@ -12,6 +12,7 @@ #include "d/d_debug_viewer.h" #include "m_Do/m_Do_Reset.h" #include "m_Do/m_Do_dvd_thread.h" +#include "tracy/Tracy.hpp" #if PLATFORM_WII || PLATFORM_SHIELD #include "Z2AudioCS/Z2AudioCS.h" @@ -157,6 +158,7 @@ static void mDoAud_Create() { void mDoAud_Execute() { DUSK_AUDIO_SKIP() + ZoneScoped; if (!mDoAud_zelAudio_c::isInitFlag()) { if (!mDoRst::isShutdown() && !mDoRst::isReturnToMenu()) { diff --git a/src/m_Do/m_Do_controller_pad.cpp b/src/m_Do/m_Do_controller_pad.cpp index c8a8566313..8ba03fc63b 100644 --- a/src/m_Do/m_Do_controller_pad.cpp +++ b/src/m_Do/m_Do_controller_pad.cpp @@ -10,6 +10,7 @@ #include "f_ap/f_ap_game.h" #include "m_Do/m_Do_Reset.h" #include "m_Do/m_Do_main.h" +#include "tracy/Tracy.hpp" JUTGamePad* mDoCPd_c::m_gamePad[4]; @@ -56,6 +57,7 @@ void mDoCPd_c::create() { } void mDoCPd_c::read() { + ZoneScoped; JUTGamePad::read(); if (!mDoRst::isReset() && mDoRst::is3ButtonReset()) { diff --git a/src/m_Do/m_Do_dvd_thread.cpp b/src/m_Do/m_Do_dvd_thread.cpp index 8949988c7c..08197ed30b 100644 --- a/src/m_Do/m_Do_dvd_thread.cpp +++ b/src/m_Do/m_Do_dvd_thread.cpp @@ -10,6 +10,7 @@ #include "JSystem/JKernel/JKRDvdRipper.h" #include "JSystem/JKernel/JKRExpHeap.h" #include "JSystem/JKernel/JKRMemArchive.h" +#include "dusk/os.h" #include "m_Do/m_Do_Reset.h" #include "m_Do/m_Do_controller_pad.h" #include "m_Do/m_Do_ext.h" @@ -17,6 +18,9 @@ s32 mDoDvdThd::main(void* param_0) { JKRThread(OSGetCurrentThread(), 0); +#if TARGET_PC + OSSetCurrentThreadName("DVD thread"); +#endif JKRSetCurrentHeap(mDoExt_getAssertHeap()); mDoDvdThd_param_c* param = static_cast(param_0); param->mainLoop(); @@ -159,7 +163,11 @@ void mDoDvdThd_param_c::mainLoop() { while ((command = this->getFirstCommand())) { this->cut(command); if (mDoDvdThd::SyncWidthSound) { + #if TARGET_PC + JASDvd::getThreadPointer()->sendCmdMsg(cb, &command, sizeof(void*)); + #else JASDvd::getThreadPointer()->sendCmdMsg(cb, &command, 4); + #endif } else { cb(&command); } diff --git a/src/m_Do/m_Do_ext.cpp b/src/m_Do/m_Do_ext.cpp index a7829bdb50..0593815b1d 100644 --- a/src/m_Do/m_Do_ext.cpp +++ b/src/m_Do/m_Do_ext.cpp @@ -1738,8 +1738,6 @@ void mDoExt_McaMorfSO::setAnm(J3DAnmTransform* i_anm, int i_attr, f32 i_morf, f3 setLoopFrame(getFrame()); setMorf(i_morf); - STUB_RET(); - if (mpSound != NULL) { if (i_anm != NULL) { mpBas = static_cast(i_anm)->getBas(); @@ -2385,8 +2383,8 @@ void mDoExt_3DlineMat0_c::draw() { int var_r26 = (field_0x14 << 1) & 0xFFFF; for (int i = 0; i < field_0x10; i++) { - GXSETARRAY(GX_VA_POS, field_0x18->field_0x8[field_0x16], sizeof(cXyz) * var_r26, sizeof(cXyz)); - GXSETARRAY(GX_VA_NRM, field_0x18->field_0x10[field_0x16], 3 * var_r26, 3); + GXSETARRAY(GX_VA_POS, field_0x18->field_0x8[field_0x16], sizeof(cXyz) * var_r26, sizeof(cXyz), true); + GXSETARRAY(GX_VA_NRM, field_0x18->field_0x10[field_0x16], 3 * var_r26, 3, true); GXBegin(GX_TRIANGLESTRIP, GX_VTXFMT0, var_r26); for (u16 j = 0; j < (u16)var_r26; j++) { @@ -2701,11 +2699,11 @@ void mDoExt_3DlineMat1_c::draw() { mDoExt_3Dline_c* lines = mpLines; u16 vert_num = field_0x34 << 1; for (s32 i = 0; i < mNumLines; i++) { - GXSETARRAY(GX_VA_POS, lines->field_0x8[mIsDrawn], vert_num * sizeof(cXyz), sizeof(cXyz)); + GXSETARRAY(GX_VA_POS, lines->field_0x8[mIsDrawn], vert_num * sizeof(cXyz), sizeof(cXyz), true); GXSETARRAY(GX_VA_NRM, lines->field_0x10[mIsDrawn], vert_num * sizeof(mDoExt_3Dline_field_0x10_c), - sizeof(mDoExt_3Dline_field_0x10_c)); - GXSETARRAY(GX_VA_TEX0, lines->field_0x18[mIsDrawn], vert_num * sizeof(cXy), sizeof(cXy)); + sizeof(mDoExt_3Dline_field_0x10_c), true); + GXSETARRAY(GX_VA_TEX0, lines->field_0x18[mIsDrawn], vert_num * sizeof(cXy), sizeof(cXy), true); GXBegin(GX_TRIANGLESTRIP, GX_VTXFMT0, vert_num); u16 j = 0; @@ -2875,7 +2873,10 @@ void mDoExt_3DlineMat1_c::update(int param_0, f32 param_1, GXColor& param_2, u16 sp_38++; } } + +#if !TARGET_PC #include "assets/l_mat2DL__d_a_grass.h" +#endif void mDoExt_3DlineMat2_c::setMaterial() { j3dSys.reinitGX(); @@ -3038,7 +3039,7 @@ mDoExt_cube8pPacket::mDoExt_cube8pPacket(cXyz* i_points, const GXColor& i_color) } void drawCube(MtxP mtx, cXyz* pos, const GXColor& color) { - GXSETARRAY(GX_VA_POS, pos, sizeof(*pos), sizeof(*pos)); + GXSETARRAY(GX_VA_POS, pos, sizeof(cXyz) * 8, sizeof(cXyz), true); GXSetVtxAttrFmt(GX_VTXFMT0, GX_VA_POS, GX_POS_XYZ, GX_F32, 0); GXClearVtxDesc(); GXSetVtxDesc(GX_VA_POS, GX_INDEX8); @@ -3117,7 +3118,7 @@ mDoExt_quadPacket::mDoExt_quadPacket(cXyz* i_points, const GXColor& i_color, u8 } void mDoExt_quadPacket::draw() { - GXSETARRAY(GX_VA_POS, mPoints, sizeof(mPoints), sizeof(cXyz)); + GXSETARRAY(GX_VA_POS, mPoints, sizeof(mPoints), sizeof(cXyz), true); GXSetVtxAttrFmt(GX_VTXFMT0, GX_VA_POS, GX_POS_XYZ, GX_F32, 0); GXClearVtxDesc(); GXSetVtxDesc(GX_VA_POS, GX_INDEX8); @@ -3169,7 +3170,7 @@ mDoExt_trianglePacket::mDoExt_trianglePacket(cXyz* i_points, const GXColor& i_co void mDoExt_trianglePacket::draw() { j3dSys.reinitGX(); - GXSETARRAY(GX_VA_POS, mPoints, sizeof(mPoints), sizeof(cXyz)); + GXSETARRAY(GX_VA_POS, mPoints, sizeof(mPoints), sizeof(cXyz), true); GXSetVtxAttrFmt(GX_VTXFMT0, GX_VA_POS, GX_POS_XYZ, GX_F32, 0); GXClearVtxDesc(); GXSetVtxDesc(GX_VA_POS, GX_INDEX8); diff --git a/src/m_Do/m_Do_graphic.cpp b/src/m_Do/m_Do_graphic.cpp index 94ba2fe6ce..a5bd4640c8 100644 --- a/src/m_Do/m_Do_graphic.cpp +++ b/src/m_Do/m_Do_graphic.cpp @@ -7,6 +7,9 @@ #include "d/dolzel.h" // IWYU pragma: keep +#include +#include +#include "DynamicLink.h" #include "JSystem/J2DGraph/J2DOrthoGraph.h" #include "JSystem/J2DGraph/J2DPrint.h" #include "JSystem/JAWExtSystem/JAWExtSystem.h" @@ -19,24 +22,22 @@ #include "SSystem/SComponent/c_math.h" #include "d/actor/d_a_player.h" #include "d/d_com_inf_game.h" -#include "d/d_menu_collect.h" +#include "d/d_debug_viewer.h" #include "d/d_jcam_editor.h" #include "d/d_jpreviewer.h" -#include +#include "d/d_menu_collect.h" +#include "d/d_meter2_info.h" +#include "d/d_s_play.h" +#include "dusk/endian.h" +#include "dusk/gx_helper.h" +#include "dusk/logging.h" #include "f_ap/f_ap_game.h" #include "f_op/f_op_camera_mng.h" #include "m_Do/m_Do_controller_pad.h" #include "m_Do/m_Do_graphic.h" #include "m_Do/m_Do_machine.h" #include "m_Do/m_Do_main.h" -#include "d/d_debug_viewer.h" -#include "d/d_meter2_info.h" -#include "d/d_s_play.h" -#include "DynamicLink.h" -#include -#include "dusk/endian.h" -#include "dusk/logging.h" -#include "dusk/gx_helper.h" +#include "tracy/Tracy.hpp" #if PLATFORM_WII || PLATFORM_SHIELD #include @@ -259,7 +260,7 @@ static ResTIMG* createTimg(u16 width, u16 height, u32 format) { JUTFader* mDoGph_gInf_c::mFader; -#if PLATFORM_WII || PLATFORM_SHIELD +#if PLATFORM_WII || PLATFORM_SHIELD || TARGET_PC ResTIMG* mDoGph_gInf_c::m_fullFrameBufferTimg; void* mDoGph_gInf_c::m_fullFrameBufferTex; #endif @@ -313,17 +314,17 @@ void mDoGph_gInf_c::create() { JUTProcBar::getManager()->setVisible(false); JUTDbPrint::getManager()->setVisible(false); - #if PLATFORM_WII || PLATFORM_SHIELD + #if PLATFORM_WII || PLATFORM_SHIELD || TARGET_PC m_fullFrameBufferTimg = createTimg(FB_WIDTH, FB_HEIGHT, 6); JUT_ASSERT(366, m_fullFrameBufferTimg != NULL); m_fullFrameBufferTex = (char*)m_fullFrameBufferTimg + sizeof(ResTIMG); #endif - mFrameBufferTimg = createTimg(FB_WIDTH / 2, FB_HEIGHT / 2, 6); + mFrameBufferTimg = createTimg(FB_WIDTH / 2, FB_HEIGHT / 2, GX_TF_RGBA8); JUT_ASSERT(374, mFrameBufferTimg != NULL); mFrameBufferTex = (char*)mFrameBufferTimg + sizeof(ResTIMG); - mZbufferTimg = createTimg(FB_WIDTH / 2, FB_HEIGHT / 2, 3); + mZbufferTimg = createTimg(FB_WIDTH / 2, FB_HEIGHT / 2, GX_TF_IA8); JUT_ASSERT(381, mZbufferTimg != NULL); mZbufferTex = (char*)mZbufferTimg + sizeof(ResTIMG); @@ -348,6 +349,8 @@ void mDoGph_gInf_c::create() { static bool data_80450BE8; void mDoGph_gInf_c::beginRender() { + ZoneScoped; + #if PLATFORM_WII || PLATFORM_SHIELD VISetTrapFilter(fapGmHIO_getTrapFilter() ? 1 : 0); VISetGamma((VIGamma)fapGmHIO_getGamma()); @@ -388,7 +391,7 @@ void mDoGph_gInf_c::onBlure() { onBlure(cMtx_getIdentity()); } -#if PLATFORM_WII || PLATFORM_SHIELD +#if PLATFORM_WII || PLATFORM_SHIELD || TARGET_PC TGXTexObj mDoGph_gInf_c::m_fullFrameBufferTexObj; #endif @@ -416,6 +419,7 @@ void mDoGph_gInf_c::fadeOut(f32 fadeSpeed) { } void darwFilter(GXColor matColor) { + ZoneScoped; GXSetNumChans(1); GXSetChanCtrl(GX_COLOR0A0, GX_FALSE, GX_SRC_REG, GX_SRC_REG, GX_LIGHT_NULL, GX_DF_NONE, GX_AF_NONE); @@ -552,8 +556,16 @@ const tvSize l_tvSize[2] = { {808, 448}, }; +#if TARGET_PC +tvSize pc_tvSize = {608, 448}; +#endif + void mDoGph_gInf_c::setTvSize() { +#if TARGET_PC + const tvSize* tvsize = &pc_tvSize; +#else const tvSize* tvsize = &l_tvSize[mWide]; +#endif m_width = tvsize->width; m_height = tvsize->height; @@ -572,13 +584,28 @@ void mDoGph_gInf_c::setTvSize() { m_aspect = m_widthF / m_heightF; m_scale = m_aspect / 1.3571428f; m_invScale = 1.0f / m_scale; + +#if TARGET_PC + hudAspectScaleDown = 1.3571428f / mDoGph_gInf_c::getAspect(); + hudAspectScaleUp = 1.0f / hudAspectScaleDown; +#endif } +#if TARGET_PC +void mDoGph_gInf_c::onWide(f32 width, f32 height) { + mWide = TRUE; + pc_tvSize.width = width; + pc_tvSize.height = height; + setTvSize(); + dMeter2Info_onWide2D(); +} +#else void mDoGph_gInf_c::onWide() { mWide = TRUE; setTvSize(); dMeter2Info_onWide2D(); } +#endif void mDoGph_gInf_c::offWide() { mWide = FALSE; @@ -686,10 +713,16 @@ void mDoGph_gInf_c::setWideZoomLightProjection(Mtx& m) { #endif #if TARGET_PC +f32 mDoGph_gInf_c::hudAspectScaleDown = 1.0f; +f32 mDoGph_gInf_c::hudAspectScaleUp = 1.0f; + void mDoGph_gInf_c::setWindowSize(AuroraWindowSize const& size) { JUTVideo::getManager()->setWindowSize(size); dComIfGp_setWindow(0, 0.0f, 0.0f, getWidth(), getHeight(), 0.0f, 1.0f, 0, 2); mFader->mBox.set(0, 0, getWidth(), getHeight()); + + f32 newWidth = (getWidth() / getHeight()) * 448.0f; + onWide(newWidth, 448.0f); } #endif @@ -789,8 +822,8 @@ int mDoGph_AfterOfDraw() { return 1; } -#if PLATFORM_WII -void drawFilterQuad(s8 param_0, s8 param_1) { +#if PLATFORM_WII || TARGET_PC +void mDoGph_drawFilterQuad(s8 param_0, s8 param_1) { GXBegin(GX_QUADS, GX_VTXFMT0, 4); GXPosition3s8(0, 0, -5); GXTexCoord2s8(0, 0); @@ -802,12 +835,10 @@ void drawFilterQuad(s8 param_0, s8 param_1) { GXTexCoord2s8(0, 1); GXEnd(); } - -// mapping to simplify call changes between wii / other platforms -#define mDoGph_drawFilterQuad drawFilterQuad #endif static void drawDepth2(view_class* param_0, view_port_class* param_1, int param_2) { + ZoneScoped; static GXColorS10 l_tevColor0 = {0, 0, 0, 0}; if (daPy_getLinkPlayerActorClass() != NULL) { @@ -914,8 +945,15 @@ static void drawDepth2(view_class* param_0, view_port_class* param_1, int param_ GX_FALSE, 0); } + #if TARGET_PC + // use full size for pc for higher quality background elements + u16 halfWidth = width; + u16 halfHeight = height; + #else u16 halfWidth = width >> 1; u16 halfHeight = height >> 1; + #endif + GXRenderModeObj* sp24 = JUTGetVideoManager()->getRenderMode(); GXSetCopyFilter(GX_FALSE, NULL, GX_TRUE, sp24->vfilter); GXSetTexCopySrc(x_orig, y_orig_pos, width, height); @@ -1054,6 +1092,7 @@ static void drawDepth2(view_class* param_0, view_port_class* param_1, int param_ } static void trimming(view_class* param_0, view_port_class* param_1) { + ZoneScoped; UNUSED(param_0); s16 y_orig = (int)param_1->y_orig & ~7; @@ -1122,7 +1161,7 @@ static void trimming(view_class* param_0, view_port_class* param_1) { param_1->scissor.height); } -#if !PLATFORM_WII +#if !PLATFORM_WII && !TARGET_PC void mDoGph_drawFilterQuad(s8 param_0, s8 param_1) { GXBegin(GX_QUADS, GX_VTXFMT0, 4); GXPosition2s8(0, 0); @@ -1139,7 +1178,11 @@ void mDoGph_drawFilterQuad(s8 param_0, s8 param_1) { void mDoGph_gInf_c::bloom_c::create() { if (m_buffer == NULL) { - u32 size = GXGetTexBufferSize(FB_WIDTH / 2, FB_HEIGHT / 2, 6, GX_FALSE, 0); +#ifdef TARGET_PC + u32 size = 0x20; // No need to allocate memory for texture +#else + u32 size = GXGetTexBufferSize(FB_WIDTH / 2, FB_HEIGHT / 2, GX_TF_RGBA8, GX_FALSE, 0); +#endif m_buffer = mDoExt_getArchiveHeap()->alloc(size, -32); JUT_ASSERT(1621, m_buffer != NULL); @@ -1162,7 +1205,8 @@ void mDoGph_gInf_c::bloom_c::remove() { void mDoGph_gInf_c::bloom_c::draw() { #if TARGET_PC - if (!dusk::g_imguiConsole.isBloomEnabled()) { + ZoneScoped; + if (!dusk::getSettings().game.enableBloom) { return; } #endif @@ -1199,12 +1243,12 @@ void mDoGph_gInf_c::bloom_c::draw() { GXClearVtxDesc(); GXSetVtxDesc(GX_VA_POS, GX_DIRECT); GXSetVtxDesc(GX_VA_TEX0, GX_DIRECT); - #if PLATFORM_WII - GXSetVtxAttrFmt(GX_VTXFMT0, GX_VA_POS, GX_CLR_RGBA, GX_RGB8, 0); + #if PLATFORM_WII || TARGET_PC + GXSetVtxAttrFmt(GX_VTXFMT0, GX_VA_POS, GX_POS_XYZ, GX_S8, 0); #else - GXSetVtxAttrFmt(GX_VTXFMT0, GX_VA_POS, GX_CLR_RGB, GX_RGB8, 0); + GXSetVtxAttrFmt(GX_VTXFMT0, GX_VA_POS, GX_POS_XY, GX_S8, 0); #endif - GXSetVtxAttrFmt(GX_VTXFMT0, GX_VA_TEX0, GX_CLR_RGBA, GX_RGB8, 0); + GXSetVtxAttrFmt(GX_VTXFMT0, GX_VA_TEX0, GX_TEX_ST, GX_S8, 0); if (mMonoColor.a != 0) { GXSetNumTevStages(1); GXSetTevOrder(GX_TEVSTAGE0, GX_TEXCOORD0, GX_TEXMAP0, GX_COLOR_NULL); @@ -1220,10 +1264,14 @@ void mDoGph_gInf_c::bloom_c::draw() { mDoGph_drawFilterQuad(4, 4); } if (enabled) { +#ifdef TARGET_PC + GXCreateFrameBuffer(width, height); +#else // Store off m_buffer to copy over again at the end. GXSetTexCopySrc(0, 0, width / 2, height / 2); GXSetTexCopyDst(width / 2, height / 2, GX_TF_RGBA8, 0); GXCopyTex(m_buffer, 0); +#endif GXSetNumTevStages(3); GXSetTevOrder(GX_TEVSTAGE0, GX_TEXCOORD0, GX_TEXMAP0, GX_COLOR_NULL); @@ -1280,7 +1328,13 @@ void mDoGph_gInf_c::bloom_c::draw() { GXSetTexCoordGen(GX_TEXCOORD0, GX_TG_MTX2x4, GX_TG_TEX0, 0x3c); for (int texCoord = (int)GX_TEXCOORD1; texCoord < (int)GX_MAX_TEXCOORD; texCoord++) { GXSetTexCoordGen((GXTexCoordID)texCoord, GX_TG_MTX2x4, GX_TG_TEX0, iVar11); + + #if TARGET_PC + f32 dVar15 = mBlureSize * ((448.0f / getHeight()) / 6400.0f); + #else f32 dVar15 = mBlureSize * (1.0f / 6400.0f); + #endif + mDoMtx_stack_c::transS((dVar15 * cM_scos(sVar10)) * getInvScale(), dVar15 * cM_ssin(sVar10), 0.0f); GXLoadTexMtxImm(mDoMtx_stack_c::get(), iVar11, GX_MTX2x4); @@ -1347,6 +1401,9 @@ void mDoGph_gInf_c::bloom_c::draw() { GXSetTexCopyDst(width / 4, height / 4, GX_TF_RGBA8, GX_FALSE); GXCopyTex(zBufferTex, GX_FALSE); +#ifdef TARGET_PC + GXRestoreFrameBuffer(); +#else // Copy back m_buffer to screen. GXInitTexObj(&tmp_tex2, m_buffer, width / 2, height / 2, GX_TF_RGBA8, GX_CLAMP, GX_CLAMP, GX_FALSE); @@ -1365,6 +1422,7 @@ void mDoGph_gInf_c::bloom_c::draw() { GX_TEVPREV); GXSetBlendMode(GX_BM_NONE, GX_BL_ONE, GX_BL_ONE, GX_LO_OR); mDoGph_drawFilterQuad(2, 2); +#endif // Now blend our bloom into the real FB. GXLoadTexObj(&tmp_tex1, GX_TEXMAP0); @@ -1410,7 +1468,11 @@ static void retry_captue_frame(view_class* param_0, view_port_class* param_1, in var_r24 = width >> 1; var_r23 = height >> 1; GXSetTexCopySrc(x_orig, y_orig_pos, width, height); +#ifdef TARGET_PC + GXSetTexCopyDst(width, height, (GXTexFmt)mDoGph_gInf_c::getFrameBufferTimg()->format, GX_TRUE); +#else GXSetTexCopyDst(var_r24, var_r23, (GXTexFmt)mDoGph_gInf_c::getFrameBufferTimg()->format, GX_TRUE); +#endif GXCopyTex(tex, GX_FALSE); GXPixModeSync(); GXInvalidateTexAll(); @@ -1418,6 +1480,7 @@ static void retry_captue_frame(view_class* param_0, view_port_class* param_1, in } static void motionBlure(view_class* param_0) { + ZoneScoped; if (g_env_light.is_blure) { GXLoadTexObj(mDoGph_gInf_c::getFrameBufferTexObj(), GX_TEXMAP0); GXColor local_60; @@ -1448,12 +1511,12 @@ static void motionBlure(view_class* param_0) { GXClearVtxDesc(); GXSetVtxDesc(GX_VA_POS, GX_DIRECT); GXSetVtxDesc(GX_VA_TEX0, GX_DIRECT); - #if PLATFORM_WII - GXSetVtxAttrFmt(GX_VTXFMT0, GX_VA_POS, GX_CLR_RGBA, GX_RGB8, 0); + #if PLATFORM_WII || TARGET_PC + GXSetVtxAttrFmt(GX_VTXFMT0, GX_VA_POS, GX_POS_XYZ, GX_S8, 0); #else - GXSetVtxAttrFmt(GX_VTXFMT0, GX_VA_POS, GX_CLR_RGB, GX_RGB8, 0); + GXSetVtxAttrFmt(GX_VTXFMT0, GX_VA_POS, GX_POS_XY, GX_S8, 0); #endif - GXSetVtxAttrFmt(GX_VTXFMT0, GX_VA_TEX0, GX_CLR_RGBA, GX_RGB8, 0); + GXSetVtxAttrFmt(GX_VTXFMT0, GX_VA_TEX0, GX_TEX_ST, GX_S8, 0); mDoGph_drawFilterQuad(1, 1); GXSetProjection(param_0->projMtx, GX_PERSPECTIVE); } @@ -1597,6 +1660,7 @@ static void captureScreenPerspDrawInfo(JPADrawInfo& info) { #endif static void drawItem3D() { + ZoneScoped; Mtx item_mtx; dMenu_Collect3D_c::setupItem3D(item_mtx); @@ -1613,6 +1677,7 @@ static void drawItem3D() { } int mDoGph_Painter() { + ZoneScoped; // Diagnostic: log windowNum to track game state machine progress static bool sDiagLoggedWindow = false; if (!sDiagLoggedWindow) { @@ -1621,6 +1686,10 @@ int mDoGph_Painter() { if (wn != 0) sDiagLoggedWindow = true; } +#if TARGET_PC + dusk::g_imguiConsole.PreDraw(); +#endif + #if DEBUG drawHeapMap(); #endif @@ -1653,7 +1722,7 @@ int mDoGph_Painter() { #endif dComIfGp_setCurrentGrafPort(&ortho); - dComIfGd_drawCopy2D(); + GX_DEBUG_GROUP(dComIfGd_drawCopy2D); #if DEBUG // "↓↓↓↓↓↓↓↓↓↓ CPU time measuring start ↓↓↓↓↓↓↓↓↓↓" @@ -1997,7 +2066,13 @@ int mDoGph_Painter() { Mtx m2; Mtx44 m; + + #if TARGET_PC + C_MTXPerspective(m, AREG_F(8) + 60.0f, 1.3571428f, 1.0f, 100000.0f); + #else C_MTXPerspective(m, AREG_F(8) + 60.0f, mDoGph_gInf_c::getAspect(), 1.0f, 100000.0f); + #endif + GXSetProjection(m, GX_PERSPECTIVE); cXyz sp38c(0.0f, 0.0f, AREG_F(7) + -2.0f); cXyz sp398(0.0f, 1.0f, 0.0f); @@ -2099,10 +2174,15 @@ int mDoGph_Painter() { fapGm_HIO_c::startCpuTimer(); #endif - #if PLATFORM_WII - if (data_8053a730) { - GXSetTexCopySrc(0, 0, FB_WIDTH, FB_HEIGHT); - GXSetTexCopyDst(FB_WIDTH, FB_HEIGHT, (GXTexFmt)mDoGph_gInf_c::m_fullFrameBufferTimg->format, 0); + #if TARGET_PC + if (dusk::getSettings().game.enableMirrorMode) + #elif PLATFORM_WII + if (data_8053a730) + #endif + #if TARGET_PC || PLATFORM_WII + { + GXSetTexCopySrc(0, 0, mDoGph_gInf_c::getWidth(), mDoGph_gInf_c::getHeight()); + GXSetTexCopyDst(mDoGph_gInf_c::getWidth(), mDoGph_gInf_c::getHeight(), (GXTexFmt)mDoGph_gInf_c::m_fullFrameBufferTimg->format, 0); GXCopyTex(mDoGph_gInf_c::m_fullFrameBufferTex, 0); GXPixModeSync(); GXInvalidateTexAll(); @@ -2128,9 +2208,9 @@ int mDoGph_Painter() { GXSetFogRangeAdj(GX_DISABLE, 0, NULL); GXSetCullMode(GX_CULL_NONE); GXSetDither(GX_ENABLE); - + Mtx44 mtx; - MTXOrtho(mtx, 0.0f, 1.0f, 0.0f, 1.0f, 0.0f, 10.0f); + MTXOrtho(mtx, 0.0f, 1.0f, 1.0f, 0.0f, 0.0f, 10.0f); GXSetProjection(mtx, GX_ORTHOGRAPHIC); GXLoadPosMtxImm(cMtx_getIdentity(), GX_PNMTX0); GXSetCurrentMtx(0); @@ -2139,7 +2219,7 @@ int mDoGph_Painter() { GXSetVtxDesc(GX_VA_TEX0, GX_DIRECT); GXSetVtxAttrFmt(GX_VTXFMT0, GX_VA_POS, GX_POS_XYZ, GX_S8, 0); GXSetVtxAttrFmt(GX_VTXFMT0, GX_VA_TEX0, GX_TEX_ST, GX_RGB8, 0); - drawFilterQuad(1, 1); + mDoGph_drawFilterQuad(1, 1); } #endif @@ -2166,25 +2246,25 @@ int mDoGph_Painter() { JPADrawInfo draw_info3(m5, 0.0f, FB_HEIGHT, 0.0f, FB_WIDTH); if (!dComIfGp_isPauseFlag()) { - dComIfGp_particle_draw2Dback(&draw_info3); + GX_DEBUG_GROUP(dComIfGp_particle_draw2Dback, &draw_info3); } - dComIfGp_particle_draw2DmenuBack(&draw_info3); + GX_DEBUG_GROUP(dComIfGp_particle_draw2DmenuBack, &draw_info3); ortho.setPort(); - dComIfGd_draw2DOpa(); - drawItem3D(); + GX_DEBUG_GROUP(dComIfGd_draw2DOpa); + GX_DEBUG_GROUP(drawItem3D); ortho.setPort(); #if DEBUG captureScreenSetPort(); #endif - dComIfGd_draw2DOpaTop(); - dComIfGd_draw2DXlu(); + GX_DEBUG_GROUP(dComIfGd_draw2DOpaTop); + GX_DEBUG_GROUP(dComIfGd_draw2DXlu); - if (!dComIfGp_isPauseFlag()) { - dComIfGp_particle_draw2Dfore(&draw_info3); + if (dComIfGp_isPauseFlag()) { + GX_DEBUG_GROUP(dComIfGp_particle_draw2Dfore, &draw_info3); } #if DEBUG @@ -2197,7 +2277,7 @@ int mDoGph_Painter() { mDoGph_gInf_c::calcFade(); } - dComIfGp_particle_draw2DmenuFore(&draw_info3); + GX_DEBUG_GROUP(dComIfGp_particle_draw2DmenuFore, &draw_info3); j3dSys.setViewMtx(m4); } else { // No camera window active — still draw 2D display lists @@ -2226,7 +2306,7 @@ int mDoGph_Painter() { #endif #if TARGET_PC - dusk::g_imguiConsole.draw(); + dusk::g_imguiConsole.PostDraw(); #endif mDoGph_gInf_c::endRender(); diff --git a/src/m_Do/m_Do_lib.cpp b/src/m_Do/m_Do_lib.cpp index b865d9eff8..93df5c23cc 100644 --- a/src/m_Do/m_Do_lib.cpp +++ b/src/m_Do/m_Do_lib.cpp @@ -153,8 +153,13 @@ void mDoLib_project(Vec* src, Vec* dst, JGeometry::TBox2 viewport) { xOffset = (0.5f * ((2.0f * viewport.i.x) + viewport.f.x)) - (int)(FB_WIDTH / 2); xSize = FB_WIDTH; } else { + #if TARGET_PC + xOffset = mDoGph_gInf_c::getMinXF(); + xSize = viewport.f.x * mDoGph_gInf_c::hudAspectScaleUp; + #else xOffset = viewport.i.x; xSize = viewport.f.x; + #endif } if (viewport.i.y != 0.0f) { diff --git a/src/m_Do/m_Do_machine.cpp b/src/m_Do/m_Do_machine.cpp index f50c8a6fdb..6b186a77e6 100644 --- a/src/m_Do/m_Do_machine.cpp +++ b/src/m_Do/m_Do_machine.cpp @@ -29,6 +29,10 @@ #include "DynamicLink.h" #include "os_report.h" +#if TARGET_PC +#include +#endif + #if !PLATFORM_GCN #include #include @@ -588,6 +592,7 @@ void myExceptionCallback(u16, OSContext*, u32, u32) { VIFlush(); } +#ifndef TARGET_PC static void fault_callback_scroll(u16, OSContext* p_context, u32, u32) { JUTException* manager = JUTException::getManager(); JUTConsole* exConsole = manager->getConsole(); @@ -710,6 +715,7 @@ static void fault_callback_scroll(u16, OSContext* p_context, u32, u32) { } while (true); } while (true); } +#endif static void dummy_string() { DEAD_STRING("\x1B[32m%-24s = size=%d KB\n\x1B[m"); @@ -991,6 +997,11 @@ int mDoMch_Create() { GXSetVerifyCallback((GXVerifyCallback)&myGXVerifyCallback); #endif JKRDvdRipper::setSZSBufferSize(0x4000); +#if TARGET_PC + JKRHeap* dvdHeap = JKRCreateExpHeap(0x10000, NULL, false); + assert(dvdHeap != NULL); + JKRDvdRipper::setHeap(dvdHeap); +#endif JKRDvdAramRipper::setSZSBufferSize(0x4000); JKRAram::setSZSBufferSize(0x2000); mDoDvdThd::create(OSGetThreadPriority(OSGetCurrentThread()) - 2); @@ -999,3 +1010,9 @@ int mDoMch_Create() { return 1; } + +#if TARGET_PC +void mDoMch_Destroy() { + JFWSystem::shutdown(); +} +#endif diff --git a/src/m_Do/m_Do_main.cpp b/src/m_Do/m_Do_main.cpp index a2fe24771d..edceafd01c 100644 --- a/src/m_Do/m_Do_main.cpp +++ b/src/m_Do/m_Do_main.cpp @@ -44,8 +44,13 @@ #include #include #include "SSystem/SComponent/c_API.h" +#include "dusk/app_info.hpp" #include "dusk/dusk.h" +#include "dusk/imgui/ImGuiEngine.hpp" #include "dusk/logging.h" +#include "dusk/main.h" +#include "dusk/imgui/ImGuiConsole.hpp" +#include "version.h" #include "dusk/time.h" #include @@ -54,7 +59,10 @@ #include #include +#include "SDL3/SDL_filesystem.h" #include "cxxopts.hpp" +#include "dusk/config.hpp" +#include "tracy/Tracy.hpp" // --- GLOBALS --- s8 mDoMain::developmentMode = -1; @@ -73,6 +81,10 @@ const int audioHeapSize = 0x14D800; // ========================================================================= #define COPYDATE_PATH "/str/Final/Release/COPYDATE" +#if TARGET_PC +bool dusk::IsShuttingDown = false; +#endif + s32 LOAD_COPYDATE(void*) { char buffer[32]; memset(buffer, 0, sizeof(buffer)); @@ -101,14 +113,13 @@ s32 LOAD_COPYDATE(void*) { } AuroraInfo auroraInfo; +AuroraStats dusk::lastFrameAuroraStats; +float dusk::frameUsagePct = 0.0f; +const char* configPath; void main01(void) { - #if TARGET_PC - Limiter frameLimiter{}; - #endif - OS_REPORT("\x1b[m"); - GXSetColorUpdate(GX_ENABLE); + // 1. Setup mDoMch_Create(); mDoGph_Create(); @@ -155,6 +166,9 @@ void main01(void) { case AURORA_WINDOW_RESIZED: mDoGph_gInf_c::setWindowSize(event->windowSize); break; + case AURORA_DISPLAY_SCALE_CHANGED: + dusk::ImGuiEngine_Initialize(event->windowSize.scale); + break; case AURORA_EXIT: goto exit; } @@ -173,6 +187,7 @@ void main01(void) { VIWaitForRetrace(); #if TARGET_PC + dusk::lastFrameAuroraStats = *aurora_get_stats(); if (!aurora_begin_frame()) { DuskLog.debug("aurora_begin_frame returned false, skipping draw this frame"); continue; @@ -187,9 +202,7 @@ void main01(void) { aurora_end_frame(); - #if TARGET_PC - frameLimiter.Sleep(DUSK_FRAME_PERIOD); - #endif + FrameMark; } while (true); exit:; @@ -228,10 +241,86 @@ static AuroraBackend ParseAuroraBackend(const std::string& value) { exit(1); } +static void aurora_imgui_init_callback(const AuroraWindowSize* size) { + dusk::ImGuiEngine_Initialize(size->scale); +} + +static void ApplyCVarOverrides(const cxxopts::OptionValue& option) { + if (option.count() == 0) { + return; + } + + const auto& cVars = option.as>(); + for (const auto& cvarArg : cVars) { + const auto sep = cvarArg.find('='); + if (sep == std::string::npos) { + DuskLog.fatal("--cvar argument has no '=': '{}'", cvarArg); + continue; + } + + const auto name = std::string_view(cvarArg).substr(0, sep); + const auto value = std::string_view(cvarArg).substr(sep + 1); + + const auto cVar = dusk::config::GetConfigVar(name); + if (!cVar) { + DuskLog.fatal("Unknown --cvar name: '{}'", name); + } + + try { + cVar->getImpl()->loadFromArg(*cVar, value); + } catch (const std::exception& e) { + DuskLog.fatal("Unable to parse: '{}': {}", value, e.what()); + } + } +} + +static const char* CalculateConfigPath() { + const auto result = SDL_GetPrefPath(dusk::OrgName, dusk::AppName); + if (!result) { + DuskLog.fatal("Unable to get PrefPath: {}", SDL_GetError()); + } + + return result; +} + +static constexpr PADDefaultMapping defaultPadMapping = { + .buttons = { + {SDL_GAMEPAD_BUTTON_SOUTH, PAD_BUTTON_A}, + {SDL_GAMEPAD_BUTTON_EAST, PAD_BUTTON_B}, + {SDL_GAMEPAD_BUTTON_WEST, PAD_BUTTON_X}, + {SDL_GAMEPAD_BUTTON_NORTH, PAD_BUTTON_Y}, + {SDL_GAMEPAD_BUTTON_START, PAD_BUTTON_START}, + {SDL_GAMEPAD_BUTTON_RIGHT_SHOULDER, PAD_TRIGGER_Z}, + {PAD_NATIVE_BUTTON_INVALID, PAD_TRIGGER_L}, + {PAD_NATIVE_BUTTON_INVALID, PAD_TRIGGER_R}, + {SDL_GAMEPAD_BUTTON_DPAD_UP, PAD_BUTTON_UP}, + {SDL_GAMEPAD_BUTTON_DPAD_DOWN, PAD_BUTTON_DOWN}, + {SDL_GAMEPAD_BUTTON_DPAD_LEFT, PAD_BUTTON_LEFT}, + {SDL_GAMEPAD_BUTTON_DPAD_RIGHT, PAD_BUTTON_RIGHT}, + }, + .axes = { + {{SDL_GAMEPAD_AXIS_LEFTX, AXIS_SIGN_POSITIVE}, SDL_GAMEPAD_BUTTON_INVALID, PAD_AXIS_LEFT_X_POS}, + {{SDL_GAMEPAD_AXIS_LEFTX, AXIS_SIGN_NEGATIVE}, SDL_GAMEPAD_BUTTON_INVALID, PAD_AXIS_LEFT_X_NEG}, + // SDL's gamepad y-axis is inverted from GC's + {{SDL_GAMEPAD_AXIS_LEFTY, AXIS_SIGN_NEGATIVE}, SDL_GAMEPAD_BUTTON_INVALID, PAD_AXIS_LEFT_Y_POS}, + {{SDL_GAMEPAD_AXIS_LEFTY, AXIS_SIGN_POSITIVE}, SDL_GAMEPAD_BUTTON_INVALID, PAD_AXIS_LEFT_Y_NEG}, + {{SDL_GAMEPAD_AXIS_RIGHTX, AXIS_SIGN_POSITIVE}, SDL_GAMEPAD_BUTTON_INVALID, PAD_AXIS_RIGHT_X_POS}, + {{SDL_GAMEPAD_AXIS_RIGHTX, AXIS_SIGN_NEGATIVE}, SDL_GAMEPAD_BUTTON_INVALID, PAD_AXIS_RIGHT_X_NEG}, + // see above + {{SDL_GAMEPAD_AXIS_RIGHTY, AXIS_SIGN_NEGATIVE}, SDL_GAMEPAD_BUTTON_INVALID, PAD_AXIS_RIGHT_Y_POS}, + {{SDL_GAMEPAD_AXIS_RIGHTY, AXIS_SIGN_POSITIVE}, SDL_GAMEPAD_BUTTON_INVALID, PAD_AXIS_RIGHT_Y_NEG}, + {{SDL_GAMEPAD_AXIS_LEFT_TRIGGER, AXIS_SIGN_POSITIVE}, SDL_GAMEPAD_BUTTON_INVALID, PAD_AXIS_TRIGGER_L}, + {{SDL_GAMEPAD_AXIS_RIGHT_TRIGGER, AXIS_SIGN_POSITIVE}, SDL_GAMEPAD_BUTTON_INVALID, PAD_AXIS_TRIGGER_R}, + }, +}; + // ========================================================================= // PC ENTRY POINT // ========================================================================= int game_main(int argc, char* argv[]) { + dusk::registerSettings(); + dusk::config::FinishRegistration(); + cxxopts::ParseResult parsed_arg_options; try { @@ -241,7 +330,8 @@ int game_main(int argc, char* argv[]) { ("l,log-level", "Log level from " + std::to_string(AuroraLogLevel::LOG_DEBUG) + " to " + std::to_string(AuroraLogLevel::LOG_FATAL), cxxopts::value()->default_value("0")) ("h,help", "Print usage") ("dvd", "Path to DVD image file", cxxopts::value()->default_value("game.iso")) - ("backend", "Graphics API backend to use (auto, d3d11, d3d12, metal, vulkan, opengl, opengles, webgpu, null)", cxxopts::value()->default_value("auto")); + ("backend", "Graphics API backend to use (auto, d3d11, d3d12, metal, vulkan, opengl, opengles, webgpu, null)", cxxopts::value()->default_value("auto")) + ("cvar", "Override configuration variables without modifying config", cxxopts::value>()); arg_options.parse_positional({"dvd"}); arg_options.positional_help(""); @@ -260,22 +350,36 @@ int game_main(int argc, char* argv[]) { exit(1); } + configPath = CalculateConfigPath(); + + dusk::config::LoadFromUserPreferences(); + ApplyCVarOverrides(parsed_arg_options["cvar"]); + AuroraConfig config{}; - config.appName = "Dusk"; + config.appName = dusk::AppName; + config.configPath = configPath; + config.vsync = dusk::getSettings().video.enableVsync; + config.startFullscreen = dusk::getSettings().video.enableFullscreen; config.windowPosX = -1; config.windowPosY = -1; - config.windowWidth = 608 * 2; - config.windowHeight = 448 * 2; + config.windowWidth = defaultWindowWidth * 2; + config.windowHeight = defaultWindowHeight * 2; config.desiredBackend = ParseAuroraBackend(parsed_arg_options["backend"].as()); - config.configPath = "."; config.logCallback = &aurora_log_callback; config.logLevel = (AuroraLogLevel)parsed_arg_options["log-level"].as(); config.mem1Size = 256 * 1024 * 1024; config.mem2Size = 24 * 1024 * 1024; config.allowJoystickBackgroundEvents = true; + config.imGuiInitCallback = &aurora_imgui_init_callback; + + PADSetDefaultMapping(&defaultPadMapping); auroraInfo = aurora_initialize(argc, argv, &config); + VISetWindowTitle( + fmt::format("Dusk {} [{}]", DUSK_WC_DESCRIBE, dusk::backend_name(auroraInfo.backend)) + .c_str()); + const auto& dvd_path = parsed_arg_options["dvd"].as(); DuskLog.info("Loading DVD image: {}", dvd_path); if (!aurora_dvd_open(dvd_path.c_str())) { @@ -307,6 +411,11 @@ int game_main(int argc, char* argv[]) { fflush(stdout); fflush(stderr); + mDoMch_Destroy(); + + // Notifies all CVs and causes threads to exit + OSResetSystem(OS_RESET_SHUTDOWN, 0, 0); + aurora_shutdown(); return 0; diff --git a/src/m_Do/m_Do_printf.cpp b/src/m_Do/m_Do_printf.cpp index f4ef1fad00..3cacece77d 100644 --- a/src/m_Do/m_Do_printf.cpp +++ b/src/m_Do/m_Do_printf.cpp @@ -21,6 +21,10 @@ u8 __OSReport_System_disable; u8 __OSReport_enable; +#if TARGET_PC +bool dusk::OSReportReallyForceEnable = false; +#endif + #ifdef __GEKKO__ asm void OSSwitchFiberEx(__REGISTER u32 param_0, __REGISTER u32 param_1, __REGISTER u32 param_2, __REGISTER u32 param_3, __REGISTER u32 code, __REGISTER u32 stack) { nofralloc @@ -153,6 +157,9 @@ void mDoPrintf_vprintf_Thread(char const* fmt, va_list args) { #endif vprintf(fmt, args); + if (dusk::OSReportReallyForceEnable) { + fflush(stdout); + } #if DEBUG if (thread != NULL) { @@ -170,12 +177,16 @@ void mDoPrintf_vprintf(char const* fmt, va_list args) { #if DEBUG mDoPrintf_vprintf_Thread(fmt, args); #else +#if !TARGET_PC u8* stackPtr = (u8*)OSGetStackPointer(); if (stackPtr < (u8*)currentThread->stackEnd + 0xA00 || stackPtr > currentThread->stackBase) { mDoPrintf_vprintf_Interrupt(fmt, args); } else { +#endif mDoPrintf_vprintf_Thread(fmt, args); +#if !TARGET_PC } +#endif #endif } } @@ -184,7 +195,11 @@ void mDoPrintf_VReport(const char* fmt, va_list args) { if (!print_initialized) { OSReportInit(); } +#if TARGET_PC + if (dusk::OSReportReallyForceEnable || __OSReport_enable || !__OSReport_disable) { +#else if (__OSReport_enable || !__OSReport_disable) { +#endif OSThread* currentThread = mDoExt_GetCurrentRunningThread(); if (__OSReport_MonopolyThread == NULL || __OSReport_MonopolyThread == currentThread) { mDoPrintf_vprintf(fmt, args); diff --git a/version.h.in b/version.h.in new file mode 100644 index 0000000000..c85a6dc659 --- /dev/null +++ b/version.h.in @@ -0,0 +1,20 @@ +#ifndef VERSION_H +#define VERSION_H + +#define DUSK_WC_DESCRIBE "@DUSK_WC_DESCRIBE@" +#define DUSK_VERSION_STRING "@DUSK_VERSION_STRING@" + +#define DUSK_WC_BRANCH "@DUSK_WC_BRANCH@" +#define DUSK_WC_REVISION "@DUSK_WC_REVISION@" +#define DUSK_WC_DATE "@DUSK_WC_DATE@" +#define DUSK_BUILD_TYPE "@CMAKE_BUILD_TYPE@" + +#if defined(__x86_64__) || defined(_M_AMD64) +#define DUSK_DLPACKAGE "dusk-@DUSK_WC_DESCRIBE@-@PLATFORM_NAME@-x86_64" +#elif defined(__i386__) || defined(_M_IX86) +#define DUSK_DLPACKAGE "dusk-@DUSK_WC_DESCRIBE@-@PLATFORM_NAME@-x86" +#elif defined(__aarch64__) || defined(_M_ARM64) +#define DUSK_DLPACKAGE "dusk-@DUSK_WC_DESCRIBE@-@PLATFORM_NAME@-arm64" +#endif + +#endif