diff --git a/.vscode/launch.json b/.vscode/launch.json index 4cc435870a..7090699dd9 100644 --- a/.vscode/launch.json +++ b/.vscode/launch.json @@ -6,7 +6,7 @@ "type": "cppvsdbg", "request": "launch", "program": "${command:cmake.launchTargetPath}", - "args": ["-l", "1", "--dvd", "${workspaceRoot}/orig/GZ2E01/GZ2E01.iso"], + "args": ["-l", "1", "--dvd", "${workspaceRoot}/orig/GZ2E01/GZ2E01.iso", "--console"], "MIMode": "gdb", "miDebuggerPath": "gdb", "symbolSearchPath": "${command:cmake.launchTargetPath}", diff --git a/CMakeLists.txt b/CMakeLists.txt index c99133738b..e8132a98fd 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -316,6 +316,48 @@ if (DUSK_MOVIE_SUPPORT) list(APPEND GAME_COMPILE_DEFS MOVIE_SUPPORT=1) endif () +option(DUSK_ENABLE_DISCORD_RPC "Enable Discord Rich Presence support" ON) +if (DUSK_ENABLE_DISCORD_RPC AND NOT ANDROID AND NOT IOS AND NOT TVOS) + + FetchContent_Populate(discord_rpc + URL https://github.com/discord/discord-rpc/archive/refs/tags/v3.4.0.tar.gz + URL_HASH SHA256=e13427019027acd187352dacba6c65953af66fdf3c35fcf38fc40b454a9d7855 + DOWNLOAD_EXTRACT_TIMESTAMP TRUE + ) + # RapidJSON is a git submodule absent from the discord-rpc tarball; fetch separately. + FetchContent_Populate(rapidjson + URL https://github.com/Tencent/rapidjson/archive/refs/tags/v1.1.0.tar.gz + URL_HASH SHA256=bf7ced29704a1e696fbccf2a2b4ea068e7774fa37f6d7dd4039d0787f8bed98e + DOWNLOAD_EXTRACT_TIMESTAMP TRUE + ) + + if (NOT TARGET discord-rpc) + set(_drpc ${discord_rpc_SOURCE_DIR}/src) + set(_drpc_src + ${_drpc}/discord_rpc.cpp + ${_drpc}/rpc_connection.cpp + ${_drpc}/serialization.cpp + ) + if (WIN32) + list(APPEND _drpc_src ${_drpc}/connection_win.cpp ${_drpc}/discord_register_win.cpp) + elseif (APPLE) + list(APPEND _drpc_src ${_drpc}/connection_unix.cpp ${_drpc}/discord_register_osx.m) + else () + list(APPEND _drpc_src ${_drpc}/connection_unix.cpp ${_drpc}/discord_register_linux.cpp) + endif () + add_library(discord-rpc STATIC ${_drpc_src}) + target_include_directories(discord-rpc PUBLIC + ${discord_rpc_SOURCE_DIR}/include + ${rapidjson_SOURCE_DIR}/include + ) + if (UNIX) + target_link_libraries(discord-rpc PUBLIC pthread) + endif () + endif () + list(APPEND GAME_LIBS discord-rpc) + list(APPEND GAME_COMPILE_DEFS DUSK_DISCORD_RPC=1) +endif () + # Edit & Continue if (MSVC) if ("${CMAKE_MSVC_DEBUG_INFORMATION_FORMAT}" STREQUAL "" AND CMAKE_BUILD_TYPE STREQUAL "Debug") diff --git a/CMakePresets.json b/CMakePresets.json index 90307aa061..92799249a9 100644 --- a/CMakePresets.json +++ b/CMakePresets.json @@ -148,8 +148,7 @@ "cacheVariables": { "CMAKE_C_COMPILER": "cl", "CMAKE_CXX_COMPILER": "cl", - "CMAKE_INSTALL_PREFIX": "${sourceDir}/build/install", - "AURORA_DAWN_PROVIDER": "vendor" + "CMAKE_INSTALL_PREFIX": "${sourceDir}/build/install" }, "vendor": { "microsoft.com/VisualStudioSettings/CMake/1.0": { @@ -359,7 +358,10 @@ "inherits": [ "relwithdebinfo", "ci" - ] + ], + "cacheVariables": { + "AURORA_SDL3_PROVIDER": "vendor" + } }, { "name": "x-linux-ci-gcc", @@ -382,7 +384,6 @@ "ci" ], "cacheVariables": { - "AURORA_DAWN_PROVIDER": "vendor", "AURORA_NOD_PROVIDER": "vendor", "CMAKE_DISABLE_FIND_PACKAGE_PkgConfig": { "type": "BOOL", diff --git a/README.md b/README.md index c41985d394..7322441b74 100644 --- a/README.md +++ b/README.md @@ -1,103 +1,59 @@ -## Dusk +![DuskLogo](res/logo-mascot.webp) -### Building -#### Prerequisites -* [CMake 3.25+](https://cmake.org) - * Windows: Install `CMake Tools` in Visual Studio - * macOS: `brew install cmake` -* [Python 3+](https://python.org) - * Windows: [Microsoft Store](https://go.microsoft.com/fwlink?linkID=2082640) - * Verify it's added to `%PATH%` by typing `python` in `cmd`. - * macOS: `brew install python@3` -* **[Windows]** [Visual Studio 2026 Community](https://www.visualstudio.com/en-us/products/visual-studio-community-vs.aspx) - * Select `C++ Development` and verify the following packages are included: - * `Windows 11 SDK` - * `CMake Tools` - * `C++ Clang Compiler` - * `C++ Clang-cl` -* **[macOS]** [Xcode 16.4+](https://developer.apple.com/xcode/download/) -* **[Linux]** Actively tested on Ubuntu 24.04, Arch Linux & derivatives. - * Ubuntu 24.04+ packages - ``` - build-essential curl git ninja-build clang lld zlib1g-dev libcurl4-openssl-dev \ - libglu1-mesa-dev libdbus-1-dev libvulkan-dev libxi-dev libxrandr-dev libasound2-dev libpulse-dev \ - libudev-dev libpng-dev libncurses5-dev cmake libx11-xcb-dev python3 python-is-python3 \ - libclang-dev libfreetype-dev libxinerama-dev libxcursor-dev python3-markupsafe libgtk-3-dev \ - libxss-dev libxtst-dev - ``` - * Arch Linux packages - ``` - base-devel cmake ninja llvm vulkan-headers python python-markupsafe clang lld alsa-lib libpulse libxrandr freetype2 - ``` - * Fedora packages - ``` - cmake vulkan-headers ninja-build clang-devel llvm-devel libpng-devel - ``` - * It's also important that you install the developer tools and libraries - ``` - sudo dnf groupinstall "Development Tools" "Development Libraries" - ``` -#### Setup -Clone and initialize the Dusk repository -```sh -git clone --recursive https://github.com/TwilitRealm/dusk.git -cd dusk -git pull -git submodule update --init --recursive -``` +- ### **[Official Website](https://twilitrealm.dev)** +- ### **[Discord](https://discord.gg/QACynxeyna)** -#### Building +# Setup +**⚠️Dusk does NOT provide any copyrighted assets. You must provide your own copy of the game.** -**CLion (Windows / macOS / Linux)** +### 1. Verify your ROM dump +First make sure your dump of the game is clean and supported by Dusk. You can do this by checking the sha1 hash of your dump against this list of supported versions. -Open the project directory in CLion. Enable the appropriate presets for your platform: +| Version | sha1 hash | +| ------------ | ---------------------------------------- | +| GameCube USA | 75edd3ddff41f125d1b4ce1a40378f1b565519e7 | -![CLion](assets/clion.png) +### 2. Download [Dusk](https://github.com/TwilitRealm/dusk/releases) -**Visual Studio (Windows)** +### 3. Setup the game +#### Windows +- Extract the zip folder +- Place your dump of the game into the same folder where you extracted to +- Launch `dusk.exe` -Open the project directory in Visual Studio. The CMake configuration will be loaded automatically. +#### macOS +- TODO -**ninja (macOS)** +#### Linux +- TODO -```sh -cmake --preset macos-default-relwithdebinfo -cmake --build --preset macos-default-relwithdebinfo -``` +#### iOS +- TODO -Alternate presets available: -- `macos-default-debug`: Clang, Debug +#### android +- TODO -**ninja (Linux)** +# Building +If you'd like to build Dusk from source, please read the [build instructions](docs/building.md). -```sh -cmake --preset linux-default-relwithdebinfo -cmake --build --preset linux-default-relwithdebinfo -``` +# Credits +- Taka +- encounter +- Antidote +- caseif +- CraftyBoss +- crowell +- dooplecks +- gymnast86 +- Irastris +- kipcode66 +- Lars +- LunarSoap +- Maddie +- MelonSpeedruns +- Pheenoh +- PJB +- Roeming +- YunataSavior -Alternate presets available: -- `linux-default-debug`: GCC, Debug -- `linux-clang-relwithdebinfo`: Clang, RelWithDebInfo -- `linux-clang-debug`: Clang, Debug - -**ninja (Windows)** - -```sh -cmake --preset windows-msvc-relwithdebinfo -cmake --build --preset windows-msvc-relwithdebinfo -``` - -Alternate presets available: -- `windows-msvc-debug`: MSVC, Debug -- `windows-clang-relwithdebinfo`: Clang-cl, RelWithDebInfo -- `windows-clang-debug`: Clang-cl, Debug - -#### Running -Pass the disc image as a positional argument. Supported formats: ISO (GCM), RVZ, WIA, WBFS, CISO, GCZ -```sh -build/{preset}/dusk /path/to/game.rvz -``` -If no path is specified, Dusk defaults to `game.iso` in the current working directory. - -#### 30 FPS on Debug -When compiled fully in a Debug the game runs too slowly to hit playable 30 FPS. To avoid this, you can set a CMake cache variable to optimize specific critical files without hampering debuggability in the rest of the program: `-DDUSK_SELECTED_OPT=ON`. When building for MSVC (Windows) you must also modify `CMAKE_CXX_FLAGS_DEBUG` and `CMAKE_C_FLAGS_DEBUG` to remove `/RTC1` from the flags, like so: `-DCMAKE_CXX_FLAGS_DEBUG="/MDd /Zi /Ob0 /Od" -DCMAKE_C_FLAGS_DEBUG="/MDd /Zi /Ob0 /Od"` +Special thanks to the TP Decomp team, the GC/Wii Decomp community, the Aurora developers, and the TP speedrunning community. diff --git a/docs/building.md b/docs/building.md new file mode 100644 index 0000000000..0b1befa49f --- /dev/null +++ b/docs/building.md @@ -0,0 +1,98 @@ +### Building +#### Prerequisites +* [CMake 3.25+](https://cmake.org) + * Windows: Install `CMake Tools` in Visual Studio + * macOS: `brew install cmake` +* [Python 3+](https://python.org) + * Windows: [Microsoft Store](https://go.microsoft.com/fwlink?linkID=2082640) + * Verify it's added to `%PATH%` by typing `python` in `cmd`. + * macOS: `brew install python@3` +* **[Windows]** [Visual Studio 2026 Community](https://www.visualstudio.com/en-us/products/visual-studio-community-vs.aspx) + * Select `C++ Development` and verify the following packages are included: + * `Windows 11 SDK` + * `CMake Tools` + * `C++ Clang Compiler` + * `C++ Clang-cl` +* **[macOS]** [Xcode 16.4+](https://developer.apple.com/xcode/download/) +* **[Linux]** Actively tested on Ubuntu 24.04, Arch Linux & derivatives. + * Ubuntu 24.04+ packages + ``` + build-essential curl git ninja-build clang lld zlib1g-dev libcurl4-openssl-dev \ + libglu1-mesa-dev libdbus-1-dev libvulkan-dev libxi-dev libxrandr-dev libasound2-dev libpulse-dev \ + libudev-dev libpng-dev libncurses5-dev cmake libx11-xcb-dev python3 python-is-python3 \ + libclang-dev libfreetype-dev libxinerama-dev libxcursor-dev python3-markupsafe libgtk-3-dev \ + libxss-dev libxtst-dev + ``` + * Arch Linux packages + ``` + base-devel cmake ninja llvm vulkan-headers python python-markupsafe clang lld alsa-lib libpulse libxrandr freetype2 + ``` + * Fedora packages + ``` + cmake vulkan-headers ninja-build clang-devel llvm-devel libpng-devel + ``` + * It's also important that you install the developer tools and libraries + ``` + sudo dnf groupinstall "Development Tools" "Development Libraries" + ``` +#### Setup +Clone and initialize the Dusk repository +```sh +git clone --recursive https://github.com/TwilitRealm/dusk.git +cd dusk +git pull +git submodule update --init --recursive +``` + +#### Building + +**CLion (Windows / macOS / Linux)** + +Open the project directory in CLion. Enable the appropriate presets for your platform: + +![CLion](../assets/clion.png) + +**Visual Studio (Windows)** + +Open the project directory in Visual Studio. The CMake configuration will be loaded automatically. + +**ninja (macOS)** + +```sh +cmake --preset macos-default-relwithdebinfo +cmake --build --preset macos-default-relwithdebinfo +``` + +Alternate presets available: +- `macos-default-debug`: Clang, Debug + +**ninja (Linux)** + +```sh +cmake --preset linux-default-relwithdebinfo +cmake --build --preset linux-default-relwithdebinfo +``` + +Alternate presets available: +- `linux-default-debug`: GCC, Debug +- `linux-clang-relwithdebinfo`: Clang, RelWithDebInfo +- `linux-clang-debug`: Clang, Debug + +**ninja (Windows)** + +```sh +cmake --preset windows-msvc-relwithdebinfo +cmake --build --preset windows-msvc-relwithdebinfo +``` + +Alternate presets available: +- `windows-msvc-debug`: MSVC, Debug +- `windows-clang-relwithdebinfo`: Clang-cl, RelWithDebInfo +- `windows-clang-debug`: Clang-cl, Debug + +#### Running +Pass the disc image as a positional argument. Supported formats: ISO (GCM), RVZ, WIA, WBFS, CISO, GCZ +```sh +build/{preset}/dusk /path/to/game.rvz +``` +If no path is specified, Dusk defaults to `game.iso` in the current working directory. diff --git a/extern/aurora b/extern/aurora index c21a7f75ab..b1957f10cf 160000 --- a/extern/aurora +++ b/extern/aurora @@ -1 +1 @@ -Subproject commit c21a7f75ab1a2fd8ea896fa45b1005b2f903de77 +Subproject commit b1957f10cf9e7ea1e0e012c1968014bd11299297 diff --git a/files.cmake b/files.cmake index a65b7572c4..e929ec85b0 100644 --- a/files.cmake +++ b/files.cmake @@ -1334,6 +1334,7 @@ set(DUSK_FILES include/dusk/endian_gx.hpp include/dusk/config.hpp include/dusk/dvd_asset.hpp + include/dusk/scope_guard.hpp src/dusk/dvd_asset.cpp src/d/actor/d_a_alink_dusk.cpp src/dusk/asserts.cpp @@ -1345,6 +1346,7 @@ set(DUSK_FILES src/dusk/file_select.cpp src/dusk/file_select.hpp src/dusk/frame_interpolation.cpp + src/dusk/game_clock.cpp src/dusk/globals.cpp src/dusk/gyro.cpp src/dusk/io.cpp @@ -1385,4 +1387,5 @@ set(DUSK_FILES src/dusk/OSContext.cpp src/dusk/OSThread.cpp src/dusk/OSMutex.cpp + src/dusk/discord_presence.cpp ) diff --git a/include/d/actor/d_a_alink.h b/include/d/actor/d_a_alink.h index 53228af84b..9980ab776f 100644 --- a/include/d/actor/d_a_alink.h +++ b/include/d/actor/d_a_alink.h @@ -4551,7 +4551,7 @@ public: #if TARGET_PC void handleWolfHowl(); void handleQuickTransform(); - bool checkGyroAimItemContext(); + bool checkGyroAimContext(); #endif }; // Size: 0x385C diff --git a/include/d/actor/d_a_e_wb.h b/include/d/actor/d_a_e_wb.h index dd36474025..ba680366fb 100644 --- a/include/d/actor/d_a_e_wb.h +++ b/include/d/actor/d_a_e_wb.h @@ -220,6 +220,15 @@ public: /* 0x17E2 */ s16 wait_roll_angle; ///< @brief Roll angle during wait state. /* 0x17E4 */ u8 field_0x17e4[0x17e8 - 0x17e4]; /* 0x17E8 */ f32 ride_speed_max; ///< @brief Speed rate for riding calculations. +#if TARGET_PC + cXyz himo_mat_interp_prev[2][16]; + cXyz himo_mat_interp_curr[2][16]; + cXyz himo_tex_interp_prev[2]; + cXyz himo_tex_interp_curr[2]; + bool himo_interp_prev_valid; + bool himo_interp_curr_valid; + s8 demo_cam_sync_ticks; +#endif }; STATIC_ASSERT(sizeof(e_wb_class) == 0x17EC); diff --git a/include/d/actor/d_a_mirror.h b/include/d/actor/d_a_mirror.h index fd69c8682e..06c5603899 100644 --- a/include/d/actor/d_a_mirror.h +++ b/include/d/actor/d_a_mirror.h @@ -25,6 +25,9 @@ public: /* 0x164 */ cXyz mMinVal; /* 0x170 */ cXyz mMaxVal; /* 0x17C */ cXyz mViewScale; +#if TARGET_PC + bool mbReset = false; +#endif }; /** diff --git a/include/d/actor/d_a_obj_sw.h b/include/d/actor/d_a_obj_sw.h index 64674b0b9c..9e2793755a 100644 --- a/include/d/actor/d_a_obj_sw.h +++ b/include/d/actor/d_a_obj_sw.h @@ -68,10 +68,8 @@ public: /* 0x904 */ cXyz field_0x904[2]; /* 0x91C */ int field_0x91c; /* 0x920 */ cXyz field_0x920[63]; - /* 0xC14 */ f32 field_0xc14[4]; - /* 0xC24 */ u8 field_0xc24[0xd10 - 0xc24]; - /* 0xD10 */ s8 field_0xd10[4]; - /* 0xD14 */ u8 field_0xd14[0xd50 - 0xd14]; + /* 0xC14 */ f32 field_0xc14[63]; + /* 0xD10 */ s8 field_0xd10[64]; /* 0xD50 */ mDoExt_3DlineMat1_c field_0xd50; /* 0xD8C */ int field_0xd8c; }; diff --git a/include/d/d_com_inf_game.h b/include/d/d_com_inf_game.h index d22d08cd10..964cc34c0f 100644 --- a/include/d/d_com_inf_game.h +++ b/include/d/d_com_inf_game.h @@ -4834,8 +4834,7 @@ inline void dComIfGd_drawXluListDark() { inline void dComIfGd_drawXluListInvisible() { ZoneScoped; #ifdef TARGET_PC - if (dusk::getSettings().game.enableWaterRefraction && - !dusk::getSettings().game.enableFrameInterpolation) { + if (!dusk::getSettings().game.disableWaterRefraction) { #endif g_dComIfG_gameInfo.drawlist.drawXluListInvisible(); #ifdef TARGET_PC @@ -4846,8 +4845,7 @@ inline void dComIfGd_drawXluListInvisible() { inline void dComIfGd_drawOpaListInvisible() { ZoneScoped; #ifdef TARGET_PC - if (dusk::getSettings().game.enableWaterRefraction && - !dusk::getSettings().game.enableFrameInterpolation) { + if (!dusk::getSettings().game.disableWaterRefraction) { #endif g_dComIfG_gameInfo.drawlist.drawOpaListInvisible(); #ifdef TARGET_PC diff --git a/include/d/d_drawlist.h b/include/d/d_drawlist.h index 4126c715f3..8368c9e92e 100644 --- a/include/d/d_drawlist.h +++ b/include/d/d_drawlist.h @@ -209,6 +209,10 @@ public: /* 0x04 */ TGXTexObj* mpTexObj; /* 0x08 */ Mtx mVolumeMtx; /* 0x38 */ Mtx mMtx; +#if TARGET_PC + const void* mVolumeMtxKey; + const void* mMtxKey; +#endif }; // Size: 0x68 struct cBgD_Vtx_t; diff --git a/include/d/d_file_select.h b/include/d/d_file_select.h index 72f7cb7f42..cf081a3b10 100644 --- a/include/d/d_file_select.h +++ b/include/d/d_file_select.h @@ -10,6 +10,7 @@ #include "JSystem/J3DGraphLoader/J3DAnmLoader.h" class dFile_info_c; +class J2DPicture; class dDlst_FileSel_c : public dDlst_base_c { public: @@ -113,6 +114,14 @@ public: /* 0x04 */ J2DScreen* Scr3m; }; +class dDlst_FileSelFade_c : public dDlst_base_c { +public: + void draw(); + virtual ~dDlst_FileSelFade_c() {} + + /* 0x04 */ J2DPicture* mpPict; +}; + class dFs_HIO_c : public JORReflexible { public: dFs_HIO_c(); @@ -676,6 +685,9 @@ public: #if PLATFORM_GCN /* 0x2378 */ J2DPicture* mpFadePict; #endif +#ifdef TARGET_PC + dDlst_FileSelFade_c mFadeDlst; +#endif #if PLATFORM_WII || PLATFORM_SHIELD /* 0x2376 */ u8 field_0x2376[SAVEFILE_SIZE]; @@ -684,6 +696,10 @@ public: #endif }; +#ifdef TARGET_PC +STATIC_ASSERT(sizeof(dFile_select_c) == 0x237C + sizeof(dDlst_FileSelFade_c)); +#else STATIC_ASSERT(sizeof(dFile_select_c) == 0x237C); +#endif #endif /* D_FILE_D_FILE_SELECT_H */ diff --git a/include/d/d_menu_ring.h b/include/d/d_menu_ring.h index f28c20aac2..39d29a35e8 100644 --- a/include/d/d_menu_ring.h +++ b/include/d/d_menu_ring.h @@ -204,6 +204,9 @@ private: /* 0x6D1 */ u8 field_0x6d1; /* 0x6D2 */ u8 field_0x6d2; /* 0x6D3 */ u8 field_0x6d3; +#if TARGET_PC + f32 mSelectItemSlideElapsed[4]; +#endif }; #endif /* D_MENU_D_MENU_RING_H */ diff --git a/include/d/d_select_cursor.h b/include/d/d_select_cursor.h index c77da550f8..1bd5991d16 100644 --- a/include/d/d_select_cursor.h +++ b/include/d/d_select_cursor.h @@ -47,6 +47,10 @@ public: mPositionY = y; } +#ifdef TARGET_PC + void refreshAspectScale(); +#endif + void onUpdateFlag() { mUpdateFlag = true; } void resetUpdateFlag() { mUpdateFlag = false; } @@ -79,6 +83,9 @@ private: /* 0x58 */ f32 mPositionX; /* 0x5C */ f32 mPositionY; /* 0x60 */ f32 mParam1; +#ifdef TARGET_PC + f32 mBaseParam1; +#endif /* 0x64 */ f32 mParam2; /* 0x68 */ f32 mParam3; /* 0x6C */ f32 mParam4; diff --git a/include/dusk/audio/DuskAudioSystem.h b/include/dusk/audio/DuskAudioSystem.h index 724776f5f1..8cdd757c82 100644 --- a/include/dusk/audio/DuskAudioSystem.h +++ b/include/dusk/audio/DuskAudioSystem.h @@ -12,6 +12,8 @@ namespace dusk::audio { void SetMasterVolume(f32 value); + void SetPaused(bool paused); + u32 GetResetCount(int channelIdx); f32 VolumeFromU16(u16 value); diff --git a/include/dusk/discord_presence.hpp b/include/dusk/discord_presence.hpp new file mode 100644 index 0000000000..899b2ad5f9 --- /dev/null +++ b/include/dusk/discord_presence.hpp @@ -0,0 +1,18 @@ +#pragma once + +#ifdef DUSK_DISCORD_RPC + +namespace dusk { +namespace discord { + +void Initialize(); + +void RunCallbacks(); + +void UpdatePresence(); + +void Shutdown(); +} +} + +#endif // DUSK_DISCORD_RPC diff --git a/include/dusk/frame_interpolation.h b/include/dusk/frame_interpolation.h index 383d16d288..bec9b600cf 100644 --- a/include/dusk/frame_interpolation.h +++ b/include/dusk/frame_interpolation.h @@ -1,5 +1,4 @@ -#ifndef DUSK_FRAME_INTERP_H -#define DUSK_FRAME_INTERP_H +#pragma once #include #include @@ -7,6 +6,7 @@ #include class camera_process_class; +class view_class; #ifdef __cplusplus namespace dusk { @@ -16,42 +16,36 @@ void ensure_initialized(); void begin_record(); void end_record(); -void interpolate(float step); +void begin_frame(bool enabled, bool is_sim_frame, float step); +void interpolate(); float get_interpolation_step(); -void notify_presentation_frame(); void request_presentation_sync(); bool presentation_sync_active(); -void notify_sim_tick_complete(); -uint32_t begin_presentation_ui_pass(); -uint32_t get_presentation_ui_advance_ticks(); -void end_presentation_ui_pass(); +bool is_enabled(); + +// TODO: These should be phased out as UI is progressively updated to use game_clock +void set_ui_tick_pending(bool value); +bool get_ui_tick_pending(); + +bool is_sim_frame(); -void open_child(const void* key, int32_t id); -void close_child(); void record_camera(::camera_process_class* cam, int camera_id); -void record_final_mtx_raw(const Mtx* dest, const Mtx src); -void record_final_mtx_raw_tagged(const Mtx* dest, const Mtx src, uint64_t stable_tag); +void interp_view(::view_class* view); +void record_final_mtx(Mtx m, const void *key); +void record_final_mtx(Mtx m); -bool lookup_replacement(const void* source, Mtx out); +bool lookup_replacement(const void* key, Mtx out); bool lookup_concat_replacement(const void* lhs, const void* rhs, Mtx out); +typedef void (*InterpolationCallBack)(bool isSimFrame, void* pUserWork); +// call on a sim tick, will get called during presentation +void add_interpolation_callback(InterpolationCallBack pCallBack, void* pUserWork); + void begin_presentation_camera(); void end_presentation_camera(); -struct PresentationCameraScope { - PresentationCameraScope() { begin_presentation_camera(); } - ~PresentationCameraScope() { end_presentation_camera(); } - PresentationCameraScope(const PresentationCameraScope&) = delete; - PresentationCameraScope& operator=(const PresentationCameraScope&) = delete; - PresentationCameraScope(PresentationCameraScope&&) = delete; - PresentationCameraScope& operator=(PresentationCameraScope&&) = delete; -}; - -uint64_t alloc_simple_shadow_pair_base(); } // namespace frame_interp } // namespace dusk #endif - -#endif diff --git a/include/dusk/game_clock.h b/include/dusk/game_clock.h new file mode 100644 index 0000000000..4a394b5c2e --- /dev/null +++ b/include/dusk/game_clock.h @@ -0,0 +1,33 @@ +#ifndef DUSK_GAME_CLOCK_H +#define DUSK_GAME_CLOCK_H + +#include + +namespace dusk { +namespace game_clock { + +void ensure_initialized(); +void reset_accumulator(); +void reset_frame_timer(); + +constexpr float sim_pace() { return 1.0f / 30.0f; } +constexpr float period_for_original_frames(float frame_count) { return frame_count * sim_pace(); } +constexpr float ui_maximum_dt() { return 0.05f; } +constexpr float ui_initial_dt() { return 1.0f / 60.0f; } + +struct MainLoopPacer { + float presentation_dt_seconds; + bool is_interpolating; + bool do_sim_tick; + float interpolation_step; + float sim_pace; +}; + +MainLoopPacer advance_main_loop(); + +float consume_interval(const void* consumer); + +} // namespace game_clock +} // namespace dusk + +#endif // DUSK_GAME_CLOCK_H diff --git a/include/dusk/gyro.h b/include/dusk/gyro.h index 4ee1c61737..279aeae16e 100644 --- a/include/dusk/gyro.h +++ b/include/dusk/gyro.h @@ -4,7 +4,7 @@ namespace dusk::gyro { void read(float dt); void getAimDeltas(float& out_yaw, float& out_pitch); -bool queryGyroAimItemContext(); +bool queryGyroAimContext(); void rollgoalTick(bool play_active, s16 camera_yaw); void rollgoalTableOffset(s16& out_ax, s16& out_az); diff --git a/include/dusk/main.h b/include/dusk/main.h index a9194e2aba..2152a6d564 100644 --- a/include/dusk/main.h +++ b/include/dusk/main.h @@ -5,6 +5,7 @@ namespace dusk { extern bool IsRunning; extern bool IsShuttingDown; extern bool IsGameLaunched; + extern bool IsFocusPaused; } #endif // DUSK_MAIN_H diff --git a/include/dusk/scope_guard.hpp b/include/dusk/scope_guard.hpp new file mode 100644 index 0000000000..281d23434d --- /dev/null +++ b/include/dusk/scope_guard.hpp @@ -0,0 +1,20 @@ +#ifndef DUSK_SCOPE_GUARD_HPP +#define DUSK_SCOPE_GUARD_HPP + +#include + +class SimpleScopeGuard { +public: + // Store the function in the constructor + explicit SimpleScopeGuard(const std::function& func) : m_func(func) {} + + // Run the function when the object goes out of scope + ~SimpleScopeGuard() { + if (m_func) m_func(); + } + +private: + std::function m_func; +}; + +#endif //DUSK_SCOPE_GUARD_HPP diff --git a/include/dusk/settings.h b/include/dusk/settings.h index 2676c461cd..03749967c9 100644 --- a/include/dusk/settings.h +++ b/include/dusk/settings.h @@ -61,18 +61,21 @@ struct UserSettings { ConfigVar noMissClimbing; ConfigVar fastTears; ConfigVar instantSaves; + ConfigVar instantText; ConfigVar sunsSong; // Preferences ConfigVar enableMirrorMode; ConfigVar invertCameraXAxis; ConfigVar disableMainHUD; + ConfigVar pauseOnFocusLost; // Graphics ConfigVar bloomMode; ConfigVar bloomMultiplier; - ConfigVar enableWaterRefraction; + ConfigVar disableWaterRefraction; ConfigVar enableFrameInterpolation; + ConfigVar internalResolutionScale; ConfigVar shadowResolutionMultiplier; // Audio @@ -91,6 +94,15 @@ struct UserSettings { ConfigVar gyroInvertYaw; // Cheats + ConfigVar infiniteHearts; + ConfigVar infiniteArrows; + ConfigVar infiniteBombs; + ConfigVar infiniteOil; + ConfigVar infiniteOxygen; + ConfigVar infiniteRupees; + ConfigVar moonJump; + ConfigVar superClawshot; + ConfigVar alwaysGreatspin; ConfigVar enableFastIronBoots; ConfigVar canTransformAnywhere; ConfigVar fastSpinner; diff --git a/include/f_pc/f_pc_leaf.h b/include/f_pc/f_pc_leaf.h index 33d7e85d29..414d706b6a 100644 --- a/include/f_pc/f_pc_leaf.h +++ b/include/f_pc/f_pc_leaf.h @@ -25,7 +25,7 @@ typedef struct leafdraw_class : base_process_class { #endif /* 0xB8 */ leafdraw_method_class* leaf_methods; /* 0xBC */ s8 unk_0xBC; - /* 0xBD */ u8 unk_0xBD; + /* 0xBD */ u8 draw_interp_frame; /* 0xBE */ draw_priority_class draw_priority; } leafdraw_class; diff --git a/include/f_pc/f_pc_node.h b/include/f_pc/f_pc_node.h index 3be7fe6c8f..0d96fd2de5 100644 --- a/include/f_pc/f_pc_node.h +++ b/include/f_pc/f_pc_node.h @@ -18,6 +18,7 @@ typedef struct process_node_class { /* 0x0BC */ layer_class layer; /* 0x0E8 */ node_list_class layer_nodelist[16]; /* 0x1A8 */ s8 unk_0x1A8; + /* 0x1A9 */ s8 draw_interp_frame; } process_node_class; typedef struct node_process_profile_definition { diff --git a/include/m_Do/m_Do_graphic.h b/include/m_Do/m_Do_graphic.h index f921912656..5d29049520 100644 --- a/include/m_Do/m_Do_graphic.h +++ b/include/m_Do/m_Do_graphic.h @@ -286,12 +286,7 @@ 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(); @@ -304,7 +299,7 @@ public: #endif #if TARGET_PC - static void setWindowSize(AuroraWindowSize const& size); + static void updateRenderSize(); #endif static TGXTexObj mFrameBufferTexObj; diff --git a/include/m_Do/m_Do_lib.h b/include/m_Do/m_Do_lib.h index 8130cab8da..14e57ddf5a 100644 --- a/include/m_Do/m_Do_lib.h +++ b/include/m_Do/m_Do_lib.h @@ -43,10 +43,6 @@ struct mDoLib_clipper { }; void mDoLib_project(Vec* src, Vec* dst); -#if TARGET_PC -void mDoLib_project(Vec* src, Vec* dst, JGeometry::TBox2 viewport); -#endif - u32 mDoLib_setResTimgObj(ResTIMG const* res, TGXTexObj* o_texObj, u32 tlut_name, GXTlutObj* o_tlutObj); void mDoLib_pos2camera(Vec* src, Vec* dst); diff --git a/libs/JSystem/include/JSystem/J3DGraphAnimator/J3DModel.h b/libs/JSystem/include/JSystem/J3DGraphAnimator/J3DModel.h index a27db4fa00..2e5b3bd38d 100644 --- a/libs/JSystem/include/JSystem/J3DGraphAnimator/J3DModel.h +++ b/libs/JSystem/include/JSystem/J3DGraphAnimator/J3DModel.h @@ -79,6 +79,10 @@ public: virtual void viewCalc(); virtual ~J3DModel() {} +#if TARGET_PC + static void interp_callback(bool isSimFrame, void* pUserWork); +#endif + J3DModelData* getModelData() { return mModelData; } void onFlag(u32 flag) { mFlags |= flag; } @@ -105,9 +109,7 @@ public: void setAnmMtx(int jointNo, Mtx m) { mMtxBuffer->setAnmMtx(jointNo, m); #ifdef TARGET_PC - dusk::frame_interp::record_final_mtx_raw( - reinterpret_cast(mMtxBuffer->getAnmMtx(jointNo)), - mMtxBuffer->getAnmMtx(jointNo)); + dusk::frame_interp::record_final_mtx(mMtxBuffer->getAnmMtx(jointNo)); #endif } MtxP getAnmMtx(int jointNo) { return mMtxBuffer->getAnmMtx(jointNo); } diff --git a/libs/JSystem/include/JSystem/J3DGraphAnimator/J3DModelData.h b/libs/JSystem/include/JSystem/J3DGraphAnimator/J3DModelData.h index 6e3d54ff45..52e5018c1b 100644 --- a/libs/JSystem/include/JSystem/J3DGraphAnimator/J3DModelData.h +++ b/libs/JSystem/include/JSystem/J3DGraphAnimator/J3DModelData.h @@ -23,6 +23,10 @@ public: void syncJ3DSysPointers() const; void syncJ3DSysFlags() const; +#if TARGET_PC + bool needsInterpCallBack() const; +#endif + virtual ~J3DModelData() {} void simpleCalcMaterial(Mtx mtx) { simpleCalcMaterial(0, mtx); } diff --git a/libs/JSystem/include/JSystem/J3DGraphBase/J3DMaterial.h b/libs/JSystem/include/JSystem/J3DGraphBase/J3DMaterial.h index 829156ad1b..70e368eec4 100644 --- a/libs/JSystem/include/JSystem/J3DGraphBase/J3DMaterial.h +++ b/libs/JSystem/include/JSystem/J3DGraphBase/J3DMaterial.h @@ -33,6 +33,9 @@ public: void copy(J3DMaterial*); s32 newSharedDisplayList(u32); s32 newSingleSharedDisplayList(u32); +#if TARGET_PC + bool needsInterpCallBack() const; +#endif virtual void calc(f32 const (*)[4]); virtual void calcDiffTexMtx(f32 const (*)[4]); @@ -46,7 +49,6 @@ public: virtual void change(); J3DMaterial() { initialize(); } - ~J3DMaterial() {} J3DMaterial* getNext() { return mNext; } J3DShape* getShape() { return mShape; } J3DTevBlock* getTevBlock() { return mTevBlock; } diff --git a/libs/JSystem/include/JSystem/JFramework/JFWDisplay.h b/libs/JSystem/include/JSystem/JFramework/JFWDisplay.h index fab39a296b..28967cc0a2 100644 --- a/libs/JSystem/include/JSystem/JFramework/JFWDisplay.h +++ b/libs/JSystem/include/JSystem/JFramework/JFWDisplay.h @@ -101,10 +101,6 @@ public: void setDrawDoneMethod(EDrawDone drawDone) { mDrawDoneMethod = drawDone; } void setFader(JUTFader* fader) { mFader = fader; } -#ifdef TARGET_PC - // For frame interpolation - void setFaderSimSteps(u32 steps); -#endif void resetFader() { setFader(NULL); } JUTFader* getFader() const { return mFader; } void setClearColor(JUtility::TColor color) { mClearColor = color; } diff --git a/libs/JSystem/include/JSystem/JUtility/JUTFader.h b/libs/JSystem/include/JSystem/JUtility/JUTFader.h index 6c98a6840f..b85e4a6cd4 100644 --- a/libs/JSystem/include/JSystem/JUtility/JUTFader.h +++ b/libs/JSystem/include/JSystem/JUtility/JUTFader.h @@ -11,8 +11,10 @@ class JUTFader { public: enum EStatus { - UNKSTATUS_M1 = -1, - UNKSTATUS_0 = 0, + None, + Wait, + FadeIn, + FadeOut, }; JUTFader(int, int, int, int, JUtility::TColor); @@ -29,12 +31,12 @@ public: void setColor(JUtility::TColor color) { mColor.set(color); } /* 0x04 */ s32 mStatus; - /* 0x08 */ u16 field_0x8; - /* 0x0A */ u16 field_0xa; + /* 0x08 */ u16 mDuration; + /* 0x0A */ u16 mTimer; /* 0x0C */ JUtility::TColor mColor; /* 0x10 */ JGeometry::TBox2 mBox; - /* 0x20 */ int mEStatus; - /* 0x24 */ u32 field_0x24; + /* 0x20 */ int mStatusTimer; + /* 0x24 */ u32 mNextStatus; }; #endif /* JUTFADER_H */ diff --git a/libs/JSystem/include/JSystem/JUtility/JUTVideo.h b/libs/JSystem/include/JSystem/JUtility/JUTVideo.h index 9a23a4dc7e..dfc6fd0b6c 100644 --- a/libs/JSystem/include/JSystem/JUtility/JUTVideo.h +++ b/libs/JSystem/include/JSystem/JUtility/JUTVideo.h @@ -33,24 +33,16 @@ public: static void postRetraceProc(u32); static void drawDoneCallback(); - u16 getFbWidth() const { - #if TARGET_PC - return m_WindowSize.fb_width; - #else - return mRenderObj->fbWidth; - #endif - } - u16 getEfbHeight() const { - #if TARGET_PC - return m_WindowSize.fb_height; - #else - return mRenderObj->efbHeight; - #endif - } + u16 getFbWidth() const { return mRenderObj->fbWidth; } + u16 getEfbHeight() const { return mRenderObj->efbHeight; } void getBounds(u16& width, u16& height) const { width = (u16)getFbWidth(); height = (u16)getEfbHeight(); } +#ifdef TARGET_PC + u32 getRenderWidth() const { return mRenderWidth; } + u32 getRenderHeight() const { return mRenderHeight; } +#endif u16 getXfbHeight() const { return u16(mRenderObj->xfbHeight); } u8 isAntiAliasing() const { return u8(mRenderObj->aa); } Pattern getSamplePattern() const { return mRenderObj->sample_pattern; } @@ -63,7 +55,7 @@ public: GXRenderModeObj* getRenderMode() const { return mRenderObj; } #if TARGET_PC - void setWindowSize(AuroraWindowSize const& size); + void setRenderSize(u32 width, u32 height); #endif private: @@ -89,7 +81,8 @@ private: #if TARGET_PC public: - AuroraWindowSize m_WindowSize; + u32 mRenderWidth; + u32 mRenderHeight; #endif }; diff --git a/libs/JSystem/src/J2DGraph/J2DGrafContext.cpp b/libs/JSystem/src/J2DGraph/J2DGrafContext.cpp index 36f54a23c6..3ac3e5d197 100644 --- a/libs/JSystem/src/J2DGraph/J2DGrafContext.cpp +++ b/libs/JSystem/src/J2DGraph/J2DGrafContext.cpp @@ -64,10 +64,6 @@ void J2DGrafContext::setup2D() { } void J2DGrafContext::setScissor() { -#if TARGET_PC - GXSetScissor(mScissorBounds.i.x, mScissorBounds.i.y, mScissorBounds.getWidth(), - mScissorBounds.getHeight()); -#else JGeometry::TBox2 bounds(0, 0, 1024, 1024); JGeometry::TBox2 curBounds(mScissorBounds); mScissorBounds.intersect(bounds); @@ -81,7 +77,6 @@ void J2DGrafContext::setScissor() { } else { GXSetScissor(0, 0, 0, 0); } -#endif } void J2DGrafContext::scissor(JGeometry::TBox2 const& bounds) { diff --git a/libs/JSystem/src/J3DGraphAnimator/J3DModel.cpp b/libs/JSystem/src/J3DGraphAnimator/J3DModel.cpp index f2bd737b4f..8c895d5077 100644 --- a/libs/JSystem/src/J3DGraphAnimator/J3DModel.cpp +++ b/libs/JSystem/src/J3DGraphAnimator/J3DModel.cpp @@ -97,6 +97,16 @@ s32 J3DModel::entryModelData(J3DModelData* pModelData, u32 mdlFlags, u32 mtxNum) return kJ3DError_Success; } +#if TARGET_PC +void J3DModel::interp_callback(bool isSimFrame, void* pUserWork) { + J3DModel* i_this = static_cast(pUserWork); + if (!isSimFrame) { + i_this->calcMaterial(); + i_this->diff(); + } +} +#endif + s32 J3DModel::createShapePacket(J3DModelData* pModelData) { J3D_ASSERTMSG(173, pModelData != NULL, "Error : null pointer."); @@ -452,11 +462,11 @@ void J3DModel::calc() { #ifdef TARGET_PC for (u16 i = 0; i < mModelData->getJointNum(); ++i) { - dusk::frame_interp::record_final_mtx_raw(reinterpret_cast(getAnmMtx(i)), getAnmMtx(i)); + dusk::frame_interp::record_final_mtx(getAnmMtx(i)); } for (u16 i = 0; i < mModelData->getWEvlpMtxNum(); ++i) { - dusk::frame_interp::record_final_mtx_raw(reinterpret_cast(getWeightAnmMtx(i)), getWeightAnmMtx(i)); + dusk::frame_interp::record_final_mtx(getWeightAnmMtx(i)); } #endif } @@ -485,6 +495,11 @@ void J3DModel::entry() { joint->entryIn(); } } + +#if TARGET_PC + if (mModelData->needsInterpCallBack()) + dusk::frame_interp::add_interpolation_callback(&J3DModel::interp_callback, this); +#endif } void J3DModel::viewCalc() { @@ -496,7 +511,7 @@ void J3DModel::viewCalc() { J3DCalcViewBaseMtx(j3dSys.getViewMtx(), mBaseScale, mBaseTransformMtx, (MtxP)&mInternalView); #ifdef TARGET_PC - dusk::frame_interp::record_final_mtx_raw(&mInternalView, mInternalView); + dusk::frame_interp::record_final_mtx(mInternalView); #endif } } else if (isCpuSkinningOn()) { @@ -504,7 +519,7 @@ void J3DModel::viewCalc() { J3DCalcViewBaseMtx(j3dSys.getViewMtx(), mBaseScale, mBaseTransformMtx, (MtxP)&mInternalView); #ifdef TARGET_PC - dusk::frame_interp::record_final_mtx_raw(&mInternalView, mInternalView); + dusk::frame_interp::record_final_mtx(mInternalView); #endif } } else if (checkFlag(J3DMdlFlag_SkinPosCpu)) { @@ -528,7 +543,7 @@ void J3DModel::viewCalc() { #ifdef TARGET_PC for (u16 i = 0; i < mModelData->getDrawMtxNum(); ++i) { - dusk::frame_interp::record_final_mtx_raw(&getDrawMtxPtr()[i], getDrawMtxPtr()[i]); + dusk::frame_interp::record_final_mtx(getDrawMtxPtr()[i]); } #endif diff --git a/libs/JSystem/src/J3DGraphAnimator/J3DModelData.cpp b/libs/JSystem/src/J3DGraphAnimator/J3DModelData.cpp index e296676187..3eed051b6c 100644 --- a/libs/JSystem/src/J3DGraphAnimator/J3DModelData.cpp +++ b/libs/JSystem/src/J3DGraphAnimator/J3DModelData.cpp @@ -84,6 +84,15 @@ void J3DModelData::simpleCalcMaterial(u16 idx, Mtx param_1) { } } +#if TARGET_PC +bool J3DModelData::needsInterpCallBack() const { + for (u16 i = 0, n = getMaterialNum(); i < n; i++) + if (getMaterialNodePointer(i)->needsInterpCallBack()) + return true; + return false; +} +#endif + void J3DModelData::syncJ3DSysPointers() const { j3dSys.setTexture(getTexture()); j3dSys.setVtxPos(getVtxPosArray(), getVtxNum()); diff --git a/libs/JSystem/src/J3DGraphBase/J3DMaterial.cpp b/libs/JSystem/src/J3DGraphBase/J3DMaterial.cpp index 0c772305b2..48d4731ed9 100644 --- a/libs/JSystem/src/J3DGraphBase/J3DMaterial.cpp +++ b/libs/JSystem/src/J3DGraphBase/J3DMaterial.cpp @@ -265,7 +265,7 @@ void J3DMaterial::diff(u32 diffFlags) { } void J3DMaterial::calc(f32 const (*param_0)[4]) { - if (j3dSys.checkFlag(0x40000000)) { + if (j3dSys.checkFlag(J3DSysFlag_PostTexMtx)) { mTexGenBlock->calcPostTexMtx(param_0); } else { mTexGenBlock->calc(param_0); @@ -276,7 +276,7 @@ void J3DMaterial::calc(f32 const (*param_0)[4]) { } void J3DMaterial::calcDiffTexMtx(f32 const (*param_0)[4]) { - if (j3dSys.checkFlag(0x40000000)) { + if (j3dSys.checkFlag(J3DSysFlag_PostTexMtx)) { mTexGenBlock->calcPostTexMtxWithoutViewMtx(param_0); } else { mTexGenBlock->calcWithoutViewMtx(param_0); @@ -288,7 +288,7 @@ void J3DMaterial::setCurrentMtx() { } void J3DMaterial::calcCurrentMtx() { - if (!j3dSys.checkFlag(0x40000000)) { + if (!j3dSys.checkFlag(J3DSysFlag_PostTexMtx)) { mCurrentMtx.setCurrentTexMtx( getTexCoord(0)->getTexGenMtx(), getTexCoord(1)->getTexGenMtx(), @@ -371,6 +371,30 @@ s32 J3DMaterial::newSingleSharedDisplayList(u32 dlSize) { return kJ3DError_Success; } +#if TARGET_PC +bool J3DMaterial::needsInterpCallBack() const { + for (int i = 0, n = getTexGenNum(); i < n; i++) { + J3DTexMtx* pTexMtx = mTexGenBlock->getTexMtx(i); + if (pTexMtx != NULL) { + u32 texMtxMode = pTexMtx->getTexMtxInfo().mInfo & 0x3f; + + // uses j3dSys.getViewMtx() + switch (texMtxMode) { + case J3DTexMtxMode_EnvmapBasic: + case J3DTexMtxMode_EnvmapOld: + case J3DTexMtxMode_Envmap: + case J3DTexMtxMode_ProjmapBasic: + case J3DTexMtxMode_Projmap: + case J3DTexMtxMode_ViewProjmap: + case J3DTexMtxMode_ViewProjmapBasic: + return true; + } + } + } + return false; +} +#endif + void J3DPatchedMaterial::initialize() { J3DMaterial::initialize(); } diff --git a/libs/JSystem/src/J3DGraphBase/J3DTevs.cpp b/libs/JSystem/src/J3DGraphBase/J3DTevs.cpp index 09ddc0b405..719976770b 100644 --- a/libs/JSystem/src/J3DGraphBase/J3DTevs.cpp +++ b/libs/JSystem/src/J3DGraphBase/J3DTevs.cpp @@ -37,9 +37,9 @@ void loadTexCoordGens(u32 texGenNum, J3DTexCoord* texCoords) { var_r28 = 61; J3DGDWriteXFCmdHdr(GX_XF_REG_DUALTEX0, texGenNum); - if (j3dSys.checkFlag(0x40000000)) { + if (j3dSys.checkFlag(J3DSysFlag_PostTexMtx)) { for (int i = 0; i < texGenNum; i++) { - if (texCoords[i].getTexGenMtx() != 60) { + if (texCoords[i].getTexGenMtx() != GX_IDENTITY) { var_r28 = i * 3; } else { var_r28 = 61; diff --git a/libs/JSystem/src/JAudio2/JAISeqMgr.cpp b/libs/JSystem/src/JAudio2/JAISeqMgr.cpp index a1f3554815..1d0e42d47e 100644 --- a/libs/JSystem/src/JAudio2/JAISeqMgr.cpp +++ b/libs/JSystem/src/JAudio2/JAISeqMgr.cpp @@ -120,11 +120,19 @@ void JAISeqMgr::mixOut() { } JAISeq* JAISeqMgr::beginStartSeq_() { - JAISeq* seq = JKR_NEW JAISeq(this, field_0x10); +#ifdef TARGET_PC + if (JAISeq::getFreeMemCount() == 0) { + JUT_WARN(273, "%s", "JASPoolAllocObject::::operator new failed .\n"); + return NULL; + } + return JKR_NEW JAISeq(this, field_0x10); +#else + JAISeq* seq = new JAISeq(this, field_0x10); if (seq == NULL) { JUT_WARN(273, "%s", "JASPoolAllocObject::::operator new failed .\n"); } return seq; +#endif } bool JAISeqMgr::endStartSeq_(JAISeq* seq, JAISoundHandle* handle) { diff --git a/libs/JSystem/src/JFramework/JFWDisplay.cpp b/libs/JSystem/src/JFramework/JFWDisplay.cpp index 38dbc7eab1..64b0fedcf2 100644 --- a/libs/JSystem/src/JFramework/JFWDisplay.cpp +++ b/libs/JSystem/src/JFramework/JFWDisplay.cpp @@ -205,14 +205,6 @@ void JFWDisplay::preGX() { } } -#ifdef TARGET_PC -static s32 s_faderSimSteps = -1; - -void JFWDisplay::setFaderSimSteps(u32 steps) { - s_faderSimSteps = static_cast(steps); -} -#endif - void JFWDisplay::endGX() { s32 bufferNum = JUTXfb::getManager()->getBufferNum(); u16 width = JUTVideo::getManager()->getFbWidth(); @@ -224,17 +216,10 @@ void JFWDisplay::endGX() { if (mFader != NULL) { ortho.setPort(); #ifdef TARGET_PC - u32 advance_count = 1; - if (dusk::getSettings().game.enableFrameInterpolation && s_faderSimSteps >= 0) { - advance_count = static_cast(s_faderSimSteps); - s_faderSimSteps = -1; - } else { - s_faderSimSteps = -1; - } - for (u32 i = 0; i < advance_count; i++) { + if (dusk::frame_interp::get_ui_tick_pending()) { mFader->advance(); } - if (mFader->getStatus() != 1) { + if (mFader->getStatus() != JUTFader::Wait) { mFader->draw(); } #else diff --git a/libs/JSystem/src/JUtility/JUTFader.cpp b/libs/JSystem/src/JUtility/JUTFader.cpp index f7fa963e63..599ae22720 100644 --- a/libs/JSystem/src/JUtility/JUTFader.cpp +++ b/libs/JSystem/src/JUtility/JUTFader.cpp @@ -10,51 +10,51 @@ JUTFader::JUTFader(int x, int y, int width, int height, JUtility::TColor pColor) : mColor(pColor), mBox(x, y, x + width, y + height) { - mStatus = 0; - field_0x8 = 0; - field_0xa = 0; - field_0x24 = 0; - mEStatus = UNKSTATUS_M1; + mStatus = None; + mDuration = 0; + mTimer = 0; + mNextStatus = 0; + mStatusTimer = -1; } void JUTFader::advance() { - if (0 <= mEStatus && mEStatus-- == 0) { - mStatus = field_0x24; + if (0 <= mStatusTimer && mStatusTimer-- == 0) { + mStatus = mNextStatus; } - if (mStatus == 1) { + if (mStatus == Wait) { return; } switch (mStatus) { - case 0: + case None: mColor.a = 0xFF; break; - case 2: + case FadeIn: #if AVOID_UB - if (field_0x8 == 0) { - mStatus = 1; + if (mDuration == 0) { + mStatus = Wait; break; } #endif - mColor.a = 0xFF - ((++field_0xa * 0xFF) / field_0x8); + mColor.a = 0xFF - ((++mTimer * 0xFF) / mDuration); - if (field_0xa >= field_0x8) { - mStatus = 1; + if (mTimer >= mDuration) { + mStatus = Wait; } break; - case 3: + case FadeOut: #if AVOID_UB - if (field_0x8 == 0) { - mStatus = 0; + if (mDuration == 0) { + mStatus = None; break; } #endif - mColor.a = ((++field_0xa * 0xFF) / field_0x8); + mColor.a = ((++mTimer * 0xFF) / mDuration); - if (field_0xa >= field_0x8) { - mStatus = 0; + if (mTimer >= mDuration) { + mStatus = None; } break; @@ -77,53 +77,53 @@ void JUTFader::draw() { } } -bool JUTFader::startFadeIn(int param_0) { +bool JUTFader::startFadeIn(int duration) { bool statusCheck = mStatus == 0; if (statusCheck) { - mStatus = 2; - field_0xa = 0; - field_0x8 = param_0; + mStatus = FadeIn; + mTimer = 0; + mDuration = duration; } return statusCheck; } -bool JUTFader::startFadeOut(int param_0) { +bool JUTFader::startFadeOut(int duration) { bool statusCheck = mStatus == 1; if (statusCheck) { - mStatus = 3; - field_0xa = 0; - field_0x8 = param_0; + mStatus = FadeOut; + mTimer = 0; + mDuration = duration; } return statusCheck; } -void JUTFader::setStatus(JUTFader::EStatus i_status, int param_1) { +void JUTFader::setStatus(JUTFader::EStatus i_status, int timer) { switch (i_status) { - case 0: - if (param_1 != 0) { - field_0x24 = 0; - mEStatus = param_1; + case None: + if (timer != 0) { + mNextStatus = None; + mStatusTimer = timer; break; } - mStatus = 0; - field_0x24 = 0; - mEStatus = 0; + mStatus = None; + mNextStatus = None; + mStatusTimer = 0; break; - case 1: - if (param_1 != 0) { - field_0x24 = 1; - mEStatus = param_1; + case Wait: + if (timer != 0) { + mNextStatus = Wait; + mStatusTimer = timer; break; } - mStatus = 1; - field_0x24 = 1; - mEStatus = 0; + mStatus = Wait; + mNextStatus = Wait; + mStatusTimer = 0; break; } } diff --git a/libs/JSystem/src/JUtility/JUTVideo.cpp b/libs/JSystem/src/JUtility/JUTVideo.cpp index f718fcac23..5586342f0e 100644 --- a/libs/JSystem/src/JUtility/JUTVideo.cpp +++ b/libs/JSystem/src/JUtility/JUTVideo.cpp @@ -205,7 +205,8 @@ void JUTVideo::setRenderMode(GXRenderModeObj const* pObj) { void JUTVideo::waitRetraceIfNeed() {} #if TARGET_PC -void JUTVideo::setWindowSize(AuroraWindowSize const& size) { - m_WindowSize = size; +void JUTVideo::setRenderSize(u32 width, u32 height) { + mRenderWidth = width; + mRenderHeight = height; } #endif diff --git a/res/logo-mascot.webp b/res/logo-mascot.webp new file mode 100644 index 0000000000..c22f3bc90f Binary files /dev/null and b/res/logo-mascot.webp differ diff --git a/src/d/actor/d_a_alink_crawl.inc b/src/d/actor/d_a_alink_crawl.inc index 4a657c1de8..2dbf88d3e1 100644 --- a/src/d/actor/d_a_alink_crawl.inc +++ b/src/d/actor/d_a_alink_crawl.inc @@ -37,18 +37,40 @@ void daAlink_c::setCrawlMoveDirectionArrow() { } if (field_0x3198 & 4) { - if (!bvar) { - direction |= data_80452F38; - } else { - direction |= data_80452F39; + #if TARGET_PC + if (dusk::getSettings().game.enableMirrorMode) { + if (!bvar) { + direction |= data_80452F39; + } else { + direction |= data_80452F38; + } + } else + #endif + { + if (!bvar) { + direction |= data_80452F38; + } else { + direction |= data_80452F39; + } } } if (field_0x3198 & 8) { - if (!bvar) { - direction |= data_80452F39; - } else { - direction |= data_80452F38; + #if TARGET_PC + if (dusk::getSettings().game.enableMirrorMode) { + if (!bvar) { + direction |= data_80452F38; + } else { + direction |= data_80452F39; + } + } else + #endif + { + if (!bvar) { + direction |= data_80452F39; + } else { + direction |= data_80452F38; + } } } diff --git a/src/d/actor/d_a_alink_cut.inc b/src/d/actor/d_a_alink_cut.inc index 8e61a262cb..f33d2935c5 100644 --- a/src/d/actor/d_a_alink_cut.inc +++ b/src/d/actor/d_a_alink_cut.inc @@ -817,6 +817,12 @@ BOOL daAlink_c::checkDownAttackState() { } BOOL daAlink_c::checkCutLargeTurnState() const { + #if TARGET_PC + if (dusk::getSettings().game.alwaysGreatspin) { + return TRUE; + } + #endif + return ((dComIfGs_isEventBit(dSv_event_flag_c::F_0344) || checkNoResetFlg3(FLG3_TRANING_CUT_LARGE_TURN)) && dComIfGs_getLife() == dComIfGs_getMaxLifeGauge() ) diff --git a/src/d/actor/d_a_alink_dusk.cpp b/src/d/actor/d_a_alink_dusk.cpp index 9b937d3678..045a9655bd 100644 --- a/src/d/actor/d_a_alink_dusk.cpp +++ b/src/d/actor/d_a_alink_dusk.cpp @@ -143,12 +143,14 @@ void daAlink_c::handleQuickTransform() { procCoMetamorphoseInit(); } -bool daAlink_c::checkGyroAimItemContext() { - if (checkWolf()) { - return false; - } - +bool daAlink_c::checkGyroAimContext() { switch (mProcID) { + case PROC_SUBJECTIVITY: + case PROC_SWIM_SUBJECTIVITY: + case PROC_HORSE_SUBJECTIVITY: + case PROC_CANOE_SUBJECTIVITY: + case PROC_BOARD_SUBJECTIVITY: + case PROC_WOLF_ROPE_SUBJECTIVITY: case PROC_BOW_SUBJECT: case PROC_BOOMERANG_SUBJECT: case PROC_COPY_ROD_SUBJECT: diff --git a/src/d/actor/d_a_alink_hook.inc b/src/d/actor/d_a_alink_hook.inc index 3641015993..d152190161 100644 --- a/src/d/actor/d_a_alink_hook.inc +++ b/src/d/actor/d_a_alink_hook.inc @@ -290,6 +290,12 @@ BOOL daAlink_c::checkHookshotStickBG(cBgS_PolyInfo& i_polyinfo) { } #endif + #if TARGET_PC + if (dusk::getSettings().game.superClawshot) { + return TRUE; + } + #endif + if (dComIfG_Bgsp().ChkPolyHSStick(i_polyinfo)) { dBgW_Base* bgw_p = dComIfG_Bgsp().GetBgWBasePointer(i_polyinfo); if (bgw_p != NULL && bgw_p->ChkPushPullOk()) { @@ -448,6 +454,12 @@ void daAlink_c::setHookshotSight() { max_length = mpHIO->mItem.mHookshot.m.mMaxLength; } + #if TARGET_PC + if (dusk::getSettings().game.superClawshot) { + max_length = 69420.0f; + } + #endif + BOOL line_cross = checkSightLine(max_length, &sight_pos); if (mHookTargetAcKeep.getActor() != NULL) { @@ -890,6 +902,14 @@ void daAlink_c::setHookshotPos() { max_length = mpHIO->mItem.mHookshot.m.mMaxLength; } + #if TARGET_PC + if (dusk::getSettings().game.superClawshot) { + return_speed = 2870.0f; + shoot_speed = 2870.0f; + max_length = 69420.0f; + } + #endif + if (mItemMode == HS_MODE_RETURN_e) { if (targetAc_p != NULL) { if (checkLv7BossRoom()) { @@ -899,6 +919,12 @@ void daAlink_c::setHookshotPos() { } } + #if TARGET_PC + if (dusk::getSettings().game.superClawshot) { + return_speed = 500.0f; + } + #endif + if (checkModeFlg(0x400)) { return_speed += current.pos.abs(field_0x3798); } @@ -1548,6 +1574,12 @@ int daAlink_c::procHookshotFly() { f32 temp_f31 = field_0x37d4.abs(); f32 temp_f30 = mpHIO->mItem.mHookshot.m.mStickReturnSpeed + spAC.abs(mHookshotTopPos); + #if TARGET_PC + if (dusk::getSettings().game.superClawshot) { + temp_f30 = 500.0f + spAC.abs(mHookshotTopPos); + } + #endif + if (temp_f31 < temp_f30 || mProcVar1.field_0x300a == 0) { setHookshotReturnEnd(); } else { diff --git a/src/d/actor/d_a_alink_kandelaar.inc b/src/d/actor/d_a_alink_kandelaar.inc index 88c2152e03..339ff90ce6 100644 --- a/src/d/actor/d_a_alink_kandelaar.inc +++ b/src/d/actor/d_a_alink_kandelaar.inc @@ -180,12 +180,7 @@ 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_link.inc b/src/d/actor/d_a_alink_link.inc index 6de02a7598..b278d866fc 100644 --- a/src/d/actor/d_a_alink_link.inc +++ b/src/d/actor/d_a_alink_link.inc @@ -130,7 +130,7 @@ BOOL daAlink_c::setBodyAngleToCamera() { } #if TARGET_PC - if (dusk::getSettings().game.enableGyroAim && checkGyroAimItemContext()) { + if (dusk::getSettings().game.enableGyroAim && checkGyroAimContext()) { f32 gyro_scale = 1.0f; if (checkWolfEyeUp()) { gyro_scale *= 0.6f; diff --git a/src/d/actor/d_a_balloon_2D.cpp b/src/d/actor/d_a_balloon_2D.cpp index 6d9c66b464..6b5b5a2bd2 100644 --- a/src/d/actor/d_a_balloon_2D.cpp +++ b/src/d/actor/d_a_balloon_2D.cpp @@ -318,11 +318,7 @@ void daBalloon2D_c::addScoreCount(cXyz* param_1, u32 param_2, u8 param_3) { field_0x5f8[current].field_0xf = field_0x5f8[prev].field_0xf; } cXyz acStack_2c; - #if TARGET_PC - mDoLib_project(param_1, &acStack_2c, { 0, 0, FB_WIDTH, FB_HEIGHT }); - #else mDoLib_project(param_1, &acStack_2c); - #endif field_0x5f8[0].field_0x0.set(acStack_2c); field_0x5f8[0].field_0xc = param_2; field_0x5f8[0].field_0xe = 60; diff --git a/src/d/actor/d_a_bg.cpp b/src/d/actor/d_a_bg.cpp index e73723d1f9..9c453b6553 100644 --- a/src/d/actor/d_a_bg.cpp +++ b/src/d/actor/d_a_bg.cpp @@ -623,6 +623,11 @@ int daBg_c::create() { dComIfGp_roomControl_onStatusFlag(roomNo, 0x10); OS_REPORT(" room%d\n", roomNo); + +#if TARGET_PC + draw_interp_frame = true; +#endif + return cPhs_COMPLEATE_e; } diff --git a/src/d/actor/d_a_boomerang.cpp b/src/d/actor/d_a_boomerang.cpp index 64dd71f985..590897640e 100644 --- a/src/d/actor/d_a_boomerang.cpp +++ b/src/d/actor/d_a_boomerang.cpp @@ -337,13 +337,7 @@ void daBoomerang_sight_c::setSight(const cXyz* i_pos, int i_no) { } Vec proj; - - #if TARGET_PC - mDoLib_project(&m_pos[i_no], &proj, {0, 0, FB_WIDTH, FB_HEIGHT}); - #else mDoLib_project(&m_pos[i_no], &proj); - #endif - m_proj_posX[i_no] = proj.x; m_proj_posY[i_no] = proj.y; } diff --git a/src/d/actor/d_a_demo00.cpp b/src/d/actor/d_a_demo00.cpp index 871e9ebca6..99ad6c1587 100644 --- a/src/d/actor/d_a_demo00.cpp +++ b/src/d/actor/d_a_demo00.cpp @@ -1658,12 +1658,7 @@ 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_dshutter.cpp b/src/d/actor/d_a_dshutter.cpp index fc122cd4e3..264f559e07 100644 --- a/src/d/actor/d_a_dshutter.cpp +++ b/src/d/actor/d_a_dshutter.cpp @@ -215,15 +215,14 @@ int daDsh_c::create() { mType = getType(); -#ifdef TARGET_PC - const char* l_resName[] = {l_arcName[mType], ""}; -#else - // !@bug By making this static, it is only initialized the first time it runs - // If gate types that use other arcs are loaded later (without reloading the code) - // this array never gets updated and will load the incorrect arc - // On GC/Wii, REL loading causes this to reset/reinitialize so the bug is avoided - // but TPHD is all statically linked so daDsh_c::CreateHeap fails to get model data and the gate unloads + // !@bug Static-init only runs once, so slot 0 keeps the first mType's arc name forever. + // GC/Wii dodges this via REL reload; TPHD is statically linked so later gates of a + // different type load the wrong arc and CreateHeap fails. The storage must stay static + // because mResLoader.load holds the pointer past create(), so we just overwrite slot 0 + // each call instead. static const char* l_resName[] = {l_arcName[mType], ""}; +#ifdef TARGET_PC + l_resName[0] = l_arcName[mType]; #endif int phase = mResLoader.load(l_resName, NULL); diff --git a/src/d/actor/d_a_e_fk.cpp b/src/d/actor/d_a_e_fk.cpp index 87734da262..5840df0495 100644 --- a/src/d/actor/d_a_e_fk.cpp +++ b/src/d/actor/d_a_e_fk.cpp @@ -429,13 +429,7 @@ 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 54dd10ad81..3ed859c686 100644 --- a/src/d/actor/d_a_e_fs.cpp +++ b/src/d/actor/d_a_e_fs.cpp @@ -463,13 +463,7 @@ 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_rd.cpp b/src/d/actor/d_a_e_rd.cpp index 3067cc456a..e540e7dccd 100644 --- a/src/d/actor/d_a_e_rd.cpp +++ b/src/d/actor/d_a_e_rd.cpp @@ -6601,13 +6601,14 @@ static int daE_RD_Execute(e_rd_class* i_this) { 1.2f, }; + #if AVOID_UB + s16 x = 0; + s16 y = 0; + #endif for (int i = 0; i < 2; i++) { MtxPush(); + #if !AVOID_UB s16 x, y; - - #if AVOID_UB - x = 0; - y = 0; #endif if (i == 0) { diff --git a/src/d/actor/d_a_e_sm.cpp b/src/d/actor/d_a_e_sm.cpp index 8894399cec..b85e22e640 100644 --- a/src/d/actor/d_a_e_sm.cpp +++ b/src/d/actor/d_a_e_sm.cpp @@ -1362,13 +1362,7 @@ void daE_SM_c::E_SM_C_Hook() { bool daE_SM_c::CheckViewArea() { Vec vec; - - #if TARGET_PC - mDoLib_project(¤t.pos, &vec, {0, 0, FB_WIDTH, FB_HEIGHT}); - #else mDoLib_project(¤t.pos, &vec); - #endif - bool rv = false; if (vec.x >= 0.0f && vec.x <= FB_WIDTH && vec.y >= 0.0f && vec.y <= FB_HEIGHT) { diff --git a/src/d/actor/d_a_e_wb.cpp b/src/d/actor/d_a_e_wb.cpp index 819439879e..75031c42bb 100644 --- a/src/d/actor/d_a_e_wb.cpp +++ b/src/d/actor/d_a_e_wb.cpp @@ -18,6 +18,8 @@ #include "m_Do/m_Do_controller_pad.h" #include "m_Do/m_Do_graphic.h" #include "res/Object/Always.h" +#include "dusk/dusk.h" +#include "dusk/frame_interpolation.h" #include @@ -184,6 +186,30 @@ static bool hio_set; static daE_WB_HIO_c l_HIO; +#if TARGET_PC +static void e_wb_rein_interp_callback(bool isSimFrame, void* pUserWork) { + e_wb_class* i_this = (e_wb_class*)pUserWork; + if (!i_this->himo_interp_prev_valid || !i_this->himo_interp_curr_valid) { + return; + } + const f32 alpha = dusk::frame_interp::get_interpolation_step(); + for (int r = 0; r < 2; r++) { + cXyz* dst = i_this->himo_mat[r].getPos(0); + for (int i = 0; i < 16; i++) { + const cXyz& p0 = i_this->himo_mat_interp_prev[r][i]; + const cXyz& p1 = i_this->himo_mat_interp_curr[r][i]; + dst[i] = p0 + (p1 - p0) * alpha; + } + } + cXyz* dst = i_this->himo_tex.getPos(0); + for (int i = 0; i < 2; i++) { + const cXyz& p0 = i_this->himo_tex_interp_prev[i]; + const cXyz& p1 = i_this->himo_tex_interp_curr[i]; + dst[i] = p0 + (p1 - p0) * alpha; + } +} +#endif + static void himo_control1(e_wb_class* i_this, cXyz* i_pos, int i_no, s8 param_3) { fopEn_enemy_c* enemy = &i_this->enemy; cXyz mae, ato; @@ -508,6 +534,21 @@ static int daE_WB_Draw(e_wb_class* i_this) { dComIfGd_set3DlineMat(&i_this->himo_mat[1]); i_this->himo_tex.update(2, l_color, &actor->tevStr); dComIfGd_set3DlineMat(&i_this->himo_tex); +#if TARGET_PC + if (dusk::getSettings().game.enableFrameInterpolation) { + if (i_this->himo_interp_curr_valid) { + memcpy(i_this->himo_mat_interp_prev, i_this->himo_mat_interp_curr, sizeof(i_this->himo_mat_interp_curr)); + memcpy(i_this->himo_tex_interp_prev, i_this->himo_tex_interp_curr, sizeof(i_this->himo_tex_interp_curr)); + i_this->himo_interp_prev_valid = true; + } + for (int r = 0; r < 2; r++) { + memcpy(i_this->himo_mat_interp_curr[r], i_this->himo_mat[r].getPos(0), 16 * sizeof(cXyz)); + } + memcpy(i_this->himo_tex_interp_curr, i_this->himo_tex.getPos(0), 2 * sizeof(cXyz)); + i_this->himo_interp_curr_valid = true; + dusk::frame_interp::add_interpolation_callback(&e_wb_rein_interp_callback, i_this); + } +#endif } return 1; @@ -3726,6 +3767,9 @@ static void demo_camera(e_wb_class* i_this) { boss = (e_rdb_class*)fopAcM_SearchByName(fpcNm_E_RDB_e); } cXyz mae, ato, eye, center; +#if TARGET_PC + const s16 entry_demo_mode = i_this->demo_mode; +#endif switch (i_this->demo_mode) { case 1: { @@ -4255,6 +4299,9 @@ static void demo_camera(e_wb_class* i_this) { if (i_this->demo_timer == 325) { fpcM_Search(s_wbZrevise_sub, i_this); +#if TARGET_PC + i_this->demo_cam_sync_ticks = 2; +#endif } if (i_this->demo_timer == 335) { @@ -4495,6 +4542,9 @@ static void demo_camera(e_wb_class* i_this) { i_this->demo_cam_way_spd.z = fabsf(i_this->demo_cam_way.z - i_this->demo_cam_ctr.z); i_this->demo_cam_morf = 0; pla->setPlayerPosAndAngle(&pla->current.pos, pla->shape_angle.y - 4000, 0); +#if TARGET_PC + dusk::frame_interp::request_presentation_sync(); +#endif } if (i_this->demo_timer == 345) { daPy_getPlayerActorClass()->setThrowDamage(boss->enemy.shape_angle.y - 8000 + TREG_S(8), @@ -4741,6 +4791,9 @@ static void demo_camera(e_wb_class* i_this) { i_this->demo_cam_eye.x += 300.0f + VREG_F(8); i_this->demo_cam_eye.y += 150.0f + VREG_F(9); i_this->demo_cam_eye.z -= 1400.0f + VREG_F(10); +#if TARGET_PC + dusk::frame_interp::request_presentation_sync(); +#endif } } else { i_this->demo_cam_eye = enemy->current.pos; @@ -4996,6 +5049,15 @@ static void demo_camera(e_wb_class* i_this) { } } } +#if TARGET_PC + if (entry_demo_mode != i_this->demo_mode) { + i_this->demo_cam_sync_ticks = 2; + } + if (i_this->demo_cam_sync_ticks > 0) { + dusk::frame_interp::request_presentation_sync(); + i_this->demo_cam_sync_ticks--; + } +#endif } static void anm_se_eff_set(e_wb_class* i_this) { diff --git a/src/d/actor/d_a_midna.cpp b/src/d/actor/d_a_midna.cpp index 01d472e075..7bb844932e 100644 --- a/src/d/actor/d_a_midna.cpp +++ b/src/d/actor/d_a_midna.cpp @@ -1054,9 +1054,9 @@ void daMidna_c::setBodyPartMatrix() { } mpModel->calcWeightEnvelopeMtx(); #ifdef TARGET_PC - // Frame interpolation: Record weight envelopes for Midna here, as they are otherwise missed causing distortion + // FRAME INTERP NOTE: Record weight envelopes for Midna here, as they are otherwise missed causing distortion for (u16 i = 0; i < mpModel->getModelData()->getWEvlpMtxNum(); i++) { - dusk::frame_interp::record_final_mtx_raw(reinterpret_cast(mpModel->getWeightAnmMtx(i)), mpModel->getWeightAnmMtx(i)); + dusk::frame_interp::record_final_mtx(mpModel->getWeightAnmMtx(i)); } #endif } diff --git a/src/d/actor/d_a_mirror.cpp b/src/d/actor/d_a_mirror.cpp index 5468d70f87..4711dee681 100644 --- a/src/d/actor/d_a_mirror.cpp +++ b/src/d/actor/d_a_mirror.cpp @@ -13,6 +13,9 @@ #include #include #include "m_Do/m_Do_lib.h" +#if TARGET_PC +#include "dusk/frame_interpolation.h" +#endif #ifndef __MWERKS__ #include "dusk/math.h" @@ -31,7 +34,11 @@ dMirror_packet_c::dMirror_packet_c() { } void dMirror_packet_c::reset() { +#if TARGET_PC + mbReset = true; +#else mModelCount = 0; +#endif } void dMirror_packet_c::calcMinMax() { @@ -73,6 +80,13 @@ void dMirror_packet_c::calcMinMax() { } int dMirror_packet_c::entryModel(J3DModel* i_model) { +#if TARGET_PC + if (mbReset) { + mModelCount = 0; + mbReset = false; + } +#endif + if (mModelCount >= 0x40) { return 0; } diff --git a/src/d/actor/d_a_movie_player.cpp b/src/d/actor/d_a_movie_player.cpp index c3074ac877..d972bddd4d 100644 --- a/src/d/actor/d_a_movie_player.cpp +++ b/src/d/actor/d_a_movie_player.cpp @@ -3342,13 +3342,8 @@ static void daMP_THPGXYuv2RgbSetup(const GXRenderModeObj* rmode) { Mtx44 m; Mtx e_m; -#if TARGET_PC - w = JUTVideo::getManager()->getFbWidth(); - h = JUTVideo::getManager()->getEfbHeight(); -#else w = rmode->fbWidth; h = rmode->efbHeight; -#endif var_f31 = 0.0f; #if WIDESCREEN_SUPPORT @@ -4383,6 +4378,8 @@ static void daMP_ActivePlayer_Draw() { daMP_DrawPosX = static_cast(rect.PosX); daMP_DrawPosY = static_cast(rect.PosY); + + daMP_THPPlayerSetVolume((dusk::getSettings().audio.masterVolume / 100.0f) * 127.0f, 0); #endif int frame = daMP_THPPlayerDrawCurrentFrame( diff --git a/src/d/actor/d_a_npc.cpp b/src/d/actor/d_a_npc.cpp index 6ec2fbe7a9..123bf66800 100644 --- a/src/d/actor/d_a_npc.cpp +++ b/src/d/actor/d_a_npc.cpp @@ -2694,12 +2694,7 @@ 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); - #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_npc_inko.cpp b/src/d/actor/d_a_npc_inko.cpp index 3c277085f6..4d55a31f8e 100644 --- a/src/d/actor/d_a_npc_inko.cpp +++ b/src/d/actor/d_a_npc_inko.cpp @@ -110,6 +110,10 @@ static int daNpc_Inko_Execute(npc_inko_class* i_this) { } f32 var_f31; + + #if AVOID_UB + var_f31 = 0.0f; + #endif if (i_this->field_0x598 == 0) { if (i_this->field_0x59c[1] == 0) { i_this->field_0x59c[1] = 30.0f + cM_rndF(70.0f); diff --git a/src/d/actor/d_a_npc_ne.cpp b/src/d/actor/d_a_npc_ne.cpp index ae43981593..1324c56cf5 100644 --- a/src/d/actor/d_a_npc_ne.cpp +++ b/src/d/actor/d_a_npc_ne.cpp @@ -18,6 +18,7 @@ #include "f_op/f_op_kankyo_mng.h" #include "c/c_damagereaction.h" #include "Z2AudioLib/Z2Instances.h" +#include "dusk/frame_interpolation.h" #include static home_path_pnt home_path[38] = { @@ -2655,6 +2656,9 @@ static void demo_camera(npc_ne_class* i_this) { i_this->mCameraFovY = 55.0f; camera->mCamera.SetTrimSize(3); daPy_getPlayerActorClass()->changeOriginalDemo(); +#ifdef TARGET_PC + dusk::frame_interp::request_presentation_sync(); +#endif // fallthrough case 2: @@ -2683,6 +2687,9 @@ static void demo_camera(npc_ne_class* i_this) { if (i_this->mDemoCounter == 0) { i_this->mCameraCenter1.set(387.0f, 133.0f, -866.0f); i_this->mCameraEye1.set(284.0f, 208.0f, -585.0f); +#ifdef TARGET_PC + dusk::frame_interp::request_presentation_sync(); +#endif } if (i_this->mDemoCounter == 12) { @@ -2719,6 +2726,9 @@ static void demo_camera(npc_ne_class* i_this) { i_this->mCameraFovY = 45.0f; camera->mCamera.SetTrimSize(3); daPy_getPlayerActorClass()->changeOriginalDemo(); +#ifdef TARGET_PC + dusk::frame_interp::request_presentation_sync(); +#endif // fallthrough case 11: @@ -2799,8 +2809,14 @@ static void demo_camera(npc_ne_class* i_this) { MtxPosition(&vec, &i_this->mCameraEye2); i_this->mCameraEye2 += player->current.pos; player->changeDemoParam2(2); +#ifdef TARGET_PC + dusk::frame_interp::request_presentation_sync(); +#endif } else if (i_this->mDemoCounter == 120) { player->changeDemoParam2(0); +#ifdef TARGET_PC + dusk::frame_interp::request_presentation_sync(); +#endif } } } @@ -2853,6 +2869,9 @@ static void demo_camera(npc_ne_class* i_this) { i_this->mCameraCenter1 = _this->current.pos; i_this->mCameraCenter1.y += 20.0f; i_this->mCameraFovY = 55.0f; +#ifdef TARGET_PC + dusk::frame_interp::request_presentation_sync(); +#endif } camera->mCamera.Set(i_this->mCameraCenter1, i_this->mCameraEye1, diff --git a/src/d/actor/d_a_obj_Lv5Key.cpp b/src/d/actor/d_a_obj_Lv5Key.cpp index 9c3b5c0e4c..a71ad25e33 100644 --- a/src/d/actor/d_a_obj_Lv5Key.cpp +++ b/src/d/actor/d_a_obj_Lv5Key.cpp @@ -170,7 +170,7 @@ void daObjLv5Key_c::Fall(int param_0) { OS_REPORT("FALL SPD = %f\n", speed.y); - if (mAcch.ChkGroundHit()) { + if (mAcch.ChkGroundHit() IF_DUSK(|| current.pos.abs(home.pos) > 200.0f)) { fopAcM_GetSpeed(this); fopAcM_SetSpeedF(this, 4.0f); fopAcM_SetSpeed(this, 0.0f, 22.0f, 0.0f); @@ -192,7 +192,7 @@ void daObjLv5Key_c::Fall(int param_0) { mAcch.CrrPos(dComIfG_Bgsp()); current.pos.y = prev_y; - if (mAcch.ChkGroundHit()) { + if (mAcch.ChkGroundHit() IF_DUSK(|| current.pos.abs(home.pos) > 200.0f)) { setAction(&daObjLv5Key_c::Land, 1); } } diff --git a/src/d/actor/d_a_obj_ari.cpp b/src/d/actor/d_a_obj_ari.cpp index 3e2727e2f2..267b0003af 100644 --- a/src/d/actor/d_a_obj_ari.cpp +++ b/src/d/actor/d_a_obj_ari.cpp @@ -499,13 +499,7 @@ 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 33595c7a77..00a35bc158 100644 --- a/src/d/actor/d_a_obj_bhashi.cpp +++ b/src/d/actor/d_a_obj_bhashi.cpp @@ -285,13 +285,7 @@ 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 27b0b8ce0e..8fbc2dbde8 100644 --- a/src/d/actor/d_a_obj_cho.cpp +++ b/src/d/actor/d_a_obj_cho.cpp @@ -289,13 +289,7 @@ 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 03ff2b1d6a..9712205ea3 100644 --- a/src/d/actor/d_a_obj_crvfence.cpp +++ b/src/d/actor/d_a_obj_crvfence.cpp @@ -224,13 +224,7 @@ 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 0b44a57ec8..2dc91c6e6b 100644 --- a/src/d/actor/d_a_obj_crvhahen.cpp +++ b/src/d/actor/d_a_obj_crvhahen.cpp @@ -137,13 +137,7 @@ 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; if (proj.x >= 0.0f && proj.x <= FB_WIDTH && proj.y >= 0.0f && proj.y <= FB_HEIGHT) { diff --git a/src/d/actor/d_a_obj_dan.cpp b/src/d/actor/d_a_obj_dan.cpp index 53dbf4e1e4..cc176b9a20 100644 --- a/src/d/actor/d_a_obj_dan.cpp +++ b/src/d/actor/d_a_obj_dan.cpp @@ -267,13 +267,7 @@ 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 a5b58a44a5..66963f0efd 100644 --- a/src/d/actor/d_a_obj_gomikabe.cpp +++ b/src/d/actor/d_a_obj_gomikabe.cpp @@ -201,13 +201,7 @@ 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 ea45fa5ea1..d5ab5558b0 100644 --- a/src/d/actor/d_a_obj_hhashi.cpp +++ b/src/d/actor/d_a_obj_hhashi.cpp @@ -214,13 +214,7 @@ 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 daa6560e6f..2b641d7769 100644 --- a/src/d/actor/d_a_obj_kamakiri.cpp +++ b/src/d/actor/d_a_obj_kamakiri.cpp @@ -517,13 +517,7 @@ 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 03d40a1066..805aa37b44 100644 --- a/src/d/actor/d_a_obj_katatsumuri.cpp +++ b/src/d/actor/d_a_obj_katatsumuri.cpp @@ -611,13 +611,7 @@ 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; if (camera != NULL) { diff --git a/src/d/actor/d_a_obj_kuwagata.cpp b/src/d/actor/d_a_obj_kuwagata.cpp index 914e25dfb1..80020208d3 100644 --- a/src/d/actor/d_a_obj_kuwagata.cpp +++ b/src/d/actor/d_a_obj_kuwagata.cpp @@ -528,13 +528,7 @@ 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; if (cc != NULL) { diff --git a/src/d/actor/d_a_obj_stone.cpp b/src/d/actor/d_a_obj_stone.cpp index f74adf12a7..080069e4f0 100644 --- a/src/d/actor/d_a_obj_stone.cpp +++ b/src/d/actor/d_a_obj_stone.cpp @@ -981,9 +981,7 @@ int daObjStone_c::draw() { if (!model) { f32 shadow_size = l_shadow_size[mStoneType]; TGXTexObj* pTex = dDlst_shadowControl_c::getSimpleTex(); - cXyz pos = current.pos; - - dComIfGd_setSimpleShadow(&pos, mChkObj.GetGroundH(), shadow_size, mChkObj.m_gnd, 0, + dComIfGd_setSimpleShadow(¤t.pos, mChkObj.GetGroundH(), shadow_size, mChkObj.m_gnd, 0, 1.0f, pTex); } return 1; diff --git a/src/d/actor/d_a_obj_ten.cpp b/src/d/actor/d_a_obj_ten.cpp index 1efe358607..fbedd6a8c9 100644 --- a/src/d/actor/d_a_obj_ten.cpp +++ b/src/d/actor/d_a_obj_ten.cpp @@ -593,13 +593,7 @@ 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 6fcbc938d9..a518e3cf25 100644 --- a/src/d/actor/d_a_obj_tombo.cpp +++ b/src/d/actor/d_a_obj_tombo.cpp @@ -504,13 +504,7 @@ 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 08932c439d..1525bdb572 100644 --- a/src/d/actor/d_a_obj_zra_freeze.cpp +++ b/src/d/actor/d_a_obj_zra_freeze.cpp @@ -38,12 +38,7 @@ 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 4c8b31c4c6..8ceb0ef237 100644 --- a/src/d/actor/d_a_player.cpp +++ b/src/d/actor/d_a_player.cpp @@ -421,13 +421,7 @@ void daPy_sightPacket_c::draw() { void daPy_sightPacket_c::setSight() { Vec proj; - - #if TARGET_PC - mDoLib_project(&mPos, &proj, {0, 0, FB_WIDTH, FB_HEIGHT}); - #else mDoLib_project(&mPos, &proj); - #endif - mDoMtx_stack_c::transS(proj.x, proj.y, proj.z); mDoMtx_stack_c::scaleM(32.0f, 32.0f, 32.0f); mDoMtx_copy(mDoMtx_stack_c::get(), mProjMtx); diff --git a/src/d/actor/d_flower.inc b/src/d/actor/d_flower.inc index 034d35961e..702337d9e5 100644 --- a/src/d/actor/d_flower.inc +++ b/src/d/actor/d_flower.inc @@ -700,13 +700,13 @@ void dFlower_packet_c::draw() { #ifdef TARGET_PC Mtx flower_mtx; if (dusk::frame_interp::lookup_replacement(reinterpret_cast(&sp44->m_modelMtx), flower_mtx)) { + GXLoadPosMtxImm(flower_mtx, 0); - } else { + } else #endif + { GXLoadPosMtxImm(sp44->m_modelMtx, 0); -#ifdef TARGET_PC } -#endif GXLoadNrmMtxImm(j3dSys.getViewMtx(), 0); #if TARGET_PC @@ -855,6 +855,7 @@ void dFlower_packet_c::draw() { #ifdef TARGET_PC Mtx flower_mtx; if (dusk::frame_interp::lookup_replacement(reinterpret_cast(&sp34->m_modelMtx), flower_mtx)) { + cMtx_concat(j3dSys.getViewMtx(), flower_mtx, flower_mtx); GXLoadPosMtxImm(flower_mtx, 0); } else { #endif @@ -994,7 +995,7 @@ void dFlower_packet_c::update() { mDoMtx_stack_c::scaleM(temp_f31, temp_f31, temp_f31); cMtx_concat(j3dSys.getViewMtx(), temp_r28, data_p->m_modelMtx); #ifdef TARGET_PC - dusk::frame_interp::record_final_mtx_raw(reinterpret_cast(&data_p->m_modelMtx), data_p->m_modelMtx); + dusk::frame_interp::record_final_mtx(mDoMtx_stack_c::get(), data_p->m_modelMtx); #endif } } diff --git a/src/d/actor/d_grass.inc b/src/d/actor/d_grass.inc index 0f651a3203..ab2724060f 100644 --- a/src/d/actor/d_grass.inc +++ b/src/d/actor/d_grass.inc @@ -756,13 +756,13 @@ void dGrass_packet_c::draw() { #ifdef TARGET_PC Mtx grass_mtx; if (dusk::frame_interp::lookup_replacement(reinterpret_cast(&var_r29->m_modelMtx), grass_mtx)) { + cMtx_concat(j3dSys.getViewMtx(), grass_mtx, grass_mtx); GXLoadPosMtxImm(grass_mtx, 0); - } else { + } else #endif + { GXLoadPosMtxImm(var_r29->m_modelMtx, 0); -#ifdef TARGET_PC } -#endif GXLoadNrmMtxImm(j3dSys.getViewMtx(), 0); if (var_r29->field_0x05 <= 3 || var_r29->field_0x05 >= 10) { if (var_r29->field_0x02 < -1) { @@ -1018,7 +1018,7 @@ void dGrass_packet_c::update() { cMtx_concat(j3dSys.getViewMtx(), mDoMtx_stack_c::get(), data_p->m_modelMtx); } #ifdef TARGET_PC - dusk::frame_interp::record_final_mtx_raw(reinterpret_cast(&data_p->m_modelMtx), data_p->m_modelMtx); + dusk::frame_interp::record_final_mtx(mDoMtx_stack_c::get(), data_p->m_modelMtx); #endif } } diff --git a/src/d/d_camera.cpp b/src/d/d_camera.cpp index b93d569003..f805a6a08b 100644 --- a/src/d/d_camera.cpp +++ b/src/d/d_camera.cpp @@ -7063,6 +7063,15 @@ bool dCamera_c::subjectCamera(s32 param_0) { } cXyz sp1E0(val0, val2, val1); + +#if TARGET_PC + f32 aspect = mDoGph_gInf_c::getAspect(); + f32 baseAspect = FB_WIDTH / FB_HEIGHT; + if (aspect > baseAspect) { + sp1E0.z += (aspect - baseAspect) * 4; + } +#endif + sp1D4 = dCamMath::xyzRotateX(sp1E0, angle_x); sp1E0 = dCamMath::xyzRotateY(sp1D4, angle_y); f32 sp6C = sp12 ? 40.0f : 0.0f; @@ -11009,6 +11018,15 @@ static int camera_execute(camera_process_class* i_this) { i_this->mCamera.CalcTrimSize(); store(i_this); + +#ifdef TARGET_PC + // record new camera for our sim frame + dusk::frame_interp::record_camera(i_this, get_camera_id(i_this)); + // interpolate the view now so that this sim frame's view matrix matches what + // we'll be rendering with later + dusk::frame_interp::interp_view(&i_this->view); +#endif + view_setup(i_this); return 1; } @@ -11077,9 +11095,6 @@ static int camera_draw(camera_process_class* i_this) { C_MTXPerspective(process->view.projMtx, process->view.fovy, process->view.aspect, process->view.near_, process->view.far_); mDoMtx_lookAt(process->view.viewMtx, &process->view.lookat.eye, &process->view.lookat.center, &process->view.lookat.up, process->view.bank); -#ifdef TARGET_PC - dusk::frame_interp::record_camera(process, camera_id); -#endif #if WIDESCREEN_SUPPORT mDoGph_gInf_c::setWideZoomProjection(process->view.projMtx); diff --git a/src/d/d_drawlist.cpp b/src/d/d_drawlist.cpp index e903e39ce4..373791f994 100644 --- a/src/d/d_drawlist.cpp +++ b/src/d/d_drawlist.cpp @@ -1096,16 +1096,7 @@ void dDlst_shadowReal_c::draw() { GXSetVtxDesc(GX_VA_POS, GX_DIRECT); GXSetVtxAttrFmt(GX_VTXFMT0, GX_VA_POS, GX_POS_XYZ, GX_F32, 0); GXSetCurrentMtx(GX_PNMTX0); -#ifdef TARGET_PC - Mtx receiver_proj_mtx; - if (dusk::frame_interp::lookup_replacement(&mReceiverProjMtx, receiver_proj_mtx)) { - GXLoadTexMtxImm(receiver_proj_mtx, GX_TEXMTX0, GX_MTX3x4); - } else { -#endif - GXLoadTexMtxImm(mReceiverProjMtx, GX_TEXMTX0, GX_MTX3x4); -#ifdef TARGET_PC - } -#endif + GXLoadTexMtxImm(mReceiverProjMtx, GX_TEXMTX0, GX_MTX3x4); mShadowRealPoly.draw(); } @@ -1263,14 +1254,9 @@ u8 dDlst_shadowReal_c::setShadowRealMtx(cXyz* param_0, cXyz* param_1, f32 param_ C_MTXOrtho(mRenderProjMtx, param_2, -param_2, -param_2, param_2, 1.0f, 10000.0f); C_MTXLightOrtho(mReceiverProjMtx, param_2, -param_2, -param_2, param_2, 0.5f, -0.5f, 0.5f, 0.5f); cMtx_concat(mReceiverProjMtx, mViewMtx, mReceiverProjMtx); -#ifdef TARGET_PC - dusk::frame_interp::record_final_mtx_raw(&mViewMtx, mViewMtx); - dusk::frame_interp::record_final_mtx_raw(&mReceiverProjMtx, mReceiverProjMtx); -#endif return r29; } - u32 dDlst_shadowReal_c::set(u32 i_key, J3DModel* i_model, cXyz* param_2, f32 param_3, f32 param_4, dKy_tevstr_c* param_5, f32 i_cameraZ, f32 param_7) { dScnKy_env_light_c* env_light = dKy_getEnvlight(); @@ -1292,6 +1278,7 @@ u32 dDlst_shadowReal_c::set(u32 i_key, J3DModel* i_model, cXyz* param_2, f32 par } field_0x1 = setShadowRealMtx(&sp60, param_2, param_3, param_4, param_7, param_5); + if (!field_0x1) { return 0; } @@ -1331,14 +1318,14 @@ void dDlst_shadowSimple_c::draw() { GXSetVtxDesc(GX_VA_POS, GX_INDEX8); #ifdef TARGET_PC Mtx volume_mtx; - if (dusk::frame_interp::lookup_replacement(&mVolumeMtx, volume_mtx)) { + if (dusk::frame_interp::lookup_replacement(mVolumeMtxKey, volume_mtx)) { + cMtx_concat(j3dSys.getViewMtx(), volume_mtx, volume_mtx); GXLoadPosMtxImm(volume_mtx, GX_PNMTX0); - } else { + } else #endif + { GXLoadPosMtxImm(mVolumeMtx, GX_PNMTX0); -#ifdef TARGET_PC } -#endif GXSetCurrentMtx(GX_PNMTX0); GXCallDisplayList(l_frontMat, 0x40); GXCallDisplayList(l_shadowVolumeDL, 0x40); @@ -1346,14 +1333,14 @@ void dDlst_shadowSimple_c::draw() { GXCallDisplayList(l_shadowVolumeDL, 0x40); #ifdef TARGET_PC Mtx shadow_mtx; - if (dusk::frame_interp::lookup_replacement(&mMtx, shadow_mtx)) { + if (dusk::frame_interp::lookup_replacement(mMtxKey, shadow_mtx)) { + cMtx_concat(j3dSys.getViewMtx(), shadow_mtx, shadow_mtx); GXLoadPosMtxImm(shadow_mtx, GX_PNMTX1); - } else { + } else #endif + { GXLoadPosMtxImm(mMtx, GX_PNMTX1); -#ifdef TARGET_PC } -#endif GXSetCurrentMtx(GX_PNMTX1); if (mpTexObj != NULL) { @@ -1383,6 +1370,12 @@ void dDlst_shadowSimple_c::draw() { GXCallDisplayList(l_shadowVolumeDL, 0x40); } +#if TARGET_PC +static const void* getInterpKey(const void* base, int idx) { + return reinterpret_cast(reinterpret_cast(base) ^ idx); +} +#endif + void dDlst_shadowSimple_c::set(cXyz* param_0, f32 param_1, f32 param_2, cXyz* param_3, s16 param_4, f32 param_5, TGXTexObj* param_6) { if (param_5 < 0.0f) { @@ -1406,6 +1399,10 @@ void dDlst_shadowSimple_c::set(cXyz* param_0, f32 param_1, f32 param_2, cXyz* pa mDoMtx_stack_c::transS(param_0->x, param_1 + f30, param_0->z); mDoMtx_stack_c::YrotM(param_4); mDoMtx_stack_c::scaleM(param_2, f30 + f30 + 16.0f, param_2 * param_5); +#if TARGET_PC + mVolumeMtxKey = getInterpKey(param_0, 0x1); + dusk::frame_interp::record_final_mtx(mDoMtx_stack_c::get(), mVolumeMtxKey); +#endif cMtx_concat(j3dSys.getViewMtx(), mDoMtx_stack_c::get(), mVolumeMtx); f32 f31 = JMAFastSqrt(1.0f - param_3->x * param_3->x); f32 f29; @@ -1431,17 +1428,11 @@ void dDlst_shadowSimple_c::set(cXyz* param_0, f32 param_1, f32 param_2, cXyz* pa mDoMtx_stack_c::get()[2][3] = param_0->z; mDoMtx_stack_c::YrotM(param_4); mDoMtx_stack_c::scaleM(param_2, 1.0f, param_2 * param_5); - cMtx_concat(j3dSys.getViewMtx(), mDoMtx_stack_c::get(), mMtx); #ifdef TARGET_PC - const uint64_t shadow_tag_base = dusk::frame_interp::alloc_simple_shadow_pair_base(); - if (shadow_tag_base != 0) { - dusk::frame_interp::record_final_mtx_raw_tagged(&mVolumeMtx, mVolumeMtx, shadow_tag_base); - dusk::frame_interp::record_final_mtx_raw_tagged(&mMtx, mMtx, shadow_tag_base + 1u); - } else { - dusk::frame_interp::record_final_mtx_raw(&mVolumeMtx, mVolumeMtx); - dusk::frame_interp::record_final_mtx_raw(&mMtx, mMtx); - } + mMtxKey = getInterpKey(param_0, 0x2); + dusk::frame_interp::record_final_mtx(mDoMtx_stack_c::get(), mMtxKey); #endif + cMtx_concat(j3dSys.getViewMtx(), mDoMtx_stack_c::get(), mMtx); mpTexObj = param_6; } @@ -1544,9 +1535,10 @@ void dDlst_shadowControl_c::imageDraw(Mtx param_0) { #ifdef TARGET_PC GXCreateFrameBuffer(r26, r26); needsRestore = true; -#endif +#else GXSetViewport(0.0f, 0.0f, r26, r26, 0.0f, 1.0f); GXSetScissor(0, 0, r26, r26); +#endif } GXSetTevColor(GX_TEVREG0, l_imageDrawColor[chan]); if (chan == 3) { diff --git a/src/d/d_file_select.cpp b/src/d/d_file_select.cpp index 550c5b3e52..23ceb96f00 100644 --- a/src/d/d_file_select.cpp +++ b/src/d/d_file_select.cpp @@ -2102,11 +2102,7 @@ void dFile_select_c::yesnoCursorShow() { 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 } } @@ -2259,11 +2255,7 @@ void dFile_select_c::YesNoCancelMove() { 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; @@ -3147,11 +3139,7 @@ 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); @@ -3204,6 +3192,9 @@ void dFile_select_c::screenSet() { timg, NULL); mpFadePict->setBlackWhite(black, white); mpFadePict->setAlpha(0); +#ifdef TARGET_PC + mFadeDlst.mpPict = mpFadePict; +#endif #endif } @@ -3284,11 +3275,7 @@ 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); @@ -3680,11 +3667,7 @@ void dFile_select_c::selFileCursorShow() { 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) { @@ -3727,11 +3710,7 @@ void dFile_select_c::menuCursorShow() { 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 } } @@ -3833,6 +3812,16 @@ void dFile_select_c::fileSelectWide() { 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); + + #if TARGET_PC + if (mSelIcon) { + mSelIcon->refreshAspectScale(); + } + + if (mSelIcon2) { + mSelIcon2->refreshAspectScale(); + } + #endif } #endif @@ -3871,9 +3860,7 @@ void dFile_select_c::_draw() { #if PLATFORM_GCN #if TARGET_PC - mpFadePict->draw(0, 0, - mDoGph_gInf_c::getWidth(), mDoGph_gInf_c::getHeight(), false, false, - false); + dComIfGd_set2DOpaTop(&mFadeDlst); #else mpFadePict->draw(mDoGph_gInf_c::getMinXF(), mDoGph_gInf_c::getMinYF(), mDoGph_gInf_c::getWidthF(), mDoGph_gInf_c::getHeightF(), false, false, @@ -3923,6 +3910,13 @@ void dDlst_FileSel3m_c::draw() { Scr3m->draw(0.0f, 0.0f, graf); } +#ifdef TARGET_PC +void dDlst_FileSelFade_c::draw() { + mpPict->draw(mDoGph_gInf_c::getMinXF(), mDoGph_gInf_c::getMinYF(), + mDoGph_gInf_c::getWidthF(), mDoGph_gInf_c::getHeightF(), false, false, false); +} +#endif + void dFile_select_c::errorMoveAnmInitSet(int param_1, int param_2) { mErrorMsgPane->setAnimation(field_0x0090); field_0x0130 = param_1; diff --git a/src/d/d_gameover.cpp b/src/d/d_gameover.cpp index baec970a32..870fb00f14 100644 --- a/src/d/d_gameover.cpp +++ b/src/d/d_gameover.cpp @@ -37,11 +37,10 @@ void dDlst_Gameover_CAPTURE_c::draw() { TGXTexObj tex_obj; Mtx44 m; -#if TARGET_PC - GXSetTexCopySrc(0, 0, mDoGph_gInf_c::getWidth(), mDoGph_gInf_c::getHeight()); - GXSetTexCopyDst(mDoGph_gInf_c::getWidth(), mDoGph_gInf_c::getHeight(), GX_TF_RGB565, GX_TRUE); -#else GXSetTexCopySrc(0, 0, FB_WIDTH, FB_HEIGHT); +#if TARGET_PC + GXSetTexCopyDst(FB_WIDTH, FB_HEIGHT, GX_TF_RGB565, GX_FALSE); +#else GXSetTexCopyDst(FB_WIDTH / 2, FB_HEIGHT / 2, GX_TF_RGB565, GX_TRUE); #endif GXCopyTex(mDoGph_gInf_c::mZbufferTex, 0); diff --git a/src/d/d_insect.cpp b/src/d/d_insect.cpp index 380f545bd3..3f1d2fae11 100644 --- a/src/d/d_insect.cpp +++ b/src/d/d_insect.cpp @@ -82,11 +82,7 @@ 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_kankyo.cpp b/src/d/d_kankyo.cpp index 9bb96efc82..6b84fbae43 100644 --- a/src/d/d_kankyo.cpp +++ b/src/d/d_kankyo.cpp @@ -35,6 +35,7 @@ #if TARGET_PC #include "dusk/imgui/ImGuiBloomWindow.hpp" #include "dusk/settings.h" +#include "dusk/frame_interpolation.h" #endif static void GxXFog_set(); @@ -8251,6 +8252,10 @@ static int dKy_Create(void* i_this) { kankyo_class* kankyo = (kankyo_class*)i_this; BOOL next_time_set = false; +#if TARGET_PC + kankyo->base.draw_interp_frame = true; +#endif + stage_envr_info_class* stage_envr_p = dComIfGp_getStageEnvrInfo(); if (stage_envr_p != NULL && dComIfGp_getStartStageRoomNo() != -1) { stage_envr_p += dComIfGp_getStartStageRoomNo(); @@ -11004,11 +11009,7 @@ 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 03bfeac196..7fdad26ed2 100644 --- a/src/d/d_kankyo_debug.cpp +++ b/src/d/d_kankyo_debug.cpp @@ -915,12 +915,7 @@ 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 31ba59e33e..64cf2247e0 100644 --- a/src/d/d_kankyo_rain.cpp +++ b/src/d/d_kankyo_rain.cpp @@ -116,12 +116,7 @@ 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; @@ -221,12 +216,7 @@ 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; @@ -4127,11 +4117,7 @@ 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 // Dusk optimization: we use vertex color rather than GX_TEVREG0 to set star color. // This allows us to merge all the stars into a single draw. @@ -4280,11 +4266,7 @@ 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; @@ -4699,11 +4681,7 @@ 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; } @@ -4968,12 +4946,7 @@ 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; @@ -5023,12 +4996,7 @@ 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; @@ -6068,13 +6036,7 @@ static void dKyr_evil_draw2(Mtx drawMtx, u8** tex) { sp34.x = 80.0f; 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 (!(proj.x > -sp34.x) || !(proj.x < (FB_WIDTH + sp34.x)) || !(proj.y > -sp34.y) || !(proj.y < (458.0f + sp34.z))) { @@ -6299,12 +6261,7 @@ 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 (!(proj.x > -sp44.x) || !(proj.x < (FB_WIDTH + sp44.x)) || !(proj.y > -sp44.y) || !(proj.y < (458.0f + sp44.z))) { diff --git a/src/d/d_map_path.cpp b/src/d/d_map_path.cpp index a31ccdedfd..916bd2c223 100644 --- a/src/d/d_map_path.cpp +++ b/src/d/d_map_path.cpp @@ -16,10 +16,6 @@ #ifdef TARGET_PC constexpr u16 kMapResolutionMultiplier = 4; -// Line widths are relative to the framebuffer size. Since we're rendering to a separate -// framebuffer, we have to scale them accordingly. The original game used about half of the -// EFB for the map rendering, so this is a reasonable approximation. -constexpr u8 kMapLineWidthMultiplier = 2; #endif void dMpath_n::dTexObjAggregate_c::create() { @@ -242,11 +238,7 @@ void dDrawPath_c::rendering(dDrawPath_c::line_class const* p_line) { int width = getLineWidth(p_line->field_0x1); if (width > 0 && p_line->mDataNum >= 2) { -#ifdef TARGET_PC - GXSetLineWidth(width * kMapLineWidthMultiplier, GX_TO_ZERO); -#else - GXSetLineWidth(width * 2, GX_TO_ZERO); -#endif + GXSetLineWidth(width, GX_TO_ZERO); GXSetTevColor(GX_TEVREG0, *getLineColor(p_line->field_0x0 & 0x3F, p_line->field_0x1)); GXBegin(GX_LINESTRIP, GX_VTXFMT0, p_line->mDataNum); @@ -435,8 +427,12 @@ void dRenderingFDAmap_c::preRenderingMap() { const u16 w = mTexWidth * kMapResolutionMultiplier; const u16 h = mTexHeight * kMapResolutionMultiplier; GXCreateFrameBuffer(w, h); - GXSetViewport(0.0f, 0.0f, w, h, 0.0f, 1.0f); - GXSetScissor(0, 0, w, h); + // Set logical viewport dimensions + GXSetViewport(0.0f, 0.0f, mTexWidth, mTexHeight, 0.0f, 1.0f); + GXSetScissor(0, 0, mTexWidth, mTexHeight); + // Set render viewport dimensions + GXSetViewportRender(0.0f, 0.0f, w, h, 0.0f, 1.0f); + GXSetScissorRender(0, 0, w, h); #else GXSetViewport(0.0f, 0.0f, mTexWidth, mTexHeight, 0.0f, 1.0f); GXSetScissor(0, 0, mTexWidth, mTexHeight); @@ -517,13 +513,8 @@ void dRenderingFDAmap_c::renderingDecoration(dDrawPath_c::line_class const* p_li BE(u16)* data_p = p_line->mpData; s32 data_num = p_line->mDataNum; -#ifdef TARGET_PC - GXSetLineWidth(width * kMapLineWidthMultiplier, GX_TO_ZERO); - GXSetPointSize(width * kMapLineWidthMultiplier, GX_TO_ONE); -#else GXSetLineWidth(width, GX_TO_ONE); GXSetPointSize(width, GX_TO_ONE); -#endif GXColor lineColor = *getDecoLineColor(p_line->field_0x0 & 0x3f, p_line->field_0x1); GXSetTevColor(GX_TEVREG0, lineColor); lineColor.r = lineColor.r - 4; diff --git a/src/d/d_menu_collect.cpp b/src/d/d_menu_collect.cpp index 7ae416c4be..46c9c1a9d9 100644 --- a/src/d/d_menu_collect.cpp +++ b/src/d/d_menu_collect.cpp @@ -164,11 +164,22 @@ void dMenu_Collect2D_c::menuCollectWide() { // Item Description Text mpScreen->search(MULTI_CHAR('infotxtn'))->scale(mDoGph_gInf_c::hudAspectScaleDown, 1.0f); + + #if TARGET_PC + if (mpDrawCursor) { + mpDrawCursor->refreshAspectScale(); + } + #endif } #endif void dMenu_Collect2D_c::_create() { mpHeap->getTotalFreeSize(); + + #if TARGET_PC + mpDrawCursor = NULL; + #endif + mpScreen = JKR_NEW J2DScreen(); mpScreen->setPriority("zelda_collect_soubi_screen.blo", 0x1020000, dComIfGp_getCollectResArchive()); @@ -1100,23 +1111,11 @@ 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 } } @@ -2688,12 +2687,7 @@ u8 dMenu_Collect3D_c::getMaskMdlVisible() { f32 dMenu_Collect3D_c::mViewOffsetY = -100.0f; void dMenu_Collect3D_c::setupItem3D(Mtx param_0) { -#if TARGET_PC - 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); -#endif mViewOffsetY = -100.0f; Mtx44 projection; C_MTXPerspective(projection, 45.0f, mDoGph_gInf_c::getAspect(), 1.0f, 100000.0f); diff --git a/src/d/d_menu_dmap.cpp b/src/d/d_menu_dmap.cpp index 739dfc7843..66533dd12c 100644 --- a/src/d/d_menu_dmap.cpp +++ b/src/d/d_menu_dmap.cpp @@ -864,33 +864,15 @@ 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 - grafContext->scissor(field_0xd94, 0.0f, FB_WIDTH, FB_HEIGHT); -#endif + grafContext->scissor(field_0xd94, 0.0f, FB_WIDTH, FB_HEIGHT); grafContext->setScissor(); mBaseScreen->draw(field_0xd94, field_0xd98, grafContext); dMenu_Dmap_c::myclass->drawFloorScreenBack(mFloorScreen, field_0xd94, field_0xd98, grafContext); -#if TARGET_PC - 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; -#endif mMapScreen[0]->draw(field_0xd94, field_0xd98, grafContext); if (mpBackTexture != NULL) { @@ -922,15 +904,9 @@ void dMenu_DmapBg_c::draw() { mpBackTexture->draw(local_28c, field_0xd94 + mpBackTexture->getBounds().i.y, mpBackTexture->getWidth(), mpBackTexture->getHeight(), false, false, false); -#if TARGET_PC - grafContext->scissor(field_0xd94, - 0, mDoGph_gInf_c::getWidth(), - scissor_height); -#else grafContext->scissor(field_0xd94 + mDoGph_gInf_c::getMinXF(), scissor_top, mDoGph_gInf_c::getWidthF(), scissor_height); -#endif grafContext->setScissor(); } @@ -957,11 +933,7 @@ void dMenu_DmapBg_c::draw() { Vec local_26c = pane.getGlobalVtx(mMapPane, &local_110, 0, false, 0); drawIcon(local_26c.x + field_0xd94, local_26c.y, field_0xda8, 1.0f); -#if TARGET_PC - grafContext->scissor(field_0xd94, scissor_top, mDoGph_gInf_c::getWidth(), scissor_height); -#else grafContext->scissor(field_0xd94 + mDoGph_gInf_c::getMinXF(), scissor_top, mDoGph_gInf_c::getWidthF(), scissor_height); -#endif grafContext->setScissor(); grafContext->scissor(scissor_left, scissor_top, scissor_width, scissor_height); grafContext->setScissor(); diff --git a/src/d/d_menu_fmap2D.cpp b/src/d/d_menu_fmap2D.cpp index 558ad05d6d..a3afaa1641 100644 --- a/src/d/d_menu_fmap2D.cpp +++ b/src/d/d_menu_fmap2D.cpp @@ -276,18 +276,14 @@ void dMenu_Fmap2DBack_c::draw() { u32 scissorLeft, scissorTop, scissorWidth, scissorHeight; GXGetScissor(&scissorLeft, &scissorTop, &scissorWidth, &scissorHeight); -#if TARGET_PC - grafPort->scissor(mTransX, 0.0f, mDoGph_gInf_c::getWidth(), mDoGph_gInf_c::getHeight()); -#else grafPort->scissor(mTransX, 0.0f, FB_WIDTH, FB_HEIGHT); -#endif grafPort->setScissor(); mpBackTex->setBlackWhite(field_0x1208, field_0x120c); mpBackTex->setAlpha(mAlphaRate * 255.0f * g_fmapHIO.mBackgroundAlpha); mpBackTex->draw(mTransX + mDoGph_gInf_c::getMinXF(), - mTransZ + mDoGph_gInf_c::getMinYF(), mDoGph_gInf_c::getWidth(), - mDoGph_gInf_c::getHeight(), false, false, false); + mTransZ + mDoGph_gInf_c::getMinYF(), mDoGph_gInf_c::getWidthF(), + mDoGph_gInf_c::getHeightF(), false, false, false); mpBackScreen->draw(mTransX, mTransZ, grafPort); mpBaseScreen->draw(mTransX, mTransZ, grafPort); @@ -297,13 +293,8 @@ void dMenu_Fmap2DBack_c::draw() { Vec vec2 = mpMapArea->getGlobalVtx(&mtx, 3, false, 0); -#if TARGET_PC - f32 width = mDoGph_gInf_c::getWidthF() / mDoGph_gInf_c::getWidth(); - f32 height = mDoGph_gInf_c::getHeightF() / mDoGph_gInf_c::getHeight(); -#else f32 width = mDoGph_gInf_c::getWidthF() / FB_WIDTH; f32 height = mDoGph_gInf_c::getHeightF() / FB_HEIGHT; -#endif grafPort->scissor(mTransX + ((vec1.x - mDoGph_gInf_c::getMinXF()) / width), mTransZ + (vec1.y / height), (vec2.x - vec1.x) / width, @@ -351,8 +342,13 @@ void dMenu_Fmap2DBack_c::draw() { scrollAreaDraw(); } - blinkMove(30); - moveLightDropAnime(); +#ifdef TARGET_PC + if (dusk::frame_interp::get_ui_tick_pending()) +#endif + { + blinkMove(30); + moveLightDropAnime(); + } setCenterPosX(field_0x11dc, 1); drawIcon(mTransX, mTransZ, mAlphaRate, field_0xfa8 * mSpotTextureFadeAlpha); @@ -360,11 +356,7 @@ 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()) { @@ -392,16 +384,15 @@ void dMenu_Fmap2DBack_c::draw() { &mArrowPos2DY); #ifdef TARGET_PC - for (u32 i = 0; i < dusk::frame_interp::get_presentation_ui_advance_ticks(); ++i) { + if (dusk::frame_interp::get_ui_tick_pending()) #endif + { field_0x11e0 -= g_fmapHIO.mCursorSpeed; if (field_0x11e0 < 0.0f) { field_0x11e0 += 360.0f; } -#ifdef TARGET_PC } -#endif mpPointParent->getPanePtr()->rotate(mpPointParent->getSizeX() / 2.0f, mpPointParent->getSizeY() / 2.0f, ROTATE_Z, @@ -2580,11 +2571,7 @@ void dMenu_Fmap2DTop_c::draw() { J2DOrthoGraph* ctx = static_cast(dComIfGp_getCurrentGrafPort()); ctx->setup2D(); GXGetScissor(&scissor_left, &scissor_top, &scissor_width, &scissor_height); -#if TARGET_PC - ctx->scissor(mTransX, 0.0f, mDoGph_gInf_c::getWidth(), mDoGph_gInf_c::getHeight()); -#else ctx->scissor(mTransX, 0.0f, FB_WIDTH, FB_HEIGHT); -#endif ctx->setScissor(); mpTitleScreen->draw(mTransX, mTransY, ctx); ctx->scissor(scissor_left, scissor_top, scissor_width, scissor_height); diff --git a/src/d/d_menu_letter.cpp b/src/d/d_menu_letter.cpp index cef018372f..a0155ef6b4 100644 --- a/src/d/d_menu_letter.cpp +++ b/src/d/d_menu_letter.cpp @@ -223,13 +223,8 @@ void dMenu_Letter_c::_draw() { f32 y1 = local_178.y; Vec local_184; local_184 = afStack_138.getGlobalVtx(field_0x1ec, &mtx, 3, false, 0); -#if TARGET_PC - f32 dVar17 = mDoGph_gInf_c::getWidthF() / mDoGph_gInf_c::getWidth(); - f32 dVar16 = mDoGph_gInf_c::getHeightF() / mDoGph_gInf_c::getHeight(); -#else f32 dVar17 = mDoGph_gInf_c::getWidthF() / FB_WIDTH; f32 dVar16 = mDoGph_gInf_c::getHeightF() / FB_HEIGHT; -#endif f32 fVar1 = (x1 - mDoGph_gInf_c::getMinXF()) / dVar17; f32 fVar2 = y1 / dVar16; grafContext->scissor(fVar1, fVar2, diff --git a/src/d/d_menu_option.cpp b/src/d/d_menu_option.cpp index 9384bc06b9..af322a1c01 100644 --- a/src/d/d_menu_option.cpp +++ b/src/d/d_menu_option.cpp @@ -555,19 +555,23 @@ 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 diff --git a/src/d/d_menu_ring.cpp b/src/d/d_menu_ring.cpp index 8e5b3cacd2..529597248a 100644 --- a/src/d/d_menu_ring.cpp +++ b/src/d/d_menu_ring.cpp @@ -29,6 +29,10 @@ #include +#if TARGET_PC +#include "dusk/game_clock.h" +#endif + typedef void (dMenu_Ring_c::*initFunc)(); static initFunc stick_init[] = { /* STATUS_WAIT */ &dMenu_Ring_c::stick_wait_init, @@ -183,6 +187,9 @@ dMenu_Ring_c::dMenu_Ring_c(JKRExpHeap* i_heap, STControl* i_stick, CSTControl* i } for (int i = 0; i < 4; i++) { field_0x674[i] = 0; +#if TARGET_PC + mSelectItemSlideElapsed[i] = 0.0f; +#endif field_0x518[i] = 0.0f; field_0x528[i] = 0.0f; field_0x538[i] = 0.0f; @@ -1022,6 +1029,9 @@ void dMenu_Ring_c::setJumpItem(bool i_useVibrationM) { field_0x6b8[0] != dComIfGs_getMixItemIndex(0)) { field_0x674[0] = 1; +#if TARGET_PC + mSelectItemSlideElapsed[0] = 0.0f; +#endif } } else if (field_0x6b3 == 1) { field_0x538[0] = g_ringHIO.mUnselectItemScale; @@ -1030,6 +1040,9 @@ void dMenu_Ring_c::setJumpItem(bool i_useVibrationM) { field_0x6b8[1] != dComIfGs_getMixItemIndex(1)) { field_0x674[1] = 1; +#if TARGET_PC + mSelectItemSlideElapsed[1] = 0.0f; +#endif } } if (field_0x674[0] == 1) { @@ -1520,7 +1533,15 @@ void dMenu_Ring_c::setSelectItem(int i_idx, u8 i_itemNo) { void dMenu_Ring_c::drawSelectItem() { for (int i = 0; i < 4; i++) { if (field_0x674[i] != 0) { +#if TARGET_PC + mSelectItemSlideElapsed[i] += dusk::game_clock::consume_interval(this); + const f32 u = std::min(mSelectItemSlideElapsed[i] / dusk::game_clock::period_for_original_frames(10.0f), 1.0f); + if (u >= 1.0f) { + setSelectItemForce(i); + } else { +#else if (field_0x674[i] < 10) { +#endif f32 initSizeX = dMeter2Info_getMeterItemPanePtr(i)->getInitSizeX() * 1.7f; f32 initSizeY = dMeter2Info_getMeterItemPanePtr(i)->getInitSizeY() * 1.7f; f32 initScaleX = dMeter2Info_getMeterItemPanePtr(i)->getInitScaleX(); @@ -1528,7 +1549,11 @@ void dMenu_Ring_c::drawSelectItem() { Vec pos = dMeter2Info_getMeterItemPanePtr(i)->getGlobalVtxCenter( dMeter2Info_getMeterItemPanePtr(i)->mPane, true, 0); +#if TARGET_PC + f32 fVar14 = 0.1f + 0.8f * u; +#else f32 fVar14 = field_0x674[i] / 10.0f; +#endif if (field_0x6cd != 0xff) { fVar14 = 1.0f - fVar14; } @@ -1549,9 +1574,11 @@ void dMenu_Ring_c::drawSelectItem() { 0); } } +#if !TARGET_PC field_0x674[i]++; } else { setSelectItemForce(i); +#endif } } } @@ -1562,6 +1589,9 @@ void dMenu_Ring_c::setSelectItemForce(int i_idx) { if (field_0x674[i_idx] != 0) { dComIfGs_setSelectItemIndex(i_idx, field_0x6b4[i_idx]); field_0x674[i_idx] = 0; +#if TARGET_PC + mSelectItemSlideElapsed[i_idx] = 0.0f; +#endif } } else if (field_0x674[i_idx] != 0) { for (int i = 0; i < 2; i++) { @@ -1569,6 +1599,9 @@ void dMenu_Ring_c::setSelectItemForce(int i_idx) { dComIfGs_setSelectItemIndex(i, field_0x6b4[i]); } field_0x674[i_idx] = 0; +#if TARGET_PC + mSelectItemSlideElapsed[i_idx] = 0.0f; +#endif } } diff --git a/src/d/d_menu_save.cpp b/src/d/d_menu_save.cpp index 557095915e..8b1d2e87b3 100644 --- a/src/d/d_menu_save.cpp +++ b/src/d/d_menu_save.cpp @@ -386,11 +386,7 @@ 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); @@ -2520,11 +2516,7 @@ void dMenu_save_c::yesnoCursorShow() { 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 } } @@ -2673,11 +2665,7 @@ void dMenu_save_c::selFileCursorShow() { 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) { @@ -2810,6 +2798,12 @@ void dMenu_save_c::menuSaveWide() { 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); + + #if TARGET_PC + if (mSelIcon) { + mSelIcon->refreshAspectScale(); + } + #endif } #endif diff --git a/src/d/d_menu_window.cpp b/src/d/d_menu_window.cpp index af8a734fe7..7f76f807df 100644 --- a/src/d/d_menu_window.cpp +++ b/src/d/d_menu_window.cpp @@ -32,15 +32,9 @@ public: if (getDrawFlag() == 1) { setDrawFlag(); dComIfGp_onPauseFlag(); - - #if TARGET_PC - GXSetTexCopySrc(0, 0, mDoGph_gInf_c::getWidth(), mDoGph_gInf_c::getHeight()); - #else GXSetTexCopySrc(0, 0, FB_WIDTH, FB_HEIGHT); - #endif - #if TARGET_PC - GXSetTexCopyDst(mDoGph_gInf_c::getWidth(), mDoGph_gInf_c::getHeight(), (GXTexFmt)mDoGph_gInf_c::getFrameBufferTimg()->format, GX_ENABLE); + GXSetTexCopyDst(FB_WIDTH, FB_HEIGHT, (GXTexFmt)mDoGph_gInf_c::getFrameBufferTimg()->format, GX_DISABLE); #else GXSetTexCopyDst(FB_WIDTH / 2, FB_HEIGHT / 2, (GXTexFmt)mDoGph_gInf_c::getFrameBufferTimg()->format, GX_ENABLE); #endif @@ -48,17 +42,17 @@ public: GXPixModeSync(); #if TARGET_PC // init mTexObj at capture time so the gpu ref survives window resizes - mCaptureWidth = mDoGph_gInf_c::getWidth(); - mCaptureHeight = mDoGph_gInf_c::getHeight(); - GXInitTexObj(&mTexObj, mDoGph_gInf_c::getFrameBufferTex(), mCaptureWidth, mCaptureHeight, + mCaptureWidth = JUTVideo::getManager()->getRenderWidth(); + mCaptureHeight = JUTVideo::getManager()->getRenderHeight(); + GXInitTexObj(&mTexObj, mDoGph_gInf_c::getFrameBufferTex(), FB_WIDTH / 2, FB_HEIGHT / 2, (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 // If the window was resized since capture, force a re-capture at the new size - if (mCaptureWidth != (u16)mDoGph_gInf_c::getWidth() || - mCaptureHeight != (u16)mDoGph_gInf_c::getHeight()) { + if (mCaptureWidth != JUTVideo::getManager()->getRenderWidth() || + mCaptureHeight != JUTVideo::getManager()->getRenderHeight()) { mFlag = 1; return; } @@ -137,8 +131,8 @@ private: /* 0x5 */ u8 mAlpha; /* 0x6 */ u8 mTopFlag; #if TARGET_PC - u16 mCaptureWidth; - u16 mCaptureHeight; + u32 mCaptureWidth; + u32 mCaptureHeight; TGXTexObj mTexObj; #endif }; @@ -705,7 +699,7 @@ void dMw_c::collect_open_proc() { dMeter2Info_set2DVibrationM(); } - if (mDoGph_gInf_c::getFader()->getStatus() == JUTFader::UNKSTATUS_0) { + if (mDoGph_gInf_c::getFader()->getStatus() == JUTFader::None) { mMenuProc = COLLECT_MOVE; } } @@ -920,7 +914,7 @@ void dMw_c::collect_letter_move_proc() { } void dMw_c::collect_letter_close_proc() { - if (mDoGph_gInf_c::getFader()->getStatus() == JUTFader::UNKSTATUS_0) { + if (mDoGph_gInf_c::getFader()->getStatus() == JUTFader::None) { mMenuProc = COLLECT_MOVE; } } @@ -952,7 +946,7 @@ void dMw_c::collect_fishing_move_proc() { } void dMw_c::collect_fishing_close_proc() { - if (mDoGph_gInf_c::getFader()->getStatus() == JUTFader::UNKSTATUS_0) { + if (mDoGph_gInf_c::getFader()->getStatus() == JUTFader::None) { mMenuProc = COLLECT_MOVE; } } @@ -983,7 +977,7 @@ void dMw_c::collect_skill_move_proc() { } void dMw_c::collect_skill_close_proc() { - if (mDoGph_gInf_c::getFader()->getStatus() == JUTFader::UNKSTATUS_0) { + if (mDoGph_gInf_c::getFader()->getStatus() == JUTFader::None) { mMenuProc = COLLECT_MOVE; } } @@ -1014,13 +1008,13 @@ void dMw_c::collect_insect_move_proc() { } void dMw_c::collect_insect_close_proc() { - if (mDoGph_gInf_c::getFader()->getStatus() == JUTFader::UNKSTATUS_0) { + if (mDoGph_gInf_c::getFader()->getStatus() == JUTFader::None) { mMenuProc = COLLECT_MOVE; } } void dMw_c::insect_open_proc() { - if (mDoGph_gInf_c::getFader()->getStatus() == JUTFader::UNKSTATUS_0) { + if (mDoGph_gInf_c::getFader()->getStatus() == JUTFader::None) { field_0x152 = 0; dComIfGp_setHeapLockFlag(1); dMw_insect_create(1); @@ -1056,7 +1050,7 @@ void dMw_c::insect_move_proc() { } void dMw_c::insect_close_proc() { - if (mDoGph_gInf_c::getFader()->getStatus() == JUTFader::UNKSTATUS_0) { + if (mDoGph_gInf_c::getFader()->getStatus() == JUTFader::None) { mMenuProc = NO_MENU; } } diff --git a/src/d/d_meter2_draw.cpp b/src/d/d_meter2_draw.cpp index 417dcad319..8e824f583b 100644 --- a/src/d/d_meter2_draw.cpp +++ b/src/d/d_meter2_draw.cpp @@ -638,12 +638,11 @@ void dMeter2Draw_c::draw() { var_f29 = g_drawHIO.mLightDrop.mDropPikariAnimSpeed_Completed; int temp_r5_2 = g_drawHIO.mLightDrop.mPikariInterval * 15; #ifdef TARGET_PC - // Set even if not advancing + // FRAME INTERP NOTE: Set even if not advancing var_f28 = g_drawHIO.mLightDrop.mPikariScaleComplete; - - const u32 ui_advance_ticks = dusk::frame_interp::get_presentation_ui_advance_ticks(); - for (u32 tick = 0; tick < ui_advance_ticks; ++tick) { + if (dusk::frame_interp::get_ui_tick_pending()) #endif + { if (field_0x756 <= temp_r5_2) { int temp_r4 = (field_0x756 % g_drawHIO.mLightDrop.mPikariInterval); int temp_r3_5 = field_0x756 / g_drawHIO.mLightDrop.mPikariInterval; @@ -669,17 +668,12 @@ void dMeter2Draw_c::draw() { } field_0x756 = -1; -#ifdef TARGET_PC - break; -#endif } else { field_0x756++; } } } -#ifdef TARGET_PC } -#endif for (int i = 0; i < 16; i++) { if (field_0x66c[i] > 0.0f) { @@ -1349,9 +1343,9 @@ void dMeter2Draw_c::drawPikari(f32 i_posX, f32 i_posY, f32* i_framep, f32 i_scal *i_framep = 0.0f; } else { #ifdef TARGET_PC - const u32 ui_advance_ticks = dusk::frame_interp::get_presentation_ui_advance_ticks(); - for (u32 i = 0; i < ui_advance_ticks; ++i) { + if (dusk::frame_interp::get_ui_tick_pending()) #endif + { *i_framep += param_8; if (*i_framep > var_f31) { if (param_9 == 1 || param_9 == 2 || param_9 == 3) { @@ -1366,9 +1360,7 @@ void dMeter2Draw_c::drawPikari(f32 i_posX, f32 i_posY, f32* i_framep, f32 i_scal } else if (*i_framep == 18.0f && param_9 == 2) { mDoAud_seStart(Z2SE_SY_ITEM_COMBINE_ICON, NULL, 0, 0); } -#ifdef TARGET_PC } -#endif playPikariBckAnimation(*i_framep); playPikariBpkAnimation(*i_framep); diff --git a/src/d/d_meter_button.cpp b/src/d/d_meter_button.cpp index 88f750d6ca..d36a124d17 100644 --- a/src/d/d_meter_button.cpp +++ b/src/d/d_meter_button.cpp @@ -16,6 +16,7 @@ #include "d/d_msg_out_font.h" #include "d/d_msg_string.h" #include "d/d_pane_class.h" +#include "dusk/frame_interpolation.h" #include #if VERSION == VERSION_GCN_JPN @@ -280,15 +281,20 @@ void dMeterButton_c::draw() { s16 temp_r6 = g_drawHIO.mEmpButton.mRepeatHitFrameNum; s16 temp_r6_2 = g_drawHIO.mEmpButton.mRepeatHitFrameNum / 2; - field_0x4b8[i]++; +#ifdef TARGET_PC + if (dusk::frame_interp::get_ui_tick_pending()) +#endif + { + field_0x4b8[i]++; - if (field_0x4b8[i] >= temp_r6) { - field_0x4b8[i] = 0; + if (field_0x4b8[i] >= temp_r6) { + field_0x4b8[i] = 0; - if (field_0x4bc[i] == 0) { - field_0x4bc[i] = 1; - } else { - field_0x4bc[i] = 0; + if (field_0x4bc[i] == 0) { + field_0x4bc[i] = 1; + } else { + field_0x4bc[i] = 0; + } } } diff --git a/src/d/d_meter_haihai.cpp b/src/d/d_meter_haihai.cpp index daf30b9aae..5ea5dad5b7 100644 --- a/src/d/d_meter_haihai.cpp +++ b/src/d/d_meter_haihai.cpp @@ -11,6 +11,7 @@ #include "d/d_com_inf_game.h" #include "d/d_meter_HIO.h" #include "d/d_pane_class.h" +#include "dusk/frame_interpolation.h" dMeterHaihai_c::dMeterHaihai_c(u8 i_type) { mType = i_type; @@ -286,14 +287,19 @@ void dMeterHaihai_c::updateHaihai() { void dMeterHaihai_c::playBckAnime(J2DAnmTransformKey* i_bck) { if (checkPlayAnime(1)) { if (i_bck != NULL) { - if (mType == 4) { - mBckFrame += g_drawHIO.mWiiLockArrowBCKAnimSpeed; - } else { - mBckFrame += g_drawHIO.mScrollArrowBCKAnimSpeed; - } +#ifdef TARGET_PC + if (dusk::frame_interp::get_ui_tick_pending()) +#endif + { + if (mType == 4) { + mBckFrame += g_drawHIO.mWiiLockArrowBCKAnimSpeed; + } else { + mBckFrame += g_drawHIO.mScrollArrowBCKAnimSpeed; + } - if (mBckFrame >= i_bck->getFrameMax()) { - mBckFrame -= i_bck->getFrameMax(); + if (mBckFrame >= i_bck->getFrameMax()) { + mBckFrame -= i_bck->getFrameMax(); + } } } else { mBtkFrame = 1.0f; @@ -309,14 +315,19 @@ void dMeterHaihai_c::playBckAnime(J2DAnmTransformKey* i_bck) { void dMeterHaihai_c::playBtkAnime(J2DAnmTextureSRTKey* i_btk) { if (checkPlayAnime(2)) { if (i_btk != NULL) { - if (mType == 4) { - mBtkFrame += g_drawHIO.mWiiLockArrowBTKAnimSpeed; - } else { - mBtkFrame += g_drawHIO.mScrollArrowBTKAnimSpeed; - } +#ifdef TARGET_PC + if (dusk::frame_interp::get_ui_tick_pending()) +#endif + { + if (mType == 4) { + mBtkFrame += g_drawHIO.mWiiLockArrowBTKAnimSpeed; + } else { + mBtkFrame += g_drawHIO.mScrollArrowBTKAnimSpeed; + } - if (mBtkFrame >= i_btk->getFrameMax()) { - mBtkFrame -= i_btk->getFrameMax(); + if (mBtkFrame >= i_btk->getFrameMax()) { + mBtkFrame -= i_btk->getFrameMax(); + } } } else { mBtkFrame = 1.0f; @@ -331,14 +342,19 @@ void dMeterHaihai_c::playBtkAnime(J2DAnmTextureSRTKey* i_btk) { void dMeterHaihai_c::playBpkAnime(J2DAnmColor* i_bpk) { if (checkPlayAnime(0)) { if (i_bpk != NULL) { - if (mType == 4) { - mBpkFrame += g_drawHIO.mWiiLockArrowBPKAnimSpeed; - } else { - mBpkFrame += g_drawHIO.mScrollArrowBPKAnimSpeed; - } +#ifdef TARGET_PC + if (dusk::frame_interp::get_ui_tick_pending()) +#endif + { + if (mType == 4) { + mBpkFrame += g_drawHIO.mWiiLockArrowBPKAnimSpeed; + } else { + mBpkFrame += g_drawHIO.mScrollArrowBPKAnimSpeed; + } - if (mBpkFrame >= i_bpk->getFrameMax()) { - mBpkFrame -= i_bpk->getFrameMax(); + if (mBpkFrame >= i_bpk->getFrameMax()) { + mBpkFrame -= i_bpk->getFrameMax(); + } } } else { mBpkFrame = 1.0f; diff --git a/src/d/d_meter_string.cpp b/src/d/d_meter_string.cpp index ad95c53edd..c28d6d5481 100644 --- a/src/d/d_meter_string.cpp +++ b/src/d/d_meter_string.cpp @@ -16,6 +16,7 @@ #include "d/d_meter2_info.h" #include "d/d_meter_HIO.h" #include "d/d_pane_class.h" +#include "dusk/frame_interpolation.h" #include dMeterString_c::dMeterString_c(int i_stringID) { @@ -105,16 +106,27 @@ void dMeterString_c::draw() { f32 var_f30 = 1.0f; if (mAnimFrame < 60.0f) { - mAnimFrame += g_drawHIO.mMiniGame.mReadyFightTextAnimSpeed; - if (mAnimFrame > 60.0f) { - mAnimFrame = 60.0f; +#if TARGET_PC + if (dusk::frame_interp::get_ui_tick_pending()) +#endif + { + mAnimFrame += g_drawHIO.mMiniGame.mReadyFightTextAnimSpeed; + if (mAnimFrame > 60.0f) { + mAnimFrame = 60.0f; + } } playBckAnimation(mAnimFrame); } else if (mAnimFrame < (f32)g_drawHIO.mMiniGame.mReadyFightTextWaitFrames + 60.0f) { - mAnimFrame += var_f30; +#if TARGET_PC + if (dusk::frame_interp::get_ui_tick_pending()) +#endif + mAnimFrame += var_f30; } else if (mAnimFrame < var_f31) { - mAnimFrame += var_f30; +#if TARGET_PC + if (dusk::frame_interp::get_ui_tick_pending()) +#endif + mAnimFrame += var_f30; var_f30 = acc(g_drawHIO.mMiniGame.field_0x172, var_f31 - mAnimFrame, 0); } @@ -128,13 +140,21 @@ void dMeterString_c::draw() { if (mPikariAnimFrame > 0.0f) { drawPikari(); } else if (mPikariAnimFrame == -1.0f && +#if TARGET_PC + dusk::frame_interp::get_ui_tick_pending() && +#endif mAnimFrame > g_drawHIO.mMiniGame.mReadyFightPikariAppearFrames) { mPikariAnimFrame = 18.0f - g_drawHIO.mMiniGame.mReadyFightPikariAnimSpeed; } - if (mAnimFrame >= var_f31) { - dMeter2Info_resetMeterString(); +#if TARGET_PC + if (dusk::frame_interp::get_ui_tick_pending()) +#endif + { + if (mAnimFrame >= var_f31) { + dMeter2Info_resetMeterString(); + } } } } diff --git a/src/d/d_msg_class.cpp b/src/d/d_msg_class.cpp index debea084dc..37085a6bb9 100644 --- a/src/d/d_msg_class.cpp +++ b/src/d/d_msg_class.cpp @@ -12,6 +12,10 @@ #include "d/d_lib.h" #include "JSystem/JUtility/JUTFont.h" +#if TARGET_PC +#include "dusk/scope_guard.hpp" +#endif + #if REGION_JPN #define CHAR_CODE_MALE_ICON 0x8189 #define CHAR_CODE_FEMALE_ICON 0x818A @@ -1918,6 +1922,11 @@ void jmessage_tSequenceProcessor::do_begin(void const* pEntry, char const* pszTe pReference->resetReference(); field_0xb5 = 0; +#if TARGET_PC + if (dusk::getSettings().game.instantText && mDoCPd_c::getHoldB(0)) { + field_0xb2 = 1; + } +#endif } void jmessage_tSequenceProcessor::do_end() { @@ -2154,6 +2163,18 @@ void jmessage_tSequenceProcessor::do_character(int iCharacter) { bool jmessage_tSequenceProcessor::do_tag(u32 i_tag, void const* i_data, u32 i_size) { jmessage_tReference* pReference = (jmessage_tReference*)getReference(); +#if TARGET_PC + // This class runs the lambda function when it goes out of scope. We want to run + // this code after the switch statement and this saves us from having to litter + // the switch statement with IF_DUSK before every return. + auto instantTextRun = SimpleScopeGuard([&]() { + if (dusk::getSettings().game.instantText && mDoCPd_c::getHoldB(0)) { + field_0xb2 = 1; + pReference->setSendTimer(0); + } + }); +#endif + switch (i_tag & 0xFF0000) { case MSGTAG_GROUP(1): { cXyz pos = pReference->getActorPos(); diff --git a/src/d/d_msg_object.cpp b/src/d/d_msg_object.cpp index 3676639908..9b7b64ebda 100644 --- a/src/d/d_msg_object.cpp +++ b/src/d/d_msg_object.cpp @@ -28,6 +28,10 @@ #include "m_Do/m_Do_lib.h" #include "JSystem/JKernel/JKRExpHeap.h" +#if TARGET_PC +#include "dusk/settings.h" +#endif + static void dMsgObject_addFundRaising(s16 param_0); static void dMsgObject_addTotalPayment(s16 param_0); @@ -1464,24 +1468,12 @@ 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) { @@ -1566,7 +1558,8 @@ u8 dMsgObject_c::isSend() { if (pRef->getSendFlag() == 5) { if (getStatusLocal() == 21) { setButtonStatusLocal(); - if (mDoCPd_c::getTrigA(0) != 0 || mDoCPd_c::getTrigB(0) != 0) { + if (IF_DUSK((dusk::getSettings().game.instantText && mDoCPd_c::getHoldB(0)) ||) + mDoCPd_c::getTrigA(0) != 0 || mDoCPd_c::getTrigB(0) != 0) { return 2; } return 0; @@ -1585,7 +1578,8 @@ u8 dMsgObject_c::isSend() { } if (pRef->getSendFlag() == 2) { setButtonStatusLocal(); - if (mDoCPd_c::getTrigA(0) != 0 || mDoCPd_c::getTrigB(0) != 0) { + if (IF_DUSK((dusk::getSettings().game.instantText && mDoCPd_c::getHoldB(0)) ||) + mDoCPd_c::getTrigA(0) != 0 || mDoCPd_c::getTrigB(0) != 0) { return 2; } } @@ -1598,7 +1592,8 @@ u8 dMsgObject_c::isSend() { return 2; } } else { - if (mDoCPd_c::getTrigA(0) != 0 || mDoCPd_c::getTrigB(0) != 0) { + if (IF_DUSK((dusk::getSettings().game.instantText && mDoCPd_c::getHoldB(0)) ||) + mDoCPd_c::getTrigA(0) != 0 || mDoCPd_c::getTrigB(0) != 0) { return 2; } if (mesgCancelButton) { diff --git a/src/d/d_msg_out_font.cpp b/src/d/d_msg_out_font.cpp index 4d15b069d3..efc655d529 100644 --- a/src/d/d_msg_out_font.cpp +++ b/src/d/d_msg_out_font.cpp @@ -5,6 +5,7 @@ #include "JSystem/JUtility/JUTTexture.h" #include "d/d_meter2_info.h" #include "d/d_msg_object.h" +#include "dusk/frame_interpolation.h" #include "f_op/f_op_msg_mng.h" COutFontSet_c::COutFontSet_c() { @@ -311,6 +312,15 @@ void COutFont_c::draw(J2DTextBox* i_textbox, f32 param_1, f32 param_2, f32 param sp256[i] = field_0x1b4[i]; } +#ifdef TARGET_PC + bool uiTickPending = dusk::frame_interp::get_ui_tick_pending(); + if (!uiTickPending) { + for (int i = 0; i < 70; i++) { + sp256[i] = -1; + } + } +#endif + for (int i = 0; i < 35; i++) { u8 type = mpOfs[i]->getType(); J2DTextBox* tbox = mpOfs[i]->getTextBoxPtr(); @@ -505,9 +515,14 @@ void COutFont_c::draw(J2DTextBox* i_textbox, f32 param_1, f32 param_2, f32 param case 20: case 21: case 22: - field_0x1b4[type]++; - if (field_0x1b4[type] >= 28) { - field_0x1b4[type] = 0; +#ifdef TARGET_PC + if (uiTickPending) +#endif + { + field_0x1b4[type]++; + if (field_0x1b4[type] >= 28) { + field_0x1b4[type] = 0; + } } mpPane[type]->rotate(0.5f * sizeX, 0.5f * sizeY, ROTATE_Z, diff --git a/src/d/d_msg_scrn_howl.cpp b/src/d/d_msg_scrn_howl.cpp index 03729377a5..1d39cba1a1 100644 --- a/src/d/d_msg_scrn_howl.cpp +++ b/src/d/d_msg_scrn_howl.cpp @@ -607,17 +607,10 @@ void dMsgScrnHowl_c::drawGuide() { J2DGrafContext* grafContext = dComIfGp_getCurrentGrafPort(); Vec local_b0 = field_0x128; Vec local_bc = field_0x140; -#if TARGET_PC - grafContext->scissor( - (local_b0.x - mDoGph_gInf_c::getMinXF()) / (mDoGph_gInf_c::getWidthF() / mDoGph_gInf_c::getWidth()), - field_0x2118, (local_bc.x - local_b0.x) / (mDoGph_gInf_c::getWidthF() / mDoGph_gInf_c::getWidth()), - field_0x2120); -#else grafContext->scissor( (local_b0.x - mDoGph_gInf_c::getMinXF()) / (mDoGph_gInf_c::getWidthF() / FB_WIDTH), field_0x2118, (local_bc.x - local_b0.x) / (mDoGph_gInf_c::getWidthF() / FB_WIDTH), field_0x2120); -#endif grafContext->setScissor(); f32 local_cc = mpLineH[0]->getGlobalPosX(); s16 sVar12 = 0; @@ -745,19 +738,11 @@ void dMsgScrnHowl_c::drawGuide2() { } Vec local_58 = field_0x128; Vec local_64 = field_0x140; -#if TARGET_PC - f32 local_70 = mDoGph_gInf_c::getHeightF() / mDoGph_gInf_c::getHeight(); - grafContext->scissor( - (local_58.x - mDoGph_gInf_c::getMinXF()) / (mDoGph_gInf_c::getWidthF() / mDoGph_gInf_c::getWidth()), - field_0x2118, (local_64.x - local_58.x) / (mDoGph_gInf_c::getWidthF() / mDoGph_gInf_c::getWidth()), - field_0x2120); -#else f32 local_70 = mDoGph_gInf_c::getHeightF() / mDoGph_gInf_c::getHeight(); grafContext->scissor( (local_58.x - mDoGph_gInf_c::getMinXF()) / (mDoGph_gInf_c::getWidthF() / FB_WIDTH), field_0x2118, (local_64.x - local_58.x) / (mDoGph_gInf_c::getWidthF() / FB_WIDTH), field_0x2120); -#endif grafContext->setScissor(); f32 local_74 = mpLineH[0]->getGlobalPosX(); s16 local_134 = 0; @@ -859,15 +844,9 @@ void dMsgScrnHowl_c::drawEffect() { Vec vec1 = field_0x128; Vec vec2 = field_0x140; mDoGph_gInf_c::getHeightF(); -#if TARGET_PC - grafContext->scissor( - (vec1.x - mDoGph_gInf_c::getMinXF()) / (mDoGph_gInf_c::getWidthF() / mDoGph_gInf_c::getWidth()), field_0x2118, - 12.0f + ((vec2.x - vec1.x) / (mDoGph_gInf_c::getWidthF() / mDoGph_gInf_c::getWidth())), field_0x2120); -#else grafContext->scissor( (vec1.x - mDoGph_gInf_c::getMinXF()) / (mDoGph_gInf_c::getWidthF() / FB_WIDTH), field_0x2118, 12.0f + ((vec2.x - vec1.x) / (mDoGph_gInf_c::getWidthF() / FB_WIDTH)), field_0x2120); -#endif grafContext->setScissor(); u8 timer = daAlink_getAlinkActorClass()->getWolfHowlMgrP()->getReleaseTimer(); u8 screenAlpha = mpScreen->search(MULTI_CHAR('line00'))->getAlpha(); diff --git a/src/d/d_msg_scrn_item.cpp b/src/d/d_msg_scrn_item.cpp index 53ef97607c..672700682d 100644 --- a/src/d/d_msg_scrn_item.cpp +++ b/src/d/d_msg_scrn_item.cpp @@ -557,22 +557,11 @@ 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_light.cpp b/src/d/d_msg_scrn_light.cpp index c34397aad2..19671b5d57 100644 --- a/src/d/d_msg_scrn_light.cpp +++ b/src/d/d_msg_scrn_light.cpp @@ -204,16 +204,14 @@ void dMsgScrnLight_c::draw(f32* i_anmFrame, f32 i_posX, f32 i_posY, f32 i_scaleX if (mPlayAnim) { #ifdef TARGET_PC - const u32 ui_advance_ticks = dusk::frame_interp::get_presentation_ui_advance_ticks(); - for (u32 i = 0; i < ui_advance_ticks; ++i) { + if (dusk::frame_interp::get_ui_tick_pending()) #endif + { *i_anmFrame += 1.0f; if (*i_anmFrame >= mpBck->getFrameMax()) { *i_anmFrame = 0.0f; } -#ifdef TARGET_PC } -#endif mBckFrame = *i_anmFrame; mBpkFrame = *i_anmFrame; @@ -229,17 +227,15 @@ void dMsgScrnLight_c::draw(f32* i_anmFrame, f32 i_posX, f32 i_posY, f32 i_scaleX if (mPlayAnim) { #ifdef TARGET_PC - const u32 ui_advance_ticks = dusk::frame_interp::get_presentation_ui_advance_ticks(); - for (u32 i = 0; i < ui_advance_ticks; ++i) { + if (dusk::frame_interp::get_ui_tick_pending()) #endif + { *i_anmFrame += i_anmRate; if (*i_anmFrame >= mpBck->getFrameMax()) { *i_anmFrame = 0.0f; } -#ifdef TARGET_PC } -#endif mBckFrame = *i_anmFrame; mBpkFrame = *i_anmFrame; diff --git a/src/d/d_msg_scrn_talk.cpp b/src/d/d_msg_scrn_talk.cpp index 68b471a14d..c9f925e784 100644 --- a/src/d/d_msg_scrn_talk.cpp +++ b/src/d/d_msg_scrn_talk.cpp @@ -441,22 +441,11 @@ 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 { - #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 <= FB_WIDTH_BASE && local_70.y >= 0.0f && local_70.y <= FB_HEIGHT_BASE) { diff --git a/src/d/d_msg_unit.cpp b/src/d/d_msg_unit.cpp index 98dd33b4a8..f773abd373 100644 --- a/src/d/d_msg_unit.cpp +++ b/src/d/d_msg_unit.cpp @@ -271,6 +271,30 @@ void dMsgUnit_c::setTag(int i_type, int i_value, char* o_buffer, bool param_4) { u32 filesize = pHeader->size; u8* pSection = ((u8*)pHeader) + filepos; + #if TARGET_PC + // patch bug in the original game where filepos would be incremented by the next section's size rather than the current section size. + // in certain scenarios this would read past the end of the file, incrementing filepos by 0 in an infinite loop + while (filepos < filesize) { + switch (((bmg_section_t*)pSection)->magic) { + case 'FLW1': + break; + case 'FLI1': + break; + case 'INF1': + pInfoBlock = (bmg_section_t*)pSection; + break; + case 'DAT1': + pMsgDataBlock = pSection; + break; + case 'STR1': + pStrAttributeBlock = (str1_section_t*)pSection; + break; + } + + filepos += ((bmg_section_t*)pSection)->size; + pSection += ((bmg_section_t*)pSection)->size; + } + #else for (; filepos < filesize; filepos += ((bmg_section_t*)pSection)->size) { switch (((bmg_section_t*)pSection)->magic) { case 'FLW1': @@ -289,6 +313,7 @@ void dMsgUnit_c::setTag(int i_type, int i_value, char* o_buffer, bool param_4) { } pSection += ((bmg_section_t*)pSection)->size; } + #endif // This section is weird. The debug seems like entriesStr is outside the condition // but the normal build doesn't really work with that. Same for pInfoBlock->entries. diff --git a/src/d/d_name.cpp b/src/d/d_name.cpp index 120bcff752..e4232eff34 100644 --- a/src/d/d_name.cpp +++ b/src/d/d_name.cpp @@ -1288,7 +1288,11 @@ 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); + #if TARGET_PC + if (mSelIcon) { + mSelIcon->refreshAspectScale(); + } + #endif // List of Characters Box static u64 l_tagName[65] = { @@ -1540,11 +1544,7 @@ 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_fade.cpp b/src/d/d_ovlp_fade.cpp index 1ae49ab74a..43732cf4be 100644 --- a/src/d/d_ovlp_fade.cpp +++ b/src/d/d_ovlp_fade.cpp @@ -26,8 +26,8 @@ static void dOvlpFd_startFadeIn(int param_0) { JUTFader* fader = JFWDisplay::getManager()->getFader(); JUT_ASSERT(0, fader != NULL); - fader->setStatus(JUTFader::UNKSTATUS_0, 0); - fader->setStatus(JUTFader::UNKSTATUS_0, -1); + fader->setStatus(JUTFader::None, 0); + fader->setStatus(JUTFader::None, -1); fader->startFadeIn(param_0); } diff --git a/src/d/d_ovlp_fade2.cpp b/src/d/d_ovlp_fade2.cpp index 37dbeedba2..c6c6cc735e 100644 --- a/src/d/d_ovlp_fade2.cpp +++ b/src/d/d_ovlp_fade2.cpp @@ -12,13 +12,8 @@ #include "m_Do/m_Do_graphic.h" void dOvlpFd2_dlst_c::draw() { -#if TARGET_PC - GXSetViewport(0.0f, 0.0f, mDoGph_gInf_c::getWidth(), mDoGph_gInf_c::getHeight(), 0.0f, 1.0f); - GXSetScissor(0, 0, mDoGph_gInf_c::getWidth(), mDoGph_gInf_c::getHeight()); -#else GXSetViewport(0.0f, 0.0f, FB_WIDTH, FB_HEIGHT, 0.0f, 1.0f); GXSetScissor(0, 0, FB_WIDTH, FB_HEIGHT); -#endif GXSetVtxAttrFmt(GX_VTXFMT0, GX_VA_POS, GX_CLR_RGB, GX_RGBA4, 0); GXClearVtxDesc(); GXSetVtxDesc(GX_VA_POS, GX_DIRECT); diff --git a/src/d/d_ovlp_fade3.cpp b/src/d/d_ovlp_fade3.cpp index d6f432f3ee..0b3c03db2b 100644 --- a/src/d/d_ovlp_fade3.cpp +++ b/src/d/d_ovlp_fade3.cpp @@ -13,11 +13,10 @@ #include "m_Do/m_Do_graphic.h" void dDlst_snapShot_c::draw() { -#if TARGET_PC - GXSetTexCopySrc(0, 0, mDoGph_gInf_c::getWidth(), mDoGph_gInf_c::getHeight()); - GXSetTexCopyDst(mDoGph_gInf_c::getWidth(), mDoGph_gInf_c::getHeight(), GX_TF_RGBA8, GX_TRUE); -#else GXSetTexCopySrc(0, 0, FB_WIDTH, FB_HEIGHT); +#if TARGET_PC + GXSetTexCopyDst(FB_WIDTH, FB_HEIGHT, GX_TF_RGBA8, GX_FALSE); +#else GXSetTexCopyDst(FB_WIDTH / 2, FB_HEIGHT / 2, GX_TF_RGBA8, GX_TRUE); #endif GXCopyTex(mDoGph_gInf_c::getFrameBufferTex(), GX_FALSE); @@ -25,13 +24,8 @@ void dDlst_snapShot_c::draw() { } void dOvlpFd3_dlst_c::draw() { -#if TARGET_PC - GXSetViewport(0.0f, 0.0f, mDoGph_gInf_c::getWidth(), mDoGph_gInf_c::getHeight(), 0.0f, 1.0f); - GXSetScissor(0, 0, mDoGph_gInf_c::getWidth(), mDoGph_gInf_c::getHeight()); -#else GXSetViewport(0.0f, 0.0f, FB_WIDTH, FB_HEIGHT, 0.0f, 1.0f); GXSetScissor(0, 0, FB_WIDTH, FB_HEIGHT); -#endif GXSetVtxAttrFmt(GX_VTXFMT0, GX_VA_POS, GX_CLR_RGB, GX_RGBA4, 0); GXClearVtxDesc(); GXSetVtxDesc(GX_VA_POS, GX_DIRECT); @@ -112,19 +106,6 @@ void dOvlpFd3_dlst_c::draw() { GXBegin(GX_QUADS, GX_VTXFMT0, 4); - #if TARGET_PC - GXPosition2s16(-FB_WIDTH / 2, FB_HEIGHT / 2); - GXTexCoord2s8(0, 0); - - GXPosition2s16(FB_WIDTH / 2, FB_HEIGHT / 2); - GXTexCoord2s8(1, 0); - - GXPosition2s16(FB_WIDTH / 2, -FB_HEIGHT / 2); - GXTexCoord2s8(1, 1); - - GXPosition2s16(-FB_WIDTH / 2, -FB_HEIGHT / 2); - GXTexCoord2s8(0, 1); - #else GXPosition2s16(-mDoGph_gInf_c::getWidth() / 2, mDoGph_gInf_c::getHeight() / 2); GXTexCoord2s8(0, 0); @@ -136,7 +117,6 @@ void dOvlpFd3_dlst_c::draw() { GXPosition2s16(-mDoGph_gInf_c::getWidth() / 2, -mDoGph_gInf_c::getHeight() / 2); GXTexCoord2s8(0, 1); - #endif GXEnd(); diff --git a/src/d/d_pane_class.cpp b/src/d/d_pane_class.cpp index 78855b2d1c..4d5104ffcf 100644 --- a/src/d/d_pane_class.cpp +++ b/src/d/d_pane_class.cpp @@ -356,12 +356,8 @@ Vec CPaneMgr::getGlobalVtx(J2DPane* p_pane, Mtx* param_1, u8 param_2, bool param Mtx m; MtxP mp = (MtxP)param_1; J2DPane* parent = p_pane->getParentPane(); - -#if TARGET_PC - J2DOrthoGraph ortho(0.0f, 0.0f, mDoGph_gInf_c::getWidth(), mDoGph_gInf_c::getHeight(), -1.0f, 1.0f); -#else + J2DOrthoGraph ortho(0.0f, 0.0f, FB_WIDTH, FB_HEIGHT, -1.0f, 1.0f); -#endif ortho.setOrtho(mDoGph_gInf_c::getMinXF(), mDoGph_gInf_c::getMinYF(), mDoGph_gInf_c::getWidthF(), mDoGph_gInf_c::getHeightF(), -1.0f, 1.0f); if (parent != NULL) { diff --git a/src/d/d_resorce.cpp b/src/d/d_resorce.cpp index 0bf537bfd7..73f031beae 100644 --- a/src/d/d_resorce.cpp +++ b/src/d/d_resorce.cpp @@ -296,7 +296,11 @@ J3DModelData* dRes_info_c::loaderBasicBmd(u32 i_tag, void* i_data) { addWarpMaterial(modelData); } - if (i_tag == 'BMDR' || i_tag == 'BMWR') { + // FRAME INTERP NOTE: Always create shared DL buffers so we can use J3DMaterial::diff() +#ifndef TARGET_PC + if (i_tag == 'BMDR' || i_tag == 'BMWR') +#endif + { s32 result = modelData->newSharedDisplayList(J3DMdlFlag_UseSingleDL); if (result != kJ3DError_Success) { return NULL; diff --git a/src/d/d_s_play.cpp b/src/d/d_s_play.cpp index 9af875b2f5..19c7d37c6d 100644 --- a/src/d/d_s_play.cpp +++ b/src/d/d_s_play.cpp @@ -1429,12 +1429,7 @@ static int phase_4(dScnPly_c* i_this) { dComIfGp_setPlayerPtr(i, NULL); } -#if TARGET_PC - dComIfGp_setWindow(0, 0.0f, 0.0f, mDoGph_gInf_c::getWidth(), mDoGph_gInf_c::getHeight(), 0.0f, - 1.0f, 0, 2); -#else dComIfGp_setWindow(0, 0.0f, 0.0f, FB_WIDTH, FB_HEIGHT, 0.0f, 1.0f, 0, 2); -#endif dComIfGp_setCameraInfo(0, NULL, 0, 0, -1); dComIfGd_setWindow(NULL); dComIfGd_setViewport(NULL); diff --git a/src/d/d_save.cpp b/src/d/d_save.cpp index c872cb0f17..71f65b61e6 100644 --- a/src/d/d_save.cpp +++ b/src/d/d_save.cpp @@ -1482,9 +1482,6 @@ void dSv_restart_c::setRoom(const cXyz& i_position, s16 i_angleY, s8 i_roomNo) { mRoomNo = i_roomNo; mRoomPos = i_position; mRoomAngleY = i_angleY; - #if TARGET_PC - triggerAutoSave(); - #endif } void dSv_turnRestart_c::set(const cXyz& i_position, s16 i_angleY, s8 param_3, u32 i_param) { diff --git a/src/d/d_select_cursor.cpp b/src/d/d_select_cursor.cpp index 2cdd454737..0773433b4d 100644 --- a/src/d/d_select_cursor.cpp +++ b/src/d/d_select_cursor.cpp @@ -69,6 +69,9 @@ dSelect_cursor_c::dSelect_cursor_c(u8 param_0, f32 param_1, JKRArchive* param_2) field_0x84[i] = 0.0f; } mParam1 = mpCursorHIO->mXAxisExpansion; +#ifdef TARGET_PC + mBaseParam1 = mParam1; +#endif mParam2 = mpCursorHIO->mYAxisExpansion; mParam3 = mpCursorHIO->mOscillation; mParam4 = mpCursorHIO->mRatioX; @@ -259,6 +262,13 @@ void dSelect_cursor_c::update() { if (field_0xb6 == 3) { fVar1 = 0.5f; } +#ifdef TARGET_PC + if (mpPane) { + Vec pos = mpPaneMgr->getGlobalVtxCenter(mpPane, false, 0); + mPositionX = pos.x; + mPositionY = pos.y; + } +#endif mpPaneMgr->translate(mPositionX, mPositionY); if (mpCursorHIO->mDebugON) { mParam1 = mpCursorHIO->mXAxisExpansion; @@ -272,9 +282,9 @@ void dSelect_cursor_c::update() { if (field_0x30) { if (chkPlayAnime(0)) { #ifdef TARGET_PC - const u32 ui_advance_ticks = dusk::frame_interp::get_presentation_ui_advance_ticks(); - for (u32 tick = 0; tick < ui_advance_ticks; ++tick) { + if (dusk::frame_interp::get_ui_tick_pending()) #endif + { if (mNameIdx == 1) { field_0x44 += mpCursorHIO->field_0x8 * fVar1; } else { @@ -284,9 +294,7 @@ void dSelect_cursor_c::update() { if (field_0x44 >= field_0x30->getFrameMax()) { field_0x44 -= field_0x30->getFrameMax(); } -#ifdef TARGET_PC } -#endif field_0x30->setFrame(field_0x44); setBpkAnimation(field_0x30); @@ -303,9 +311,9 @@ void dSelect_cursor_c::update() { if (field_0x34[i]) { if ((i == 0 && chkPlayAnime(2)) || (i == 1 && chkPlayAnime(3))) { #ifdef TARGET_PC - const u32 ui_advance_ticks = dusk::frame_interp::get_presentation_ui_advance_ticks(); - for (u32 tick = 0; tick < ui_advance_ticks; ++tick) { + if (dusk::frame_interp::get_ui_tick_pending()) #endif + { if (mNameIdx == 1) { field_0x48[i] += mpCursorHIO->field_0x8 * fVar1; } else { @@ -314,9 +322,7 @@ void dSelect_cursor_c::update() { if (field_0x48[i] >= field_0x34[i]->getFrameMax()) { field_0x48[i] -= field_0x34[i]->getFrameMax(); } -#ifdef TARGET_PC } -#endif field_0x34[i]->setFrame(field_0x48[i]); } @@ -326,9 +332,9 @@ void dSelect_cursor_c::update() { if (field_0x2C && chkPlayAnime(1)) { #ifdef TARGET_PC - const u32 ui_advance_ticks = dusk::frame_interp::get_presentation_ui_advance_ticks(); - for (u32 tick = 0; tick < ui_advance_ticks; ++tick) { + if (dusk::frame_interp::get_ui_tick_pending()) #endif + { if (mNameIdx == 1) { field_0x40 += mpCursorHIO->field_0x8 * fVar1; } else { @@ -337,9 +343,7 @@ void dSelect_cursor_c::update() { if (field_0x40 >= field_0x2C->getFrameMax()) { field_0x40 -= field_0x2C->getFrameMax(); } -#ifdef TARGET_PC } -#endif field_0x2C->setFrame(field_0x40); setBckAnimation(field_0x2C); @@ -348,13 +352,11 @@ void dSelect_cursor_c::update() { if (chkPlayAnime(1) && mNameIdx == 0) { #ifdef TARGET_PC - const u32 ui_advance_ticks = dusk::frame_interp::get_presentation_ui_advance_ticks(); - for (u32 tick = 0; tick < ui_advance_ticks; ++tick) { + if (dusk::frame_interp::get_ui_tick_pending()) #endif + { setCursorAnimation(); -#ifdef TARGET_PC } -#endif } mpScreen->animation(); @@ -412,6 +414,9 @@ void dSelect_cursor_c::setPos(f32 i_posX, f32 i_posY, J2DPane* i_pane, bool i_sc void dSelect_cursor_c::setParam(f32 i_param1, f32 i_param2, f32 i_param3, f32 i_param4, f32 i_param5) { mParam1 = i_param1; +#ifdef TARGET_PC + mBaseParam1 = i_param1; +#endif mParam2 = i_param2; mParam3 = i_param3; mParam4 = i_param4; @@ -570,3 +575,9 @@ void dSelect_cursor_c::setBckAnimation(J2DAnmTransformKey* param_0) { void dSelect_cursor_c::moveCenter(J2DPane* i_pane, f32 i_x, f32 i_y) { i_pane->translate(i_x,i_y); } + +#ifdef TARGET_PC +void dSelect_cursor_c::refreshAspectScale() { + mParam1 = mBaseParam1 * mDoGph_gInf_c::hudAspectScaleUp; +} +#endif diff --git a/src/d/d_select_icon.cpp b/src/d/d_select_icon.cpp index 3a4671fefa..32be9c15e2 100644 --- a/src/d/d_select_icon.cpp +++ b/src/d/d_select_icon.cpp @@ -9,9 +9,9 @@ dSi_HIO_c::dSi_HIO_c() {} void dSelect_icon_c::animation() { if (field_0x10->getAlpha() != 0) { #ifdef TARGET_PC - const u32 ui_advance_ticks = dusk::frame_interp::get_presentation_ui_advance_ticks(); - for (u32 i = 0; i < ui_advance_ticks; ++i) { + if (dusk::frame_interp::get_ui_tick_pending()) #endif + { field_0x20 += field_0x2c; if (field_0x20 >= field_0x1c->getFrameMax()) { field_0x20 = 0.0f; @@ -22,9 +22,9 @@ void dSelect_icon_c::animation() { if (field_0x28 >= field_0x24->getFrameMax()) { field_0x28 = 0.0f; } -#ifdef TARGET_PC } - // Set even if not advancing +#ifdef TARGET_PC + // FRAME INTERP NOTE: Set even if not advancing field_0x1c->setFrame(field_0x20); #endif diff --git a/src/d/d_shop_system.cpp b/src/d/d_shop_system.cpp index f1636bb093..5871d65d2a 100644 --- a/src/d/d_shop_system.cpp +++ b/src/d/d_shop_system.cpp @@ -855,11 +855,7 @@ int dShopSystem_c::seq_wait(fopAc_ac_c* param_0, dMsgFlow_c* param_1) { } inline void pos3Dto2D(Vec* a, Vec* b) { -#if TARGET_PC - mDoLib_project(a, b, {0, 0, FB_WIDTH, FB_HEIGHT}); -#else mDoLib_project(a, b); -#endif } int dShopSystem_c::seq_start(fopAc_ac_c* actor, dMsgFlow_c* i_flow) { @@ -1572,10 +1568,22 @@ BOOL dShopSystem_c::checkShopOpen() { } bool dShopSystem_c::checkLeftTrigger(STControl* i_stick) { +#if TARGET_PC + if (dusk::getSettings().game.enableMirrorMode) { + return i_stick->checkRightTrigger(); + } +#endif + return i_stick->checkLeftTrigger(); } bool dShopSystem_c::checkRightTrigger(STControl* i_stick) { +#if TARGET_PC + if (dusk::getSettings().game.enableMirrorMode) { + return i_stick->checkLeftTrigger(); + } +#endif + return i_stick->checkRightTrigger(); } diff --git a/src/d/d_timer.cpp b/src/d/d_timer.cpp index 552874b552..cb40e3444a 100644 --- a/src/d/d_timer.cpp +++ b/src/d/d_timer.cpp @@ -23,9 +23,7 @@ #include "m_Do/m_Do_lib.h" #include -#if TARGET_PC #include "dusk/frame_interpolation.h" -#endif static int dTimer_createStart2D(s32 param_0, u16 param_1); @@ -1340,27 +1338,22 @@ void dDlst_TimerScrnDraw_c::draw() { f32 temp = (f32)g_drawHIO.mMiniGame.mGetInTextAlphaFrames + ((f32)g_drawHIO.mMiniGame.mGetInTextWaitFrames + 60.0f); -#if TARGET_PC - const u32 pending_ui_ticks = dusk::frame_interp::get_presentation_ui_advance_ticks(); -#else - const u32 pending_ui_ticks = 1u; -#endif - for (int i = 0; i < 51; i++) { - for (u32 tick = 0; tick < pending_ui_ticks; tick++) { - if (!(m_getin_info[i].bck_frame > 0.0f && m_getin_info[i].bck_frame < temp)) { - break; - } - - if (m_getin_info[i].bck_frame < 60.0f) { - m_getin_info[i].bck_frame += g_drawHIO.mMiniGame.mGetInTextAnimSpeed; - if (m_getin_info[i].bck_frame > 60.0f) { - m_getin_info[i].bck_frame = 60.0f; +#if TARGET_PC + if (dusk::frame_interp::get_ui_tick_pending()) +#endif + { + if (m_getin_info[i].bck_frame > 0.0f && m_getin_info[i].bck_frame < temp) { + if (m_getin_info[i].bck_frame < 60.0f) { + m_getin_info[i].bck_frame += g_drawHIO.mMiniGame.mGetInTextAnimSpeed; + if (m_getin_info[i].bck_frame > 60.0f) { + m_getin_info[i].bck_frame = 60.0f; + } + } else if (m_getin_info[i].bck_frame < g_drawHIO.mMiniGame.mGetInTextWaitFrames + 60.0f) { + m_getin_info[i].bck_frame++; + } else if (m_getin_info[i].bck_frame < temp) { + m_getin_info[i].bck_frame++; } - } else if (m_getin_info[i].bck_frame < g_drawHIO.mMiniGame.mGetInTextWaitFrames + 60.0f) { - m_getin_info[i].bck_frame++; - } else if (m_getin_info[i].bck_frame < temp) { - m_getin_info[i].bck_frame++; } } @@ -1369,7 +1362,7 @@ void dDlst_TimerScrnDraw_c::draw() { if (m_getin_info[i].bck_frame >= g_drawHIO.mMiniGame.mGetInTextWaitFrames + 60.0f && m_getin_info[i].bck_frame < temp) { var_f29 = acc(g_drawHIO.mMiniGame.mGetInTextAlphaFrames, - temp - m_getin_info[i].bck_frame, 0); + temp - m_getin_info[i].bck_frame, 0); } if (m_getin_info[i].bck_frame < 60.0f) { @@ -1382,7 +1375,7 @@ void dDlst_TimerScrnDraw_c::draw() { if (g_drawHIO.mMiniGame.mGetInTextLocation == 1) { mpGetInRoot->translate(m_getin_info[i].pos_x + g_drawHIO.mMiniGame.mGetInTextPosX, - m_getin_info[i].pos_y + g_drawHIO.mMiniGame.mGetInTextPosY); + m_getin_info[i].pos_y + g_drawHIO.mMiniGame.mGetInTextPosY); } else { f32 temp_f2 = m_getin_info[i].bck_frame - 40.0f; f32 var_f3 = ((temp_f2 * 0.5f) * temp_f2) * 0.15f; @@ -1396,20 +1389,25 @@ void dDlst_TimerScrnDraw_c::draw() { } mpGetInRoot->scale(g_drawHIO.mMiniGame.mGetInTextSizeX, - g_drawHIO.mMiniGame.mGetInTextSizeY); + g_drawHIO.mMiniGame.mGetInTextSizeY); mpGetInScreen->draw(0.0f, 0.0f, graf_ctx); if (m_getin_info[i].pikari_frame > 0.0f) { drawPikari(i); } else if (m_getin_info[i].pikari_frame == -1.0f) { - if (m_getin_info[i].field_0xc == 0) { - if (m_getin_info[i].bck_frame > g_drawHIO.mMiniGame.mGetInPikariAppearFrames) { +#if TARGET_PC + if (dusk::frame_interp::get_ui_tick_pending()) +#endif + { + if (m_getin_info[i].field_0xc == 0) { + if (m_getin_info[i].bck_frame > g_drawHIO.mMiniGame.mGetInPikariAppearFrames) { + m_getin_info[i].pikari_frame = + 18.0f - g_drawHIO.mMiniGame.mGetInPikariAnimSpeed; + } + } else if (m_getin_info[i].bck_frame > g_drawHIO.mMiniGame.mStartPikariAppearFrames) { m_getin_info[i].pikari_frame = - 18.0f - g_drawHIO.mMiniGame.mGetInPikariAnimSpeed; + 18.0f - g_drawHIO.mMiniGame.mStartPikariAnimSpeed; } - } else if (m_getin_info[i].bck_frame > g_drawHIO.mMiniGame.mStartPikariAppearFrames) { - m_getin_info[i].pikari_frame = - 18.0f - g_drawHIO.mMiniGame.mStartPikariAnimSpeed; } } } diff --git a/src/dusk/audio/DuskAudioSystem.cpp b/src/dusk/audio/DuskAudioSystem.cpp index c818e46738..3577d3c9c7 100644 --- a/src/dusk/audio/DuskAudioSystem.cpp +++ b/src/dusk/audio/DuskAudioSystem.cpp @@ -77,6 +77,14 @@ void dusk::audio::SetMasterVolume(const f32 value) { MasterVolume = value; } +void dusk::audio::SetPaused(const bool paused) { + if (paused) { + SDL_PauseAudioStreamDevice(PlaybackStream); + } else { + SDL_ResumeAudioStreamDevice(PlaybackStream); + } +} + void dusk::audio::SetEnableReverb(const bool value) { JASCriticalSection section; diff --git a/src/dusk/discord_presence.cpp b/src/dusk/discord_presence.cpp new file mode 100644 index 0000000000..3b12075c8b --- /dev/null +++ b/src/dusk/discord_presence.cpp @@ -0,0 +1,122 @@ +#ifdef DUSK_DISCORD_RPC + +#include "dusk/discord_presence.hpp" +#include "dusk/logging.h" +#include "dusk/main.h" +#include "dusk/map_loader_definitions.h" +#include "d/d_com_inf_game.h" +#include "discord_rpc.h" +#include "fmt/format.h" + +#include +#include +#include + +namespace dusk { +namespace discord { + +static int64_t g_startTime = 0; +static bool g_initialized = false; +static const char* APPLICATION_ID = "1495632471994405035"; + +static void OnReady(const DiscordUser* user) { + DuskLog.info("Discord: Connected as {}", user->username); +} + +static void OnDisconnected(int errorCode, const char* message) { + DuskLog.warn("Discord: Disconnected ({}: {})", errorCode, message); +} + +static void OnError(int errorCode, const char* message) { + DuskLog.warn("Discord: Error ({}: {})", errorCode, message); +} + +static const char* LookupMapName(const char* mapFile) { + if (!mapFile || mapFile[0] == '\0') return nullptr; + for (const auto& region : gameRegions) { + for (const auto& map : region.maps) { + if (map.mapFile && strcmp(mapFile, map.mapFile) == 0) { + return map.mapName; + } + } + } + return nullptr; +} + +void Initialize() { + g_startTime = static_cast( + std::chrono::duration_cast( + std::chrono::system_clock::now().time_since_epoch() + ).count() + ); + + DiscordEventHandlers handlers{}; + handlers.ready = OnReady; + handlers.disconnected = OnDisconnected; + handlers.errored = OnError; + Discord_Initialize(APPLICATION_ID, &handlers, 0, nullptr); + g_initialized = true; + + DuskLog.info("Discord Rich Presence initialized"); +} + +void RunCallbacks() { + if (!g_initialized) return; + Discord_RunCallbacks(); +} + +void UpdatePresence() { + if (!g_initialized) return; + + static auto lastUpdate = std::chrono::steady_clock::time_point{}; + const auto now = std::chrono::steady_clock::now(); + if (now - lastUpdate < std::chrono::seconds(15)) return; + lastUpdate = now; + + static std::string detailsBuf; + static std::string stateBuf; + + DiscordRichPresence presence{}; + presence.startTimestamp = g_startTime; + presence.largeImageKey = "icon"; + presence.largeImageText = "Dusk"; + + if (dusk::IsGameLaunched) { + const char* stageName = dComIfGp_getLastPlayStageName(); + + // stageName is empty until a room is actually entered + if (stageName[0] != '\0') { + const char* locationName = LookupMapName(stageName); + + if (locationName) { + detailsBuf = locationName; + } + else { + detailsBuf = "Twilight Princess"; + } + + presence.details = detailsBuf.c_str(); + + stateBuf = fmt::format(FMT_STRING("{}/{} \u2665 | {} Rupees"), + dComIfGs_getLife() / 4, dComIfGs_getMaxLife() / 5, dComIfGs_getRupee()); + + presence.state = stateBuf.c_str(); + } + } + + Discord_UpdatePresence(&presence); + DuskLog.debug("Discord Rich Presence sent"); +} + +void Shutdown() { + if (!g_initialized) return; + Discord_ClearPresence(); + Discord_Shutdown(); + g_initialized = false; + DuskLog.info("Discord Rich Presence shut down"); +} + +} // namespace discord +} // namespace dusk + +#endif // DUSK_DISCORD_RPC diff --git a/src/dusk/frame_interpolation.cpp b/src/dusk/frame_interpolation.cpp index e3de48bcfc..c72923da7d 100644 --- a/src/dusk/frame_interpolation.cpp +++ b/src/dusk/frame_interpolation.cpp @@ -1,79 +1,31 @@ #include "dusk/frame_interpolation.h" #include +#include "mtx.h" #include "f_op/f_op_camera_mng.h" +#include "m_Do/m_Do_graphic.h" namespace { -enum class Op : uint8_t { - OpenChild, - FinalMtx, -}; - -struct Label { - const void* key = nullptr; - int32_t id = 0; - - bool operator==(const Label& other) const { - return key == other.key && id == other.id; - } -}; - -struct Data { - Label child_label{}; - size_t child_index = 0; - Mtx matrix{}; - const Mtx* dest = nullptr; - uint64_t stable_tag = 0; -}; - -struct Path; - -struct ChildBucket { - Label label{}; - std::vector> nodes; -}; - -struct OpBucket { - Op op = Op::OpenChild; - std::vector values; -}; - -struct Path { - std::vector children; - std::vector ops; - std::vector> items; - Label draw_scope{}; - uint32_t simple_shadow_pair_seq = 0; -}; struct Recording { - Path root; + std::unordered_map matrix_values; }; -struct MatrixValue { - Mtx value; -}; - -using FinalMtxLookup = std::unordered_map; -using FinalMtxLookupTagged = std::unordered_map; - bool s_initialized = false; bool g_enabled = false; bool g_recording = false; bool g_interpolating = false; bool g_sync_presentation = false; -uint32_t g_presentation_counter = 0; float g_step = 0.0f; -uint32_t g_pending_presentation_ui_ticks = 0; -uint32_t g_current_presentation_ui_ticks = 0; +bool g_is_sim_frame = false; +bool g_ui_tick_pending = false; Recording g_current_recording; Recording g_previous_recording; -std::vector g_current_path; -std::unordered_map g_replacements; +std::unordered_map g_replacements; struct CameraSnapshot { cXyz eye{}; @@ -84,6 +36,7 @@ struct CameraSnapshot { f32 aspect{}; f32 near_{}; f32 far_{}; + bool wideZoom{}; bool valid{}; }; @@ -93,6 +46,13 @@ CameraSnapshot s_cam_curr{}; view_class s_presentation_view_backup{}; int s_presentation_depth = 0; +struct InterpolationCallBackWork { + dusk::frame_interp::InterpolationCallBack pCallBack; + void* pUserWork; +}; + +std::vector s_interpolationCallBackWork; + void copy_view_to_snap(CameraSnapshot* dst, const view_class& v) { dst->eye = v.lookat.eye; dst->center = v.lookat.center; @@ -105,14 +65,6 @@ void copy_view_to_snap(CameraSnapshot* dst, const view_class& v) { dst->valid = true; } -inline void copy_matrix(const Mtx src, Mtx dst) { - MTXCopy(src, dst); -} - -inline void concat_matrix(const Mtx lhs, const Mtx rhs, Mtx out) { - MTXConcat(lhs, rhs, out); -} - inline void lerp_matrix(Mtx out, const Mtx lhs, const Mtx rhs, float step) { const float old_weight = 1.0f - step; for (size_t row = 0; row < 3; ++row) { @@ -146,162 +98,22 @@ inline bool matrix_differs(const Mtx lhs, const Mtx rhs, float epsilon = 0.0001f return false; } -Data& append_op(Op op) { - auto& items = g_current_path.back()->items; - auto& buckets = g_current_path.back()->ops; - auto it = std::find_if(buckets.begin(), buckets.end(), - [op](const OpBucket& bucket) { return bucket.op == op; }); - if (it == buckets.end()) { - buckets.push_back({op, {}}); - it = buckets.end() - 1; - } - items.emplace_back(op, it->values.size()); - return it->values.emplace_back(); -} - -const Data* find_matching_data(const Path& path, Op op, size_t index) { - auto it = std::find_if(path.ops.begin(), path.ops.end(), - [op](const OpBucket& bucket) { return bucket.op == op; }); - if (it == path.ops.end() || index >= it->values.size()) { - return nullptr; - } - return &it->values[index]; -} - -const OpBucket* find_op_bucket(const Path& path, Op op) { - auto it = std::find_if(path.ops.begin(), path.ops.end(), - [op](const OpBucket& bucket) { return bucket.op == op; }); - if (it == path.ops.end()) { - return nullptr; - } - return &*it; -} - -void build_final_mtx_lookups(const Path& path, FinalMtxLookup& dest_lookup, FinalMtxLookupTagged& tag_lookup) { - dest_lookup.clear(); - tag_lookup.clear(); - - const OpBucket* bucket = find_op_bucket(path, Op::FinalMtx); - if (bucket == nullptr) { - return; - } - - for (const Data& data : bucket->values) { - if (data.dest != nullptr) { - dest_lookup[data.dest] = &data; - } - if (data.stable_tag != 0) { - tag_lookup[data.stable_tag] = &data; - } - } -} - -const Data* find_matching_final_mtx(const FinalMtxLookup& lookup, const Data& new_data) { - if (new_data.dest == nullptr) { - return nullptr; - } - - auto it = lookup.find(new_data.dest); - if (it == lookup.end()) { - return nullptr; - } - return it->second; -} - -ChildBucket& get_child_bucket(Path& path, const Label& label) { - auto it = std::find_if(path.children.begin(), path.children.end(), - [&label](const ChildBucket& bucket) { return bucket.label == label; }); - if (it == path.children.end()) { - path.children.push_back({}); - it = path.children.end() - 1; - it->label = label; - } - return *it; -} - -const ChildBucket* find_child_bucket(const Path& path, const Label& label) { - auto it = std::find_if(path.children.begin(), path.children.end(), - [&label](const ChildBucket& bucket) { return bucket.label == label; }); - if (it == path.children.end()) { - return nullptr; - } - return &*it; -} - -void store_replacement(const Data& old_data, const Data& new_data, float step) { - if (new_data.dest == nullptr) { - return; - } - - auto& replacement = g_replacements[new_data.dest]; - lerp_matrix(replacement.value, old_data.matrix, new_data.matrix, step); -} - -void interpolate_branch(const Path& old_path, const Path& new_path, float step) { - FinalMtxLookup old_final_mtx_lookup; - FinalMtxLookupTagged old_final_mtx_lookup_tagged; - build_final_mtx_lookups(old_path, old_final_mtx_lookup, old_final_mtx_lookup_tagged); - - for (const auto& item : new_path.items) { - const Op op = item.first; - const size_t index = item.second; - const Data* new_data = find_matching_data(new_path, op, index); - if (new_data == nullptr) { - continue; - } - - if (op == Op::OpenChild) { - const ChildBucket* new_children = find_child_bucket(new_path, new_data->child_label); - if (new_children == nullptr || new_data->child_index >= new_children->nodes.size()) - { - continue; - } - - const Path& new_child = *new_children->nodes[new_data->child_index]; - const ChildBucket* old_children = find_child_bucket(old_path, new_data->child_label); - if (old_children != nullptr && new_data->child_index < old_children->nodes.size()) - { - interpolate_branch(*old_children->nodes[new_data->child_index], new_child, step); - } else { - interpolate_branch(new_child, new_child, step); - } - continue; - } - - const Data* indexed_old_data = find_matching_data(old_path, op, index); - const Data* old_data = nullptr; - if (op == Op::FinalMtx) { - if (new_data->stable_tag != 0) { - const auto it = old_final_mtx_lookup_tagged.find(new_data->stable_tag); - old_data = it != old_final_mtx_lookup_tagged.end() ? it->second : nullptr; - } else { - old_data = find_matching_final_mtx(old_final_mtx_lookup, *new_data); - } - } else { - old_data = indexed_old_data; - } - if (op == Op::FinalMtx) { - store_replacement(old_data != nullptr ? *old_data : *new_data, *new_data, step); - } - } -} - const Mtx* resolve_replacement(const Mtx* source, Mtx* scratch) { if (!g_interpolating || source == nullptr || dusk::frame_interp::presentation_sync_active()) { return source; } - auto it = g_replacements.find(source); + auto it = g_replacements.find(reinterpret_cast(source)); if (it == g_replacements.end()) { return source; } - copy_matrix(it->second.value, *scratch); + MTXCopy(it->second, *scratch); return scratch; } bool has_recording_data(const Recording& recording) { - return !recording.root.items.empty() || !recording.root.children.empty(); + return !recording.matrix_values.empty(); } void clear_replacements() { @@ -312,10 +124,27 @@ void clear_replacements() { namespace dusk::frame_interp { void ensure_initialized() { - g_enabled = getSettings().game.enableFrameInterpolation; s_initialized = true; } +void begin_frame(bool enabled, bool is_sim_frame, float step) { + g_enabled = enabled; + g_is_sim_frame = is_sim_frame; + g_step = std::clamp(step, 0.0f, 1.0f); + if (is_sim_frame) { + s_interpolationCallBackWork.clear(); + s_cam_prev = std::move(s_cam_curr); + } +} + +bool is_enabled() { + return g_enabled; +} + +bool is_sim_frame() { + return g_is_sim_frame; +} + void begin_record() { ensure_initialized(); @@ -324,7 +153,6 @@ void begin_record() { g_sync_presentation = false; g_previous_recording = {}; g_current_recording = {}; - g_current_path.clear(); clear_replacements(); s_cam_prev.valid = false; s_cam_curr.valid = false; @@ -334,8 +162,6 @@ void begin_record() { g_sync_presentation = false; g_previous_recording = std::move(g_current_recording); g_current_recording = {}; - g_current_path.clear(); - g_current_path.push_back(&g_current_recording.root); g_recording = true; g_interpolating = false; clear_replacements(); @@ -345,8 +171,6 @@ void begin_record() { s_cam_prev.valid = false; s_cam_curr.valid = false; return; - } else { - copy_view_to_snap(&s_cam_prev, cam->view); } } @@ -354,21 +178,20 @@ void end_record() { g_recording = false; } -void interpolate(float step) { +void interpolate() { ensure_initialized(); clear_replacements(); - g_step = std::clamp(step, 0.0f, 1.0f); g_interpolating = g_enabled && !g_recording && !g_sync_presentation && has_recording_data(g_current_recording); if (!g_interpolating) { return; } - const Path& old_root = has_recording_data(g_previous_recording) ? g_previous_recording.root : g_current_recording.root; - interpolate_branch(old_root, g_current_recording.root, g_step); -} - -void notify_presentation_frame() { - ensure_initialized(); - ++g_presentation_counter; + for (auto const& old : g_previous_recording.matrix_values) { + if (auto it = g_current_recording.matrix_values.find(old.first); + it != g_current_recording.matrix_values.end()) + { + lerp_matrix(g_replacements[old.first], old.second, it->second, g_step); + } + } } void request_presentation_sync() { @@ -391,92 +214,40 @@ float get_interpolation_step() { return presentation_sync_active() ? 1.0f : g_step; } -void notify_sim_tick_complete() { +void set_ui_tick_pending(bool value) { + if (g_ui_tick_pending == value) { return; } + g_ui_tick_pending = value; +} + +bool get_ui_tick_pending() { ensure_initialized(); - g_pending_presentation_ui_ticks++; + return g_enabled ? g_ui_tick_pending : true; } -uint32_t begin_presentation_ui_pass() { - ensure_initialized(); - g_current_presentation_ui_ticks = g_pending_presentation_ui_ticks; - g_pending_presentation_ui_ticks = 0; - return g_current_presentation_ui_ticks; -} - -uint32_t get_presentation_ui_advance_ticks() { - if (!s_initialized) { - return 0; - } - if (!g_enabled) { - return 1; - } - return g_current_presentation_ui_ticks; -} - -void end_presentation_ui_pass() { - if (!s_initialized) { - return; - } - g_current_presentation_ui_ticks = 0; -} - -void open_child(const void* key, int32_t id) { - if (!s_initialized || !g_recording) { +void record_final_mtx(Mtx m, const void* key) { + if (!s_initialized || !g_recording || m == nullptr) { return; } - Label label{key, id}; - auto& siblings = get_child_bucket(*g_current_path.back(), label).nodes; - Data& data = append_op(Op::OpenChild); - data.child_label = label; - data.child_index = siblings.size(); - siblings.emplace_back(std::make_unique()); - Path* const child = siblings.back().get(); - child->draw_scope = label; - g_current_path.push_back(child); + auto& it = g_current_recording.matrix_values[reinterpret_cast(key)]; + MTXCopy(m, it); } -void close_child() { - if (!s_initialized || !g_recording || g_current_path.size() <= 1) { - return; - } - - g_current_path.pop_back(); +void record_final_mtx(Mtx m) { + record_final_mtx(m, m); } -void record_final_mtx_raw(const Mtx* dest, const Mtx src) { - if (!s_initialized || !g_recording || dest == nullptr) { - return; - } - - Data& data = append_op(Op::FinalMtx); - data.dest = dest; - data.stable_tag = 0; - copy_matrix(src, data.matrix); -} - -void record_final_mtx_raw_tagged(const Mtx* dest, const Mtx src, uint64_t stable_tag) { - if (!s_initialized || !g_recording || dest == nullptr) { - return; - } - - Data& data = append_op(Op::FinalMtx); - data.dest = dest; - data.stable_tag = stable_tag; - copy_matrix(src, data.matrix); -} - -bool lookup_replacement(const void* source, Mtx out) { - if (presentation_sync_active() || !g_interpolating || source == nullptr) { +bool lookup_replacement(const void* key, Mtx out) { + if (presentation_sync_active() || !g_interpolating || key == nullptr) { return false; } - auto it = g_replacements.find(reinterpret_cast(source)); + auto it = g_replacements.find(reinterpret_cast(key)); if (it == g_replacements.end()) { return false; } - copy_matrix(it->second.value, out); + MTXCopy(it->second, out); return true; } @@ -493,7 +264,7 @@ bool lookup_concat_replacement(const void* lhs, const void* rhs, Mtx out) { return false; } - concat_matrix(*resolved_lhs, *resolved_rhs, out); + MTXConcat(*resolved_lhs, *resolved_rhs, out); return true; } @@ -502,27 +273,17 @@ void record_camera(::camera_process_class* cam, int camera_id) { return; } copy_view_to_snap(&s_cam_curr, cam->view); +#if WIDESCREEN_SUPPORT + s_cam_curr.wideZoom = mDoGph_gInf_c::isWideZoom(); +#endif } -void begin_presentation_camera() { - ensure_initialized(); - if (!g_enabled) { +void interp_view(::view_class* view) { + if (!g_enabled) return; - } - if (s_presentation_depth > 0) { - s_presentation_depth++; - return; - } - if (!s_cam_prev.valid || !s_cam_curr.valid) { - return; - } - view_class* const view = dComIfGd_getView(); - if (view == nullptr) { + if (!s_cam_prev.valid || !s_cam_curr.valid) return; - } - - std::memcpy(&s_presentation_view_backup, view, sizeof(view_class)); const f32 step = get_interpolation_step(); cXyz eye; @@ -545,6 +306,53 @@ void begin_presentation_camera() { view->near_ = s_cam_prev.near_ + (s_cam_curr.near_ - s_cam_prev.near_) * step; view->far_ = s_cam_prev.far_ + (s_cam_curr.far_ - s_cam_prev.far_) * step; + // FRAME INTERP TODO: It might be better if I rewired the game to not clear this flag until the + // next sim frame, but I don't care enough to right now +#if WIDESCREEN_SUPPORT + if (mDoGph_gInf_c::isWide() && !mDoGph_gInf_c::isWideZoom() && step >= 0.5f ? + s_cam_curr.wideZoom : + s_cam_prev.wideZoom) + { + mDoGph_gInf_c::onWideZoom(); + } +#endif +} + +static void run_interpolation_callbacks() { + for (size_t i = 0; i < s_interpolationCallBackWork.size(); i++) { + auto const& work = s_interpolationCallBackWork[i]; + work.pCallBack(g_is_sim_frame, work.pUserWork); + } +} + +void add_interpolation_callback(InterpolationCallBack pCallBack, void* pUserWork) { + if (!is_enabled() || s_presentation_depth > 0 || !g_is_sim_frame) + return; + + s_interpolationCallBackWork.emplace_back(pCallBack, pUserWork); +} + +void begin_presentation_camera() { + ensure_initialized(); + if (!g_enabled) { + return; + } + if (s_presentation_depth > 0) { + s_presentation_depth++; + return; + } + if (!s_cam_prev.valid || !s_cam_curr.valid) { + return; + } + + view_class* const view = dComIfGd_getView(); + if (view == nullptr) { + return; + } + + std::memcpy(&s_presentation_view_backup, view, sizeof(view_class)); + interp_view(view); + // FRAME INTERP TODO: Largely copied from d_camera's camera_draw function from this point, got any better ideas? C_MTXPerspective(view->projMtx, view->fovy, view->aspect, view->near_, view->far_); mDoMtx_lookAt(view->viewMtx, &view->lookat.eye, &view->lookat.center, &view->lookat.up, view->bank); @@ -600,8 +408,14 @@ void begin_presentation_camera() { } mDoLib_clipper::setup(view->fovy, view->aspect, view->near_, far_); + +#if WIDESCREEN_SUPPORT + mDoGph_gInf_c::offWideZoom(); +#endif s_presentation_depth = 1; + + run_interpolation_callbacks(); } void end_presentation_camera() { @@ -618,20 +432,4 @@ void end_presentation_camera() { std::memcpy(view, &s_presentation_view_backup, sizeof(view_class)); } } - -uint64_t alloc_simple_shadow_pair_base() { - if (!s_initialized || !g_recording || g_current_path.size() <= 1) { - return 0; - } - - Path* const scope = g_current_path.back(); - const uint64_t h = static_cast(reinterpret_cast(scope->draw_scope.key)); - const uint32_t lo = scope->simple_shadow_pair_seq; - scope->simple_shadow_pair_seq += 2; - uint64_t tag0 = (h << 17) ^ (static_cast(lo) << 1u); - if (tag0 == 0) { - tag0 = 2; - } - return tag0; -} } // namespace dusk::frame_interp diff --git a/src/dusk/game_clock.cpp b/src/dusk/game_clock.cpp new file mode 100644 index 0000000000..a262d0283c --- /dev/null +++ b/src/dusk/game_clock.cpp @@ -0,0 +1,82 @@ +#include "dusk/game_clock.h" + +#include +#include +#include +#include + +namespace dusk { +namespace game_clock { + +using clock = std::chrono::steady_clock; + +bool s_initialized = false; +clock::time_point s_previous_sample{}; +float s_sim_accumulator = 0.0f; + +std::unordered_map s_interval_last_sample; + +void ensure_initialized() { + if (s_initialized) { + return; + } + s_previous_sample = clock::now(); + s_sim_accumulator = sim_pace(); + s_initialized = true; +} + +void reset_accumulator() { + ensure_initialized(); + s_sim_accumulator = fmodf(s_sim_accumulator, sim_pace()); +} + +void reset_frame_timer() { + s_previous_sample = clock::now(); + s_sim_accumulator = 0.0f; +} + +MainLoopPacer advance_main_loop() { + ensure_initialized(); + + const clock::time_point now = clock::now(); + const float presentation_dt = std::chrono::duration(now - s_previous_sample).count(); + s_previous_sample = now; + + s_sim_accumulator += presentation_dt; + + MainLoopPacer out{}; + out.presentation_dt_seconds = presentation_dt; + + const bool should_interpolate = dusk::getSettings().game.enableFrameInterpolation && !dusk::getTransientSettings().skipFrameRateLimit; + out.is_interpolating = should_interpolate; + out.sim_pace = sim_pace(); + + if (!should_interpolate) { + s_sim_accumulator = 0.0f; + out.do_sim_tick = true; + out.interpolation_step = 0.0f; + return out; + } else { + out.do_sim_tick = s_sim_accumulator >= sim_pace(); + out.interpolation_step = out.do_sim_tick ? 0.0f : s_sim_accumulator / sim_pace(); + return out; + } +} + +float consume_interval(const void* consumer) { + ensure_initialized(); + const uintptr_t key = reinterpret_cast(consumer); + const clock::time_point now = clock::now(); + + float dt = ui_initial_dt(); + const auto it = s_interval_last_sample.find(key); + if (it != s_interval_last_sample.end()) { + dt = std::chrono::duration(now - it->second).count(); + dt = std::min(dt, ui_maximum_dt()); + } + s_interval_last_sample[key] = now; + return dt; +} + +} // namespace game_clock +} // namespace dusk diff --git a/src/dusk/gyro.cpp b/src/dusk/gyro.cpp index 0905bd59fd..d390c9c8b4 100644 --- a/src/dusk/gyro.cpp +++ b/src/dusk/gyro.cpp @@ -35,7 +35,7 @@ bool s_sensor_keep_alive = false; bool get_sensor_keep_alive() { return s_sensor_keep_alive; } void set_sensor_keep_alive(bool value) { s_sensor_keep_alive = value; } -bool queryGyroAimItemContext() { +bool queryGyroAimContext() { if (!static_cast(dusk::getSettings().game.enableGyroAim)) { return false; } @@ -45,11 +45,11 @@ bool queryGyroAimItemContext() { return false; } - return link->checkGyroAimItemContext() && dComIfGp_checkCameraAttentionStatus(link->field_0x317c, 0x10); + return link->checkGyroAimContext() && dComIfGp_checkCameraAttentionStatus(link->field_0x317c, 0x10); } void read(float dt) { - if (!s_sensor_keep_alive && !(dusk::getSettings().game.enableGyroAim && queryGyroAimItemContext())) { + if (!s_sensor_keep_alive && !queryGyroAimContext()) { if (s_sensor_enabled) { PADSetSensorEnabled(PAD_CHAN0, PAD_SENSOR_GYRO, FALSE); s_sensor_enabled = false; diff --git a/src/dusk/imgui/ImGuiCameraOverlay.cpp b/src/dusk/imgui/ImGuiCameraOverlay.cpp index daaa2d6180..aa3d1ac093 100644 --- a/src/dusk/imgui/ImGuiCameraOverlay.cpp +++ b/src/dusk/imgui/ImGuiCameraOverlay.cpp @@ -49,9 +49,10 @@ namespace dusk { ImGui::SeparatorText("Free-look Data"); static float eyeYawDeg = 0.0f; - static float moveSpeed = 10000.0f; + static float moveSpeed = 5000.0f; static float rotSpeed = 5.0f; static cXyz freeLookPos = cXyz::Zero; + static bool freeLookActive = false; bool changed = false; @@ -91,7 +92,17 @@ namespace dusk { changed = true; } - if (changed) { + if (!freeLookActive && changed) { + freeLookPos += dCam->Center(); + freeLookActive = true; + } + + if (ImGui::IsKeyDown(ImGuiKey_R)) { + freeLookPos = cXyz::Zero; + freeLookActive = false; + } + + if (freeLookActive) { dCam->Reset(freeLookPos, freeLookPos + (frontDir * 100.0f)); } diff --git a/src/dusk/imgui/ImGuiConsole.cpp b/src/dusk/imgui/ImGuiConsole.cpp index 856b97f5ca..99a48e656e 100644 --- a/src/dusk/imgui/ImGuiConsole.cpp +++ b/src/dusk/imgui/ImGuiConsole.cpp @@ -17,6 +17,7 @@ #include "dusk/audio/DuskAudioSystem.h" #include "dusk/config.hpp" #include "dusk/dusk.h" +#include "dusk/frame_interpolation.h" #include "dusk/main.h" #include "dusk/settings.h" #include "m_Do/m_Do_controller_pad.h" @@ -281,7 +282,7 @@ namespace dusk { void ImGuiConsole::UpdateSettings() { getTransientSettings().skipFrameRateLimit = getSettings().game.enableTurboKeybind && ImGui::IsKeyDown(ImGuiKey_Tab); - if (mDoMain::developmentMode == 1 && mDoCPd_c::getHoldL(PAD_1) && mDoCPd_c::getHoldR(PAD_1) && mDoCPd_c::getTrigY(PAD_1)) { + if (dusk::frame_interp::get_ui_tick_pending() && mDoMain::developmentMode == 1 && (mDoCPd_c::getHold(PAD_1) & (PAD_TRIGGER_R | PAD_TRIGGER_L)) == (PAD_TRIGGER_R | PAD_TRIGGER_L) && mDoCPd_c::getTrigY(PAD_1)) { getTransientSettings().moveLinkActive = !getTransientSettings().moveLinkActive; } if (mDoMain::developmentMode != 1) { @@ -368,10 +369,16 @@ namespace dusk { m_menuTools.ShowStateShare(); DuskDebugPad(); // temporary, remove later - // Only show cursor when menu or any windows are open - if (showMenu || ImGui::GetIO().MetricsRenderWindows > 0) { - ImGui::GetIO().ConfigFlags &= ~ImGuiConfigFlags_NoMouseCursorChange; - // Imgui will re-show cursor. + // Hide mouse cursor if the F1 menu is not open and the cursor is idle for 3 seconds. + ImGuiIO& io = ImGui::GetIO(); + if (showMenu) { + mouseHideTimer = 0.0f; + ImGui::GetIO().ConfigFlags &= ~ImGuiConfigFlags_NoMouseCursorChange; // Imgui will re-show cursor. + } else if (io.MouseDelta.x != 0.0f || io.MouseDelta.y != 0.0f) { + mouseHideTimer = 0.0f; + ImGui::GetIO().ConfigFlags &= ~ImGuiConfigFlags_NoMouseCursorChange; // Imgui will re-show cursor. + } else if (mouseHideTimer <= 3.0f) { + mouseHideTimer += ImGui::GetIO().DeltaTime; } else { ImGui::GetIO().ConfigFlags |= ImGuiConfigFlags_NoMouseCursorChange; SDL_HideCursor(); diff --git a/src/dusk/imgui/ImGuiConsole.hpp b/src/dusk/imgui/ImGuiConsole.hpp index 9d733d939e..2e8bd7497b 100644 --- a/src/dusk/imgui/ImGuiConsole.hpp +++ b/src/dusk/imgui/ImGuiConsole.hpp @@ -40,6 +40,8 @@ private: remain(duration) {} }; + float mouseHideTimer = 0.0f; + bool m_isHidden = true; bool m_isLaunchInitialized = false; bool m_touchTapActive = false; diff --git a/src/dusk/imgui/ImGuiFirstRunPreset.cpp b/src/dusk/imgui/ImGuiFirstRunPreset.cpp index c218185c92..fb2d181562 100644 --- a/src/dusk/imgui/ImGuiFirstRunPreset.cpp +++ b/src/dusk/imgui/ImGuiFirstRunPreset.cpp @@ -13,7 +13,7 @@ static void ApplyPresetClassic() { auto& s = getSettings(); s.video.lockAspectRatio.setValue(true); s.game.bloomMode.setValue(BloomMode::Classic); - VILockAspectRatio(defaultAspectRatioW, defaultAspectRatioH); + AuroraSetViewportPolicy(AURORA_VIEWPORT_FIT); } static void ApplyPresetHD() { diff --git a/src/dusk/imgui/ImGuiMenuEnhancements.cpp b/src/dusk/imgui/ImGuiMenuEnhancements.cpp index d47b4e8d4b..7d179aa578 100644 --- a/src/dusk/imgui/ImGuiMenuEnhancements.cpp +++ b/src/dusk/imgui/ImGuiMenuEnhancements.cpp @@ -65,6 +65,11 @@ namespace dusk { ImGui::SetTooltip("Skip the delay when writing to the Memory Card."); } + config::ImGuiCheckbox("Hold B for Instant Text", getSettings().game.instantText); + if (ImGui::IsItemHovered()) { + ImGui::SetTooltip("Make text scroll immediately by holding B."); + } + config::ImGuiCheckbox("No Climbing Miss Animation", getSettings().game.noMissClimbing); if (ImGui::IsItemHovered()) { ImGui::SetTooltip("Prevents Link from playing a struggle animation\n" @@ -144,8 +149,10 @@ namespace dusk { config::ImGuiCheckbox("Gyro Aim", getSettings().game.enableGyroAim); if (ImGui::IsItemHovered()) { - ImGui::SetTooltip("Enables the gyroscope on supported controllers while aiming the\n" - "Slingshot, Gale Boomerang, Hero's Bow, Clawshot(s), Ball and Chain, and Dominion Rod."); + ImGui::SetTooltip("Enables the gyroscope on supported controllers\n" + "while in look mode (C-Up) and while aiming the\n" + "Slingshot, Gale Boomerang, Hero's Bow, Clawshot(s),\n" + "Ball and Chain, and Dominion Rod."); } config::ImGuiCheckbox("Gyro Rollgoal", getSettings().game.enableGyroRollgoal); @@ -195,6 +202,16 @@ namespace dusk { ImGui::Separator(); if (ImGui::BeginMenu("Cheats")) { + config::ImGuiCheckbox("Infinite Hearts", getSettings().game.infiniteHearts); + config::ImGuiCheckbox("Infinite Arrows", getSettings().game.infiniteArrows); + config::ImGuiCheckbox("Infinite Bombs", getSettings().game.infiniteBombs); + config::ImGuiCheckbox("Infinite Oil", getSettings().game.infiniteOil); + config::ImGuiCheckbox("Infinite Oxygen", getSettings().game.infiniteOxygen); + config::ImGuiCheckbox("Infinite Rupees", getSettings().game.infiniteRupees); + config::ImGuiCheckbox("Moon Jump (R+A)", getSettings().game.moonJump); + config::ImGuiCheckbox("Super Clawshot", getSettings().game.superClawshot); + config::ImGuiCheckbox("Always Greatspin", getSettings().game.alwaysGreatspin); + config::ImGuiCheckbox("Fast Iron Boots", getSettings().game.enableFastIronBoots); config::ImGuiCheckbox("Can Transform Anywhere", getSettings().game.canTransformAnywhere); diff --git a/src/dusk/imgui/ImGuiMenuGame.cpp b/src/dusk/imgui/ImGuiMenuGame.cpp index b0c20b4d46..c6676df774 100644 --- a/src/dusk/imgui/ImGuiMenuGame.cpp +++ b/src/dusk/imgui/ImGuiMenuGame.cpp @@ -17,10 +17,42 @@ #include "m_Do/m_Do_graphic.h" #include +#include #include +#include #include "dusk/main.h" +#if defined(__APPLE__) +#include +#endif + +#if defined(_WIN32) || (defined(__APPLE__) && !TARGET_OS_IOS && !TARGET_OS_MACCATALYST) || (defined(__linux__) && !defined(__ANDROID__)) +#define DUSK_CAN_OPEN_DATA_FOLDER 1 + +namespace fs = std::filesystem; + +static void OpenDataFolder() { + const std::string path = fs::absolute(fs::path(aurora::g_config.configPath)).generic_string(); +#if defined(_WIN32) + const std::string url = std::string("file:///") + path; +#else + const std::string url = std::string("file://") + path; +#endif + (void)SDL_OpenURL(url.c_str()); +} +#else +#define DUSK_CAN_OPEN_DATA_FOLDER 0 +#endif + +namespace { +constexpr int kInternalResolutionScaleMax = 12; +} // namespace + +namespace aurora::gx { +extern bool enableLodBias; +} + namespace dusk { void ImGuiMenuGame::ToggleFullscreen() { getSettings().video.enableFullscreen.setValue(!getSettings().video.enableFullscreen); @@ -58,14 +90,34 @@ namespace dusk { getSettings().video.lockAspectRatio.setValue(lockAspect); if (lockAspect) { - VILockAspectRatio(defaultAspectRatioW, defaultAspectRatioH); + AuroraSetViewportPolicy(AURORA_VIEWPORT_FIT); } else { - VIUnlockAspectRatio(); + AuroraSetViewportPolicy(AURORA_VIEWPORT_STRETCH); } config::Save(); } + u32 internalResolutionWidth = 0; + u32 internalResolutionHeight = 0; + AuroraGetRenderSize(&internalResolutionWidth, &internalResolutionHeight); + ImGui::TextDisabled("Current internal resolution: %ux%u", internalResolutionWidth, + internalResolutionHeight); + + int scale = std::clamp(getSettings().game.internalResolutionScale.getValue(), 0, + kInternalResolutionScaleMax); + if (ImGui::SliderInt("Internal Resolution", &scale, 0, kInternalResolutionScaleMax, + scale == 0 ? "Auto" : "%dx")) + { + getSettings().game.internalResolutionScale.setValue(scale); + VISetFrameBufferScale(static_cast(scale)); + config::Save(); + } + if (ImGui::IsItemHovered()) { + ImGui::SetTooltip("Auto renders at the native window resolution.\n" + "Higher values scale the game's internal framebuffer."); + } + constexpr const char* bloomModeNames[] = {"Off", "Classic", "Dusk"}; int bloomMode = static_cast(getSettings().game.bloomMode.getValue()); if (ImGui::BeginCombo("Bloom", bloomModeNames[bloomMode])) { @@ -91,7 +143,7 @@ namespace dusk { } if (bloomOff) ImGui::EndDisabled(); - config::ImGuiCheckbox("Enable Water Refraction", getSettings().game.enableWaterRefraction); + ImGui::Checkbox("Enable LOD Bias", &aurora::gx::enableLodBias); ImGui::EndMenu(); } @@ -140,12 +192,23 @@ namespace dusk { #if DUSK_ENABLE_SENTRY_NATIVE config::ImGuiCheckbox("Enable Crash Reporting", getSettings().backend.enableCrashReporting); #endif + if (!IsMobile) { + config::ImGuiCheckbox("Pause on Focus Lost", getSettings().game.pauseOnFocusLost); + } ImGui::EndMenu(); } ImGui::Separator(); +#if DUSK_CAN_OPEN_DATA_FOLDER + if (ImGui::MenuItem("Open Data Folder")) { + OpenDataFolder(); + } +#endif + + ImGui::Separator(); + if (ImGui::MenuItem("Reset", hotkeys::DO_RESET)) { JUTGamePad::C3ButtonReset::sResetSwitchPushing = true; } diff --git a/src/dusk/imgui/ImGuiMenuTools.cpp b/src/dusk/imgui/ImGuiMenuTools.cpp index 9bb7670e88..1f9d42fbc9 100644 --- a/src/dusk/imgui/ImGuiMenuTools.cpp +++ b/src/dusk/imgui/ImGuiMenuTools.cpp @@ -2,6 +2,7 @@ #include "imgui.h" #include "aurora/gfx.h" +#include "ImGuiConfig.hpp" #include "dusk/hotkeys.h" #include "dusk/settings.h" #include "ImGuiConsole.hpp" @@ -28,6 +29,15 @@ namespace dusk { ImGui::Separator(); auto& collisionView = getTransientSettings().collisionView; + if (ImGui::BeginMenu("Graphics Settings")) { + bool disableWaterRefraction = getSettings().game.disableWaterRefraction; + if (ImGui::Checkbox("Disable Water Refraction", &disableWaterRefraction)) { + getSettings().game.disableWaterRefraction.setValue(disableWaterRefraction); + config::Save(); + } + ImGui::EndMenu(); + } + if (ImGui::BeginMenu("Collision View")) { ImGui::Checkbox("Enable Terrain view", &collisionView.enableTerrainView); ImGui::Checkbox("Enable wireframe view", &collisionView.enableWireframe); diff --git a/src/dusk/imgui/ImGuiProcessOverlay.cpp b/src/dusk/imgui/ImGuiProcessOverlay.cpp index 04a87f00b6..ed71e6c485 100644 --- a/src/dusk/imgui/ImGuiProcessOverlay.cpp +++ b/src/dusk/imgui/ImGuiProcessOverlay.cpp @@ -9,53 +9,109 @@ #include "f_pc/f_pc_layer_iter.h" #include "f_pc/f_pc_leaf.h" #include "f_pc/f_pc_node.h" +#include "d/d_debug_viewer.h" #include "imgui.h" #include "ImGuiConsole.hpp" #include "ImGuiMenuTools.hpp" #include "imgui_internal.h" namespace dusk { - bool showTreeRecursive; + static bool BeginProcTable() { + static ImGuiTableFlags table_flags = + ImGuiTableFlags_BordersV | ImGuiTableFlags_BordersOuterH | ImGuiTableFlags_Resizable | + ImGuiTableFlags_RowBg | ImGuiTableFlags_NoBordersInBody; + + if (ImGui::BeginTable("proc_table", 7)) { + ImGui::TableSetupColumn("ID", ImGuiTableColumnFlags_WidthFixed, 128); + ImGui::TableSetupColumn("En", ImGuiTableColumnFlags_WidthFixed, 32); + ImGui::TableSetupColumn("Vs", ImGuiTableColumnFlags_WidthFixed, 32); + ImGui::TableSetupColumn("ProcName"); + ImGui::TableSetupColumn("Param", ImGuiTableColumnFlags_WidthFixed, 128); + ImGui::TableSetupColumn("Pi", ImGuiTableColumnFlags_WidthFixed, 64); + ImGui::TableSetupColumn("DwPi", ImGuiTableColumnFlags_WidthFixed, 64); + ImGui::TableHeadersRow(); + return true; + } + return false; + } static int ShowProcess(void* p, void*) { auto proc = static_cast(p); - char buf[64]; - snprintf(buf, sizeof(buf), "%d", proc->id); + ImGui::TableNextRow(); + ImGui::PushID(proc); + bool pending = proc->create_req != nullptr; + if (pending) + ImGui::PushStyleColor(ImGuiCol_Text, {255, 200, 0, 255}); + ImGui::TableNextColumn(); - ImVec2 avail = ImGui::GetContentRegionAvail(); + char id_buf[32]; + sprintf(id_buf, "%d", proc->id); - ImVec2 vec = { avail.x, 0 }; - if (ImGui::BeginChild(buf, vec, ImGuiChildFlags_Border | ImGuiChildFlags_AutoResizeY)) { - ImGui::Text("[%d] %s", proc->id, GetProcName(proc->profname)); - ImGui::Text("init_state: %d, create_phase: %d", proc->state.init_state, proc->state.create_phase); + int flags = ImGuiTreeNodeFlags_SpanAllColumns; + bool isLayer = fpcBs_Is_JustOfType(g_fpcNd_type, proc->subtype); + if (isLayer) { + flags |= ImGuiTreeNodeFlags_DefaultOpen; + } else { + flags |= ImGuiTreeNodeFlags_Leaf | ImGuiTreeNodeFlags_NoTreePushOnOpen; + } - const char* ofTypeName = "unknown"; - if (proc->subtype == g_fpcNd_type) { - ofTypeName = "Node"; - } - else if (proc->subtype == g_fpcLf_type) { - ofTypeName = "Leaf"; - } + bool open = ImGui::TreeNodeEx(id_buf, flags); + fopAc_ac_c* ac = fopAcM_IsActor(proc) ? (fopAc_ac_c*)proc : nullptr; + if (ac != nullptr && ImGui::IsItemHovered()) { + fopAcM_DrawCullingBox(ac, {0, 255, 255, 255}); + } - ImGui::Text("OfType: %d (%s), layer: %d", proc->subtype, ofTypeName, proc->layer_tag.layer->layer_id); + ImGui::TableNextColumn(); + bool enable = !fpcM_IsPause(proc, 1); + if (ImGui::Checkbox("##enable", &enable)) { + if (enable) + fpcM_PauseDisable(proc, 1); + else + fpcM_PauseEnable(proc, 1); + } - if (proc->create_req != nullptr) { - ImGui::TextColored(ImVec4(1.0f, 0.0f, 0.0f, 1.0f), "Pending create request"); - } - - if (showTreeRecursive) { - if (fpcBs_Is_JustOfType(g_fpcNd_type, proc->subtype)) { - auto procNode = static_cast(p); - - ImGui::Text("Owns layer %d", procNode->layer.layer_id); - - fpcLyIt_OnlyHere(&procNode->layer, ShowProcess, nullptr); - } + ImGui::TableNextColumn(); + if (fpcBs_Is_JustOfType(g_fpcLf_type, proc->subtype)) { + leafdraw_class* lf = (leafdraw_class*)proc; + bool vis = lf->unk_0xBC == 0; + if (ImGui::Checkbox("##visible", &vis)) { + if (vis) + lf->unk_0xBC = 0; + else + lf->unk_0xBC = 1; } } - ImGui::EndChild(); + ImGui::TableNextColumn(); + ImGui::Text("%s", ac != nullptr ? fopAcM_getProcNameString(ac) : GetProcName(proc->profname)); + + ImGui::TableNextColumn(); + if (proc->profname == fpcNm_ROOM_SCENE_e) { + ImGui::Text("Room %d", proc->parameters); + } else { + ImGui::Text("%08x", proc->parameters); + } + + ImGui::TableNextColumn(); + ImGui::Text("%d", proc->priority.current_info.list_id); + + ImGui::TableNextColumn(); + if (fpcBs_Is_JustOfType(g_fpcLf_type, proc->subtype)) { + ImGui::Text("%d", fpcM_DrawPriority(proc)); + } else { + ImGui::Text("--"); + } + + if (isLayer && open) { + auto procNode = static_cast(p); + fpcLyIt_OnlyHere(&procNode->layer, ShowProcess, nullptr); + ImGui::TreePop(); + } + + if (pending) + ImGui::PopStyleColor(1); + ImGui::PopID(); return 1; } @@ -76,15 +132,11 @@ namespace dusk { if (ImGui::Begin("Processes", &m_showProcessManagement)) { if (ImGui::BeginTabBar("Tabs")) { - showTreeRecursive = true; if (ImGui::BeginTabItem("Tree")) { - fpcLyIt_OnlyHere(fpcLy_RootLayer(), ShowProcess, nullptr); - ImGui::EndTabItem(); - } - - showTreeRecursive = false; - if (ImGui::BeginTabItem("All layers")) { - fpcLyIt_All(ShowProcess, nullptr); + if (BeginProcTable()) { + fpcLyIt_OnlyHere(fpcLy_RootLayer(), ShowProcess, nullptr); + ImGui::EndTable(); + } ImGui::EndTabItem(); } diff --git a/src/dusk/settings.cpp b/src/dusk/settings.cpp index e4cace9ff0..2bcdbe2185 100644 --- a/src/dusk/settings.cpp +++ b/src/dusk/settings.cpp @@ -35,18 +35,21 @@ UserSettings g_userSettings = { .noMissClimbing {"game.noMissClimbing", false}, .fastTears {"game.fastTears", false}, .instantSaves {"game.instantSaves", false}, + .instantText {"game.instantText", false}, .sunsSong {"game.sunsSong", false}, // Preferences .enableMirrorMode {"game.enableMirrorMode", false}, .invertCameraXAxis {"game.invertCameraXAxis", false}, .disableMainHUD {"game.disableMainHUD", false}, + .pauseOnFocusLost {"game.pauseOnFocusLost", false}, // Graphics .bloomMode {"game.bloomMode", BloomMode::Classic}, .bloomMultiplier {"game.bloomMultiplier", 1.0f}, - .enableWaterRefraction {"game.enableWaterRefraction", true}, + .disableWaterRefraction {"game.disableWaterRefraction", false}, .enableFrameInterpolation = {"game.enableFrameInterpolation", false}, + .internalResolutionScale {"game.internalResolutionScale", 0}, .shadowResolutionMultiplier {"game.shadowResolutionMultiplier", 1}, // Audio @@ -65,6 +68,15 @@ UserSettings g_userSettings = { .gyroInvertYaw {"game.gyroInvertYaw", false}, // Cheats + .infiniteHearts {"game.infiniteHearts", false}, + .infiniteArrows{"game.infiniteArrows", false}, + .infiniteBombs{"game.infiniteBombs", false}, + .infiniteOil{"game.infiniteOil", false}, + .infiniteOxygen{"game.infiniteOxygen", false}, + .infiniteRupees{"game.infiniteRupees", false}, + .moonJump{"game.moonJump", false}, + .superClawshot{"game.superClawshot", false}, + .alwaysGreatspin{"game.alwaysGreatspin", false}, .enableFastIronBoots {"game.enableFastIronBoots", false}, .canTransformAnywhere {"game.canTransformAnywhere", false}, .fastSpinner {"game.fastSpinner", false}, @@ -120,13 +132,16 @@ void registerSettings() { Register(g_userSettings.game.fastClimbing); Register(g_userSettings.game.fastTears); Register(g_userSettings.game.instantSaves); + Register(g_userSettings.game.instantText); Register(g_userSettings.game.sunsSong); Register(g_userSettings.game.enableMirrorMode); Register(g_userSettings.game.invertCameraXAxis); Register(g_userSettings.game.disableMainHUD); + Register(g_userSettings.game.pauseOnFocusLost); Register(g_userSettings.game.bloomMode); Register(g_userSettings.game.bloomMultiplier); - Register(g_userSettings.game.enableWaterRefraction); + Register(g_userSettings.game.disableWaterRefraction); + Register(g_userSettings.game.internalResolutionScale); Register(g_userSettings.game.shadowResolutionMultiplier); Register(g_userSettings.game.enableFastIronBoots); Register(g_userSettings.game.canTransformAnywhere); @@ -137,6 +152,15 @@ void registerSettings() { Register(g_userSettings.game.midnasLamentNonStop); Register(g_userSettings.game.enableTurboKeybind); Register(g_userSettings.game.fastSpinner); + Register(g_userSettings.game.infiniteHearts); + Register(g_userSettings.game.infiniteArrows); + Register(g_userSettings.game.infiniteBombs); + Register(g_userSettings.game.infiniteOil); + Register(g_userSettings.game.infiniteOxygen); + Register(g_userSettings.game.infiniteRupees); + Register(g_userSettings.game.moonJump); + Register(g_userSettings.game.superClawshot); + Register(g_userSettings.game.alwaysGreatspin); Register(g_userSettings.game.enableFrameInterpolation); Register(g_userSettings.game.enableGyroAim); Register(g_userSettings.game.enableGyroRollgoal); diff --git a/src/dusk/stubs.cpp b/src/dusk/stubs.cpp index 668541f49c..07e420445c 100644 --- a/src/dusk/stubs.cpp +++ b/src/dusk/stubs.cpp @@ -332,14 +332,6 @@ static VIRetraceCallback sVIPostRetraceCallback = NULL; extern "C" { -void VIConfigure(const GXRenderModeObj* rm) { - STUB_LOG(); -} - -void VIConfigurePan(u16 xOrg, u16 yOrg, u16 width, u16 height) { - STUB_LOG(); -} - u32 VIGetRetraceCount() { return sRetraceCount; } diff --git a/src/f_ap/f_ap_game.cpp b/src/f_ap/f_ap_game.cpp index 3dc192b665..d66c6fbbe1 100644 --- a/src/f_ap/f_ap_game.cpp +++ b/src/f_ap/f_ap_game.cpp @@ -821,9 +821,67 @@ void waitingForWrite() { } void endAutoSave() { - dusk::g_imguiConsole.ShowToast("Saving...", 3.0f); + dusk::g_imguiConsole.ShowToast("Saving...", 2.0f); mAutoSaveProc = 0; } + +static void duskExecute() { + updateAutoSave(); + + if (mDoCPd_c::getHoldR(PAD_1) && mDoCPd_c::getTrigX(PAD_1)) { + if (const auto link = g_dComIfG_gameInfo.play.getPlayer(0)) { + dynamic_cast(link)->handleWolfHowl(); + } + } + + if ((mDoCPd_c::getHold(PAD_1) & (PAD_TRIGGER_R | PAD_TRIGGER_L)) == PAD_TRIGGER_R && mDoCPd_c::getTrigY(PAD_1)) { + if (const auto link = g_dComIfG_gameInfo.play.getPlayer(0)) { + dynamic_cast(link)->handleQuickTransform(); + } + } + + if (dusk::getSettings().game.moonJump && (mDoCPd_c::getHoldR(PAD_1) && mDoCPd_c::getHoldA(PAD_1))) { + if (const auto link = g_dComIfG_gameInfo.play.getPlayer(0)) { + link->speed.y = 56.0f; + } + } + + 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; + } + } + } + + if (dusk::getSettings().game.infiniteHearts) { + dComIfGs_setLife((dComIfGs_getMaxLife() / 5) * 4); + } + + if (dusk::getSettings().game.infiniteArrows) { + dComIfGs_setArrowNum(dComIfGs_getArrowMax()); + } + + if (dusk::getSettings().game.infiniteBombs) { + dComIfGs_setBombNum(0, 99); + dComIfGs_setBombNum(1, 99); + dComIfGs_setBombNum(2, 99); + } + + if (dusk::getSettings().game.infiniteOil) { + dComIfGs_setOil(dComIfGs_getMaxOil()); + } + + if (dusk::getSettings().game.infiniteRupees) { + dComIfGs_setRupee(9999); + } + + if (dusk::getSettings().game.infiniteOxygen) { + dComIfGp_setOxygen(dComIfGp_getMaxOxygen()); + } +} #endif void fapGm_Execute() { @@ -839,29 +897,7 @@ void fapGm_Execute() { #endif #if TARGET_PC - updateAutoSave(); - - if (mDoCPd_c::getHoldR(PAD_1) && mDoCPd_c::getTrigX(PAD_1)) { - if (const auto link = g_dComIfG_gameInfo.play.getPlayer(0)) { - dynamic_cast(link)->handleWolfHowl(); - } - } - - if (mDoCPd_c::getHoldR(PAD_1) && mDoCPd_c::getTrigY(PAD_1)) { - if (const auto link = g_dComIfG_gameInfo.play.getPlayer(0)) { - dynamic_cast(link)->handleQuickTransform(); - } - } - - if (dusk::getSettings().game.fastSpinner && mDoCPd_c::getHoldR(PAD_1)) { - if (const auto link = g_dComIfG_gameInfo.play.getPlayer(0)) { - auto spinnerActor = (fopAc_ac_c*)dynamic_cast(link)->getSpinnerActor(); - if (spinnerActor) { - if (spinnerActor->speedF < 60.f) - spinnerActor->speedF += 2.f; - } - } - } + duskExecute(); #endif #ifdef TARGET_PC diff --git a/src/f_pc/f_pc_draw.cpp b/src/f_pc/f_pc_draw.cpp index 697d19cf29..8b775257fc 100644 --- a/src/f_pc/f_pc_draw.cpp +++ b/src/f_pc/f_pc_draw.cpp @@ -26,13 +26,7 @@ int fpcDw_Execute(base_process_class* i_proc) { } fpcLy_SetCurrentLayer(i_proc->layer_tag.layer); -#ifdef TARGET_PC - dusk::frame_interp::open_child(i_proc, 0); -#endif ret = draw_func(i_proc); -#ifdef TARGET_PC - dusk::frame_interp::close_child(); -#endif fpcLy_SetCurrentLayer(save_layer); return ret; } diff --git a/src/f_pc/f_pc_leaf.cpp b/src/f_pc/f_pc_leaf.cpp index eab6532a92..7f6d6df802 100644 --- a/src/f_pc/f_pc_leaf.cpp +++ b/src/f_pc/f_pc_leaf.cpp @@ -6,6 +6,10 @@ #include "f_pc/f_pc_leaf.h" #include "f_pc/f_pc_debug_sv.h" +#if TARGET_PC +#include "dusk/frame_interpolation.h" +#endif + s16 fpcLf_GetPriority(const leafdraw_class* i_leaf) { return fpcDwPi_Get(&i_leaf->draw_priority); } @@ -16,6 +20,11 @@ int fpcLf_DrawMethod(leafdraw_method_class* i_methods, void* i_process) { int fpcLf_Draw(leafdraw_class* i_leaf) { int ret = 0; +#if TARGET_PC + if (!i_leaf->draw_interp_frame && !dusk::frame_interp::is_sim_frame()) { + return ret; + } +#endif if (i_leaf->unk_0xBC == 0) { ret = fpcLf_DrawMethod(i_leaf->leaf_methods, i_leaf); } @@ -56,6 +65,9 @@ int fpcLf_Create(leafdraw_class* i_leaf) { LEAFDRAW_BASE(i_leaf).subtype = fpcBs_MakeOfType(&g_fpcLf_type); fpcDwPi_Init(&i_leaf->draw_priority, pprofile->priority); i_leaf->unk_0xBC = 0; +#if TARGET_PC + i_leaf->draw_interp_frame = false; +#endif } int ret = fpcMtd_Create(&i_leaf->leaf_methods->base, i_leaf); diff --git a/src/f_pc/f_pc_manager.cpp b/src/f_pc/f_pc_manager.cpp index 4d424ad75e..ad226b4d1d 100644 --- a/src/f_pc/f_pc_manager.cpp +++ b/src/f_pc/f_pc_manager.cpp @@ -65,7 +65,7 @@ void fpcM_Management(fpcM_ManagementFunc i_preExecuteFn, fpcM_ManagementFunc i_p #ifdef TARGET_PC // FRAME INTERP NOTE: Called in m_Do_main when interp is enabled - if (!dusk::getSettings().game.enableFrameInterpolation || dusk::getTransientSettings().skipFrameRateLimit) + if (!dusk::frame_interp::is_enabled()) #endif { cAPIGph_Painter(); diff --git a/src/f_pc/f_pc_node.cpp b/src/f_pc/f_pc_node.cpp index 205d392ff1..ca7bcc044b 100644 --- a/src/f_pc/f_pc_node.cpp +++ b/src/f_pc/f_pc_node.cpp @@ -7,6 +7,13 @@ #include "f_pc/f_pc_layer_iter.h" #include "f_pc/f_pc_debug_sv.h" +#if TARGET_PC +#include "f_op/f_op_draw_iter.h" +#include "f_pc/f_pc_manager.h" + +#include "dusk/frame_interpolation.h" +#endif + int fpcNd_DrawMethod(nodedraw_method_class* i_method_class, void* i_data) { return fpcMtd_Method(i_method_class->draw_method, i_data); } @@ -18,7 +25,17 @@ int fpcNd_Draw(process_node_class* i_procNode) { if (i_procNode->unk_0x1A8 == 0) { layer_class* save_layer = fpcLy_CurrentLayer(); fpcLy_SetCurrentLayer(&var_r28->layer); - ret = fpcNd_DrawMethod(i_procNode->nodedraw_method, i_procNode); +#if TARGET_PC + if (!i_procNode->draw_interp_frame && !dusk::frame_interp::is_sim_frame()) { + for (create_tag_class* i = fopDwIt_Begin(); i != NULL; i = fopDwIt_Next(i)) { + void* process = i->mpTagData; + fpcM_Draw(process); + } + } else +#endif + { + ret = fpcNd_DrawMethod(i_procNode->nodedraw_method, i_procNode); + } fpcLy_SetCurrentLayer(save_layer); } diff --git a/src/m_Do/m_Do_MemCard.cpp b/src/m_Do/m_Do_MemCard.cpp index 36de5480e5..a0c0302b09 100644 --- a/src/m_Do/m_Do_MemCard.cpp +++ b/src/m_Do/m_Do_MemCard.cpp @@ -84,11 +84,12 @@ void mDoMemCd_Ctrl_c::ThdInit() { mProbeStat = 2; mCardState = CARD_STATE_NO_CARD_e; - #if TARGET_PC - mCardState = CARD_STATE_READY_e; - #endif - +#if TARGET_PC + mCardCommand = COMM_ATTACH_e; +#else mCardCommand = COMM_NONE_e; +#endif + mChannel = SLOT_A; OSInitMutex(&mMutex); diff --git a/src/m_Do/m_Do_ext.cpp b/src/m_Do/m_Do_ext.cpp index 024dd596a8..84bf51ecf5 100644 --- a/src/m_Do/m_Do_ext.cpp +++ b/src/m_Do/m_Do_ext.cpp @@ -25,6 +25,7 @@ #include #include #include "dusk/logging.h" +#include "dusk/frame_interpolation.h" u8 mDoExt::CurrentHeapAdjustVerbose; u8 mDoExt::HeapAdjustVerbose; @@ -349,6 +350,11 @@ void mDoExt_modelUpdateDL(J3DModel* i_model) { } void mDoExt_modelEntryDL(J3DModel* i_model) { +#if TARGET_PC + if (!dusk::frame_interp::is_sim_frame()) + return; +#endif + modelMtxErrorCheck(i_model); J3DModelData* model_data = i_model->getModelData(); diff --git a/src/m_Do/m_Do_graphic.cpp b/src/m_Do/m_Do_graphic.cpp index a56e448645..d949d10ff0 100644 --- a/src/m_Do/m_Do_graphic.cpp +++ b/src/m_Do/m_Do_graphic.cpp @@ -141,7 +141,7 @@ void dDlst_heapMap_c::draw() { f32 var_f29 = field_0x10 - field_0x8; f32 sp4C = field_0x14 - field_0xc; f32 sp48 = var_f29 * sp4C; - + uintptr_t start_addr = (uintptr_t)m_heap->getStartAddr(); uintptr_t end_addr = (uintptr_t)m_heap->getEndAddr(); u32 sp40 = end_addr - start_addr; @@ -156,7 +156,7 @@ void dDlst_heapMap_c::draw() { f32 var_f30 = (f32)sp38 * sp3C; uintptr_t sp34 = (uintptr_t)block - start_addr; f32 sp30 = (f32)sp34 * sp3C; - + f32 var_f28 = std::floor(sp30 / var_f29); f32 sp2C = sp30 - (var_f29 * var_f28); @@ -471,72 +471,32 @@ void darwFilter(GXColor matColor) { GXEnd(); } -#ifdef TARGET_PC -static void mDoGph_AdvanceFadeState() { - if (mDoGph_gInf_c::isFade() != 0) { - f32 fade_rate = mDoGph_gInf_c::getFadeRate() + mDoGph_gInf_c::getFadeSpeed(); - - if (fade_rate < 0.0f) { - fade_rate = 0.0f; - mDoGph_gInf_c::offFade(); - } else if (fade_rate > 1.0f) { - fade_rate = 1.0f; - } - - mDoGph_gInf_c::setFadeRate(fade_rate); - mDoGph_gInf_c::getFadeColor().a = 255.0f * fade_rate; - } else { - GXColor& fade_color = mDoGph_gInf_c::getFadeColor(); - if (dComIfG_getBrightness() != 255) { - fade_color.r = 0; - fade_color.g = 0; - fade_color.b = 0; - fade_color.a = 255 - dComIfG_getBrightness(); - } else { - fade_color.a = 0; - } - } -} - -static void mDoGph_AdvanceFadeState(u32 tick_count) { - for (u32 i = 0; i < tick_count; ++i) { - mDoGph_AdvanceFadeState(); - } -} - -static void mDoGph_DrawStoredFade() { - GXColor& fade_color = mDoGph_gInf_c::getFadeColor(); - if (fade_color.a != 0) { - darwFilter(fade_color); - } -} - void mDoGph_gInf_c::calcFade() { - mDoGph_AdvanceFadeState(); - mDoGph_DrawStoredFade(); -} -#else -void mDoGph_gInf_c::calcFade() { - if (mDoGph_gInf_c::mFade != 0) { - mFadeRate += mFadeSpeed; +#if TARGET_PC + if (dusk::frame_interp::get_ui_tick_pending()) +#endif + { + if (mFade != 0) { + mFadeRate += mFadeSpeed; - if (mFadeRate < 0.0f) { - mFadeRate = 0.0f; - mDoGph_gInf_c::mFade = 0; - } else { - if (mFadeRate > 1.0f) { - mFadeRate = 1.0f; + if (mFadeRate < 0.0f) { + mFadeRate = 0.0f; + mFade = 0; + } else { + if (mFadeRate > 1.0f) { + mFadeRate = 1.0f; + } } - } - mFadeColor.a = 255.0f * mFadeRate; - } else { - if (dComIfG_getBrightness() != 255) { - mFadeColor.r = 0; - mFadeColor.g = 0; - mFadeColor.b = 0; - mFadeColor.a = 255 - dComIfG_getBrightness(); + mFadeColor.a = 255.0f * mFadeRate; } else { - mFadeColor.a = 0; + if (dComIfG_getBrightness() != 255) { + mFadeColor.r = 0; + mFadeColor.g = 0; + mFadeColor.b = 0; + mFadeColor.a = 255 - dComIfG_getBrightness(); + } else { + mFadeColor.a = 0; + } } } @@ -544,7 +504,6 @@ void mDoGph_gInf_c::calcFade() { darwFilter(mFadeColor); } } -#endif #if PLATFORM_WII || PLATFORM_SHIELD u32 mDoGph_gInf_c::csr_c::m_blurID; @@ -603,21 +562,16 @@ struct tvSize { u16 width; u16 height; }; -const tvSize l_tvSize[2] = { +#ifndef TARGET_PC +const +#endif +tvSize l_tvSize[2] = { {FB_WIDTH_BASE, FB_HEIGHT_BASE}, {808, FB_HEIGHT_BASE}, }; -#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; @@ -644,21 +598,11 @@ void mDoGph_gInf_c::setTvSize() { #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; @@ -800,8 +744,11 @@ void mDoGph_gInf_c::updateSafeAreaBounds() { return; } + u32 renderWidth = 0; + u32 renderHeight = 0; + AuroraGetRenderSize(&renderWidth, &renderHeight); if (windowSize.native_fb_width == 0 || windowSize.native_fb_height == 0 || - windowSize.fb_width == 0 || windowSize.fb_height == 0) + renderWidth == 0 || renderHeight == 0) { return; } @@ -814,23 +761,25 @@ void mDoGph_gInf_c::updateSafeAreaBounds() { const f32 safeRight = static_cast(safeRect.x + safeRect.w) * nativeScaleX; const f32 safeBottom = static_cast(safeRect.y + safeRect.h) * nativeScaleY; - const f32 viewportLeft = - (static_cast(windowSize.native_fb_width) - static_cast(windowSize.fb_width)) * - 0.5f; - const f32 viewportTop = - (static_cast(windowSize.native_fb_height) - static_cast(windowSize.fb_height)) * - 0.5f; - const f32 viewportRight = viewportLeft + static_cast(windowSize.fb_width); - const f32 viewportBottom = viewportTop + static_cast(windowSize.fb_height); + f32 viewportWidth = static_cast(windowSize.native_fb_width); + f32 viewportHeight = static_cast(windowSize.native_fb_height); + const f32 targetAspect = viewportWidth / viewportHeight; + const f32 contentAspect = static_cast(renderWidth) / static_cast(renderHeight); + if (targetAspect > contentAspect) { + viewportWidth = std::max(1.0f, std::round(viewportHeight * contentAspect)); + } else if (targetAspect < contentAspect) { + viewportHeight = std::max(1.0f, std::round(viewportWidth / contentAspect)); + } - const f32 leftInset = std::max(0.0f, safeLeft - viewportLeft) * - (m_widthF / static_cast(windowSize.fb_width)); - const f32 topInset = std::max(0.0f, safeTop - viewportTop) * - (m_heightF / static_cast(windowSize.fb_height)); - const f32 rightInset = std::max(0.0f, viewportRight - safeRight) * - (m_widthF / static_cast(windowSize.fb_width)); - const f32 bottomInset = std::max(0.0f, viewportBottom - safeBottom) * - (m_heightF / static_cast(windowSize.fb_height)); + const f32 viewportLeft = (static_cast(windowSize.native_fb_width) - viewportWidth) * 0.5f; + const f32 viewportTop = (static_cast(windowSize.native_fb_height) - viewportHeight) * 0.5f; + const f32 viewportRight = viewportLeft + viewportWidth; + const f32 viewportBottom = viewportTop + viewportHeight; + + const f32 leftInset = std::max(0.0f, safeLeft - viewportLeft) * (m_widthF / viewportWidth); + const f32 topInset = std::max(0.0f, safeTop - viewportTop) * (m_heightF / viewportHeight); + const f32 rightInset = std::max(0.0f, viewportRight - safeRight) * (m_widthF / viewportWidth); + const f32 bottomInset = std::max(0.0f, viewportBottom - safeBottom) * (m_heightF / viewportHeight); const f32 safeMinXF = m_minXF + leftInset; const f32 safeMinYF = m_minYF + topInset; @@ -851,13 +800,13 @@ void mDoGph_gInf_c::updateSafeAreaBounds() { m_safeHeightF = safeHeightF; } -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); +void mDoGph_gInf_c::updateRenderSize() { + u32 width, height; + AuroraGetRenderSize(&width, &height); + JUTVideo::getManager()->setRenderSize(width, height); + l_tvSize[1].width = static_cast(static_cast(width) / static_cast(height) * + static_cast(l_tvSize[1].height)); + onWide(); } #endif @@ -954,9 +903,6 @@ int mDoGph_AfterOfDraw() { JUTVideo::getManager()->setRenderMode(mDoMch_render_c::getRenderModeObj()); mDoGph_gInf_c::endFrame(); -#ifdef TARGET_PC - dusk::frame_interp::notify_sim_tick_complete(); -#endif return 1; } @@ -996,7 +942,7 @@ static void drawDepth2(view_class* param_0, view_port_class* param_1, int param_ GXProject(param_0->lookat.center.x, param_0->lookat.center.y, param_0->lookat.center.z, param_0->viewMtx, sp4C, sp34, &sp1C, &sp18, &sp14); - + param_2 = (0xFF0000 - (int)(16777215.0f * sp14)) >> 8; param_2 = cLib_minMaxLimit(param_2, -0x400, 0); } @@ -1361,8 +1307,8 @@ void mDoGph_gInf_c::bloom_c::draw2() { if (mMonoColor.a == 0 && !enabled) return; - f32 width = mDoGph_gInf_c::getWidth(); - f32 height = mDoGph_gInf_c::getHeight(); + f32 width = JUTVideo::getManager()->getRenderWidth(); + f32 height = JUTVideo::getManager()->getRenderHeight(); GXLoadTexObj(getFrameBufferTexObj(), GX_TEXMAP0); GXSetNumChans(0); @@ -1446,7 +1392,7 @@ void mDoGph_gInf_c::bloom_c::draw2() { CopyToTexObj(&tmpTex[texNo], texNo, rect.w, rect.h); return &tmpTex[texNo]; }; - + auto divQuad = [&](int divNo) { auto const& rect = divRects[divNo]; f32 x0 = rect.x / width; @@ -1479,8 +1425,8 @@ void mDoGph_gInf_c::bloom_c::draw2() { } if (enabled) { - GXCreateFrameBuffer(width * 0.75f, height * 0.5f); - GXSetViewport(0.0f, 0.0f, width, height, 0.0f, 1.0f); // use oversized viewport to make the math easier + GXCreateFrameBuffer(divRects[2].x + divRects[2].w, divRects[1].y + divRects[1].h); + GXSetViewportRender(0.0f, 0.0f, width, height, 0.0f, 1.0f); // use oversized viewport to make the math easier GXSetNumTevStages(3); GXSetTevOrder(GX_TEVSTAGE0, GX_TEXCOORD0, GX_TEXMAP0, GX_COLOR_NULL); @@ -1517,7 +1463,7 @@ void mDoGph_gInf_c::bloom_c::draw2() { GXTexObj* texPass0 = divCopyTex(Pass0, 2); GXLoadTexObj(texPass0, GX_TEXMAP0); - f32 blurScale = mBlureSize * ((448.0f / getHeight()) / 6400.0f); + f32 blurScale = mBlureSize * ((448.0f / height) / 6400.0f); // Setup blur filter TEV. GXSetNumTexGens(8); @@ -1551,7 +1497,7 @@ void mDoGph_gInf_c::bloom_c::draw2() { // This is applied over two passes, the second one with an alpha of 25%; however, the clipping that this introduces is a bit integral to the look, // so we do the same thing, letting it clip. float brightnessF32 = (mBlureRatio * 16 / 255.0f); - + // Distribute the brightness through the total number of passes. f32 totalNumPasses = (divNum - divStart + 1); float brightnessPerPass = 255.0f * powf(brightnessF32, 1.0f / totalNumPasses); @@ -1623,13 +1569,8 @@ void mDoGph_gInf_c::bloom_c::draw() { bool enabled = mEnable && m_buffer != NULL; if (mMonoColor.a != 0 || enabled) { -#if TARGET_PC - f32 width = mDoGph_gInf_c::getWidth(); - f32 height = mDoGph_gInf_c::getHeight(); -#else f32 width = FB_WIDTH; f32 height = FB_HEIGHT; -#endif GXSetViewport(0.0f, 0.0f, width, height, 0.0f, 1.0f); GXSetScissor(0, 0, width, height); @@ -1744,7 +1685,7 @@ void mDoGph_gInf_c::bloom_c::draw() { GXSetTexCoordGen(GX_TEXCOORD0, GX_TG_MTX2x4, GX_TG_TEX0, GX_IDENTITY); for (int texCoord = (int)GX_TEXCOORD1; texCoord < (int)GX_MAX_TEXCOORD; texCoord++) { GXSetTexCoordGen((GXTexCoordID)texCoord, GX_TG_MTX2x4, GX_TG_TEX0, texMtxID); - + #if TARGET_PC f32 dVar15 = mBlureSize * ((448.0f / height) / 6400.0f); #else @@ -1885,7 +1826,7 @@ static void retry_captue_frame(view_class* param_0, view_port_class* param_1, in var_r23 = height >> 1; GXSetTexCopySrc(x_orig, y_orig_pos, width, height); #ifdef TARGET_PC - GXSetTexCopyDst(width, height, (GXTexFmt)mDoGph_gInf_c::getFrameBufferTimg()->format, GX_TRUE); + GXSetTexCopyDst(width, height, (GXTexFmt)mDoGph_gInf_c::getFrameBufferTimg()->format, GX_FALSE); #else GXSetTexCopyDst(var_r24, var_r23, (GXTexFmt)mDoGph_gInf_c::getFrameBufferTimg()->format, GX_TRUE); #endif @@ -2114,8 +2055,6 @@ int mDoGph_Painter() { #if TARGET_PC dusk::g_imguiConsole.PreDraw(); - - const u32 pending_ui_ticks = dusk::frame_interp::begin_presentation_ui_pass(); #endif #if DEBUG @@ -2123,7 +2062,7 @@ int mDoGph_Painter() { #endif #ifdef TARGET_PC - for (u32 i = 0; i < pending_ui_ticks; ++i) + if (dusk::frame_interp::get_ui_tick_pending()) #endif { dComIfGp_particle_calcMenu(); @@ -2143,8 +2082,7 @@ int mDoGph_Painter() { j3dSys.drawInit(); GXSetDither(GX_ENABLE); - J2DOrthoGraph ortho(0.0f, 0.0f, mDoGph_gInf_c::getWidth(), mDoGph_gInf_c::getHeight(), -1.0f, - 1.0f); + J2DOrthoGraph ortho(0.0f, 0.0f, FB_WIDTH, FB_HEIGHT, -1.0f, 1.0f); ortho.setOrtho(mDoGph_gInf_c::getMinXF(), mDoGph_gInf_c::getMinYF(), mDoGph_gInf_c::getWidthF(), mDoGph_gInf_c::getHeightF(), -1.0f, 1.0f); @@ -2190,13 +2128,8 @@ int mDoGph_Painter() { view_port_class new_port; new_port.x_orig = 0.0f; new_port.y_orig = 0.0f; - #if TARGET_PC - new_port.width = mDoGph_gInf_c::getWidth(); - new_port.height = mDoGph_gInf_c::getHeight(); - #else new_port.width = FB_WIDTH; new_port.height = FB_HEIGHT; - #endif new_port.near_z = view_port->near_z; new_port.far_z = view_port->far_z; new_port.scissor = view_port->scissor; @@ -2214,7 +2147,7 @@ int mDoGph_Painter() { view_port->height); #ifdef TARGET_PC - // Frame interpolation: Call setViewMtx earlier so that it's interpolated in time for draw_info to use it + // FRAME INTERP NOTE: Call setViewMtx earlier so that it's interpolated in time for draw_info to use it j3dSys.setViewMtx(camera_p->view.viewMtx); JPADrawInfo draw_info(j3dSys.getViewMtx(), camera_p->view.fovy, camera_p->view.aspect); #else @@ -2250,7 +2183,7 @@ int mDoGph_Painter() { dComIfGp_setCurrentView(&camera_p->view); dComIfGp_setCurrentViewport(view_port); GXSetProjection(camera_p->view.projMtx, GX_PERSPECTIVE); - + #if DEBUG captureScreenSetProjection(camera_p->view.projMtx); #endif @@ -2327,7 +2260,7 @@ int mDoGph_Painter() { #endif GX_DEBUG_GROUP(dComIfGd_drawOpaListPacket); - + #if DEBUG // "drawing up to special-use drawing (Opaque) except J3D (Rendering)" fapGm_HIO_c::stopCpuTimer("J3D以外などの特殊用(不透明)描画まで(レンダリング)"); @@ -2409,7 +2342,7 @@ int mDoGph_Painter() { GX_DEBUG_GROUP(dComIfGd_drawXluListInvisible); } } - + #if DEBUG // "drawing up to projection (Translucent)" @@ -2513,12 +2446,8 @@ int mDoGph_Painter() { retry_captue_frame(&camera_p->view, view_port, dComIfGp_getCameraZoomForcus(camera_id)); } - - #if TARGET_PC - GXSetViewport(0.0f, 0.0f, mDoGph_gInf_c::getWidth(), mDoGph_gInf_c::getHeight(), 0.0f, 1.0f); - #else + GXSetViewport(0.0f, 0.0f, FB_WIDTH, FB_HEIGHT, 0.0f, 1.0f); - #endif Mtx m2; Mtx44 m; @@ -2615,12 +2544,7 @@ int mDoGph_Painter() { if (strcmp(dComIfGp_getStartStageName(), "F_SP127") != 0 && (mDoGph_gInf_c::isFade() & 0x80) == 0) { -#ifdef TARGET_PC - mDoGph_AdvanceFadeState(pending_ui_ticks); - mDoGph_DrawStoredFade(); -#else mDoGph_gInf_c::calcFade(); -#endif } #if DEBUG @@ -2686,7 +2610,7 @@ int mDoGph_Painter() { GXSetClipMode(GX_CLIP_ENABLE); #if TARGET_PC - for (u32 i = 0; i < pending_ui_ticks; ++i) + if (dusk::frame_interp::get_ui_tick_pending()) #endif { dDlst_list_c::calcWipe(); @@ -2740,12 +2664,7 @@ int mDoGph_Painter() { if (strcmp(dComIfGp_getStartStageName(), "F_SP127") == 0 || (mDoGph_gInf_c::isFade() & 0x80) != 0) { -#ifdef TARGET_PC - mDoGph_AdvanceFadeState(pending_ui_ticks); - mDoGph_DrawStoredFade(); -#else mDoGph_gInf_c::calcFade(); -#endif } GX_DEBUG_GROUP(dComIfGp_particle_draw2DmenuFore, &draw_info3); @@ -2778,18 +2697,10 @@ int mDoGph_Painter() { #if TARGET_PC dusk::g_imguiConsole.PostDraw(); - - if (dusk::getSettings().game.enableFrameInterpolation) { - JFWDisplay::getManager()->setFaderSimSteps(pending_ui_ticks); - } #endif mDoGph_gInf_c::endRender(); -#ifdef TARGET_PC - dusk::frame_interp::end_presentation_ui_pass(); -#endif - #if WIDESCREEN_SUPPORT mDoGph_gInf_c::offWideZoom(); #endif diff --git a/src/m_Do/m_Do_lib.cpp b/src/m_Do/m_Do_lib.cpp index b541490353..921681d464 100644 --- a/src/m_Do/m_Do_lib.cpp +++ b/src/m_Do/m_Do_lib.cpp @@ -95,8 +95,13 @@ void mDoLib_project(Vec* src, Vec* dst) { xOffset = (0.5f * ((2.0f * viewPort->x_orig) + viewPort->width)) - (int)(FB_WIDTH / 2); xSize = FB_WIDTH; } else { +#if TARGET_PC + xOffset = mDoGph_gInf_c::getSafeMinXF(); + xSize = viewPort->width * mDoGph_gInf_c::hudAspectScaleUp; +#else xOffset = viewPort->x_orig; xSize = viewPort->width; +#endif } if (viewPort->y_orig != 0.0f) { @@ -108,73 +113,15 @@ void mDoLib_project(Vec* src, Vec* dst) { } dst->x = ((0.5f + (multVec.x * calcFloat)) * xSize) + xOffset; + #if TARGET_PC + if (dusk::getSettings().game.enableMirrorMode) { + dst->x = ((0.5f + (-multVec.x * calcFloat)) * xSize) + xOffset; + } + #endif + dst->y = ((0.5f + (multVec.y * (-calcFloat))) * ySize) + yOffset; } - -#if TARGET_PC -void mDoLib_project(Vec* src, Vec* dst, JGeometry::TBox2 viewport) { - if (dComIfGd_getView() == NULL) { - dst->x = 0.0f; - dst->y = 0.0f; - dst->z = 0.0f; - return; - } - - { int unused; } - - Vec multVec; - cMtx_multVec(*dComIfGd_getProjViewMtx(), src, &multVec); - - f32 calcFloat = (src->x * (*dComIfGd_getProjViewMtx())[3][0]) + - (src->y * (*dComIfGd_getProjViewMtx())[3][1]) + - (src->z * (*dComIfGd_getProjViewMtx())[3][2]) + - (*dComIfGd_getProjViewMtx())[3][3]; - if (multVec.z >= 0.0f) { - multVec.z = 0.0f; - } - if (calcFloat <= 0.0f) { - if (calcFloat == 0.0f) { - dst->z = multVec.z * 500000.0f; - } else { - dst->z = multVec.z * (0.5f / calcFloat); - } - calcFloat = 500000.0f; - } else { - calcFloat = 0.5f / calcFloat; - dst->z = multVec.z * calcFloat; - } - - f32 xOffset; - f32 yOffset; - f32 xSize; - f32 ySize; - if (viewport.i.x != 0.0f) { - xOffset = (0.5f * ((2.0f * viewport.i.x) + viewport.f.x)) - (int)(FB_WIDTH / 2); - xSize = FB_WIDTH; - } else { - #if TARGET_PC - xOffset = mDoGph_gInf_c::getSafeMinXF(); - xSize = viewport.f.x * mDoGph_gInf_c::hudAspectScaleUp; - #else - xOffset = viewport.i.x; - xSize = viewport.f.x; - #endif - } - - if (viewport.i.y != 0.0f) { - yOffset = (0.5f * ((2.0f * viewport.i.y) + viewport.f.y)) - (int)(FB_HEIGHT / 2); - ySize = FB_HEIGHT; - } else { - yOffset = viewport.i.y; - ySize = viewport.f.y; - } - - dst->x = ((0.5f + (multVec.x * calcFloat)) * xSize) + xOffset; - dst->y = ((0.5f + (multVec.y * (-calcFloat))) * ySize) + yOffset; -} -#endif - void mDoLib_pos2camera(Vec* src, Vec* dst) { if (dComIfGd_getView() == NULL) { dst->x = 0.0f; diff --git a/src/m_Do/m_Do_main.cpp b/src/m_Do/m_Do_main.cpp index 784aea3f26..c597ad2804 100644 --- a/src/m_Do/m_Do_main.cpp +++ b/src/m_Do/m_Do_main.cpp @@ -42,7 +42,6 @@ #include "SSystem/SComponent/c_counter.h" #include -#include #include #include #include @@ -51,6 +50,7 @@ #include "dusk/crash_reporting.h" #include "dusk/dusk.h" #include "dusk/frame_interpolation.h" +#include "dusk/game_clock.h" #include "dusk/gyro.h" #include "dusk/imgui/ImGuiEngine.hpp" #include "dusk/logging.h" @@ -68,8 +68,11 @@ #include "cxxopts.hpp" #include "dusk/audio/DuskAudioSystem.h" #include "dusk/config.hpp" +#include "dusk/settings.h" #include "dusk/imgui/ImGuiConsole.hpp" +#include "dusk/discord_presence.hpp" #include "tracy/Tracy.hpp" +#include "f_pc/f_pc_draw.h" // --- GLOBALS --- s8 mDoMain::developmentMode = -1; @@ -92,6 +95,7 @@ const int audioHeapSize = 0x14D800; bool dusk::IsRunning = true; bool dusk::IsShuttingDown = false; bool dusk::IsGameLaunched = false; +bool dusk::IsFocusPaused = false; #endif s32 LOAD_COPYDATE(void*) { @@ -126,8 +130,6 @@ AuroraStats dusk::lastFrameAuroraStats; float dusk::frameUsagePct = 0.0f; const char* configPath; -AuroraWindowSize preLaunchUIWindowSize; - bool launchUILoop() { while (dusk::IsRunning && !dusk::IsGameLaunched) { const AuroraEvent* event = aurora_update(); @@ -136,9 +138,6 @@ bool launchUILoop() { case AURORA_SDL_EVENT: dusk::g_imguiConsole.HandleSDLEvent(event->sdl); break; - case AURORA_WINDOW_RESIZED: - preLaunchUIWindowSize = event->windowSize; - break; case AURORA_DISPLAY_SCALE_CHANGED: dusk::ImGuiEngine_Initialize(event->windowSize.scale); break; @@ -202,12 +201,7 @@ void main01(void) { OSReport("Entering Main Loop (main01)...\n"); - if (preLaunchUIWindowSize.width != 0) - mDoGph_gInf_c::setWindowSize(preLaunchUIWindowSize); - - constexpr float kSimStepSeconds = 1.0 / 30.0; - auto previous_time = std::chrono::steady_clock::now(); - float accumulator = kSimStepSeconds; + dusk::game_clock::ensure_initialized(); do { // 1. Update Window Events @@ -218,9 +212,16 @@ void main01(void) { goto eventsDone; case AURORA_SDL_EVENT: dusk::g_imguiConsole.HandleSDLEvent(event->sdl); - break; - case AURORA_WINDOW_RESIZED: - mDoGph_gInf_c::setWindowSize(event->windowSize); + if (event->sdl.type == SDL_EVENT_WINDOW_FOCUS_LOST && + dusk::getSettings().game.pauseOnFocusLost) { + dusk::IsFocusPaused = true; + dusk::audio::SetPaused(true); + } else if (event->sdl.type == SDL_EVENT_WINDOW_FOCUS_GAINED && + dusk::IsFocusPaused) { + dusk::IsFocusPaused = false; + dusk::audio::SetPaused(false); + dusk::game_clock::reset_frame_timer(); + } break; case AURORA_DISPLAY_SCALE_CHANGED: dusk::ImGuiEngine_Initialize(event->windowSize.scale); @@ -234,10 +235,12 @@ void main01(void) { eventsDone:; - auto current_time = std::chrono::steady_clock::now(); - float frame_seconds = std::chrono::duration(current_time - previous_time).count(); - previous_time = current_time; - accumulator += frame_seconds; + if (dusk::IsFocusPaused) { + std::this_thread::sleep_for(std::chrono::milliseconds(16)); + continue; + } + + const dusk::game_clock::MainLoopPacer pacing = dusk::game_clock::advance_main_loop(); VIWaitForRetrace(); @@ -247,26 +250,35 @@ void main01(void) { continue; } - if (dusk::getSettings().game.enableFrameInterpolation && !dusk::getTransientSettings().skipFrameRateLimit) { - dusk::frame_interp::notify_presentation_frame(); - if (accumulator >= kSimStepSeconds) { + mDoGph_gInf_c::updateRenderSize(); + + dusk::frame_interp::begin_frame(pacing.is_interpolating, pacing.do_sim_tick, pacing.interpolation_step); + if (pacing.is_interpolating) { + if (pacing.do_sim_tick) { + dusk::frame_interp::set_ui_tick_pending(true); mDoCPd_c::read(); - dusk::gyro::read(kSimStepSeconds); + DuskDebugPad(); + dusk::gyro::read(pacing.sim_pace); fapGm_Execute(); mDoAud_Execute(); - accumulator = 0.0f; + dusk::game_clock::reset_accumulator(); } - dusk::frame_interp::interpolate(static_cast(accumulator / kSimStepSeconds)); - { - dusk::frame_interp::PresentationCameraScope presentation_camera; - cAPIGph_Painter(); + dusk::frame_interp::interpolate(); + dusk::frame_interp::begin_presentation_camera(); + if (!pacing.do_sim_tick) { + // run draw functions for anything specially marked to handle interp on non-sim + // ticks + fpcM_DrawIterater((fpcM_DrawIteraterFunc)fpcM_Draw); } + cAPIGph_Painter(); + dusk::frame_interp::end_presentation_camera(); + dusk::frame_interp::set_ui_tick_pending(false); } else { - accumulator = 0.0f; - + dusk::frame_interp::set_ui_tick_pending(true); + // Game Inputs mDoCPd_c::read(); - dusk::gyro::read(frame_seconds); + dusk::gyro::read(pacing.presentation_dt_seconds); // EXECUTE GAME LOGIC & RENDER // This calls mDoGph_Painter -> JFWDisplay -> GX Functions @@ -278,6 +290,11 @@ void main01(void) { aurora_end_frame(); FrameMark; + +#ifdef DUSK_DISCORD_RPC + dusk::discord::RunCallbacks(); + dusk::discord::UpdatePresence(); +#endif } while (dusk::IsRunning); exit:; @@ -520,15 +537,20 @@ int game_main(int argc, char* argv[]) { auroraInfo = aurora_initialize(argc, argv, &config); +#ifdef DUSK_DISCORD_RPC + dusk::discord::Initialize(); +#endif + VISetWindowTitle( fmt::format("Dusk {} [{}]", DUSK_WC_DESCRIBE, dusk::backend_name(auroraInfo.backend)) .c_str()); if (dusk::getSettings().video.lockAspectRatio) { - VILockAspectRatio(defaultAspectRatioW, defaultAspectRatioH); + AuroraSetViewportPolicy(AURORA_VIEWPORT_FIT); } else { - VIUnlockAspectRatio(); + AuroraSetViewportPolicy(AURORA_VIEWPORT_STRETCH); } + VISetFrameBufferScale(dusk::getSettings().game.internalResolutionScale.getValue()); dusk::audio::SetMasterVolume(dusk::getSettings().audio.masterVolume / 100.0f); dusk::audio::SetEnableReverb(dusk::getSettings().audio.enableReverb); @@ -552,6 +574,9 @@ int game_main(int argc, char* argv[]) { // pre game launch ui main loop if (!launchUILoop()) { dusk::ShutdownCrashReporting(); +#ifdef DUSK_DISCORD_RPC + dusk::discord::Shutdown(); +#endif aurora_shutdown(); return 0; } @@ -599,6 +624,9 @@ int game_main(int argc, char* argv[]) { // Notifies all CVs and causes threads to exit OSResetSystem(OS_RESET_SHUTDOWN, 0, 0); +#ifdef DUSK_DISCORD_RPC + dusk::discord::Shutdown(); +#endif aurora_shutdown(); return 0;