diff --git a/CMakeLists.txt b/CMakeLists.txt index e3fbb82437..66c86bb5f4 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -71,6 +71,12 @@ FetchContent_Declare( ) FetchContent_MakeAvailable(cxxopts) +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(json) include(files.cmake) @@ -88,9 +94,35 @@ message(STATUS "dusk: TP 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) + +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) + +if (DUSK_MOVIE_SUPPORT_REAL) + if (TARGET libjpeg-turbo::turbojpeg-static) + message(STATUS "dusk: Linking against libjpeg-turbo static library") + list(APPEND GAME_LIBS "libjpeg-turbo::turbojpeg-static") + else () + message(STATUS "dusk: Linking against libjpeg-turbo shared library") + 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} +add_library(game_debug OBJECT ${JSYSTEM_DEBUG_FILES} ${SSYSTEM_FILES} src/dusk/audio/DuskAudioSystem.cpp src/dusk/audio/JASCriticalSection.cpp src/dusk/audio/DuskDsp.hpp @@ -98,40 +130,33 @@ add_library(game_debug STATIC ${JSYSTEM_DEBUG_FILES} ${SSYSTEM_FILES} src/dusk/audio/Adpcm.cpp src/dusk/audio/Adpcm.hpp src/dusk/audio/DspStub.cpp) -target_compile_definitions(game_debug PRIVATE TARGET_PC AVOID_UB=1 VERSION=0 $<$:DEBUG=1>) -# 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 - libs - 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 freeverb) - -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} +# 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} src/dusk/imgui/ImGuiStubLog.cpp src/dusk/imgui/ImGuiAudio.cpp) -target_link_libraries(game PRIVATE game_debug cxxopts::cxxopts absl::flat_hash_map freeverb) -if (DUSK_MOVIE_SUPPORT_REAL) - if (TARGET libjpeg-turbo::turbojpeg-static) - message(STATUS "dusk: Linking against libjpeg-turbo static library") - target_link_libraries(game PRIVATE libjpeg-turbo::turbojpeg-static) - else () - message(STATUS "dusk: Linking against libjpeg-turbo shared library") - target_link_libraries(game PRIVATE libjpeg-turbo::turbojpeg) - endif () - target_compile_definitions(game PRIVATE MOVIE_SUPPORT=1) -endif () -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}") -target_precompile_headers(game PRIVATE "$<$:${CMAKE_SOURCE_DIR}/include/dusk_pch.hpp>") +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}) + 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) @@ -145,7 +170,7 @@ add_custom_command(TARGET dusk POST_BUILD ) 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") diff --git a/README.md b/README.md index 200913770a..59f12abc2a 100644 --- a/README.md +++ b/README.md @@ -37,25 +37,24 @@ 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 cd dusk git pull git submodule update --recursive ``` -2. Generate assets -```sh -cp /path/to/GZ2E01.iso orig/GZ2E01/. -python3 ./configure.py -ninja -``` #### Building **Visual Studio (Recommended for Windows)** ```sh cmake -B build/dusk -G "Visual Studio 17 2022" -A x64 # Win32 for 32bit ``` + +**Visual Studio Code with ninja** + +Project has support for the CMakeTools extension with variants and has a debug launch target + **ninja (Windows/macOS/Linux)** ```sh cmake -B build/dusk -GNinja diff --git a/extern/aurora b/extern/aurora index b17da31593..f5c5917832 160000 --- a/extern/aurora +++ b/extern/aurora @@ -1 +1 @@ -Subproject commit b17da315932b85d7d708eaf3e44914f70045a44e +Subproject commit f5c59178322c31b42676f49dd24e760e3b014f24 diff --git a/files.cmake b/files.cmake index 278ecdb815..e9149a1777 100644 --- a/files.cmake +++ b/files.cmake @@ -1332,17 +1332,24 @@ 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 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/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_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_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_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_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/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/DuskAudioSystem.h b/include/dusk/audio/DuskAudioSystem.h index 1b31db6e7c..724776f5f1 100644 --- a/include/dusk/audio/DuskAudioSystem.h +++ b/include/dusk/audio/DuskAudioSystem.h @@ -8,6 +8,8 @@ namespace dusk::audio { */ void Initialize(); + void SetEnableReverb(bool value); + void SetMasterVolume(f32 value); u32 GetResetCount(int channelIdx); 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..064d37028d --- /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 + explicit 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 744b0f9152..a466f10a88 100644 --- a/include/dusk/dusk.h +++ b/include/dusk/dusk.h @@ -3,7 +3,14 @@ #include +#include "aurora/gfx.h" + extern AuroraInfo auroraInfo; +extern const char* configPath; + +namespace dusk { + extern AuroraStats lastFrameAuroraStats; +} constexpr u32 defaultWindowWidth = 608; constexpr u32 defaultWindowHeight = 448; 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/hotkeys.h b/include/dusk/hotkeys.h index c40f35925f..6e98d62521 100644 --- a/include/dusk/hotkeys.h +++ b/include/dusk/hotkeys.h @@ -3,7 +3,11 @@ 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"; 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/settings.h b/include/dusk/settings.h index b4ded9f83e..524f8cbcc0 100644 --- a/include/dusk/settings.h +++ b/include/dusk/settings.h @@ -1,8 +1,12 @@ #ifndef DUSK_CONFIG_H #define DUSK_CONFIG_H +#include "dusk/config_var.hpp" + namespace dusk { +using namespace config; + // Persistent user settings struct UserSettings { @@ -10,62 +14,66 @@ struct UserSettings { struct { // Video - bool enableFullscreen; - bool lockAspectRatio; + ConfigVar enableFullscreen; + ConfigVar enableVsync; + ConfigVar lockAspectRatio; } video; struct { // Audio - int masterVolume; - int mainMusicVolume; - int subMusicVolume; - int soundEffectsVolume; - int fanfareVolume; - bool enableReverb; + ConfigVar masterVolume; + ConfigVar mainMusicVolume; + ConfigVar subMusicVolume; + ConfigVar soundEffectsVolume; + ConfigVar fanfareVolume; + ConfigVar enableReverb; } audio; // Game settings struct { // QoL - bool enableQuickTransform; - bool hideTvSettingsScreen; - bool biggerWallets; - bool noReturnRupees; - bool disableRupeeCutscenes; - bool noSwordRecoil; - int damageMultiplier; - bool instantDeath; - bool fastClimbing; - bool noMissClimbing; - bool fastTears; + ConfigVar enableQuickTransform; + ConfigVar hideTvSettingsScreen; + ConfigVar biggerWallets; + ConfigVar noReturnRupees; + ConfigVar disableRupeeCutscenes; + ConfigVar noSwordRecoil; + ConfigVar damageMultiplier; + ConfigVar instantDeath; + ConfigVar fastClimbing; + ConfigVar noMissClimbing; + ConfigVar fastTears; // Preferences - bool enableMirrorMode; - bool invertCameraXAxis; + ConfigVar enableMirrorMode; + ConfigVar invertCameraXAxis; // Graphics - bool enableBloom; - bool useWaterProjectionOffset; + ConfigVar enableBloom; + ConfigVar useWaterProjectionOffset; // Audio - bool noLowHpSound; - bool midnasLamentNonStop; + ConfigVar noLowHpSound; + ConfigVar midnasLamentNonStop; // Cheats - bool enableFastIronBoots; - bool canTransformAnywhere; + ConfigVar enableFastIronBoots; + ConfigVar canTransformAnywhere; + ConfigVar fastSpinner; // Technical - bool restoreWiiGlitches; + ConfigVar restoreWiiGlitches; // Controls - bool enableTurboKeybind; + ConfigVar enableTurboKeybind; } game; }; UserSettings& getSettings(); +void registerSettings(); + // Transient settings struct CollisionViewSettings { diff --git a/include/m_Do/m_Do_graphic.h b/include/m_Do/m_Do_graphic.h index 3d560efeb6..421e1ae47f 100644 --- a/include/m_Do/m_Do_graphic.h +++ b/include/m_Do/m_Do_graphic.h @@ -8,7 +8,7 @@ #include #endif -#if WIDESCREEN_SUPPORT +#if WIDESCREEN_SUPPORT && !TARGET_PC #define FB_WIDTH (640) #define FB_HEIGHT (456) #else @@ -117,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); } @@ -266,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(); 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/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/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/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/JAudio2/JASSeqParser.cpp b/libs/JSystem/src/JAudio2/JASSeqParser.cpp index 7b417f2c82..376ec22b4c 100644 --- a/libs/JSystem/src/JAudio2/JASSeqParser.cpp +++ b/libs/JSystem/src/JAudio2/JASSeqParser.cpp @@ -884,6 +884,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 +906,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; } diff --git a/libs/JSystem/src/JFramework/JFWSystem.cpp b/libs/JSystem/src/JFramework/JFWSystem.cpp index b4effd547a..d6322f34c9 100644 --- a/libs/JSystem/src/JFramework/JFWSystem.cpp +++ b/libs/JSystem/src/JFramework/JFWSystem.cpp @@ -116,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/JKernel/JKRAram.cpp b/libs/JSystem/src/JKernel/JKRAram.cpp index 32afe1cef4..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, diff --git a/libs/JSystem/src/JKernel/JKRDecomp.cpp b/libs/JSystem/src/JKernel/JKRDecomp.cpp index 776823531d..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}; @@ -34,15 +43,15 @@ void* JKRDecomp::run() { OSInitMessageQueue(&sMessageQueue, sMessageBuffer, 8); for (;;) { OSMessage message; -#ifdef TARGET_PC - if (!OSReceiveMessage(&sMessageQueue, &message, OS_MESSAGE_BLOCK)) { - break; - } -#else OSReceiveMessage(&sMessageQueue, &message, OS_MESSAGE_BLOCK); -#endif 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) { 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/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/src/d/actor/d_a_alink_effect.inc b/src/d/actor/d_a_alink_effect.inc index 6e76280ff6..1c02cb54f0 100644 --- a/src/d/actor/d_a_alink_effect.inc +++ b/src/d/actor/d_a_alink_effect.inc @@ -1562,6 +1562,11 @@ void daAlink_c::setMetamorphoseEffectStartLink() { emitter->setGlobalParticleScale(effScale); } #endif + + #if TARGET_PC + static const Vec effWideScale = {mDoGph_gInf_c::getAspect(), 1.0f, 1.0f}; + emitter->setGlobalParticleScale(effWideScale); + #endif } void daAlink_c::setMetamorphoseEffect() { 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_demo00.cpp b/src/d/actor/d_a_demo00.cpp index 99ad6c1587..871e9ebca6 100644 --- a/src/d/actor/d_a_demo00.cpp +++ b/src/d/actor/d_a_demo00.cpp @@ -1658,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_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_mant.cpp b/src/d/actor/d_a_mant.cpp index a3b48f1098..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); diff --git a/src/d/actor/d_a_movie_player.cpp b/src/d/actor/d_a_movie_player.cpp index 4573684b2f..c3074ac877 100644 --- a/src/d/actor/d_a_movie_player.cpp +++ b/src/d/actor/d_a_movie_player.cpp @@ -4473,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_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_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_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_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_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_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_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_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_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_flower.inc b/src/d/actor/d_flower.inc index 762b1e02e9..4fb53ffaa7 100644 --- a/src/d/actor/d_flower.inc +++ b/src/d/actor/d_flower.inc @@ -13,7 +13,13 @@ 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, @@ -104,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" @@ -113,6 +129,7 @@ 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; @@ -122,7 +139,12 @@ 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, @@ -249,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" @@ -260,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; @@ -521,6 +556,32 @@ 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 @@ -553,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, false); - GXSETARRAY(GX_VA_NRM, &l_flowerNormal, sizeof(l_flowerNormal), 0xC, false); - GXSETARRAY(GX_VA_CLR0, &l_flowerColor, sizeof(l_flowerColor), 4, false); - GXSETARRAY(GX_VA_TEX0, &l_flowerTexCoord, sizeof(l_flowerTexCoord), 8, false); + 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; @@ -584,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); @@ -642,9 +703,9 @@ void dFlower_packet_c::draw() { #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); } } } @@ -652,9 +713,9 @@ void dFlower_packet_c::draw() { sp5C++; } - GXSETARRAY(GX_VA_POS, mp_pos, sizeof(l_flowerPos2), 0xC, true); - GXSETARRAY(GX_VA_NRM, &l_flowerNormal2, sizeof(l_flowerNormal2), 0xC, false); - GXSETARRAY(GX_VA_CLR0, mp_colors, sizeof(l_flowerColor2), 4, true); + 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; @@ -791,7 +852,7 @@ void dFlower_packet_c::draw() { 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 6351cc75fc..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; 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_error_msg.cpp b/src/d/d_error_msg.cpp index faa40ae543..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,16 +243,12 @@ 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) { -#if TARGET_PC - GXSetTexCopySrc(0, 0, mDoGph_gInf_c::getWidth(), mDoGph_gInf_c::getHeight()); - GXSetTexCopyDst(mDoGph_gInf_c::getWidth(), mDoGph_gInf_c::getHeight(), (GXTexFmt)mDoGph_gInf_c::getFrameBufferTimg()->format, GX_TRUE); -#else GXSetTexCopySrc(0, 0, FB_WIDTH, FB_HEIGHT); GXSetTexCopyDst(FB_WIDTH / 2, FB_HEIGHT / 2, (GXTexFmt)mDoGph_gInf_c::getFrameBufferTimg()->format, GX_TRUE); -#endif GXCopyTex(mDoGph_gInf_c::getFrameBufferTex(), GX_FALSE); l_texCopied = true; } @@ -256,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); @@ -298,6 +297,7 @@ static void drawCapture(u8 alpha) { mDoGph_drawFilterQuad(1, 1); mDoGph_gInf_c::endRender(); JFWDisplay::getManager()->resetFader(); + #endif } bool dShutdownErrorMsg_c::execute() { @@ -325,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..f63403d886 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; @@ -2091,7 +2095,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 +2252,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 +3140,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 +3277,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 +3673,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 +3720,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 +3767,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_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 ec35ee8bc7..b9262bab23 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 @@ -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 @@ -1175,7 +1176,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) { @@ -10977,7 +10978,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 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..c1927c5875 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; @@ -4111,7 +4121,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 +4262,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 +4648,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 +4917,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 +4972,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 +6018,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 +6248,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_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_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_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_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_option.cpp b/src/d/d_menu_option.cpp index abe9f864ce..9384bc06b9 100644 --- a/src/d/d_menu_option.cpp +++ b/src/d/d_menu_option.cpp @@ -555,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); diff --git a/src/d/d_menu_save.cpp b/src/d/d_menu_save.cpp index ef1fb9d61e..eb7b6a35b8 100644 --- a/src/d/d_menu_save.cpp +++ b/src/d/d_menu_save.cpp @@ -56,7 +56,11 @@ static dMs_HIO_c g_msHIO; dMs_HIO_c::dMs_HIO_c() { mDisplayWaitFrames = 15; + #if TARGET_PC + mCardWaitFrames = 0; + #else mCardWaitFrames = 90; + #endif mEffectDispFrames = 5; mCharSwitchFrames = 5; mSelectIcon = 5; @@ -384,7 +388,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); @@ -2516,7 +2525,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 +2678,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 +2782,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 +2826,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 3e173049bd..7fd5ea31a2 100644 --- a/src/d/d_menu_window.cpp +++ b/src/d/d_menu_window.cpp @@ -32,7 +32,7 @@ public: if (getDrawFlag() == 1) { setDrawFlag(); dComIfGp_onPauseFlag(); - + #if TARGET_PC GXSetTexCopySrc(0, 0, mDoGph_gInf_c::getWidth(), mDoGph_gInf_c::getHeight()); #else @@ -46,17 +46,23 @@ public: #endif GXCopyTex(mDoGph_gInf_c::getFrameBufferTex(), GX_FALSE); GXPixModeSync(); - } else { - TGXTexObj tex; #if TARGET_PC - GXInitTexObj(&tex, mDoGph_gInf_c::getFrameBufferTex(), mDoGph_gInf_c::getWidth(), mDoGph_gInf_c::getHeight(), + // 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); -#endif 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); @@ -119,6 +125,9 @@ private: /* 0x4 */ u8 mFlag; /* 0x5 */ u8 mAlpha; /* 0x6 */ u8 mTopFlag; +#if TARGET_PC + TGXTexObj mTexObj; +#endif }; BOOL dMw_UP_TRIGGER() { @@ -1507,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 3e8d2601c1..7307755c04 100644 --- a/src/d/d_meter2_info.cpp +++ b/src/d/d_meter2_info.cpp @@ -1639,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; @@ -1868,12 +1868,16 @@ f32 dMeter2Info_getWide2DPosX(f32* 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 diff --git a/src/d/d_meter_HIO.cpp b/src/d/d_meter_HIO.cpp index 685f9c580c..94b1c79420 100644 --- a/src/d/d_meter_HIO.cpp +++ b/src/d/d_meter_HIO.cpp @@ -2287,7 +2287,18 @@ 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.mRupeeKeyPosX = mDoGph_gInf_c::ScaleHUDXRight(g_drawHIO.mRupeeKeyPosX); + 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 +3014,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 7e55d899fd..b5900a4be5 100644 --- a/src/d/d_meter_map.cpp +++ b/src/d/d_meter_map.cpp @@ -596,7 +596,8 @@ void dMeterMap_c::_draw() { #if TARGET_PC // Optimization: don't draw map if it's off-screen/invisible. // Especially useful in debug builds on Hyrule field etc., it's slow! - if ((!mMapIsInside && mSlidePositionOffset == getDispPosOutSide_OffsetX()) || mMapAlpha == 0) { + // That +3 is an arbitrary bias to avoid rounding issues causing this to fail. + if ((!mMapIsInside && mSlidePositionOffset <= getDispPosOutSide_OffsetX() + 3) || mMapAlpha == 0) { return; } #endif @@ -628,7 +629,13 @@ void dMeterMap_c::draw() { #endif mMapJ2DPicture->setAlpha(alpha); + #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(); } } diff --git a/src/d/d_msg_object.cpp b/src/d/d_msg_object.cpp index 8836acff10..3676639908 100644 --- a/src/d/d_msg_object.cpp +++ b/src/d/d_msg_object.cpp @@ -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) { diff --git a/src/d/d_msg_scrn_item.cpp b/src/d/d_msg_scrn_item.cpp index bb4daf3927..7cba6c7b86 100644 --- a/src/d/d_msg_scrn_item.cpp +++ b/src/d/d_msg_scrn_item.cpp @@ -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_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 70304451fb..d6f432f3ee 100644 --- a/src/d/d_ovlp_fade3.cpp +++ b/src/d/d_ovlp_fade3.cpp @@ -64,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_stage.cpp b/src/d/d_stage.cpp index 057bcdf4ff..f3cdfed17b 100644 --- a/src/d/d_stage.cpp +++ b/src/d/d_stage.cpp @@ -393,13 +393,7 @@ static void dummy1(dStage_roomControl_c* roomControl) { JKRExpHeap* dStage_roomControl_c::createMemoryBlock(int i_blockIdx, u32 i_heapSize) { #if TARGET_PC - // Cave of Ordeals crashes around floor 29 due to no free heap space - // Increasing the size here avoids that, though its ugly. maybe TODO a better fix - if (strcmp(dComIfGp_getStartStageName(), "D_SB01") == 0) { - u32 prev = i_heapSize; - i_heapSize *= 2; - DuskLog.warn("Doubling heap size for D_SB01... ({}) -> ({})", prev, i_heapSize); - } + i_heapSize *= 2; #endif if (mMemoryBlock[i_blockIdx] == NULL) { diff --git a/src/dusk/OSContext.cpp b/src/dusk/OSContext.cpp index 9aa6932e52..d2bb1803ea 100644 --- a/src/dusk/OSContext.cpp +++ b/src/dusk/OSContext.cpp @@ -23,16 +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; + // No-op on PC } void OSDumpContext(OSContext* context) { diff --git a/src/dusk/OSThread.cpp b/src/dusk/OSThread.cpp index ea9c568eef..af339e8656 100644 --- a/src/dusk/OSThread.cpp +++ b/src/dusk/OSThread.cpp @@ -101,7 +101,7 @@ static thread_local OSThread* tls_currentThread = nullptr; static OSThread sDefaultThread; static u8 sDefaultStack[64 * 1024]; -static u32 sDefaultStackEnd = OS_THREAD_STACK_MAGIC; +static u8 sDefaultStackEnd = OS_THREAD_STACK_MAGIC; // Global interrupt mutex (coarse-grained lock replacing interrupt disable) // Lazy-initialized to avoid DLL static init crashes @@ -237,7 +237,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); @@ -496,7 +496,7 @@ void OSDetachThread(OSThread* thread) { 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)) { diff --git a/src/dusk/audio/DuskAudioSystem.cpp b/src/dusk/audio/DuskAudioSystem.cpp index c7313749c2..7b464e4f0e 100644 --- a/src/dusk/audio/DuskAudioSystem.cpp +++ b/src/dusk/audio/DuskAudioSystem.cpp @@ -76,6 +76,12 @@ void dusk::audio::SetMasterVolume(const f32 value) { MasterVolume = value; } +void dusk::audio::SetEnableReverb(const bool value) { + JASCriticalSection section; + + EnableReverb = value; +} + void SDLCALL GetNewAudio( void*, SDL_AudioStream*, 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/ImGuiConfig.hpp b/src/dusk/imgui/ImGuiConfig.hpp new file mode 100644 index 0000000000..fc5aa34bbd --- /dev/null +++ b/src/dusk/imgui/ImGuiConfig.hpp @@ -0,0 +1,41 @@ +#ifndef DUSK_IMGUICONFIG_HPP +#define DUSK_IMGUICONFIG_HPP + +#include "dusk/config.hpp" +#include "imgui.h" + +namespace dusk::config { + inline void ImGuiCheckbox(const char* title, ConfigVar& var) { + bool copy = var.getValue(); + if (ImGui::Checkbox(title, ©)) { + var.setValue(copy); + Save(); + } + } + + static void 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(); + } + } + + static void 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(); + } + } + + static void 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(); + } + } +} + +#endif // DUSK_IMGUICONFIG_HPP diff --git a/src/dusk/imgui/ImGuiConsole.cpp b/src/dusk/imgui/ImGuiConsole.cpp index 7efa6c3314..e0ca351e4f 100644 --- a/src/dusk/imgui/ImGuiConsole.cpp +++ b/src/dusk/imgui/ImGuiConsole.cpp @@ -7,13 +7,15 @@ #include "fmt/format.h" #include "imgui.h" -#include "aurora/gfx.h" #include #include "ImGuiConsole.hpp" #include "JSystem/JUtility/JUTGamePad.h" +#include "dusk/config.hpp" #include "dusk/settings.h" +#include "dusk/audio/DuskAudioSystem.h" +#include "dusk/dusk.h" #if _WIN32 #define NOMINMAX @@ -177,13 +179,30 @@ namespace dusk { ImGuiConsole::ImGuiConsole() {} + void ImGuiConsole::InitSettings() { + bool lockAspect = getSettings().video.lockAspectRatio; + if (lockAspect) { + VILockAspectRatio(defaultAspectRatioW, defaultAspectRatioH); + } else { + VIUnlockAspectRatio(); + } + } + + void ImGuiConsole::UpdateSettings() { + dusk::audio::SetMasterVolume(dusk::getSettings().audio.masterVolume / 100.0f); + dusk::audio::SetEnableReverb(dusk::getSettings().audio.enableReverb); + getTransientSettings().skipFrameRateLimit = getSettings().game.enableTurboKeybind && ImGui::IsKeyDown(ImGuiKey_Tab); + } + void ImGuiConsole::PreDraw() { if (!m_isLaunchInitialized) { + InitSettings(); + m_toasts.emplace_back("Press F1 to toggle menu"s, 5.f); m_isLaunchInitialized = true; } - getTransientSettings().skipFrameRateLimit = getSettings().game.enableTurboKeybind && ImGui::IsKeyDown(ImGuiKey_Tab); + UpdateSettings(); if ((ImGui::IsKeyDown(ImGuiKey_LeftCtrl) || ImGui::IsKeyDown(ImGuiKey_RightCtrl)) && ImGui::IsKeyPressed(ImGuiKey_R)) @@ -192,8 +211,7 @@ namespace dusk { } if (ImGui::IsKeyPressed(ImGuiKey_F11)) { - getSettings().video.enableFullscreen = !getSettings().video.enableFullscreen; - VISetWindowFullscreen(getSettings().video.enableFullscreen); + ImGuiMenuGame::ToggleFullscreen(); } if (CheckMenuViewToggle(ImGuiKey_F1, m_isHidden)) { diff --git a/src/dusk/imgui/ImGuiConsole.hpp b/src/dusk/imgui/ImGuiConsole.hpp index 27032ed39b..3d13e2ed6d 100644 --- a/src/dusk/imgui/ImGuiConsole.hpp +++ b/src/dusk/imgui/ImGuiConsole.hpp @@ -14,6 +14,8 @@ namespace dusk { class ImGuiConsole { public: ImGuiConsole(); + void InitSettings(); + void UpdateSettings(); void PreDraw(); void PostDraw(); diff --git a/src/dusk/imgui/ImGuiMenuEnhancements.cpp b/src/dusk/imgui/ImGuiMenuEnhancements.cpp index 3069d9b3f6..e9404e2476 100644 --- a/src/dusk/imgui/ImGuiMenuEnhancements.cpp +++ b/src/dusk/imgui/ImGuiMenuEnhancements.cpp @@ -1,7 +1,7 @@ #include "imgui.h" #include "ImGuiMenuEnhancements.hpp" - +#include "ImGuiConfig.hpp" #include "dusk/settings.h" namespace dusk { @@ -10,45 +10,45 @@ namespace dusk { void ImGuiMenuEnhancements::draw() { if (ImGui::BeginMenu("Enhancements")) { if (ImGui::BeginMenu("Quality of Life")) { - ImGui::Checkbox("Quick Transform (R+Y)", &getSettings().game.enableQuickTransform); + config::ImGuiCheckbox("Quick Transform (R+Y)", getSettings().game.enableQuickTransform); - ImGui::Checkbox("Bigger Wallets", &getSettings().game.biggerWallets); + config::ImGuiCheckbox("Bigger Wallets", getSettings().game.biggerWallets); if (ImGui::IsItemHovered()) { ImGui::SetTooltip("Wallet sizes are like in the HD version (500, 1000, 2000)"); } - ImGui::Checkbox("No Rupee Returns", &getSettings().game.noReturnRupees); + config::ImGuiCheckbox("No Rupee Returns", getSettings().game.noReturnRupees); if (ImGui::IsItemHovered()) { ImGui::SetTooltip("Always collect Rupees even if your Wallet is too full"); } - ImGui::Checkbox("Disable Rupee Cutscenes", &getSettings().game.disableRupeeCutscenes); + 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"); } - ImGui::Checkbox("No Sword Recoil", &getSettings().game.noSwordRecoil); + config::ImGuiCheckbox("No Sword Recoil", getSettings().game.noSwordRecoil); if (ImGui::IsItemHovered()) { ImGui::SetTooltip("Link won't recoil when his sword hits walls"); } - ImGui::Checkbox("Faster Climbing", &getSettings().game.fastClimbing); + config::ImGuiCheckbox("Faster Climbing", getSettings().game.fastClimbing); if (ImGui::IsItemHovered()) { ImGui::SetTooltip("Quicker climbing on ladders and vines like the HD version"); } - ImGui::Checkbox("No Climbing Miss Animation", &getSettings().game.noMissClimbing); + 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"); } - ImGui::Checkbox("Faster Tears of Light", &getSettings().game.fastTears); + 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"); } - ImGui::Checkbox("Hide TV Settings Screen", &getSettings().game.hideTvSettingsScreen); + config::ImGuiCheckbox("Hide TV Settings Screen", getSettings().game.hideTvSettingsScreen); if (ImGui::IsItemHovered()) { ImGui::SetTooltip("Hides the TV calibration screen shown when loading a save"); } @@ -57,20 +57,20 @@ namespace dusk { } if (ImGui::BeginMenu("Preferences")) { - ImGui::Checkbox("Mirror Mode", &getSettings().game.enableMirrorMode); + config::ImGuiCheckbox("Mirror Mode", getSettings().game.enableMirrorMode); if (ImGui::IsItemHovered()) { ImGui::SetTooltip("Mirrors the world, matching the Wii version of the game"); } - ImGui::Checkbox("Invert Camera X Axis", &getSettings().game.invertCameraXAxis); + config::ImGuiCheckbox("Invert Camera X Axis", getSettings().game.invertCameraXAxis); ImGui::EndMenu(); } if (ImGui::BeginMenu("Graphics")) { - ImGui::Checkbox("Native Bloom", &getSettings().game.enableBloom); + config::ImGuiCheckbox("Native Bloom", getSettings().game.enableBloom); - ImGui::Checkbox("Water Projection Offset", &getSettings().game.useWaterProjectionOffset); + 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"); @@ -80,12 +80,12 @@ namespace dusk { } if (ImGui::BeginMenu("Audio")) { - ImGui::Checkbox("No Low HP Sound", &getSettings().game.noLowHpSound); + config::ImGuiCheckbox("No Low HP Sound", getSettings().game.noLowHpSound); if (ImGui::IsItemHovered()) { ImGui::SetTooltip("Disable the beeping sound when having low health"); } - ImGui::Checkbox("Non-Stop Midna's Lament", &getSettings().game.midnasLamentNonStop); + config::ImGuiCheckbox("Non-Stop Midna's Lament", getSettings().game.midnasLamentNonStop); if (ImGui::IsItemHovered()) { ImGui::SetTooltip("Prevents enemy music while Midna's Lament is playing"); } @@ -94,20 +94,25 @@ namespace dusk { } if (ImGui::BeginMenu("Cheats")) { - ImGui::Checkbox("Fast Iron Boots", &getSettings().game.enableFastIronBoots); + config::ImGuiCheckbox("Fast Iron Boots", getSettings().game.enableFastIronBoots); - ImGui::Checkbox("Can Transform Anywhere", &getSettings().game.canTransformAnywhere); + 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."); + } + ImGui::EndMenu(); } if (ImGui::BeginMenu("Difficulty")) { - ImGui::SliderInt("Damage Multiplier", &getSettings().game.damageMultiplier, 1, 8, "x%d"); + config::ImGuiSliderInt("Damage Multiplier", getSettings().game.damageMultiplier, 1, 8, "x%d"); - ImGui::Checkbox("Instant Death", &getSettings().game.instantDeath); + config::ImGuiCheckbox("Instant Death", getSettings().game.instantDeath); if (ImGui::IsItemHovered()) { ImGui::SetTooltip("Any hit will instantly kill you"); } @@ -116,7 +121,7 @@ namespace dusk { } if (ImGui::BeginMenu("Technical")) { - ImGui::Checkbox("Restore Wii 1.0 Glitches", &getSettings().game.restoreWiiGlitches); + 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"); @@ -125,6 +130,12 @@ namespace dusk { ImGui::EndMenu(); } + if (ImGui::BeginMenu("Tools")) { + config::ImGuiCheckbox("Enable Turbo Key", getSettings().game.enableTurboKeybind); + + ImGui::EndMenu(); + } + ImGui::EndMenu(); } } diff --git a/src/dusk/imgui/ImGuiMenuGame.cpp b/src/dusk/imgui/ImGuiMenuGame.cpp index b1849a6856..50877caad9 100644 --- a/src/dusk/imgui/ImGuiMenuGame.cpp +++ b/src/dusk/imgui/ImGuiMenuGame.cpp @@ -3,6 +3,7 @@ #include "ImGuiConsole.hpp" #include "ImGuiMenuGame.hpp" +#include "ImGuiConfig.hpp" #include #include "JSystem/JUtility/JUTGamePad.h" @@ -12,8 +13,17 @@ #include "dusk/hotkeys.h" #include "dusk/settings.h" #include "m_Do/m_Do_controller_pad.h" +#include "m_Do/m_Do_graphic.h" + +#include namespace dusk { + void ImGuiMenuGame::ToggleFullscreen() { + getSettings().video.enableFullscreen.setValue(!getSettings().video.enableFullscreen); + VISetWindowFullscreen(getSettings().video.enableFullscreen); + config::Save(); + } + ImGuiMenuGame::ImGuiMenuGame() {} void ImGuiMenuGame::draw() { @@ -26,17 +36,34 @@ namespace dusk { if (ImGui::BeginMenu("Graphics")) { if (ImGui::MenuItem("Toggle Fullscreen", hotkeys::TOGGLE_FULLSCREEN)) { - getSettings().video.enableFullscreen = !getSettings().video.enableFullscreen; - VISetWindowFullscreen(getSettings().video.enableFullscreen); + ToggleFullscreen(); } - bool& lockAspect = getSettings().video.lockAspectRatio; + 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("Lock Aspect Ratio", &lockAspect)) { + getSettings().video.lockAspectRatio.setValue(lockAspect); + if (lockAspect) { VILockAspectRatio(defaultAspectRatioW, defaultAspectRatioH); } else { VIUnlockAspectRatio(); } + + config::Save(); } ImGui::EndMenu(); @@ -44,9 +71,8 @@ namespace dusk { if (ImGui::BeginMenu("Audio")) { ImGui::Text("Master Volume"); - ImGui::SliderInt("##masterVolume", &getSettings().audio.masterVolume, 0, 100); - ImGui::Checkbox("Enable Reverb", &getSettings().audio.enableReverb); - + config::ImGuiSliderInt("##masterVolume", getSettings().audio.masterVolume, 0, 100); + config::ImGuiCheckbox("Enable Reverb", getSettings().audio.enableReverb); /* // TODO: Implement additional settings ImGui::Text("Main Music Volume"); @@ -66,9 +92,6 @@ namespace dusk { } */ - audio::SetMasterVolume(getSettings().audio.masterVolume / 100.0f); - audio::EnableReverb = getSettings().audio.enableReverb; - ImGui::EndMenu(); } diff --git a/src/dusk/imgui/ImGuiMenuGame.hpp b/src/dusk/imgui/ImGuiMenuGame.hpp index 6d7ed614aa..77e5952d1a 100644 --- a/src/dusk/imgui/ImGuiMenuGame.hpp +++ b/src/dusk/imgui/ImGuiMenuGame.hpp @@ -16,6 +16,8 @@ namespace dusk { void windowInputViewer(); void windowControllerConfig(); + static void ToggleFullscreen(); + private: struct { int m_selectedPort = 0; diff --git a/src/dusk/imgui/ImGuiMenuTools.cpp b/src/dusk/imgui/ImGuiMenuTools.cpp index b48127167c..4a455672a9 100644 --- a/src/dusk/imgui/ImGuiMenuTools.cpp +++ b/src/dusk/imgui/ImGuiMenuTools.cpp @@ -7,10 +7,11 @@ #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() {} @@ -18,7 +19,7 @@ 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; } @@ -49,8 +50,6 @@ namespace dusk { ImGui::MenuItem("Save Editor", nullptr, &m_showSaveEditor); ImGui::MenuItem("Audio Debug", hotkeys::SHOW_AUDIO_DEBUG, &m_showAudioDebug); ImGui::MenuItem("OSReport Force", nullptr, &OSReportReallyForceEnable); - ImGui::Separator(); - ImGui::MenuItem("Enable Turbo Key", hotkeys::TURBO, &getSettings().game.enableTurboKeybind); ImGui::EndMenu(); } @@ -111,31 +110,31 @@ 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))); + BytesToString(stats.lastTextureUploadSize))); ImGuiStringViewText(fmt::format( FMT_STRING("Total: {}\n"), - BytesToString(stats->lastVertSize + stats->lastUniformSize + - stats->lastIndexSize + stats->lastStorageSize + - stats->lastTextureUploadSize))); + BytesToString(stats.lastVertSize + stats.lastUniformSize + + stats.lastIndexSize + stats.lastStorageSize + + stats.lastTextureUploadSize))); // TODO: persist to config ShowCornerContextMenu(m_debugOverlayCorner, m_cameraOverlayCorner); 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/settings.cpp b/src/dusk/settings.cpp index 5625b284e3..ac77a9aede 100644 --- a/src/dusk/settings.cpp +++ b/src/dusk/settings.cpp @@ -1,69 +1,106 @@ #include "dusk/settings.h" +#include "dusk/config.hpp" namespace dusk { UserSettings g_userSettings = { - // Program settings - - // Video .video = { - .enableFullscreen = false, - .lockAspectRatio = false, + .enableFullscreen {"video.enableFullscreen", false}, + .enableVsync {"video.enableVsync", true}, + .lockAspectRatio {"video.lockAspectRatio", false}, }, - // Audio .audio = { - .masterVolume = 80, - .mainMusicVolume = 100, - .subMusicVolume = 100, - .soundEffectsVolume = 100, - .fanfareVolume = 100, - .enableReverb = true + .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 settings .game = { // Quality of Life - .enableQuickTransform = false, - .hideTvSettingsScreen = false, - .biggerWallets = false, - .noReturnRupees = false, - .disableRupeeCutscenes = false, - .noSwordRecoil = false, - .damageMultiplier = 1, - .instantDeath = false, - .fastClimbing = false, - .noMissClimbing = false, - .fastTears = false, + .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}, // Preferences - .enableMirrorMode = false, - .invertCameraXAxis = false, + .enableMirrorMode {"game.enableMirrorMode", false}, + .invertCameraXAxis {"game.invertCameraXAxis", false}, // Graphics - .enableBloom = true, - .useWaterProjectionOffset = false, + .enableBloom {"game.enableBloom", true}, + .useWaterProjectionOffset {"game.useWaterProjectionOffset", false}, // Audio - .noLowHpSound = false, - .midnasLamentNonStop = false, + .noLowHpSound {"game.noLowHpSound", false}, + .midnasLamentNonStop {"game.midnasLamentNonStop", false}, // Cheats - .enableFastIronBoots = false, - .canTransformAnywhere = false, + .enableFastIronBoots {"game.enableFastIronBoots", false}, + .canTransformAnywhere {"game.canTransformAnywhere", false}, + .fastSpinner {"game.fastSpinner", false}, // Technical - .restoreWiiGlitches = false, + .restoreWiiGlitches {"game.restoreWiiGlitches", false}, // Controls - .enableTurboKeybind = true, - } + .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.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.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 = { diff --git a/src/dusk/stubs.cpp b/src/dusk/stubs.cpp index 2cb385966e..e655ed6d7d 100644 --- a/src/dusk/stubs.cpp +++ b/src/dusk/stubs.cpp @@ -94,7 +94,7 @@ static void ClearMsgQueueMap() { map.clear(); } -void OSInitMessageQueue(OSMessageQueue* mq, void* msgArray, s32 msgCount) { +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; @@ -128,7 +128,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); diff --git a/src/f_ap/f_ap_game.cpp b/src/f_ap/f_ap_game.cpp index 1cbbb7449f..b1edb7fa23 100644 --- a/src/f_ap/f_ap_game.cpp +++ b/src/f_ap/f_ap_game.cpp @@ -738,6 +738,16 @@ void fapGm_Execute() { 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); diff --git a/src/f_op/f_op_actor_mng.cpp b/src/f_op/f_op_actor_mng.cpp index 36217076bf..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; diff --git a/src/m_Do/m_Do_ext.cpp b/src/m_Do/m_Do_ext.cpp index d744d048ba..0593815b1d 100644 --- a/src/m_Do/m_Do_ext.cpp +++ b/src/m_Do/m_Do_ext.cpp @@ -2873,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(); diff --git a/src/m_Do/m_Do_graphic.cpp b/src/m_Do/m_Do_graphic.cpp index a7a09a8d87..5c535c2eb1 100644 --- a/src/m_Do/m_Do_graphic.cpp +++ b/src/m_Do/m_Do_graphic.cpp @@ -552,8 +552,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 +580,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 +709,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 @@ -1285,7 +1314,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); @@ -2014,7 +2049,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); diff --git a/src/m_Do/m_Do_machine.cpp b/src/m_Do/m_Do_machine.cpp index d5258b6f98..6b186a77e6 100644 --- a/src/m_Do/m_Do_machine.cpp +++ b/src/m_Do/m_Do_machine.cpp @@ -592,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(); @@ -714,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"); @@ -1008,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 84c50a5f52..73298895ee 100644 --- a/src/m_Do/m_Do_main.cpp +++ b/src/m_Do/m_Do_main.cpp @@ -44,11 +44,12 @@ #include #include #include "SSystem/SComponent/c_API.h" +#include "dusk/app_info.hpp" #include "dusk/dusk.h" -#include "dusk/logging.h" -#include "dusk/time.h" -#include "dusk/main.h" #include "dusk/imgui/ImGuiEngine.hpp" +#include "dusk/logging.h" +#include "dusk/main.h" +#include "dusk/time.h" #include #include @@ -56,7 +57,9 @@ #include #include +#include "SDL3/SDL_filesystem.h" #include "cxxopts.hpp" +#include "dusk/config.hpp" // --- GLOBALS --- s8 mDoMain::developmentMode = -1; @@ -107,6 +110,8 @@ s32 LOAD_COPYDATE(void*) { } AuroraInfo auroraInfo; +AuroraStats dusk::lastFrameAuroraStats; +const char* configPath; void main01(void) { OS_REPORT("\x1b[m"); @@ -178,6 +183,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; @@ -233,10 +239,51 @@ 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; +} + // ========================================================================= // PC ENTRY POINT // ========================================================================= int game_main(int argc, char* argv[]) { + dusk::registerSettings(); + dusk::config::FinishRegistration(); + cxxopts::ParseResult parsed_arg_options; try { @@ -246,7 +293,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(""); @@ -265,8 +313,16 @@ 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 = defaultWindowWidth * 2; @@ -312,6 +368,8 @@ 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);