diff --git a/MarathonRecomp/CMakeLists.txt b/MarathonRecomp/CMakeLists.txt index d59de3160..93c350c24 100644 --- a/MarathonRecomp/CMakeLists.txt +++ b/MarathonRecomp/CMakeLists.txt @@ -140,9 +140,11 @@ set(MARATHON_RECOMP_PATCHES_CXX_SOURCES "patches/camera_patches.cpp" "patches/fps_patches.cpp" "patches/frontend_listener.cpp" + "patches/input_patches.cpp" "patches/loading_patches.cpp" "patches/MainMenuTask_patches.cpp" "patches/misc_patches.cpp" + "patches/pause_patches.cpp" "patches/player_patches.cpp" "patches/SaveDataTask_patches.cpp" "patches/text_patches.cpp" @@ -154,15 +156,14 @@ set(MARATHON_RECOMP_UI_CXX_SOURCES "ui/achievement_menu.cpp" "ui/achievement_overlay.cpp" "ui/black_bar.cpp" - "ui/button_guide.cpp" + "ui/button_window.cpp" + "ui/common_menu.cpp" "ui/fader.cpp" "ui/game_window.cpp" "ui/imgui_utils.cpp" "ui/installer_wizard.cpp" "ui/message_window.cpp" "ui/options_menu.cpp" - "ui/options_menu_thumbnails.cpp" - "ui/tv_static.cpp" ) set(MARATHON_RECOMP_INSTALL_CXX_SOURCES @@ -538,13 +539,14 @@ BIN2C(TARGET_OBJ MarathonRecomp SOURCE_FILE "${RESOURCES_SOURCE_PATH}/bc_diff/bu BIN2C(TARGET_OBJ MarathonRecomp SOURCE_FILE "${RESOURCES_SOURCE_PATH}/font/im_font_atlas.bin" DEST_FILE "${RESOURCES_OUTPUT_PATH}/font/im_font_atlas.bin" ARRAY_NAME "g_im_font_atlas" COMPRESSION_TYPE "zstd") BIN2C(TARGET_OBJ MarathonRecomp SOURCE_FILE "${RESOURCES_SOURCE_PATH}/font/im_font_atlas.dds" DEST_FILE "${RESOURCES_OUTPUT_PATH}/font/im_font_atlas.dds" ARRAY_NAME "g_im_font_atlas_texture" COMPRESSION_TYPE "zstd") BIN2C(TARGET_OBJ MarathonRecomp SOURCE_FILE "${RESOURCES_SOURCE_PATH}/images/achievements_menu/trophy.dds" DEST_FILE "${RESOURCES_OUTPUT_PATH}/images/achievements_menu/trophy.dds" ARRAY_NAME "g_trophy" COMPRESSION_TYPE "zstd") +BIN2C(TARGET_OBJ MarathonRecomp SOURCE_FILE "${RESOURCES_SOURCE_PATH}/images/common/button_window.dds" DEST_FILE "${RESOURCES_OUTPUT_PATH}/images/common/button_window.dds" ARRAY_NAME "g_button_window" COMPRESSION_TYPE "zstd") BIN2C(TARGET_OBJ MarathonRecomp SOURCE_FILE "${RESOURCES_SOURCE_PATH}/images/common/controller.dds" DEST_FILE "${RESOURCES_OUTPUT_PATH}/images/common/controller.dds" ARRAY_NAME "g_controller" COMPRESSION_TYPE "zstd") -BIN2C(TARGET_OBJ MarathonRecomp SOURCE_FILE "${RESOURCES_SOURCE_PATH}/images/common/general_window.dds" DEST_FILE "${RESOURCES_OUTPUT_PATH}/images/common/general_window.dds" ARRAY_NAME "g_general_window" COMPRESSION_TYPE "zstd") -BIN2C(TARGET_OBJ MarathonRecomp SOURCE_FILE "${RESOURCES_SOURCE_PATH}/images/common/hedge-dev.dds" DEST_FILE "${RESOURCES_OUTPUT_PATH}/images/common/hedge-dev.dds" ARRAY_NAME "g_hedgedev" COMPRESSION_TYPE "zstd") +BIN2C(TARGET_OBJ MarathonRecomp SOURCE_FILE "${RESOURCES_SOURCE_PATH}/images/common/sonicnext-dev.dds" DEST_FILE "${RESOURCES_OUTPUT_PATH}/images/common/sonicnext-dev.dds" ARRAY_NAME "g_sonicnextdev" COMPRESSION_TYPE "zstd") BIN2C(TARGET_OBJ MarathonRecomp SOURCE_FILE "${RESOURCES_SOURCE_PATH}/images/common/kbm.dds" DEST_FILE "${RESOURCES_OUTPUT_PATH}/images/common/kbm.dds" ARRAY_NAME "g_kbm" COMPRESSION_TYPE "zstd") -BIN2C(TARGET_OBJ MarathonRecomp SOURCE_FILE "${RESOURCES_SOURCE_PATH}/images/common/select.dds" DEST_FILE "${RESOURCES_OUTPUT_PATH}/images/common/select.dds" ARRAY_NAME "g_select" COMPRESSION_TYPE "zstd") -BIN2C(TARGET_OBJ MarathonRecomp SOURCE_FILE "${RESOURCES_SOURCE_PATH}/images/common/light.dds" DEST_FILE "${RESOURCES_OUTPUT_PATH}/images/common/light.dds" ARRAY_NAME "g_light" COMPRESSION_TYPE "zstd") BIN2C(TARGET_OBJ MarathonRecomp SOURCE_FILE "${RESOURCES_SOURCE_PATH}/images/common/main_menu1.dds" DEST_FILE "${RESOURCES_OUTPUT_PATH}/images/common/main_menu1.dds" ARRAY_NAME "g_main_menu1" COMPRESSION_TYPE "zstd") +BIN2C(TARGET_OBJ MarathonRecomp SOURCE_FILE "${RESOURCES_SOURCE_PATH}/images/common/main_menu7.dds" DEST_FILE "${RESOURCES_OUTPUT_PATH}/images/common/main_menu7.dds" ARRAY_NAME "g_main_menu7" COMPRESSION_TYPE "zstd") +BIN2C(TARGET_OBJ MarathonRecomp SOURCE_FILE "${RESOURCES_SOURCE_PATH}/images/common/main_menu8.dds" DEST_FILE "${RESOURCES_OUTPUT_PATH}/images/common/main_menu8.dds" ARRAY_NAME "g_main_menu8" COMPRESSION_TYPE "zstd") +BIN2C(TARGET_OBJ MarathonRecomp SOURCE_FILE "${RESOURCES_SOURCE_PATH}/images/common/main_menu9.dds" DEST_FILE "${RESOURCES_OUTPUT_PATH}/images/common/main_menu9.dds" ARRAY_NAME "g_main_menu9" COMPRESSION_TYPE "zstd") BIN2C(TARGET_OBJ MarathonRecomp SOURCE_FILE "${RESOURCES_SOURCE_PATH}/images/common/arrow.dds" DEST_FILE "${RESOURCES_OUTPUT_PATH}/images/common/arrow.dds" ARRAY_NAME "g_arrow" COMPRESSION_TYPE "zstd") BIN2C(TARGET_OBJ MarathonRecomp SOURCE_FILE "${RESOURCES_SOURCE_PATH}/images/common/window.dds" DEST_FILE "${RESOURCES_OUTPUT_PATH}/images/common/window.dds" ARRAY_NAME "g_window" COMPRESSION_TYPE "zstd") BIN2C(TARGET_OBJ MarathonRecomp SOURCE_FILE "${RESOURCES_SOURCE_PATH}/images/common/select_arrow.dds" DEST_FILE "${RESOURCES_OUTPUT_PATH}/images/common/select_arrow.dds" ARRAY_NAME "g_select_arrow" COMPRESSION_TYPE "zstd") @@ -559,56 +561,6 @@ BIN2C(TARGET_OBJ MarathonRecomp SOURCE_FILE "${RESOURCES_SOURCE_PATH}/images/ins BIN2C(TARGET_OBJ MarathonRecomp SOURCE_FILE "${RESOURCES_SOURCE_PATH}/images/installer/install_007.dds" DEST_FILE "${RESOURCES_OUTPUT_PATH}/images/installer/install_007.dds" ARRAY_NAME "g_install_007" COMPRESSION_TYPE "zstd") BIN2C(TARGET_OBJ MarathonRecomp SOURCE_FILE "${RESOURCES_SOURCE_PATH}/images/installer/install_008.dds" DEST_FILE "${RESOURCES_OUTPUT_PATH}/images/installer/install_008.dds" ARRAY_NAME "g_install_008" COMPRESSION_TYPE "zstd") -## Options Menu ## -BIN2C(TARGET_OBJ MarathonRecomp SOURCE_FILE "${RESOURCES_SOURCE_PATH}/images/options_menu/thumbnails/achievement_notifications.dds" DEST_FILE "${RESOURCES_OUTPUT_PATH}/images/options_menu/thumbnails/achievement_notifications.dds" ARRAY_NAME "g_achievement_notifications" COMPRESSION_TYPE "zstd") -BIN2C(TARGET_OBJ MarathonRecomp SOURCE_FILE "${RESOURCES_SOURCE_PATH}/images/options_menu/thumbnails/allow_background_input_ps.dds" DEST_FILE "${RESOURCES_OUTPUT_PATH}/images/options_menu/thumbnails/allow_background_input_ps.dds" ARRAY_NAME "g_allow_background_input_ps" COMPRESSION_TYPE "zstd") -BIN2C(TARGET_OBJ MarathonRecomp SOURCE_FILE "${RESOURCES_SOURCE_PATH}/images/options_menu/thumbnails/allow_background_input_xb.dds" DEST_FILE "${RESOURCES_OUTPUT_PATH}/images/options_menu/thumbnails/allow_background_input_xb.dds" ARRAY_NAME "g_allow_background_input_xb" COMPRESSION_TYPE "zstd") -BIN2C(TARGET_OBJ MarathonRecomp SOURCE_FILE "${RESOURCES_SOURCE_PATH}/images/options_menu/thumbnails/antialiasing_none.dds" DEST_FILE "${RESOURCES_OUTPUT_PATH}/images/options_menu/thumbnails/antialiasing_none.dds" ARRAY_NAME "g_antialiasing_none" COMPRESSION_TYPE "zstd") -BIN2C(TARGET_OBJ MarathonRecomp SOURCE_FILE "${RESOURCES_SOURCE_PATH}/images/options_menu/thumbnails/antialiasing_2x.dds" DEST_FILE "${RESOURCES_OUTPUT_PATH}/images/options_menu/thumbnails/antialiasing_2x.dds" ARRAY_NAME "g_antialiasing_2x" COMPRESSION_TYPE "zstd") -BIN2C(TARGET_OBJ MarathonRecomp SOURCE_FILE "${RESOURCES_SOURCE_PATH}/images/options_menu/thumbnails/antialiasing_4x.dds" DEST_FILE "${RESOURCES_OUTPUT_PATH}/images/options_menu/thumbnails/antialiasing_4x.dds" ARRAY_NAME "g_antialiasing_4x" COMPRESSION_TYPE "zstd") -BIN2C(TARGET_OBJ MarathonRecomp SOURCE_FILE "${RESOURCES_SOURCE_PATH}/images/options_menu/thumbnails/antialiasing_8x.dds" DEST_FILE "${RESOURCES_OUTPUT_PATH}/images/options_menu/thumbnails/antialiasing_8x.dds" ARRAY_NAME "g_antialiasing_8x" COMPRESSION_TYPE "zstd") -BIN2C(TARGET_OBJ MarathonRecomp SOURCE_FILE "${RESOURCES_SOURCE_PATH}/images/options_menu/thumbnails/aspect_ratio.dds" DEST_FILE "${RESOURCES_OUTPUT_PATH}/images/options_menu/thumbnails/aspect_ratio.dds" ARRAY_NAME "g_aspect_ratio" COMPRESSION_TYPE "zstd") -BIN2C(TARGET_OBJ MarathonRecomp SOURCE_FILE "${RESOURCES_SOURCE_PATH}/images/options_menu/thumbnails/brightness.dds" DEST_FILE "${RESOURCES_OUTPUT_PATH}/images/options_menu/thumbnails/brightness.dds" ARRAY_NAME "g_brightness" COMPRESSION_TYPE "zstd") -BIN2C(TARGET_OBJ MarathonRecomp SOURCE_FILE "${RESOURCES_SOURCE_PATH}/images/options_menu/thumbnails/channel_stereo.dds" DEST_FILE "${RESOURCES_OUTPUT_PATH}/images/options_menu/thumbnails/channel_stereo.dds" ARRAY_NAME "g_channel_stereo" COMPRESSION_TYPE "zstd") -BIN2C(TARGET_OBJ MarathonRecomp SOURCE_FILE "${RESOURCES_SOURCE_PATH}/images/options_menu/thumbnails/channel_surround.dds" DEST_FILE "${RESOURCES_OUTPUT_PATH}/images/options_menu/thumbnails/channel_surround.dds" ARRAY_NAME "g_channel_surround" COMPRESSION_TYPE "zstd") -BIN2C(TARGET_OBJ MarathonRecomp SOURCE_FILE "${RESOURCES_SOURCE_PATH}/images/options_menu/thumbnails/control_tutorial_ps.dds" DEST_FILE "${RESOURCES_OUTPUT_PATH}/images/options_menu/thumbnails/control_tutorial_ps.dds" ARRAY_NAME "g_control_tutorial_ps" COMPRESSION_TYPE "zstd") -BIN2C(TARGET_OBJ MarathonRecomp SOURCE_FILE "${RESOURCES_SOURCE_PATH}/images/options_menu/thumbnails/control_tutorial_xb.dds" DEST_FILE "${RESOURCES_OUTPUT_PATH}/images/options_menu/thumbnails/control_tutorial_xb.dds" ARRAY_NAME "g_control_tutorial_xb" COMPRESSION_TYPE "zstd") -BIN2C(TARGET_OBJ MarathonRecomp SOURCE_FILE "${RESOURCES_SOURCE_PATH}/images/options_menu/thumbnails/controller_icons.dds" DEST_FILE "${RESOURCES_OUTPUT_PATH}/images/options_menu/thumbnails/controller_icons.dds" ARRAY_NAME "g_controller_icons" COMPRESSION_TYPE "zstd") -BIN2C(TARGET_OBJ MarathonRecomp SOURCE_FILE "${RESOURCES_SOURCE_PATH}/images/options_menu/thumbnails/default.dds" DEST_FILE "${RESOURCES_OUTPUT_PATH}/images/options_menu/thumbnails/default.dds" ARRAY_NAME "g_default" COMPRESSION_TYPE "zstd") -BIN2C(TARGET_OBJ MarathonRecomp SOURCE_FILE "${RESOURCES_SOURCE_PATH}/images/options_menu/thumbnails/effects_volume.dds" DEST_FILE "${RESOURCES_OUTPUT_PATH}/images/options_menu/thumbnails/effects_volume.dds" ARRAY_NAME "g_effects_volume" COMPRESSION_TYPE "zstd") -BIN2C(TARGET_OBJ MarathonRecomp SOURCE_FILE "${RESOURCES_SOURCE_PATH}/images/options_menu/thumbnails/fps.dds" DEST_FILE "${RESOURCES_OUTPUT_PATH}/images/options_menu/thumbnails/fps.dds" ARRAY_NAME "g_fps" COMPRESSION_TYPE "zstd") -BIN2C(TARGET_OBJ MarathonRecomp SOURCE_FILE "${RESOURCES_SOURCE_PATH}/images/options_menu/thumbnails/fullscreen.dds" DEST_FILE "${RESOURCES_OUTPUT_PATH}/images/options_menu/thumbnails/fullscreen.dds" ARRAY_NAME "g_fullscreen" COMPRESSION_TYPE "zstd") -BIN2C(TARGET_OBJ MarathonRecomp SOURCE_FILE "${RESOURCES_SOURCE_PATH}/images/options_menu/thumbnails/csm_texture_filtering_bilinear.dds" DEST_FILE "${RESOURCES_OUTPUT_PATH}/images/options_menu/thumbnails/csm_texture_filtering_bilinear.dds" ARRAY_NAME "g_csm_texture_filtering_bilinear" COMPRESSION_TYPE "zstd") -BIN2C(TARGET_OBJ MarathonRecomp SOURCE_FILE "${RESOURCES_SOURCE_PATH}/images/options_menu/thumbnails/csm_texture_filtering_bicubic.dds" DEST_FILE "${RESOURCES_OUTPUT_PATH}/images/options_menu/thumbnails/csm_texture_filtering_bicubic.dds" ARRAY_NAME "g_csm_texture_filtering_bicubic" COMPRESSION_TYPE "zstd") -BIN2C(TARGET_OBJ MarathonRecomp SOURCE_FILE "${RESOURCES_SOURCE_PATH}/images/options_menu/thumbnails/hints.dds" DEST_FILE "${RESOURCES_OUTPUT_PATH}/images/options_menu/thumbnails/hints.dds" ARRAY_NAME "g_hints" COMPRESSION_TYPE "zstd") -BIN2C(TARGET_OBJ MarathonRecomp SOURCE_FILE "${RESOURCES_SOURCE_PATH}/images/options_menu/thumbnails/horizontal_camera.dds" DEST_FILE "${RESOURCES_OUTPUT_PATH}/images/options_menu/thumbnails/horizontal_camera.dds" ARRAY_NAME "g_horizontal_camera" COMPRESSION_TYPE "zstd") -BIN2C(TARGET_OBJ MarathonRecomp SOURCE_FILE "${RESOURCES_SOURCE_PATH}/images/options_menu/thumbnails/language.dds" DEST_FILE "${RESOURCES_OUTPUT_PATH}/images/options_menu/thumbnails/language.dds" ARRAY_NAME "g_language" COMPRESSION_TYPE "zstd") -BIN2C(TARGET_OBJ MarathonRecomp SOURCE_FILE "${RESOURCES_SOURCE_PATH}/images/options_menu/thumbnails/master_volume.dds" DEST_FILE "${RESOURCES_OUTPUT_PATH}/images/options_menu/thumbnails/master_volume.dds" ARRAY_NAME "g_master_volume" COMPRESSION_TYPE "zstd") -BIN2C(TARGET_OBJ MarathonRecomp SOURCE_FILE "${RESOURCES_SOURCE_PATH}/images/options_menu/thumbnails/monitor.dds" DEST_FILE "${RESOURCES_OUTPUT_PATH}/images/options_menu/thumbnails/monitor.dds" ARRAY_NAME "g_monitor" COMPRESSION_TYPE "zstd") -BIN2C(TARGET_OBJ MarathonRecomp SOURCE_FILE "${RESOURCES_SOURCE_PATH}/images/options_menu/thumbnails/movie_scale_fit.dds" DEST_FILE "${RESOURCES_OUTPUT_PATH}/images/options_menu/thumbnails/movie_scale_fit.dds" ARRAY_NAME "g_movie_scale_fit" COMPRESSION_TYPE "zstd") -BIN2C(TARGET_OBJ MarathonRecomp SOURCE_FILE "${RESOURCES_SOURCE_PATH}/images/options_menu/thumbnails/movie_scale_fill.dds" DEST_FILE "${RESOURCES_OUTPUT_PATH}/images/options_menu/thumbnails/movie_scale_fill.dds" ARRAY_NAME "g_movie_scale_fill" COMPRESSION_TYPE "zstd") -BIN2C(TARGET_OBJ MarathonRecomp SOURCE_FILE "${RESOURCES_SOURCE_PATH}/images/options_menu/thumbnails/music_attenuation.dds" DEST_FILE "${RESOURCES_OUTPUT_PATH}/images/options_menu/thumbnails/music_attenuation.dds" ARRAY_NAME "g_music_attenuation" COMPRESSION_TYPE "zstd") -BIN2C(TARGET_OBJ MarathonRecomp SOURCE_FILE "${RESOURCES_SOURCE_PATH}/images/options_menu/thumbnails/music_volume.dds" DEST_FILE "${RESOURCES_OUTPUT_PATH}/images/options_menu/thumbnails/music_volume.dds" ARRAY_NAME "g_music_volume" COMPRESSION_TYPE "zstd") -BIN2C(TARGET_OBJ MarathonRecomp SOURCE_FILE "${RESOURCES_SOURCE_PATH}/images/options_menu/thumbnails/shadow_resolution_x512.dds" DEST_FILE "${RESOURCES_OUTPUT_PATH}/images/options_menu/thumbnails/shadow_resolution_x512.dds" ARRAY_NAME "g_shadow_resolution_x512" COMPRESSION_TYPE "zstd") -BIN2C(TARGET_OBJ MarathonRecomp SOURCE_FILE "${RESOURCES_SOURCE_PATH}/images/options_menu/thumbnails/shadow_resolution_x1024.dds" DEST_FILE "${RESOURCES_OUTPUT_PATH}/images/options_menu/thumbnails/shadow_resolution_x1024.dds" ARRAY_NAME "g_shadow_resolution_x1024" COMPRESSION_TYPE "zstd") -BIN2C(TARGET_OBJ MarathonRecomp SOURCE_FILE "${RESOURCES_SOURCE_PATH}/images/options_menu/thumbnails/shadow_resolution_x2048.dds" DEST_FILE "${RESOURCES_OUTPUT_PATH}/images/options_menu/thumbnails/shadow_resolution_x2048.dds" ARRAY_NAME "g_shadow_resolution_x2048" COMPRESSION_TYPE "zstd") -BIN2C(TARGET_OBJ MarathonRecomp SOURCE_FILE "${RESOURCES_SOURCE_PATH}/images/options_menu/thumbnails/shadow_resolution_x4096.dds" DEST_FILE "${RESOURCES_OUTPUT_PATH}/images/options_menu/thumbnails/shadow_resolution_x4096.dds" ARRAY_NAME "g_shadow_resolution_x4096" COMPRESSION_TYPE "zstd") -BIN2C(TARGET_OBJ MarathonRecomp SOURCE_FILE "${RESOURCES_SOURCE_PATH}/images/options_menu/thumbnails/shadow_resolution_x8192.dds" DEST_FILE "${RESOURCES_OUTPUT_PATH}/images/options_menu/thumbnails/shadow_resolution_x8192.dds" ARRAY_NAME "g_shadow_resolution_x8192" COMPRESSION_TYPE "zstd") -BIN2C(TARGET_OBJ MarathonRecomp SOURCE_FILE "${RESOURCES_SOURCE_PATH}/images/options_menu/thumbnails/transparency_antialiasing_false.dds" DEST_FILE "${RESOURCES_OUTPUT_PATH}/images/options_menu/thumbnails/transparency_antialiasing_false.dds" ARRAY_NAME "g_transparency_antialiasing_false" COMPRESSION_TYPE "zstd") -BIN2C(TARGET_OBJ MarathonRecomp SOURCE_FILE "${RESOURCES_SOURCE_PATH}/images/options_menu/thumbnails/transparency_antialiasing_true.dds" DEST_FILE "${RESOURCES_OUTPUT_PATH}/images/options_menu/thumbnails/transparency_antialiasing_true.dds" ARRAY_NAME "g_transparency_antialiasing_true" COMPRESSION_TYPE "zstd") -BIN2C(TARGET_OBJ MarathonRecomp SOURCE_FILE "${RESOURCES_SOURCE_PATH}/images/options_menu/thumbnails/ui_alignment_centre.dds" DEST_FILE "${RESOURCES_OUTPUT_PATH}/images/options_menu/thumbnails/ui_alignment_centre.dds" ARRAY_NAME "g_ui_alignment_centre" COMPRESSION_TYPE "zstd") -BIN2C(TARGET_OBJ MarathonRecomp SOURCE_FILE "${RESOURCES_SOURCE_PATH}/images/options_menu/thumbnails/ui_alignment_edge.dds" DEST_FILE "${RESOURCES_OUTPUT_PATH}/images/options_menu/thumbnails/ui_alignment_edge.dds" ARRAY_NAME "g_ui_alignment_edge" COMPRESSION_TYPE "zstd") -BIN2C(TARGET_OBJ MarathonRecomp SOURCE_FILE "${RESOURCES_SOURCE_PATH}/images/options_menu/thumbnails/vertical_camera.dds" DEST_FILE "${RESOURCES_OUTPUT_PATH}/images/options_menu/thumbnails/vertical_camera.dds" ARRAY_NAME "g_vertical_camera" COMPRESSION_TYPE "zstd") -BIN2C(TARGET_OBJ MarathonRecomp SOURCE_FILE "${RESOURCES_SOURCE_PATH}/images/options_menu/thumbnails/voice_language.dds" DEST_FILE "${RESOURCES_OUTPUT_PATH}/images/options_menu/thumbnails/voice_language.dds" ARRAY_NAME "g_voice_language" COMPRESSION_TYPE "zstd") -BIN2C(TARGET_OBJ MarathonRecomp SOURCE_FILE "${RESOURCES_SOURCE_PATH}/images/options_menu/thumbnails/vibration_ps.dds" DEST_FILE "${RESOURCES_OUTPUT_PATH}/images/options_menu/thumbnails/vibration_ps.dds" ARRAY_NAME "g_vibration_ps" COMPRESSION_TYPE "zstd") -BIN2C(TARGET_OBJ MarathonRecomp SOURCE_FILE "${RESOURCES_SOURCE_PATH}/images/options_menu/thumbnails/vibration_xb.dds" DEST_FILE "${RESOURCES_OUTPUT_PATH}/images/options_menu/thumbnails/vibration_xb.dds" ARRAY_NAME "g_vibration_xb" COMPRESSION_TYPE "zstd") -BIN2C(TARGET_OBJ MarathonRecomp SOURCE_FILE "${RESOURCES_SOURCE_PATH}/images/options_menu/thumbnails/vsync_on.dds" DEST_FILE "${RESOURCES_OUTPUT_PATH}/images/options_menu/thumbnails/vsync_on.dds" ARRAY_NAME "g_vsync_on" COMPRESSION_TYPE "zstd") -BIN2C(TARGET_OBJ MarathonRecomp SOURCE_FILE "${RESOURCES_SOURCE_PATH}/images/options_menu/thumbnails/vsync_off.dds" DEST_FILE "${RESOURCES_OUTPUT_PATH}/images/options_menu/thumbnails/vsync_off.dds" ARRAY_NAME "g_vsync_off" COMPRESSION_TYPE "zstd") -BIN2C(TARGET_OBJ MarathonRecomp SOURCE_FILE "${RESOURCES_SOURCE_PATH}/images/options_menu/thumbnails/window_size.dds" DEST_FILE "${RESOURCES_OUTPUT_PATH}/images/options_menu/thumbnails/window_size.dds" ARRAY_NAME "g_window_size" COMPRESSION_TYPE "zstd") -BIN2C(TARGET_OBJ MarathonRecomp SOURCE_FILE "${RESOURCES_SOURCE_PATH}/images/options_menu/miles_electric.dds" DEST_FILE "${RESOURCES_OUTPUT_PATH}/images/options_menu/miles_electric.dds" ARRAY_NAME "g_miles_electric" COMPRESSION_TYPE "zstd") -BIN2C(TARGET_OBJ MarathonRecomp SOURCE_FILE "${RESOURCES_SOURCE_PATH}/images/options_menu/options_static.dds" DEST_FILE "${RESOURCES_OUTPUT_PATH}/images/options_menu/options_static.dds" ARRAY_NAME "g_options_static" COMPRESSION_TYPE "zstd") -BIN2C(TARGET_OBJ MarathonRecomp SOURCE_FILE "${RESOURCES_SOURCE_PATH}/images/options_menu/options_static_flash.dds" DEST_FILE "${RESOURCES_OUTPUT_PATH}/images/options_menu/options_static_flash.dds" ARRAY_NAME "g_options_static_flash" COMPRESSION_TYPE "zstd") - ## Game Icon ## BIN2C(TARGET_OBJ MarathonRecomp SOURCE_FILE "${RESOURCES_SOURCE_PATH}/images/game_icon.bmp" DEST_FILE "${RESOURCES_OUTPUT_PATH}/images/game_icon.bmp" ARRAY_NAME "g_game_icon") diff --git a/MarathonRecomp/api/CSD/Manager/csdmBase.h b/MarathonRecomp/api/Chao/CSD/Core/csdBase.h similarity index 100% rename from MarathonRecomp/api/CSD/Manager/csdmBase.h rename to MarathonRecomp/api/Chao/CSD/Core/csdBase.h diff --git a/MarathonRecomp/api/CSD/Manager/csdmRCObject.h b/MarathonRecomp/api/Chao/CSD/Core/csdRCObject.h similarity index 57% rename from MarathonRecomp/api/CSD/Manager/csdmRCObject.h rename to MarathonRecomp/api/Chao/CSD/Core/csdRCObject.h index 8294228ff..ec4e7f209 100644 --- a/MarathonRecomp/api/CSD/Manager/csdmRCObject.h +++ b/MarathonRecomp/api/Chao/CSD/Core/csdRCObject.h @@ -1,6 +1,6 @@ #pragma once -#include +#include namespace Chao::CSD { @@ -10,13 +10,13 @@ namespace Chao::CSD struct Vftable { be fpDestroy; - be fpDeallocate; + be fpFree; }; xpointer m_pVftable; xpointer m_pMemory; - be m_RefCount; - xpointer m_pDealloctor; - be m_eDealloctor; + be m_ReferenceCount; + xpointer m_Field0C; + be m_Field10; }; } diff --git a/MarathonRecomp/api/CSD/Manager/csdmRCObjectImp.h b/MarathonRecomp/api/Chao/CSD/Core/csdRCObjectImp.h similarity index 76% rename from MarathonRecomp/api/CSD/Manager/csdmRCObjectImp.h rename to MarathonRecomp/api/Chao/CSD/Core/csdRCObjectImp.h index 8b672b34d..1bd6142f9 100644 --- a/MarathonRecomp/api/CSD/Manager/csdmRCObjectImp.h +++ b/MarathonRecomp/api/Chao/CSD/Core/csdRCObjectImp.h @@ -1,6 +1,6 @@ #pragma once -#include +#include namespace Chao::CSD { diff --git a/MarathonRecomp/api/CSD/Manager/csdmRCPtr.h b/MarathonRecomp/api/Chao/CSD/Core/csdRCPtr.h similarity index 78% rename from MarathonRecomp/api/CSD/Manager/csdmRCPtr.h rename to MarathonRecomp/api/Chao/CSD/Core/csdRCPtr.h index 36651138c..c334a8421 100644 --- a/MarathonRecomp/api/CSD/Manager/csdmRCPtr.h +++ b/MarathonRecomp/api/Chao/CSD/Core/csdRCPtr.h @@ -1,6 +1,6 @@ #pragma once -#include +#include namespace Chao::CSD { diff --git a/MarathonRecomp/api/CSD/Manager/csdmRCPtrAbs.h b/MarathonRecomp/api/Chao/CSD/Core/csdRCPtrAbs.h similarity index 100% rename from MarathonRecomp/api/CSD/Manager/csdmRCPtrAbs.h rename to MarathonRecomp/api/Chao/CSD/Core/csdRCPtrAbs.h diff --git a/MarathonRecomp/api/CSD/Platform/csdTexList.h b/MarathonRecomp/api/Chao/CSD/Core/csdTexList.h similarity index 77% rename from MarathonRecomp/api/CSD/Platform/csdTexList.h rename to MarathonRecomp/api/Chao/CSD/Core/csdTexList.h index c24cc7702..49e710063 100644 --- a/MarathonRecomp/api/CSD/Platform/csdTexList.h +++ b/MarathonRecomp/api/Chao/CSD/Core/csdTexList.h @@ -1,7 +1,7 @@ #pragma once -#include -#include +#include +#include namespace Chao::CSD { diff --git a/MarathonRecomp/api/CSD/Manager/csdmMotionPattern.h b/MarathonRecomp/api/Chao/CSD/Manager/csdmMotionPattern.h similarity index 100% rename from MarathonRecomp/api/CSD/Manager/csdmMotionPattern.h rename to MarathonRecomp/api/Chao/CSD/Manager/csdmMotionPattern.h diff --git a/MarathonRecomp/api/CSD/Manager/csdmNode.h b/MarathonRecomp/api/Chao/CSD/Manager/csdmNode.h similarity index 64% rename from MarathonRecomp/api/CSD/Manager/csdmNode.h rename to MarathonRecomp/api/Chao/CSD/Manager/csdmNode.h index efedb3975..5905caf9f 100644 --- a/MarathonRecomp/api/CSD/Manager/csdmNode.h +++ b/MarathonRecomp/api/Chao/CSD/Manager/csdmNode.h @@ -1,10 +1,10 @@ #pragma once #include -#include -#include -#include -#include +#include +#include +#include +#include namespace Chao::CSD { diff --git a/MarathonRecomp/api/CSD/Manager/csdmNodeObserver.h b/MarathonRecomp/api/Chao/CSD/Manager/csdmNodeObserver.h similarity index 70% rename from MarathonRecomp/api/CSD/Manager/csdmNodeObserver.h rename to MarathonRecomp/api/Chao/CSD/Manager/csdmNodeObserver.h index ff72cb3e1..3cadb3442 100644 --- a/MarathonRecomp/api/CSD/Manager/csdmNodeObserver.h +++ b/MarathonRecomp/api/Chao/CSD/Manager/csdmNodeObserver.h @@ -1,6 +1,6 @@ #pragma once -#include +#include namespace Chao::CSD { diff --git a/MarathonRecomp/api/CSD/Manager/csdmObserverBase.h b/MarathonRecomp/api/Chao/CSD/Manager/csdmObserverBase.h similarity index 87% rename from MarathonRecomp/api/CSD/Manager/csdmObserverBase.h rename to MarathonRecomp/api/Chao/CSD/Manager/csdmObserverBase.h index af69a5a07..151e287f5 100644 --- a/MarathonRecomp/api/CSD/Manager/csdmObserverBase.h +++ b/MarathonRecomp/api/Chao/CSD/Manager/csdmObserverBase.h @@ -14,6 +14,6 @@ namespace Chao::CSD }; xpointer m_pVftable; - MARATHON_INSERT_PADDING(0x08); + MARATHON_INSERT_PADDING(0x0C); }; } diff --git a/MarathonRecomp/api/CSD/Manager/csdmProject.h b/MarathonRecomp/api/Chao/CSD/Manager/csdmProject.h similarity index 83% rename from MarathonRecomp/api/CSD/Manager/csdmProject.h rename to MarathonRecomp/api/Chao/CSD/Manager/csdmProject.h index ac8b38b8c..5b597b453 100644 --- a/MarathonRecomp/api/CSD/Manager/csdmProject.h +++ b/MarathonRecomp/api/Chao/CSD/Manager/csdmProject.h @@ -1,8 +1,8 @@ #pragma once #include -#include -#include +#include +#include namespace Chao::CSD { diff --git a/MarathonRecomp/api/CSD/Manager/csdmResourceBase.h b/MarathonRecomp/api/Chao/CSD/Manager/csdmResourceBase.h similarity index 90% rename from MarathonRecomp/api/CSD/Manager/csdmResourceBase.h rename to MarathonRecomp/api/Chao/CSD/Manager/csdmResourceBase.h index 63afeb830..76036557a 100644 --- a/MarathonRecomp/api/CSD/Manager/csdmResourceBase.h +++ b/MarathonRecomp/api/Chao/CSD/Manager/csdmResourceBase.h @@ -1,6 +1,6 @@ #pragma once -#include +#include namespace Chao::CSD { diff --git a/MarathonRecomp/api/CSD/Manager/csdmScene.h b/MarathonRecomp/api/Chao/CSD/Manager/csdmScene.h similarity index 94% rename from MarathonRecomp/api/CSD/Manager/csdmScene.h rename to MarathonRecomp/api/Chao/CSD/Manager/csdmScene.h index ea6deab69..cf5a67c60 100644 --- a/MarathonRecomp/api/CSD/Manager/csdmScene.h +++ b/MarathonRecomp/api/Chao/CSD/Manager/csdmScene.h @@ -1,10 +1,10 @@ #pragma once #include -#include -#include -#include -#include +#include +#include +#include +#include namespace Chao::CSD { diff --git a/MarathonRecomp/api/CSD/Manager/csdmSceneObserver.h b/MarathonRecomp/api/Chao/CSD/Manager/csdmSceneObserver.h similarity index 71% rename from MarathonRecomp/api/CSD/Manager/csdmSceneObserver.h rename to MarathonRecomp/api/Chao/CSD/Manager/csdmSceneObserver.h index 524cfaab9..6f3e204aa 100644 --- a/MarathonRecomp/api/CSD/Manager/csdmSceneObserver.h +++ b/MarathonRecomp/api/Chao/CSD/Manager/csdmSceneObserver.h @@ -1,6 +1,6 @@ #pragma once -#include +#include namespace Chao::CSD { diff --git a/MarathonRecomp/api/CSD/Manager/csdmSubjectBase.h b/MarathonRecomp/api/Chao/CSD/Manager/csdmSubjectBase.h similarity index 100% rename from MarathonRecomp/api/CSD/Manager/csdmSubjectBase.h rename to MarathonRecomp/api/Chao/CSD/Manager/csdmSubjectBase.h diff --git a/MarathonRecomp/api/Marathon.h b/MarathonRecomp/api/Marathon.h index a12e4dd1e..0e87f796a 100644 --- a/MarathonRecomp/api/Marathon.h +++ b/MarathonRecomp/api/Marathon.h @@ -1,30 +1,32 @@ #pragma once -#include "CSD/Manager/csdmBase.h" -#include "CSD/Manager/csdmMotionPattern.h" -#include "CSD/Manager/csdmNode.h" -#include "CSD/Manager/csdmNodeObserver.h" -#include "CSD/Manager/csdmObserverBase.h" -#include "CSD/Manager/csdmProject.h" -#include "CSD/Manager/csdmRCObject.h" -#include "CSD/Manager/csdmRCObjectImp.h" -#include "CSD/Manager/csdmRCPtr.h" -#include "CSD/Manager/csdmRCPtrAbs.h" -#include "CSD/Manager/csdmResourceBase.h" -#include "CSD/Manager/csdmScene.h" -#include "CSD/Manager/csdmSceneObserver.h" -#include "CSD/Manager/csdmSubjectBase.h" -#include "CSD/Platform/csdTexList.h" +#include "Chao/CSD/Core/csdBase.h" +#include "Chao/CSD/Core/csdRCObject.h" +#include "Chao/CSD/Core/csdRCObjectImp.h" +#include "Chao/CSD/Core/csdRCPtr.h" +#include "Chao/CSD/Core/csdRCPtrAbs.h" +#include "Chao/CSD/Core/csdTexList.h" +#include "Chao/CSD/Manager/csdmMotionPattern.h" +#include "Chao/CSD/Manager/csdmNode.h" +#include "Chao/CSD/Manager/csdmNodeObserver.h" +#include "Chao/CSD/Manager/csdmObserverBase.h" +#include "Chao/CSD/Manager/csdmProject.h" +#include "Chao/CSD/Manager/csdmResourceBase.h" +#include "Chao/CSD/Manager/csdmScene.h" +#include "Chao/CSD/Manager/csdmSceneObserver.h" +#include "Chao/CSD/Manager/csdmSubjectBase.h" #include "Sonicteam/Actor.h" #include "Sonicteam/ActorManager.h" #include "Sonicteam/AlertWindowTask.h" #include "Sonicteam/AppMarathon.h" #include "Sonicteam/AudioEngineXenon.h" +#include "Sonicteam/ButtonWindowTask.h" #include "Sonicteam/CObjBalloonIconDrawable.h" -#include "Sonicteam/Camera/CameraModeManager.h" #include "Sonicteam/Camera/CameraMode.h" +#include "Sonicteam/Camera/CameraModeManager.h" #include "Sonicteam/Camera/Cameraman.h" #include "Sonicteam/Camera/SonicCamera.h" +#include "Sonicteam/CommonObjectHint.h" #include "Sonicteam/CsdLink.h" #include "Sonicteam/CsdManager.h" #include "Sonicteam/CsdObject.h" @@ -35,6 +37,7 @@ #include "Sonicteam/Enemy/EnemyShotNormal.h" #include "Sonicteam/Enemy/EnemyShotPoint.h" #include "Sonicteam/Fixture.h" +#include "Sonicteam/Game.h" #include "Sonicteam/GameImp.h" #include "Sonicteam/GameMode.h" #include "Sonicteam/Globals.h" @@ -45,6 +48,7 @@ #include "Sonicteam/HUDMainDisplay.h" #include "Sonicteam/HUDMainMenu.h" #include "Sonicteam/HUDMessageWindow.h" +#include "Sonicteam/HUDOption.h" #include "Sonicteam/HUDPopupScreen.h" #include "Sonicteam/HUDRaderMap.h" #include "Sonicteam/HUDStageTitle.h" @@ -54,13 +58,23 @@ #include "Sonicteam/MainDisplayTask.h" #include "Sonicteam/MainMenuTask.h" #include "Sonicteam/MainMode.h" -#include "Sonicteam/Message/MsgCameramanCameraMode.h" +#include "Sonicteam/Message/MsgCameramanChangeMode.h" +#include "Sonicteam/Message/MsgHUDButtonWindowChangeButtons.h" +#include "Sonicteam/Message/MsgHUDMainMenuChangeState.h" +#include "Sonicteam/Message/MsgHUDMainMenuSetCursor.h" +#include "Sonicteam/Message/MsgHUDMainMenuTransition.h" +#include "Sonicteam/Message/MsgMissionGetGlobalFlag.h" #include "Sonicteam/Message/MsgObjJump123GetNextPoint.h" +#include "Sonicteam/Message/MsgPauseAdapterText.h" #include "Sonicteam/Message/MsgSuckPlayer.h" #include "Sonicteam/MessageWindowTask.h" +#include "Sonicteam/Mission/Core.h" #include "Sonicteam/MovieObject.h" #include "Sonicteam/MovieObjectWmv.h" #include "Sonicteam/MovieTask.h" +#include "Sonicteam/MyCue.h" +#include "Sonicteam/MyCueAdx.h" +#include "Sonicteam/MyCueAttenuate.h" #include "Sonicteam/MyGraphicsDevice.h" #include "Sonicteam/MyPhantom.h" #include "Sonicteam/MyTexture.h" @@ -70,10 +84,13 @@ #include "Sonicteam/NoSyncThread.h" #include "Sonicteam/ObjectVehicle.h" #include "Sonicteam/ObjectVehicleBike.h" +#include "Sonicteam/PauseAdapter.h" +#include "Sonicteam/PauseTask.h" #include "Sonicteam/Player/GroundRayListener.h" #include "Sonicteam/Player/ICollisionListener.h" #include "Sonicteam/Player/ICollisionListenerTemplate.h" #include "Sonicteam/Player/IDynamicLink.h" +#include "Sonicteam/Player/IEventerListener.h" #include "Sonicteam/Player/IExportExternalFlag.h" #include "Sonicteam/Player/IExportPostureRequestFlag.h" #include "Sonicteam/Player/IExportWeaponRequestFlag.h" @@ -92,6 +109,9 @@ #include "Sonicteam/Player/IStepable.h" #include "Sonicteam/Player/IVariable.h" #include "Sonicteam/Player/IZock.h" +#include "Sonicteam/Player/Input/IListener.h" +#include "Sonicteam/Player/Input/ListenerNormal.h" +#include "Sonicteam/Player/Input/TimedAction.h" #include "Sonicteam/Player/Object.h" #include "Sonicteam/Player/PostureControl.h" #include "Sonicteam/Player/RootFrame.h" @@ -114,13 +134,17 @@ #include "Sonicteam/Player/Unit/ITestCase.h" #include "Sonicteam/Player/Weapon/SonicWeapons.h" #include "Sonicteam/Player/Zock.h" +#include "Sonicteam/PropFixture.h" #include "Sonicteam/RaderMapManager.h" #include "Sonicteam/SaveDataTask.h" #include "Sonicteam/SaveDataTaskXENON.h" #include "Sonicteam/SelectWindowTask.h" #include "Sonicteam/SoX/AI/StateMachine.h" #include "Sonicteam/SoX/ApplicationXenon.h" +#include "Sonicteam/SoX/Audio/Cue.h" #include "Sonicteam/SoX/Audio/IAudioEngine.h" +#include "Sonicteam/SoX/Audio/Player.h" +#include "Sonicteam/SoX/Audio/PlayerImpl.h" #include "Sonicteam/SoX/Component.h" #include "Sonicteam/SoX/Engine/Application.h" #include "Sonicteam/SoX/Engine/Doc.h" @@ -181,6 +205,7 @@ #include "Sonicteam/VehicleMissileCtrl.h" #include "Sonicteam/VehicleMissileCtrlAutomatic.h" #include "Sonicteam/VehicleMissileCtrlSingle.h" +#include "Sonicteam/sonicXmaPlayer.h" #include "boost/smart_ptr/make_shared_object.h" #include "boost/smart_ptr/shared_ptr.h" #include "hk330/hkArray.h" diff --git a/MarathonRecomp/api/Marathon.inl b/MarathonRecomp/api/Marathon.inl index 433ce6a3d..c6b017ebb 100644 --- a/MarathonRecomp/api/Marathon.inl +++ b/MarathonRecomp/api/Marathon.inl @@ -126,12 +126,12 @@ inline bool strcmpU16(const uint16_t* a, const uint16_t* b, bool endianSwapA = f return true; } -inline void printU16(const uint16_t* str) +inline void printU16(const uint16_t* str, bool endianSwap = false) { for (size_t i = 0; i < strlenU16(str); i++) { - auto c0 = str[i] >> 8; - auto c1 = str[i] & 0xFF; + auto c0 = endianSwap ? ByteSwap(str[i]) >> 8 : str[i] >> 8; + auto c1 = endianSwap ? ByteSwap(str[i]) & 0xFF : str[i] & 0xFF; printf("%c%c", c0, c1); } diff --git a/MarathonRecomp/api/Sonicteam/AppMarathon.h b/MarathonRecomp/api/Sonicteam/AppMarathon.h index ec42f1733..f7d0195c0 100644 --- a/MarathonRecomp/api/Sonicteam/AppMarathon.h +++ b/MarathonRecomp/api/Sonicteam/AppMarathon.h @@ -3,6 +3,7 @@ #include #include #include +#include namespace Sonicteam { @@ -12,6 +13,14 @@ namespace Sonicteam xpointer m_pDoc; static AppMarathon* GetInstance(); + + GameImp* GetGame() const + { + if (auto pGameMode = m_pDoc->GetDocMode()) + return pGameMode->GetGame(); + + return nullptr; + } }; } diff --git a/MarathonRecomp/api/Sonicteam/ButtonWindowTask.h b/MarathonRecomp/api/Sonicteam/ButtonWindowTask.h new file mode 100644 index 000000000..2b90cef84 --- /dev/null +++ b/MarathonRecomp/api/Sonicteam/ButtonWindowTask.h @@ -0,0 +1,13 @@ +#pragma once + +#include +#include + +namespace Sonicteam +{ + class ButtonWindowTask : public SoX::Engine::Task + { + public: + xpointer m_pHUDButtonWindow; + }; +} diff --git a/MarathonRecomp/api/Sonicteam/Camera/CameraMode.h b/MarathonRecomp/api/Sonicteam/Camera/CameraMode.h index 5866a133d..9d03806ca 100644 --- a/MarathonRecomp/api/Sonicteam/Camera/CameraMode.h +++ b/MarathonRecomp/api/Sonicteam/Camera/CameraMode.h @@ -10,8 +10,13 @@ namespace Sonicteam::Camera class CameraMode : public SoX::MessageReceiver { public: - boost::shared_ptr m_spGameImp; - xpointer m_pTPCameraInputListener; + boost::shared_ptr m_spGame; + xpointer m_pCameraInputListener; MARATHON_INSERT_PADDING(0x18); + + GameImp* GetGame() const + { + return (GameImp*)m_spGame.get(); + } }; } diff --git a/MarathonRecomp/api/Sonicteam/Camera/CameraModeManager.h b/MarathonRecomp/api/Sonicteam/Camera/CameraModeManager.h index e200aee09..6c35fe41c 100644 --- a/MarathonRecomp/api/Sonicteam/Camera/CameraModeManager.h +++ b/MarathonRecomp/api/Sonicteam/Camera/CameraModeManager.h @@ -2,23 +2,23 @@ #include #include -#include +#include +#include namespace Sonicteam::Camera { - class Cameraman; - class CameraMode; class CameraModeManager { - // TODO: figure out all these, 8218C100 - struct _vector_struct_ + public: + // TODO: research these fields (processed by 0x8218C100). + struct UnknownStruct { MARATHON_INSERT_PADDING(0x14); }; - public: + xpointer m_pCameraman; boost::shared_ptr m_spCameraMode; - MARATHON_INSERT_PADDING(0x8); - stdx::vector<_vector_struct_> m_vVector; + MARATHON_INSERT_PADDING(8); + stdx::vector m_vUnkStructs; }; } diff --git a/MarathonRecomp/api/Sonicteam/Camera/Cameraman.h b/MarathonRecomp/api/Sonicteam/Camera/Cameraman.h index bbb76405b..efab95d57 100644 --- a/MarathonRecomp/api/Sonicteam/Camera/Cameraman.h +++ b/MarathonRecomp/api/Sonicteam/Camera/Cameraman.h @@ -2,16 +2,17 @@ #include #include -#include namespace Sonicteam::Camera { + class CameraModeManager; + class Cameraman : public Actor { public: MARATHON_INSERT_PADDING(0x24); boost::shared_ptr m_spCameraModeManager; MARATHON_INSERT_PADDING(0x2C); - be m_FOV; // 0xB0 + be m_FOV; }; } diff --git a/MarathonRecomp/api/Sonicteam/CommonObjectHint.h b/MarathonRecomp/api/Sonicteam/CommonObjectHint.h new file mode 100644 index 000000000..0487f56e8 --- /dev/null +++ b/MarathonRecomp/api/Sonicteam/CommonObjectHint.h @@ -0,0 +1,32 @@ +#pragma once + +#include +#include + +namespace Sonicteam +{ + class CommonObjectHint : public PropFixture + { + public: + enum CommonObjectHintType : uint32_t + { + CommonObjectHintType_HintRing, + CommonObjectHintType_HintVolume + }; + + MARATHON_INSERT_PADDING(4); + char m_MessageName[20]; + MARATHON_INSERT_PADDING(0x40); + be m_Type; + bool m_IsFastAnim; + bool m_IsHitAnim; + MARATHON_INSERT_PADDING(2); + be m_HitTime; + }; + + MARATHON_ASSERT_OFFSETOF(CommonObjectHint, m_MessageName, 0x184); + MARATHON_ASSERT_OFFSETOF(CommonObjectHint, m_Type, 0x1D8); + MARATHON_ASSERT_OFFSETOF(CommonObjectHint, m_IsFastAnim, 0x1DC); + MARATHON_ASSERT_OFFSETOF(CommonObjectHint, m_IsHitAnim, 0x1DD); + MARATHON_ASSERT_OFFSETOF(CommonObjectHint, m_HitTime, 0x1E0); +} diff --git a/MarathonRecomp/api/Sonicteam/CsdLink.h b/MarathonRecomp/api/Sonicteam/CsdLink.h index c55a759c8..ca3b212bb 100644 --- a/MarathonRecomp/api/Sonicteam/CsdLink.h +++ b/MarathonRecomp/api/Sonicteam/CsdLink.h @@ -9,7 +9,8 @@ namespace Sonicteam public: struct Vftable { - MARATHON_INSERT_PADDING(8); + be fpDestroy; + MARATHON_INSERT_PADDING(4); be fpUpdate; }; @@ -19,6 +20,11 @@ namespace Sonicteam be m_Priority; MARATHON_INSERT_PADDING(8); + void* Destroy(uint32_t flags = 1) + { + return GuestToHostFunction(m_pVftable->fpDestroy.get(), this, flags); + } + int Update(double deltaTime = 0.0) { return GuestToHostFunction(m_pVftable->fpUpdate.get(), this, deltaTime); diff --git a/MarathonRecomp/api/Sonicteam/CsdObject.h b/MarathonRecomp/api/Sonicteam/CsdObject.h index 34423349e..33a416748 100644 --- a/MarathonRecomp/api/Sonicteam/CsdObject.h +++ b/MarathonRecomp/api/Sonicteam/CsdObject.h @@ -2,6 +2,7 @@ #include #include +#include #include namespace Sonicteam diff --git a/MarathonRecomp/api/Sonicteam/CsdResource.h b/MarathonRecomp/api/Sonicteam/CsdResource.h index 7388fddda..2712a5260 100644 --- a/MarathonRecomp/api/Sonicteam/CsdResource.h +++ b/MarathonRecomp/api/Sonicteam/CsdResource.h @@ -2,6 +2,7 @@ #include #include +#include namespace Sonicteam { diff --git a/MarathonRecomp/api/Sonicteam/Game.h b/MarathonRecomp/api/Sonicteam/Game.h new file mode 100644 index 000000000..42772469f --- /dev/null +++ b/MarathonRecomp/api/Sonicteam/Game.h @@ -0,0 +1,8 @@ +#pragma once + +#include + +namespace Sonicteam +{ + class Game : public SoX::MessageReceiver {}; +} diff --git a/MarathonRecomp/api/Sonicteam/GameImp.h b/MarathonRecomp/api/Sonicteam/GameImp.h index 8f9b5325d..52f49c499 100644 --- a/MarathonRecomp/api/Sonicteam/GameImp.h +++ b/MarathonRecomp/api/Sonicteam/GameImp.h @@ -2,17 +2,22 @@ #include #include +#include +#include #include #include #include #include +#include +#include #include namespace Sonicteam { - class ActorManager; // Gauge patch + class ActorManager; class GameScript; - class GameImp : public SoX::MessageReceiver + + class GameImp : public Game { public: enum GameState : uint32_t @@ -28,6 +33,15 @@ namespace Sonicteam GameState_ReturnToMainMenu }; + enum GameFlags : uint32_t + { + GameFlags_RestartArea1 = 1, + GameFlags_RestartArea2 = 0x200, + GameFlags_IsPaused = 0x1000, + GameFlags_LoadArea1 = 0x40000, + GameFlags_LoadArea2 = 0x200000 + }; + struct PlayerData { be ActorID; @@ -49,9 +63,9 @@ namespace Sonicteam }; MARATHON_INSERT_PADDING(4); - be m_GameState; + be m_State; xpointer m_pDoc; - be m_Flags; + be m_Flags; MARATHON_INSERT_PADDING(0xE2C); PlayerData m_PlayerData[4]; MARATHON_INSERT_PADDING(0x200); @@ -61,9 +75,16 @@ namespace Sonicteam xpointer m_pGameScript; be m_aObjPlayerActorID[0xF]; boost::shared_ptr m_spActorManager; - MARATHON_INSERT_PADDING(0xC); + xpointer m_pSystemTextBook; + MARATHON_INSERT_PADDING(8); stdx::vector>> m_vvspCameras; - MARATHON_INSERT_PADDING(0x7D4); + MARATHON_INSERT_PADDING(0x1B4); + xpointer m_pBgmCue; + MARATHON_INSERT_PADDING(0x36C); + xpointer m_pHintTextBook; + MARATHON_INSERT_PADDING(4); + xpointer m_pMissionCore; + MARATHON_INSERT_PADDING(0x2A4); SoX::RefSharedPointer m_spPhysicsWorld; xpointer m_pMyCollisionFilter; @@ -78,7 +99,7 @@ namespace Sonicteam return -1; } - SoX::Scenery::CameraImp* GetCameraImp(const char* pName, int which = 0) + SoX::Scenery::CameraImp* GetCamera(const char* pName, int which = 0) { if (m_vvspCameras.empty()) return nullptr; @@ -94,6 +115,12 @@ namespace Sonicteam return nullptr; } + template + T* GetBgmCue() const + { + return (T*)m_pBgmCue.get(); + } + template T* GetPhysicsWorld() const { diff --git a/MarathonRecomp/api/Sonicteam/GameMode.h b/MarathonRecomp/api/Sonicteam/GameMode.h index ecbfd7d14..61a90b513 100644 --- a/MarathonRecomp/api/Sonicteam/GameMode.h +++ b/MarathonRecomp/api/Sonicteam/GameMode.h @@ -1,6 +1,7 @@ #pragma once #include +#include namespace Sonicteam { @@ -8,7 +9,12 @@ namespace Sonicteam { public: MARATHON_INSERT_PADDING(0x1C); - xpointer m_pGameImp; + xpointer m_pGame; MARATHON_INSERT_PADDING(0x1C); + + GameImp* GetGame() const + { + return (GameImp*)m_pGame.get(); + } }; } diff --git a/MarathonRecomp/api/Sonicteam/HUDButtonWindow.h b/MarathonRecomp/api/Sonicteam/HUDButtonWindow.h index d100581ce..a7363ef52 100644 --- a/MarathonRecomp/api/Sonicteam/HUDButtonWindow.h +++ b/MarathonRecomp/api/Sonicteam/HUDButtonWindow.h @@ -1,16 +1,39 @@ #pragma once #include +#include +#include #include #include +#include #include +#include +#include +#include namespace Sonicteam { + class HUDButtonWindow; + + class HUDButtonWindowNextObserver : public SoX::RefCountObject, public Chao::CSD::CSceneObserver + { + public: + MARATHON_INSERT_PADDING(4); + xpointer m_pHUDButtonWindow; + MARATHON_INSERT_PADDING(4); + }; + class HUDButtonWindow : public SoX::RefCountObject, public SoX::Engine::Task { public: - MARATHON_INSERT_PADDING(0x38); + xpointer m_pTextBook; + xpointer m_pCsdResource; + HUDButtonWindowNextObserver m_NextObserver; + be m_Field80; + boost::shared_ptr m_spTextCard; + boost::shared_ptr m_spTextEntity; xpointer m_pHudTextParts; + be m_Field98; + bool m_IsIntroAnimStarted; }; } diff --git a/MarathonRecomp/api/Sonicteam/HUDMainMenu.h b/MarathonRecomp/api/Sonicteam/HUDMainMenu.h index ecc5fe1d3..e1e8ef3f3 100644 --- a/MarathonRecomp/api/Sonicteam/HUDMainMenu.h +++ b/MarathonRecomp/api/Sonicteam/HUDMainMenu.h @@ -1,13 +1,29 @@ #pragma once #include +#include +#include namespace Sonicteam { class HUDMainMenu : public SoX::RefCountObject, public SoX::Engine::Task { public: - MARATHON_INSERT_PADDING(0x4FC); + enum HUDMainMenuState : uint32_t + { + HUDMainMenuState_OptionsOutro = 5, + HUDMainMenuState_OptionsIntro = 90, + HUDMainMenuState_MainCursorIntro = 98, + HUDMainMenuState_MainCursorOutro = 99 + }; + + MARATHON_INSERT_PADDING(0x20); + xpointer m_pCsdObject; + MARATHON_INSERT_PADDING(0x1B0); + be m_CursorFlags; + MARATHON_INSERT_PADDING(0x32C); xpointer m_pHudTextRoot; }; + + MARATHON_ASSERT_OFFSETOF(HUDMainMenu, m_pHudTextRoot, 0x558); } diff --git a/MarathonRecomp/api/Sonicteam/HUDOption.h b/MarathonRecomp/api/Sonicteam/HUDOption.h new file mode 100644 index 000000000..f3c12dd85 --- /dev/null +++ b/MarathonRecomp/api/Sonicteam/HUDOption.h @@ -0,0 +1,14 @@ +#pragma once + +#include +#include + +namespace Sonicteam +{ + class HUDOption : public SoX::RefCountObject, public SoX::Engine::Task + { + public: + MARATHON_INSERT_PADDING(0x188); + xpointer m_pHudTextRoot; + }; +} diff --git a/MarathonRecomp/api/Sonicteam/HudTextParts.h b/MarathonRecomp/api/Sonicteam/HudTextParts.h index 8fe8f5172..a96cc8ba8 100644 --- a/MarathonRecomp/api/Sonicteam/HudTextParts.h +++ b/MarathonRecomp/api/Sonicteam/HudTextParts.h @@ -2,6 +2,7 @@ #include #include +#include #include #include #include @@ -23,5 +24,35 @@ namespace Sonicteam be m_OffsetY; MARATHON_INSERT_PADDING(4); be m_AlignmentFlags; + + HudTextParts* Find(const char* pSceneName) + { + auto pRoot = this; + + while (pRoot) + { + if (pRoot->m_SceneName == pSceneName) + return pRoot; + + pRoot = pRoot->m_pNext; + } + + return nullptr; + } + + HudTextParts* Find(const char* pSceneName, const char* pCastName) + { + auto pRoot = this; + + while (pRoot) + { + if (pRoot->m_SceneName == pSceneName && pRoot->m_CastName == pCastName) + return pRoot; + + pRoot = pRoot->m_pNext; + } + + return nullptr; + } }; } diff --git a/MarathonRecomp/api/Sonicteam/MainMenuTask.h b/MarathonRecomp/api/Sonicteam/MainMenuTask.h index 26e805ece..0cd58ed1c 100644 --- a/MarathonRecomp/api/Sonicteam/MainMenuTask.h +++ b/MarathonRecomp/api/Sonicteam/MainMenuTask.h @@ -1,8 +1,9 @@ #pragma once #include -#include #include +#include +#include namespace Sonicteam { @@ -23,6 +24,7 @@ namespace Sonicteam MainMenuState_Multiplayer = 0x17, MainMenuState_Extras = 0x1C, MainMenuState_Tag = 0x1E, + MainMenuState_Tag1PSelect = 0x1F, MainMenuState_Battle = 0x22, MainMenuState_GoldMedalResults = 0x26, MainMenuState_AudioRoom = 0x2F, @@ -33,7 +35,15 @@ namespace Sonicteam }; be m_State; - MARATHON_INSERT_PADDING(0x248); + MARATHON_INSERT_PADDING(0x24); + xpointer m_pHUDMainMenu; + MARATHON_INSERT_PADDING(0x20); + xpointer m_pButtonWindowTask; + MARATHON_INSERT_PADDING(4); + be m_MainMenuSelectedIndex; + MARATHON_INSERT_PADDING(0x1D8); + be m_PressedButtons; + MARATHON_INSERT_PADDING(0x18); xpointer m_Field298; xpointer m_SelectCharacters[9]; }; diff --git a/MarathonRecomp/api/Sonicteam/Message/MsgCameramanChangeMode.h b/MarathonRecomp/api/Sonicteam/Message/MsgCameramanChangeMode.h new file mode 100644 index 000000000..39eea5de2 --- /dev/null +++ b/MarathonRecomp/api/Sonicteam/Message/MsgCameramanChangeMode.h @@ -0,0 +1,15 @@ +#pragma once + +#include +#include +#include + +namespace Sonicteam::Message +{ + struct MsgCameramanChangeMode : SoX::Message<0x14007> + { + be ControllerIndex; + be TargetActorID; + bool IsDemoCamera; + }; +} diff --git a/MarathonRecomp/api/Sonicteam/Message/MsgHUDButtonWindowChangeButtons.h b/MarathonRecomp/api/Sonicteam/Message/MsgHUDButtonWindowChangeButtons.h new file mode 100644 index 000000000..426dffedc --- /dev/null +++ b/MarathonRecomp/api/Sonicteam/Message/MsgHUDButtonWindowChangeButtons.h @@ -0,0 +1,14 @@ +#pragma once + +#include +#include + +namespace Sonicteam::Message +{ + struct MsgHUDButtonWindowChangeButtons : SoX::Message<0x1B05B> + { + be ButtonType; + + MsgHUDButtonWindowChangeButtons(uint32_t buttonType = 0) : ButtonType(buttonType) {} + }; +} diff --git a/MarathonRecomp/api/Sonicteam/Message/MsgHUDMainMenuChangeState.h b/MarathonRecomp/api/Sonicteam/Message/MsgHUDMainMenuChangeState.h new file mode 100644 index 000000000..7a153dc44 --- /dev/null +++ b/MarathonRecomp/api/Sonicteam/Message/MsgHUDMainMenuChangeState.h @@ -0,0 +1,12 @@ +#pragma once + +#include +#include + +namespace Sonicteam::Message +{ + struct MsgHUDMainMenuChangeState : SoX::Message<0x1B053> + { + be State; + }; +} diff --git a/MarathonRecomp/api/Sonicteam/Message/MsgHUDMainMenuSetCursor.h b/MarathonRecomp/api/Sonicteam/Message/MsgHUDMainMenuSetCursor.h new file mode 100644 index 000000000..eb027d591 --- /dev/null +++ b/MarathonRecomp/api/Sonicteam/Message/MsgHUDMainMenuSetCursor.h @@ -0,0 +1,25 @@ +#pragma once + +#include +#include + +namespace Sonicteam::Message +{ + struct MsgHUDMainMenuSetCursor : MsgHUDMainMenuChangeState + { + be CursorIndex; + + MsgHUDMainMenuSetCursor() {} + + MsgHUDMainMenuSetCursor(uint32_t state) + { + State = state; + } + + MsgHUDMainMenuSetCursor(uint32_t state, uint32_t cursorIndex) + { + State = state; + CursorIndex = cursorIndex; + } + }; +} diff --git a/MarathonRecomp/api/Sonicteam/Message/MsgHUDMainMenuTransition.h b/MarathonRecomp/api/Sonicteam/Message/MsgHUDMainMenuTransition.h new file mode 100644 index 000000000..1ad56d614 --- /dev/null +++ b/MarathonRecomp/api/Sonicteam/Message/MsgHUDMainMenuTransition.h @@ -0,0 +1,25 @@ +#pragma once + +#include +#include + +namespace Sonicteam::Message +{ + struct MsgHUDMainMenuTransition : MsgHUDMainMenuChangeState + { + be Flags; + + MsgHUDMainMenuTransition() {} + + MsgHUDMainMenuTransition(uint32_t state) + { + State = state; + } + + MsgHUDMainMenuTransition(uint32_t state, uint32_t flags) + { + State = state; + Flags = flags; + } + }; +} diff --git a/MarathonRecomp/api/Sonicteam/Message/MsgMissionGetGlobalFlag.h b/MarathonRecomp/api/Sonicteam/Message/MsgMissionGetGlobalFlag.h new file mode 100644 index 000000000..31b9e50f2 --- /dev/null +++ b/MarathonRecomp/api/Sonicteam/Message/MsgMissionGetGlobalFlag.h @@ -0,0 +1,14 @@ +#pragma once + +#include + +namespace Sonicteam::Message +{ + struct MsgMissionGetGlobalFlag : SoX::Message<0x1E004> + { + be FlagID; + be FlagValue; + + MsgMissionGetGlobalFlag(uint32_t flagId) : FlagID(flagId) {} + }; +} diff --git a/MarathonRecomp/api/Sonicteam/Message/MsgObjJump123GetNextPoint.h b/MarathonRecomp/api/Sonicteam/Message/MsgObjJump123GetNextPoint.h index 5ae887150..284ce96f7 100644 --- a/MarathonRecomp/api/Sonicteam/Message/MsgObjJump123GetNextPoint.h +++ b/MarathonRecomp/api/Sonicteam/Message/MsgObjJump123GetNextPoint.h @@ -8,7 +8,7 @@ namespace Sonicteam::Message { struct MsgObjJump123GetNextPoint : SoX::Message<0x10007> { - Sonicteam::SoX::Math::Quaternion m_Rotation; - Sonicteam::SoX::Math::Vector m_Position; + Sonicteam::SoX::Math::Quaternion Rotation; + Sonicteam::SoX::Math::Vector Position; }; } diff --git a/MarathonRecomp/api/Sonicteam/Message/MsgCameramanCameraMode.h b/MarathonRecomp/api/Sonicteam/Message/MsgPauseAdapterText.h similarity index 50% rename from MarathonRecomp/api/Sonicteam/Message/MsgCameramanCameraMode.h rename to MarathonRecomp/api/Sonicteam/Message/MsgPauseAdapterText.h index a57c4cddd..36a42911e 100644 --- a/MarathonRecomp/api/Sonicteam/Message/MsgCameramanCameraMode.h +++ b/MarathonRecomp/api/Sonicteam/Message/MsgPauseAdapterText.h @@ -3,13 +3,13 @@ #include #include #include +#include namespace Sonicteam::Message { - struct MsgCameramanCameraInitialize : SoX::Message<0x14007> + struct MsgPauseAdapterText : SoX::Message<0x1C003> { - be m_PadID; - be m_TargetActorID; - bool IsDemoCam; + stdx::string PauseName; + stdx::string SelectedName; }; } diff --git a/MarathonRecomp/api/Sonicteam/Mission/Core.h b/MarathonRecomp/api/Sonicteam/Mission/Core.h new file mode 100644 index 000000000..574d4f3e2 --- /dev/null +++ b/MarathonRecomp/api/Sonicteam/Mission/Core.h @@ -0,0 +1,8 @@ +#pragma once + +#include + +namespace Sonicteam::Mission +{ + class Core : public SoX::MessageReceiver {}; +} diff --git a/MarathonRecomp/api/Sonicteam/MyCue.h b/MarathonRecomp/api/Sonicteam/MyCue.h new file mode 100644 index 000000000..9eb657fc6 --- /dev/null +++ b/MarathonRecomp/api/Sonicteam/MyCue.h @@ -0,0 +1,5 @@ +#pragma once + +#include + +class MyCue : public Sonicteam::SoX::Audio::Cue {}; diff --git a/MarathonRecomp/api/Sonicteam/MyCueAdx.h b/MarathonRecomp/api/Sonicteam/MyCueAdx.h new file mode 100644 index 000000000..6951bb150 --- /dev/null +++ b/MarathonRecomp/api/Sonicteam/MyCueAdx.h @@ -0,0 +1,17 @@ +#pragma once + +#include +#include +#include +#include + +class MyCueAdx : public MyCue, public MyCueAttenuate +{ +public: + MARATHON_INSERT_PADDING(0x0C); + be m_Field50; + be m_Field54; + xpointer m_pXmaPlayer; + bool m_IsPaused; + MARATHON_INSERT_PADDING(3); +}; diff --git a/MarathonRecomp/api/Sonicteam/MyCueAttenuate.h b/MarathonRecomp/api/Sonicteam/MyCueAttenuate.h new file mode 100644 index 000000000..1eaffab48 --- /dev/null +++ b/MarathonRecomp/api/Sonicteam/MyCueAttenuate.h @@ -0,0 +1,13 @@ +#pragma once + +class MyCueAttenuate +{ +public: + be m_Time; + be m_FadeOutRate; + be m_FadeInRate; + be m_MinVolume; + be m_MaxVolume; + bool m_IsFadeOut; + MARATHON_INSERT_PADDING(3); +}; diff --git a/MarathonRecomp/api/Sonicteam/PauseAdapter.h b/MarathonRecomp/api/Sonicteam/PauseAdapter.h new file mode 100644 index 000000000..b0772066f --- /dev/null +++ b/MarathonRecomp/api/Sonicteam/PauseAdapter.h @@ -0,0 +1,19 @@ +#pragma once + +#include + +namespace Sonicteam +{ + class PauseAdapter : public SoX::Engine::Task + { + public: + xpointer m_pGame; + be m_SelectedID; + be m_Field54; + + GameImp* GetGame() const + { + return (GameImp*)m_pGame.get(); + } + }; +} diff --git a/MarathonRecomp/api/Sonicteam/PauseTask.h b/MarathonRecomp/api/Sonicteam/PauseTask.h new file mode 100644 index 000000000..31ead449e --- /dev/null +++ b/MarathonRecomp/api/Sonicteam/PauseTask.h @@ -0,0 +1,31 @@ +#pragma once + +#include + +namespace Sonicteam +{ + class PauseTask : public SoX::Engine::Task + { + public: + enum PauseTaskState + { + PauseTaskState_Opened, + PauseTaskState_Opening, + PauseTaskState_Idle, + PauseTaskState_ClosingToAction, + PauseTaskState_Closing, + PauseTaskState_Closed + }; + + MARATHON_INSERT_PADDING(4); + xpointer m_pHUDPause; + MARATHON_INSERT_PADDING(0x18); + be m_State; + be m_Flags; + be m_SelectedIndex; + MARATHON_INSERT_PADDING(0x28); + be m_Buttons; + MARATHON_INSERT_PADDING(0x1E0); + be m_ItemCount; + }; +} diff --git a/MarathonRecomp/api/Sonicteam/Player/GroundRayListener.h b/MarathonRecomp/api/Sonicteam/Player/GroundRayListener.h index 5dc1e7b49..2796d3b31 100644 --- a/MarathonRecomp/api/Sonicteam/Player/GroundRayListener.h +++ b/MarathonRecomp/api/Sonicteam/Player/GroundRayListener.h @@ -10,14 +10,14 @@ namespace Sonicteam::Player { - class GroundRayListener:public ICollisionListenerTemplate + class GroundRayListener : public ICollisionListenerTemplate { public: SoX::Math::Vector m_ContactPosition; SoX::Math::Vector m_ContactNormal; - be m_RayDistance; // Not sure - be m_RayFlag; // Not sure + be m_RayDistance; + be m_RayFlags; SoX::LinkRef m_ContactEntity; - MARATHON_INSERT_PADDING(0xC); + MARATHON_INSERT_PADDING(0x0C); }; } diff --git a/MarathonRecomp/api/Sonicteam/Player/ICollisionListener.h b/MarathonRecomp/api/Sonicteam/Player/ICollisionListener.h index fb49acd2c..7e80119b8 100644 --- a/MarathonRecomp/api/Sonicteam/Player/ICollisionListener.h +++ b/MarathonRecomp/api/Sonicteam/Player/ICollisionListener.h @@ -9,10 +9,10 @@ namespace Sonicteam::Player public: xpointer m_pVftable; MARATHON_INSERT_PADDING(0xC); - be m_Flag1; - be m_Flag2; - be m_Flag3; + be m_FlagsA; + be m_FlagsB; + be m_FlagsC; MARATHON_INSERT_PADDING(0x4); - SoX::Math::Vector m_CollisionNormal; + SoX::Math::Vector m_SurfaceNormal; }; } diff --git a/MarathonRecomp/api/Sonicteam/Player/ICollisionListenerTemplate.h b/MarathonRecomp/api/Sonicteam/Player/ICollisionListenerTemplate.h index 66c0747f7..1c89999ab 100644 --- a/MarathonRecomp/api/Sonicteam/Player/ICollisionListenerTemplate.h +++ b/MarathonRecomp/api/Sonicteam/Player/ICollisionListenerTemplate.h @@ -5,6 +5,6 @@ namespace Sonicteam::Player { - template - class ICollisionListenerTemplate:ICollisionListener,Cast {}; + template + class ICollisionListenerTemplate : public ICollisionListener, public TListener {}; } diff --git a/MarathonRecomp/api/Sonicteam/Player/IEventerListener.h b/MarathonRecomp/api/Sonicteam/Player/IEventerListener.h new file mode 100644 index 000000000..419d16ca8 --- /dev/null +++ b/MarathonRecomp/api/Sonicteam/Player/IEventerListener.h @@ -0,0 +1,11 @@ +#pragma once + +namespace Sonicteam::Player +{ + class IEventerListener + { + public: + xpointer m_pVftable; + MARATHON_INSERT_PADDING(8); + }; +} diff --git a/MarathonRecomp/api/Sonicteam/Player/IPostureControl.h b/MarathonRecomp/api/Sonicteam/Player/IPostureControl.h index ff88e18a4..9ae0c8f4d 100644 --- a/MarathonRecomp/api/Sonicteam/Player/IPostureControl.h +++ b/MarathonRecomp/api/Sonicteam/Player/IPostureControl.h @@ -27,23 +27,23 @@ namespace Sonicteam::Player boost::shared_ptr m_spGravity; boost::shared_ptr m_spInputListener; boost::shared_ptr m_spAmigoListener; - boost::shared_ptr m_ContextIF; + boost::shared_ptr m_spCommonContextIF; boost::shared_ptr m_spActorManager; xpointer m_pTask; boost::shared_ptr m_spPosturePlugIn; SoX::Math::Vector m_GravityDirection; be m_GravityForce; - SoX::Math::Vector m_NormalizedSurface; // Ground normal? + SoX::Math::Vector m_SurfaceNormal; SoX::Math::Vector m_Position; SoX::Math::Quaternion m_Rotation; MARATHON_INSERT_PADDING(0x20); be m_PostureFlag; be m_ImpulseForward; be m_ImpulseVertical; - SoX::Math::Vector m_ImpulseUP; - be m_ContextIFFlag; - be m_PostureRequestFlag; - be m_PostureFlag118; - be m_PostureFlag11C; + SoX::Math::Vector m_ImpulseUp; + be m_CommonContextIFFlags; + be m_PostureRequestFlags; + be m_PostureFlags118; + be m_PostureFlags11C; }; } diff --git a/MarathonRecomp/api/Sonicteam/Player/IPostureSupportEdge.h b/MarathonRecomp/api/Sonicteam/Player/IPostureSupportEdge.h index 1ea8aae53..05c8286e3 100644 --- a/MarathonRecomp/api/Sonicteam/Player/IPostureSupportEdge.h +++ b/MarathonRecomp/api/Sonicteam/Player/IPostureSupportEdge.h @@ -8,6 +8,6 @@ namespace Sonicteam::Player { public: xpointer m_pVftable; - MARATHON_INSERT_PADDING(0x70 - 4); + MARATHON_INSERT_PADDING(0x6C); }; } diff --git a/MarathonRecomp/api/Sonicteam/Player/IPostureSupportInput.h b/MarathonRecomp/api/Sonicteam/Player/IPostureSupportInput.h index 261f1d5a4..33d8809b5 100644 --- a/MarathonRecomp/api/Sonicteam/Player/IPostureSupportInput.h +++ b/MarathonRecomp/api/Sonicteam/Player/IPostureSupportInput.h @@ -8,6 +8,6 @@ namespace Sonicteam::Player { public: xpointer m_pVftable; - MARATHON_INSERT_PADDING(0x30 - 4); + MARATHON_INSERT_PADDING(0x2C); }; } diff --git a/MarathonRecomp/api/Sonicteam/Player/IPostureSupportOttoto.h b/MarathonRecomp/api/Sonicteam/Player/IPostureSupportOttoto.h index 6c2cef413..521aaf3ba 100644 --- a/MarathonRecomp/api/Sonicteam/Player/IPostureSupportOttoto.h +++ b/MarathonRecomp/api/Sonicteam/Player/IPostureSupportOttoto.h @@ -8,6 +8,6 @@ namespace Sonicteam::Player { public: xpointer m_pVftable; - MARATHON_INSERT_PADDING(0x70 - 4); + MARATHON_INSERT_PADDING(0x6C); }; } diff --git a/MarathonRecomp/api/Sonicteam/Player/IPostureSupportSphere.h b/MarathonRecomp/api/Sonicteam/Player/IPostureSupportSphere.h index 02228ea5a..2742455c8 100644 --- a/MarathonRecomp/api/Sonicteam/Player/IPostureSupportSphere.h +++ b/MarathonRecomp/api/Sonicteam/Player/IPostureSupportSphere.h @@ -8,6 +8,6 @@ namespace Sonicteam::Player { public: xpointer m_pVftable; - MARATHON_INSERT_PADDING(0xD0 - 4); + MARATHON_INSERT_PADDING(0xCC); }; } diff --git a/MarathonRecomp/api/Sonicteam/Player/Input/IListener.h b/MarathonRecomp/api/Sonicteam/Player/Input/IListener.h new file mode 100644 index 000000000..76ac711d5 --- /dev/null +++ b/MarathonRecomp/api/Sonicteam/Player/Input/IListener.h @@ -0,0 +1,13 @@ +#pragma once + +#include + +namespace Sonicteam::Player::Input +{ + class IListener + { + public: + xpointer m_pVftable; + MARATHON_INSERT_PADDING(0x14); + }; +} diff --git a/MarathonRecomp/api/Sonicteam/Player/Input/ListenerNormal.h b/MarathonRecomp/api/Sonicteam/Player/Input/ListenerNormal.h new file mode 100644 index 000000000..abf1d0bfd --- /dev/null +++ b/MarathonRecomp/api/Sonicteam/Player/Input/ListenerNormal.h @@ -0,0 +1,21 @@ +#pragma once + +#include +#include + +namespace Sonicteam::Player::Input +{ + class ListenerNormal : public IListener, public IPlugIn, public IVariable, public IStepable + { + public: + MARATHON_INSERT_PADDING(4); + xpointer m_pIsListening; + be m_State; + MARATHON_INSERT_PADDING(0x50); + be m_ActionA; + be m_ActionB; + be m_ActionC; + be m_ActionD; + TimedAction m_TimedAction; + }; +} diff --git a/MarathonRecomp/api/Sonicteam/Player/Input/TimedAction.h b/MarathonRecomp/api/Sonicteam/Player/Input/TimedAction.h new file mode 100644 index 000000000..2dee534ce --- /dev/null +++ b/MarathonRecomp/api/Sonicteam/Player/Input/TimedAction.h @@ -0,0 +1,17 @@ +#pragma once + +#include + +namespace Sonicteam::Player::Input +{ + struct TimedAction + { + be m_Time; + be m_Action; + bool m_Field08; + bool m_IsDoubleTapped; + bool m_Field0A; + bool m_Field0B; + be m_Field0C; + }; +} diff --git a/MarathonRecomp/api/Sonicteam/Player/Object.h b/MarathonRecomp/api/Sonicteam/Player/Object.h index 08da1315a..8323109b2 100644 --- a/MarathonRecomp/api/Sonicteam/Player/Object.h +++ b/MarathonRecomp/api/Sonicteam/Player/Object.h @@ -2,6 +2,7 @@ #include #include +#include #include #include #include @@ -14,52 +15,51 @@ namespace Sonicteam::Player { class Object : public Actor { - struct ObjectPlayerUpgrade + public: + struct CreationParams { - uint32_t GlobalFlag; - uint32_t EquipFlag; + xpointer pPlayerLua; + MARATHON_INSERT_PADDING(0x2C); + SoX::Math::Vector Position; }; - public: - class CreationParams + struct EquipFlags { - public: - xpointer m_pPlayerLua; - MARATHON_INSERT_PADDING(0x2C); - SoX::Math::Vector m_Position; + uint32_t GlobalFlag; + uint32_t EquipFlag; }; - stdx::string m_PlayerLua; - stdx::string m_PlayerPackage; + stdx::string m_LuaFile; + stdx::string m_PackageFile; be m_TargetCameraActorID; - xpointer m_pCameraman; // Here as MessageReceiver - be m_PlayerIndex; - be m_PlayerControllerIndex; + xpointer m_pCameraman; + be m_Index; + be m_ControllerIndex; SoX::Math::Quaternion m_SpawnRotation; SoX::Math::Vector m_SpawnPosition; - be m_SpawnRing; - SoX::RefSharedPointer<> m_spSpawnSource; // REF_TYPE(RefCountObject) + be m_SpawnRingCount; + SoX::RefSharedPointer<> m_spSpawnSource; bool m_IsPlayer; bool m_IsPosture; bool m_IsAmigo; MARATHON_INSERT_PADDING(1); SoX::RefSharedPointer m_spRootFrame; SoX::RefSharedPointer<> m_spPackageBinary; - boost::shared_ptr m_spPlayerModel; - boost::shared_ptr m_spPlayerPosture; + boost::shared_ptr m_spModel; + boost::shared_ptr m_spPostureControl; boost::shared_ptr m_spStateMachine; - boost::shared_ptr m_spPlayerGravity; - boost::shared_ptr m_spPlayerImpulse; + boost::shared_ptr m_spGravity; + boost::shared_ptr m_spImpulse; be m_SetupModuleIndexPrefix; be m_SetupModuleIndexPostfix; boost::shared_ptr m_spGauge; MARATHON_INSERT_PADDING(8); - stdx::vector> m_vspPlayerPlugins; + stdx::vector> m_vspPlugins; MARATHON_INSERT_PADDING(0x58); - be m_PlayerDelta; + be m_DeltaTime; MARATHON_INSERT_PADDING(0x48); - stdx::vector m_PlayerUpgrade; - stdx::string m_PlayerName; + stdx::vector m_vEquipFlags; + stdx::string m_Name; MARATHON_INSERT_PADDING(0x134); template @@ -71,7 +71,7 @@ namespace Sonicteam::Player template inline T* GetPlugin(const char* pluginName) { - for (auto& spPlugin : m_vspPlayerPlugins) + for (auto& spPlugin : m_vspPlugins) { if (spPlugin->m_Name == pluginName) return static_cast(spPlugin.get()); @@ -79,5 +79,18 @@ namespace Sonicteam::Player return nullptr; } + + SoX::Input::Manager* GetInputManager() + { + if (!m_IsPlayer) + return nullptr; + + auto pDoc = GetDoc(); + auto pGame = pDoc->GetDocMode()->GetGame(); + auto playerIndex = pGame->PlayerActorIDToIndex(m_ActorID); + auto controllerID = pDoc->m_PlayerControllerID[playerIndex]; + + return pDoc->m_vspInputManager[controllerID].get(); + } }; } diff --git a/MarathonRecomp/api/Sonicteam/Player/PostureControl.h b/MarathonRecomp/api/Sonicteam/Player/PostureControl.h index b57b60b81..12e32bcd0 100644 --- a/MarathonRecomp/api/Sonicteam/Player/PostureControl.h +++ b/MarathonRecomp/api/Sonicteam/Player/PostureControl.h @@ -14,25 +14,52 @@ namespace Sonicteam::Player class PostureControl : public IPostureControl, public IPostureSupportSphere, public IPostureSupportOttoto, public IPostureSupportEdge, public IPostureSupportInput, public IPostureSupportRayTemplate { public: - // Credit to Gordon Ramsay enum PostureFlag { - PostureFlag_Ground = 0x1, // Detects Ground - PostureFlag_WallBrushing = 0x8, // Detects brushing against a wall - PostureFlag_HeadOnWall = 0x10, // Detects head-on wall collision (will always be enabled w/ WallBrushing) - PostureFlag_RailGrind = 0x40, // Rail grinding - PostureFlag_BeforeFall = 0x100, // Seems like Neutral or Pre-Fall? The moment before transitioning from the Jump to Fall animation - PostureFlag_Fall = 0x200, // FALL - PostureFlag_WaterCollision = 0x800, // Water collision (making you slide down an incline)? BeforeFall is often set with this - PostureFlag_LightDash = 0x4000, // Light Dashing - PostureFlag_QuickRotate = 0x8000, // Is moving the control stick in a non-forward direction (usually only active for a frame since the character instantly rotates) - PostureFlag_Tentative = 0x10000, // Is Tentative collision - PostureFlag_WaterSlide = 0x20000, // Water sliding - PostureFlag_Grass = 0x100000, // Grass - PostureFlag_DirtClay = 0x200000, // Dirt/clay - PostureFlag_Stone = 0x400000, // Stone - PostureFlag_Shoreline = 0x1000000 // Shoreline? sand? Uncertain + // The player is grounded. + PostureFlag_Grounded = 0x01, + + // The player is brushing against a wall. + PostureFlag_WallSide = 0x08, + + // The player is head on against a wall. + PostureFlag_WallFront = 0x10, + + // The player is grinding on a rail. + PostureFlag_RailGrind = 0x40, + + // The player is in the intermediate state between jumping and falling. + PostureFlag_FallIntermediate = 0x100, + + // The player is falling. + PostureFlag_Fall = 0x200, + + // The player is on water collision. + PostureFlag_Water = 0x800, + + // The player is light dashing. + PostureFlag_LightDash = 0x4000, + + // The player is rotating in a non-forward direction. + PostureFlag_QuickRotate = 0x8000, + + // The player is on tentative collision. + PostureFlag_Tentative = 0x10000, + + // The player is water sliding. + PostureFlag_WaterSlide = 0x20000, + + // The player is on grass collision. + PostureFlag_Grass = 0x100000, + + // The player is on dirt collision. + PostureFlag_Dirt = 0x200000, + + // The player is on stone collision. + PostureFlag_Stone = 0x400000, + + // The player is on sand collision. + PostureFlag_Sand = 0x1000000 }; - // 0x314 ... 0x400 }; } diff --git a/MarathonRecomp/api/Sonicteam/Player/SonicGauge.h b/MarathonRecomp/api/Sonicteam/Player/SonicGauge.h index d628e4114..c80ad5170 100644 --- a/MarathonRecomp/api/Sonicteam/Player/SonicGauge.h +++ b/MarathonRecomp/api/Sonicteam/Player/SonicGauge.h @@ -11,16 +11,16 @@ namespace Sonicteam::Player be m_GroundedTime; be m_Flags; be m_GroundedFlags; - be m_Maximum; - be m_Green; - be m_Red; - be m_Blue; - be m_White; - be m_Sky; - be m_Yellow; - be m_Purple; - be m_Super; - be m_Heal; - be m_HealDelay; + be c_gauge_max; + be c_gauge_green; + be c_gauge_red; + be c_gauge_blue; + be c_gauge_white; + be c_gauge_sky; + be c_gauge_yellow; + be c_gauge_purple; + be c_gauge_super; + be c_gauge_heal; + be c_gauge_heal_delay; }; } diff --git a/MarathonRecomp/api/Sonicteam/Player/State/CommonContext.h b/MarathonRecomp/api/Sonicteam/Player/State/CommonContext.h index ce675d7e1..1b40fe196 100644 --- a/MarathonRecomp/api/Sonicteam/Player/State/CommonContext.h +++ b/MarathonRecomp/api/Sonicteam/Player/State/CommonContext.h @@ -13,18 +13,29 @@ namespace Sonicteam::Player::State { public: xpointer m_spComboAttackManager; - be m_ContextIFFlag1; - be m_ContextIFFlag2; - be m_ContextIFFlag3; - be m_ExportPostureRequestFlag; - be m_ExportWeaponRequestFlag; + be m_CommonContextIFFlags1; + be m_CommonContextIFFlags2; + be m_CommonContextIFFlags3; + be m_ExportPostureRequestFlags; + be m_ExportWeaponRequestFlags; MARATHON_INSERT_PADDING(0x14); - be m_PostureFlag; - be m_ExternalFlag; - be m_VehicleFlag; - be m_AmigoFlag; + be m_PostureFlags; + be m_ExternalFlags; + be m_VehicleFlags; + be m_AmigoFlags; MARATHON_INSERT_PADDING(0x50); boost::shared_ptr m_spScore; - MARATHON_INSERT_PADDING(0x100); + MARATHON_INSERT_PADDING(8); + boost::shared_ptr m_spInputListenerNormal; + boost::anonymous_shared_ptr m_spInputListenerAmigo; + MARATHON_INSERT_PADDING(0xE8); + + SoX::Input::Manager* GetInputManager() const + { + if (!m_spScore.get()) + return nullptr; + + return m_spScore->m_pPlayer->GetInputManager(); + } }; } diff --git a/MarathonRecomp/api/Sonicteam/Player/State/ICommonContext.h b/MarathonRecomp/api/Sonicteam/Player/State/ICommonContext.h index 1773308fe..e03c7e8d9 100644 --- a/MarathonRecomp/api/Sonicteam/Player/State/ICommonContext.h +++ b/MarathonRecomp/api/Sonicteam/Player/State/ICommonContext.h @@ -16,10 +16,9 @@ namespace Sonicteam::Player::State be m_LastVelocityVertical; be m_LastLockButtons; be m_Buttons; - be m_CurrentStickBorder; // 0 .. 1.0 + be m_CurrentStickBorder; MARATHON_INSERT_PADDING(4); - be m_AnimationState; // & 2 == 0 (Animation End, no any idea about others) + be m_AnimationState; MARATHON_INSERT_PADDING(0x2C); }; - //0x90 } diff --git a/MarathonRecomp/api/Sonicteam/Player/State/SonicContext.h b/MarathonRecomp/api/Sonicteam/Player/State/SonicContext.h index 028a8e502..bf987b731 100644 --- a/MarathonRecomp/api/Sonicteam/Player/State/SonicContext.h +++ b/MarathonRecomp/api/Sonicteam/Player/State/SonicContext.h @@ -10,7 +10,6 @@ namespace Sonicteam::Player::State class SonicContext : public CommonContext { public: - // Sprite enum GemSprite : uint32_t { GemSprite_Green = 1, @@ -35,14 +34,26 @@ namespace Sonicteam::Player::State Gem_Super }; + static constexpr GemSprite ms_GemSpriteConversionTable[8] = + { + GemSprite_Blue, + GemSprite_Red, + GemSprite_Green, + GemSprite_Purple, + GemSprite_Sky, + GemSprite_White, + GemSprite_Yellow, + GemSprite_Super + }; + be m_CurrentGemSprite; boost::shared_ptr m_Gauge; uint8_t m_HomingLockOn; uint8_t m_DisablePlayerMovement; uint8_t m_AntigravityHitBox; - uint8_t m_23F; + uint8_t m_Field23F; uint8_t m_BoundAttackHitBox; - uint8_t m_241; + uint8_t m_Field241; uint8_t m_Shrink; uint8_t m_ThunderGuard; uint8_t m_Tornado; @@ -51,8 +62,8 @@ namespace Sonicteam::Player::State uint8_t m_SlowTime; uint8_t m_MachAura; uint8_t m_GemsEnabled; - uint8_t m_24A; - uint8_t m_24B; + uint8_t m_Field24A; + uint8_t m_Field24B; be m_HomingFlip; be m_CurrentGem; MARATHON_INSERT_PADDING(0x58); diff --git a/MarathonRecomp/api/Sonicteam/PropFixture.h b/MarathonRecomp/api/Sonicteam/PropFixture.h new file mode 100644 index 000000000..78054b719 --- /dev/null +++ b/MarathonRecomp/api/Sonicteam/PropFixture.h @@ -0,0 +1,13 @@ +#pragma once + +#include +#include + +namespace Sonicteam +{ + class PropFixture : public Fixture + { + public: + MARATHON_INSERT_PADDING(0x10); + }; +} diff --git a/MarathonRecomp/api/Sonicteam/SoX/AI/StateMachine.h b/MarathonRecomp/api/Sonicteam/SoX/AI/StateMachine.h index c3b7b17bd..3d9e070e3 100644 --- a/MarathonRecomp/api/Sonicteam/SoX/AI/StateMachine.h +++ b/MarathonRecomp/api/Sonicteam/SoX/AI/StateMachine.h @@ -4,13 +4,13 @@ namespace Sonicteam::SoX::AI { - template + template class StateMachine { public: xpointer m_pVftable; - xpointer> m_pState; - xpointer m_pContext; + xpointer> m_pState; + xpointer m_pContext; template TState* GetState() @@ -18,6 +18,12 @@ namespace Sonicteam::SoX::AI return (TState*)m_pState.get(); } + TStateContext* GetContext() + { + return (TStateContext*)m_pContext.get(); + } + + template TContext* GetContext() { return (TContext*)m_pContext.get(); diff --git a/MarathonRecomp/api/Sonicteam/SoX/Audio/Cue.h b/MarathonRecomp/api/Sonicteam/SoX/Audio/Cue.h new file mode 100644 index 000000000..601a9d1c5 --- /dev/null +++ b/MarathonRecomp/api/Sonicteam/SoX/Audio/Cue.h @@ -0,0 +1,34 @@ +#pragma once + +#include +#include +#include + +namespace Sonicteam::SoX::Audio +{ + class Cue : public RefCountObject + { + public: + struct Vftable : RefCountObject::Vftable + { + MARATHON_INSERT_PADDING(0x18); + be fpSetPause; + }; + + MARATHON_INSERT_PADDING(0x0C); + LinkNode m_Field14; + MARATHON_INSERT_PADDING(8); + xpointer m_pPlayer; + + template + T* GetPlayer() + { + return (T*)m_pPlayer.get(); + } + + void SetPause(bool isPaused) + { + GuestToHostFunction(((Vftable*)m_pVftable.get())->fpSetPause, this, isPaused); + } + }; +} diff --git a/MarathonRecomp/api/Sonicteam/SoX/Audio/Player.h b/MarathonRecomp/api/Sonicteam/SoX/Audio/Player.h new file mode 100644 index 000000000..24a4943ad --- /dev/null +++ b/MarathonRecomp/api/Sonicteam/SoX/Audio/Player.h @@ -0,0 +1,12 @@ +#pragma once + +#include + +namespace Sonicteam::SoX::Audio +{ + class Player + { + public: + xpointer m_pVftable; + }; +} diff --git a/MarathonRecomp/api/Sonicteam/SoX/Audio/PlayerImpl.h b/MarathonRecomp/api/Sonicteam/SoX/Audio/PlayerImpl.h new file mode 100644 index 000000000..445509d6a --- /dev/null +++ b/MarathonRecomp/api/Sonicteam/SoX/Audio/PlayerImpl.h @@ -0,0 +1,8 @@ +#pragma once + +#include + +namespace Sonicteam::SoX::Audio +{ + class PlayerImpl : public Player {}; +} diff --git a/MarathonRecomp/api/Sonicteam/SoX/Engine/Task.h b/MarathonRecomp/api/Sonicteam/SoX/Engine/Task.h index 23ac88e6a..310196f6f 100644 --- a/MarathonRecomp/api/Sonicteam/SoX/Engine/Task.h +++ b/MarathonRecomp/api/Sonicteam/SoX/Engine/Task.h @@ -38,5 +38,11 @@ namespace Sonicteam::SoX::Engine { return m_pDependencies.get(); } + + template + T* GetDoc() + { + return (T*)m_pDoc.get(); + } }; } diff --git a/MarathonRecomp/api/Sonicteam/SoX/IResource2.h b/MarathonRecomp/api/Sonicteam/SoX/IResource2.h index 2251aa7d0..fc01e8bbd 100644 --- a/MarathonRecomp/api/Sonicteam/SoX/IResource2.h +++ b/MarathonRecomp/api/Sonicteam/SoX/IResource2.h @@ -2,6 +2,7 @@ #include #include +#include namespace Sonicteam::SoX { diff --git a/MarathonRecomp/api/Sonicteam/SoX/Input/Manager.h b/MarathonRecomp/api/Sonicteam/SoX/Input/Manager.h index b4558da1e..00f7b1bf4 100644 --- a/MarathonRecomp/api/Sonicteam/SoX/Input/Manager.h +++ b/MarathonRecomp/api/Sonicteam/SoX/Input/Manager.h @@ -49,7 +49,7 @@ namespace Sonicteam::SoX::Input class Manager { public: - be m_ControllerID; + be m_ControllerIndex; MARATHON_INSERT_PADDING(0xC); PadState m_PadState; MARATHON_INSERT_PADDING(0x28); diff --git a/MarathonRecomp/api/Sonicteam/SoX/Math/Vector.h b/MarathonRecomp/api/Sonicteam/SoX/Math/Vector.h index 1fcd91326..e3ac86e36 100644 --- a/MarathonRecomp/api/Sonicteam/SoX/Math/Vector.h +++ b/MarathonRecomp/api/Sonicteam/SoX/Math/Vector.h @@ -27,11 +27,6 @@ namespace Sonicteam::SoX::Math be Z; be W; - Vector operator+(float addend) - { - return { X + addend, Y + addend, Z + addend, W + addend }; - } - float DistanceTo(const Vector& other) const { float dx = static_cast(X) - static_cast(other.X); @@ -40,5 +35,10 @@ namespace Sonicteam::SoX::Math return std::sqrt(dx * dx + dy * dy + dz * dz); } + + Vector operator+(float addend) + { + return { X + addend, Y + addend, Z + addend, W + addend }; + } }; } diff --git a/MarathonRecomp/api/Sonicteam/SoX/MessageReceiver.h b/MarathonRecomp/api/Sonicteam/SoX/MessageReceiver.h index 9858a8cce..cca227a2b 100644 --- a/MarathonRecomp/api/Sonicteam/SoX/MessageReceiver.h +++ b/MarathonRecomp/api/Sonicteam/SoX/MessageReceiver.h @@ -11,14 +11,19 @@ namespace Sonicteam::SoX struct Vftable { be fpDestroy; - be fpOnMessageReceived; + be fpProcessMessage; }; xpointer m_pVftable; - bool OnMessageReceived(IMessage* pMessage) + void* Destroy(uint8_t flags = 1) { - return GuestToHostFunction(m_pVftable->fpOnMessageReceived, this, pMessage); + return GuestToHostFunction(m_pVftable->fpDestroy, this, flags); + } + + bool ProcessMessage(IMessage* pMessage) + { + return GuestToHostFunction(m_pVftable->fpProcessMessage, this, pMessage); } }; } diff --git a/MarathonRecomp/api/Sonicteam/SoX/RefCountObject.h b/MarathonRecomp/api/Sonicteam/SoX/RefCountObject.h index 3b1c4101a..9eef91441 100644 --- a/MarathonRecomp/api/Sonicteam/SoX/RefCountObject.h +++ b/MarathonRecomp/api/Sonicteam/SoX/RefCountObject.h @@ -15,6 +15,11 @@ namespace Sonicteam::SoX xpointer m_pVftable; be m_ReferenceCount; + void* Destroy(uint32_t flag = 1) + { + return GuestToHostFunction(m_pVftable->fpDestroy, this, flag); + } + void Release(uint32_t flag = 1) { m_ReferenceCount = m_ReferenceCount - 1; @@ -23,14 +28,9 @@ namespace Sonicteam::SoX Destroy(flag); } - inline void AddRef() + inline void AddReference() { m_ReferenceCount = m_ReferenceCount + 1; } - - void* Destroy(uint32_t flag) - { - return GuestToHostFunction(m_pVftable->fpDestroy, this, flag); - } }; } diff --git a/MarathonRecomp/api/Sonicteam/System/CreateStatic.h b/MarathonRecomp/api/Sonicteam/System/CreateStatic.h index 76b99ed34..f888e16a9 100644 --- a/MarathonRecomp/api/Sonicteam/System/CreateStatic.h +++ b/MarathonRecomp/api/Sonicteam/System/CreateStatic.h @@ -2,13 +2,13 @@ namespace Sonicteam::System { - template + template class CreateStatic { public: static T* Create() { - return GuestToHostFunction(TCreator); + return GuestToHostFunction(fpCreator); } }; } diff --git a/MarathonRecomp/api/Sonicteam/System/Singleton.h b/MarathonRecomp/api/Sonicteam/System/Singleton.h index 336e58c18..11ac491f4 100644 --- a/MarathonRecomp/api/Sonicteam/System/Singleton.h +++ b/MarathonRecomp/api/Sonicteam/System/Singleton.h @@ -2,7 +2,7 @@ namespace Sonicteam::System { - template + template class Singleton { inline static TCreator ms_Creator{}; @@ -10,7 +10,7 @@ namespace Sonicteam::System public: static T* GetInstance() { - auto pInstance = (xpointer*)g_memory.Translate(Ptr); + auto pInstance = (xpointer*)g_memory.Translate(pSingleton); if (!pInstance->ptr.get()) *pInstance = ms_Creator.Create(); diff --git a/MarathonRecomp/api/Sonicteam/TextBook.h b/MarathonRecomp/api/Sonicteam/TextBook.h index f0c9185ec..18bc4757e 100644 --- a/MarathonRecomp/api/Sonicteam/TextBook.h +++ b/MarathonRecomp/api/Sonicteam/TextBook.h @@ -1,7 +1,9 @@ #pragma once #include +#include #include +#include #include namespace Sonicteam diff --git a/MarathonRecomp/api/Sonicteam/TextBookMgr.h b/MarathonRecomp/api/Sonicteam/TextBookMgr.h index 3c269d094..18335fce5 100644 --- a/MarathonRecomp/api/Sonicteam/TextBookMgr.h +++ b/MarathonRecomp/api/Sonicteam/TextBookMgr.h @@ -1,6 +1,8 @@ #pragma once #include +#include +#include namespace Sonicteam { diff --git a/MarathonRecomp/api/Sonicteam/sonicXmaPlayer.h b/MarathonRecomp/api/Sonicteam/sonicXmaPlayer.h new file mode 100644 index 000000000..d99d20e8d --- /dev/null +++ b/MarathonRecomp/api/Sonicteam/sonicXmaPlayer.h @@ -0,0 +1,13 @@ +#pragma once + +#include + +namespace Sonicteam +{ + class sonicXmaPlayer : public SoX::RefCountObject + { + public: + MARATHON_INSERT_PADDING(0xD8); + bool m_IsPaused; + }; +} diff --git a/MarathonRecomp/api/stdx/wstring.h b/MarathonRecomp/api/stdx/wstring.h index 3d13b0ab5..334277b02 100644 --- a/MarathonRecomp/api/stdx/wstring.h +++ b/MarathonRecomp/api/stdx/wstring.h @@ -23,7 +23,7 @@ namespace stdx bool is_short() const { - return _Mysize <= 8; + return _Mysize < 8; } public: diff --git a/MarathonRecomp/app.h b/MarathonRecomp/app.h index da7fe65a9..1fb797236 100644 --- a/MarathonRecomp/app.h +++ b/MarathonRecomp/app.h @@ -7,6 +7,7 @@ class App { public: static inline bool s_isInit; + static inline bool s_isSkipLogos; static inline bool s_isMissingDLC; static inline bool s_isLoading; static inline bool s_isSaving; diff --git a/MarathonRecomp/apu/driver/sdl2_driver.cpp b/MarathonRecomp/apu/driver/sdl2_driver.cpp index 29be3b9a2..a2615f44f 100644 --- a/MarathonRecomp/apu/driver/sdl2_driver.cpp +++ b/MarathonRecomp/apu/driver/sdl2_driver.cpp @@ -2,6 +2,7 @@ #include #include #include +#include #include static PPCFunc* g_clientCallback{}; @@ -110,6 +111,10 @@ void XAudioRegisterClient(PPCFunc* callback, uint32_t param) void XAudioSubmitFrame(void* samples) { auto floatSamples = reinterpret_cast*>(samples); + auto volume = Config::MasterVolume.Value; + + if (Config::MuteOnFocusLost && !GameWindow::s_isFocused) + volume = 0.0f; if (g_downMixToStereo) { @@ -131,8 +136,8 @@ void XAudioSubmitFrame(void* samples) float ch4 = floatSamples[4 * XAUDIO_NUM_SAMPLES + i]; float ch5 = floatSamples[5 * XAUDIO_NUM_SAMPLES + i]; - float samp0 = (ch0 + ch2 * 0.75f + ch4) * Config::MasterVolume; - float samp1 = (ch1 + ch2 * 0.75f + ch5) * Config::MasterVolume; + float samp0 = (ch0 + ch2 * 0.75f + ch4) * volume; + float samp1 = (ch1 + ch2 * 0.75f + ch5) * volume; audioFrames[i * 2 + 0] = isnan(samp0) ? 0.0f : samp0; audioFrames[i * 2 + 1] = isnan(samp1) ? 0.0f : samp1; @@ -146,8 +151,9 @@ void XAudioSubmitFrame(void* samples) for (size_t i = 0; i < XAUDIO_NUM_SAMPLES; i++) { - for (size_t j = 0; j < XAUDIO_NUM_CHANNELS; j++) { - float samp = floatSamples[j * XAUDIO_NUM_SAMPLES + i] * Config::MasterVolume; + for (size_t j = 0; j < XAUDIO_NUM_CHANNELS; j++) + { + float samp = floatSamples[j * XAUDIO_NUM_SAMPLES + i] * volume; audioFrames[i * 2 + j] = isnan(samp) ? 0.0f : samp; } } diff --git a/MarathonRecomp/framework.h b/MarathonRecomp/framework.h index 96c993058..5730c2842 100644 --- a/MarathonRecomp/framework.h +++ b/MarathonRecomp/framework.h @@ -83,3 +83,27 @@ inline bool strcmpIgnoreCase(const char* a, const char* b) return true; } + +inline bool strcmpWildcard(const char* str, const char* pattern) +{ + // Match if both strings passed all + // comparisons and reached the end. + if (*pattern == '\0' && *str == '\0') + return true; + + // Check if any number of chars matches. + if (*pattern == '*') + { + // Skip duplicates. + while (*(pattern + 1) == '*') + pattern++; + + return strcmpWildcard(str, pattern + 1) || (*str && strcmpWildcard(str + 1, pattern)); + } + + // Check if current char matches. + if (*pattern == '?' || *pattern == *str) + return strcmpWildcard(str + 1, pattern + 1); + + return false; +} diff --git a/MarathonRecomp/gpu/imgui/imgui_font_builder.cpp b/MarathonRecomp/gpu/imgui/imgui_font_builder.cpp index 0b2e28d76..5d28610c9 100644 --- a/MarathonRecomp/gpu/imgui/imgui_font_builder.cpp +++ b/MarathonRecomp/gpu/imgui/imgui_font_builder.cpp @@ -220,10 +220,19 @@ static bool FontBuilder_Build(ImFontAtlas* atlas) for (size_t i = 0; i < atlas->ConfigData.size(); i++) { + auto& config = atlas->ConfigData[i]; + double spaceAdvance = 0.0; + double spaceMultiplier = 1.0; - auto& config = atlas->ConfigData[i]; - bool increaseSpacing = strstr(config.Name, "Rodin") != nullptr; + if (strstr(config.Name, "FOT-Rodin") != nullptr) + { + spaceMultiplier = 1.75; + } + else if (strstr(config.Name, "FOT-NewRodin") != nullptr) + { + spaceMultiplier = 2.5; + } auto& [index, count] = ranges[i]; for (size_t j = 0; j < count; j++) @@ -236,11 +245,7 @@ static bool FontBuilder_Build(ImFontAtlas* atlas) double advance = glyph.getAdvance(); if (glyph.getCodepoint() == ' ') { - if (increaseSpacing) - { - advance *= 1.75; - } - + advance *= spaceMultiplier; spaceAdvance = advance; } diff --git a/MarathonRecomp/gpu/video.cpp b/MarathonRecomp/gpu/video.cpp index 3966b4e0b..8eef90562 100644 --- a/MarathonRecomp/gpu/video.cpp +++ b/MarathonRecomp/gpu/video.cpp @@ -22,7 +22,7 @@ #include #include #include -#include +#include #include #include #include @@ -1580,8 +1580,6 @@ static void CreateImGuiBackend() InitImGuiUtils(); AchievementMenu::Init(); AchievementOverlay::Init(); - ButtonGuide::Init(); - MessageWindow::Init(); OptionsMenu::Init(); InstallerWizard::Init(); @@ -2848,10 +2846,10 @@ static void DrawImGui() #endif AchievementMenu::Draw(); -// OptionsMenu::Draw(); + OptionsMenu::Draw(); AchievementOverlay::Draw(); InstallerWizard::Draw(); - ButtonGuide::Draw(); + ButtonWindow::Draw(); MessageWindow::Draw(); Fader::Draw(); BlackBar::Draw(); @@ -3267,43 +3265,26 @@ void Video::ComputeViewportDimensions() switch (Config::AspectRatio) { - case EAspectRatio::Wide: - { - if (aspectRatio > WIDE_ASPECT_RATIO) - { - s_viewportWidth = height * 16 / 9; - s_viewportHeight = height; - } - else + case EAspectRatio::Original: { - s_viewportWidth = width; - s_viewportHeight = width * 9 / 16; - } - - break; - } + if (aspectRatio > WIDE_ASPECT_RATIO) + { + s_viewportWidth = height * 16 / 9; + s_viewportHeight = height; + } + else + { + s_viewportWidth = width; + s_viewportHeight = width * 9 / 16; + } - case EAspectRatio::Narrow: - case EAspectRatio::OriginalNarrow: - { - if (aspectRatio > NARROW_ASPECT_RATIO) - { - s_viewportWidth = height * 4 / 3; - s_viewportHeight = height; - } - else - { - s_viewportWidth = width; - s_viewportHeight = width * 3 / 4; + break; } - break; - } - - default: - s_viewportWidth = width; - s_viewportHeight = height; - break; + default: + s_viewportWidth = width; + s_viewportHeight = height; + break; } AspectRatioPatches::ComputeOffsets(); @@ -4095,12 +4076,8 @@ static void ProcSetViewport(const RenderCommand& cmd) static void SetTexture(GuestDevice* device, uint32_t index, GuestTexture* texture) { // printf("SetTexture: %x %d %x\n", device, index, texture); - auto isPlayStation = Config::ControllerIcons == EControllerIcons::PlayStation; - - if (Config::ControllerIcons == EControllerIcons::Auto) - isPlayStation = hid::g_inputDeviceController == hid::EInputDevice::PlayStation; - if (isPlayStation && texture != nullptr && texture->patchedTexture != nullptr) + if (Config::IsControllerIconsPS3() && texture != nullptr && texture->patchedTexture != nullptr) texture = texture->patchedTexture.get(); RenderCommand cmd; @@ -6198,15 +6175,17 @@ static void DiffPatchTexture(GuestTexture& texture, uint8_t* data, uint32_t data auto entries = reinterpret_cast(g_buttonBcDiff.get() + header->entriesOffset); auto end = entries + header->entryCount; - XXH64_hash_t hash = XXH3_64bits(data, dataSize); + auto hash = XXH3_64bits(data, dataSize); + auto findResult = std::lower_bound(entries, end, hash, [](BlockCompressionDiffPatchEntry& lhs, XXH64_hash_t rhs) - { - return lhs.hash < rhs; - }); + { + return lhs.hash < rhs; + }); if (findResult != end && findResult->hash == hash) { auto patch = reinterpret_cast(g_buttonBcDiff.get() + findResult->patchesOffset); + for (size_t i = 0; i < findResult->patchCount; i++) { assert(patch->destinationOffset + patch->patchBytesSize <= dataSize); @@ -6215,6 +6194,7 @@ static void DiffPatchTexture(GuestTexture& texture, uint8_t* data, uint32_t data } GuestTexture patchedTexture(ResourceType::Texture); + if (LoadTexture(patchedTexture, data, dataSize, {})) texture.patchedTexture = std::make_unique(std::move(patchedTexture)); } @@ -6229,12 +6209,10 @@ static void MakePictureData(GuestMyTexture* pictureData, uint8_t* data, uint32_t if (LoadTexture(texture, data, dataSize, {})) { #ifdef _DEBUG - if (pictureData->str1.size.get() > 0) { + if (pictureData->str1.size.get() > 0) texture.texture->setName(fmt::format("Texture {}", pictureData->str1.c_str())); - } #endif - - // DiffPatchTexture(texture, data, dataSize); + DiffPatchTexture(texture, data, dataSize); pictureData->texture = g_memory.MapVirtual(g_userHeap.AllocPhysical(std::move(texture))); pictureData->width = texture.width; diff --git a/MarathonRecomp/kernel/xam.cpp b/MarathonRecomp/kernel/xam.cpp index 12eea8337..8e13a58ec 100644 --- a/MarathonRecomp/kernel/xam.cpp +++ b/MarathonRecomp/kernel/xam.cpp @@ -517,7 +517,7 @@ uint32_t XamInputSetState(uint32_t userIndex, uint32_t flags, XAMINPUT_VIBRATION if (userIndex != 0) return ERROR_NO_SUCH_USER; - if (!hid::IsInputDeviceController() || !Config::Vibration) + if (!hid::IsInputDeviceController()) return ERROR_SUCCESS; ByteSwapInplace(vibration->wLeftMotorSpeed); diff --git a/MarathonRecomp/locale/config_locale.cpp b/MarathonRecomp/locale/config_locale.cpp index 0c15f5672..0d0692d85 100644 --- a/MarathonRecomp/locale/config_locale.cpp +++ b/MarathonRecomp/locale/config_locale.cpp @@ -48,12 +48,12 @@ CONFIG_DEFINE_LOCALE(Language) { - { ELanguage::English, { "Language", "Change the language used for text and logos." } }, - { ELanguage::Japanese, { "言語", "ゲーム内の\u200B表示言語を\u200B変更できます" } }, - { ELanguage::German, { "Sprache", "Ändere die Sprache für Text und Logos." } }, - { ELanguage::French, { "Langue", "Modifie la langue utilisée pour le texte et logos." } }, - { ELanguage::Spanish, { "Idioma", "Cambia el idioma utilizado para el texto y los logos." } }, - { ELanguage::Italian, { "Lingua", "Cambia la lingua utilizzata per i testi e i logo." } } + { ELanguage::English, { "Language", "Change the language used for text." } }, + { ELanguage::Japanese, { "言語", "ゲーム内の表示言語を変更できます" } }, + { ELanguage::German, { "Sprache", "Ändere die Textsprache." } }, + { ELanguage::French, { "Langue", "Modifier la langue utilisée pour le texte." } }, + { ELanguage::Spanish, { "Idioma", "Cambia el idioma utilizado para los textos." } }, + { ELanguage::Italian, { "Lingua", "Cambia la lingua utilizzata per il testo." } } }; // Notes: do not localise this. @@ -62,23 +62,33 @@ CONFIG_DEFINE_ENUM_LOCALE(ELanguage) { ELanguage::English, { - { ELanguage::English, { "ENGLISH", "" } }, + { ELanguage::English, { "English", "" } }, { ELanguage::Japanese, { "日本語", "" } }, - { ELanguage::German, { "DEUTSCH", "" } }, - { ELanguage::French, { "FRANÇAIS", "" } }, - { ELanguage::Spanish, { "ESPAÑOL", "" } }, - { ELanguage::Italian, { "ITALIANO", "" } } + { ELanguage::German, { "Deutsch", "" } }, + { ELanguage::French, { "Français", "" } }, + { ELanguage::Spanish, { "Español", "" } }, + { ELanguage::Italian, { "Italiano", "" } } } } }; +CONFIG_DEFINE_LOCALE(VoiceLanguage) +{ + { ELanguage::English, { "Voice Language", "Change the language used for character voices." } }, + { ELanguage::Japanese, { "音声言語", "ゲーム内の音声言語を変更できます" } }, + { ELanguage::German, { "Stimmeinstellung", "Ändere die Sprache, die für Charakterstimmen benutzt wird." } }, + { ELanguage::French, { "Langue de doublage", "Modifie la langue utilisée pour la voix des personnages." } }, + { ELanguage::Spanish, { "Idioma de voz", "Cambia el idioma utilizado para las voces de los personajes." } }, + { ELanguage::Italian, { "Lingua delle voci", "Modifica la lingua utilizzata per le voci dei personaggi." } } +}; + CONFIG_DEFINE_ENUM_LOCALE(EVoiceLanguage) { { ELanguage::English, { - { EVoiceLanguage::English, { "ENGLISH", "" } }, - { EVoiceLanguage::Japanese, { "JAPANESE", "" } } + { EVoiceLanguage::English, { "English", "" } }, + { EVoiceLanguage::Japanese, { "Japanese", "" } } } }, { @@ -91,37 +101,47 @@ CONFIG_DEFINE_ENUM_LOCALE(EVoiceLanguage) { ELanguage::German, { - { EVoiceLanguage::English, { "ENGLISCH", "" } }, - { EVoiceLanguage::Japanese, { "JAPANISCH", "" } } + { EVoiceLanguage::English, { "Englisch", "" } }, + { EVoiceLanguage::Japanese, { "Japanisch", "" } } } }, { ELanguage::French, { - { EVoiceLanguage::English, { "ANGLAIS", "" } }, - { EVoiceLanguage::Japanese, { "JAPONAIS", "" } } + { EVoiceLanguage::English, { "Anglais", "" } }, + { EVoiceLanguage::Japanese, { "Japonais", "" } } } }, { ELanguage::Spanish, { - { EVoiceLanguage::English, { "INGLÉS", "" } }, - { EVoiceLanguage::Japanese, { "JAPONÉS", "" } } + { EVoiceLanguage::English, { "Inglés", "" } }, + { EVoiceLanguage::Japanese, { "Japonés", "" } } } }, { ELanguage::Italian, { - { EVoiceLanguage::English, { "INGLESE", "" } }, - { EVoiceLanguage::Japanese, { "GIAPPONESE", "" } } + { EVoiceLanguage::English, { "Inglese", "" } }, + { EVoiceLanguage::Japanese, { "Giapponese", "" } } } }, }; +CONFIG_DEFINE_LOCALE(Subtitles) +{ + { ELanguage::English, { "Subtitles", "Show subtitles during dialogue." } }, + { ELanguage::Japanese, { "字幕", "字幕の表示を選択できます" } }, + { ELanguage::German, { "Untertitel", "Zeige Untertitel bei Dialogen." } }, + { ELanguage::French, { "Sous-titres", "Affiche les sous-titres pendant les dialogues." } }, + { ELanguage::Spanish, { "Subtítulos", "Muestra subtítulos durante los diálogos." } }, + { ELanguage::Italian, { "Sottotitoli", "Mostra i sottotitoli durante i dialoghi." } } +}; + CONFIG_DEFINE_LOCALE(Hints) { { ELanguage::English, { "Hints", "Show hints during gameplay." } }, - { ELanguage::Japanese, { "ヒントリング", "ゲーム内に\u200Bヒントリングを\u200B表示するか\u200B選択できます" } }, + { ELanguage::Japanese, { "ヒントリング", "ゲーム内にヒントリングを表示するか選択できます" } }, { ELanguage::German, { "Hinweise", "Zeige Hinweise während des Spiels." } }, { ELanguage::French, { "Indices", "Affiche les indices pendant le jeu." } }, { ELanguage::Spanish, { "Pistas", "Muestra pistas durante el juego." } }, @@ -130,38 +150,114 @@ CONFIG_DEFINE_LOCALE(Hints) CONFIG_DEFINE_LOCALE(ControlTutorial) { - { ELanguage::English, { "Control Tutorial", "Show controller hints during gameplay.\n\nThe Werehog Critical Attack prompt will be unaffected." } }, - { ELanguage::Japanese, { "アクションナビ", "ゲーム内に\u200Bアクションナビを\u200B表示するか\u200B選択できます\n\n「チャンスアタック」の\u200B表示は\u200B影響されません" } }, - { ELanguage::German, { "Steuerungsanleitung", "Zeige Steuerungshinweise während des Spiels.\n\nKritische Angriffe des Werehogs werden hiervon nicht beeinflusst." } }, - { ELanguage::French, { "Indication des commandes", "Affiche les indications des commandes pendant le jeu.\n\nCeci n'affecte pas les Coup critique du Werehog." } }, - { ELanguage::Spanish, { "Tutorial de controles", "Muestra pistas de controles durante el juego.\n\nEl indicador de ataque crítico del Werehog no se verá afectado." } }, - { ELanguage::Italian, { "Tutorial dei comandi", "Mostra i tutorial dei comandi durante il gioco.\n\nIl tutorial per l'attacco critico del Werehog non verrà influenzato da questa opzione." } } + { ELanguage::English, { "Control Tutorial", "Show controller hints during gameplay." } }, + { ELanguage::Japanese, { "アクションナビ", "ゲーム内にアクションナビを表示するか選択できます" } }, + { ELanguage::German, { "Steuerungsanleitung", "Zeige Steuerungshinweise während des Spiels." } }, + { ELanguage::French, { "Indication des commandes", "Affiche les indications des commandes pendant le jeu." } }, + { ELanguage::Spanish, { "Tutorial de controles", "Muestra pistas de controles durante el juego." } }, + { ELanguage::Italian, { "Tutorial dei comandi", "Mostra i tutorial dei comandi durante il gioco." } } }; CONFIG_DEFINE_LOCALE(Autosave) { { ELanguage::English, { "Autosave", "Save the game automatically at manual save points." } }, - { ELanguage::Japanese, { "", "" } }, - { ELanguage::German, { "", "" } }, - { ELanguage::French, { "", "" } }, - { ELanguage::Spanish, { "", "" } }, - { ELanguage::Italian, { "", "" } } + { ELanguage::Japanese, { "オートセーブ", "手動セーブポイントでゲームを自動的にセーブします" } }, + { ELanguage::German, { "Automatisches Speichern", "Speichert das Spiel automatisch an manuellen Speicherpunkten." } }, + { ELanguage::French, { "Sauvegarde Auto", "Sauvegarder automatiquement la partie lorsque le jeu propose une sauvegarde." } }, + { ELanguage::Spanish, { "Autoguardado", "Guarda el juego automáticamente en los puntos de guardado manuales." } }, + { ELanguage::Italian, { "Salvataggio automatico", "Salva automaticamente il gioco nei punti di salvataggio manuali." } } }; CONFIG_DEFINE_LOCALE(AchievementNotifications) { - { ELanguage::English, { "Achievement Notifications", "Show notifications for unlocking achievements.\n\nAchievements will still be rewarded with notifications disabled." } }, - { ELanguage::Japanese, { "実績通知", "実績通知の\u200B有無を\u200B選択できます\n\nオフにしても\u200B実績は\u200B付与されます" } }, - { ELanguage::German, { "Erfolgsbenachrichtigungen", "Zeige Benachrichtigungen für das Freischalten von Erfolgen.\n\nErfolge werden weiterhin freigeschaltet, auch wenn die Benachrichtigungen ausgeschaltet sind." } }, - { ELanguage::French, { "Notification des succès", "Affiche les notifications pour le déverrouillage des succès.\n\nLes succès seront toujours obtenus même si les notifications sont désactivées." } }, - { ELanguage::Spanish, { "Notificaciones de logros", "Muestra notificaciones al desbloquear logros.\n\nLos logros se seguirán obteniendo aunque las notificaciones estén desactivadas." } }, - { ELanguage::Italian, { "Notifiche obiettivi", "Mostra delle notifiche quando sblocchi degli obiettivi.\n\nGli obiettivi verranno comunque assegnati anche con le notifiche disattivate." } } + { ELanguage::English, { "Achievement Notifications", "Show notifications for unlocking achievements. Achievements will still be rewarded with notifications disabled." } }, + { ELanguage::Japanese, { "実績通知", "実績通知の有無を選択できます オフにしても実績は付与されます" } }, + { ELanguage::German, { "Erfolgsbenachrichtigungen", "Zeige Benachrichtigungen für das Freischalten von Erfolgen. Erfolge werden weiterhin freigeschaltet, auch wenn die Benachrichtigungen ausgeschaltet sind." } }, + { ELanguage::French, { "Notification des succès", "Affiche les notifications pour le déverrouillage des succès. Les succès seront toujours obtenus même si les notifications sont désactivées." } }, + { ELanguage::Spanish, { "Notificaciones de logros", "Muestra notificaciones al desbloquear logros. Los logros se seguirán obteniendo aunque las notificaciones estén desactivadas." } }, + { ELanguage::Italian, { "Notifiche obiettivi", "Mostra delle notifiche quando sblocchi degli obiettivi. Gli obiettivi verranno comunque assegnati anche con le notifiche disattivate." } } +}; + +CONFIG_DEFINE_LOCALE(HorizontalCamera) +{ + { ELanguage::English, { "Horizontal Camera", "Change how the camera moves left and right." } }, + { ELanguage::Japanese, { "カメラの左右", "カメラ左右の動く方向を選択できます" } }, + { ELanguage::German, { "Horizontale Kamera", "Ändere wie sich die Kamera nach links und rechts bewegt." } }, + { ELanguage::French, { "Caméra horizontale", "Modifie la rotation horizontale de la caméra." } }, + { ELanguage::Spanish, { "Cámara horizontal", "Cambia cómo se mueve la camara hacia la izquierda y la derecha." } }, + { ELanguage::Italian, { "Telecamera orizzontale", "Modifica come la telecamera si muove da sinistra a destra." } } +}; + +CONFIG_DEFINE_LOCALE(VerticalCamera) +{ + { ELanguage::English, { "Vertical Camera", "Change how the camera moves up and down." } }, + { ELanguage::Japanese, { "カメラの上下", "カメラ上下の動く方向を選択できます" } }, + { ELanguage::German, { "Vertikale Kamera", "Ändere wie sich die Kamera nach oben und unten bewegt." } }, + { ELanguage::French, { "Caméra verticale", "Modifie la rotation verticale de la caméra." } }, + { ELanguage::Spanish, { "Cámara vertical", "Cambia cómo se mueve la camara hacia arriba y abajo." } }, + { ELanguage::Italian, { "Telecamera verticale", "Modifica come la telecamera si muove su e giù." } } +}; + +CONFIG_DEFINE_ENUM_LOCALE(ECameraRotationMode) +{ + { + ELanguage::English, + { + { ECameraRotationMode::Normal, { "Normal", "" } }, + { ECameraRotationMode::Reverse, { "Reverse", "" } } + } + }, + { + ELanguage::Japanese, + { + { ECameraRotationMode::Normal, { "ノーマル", "" } }, + { ECameraRotationMode::Reverse, { "リバース", "" } } + } + }, + { + ELanguage::German, + { + { ECameraRotationMode::Normal, { "Normal", "" } }, + { ECameraRotationMode::Reverse, { "Invertiert", "" } } + } + }, + { + ELanguage::French, + { + { ECameraRotationMode::Normal, { "Normale", "" } }, + { ECameraRotationMode::Reverse, { "Inversée", "" } } + } + }, + { + ELanguage::Spanish, + { + { ECameraRotationMode::Normal, { "Normal", "" } }, + { ECameraRotationMode::Reverse, { "Invertido", "" } } + } + }, + { + ELanguage::Italian, + { + { ECameraRotationMode::Normal, { "Normale", "" } }, + { ECameraRotationMode::Reverse, { "Invertita", "" } } + } + } +}; + +CONFIG_DEFINE_LOCALE(AllowBackgroundInput) +{ + { ELanguage::English, { "Allow Background Input", "Allow controller input whilst the game window is unfocused." } }, + { ELanguage::Japanese, { "バックグラウンド入力", "フォーカスされていないゲームに入力できるか選択できます" } }, + { ELanguage::German, { "Erlaube Hintergrundeingaben", "Erlaube Eingaben deines Controllers auch wenn das Spielfenster nicht fokussiert ist." } }, + { ELanguage::French, { "Manette en arrière plan", "Permet d'utiliser la manette dans le jeu lorsque qu'il n'est pas au premier plan." } }, + { ELanguage::Spanish, { "Control en segundo plano", "Permite controlar el juego con un mando mientras la ventana esté en segundo plano." } }, + { ELanguage::Italian, { "Input con la finestra inattiva", "Attiva/disattiva i tasti del controller mentre la finestra è inattiva." } } }; CONFIG_DEFINE_LOCALE(ControllerIcons) { { ELanguage::English, { "Controller Icons", "Change the icons to match your controller." } }, - { ELanguage::Japanese, { "コントローラーアイコン", "ゲーム内の\u200Bコントローラーアイコン\u200Bを変更できます" } }, + { ELanguage::Japanese, { "コントローラーアイコン", "ゲーム内のコントローラーアイコンを変更できます" } }, { ELanguage::German, { "Controllersymbole", "Ändere die Controllersymbole, um sie auf dein Modell anzupassen." } }, { ELanguage::French, { "Icône des boutons", "Modifie les icônes pour les faire correspondre à votre manette." } }, { ELanguage::Spanish, { "Iconos del mando", "Cambia los iconos para que coincidan con tu mando." } }, @@ -173,143 +269,168 @@ CONFIG_DEFINE_ENUM_LOCALE(EControllerIcons) { ELanguage::English, { - { EControllerIcons::Auto, { "AUTO", "Auto: the game will determine which icons to use based on the current input device." } }, - { EControllerIcons::Xbox, { "XBOX", "" } }, - { EControllerIcons::PlayStation, { "PLAYSTATION", "" } } + { EControllerIcons::Auto, { "Auto", "Auto: the game will determine which icons to use based on the current input device." } }, + { EControllerIcons::Xbox, { "Xbox", "" } }, + { EControllerIcons::PlayStation, { "PlayStation", "" } } } }, { ELanguage::Japanese, { - { EControllerIcons::Auto, { "自動検出", "\u2005自動検出: コントローラーアイコン\u200Bを使用している\u200B\u2005入\u2005力\u2005デバイスに\u200B応じて\u200B自動的に\u200B決定します" } }, - { EControllerIcons::Xbox, { "XBOX", "" } }, - { EControllerIcons::PlayStation, { "PLAYSTATION", "" } } + { EControllerIcons::Auto, { "自動検出", "自動検出: コントローラーアイコンを使用している入力デバイスに応じて自動的に決定します" } }, + { EControllerIcons::Xbox, { "Xbox", "" } }, + { EControllerIcons::PlayStation, { "PlayStation", "" } } } }, { ELanguage::German, { - { EControllerIcons::Auto, { "AUTO", "Auto: Das Spiel erkennt automatisch deinen Controller um die Symbole dementsprechend anzupassen." } }, - { EControllerIcons::Xbox, { "XBOX", "" } }, - { EControllerIcons::PlayStation, { "PLAYSTATION", "" } } + { EControllerIcons::Auto, { "Auto", "Auto: Das Spiel erkennt automatisch deinen Controller um die Symbole dementsprechend anzupassen." } }, + { EControllerIcons::Xbox, { "Xbox", "" } }, + { EControllerIcons::PlayStation, { "PlayStation", "" } } } }, { ELanguage::French, { - { EControllerIcons::Auto, { "AUTO", "Auto : le jeu déterminera automatiquement quelles icônes utiliser en fonction du périphérique d'entrée." } }, - { EControllerIcons::Xbox, { "XBOX", "" } }, - { EControllerIcons::PlayStation, { "PLAYSTATION", "" } } + { EControllerIcons::Auto, { "Auto", "Auto : le jeu déterminera automatiquement quelles icônes utiliser en fonction du périphérique d'entrée." } }, + { EControllerIcons::Xbox, { "Xbox", "" } }, + { EControllerIcons::PlayStation, { "PlayStation", "" } } } }, { ELanguage::Spanish, { - { EControllerIcons::Auto, { "AUTO", "Auto: el juego determinará de forma automática qué iconos utilizar dependiendo del dispositivo de entrada actual." } }, - { EControllerIcons::Xbox, { "XBOX", "" } }, - { EControllerIcons::PlayStation, { "PLAYSTATION", "" } } + { EControllerIcons::Auto, { "Auto", "Auto: el juego determinará de forma automática qué iconos utilizar dependiendo del dispositivo de entrada actual." } }, + { EControllerIcons::Xbox, { "Xbox", "" } }, + { EControllerIcons::PlayStation, { "PlayStation", "" } } } }, { ELanguage::Italian, { - { EControllerIcons::Auto, { "AUTO", "Auto: il gioco determinerà quali icone da utilizzare in base al dispositivo di input attuale." } }, - { EControllerIcons::Xbox, { "XBOX", "" } }, - { EControllerIcons::PlayStation, { "PLAYSTATION", "" } } + { EControllerIcons::Auto, { "Auto", "Auto: il gioco determinerà quali icone da utilizzare in base al dispositivo di input attuale." } }, + { EControllerIcons::Xbox, { "Xbox", "" } }, + { EControllerIcons::PlayStation, { "PlayStation", "" } } } } }; - -CONFIG_DEFINE_LOCALE(HorizontalCamera) -{ - { ELanguage::English, { "Horizontal Camera", "Change how the camera moves left and right." } }, - { ELanguage::Japanese, { "カメラの左右", "カメラ左右の\u200B動く方向を\u200B選択できます" } }, - { ELanguage::German, { "Horizontale Kamera", "Ändere wie sich die Kamera nach links und rechts bewegt." } }, - { ELanguage::French, { "Caméra horizontale", "Modifie la rotation horizontale de la caméra." } }, - { ELanguage::Spanish, { "Cámara horizontal", "Cambia cómo se mueve la camara hacia la izquierda y la derecha." } }, - { ELanguage::Italian, { "Telecamera orizzontale", "Modifica come la telecamera si muove da sinistra a destra." } } -}; - -CONFIG_DEFINE_LOCALE(VerticalCamera) +CONFIG_DEFINE_LOCALE(LightDash) { - { ELanguage::English, { "Vertical Camera", "Change how the camera moves up and down." } }, - { ELanguage::Japanese, { "カメラの上下", "カメラ上下の\u200B動く方向を\u200B選択できます" } }, - { ELanguage::German, { "Vertikale Kamera", "Ändere wie sich die Kamera nach oben und unten bewegt." } }, - { ELanguage::French, { "Caméra verticale", "Modifie la rotation verticale de la caméra." } }, - { ELanguage::Spanish, { "Cámara vertical", "Cambia cómo se mueve la camara hacia arriba y abajo." } }, - { ELanguage::Italian, { "Telecamera verticale", "Modifica come la telecamera si muove su e giù." } } + { ELanguage::English, { "Light Dash", "Change how Light Dash is activated for Sonic and Shadow." } }, + { ELanguage::Japanese, { "ライトダッシュ", "ソニックとシャドウのライトダッシュの発動方法を変更します" } }, + { ELanguage::German, { "Lichtsprint", "Ändere wie der Lichtsprint von Sonic und Shadow aktiviert wird." } }, + { ELanguage::French, { "Course éclair", "Modifier la façon dont Course éclair est activée pour Sonic et Shadow." } }, + { ELanguage::Spanish, { "Acelerón ligero", "Cambia cómo se activa el acelerón ligero para Sonic y Shadow." } }, + { ELanguage::Italian, { "Super spinta", "Cambia il modo in cui viene attivata la Super spinta per Sonic e Shadow." } } }; -CONFIG_DEFINE_ENUM_LOCALE(ECameraRotationMode) +CONFIG_DEFINE_ENUM_LOCALE(ELightDash) { { ELanguage::English, { - { ECameraRotationMode::Normal, { "NORMAL", "" } }, - { ECameraRotationMode::Reverse, { "REVERSE", "" } } + { ELightDash::X, { "Press ${picture(button_x)}", "" } }, + { ELightDash::Y, { "Press ${picture(button_y)}", "" } } } }, { ELanguage::Japanese, { - { ECameraRotationMode::Normal, { "ノーマル", "" } }, - { ECameraRotationMode::Reverse, { "リバース", "" } } + { ELightDash::X, { "${picture(button_x)}を押す", "" } }, + { ELightDash::Y, { "${picture(button_y)}を押す", "" } } } }, { ELanguage::German, { - { ECameraRotationMode::Normal, { "NORMAL", "" } }, - { ECameraRotationMode::Reverse, { "INVERTIERT", "" } } + { ELightDash::X, { "Drücke ${picture(button_x)}", "" } }, + { ELightDash::Y, { "Drücke ${picture(button_y)}", "" } } } }, { ELanguage::French, { - { ECameraRotationMode::Normal, { "NORMALE", "" } }, - { ECameraRotationMode::Reverse, { "INVERSÉE", "" } } + { ELightDash::X, { "Appuyer sur ${picture(button_x)}", "" } }, + { ELightDash::Y, { "Appuyer sur ${picture(button_y)}", "" } } } }, { ELanguage::Spanish, { - { ECameraRotationMode::Normal, { "NORMAL", "" } }, - { ECameraRotationMode::Reverse, { "INVERTIDO", "" } } + { ELightDash::X, { "Pulsar ${picture(button_x)}", "" } }, + { ELightDash::Y, { "Pulsar ${picture(button_y)}", "" } } } }, { ELanguage::Italian, { - { ECameraRotationMode::Normal, { "NORMALE", "" } }, - { ECameraRotationMode::Reverse, { "INVERTITA", "" } } + { ELightDash::X, { "Premi ${picture(button_x)}", "" } }, + { ELightDash::Y, { "Premi ${picture(button_y)}", "" } } } } }; -CONFIG_DEFINE_LOCALE(Vibration) +CONFIG_DEFINE_LOCALE(SlidingAttack) { - { ELanguage::English, { "Vibration", "Toggle controller vibration." } }, - { ELanguage::Japanese, { "振動", "振動の\u200B有無を\u200B選択できます" } }, - { ELanguage::German, { "Vibration", "Schalte die Controllervibration an oder aus." } }, - { ELanguage::French, { "Vibration", "Active les vibrations de la manette." } }, - { ELanguage::Spanish, { "Vibración", "Activa o desactiva la vibración del mando." } }, - { ELanguage::Italian, { "Vibrazione", "Attiva/disattiva la vibrazione del controller." } } + { ELanguage::English, { "Sliding Attack", "Change how the Sliding Attack is activated for Sonic." } }, + { ELanguage::Japanese, { "スライディングアタック", "ソニックのスライディングアタックの発動方法を変更します" } }, + { ELanguage::German, { "Schlitterangriff", "Ändere wie der Schlitterangriff von Sonic aktiviert wird." } }, + { ELanguage::French, { "Attaque-dérapage", "Modifier la façon dont l'Attaque-dérapage est activée pour Sonic." } }, + { ELanguage::Spanish, { "Ataque derrape", "Cambia cómo se activa el ataque derrape para Sonic." } }, + { ELanguage::Italian, { "Scivolata", "Cambia il modo in cui viene attivata la Scivolata per Sonic." } } }; -CONFIG_DEFINE_LOCALE(AllowBackgroundInput) +CONFIG_DEFINE_ENUM_LOCALE(ESlidingAttack) { - { ELanguage::English, { "Allow Background Input", "Allow controller input whilst the game window is unfocused." } }, - { ELanguage::Japanese, { "バックグラウンド入力", "フォーカスされていない\u200Bゲームに\u200B入力できるか\u200B選択できます" } }, - { ELanguage::German, { "Erlaube Hintergrundeingaben", "Erlaube Eingaben deines Controllers auch wenn das Spielfenster nicht fokussiert ist." } }, - { ELanguage::French, { "Manette en arrière plan", "Permet d'utiliser la manette dans le jeu lorsque qu'il n'est pas au premier plan." } }, - { ELanguage::Spanish, { "Control en segundo plano", "Permite controlar el juego con un mando mientras la ventana esté en segundo plano." } }, - { ELanguage::Italian, { "Input con la finestra inattiva", "Attiva/disattiva i tasti del controller mentre la finestra è inattiva." } } + { + ELanguage::English, + { + { ESlidingAttack::B, { "Hold ${picture(button_b)}", "" } }, + { ESlidingAttack::X, { "Release ${picture(button_x)}", "" } } + } + }, + { + ELanguage::Japanese, + { + { ESlidingAttack::B, { "${picture(button_b)}を押し続ける", "" } }, + { ESlidingAttack::X, { "${picture(button_x)}を離す", "" } } + } + }, + { + ELanguage::German, + { + { ESlidingAttack::B, { "Halte ${picture(button_b)} gedrückt", "" } }, + { ESlidingAttack::X, { "Lasse ${picture(button_x)} los", "" } } + } + }, + { + ELanguage::French, + { + { ESlidingAttack::B, { "Maintenir ${picture(button_b)}", "" } }, + { ESlidingAttack::X, { "Relâcher ${picture(button_x)}", "" } } + } + }, + { + ELanguage::Spanish, + { + { ESlidingAttack::B, { "Mantener ${picture(button_b)}", "" } }, + { ESlidingAttack::X, { "Soltar ${picture(button_x)}", "" } } + } + }, + { + ELanguage::Italian, + { + { ESlidingAttack::B, { "Tieni premuto ${picture(button_b)}", "" } }, + { ESlidingAttack::X, { "Rilascia ${picture(button_x)}", "" } } + } + } }; CONFIG_DEFINE_LOCALE(MasterVolume) { { ELanguage::English, { "Master Volume", "Adjust the overall volume." } }, - { ELanguage::Japanese, { "マスターボリューム", "全体ボリュームの\u200B大きさを\u200B調整できます" } }, + { ELanguage::Japanese, { "マスターボリューム", "全体ボリュームの大きさを調整できます" } }, { ELanguage::German, { "Gesamtlautstärke", "Passe die Gesamtlautstärke an." } }, { ELanguage::French, { "Volume général", "Réglage du volume général." } }, { ELanguage::Spanish, { "Volumen maestro", "Ajusta el volumen general." } }, @@ -319,7 +440,7 @@ CONFIG_DEFINE_LOCALE(MasterVolume) CONFIG_DEFINE_LOCALE(MusicVolume) { { ELanguage::English, { "Music Volume", "Adjust the volume for the music." } }, - { ELanguage::Japanese, { "BGMボリューム", "BGMボリュームの\u200B大きさを\u200B調整できます" } }, + { ELanguage::Japanese, { "BGMボリューム", "BGMボリュームの大きさを調整できます" } }, { ELanguage::German, { "Musiklautstärke", "Passe die Lautstärke der Musik an." } }, { ELanguage::French, { "Volume de la musique", "Réglage du volume de la musique." } }, { ELanguage::Spanish, { "Volumen de la música", "Ajusta el volumen de la música." } }, @@ -329,27 +450,17 @@ CONFIG_DEFINE_LOCALE(MusicVolume) CONFIG_DEFINE_LOCALE(EffectsVolume) { { ELanguage::English, { "Effects Volume", "Adjust the volume for sound effects." } }, - { ELanguage::Japanese, { "SEボリューム", "SEボリュームの\u200B大きさを\u200B調整できます" } }, + { ELanguage::Japanese, { "SEボリューム", "SEボリュームの大きさを調整できます" } }, { ELanguage::German, { "Soundeffektlautstärke", "Passe die Lautstärke der Soundeffekte an." } }, { ELanguage::French, { "Volume des effets sonores", "Réglage du volume des effets sonores." } }, { ELanguage::Spanish, { "Volumen de efectos", "Ajusta el volumen de los efectos de sonido." } }, { ELanguage::Italian, { "Volume effetti sonori", "Regola il volume degli effetti sonori." } } }; -CONFIG_DEFINE_LOCALE(MusicAttenuation) -{ - { ELanguage::English, { "Music Attenuation", "Fade out the game's music when external media is playing." } }, - { ELanguage::Japanese, { "BGM減衰", "外部メディアを\u200B再生すると\u200Bゲームの\u200B音楽を\u200Bフェードアウト\u200Bします" } }, - { ELanguage::German, { "Musikdämpfung", "Stelle die Musik des Spiels stumm während externe Medien abgespielt werden." } }, - { ELanguage::French, { "Atténuation audio", "Abaisse le volume des musiques du jeu lorsqu'un média externe est en cours de lecture." } }, - { ELanguage::Spanish, { "Atenuación de música", "Atenúa la música del juego cuando un reproductor multimedia se encuentra activo." } }, - { ELanguage::Italian, { "Attenuazione musica", "Abbassa il volume della musica di sottofondo quando un'altra applicazione riproduce dei suoni." } } -}; - CONFIG_DEFINE_LOCALE(ChannelConfiguration) { { ELanguage::English, { "Channel Configuration", "Change the output mode for your audio device." } }, - { ELanguage::Japanese, { "チャンネル設定", "オーディオデバイスの\u200B\u2005出\u2005力\u2005モード\u200Bを変更できます" } }, + { ELanguage::Japanese, { "チャンネル設定", "オーディオデバイスの出力モードを変更できます" } }, { ELanguage::German, { "Kanalkonfiguration", "Ändere den Ausgabemodus für dein Audioausgabegerät." } }, { ELanguage::French, { "Configuration sortie audio", "Modifie le mode de sortie pour votre périphérique audio." } }, { ELanguage::Spanish, { "Configuración de canales", "Cambia el modo de salida para tu dispositivo de audio." } }, @@ -361,8 +472,8 @@ CONFIG_DEFINE_ENUM_LOCALE(EChannelConfiguration) { ELanguage::English, { - { EChannelConfiguration::Stereo, { "STEREO", "" } }, - { EChannelConfiguration::Surround, { "SURROUND", "" } } + { EChannelConfiguration::Stereo, { "Stereo", "" } }, + { EChannelConfiguration::Surround, { "Surround", "" } } } }, { @@ -375,67 +486,57 @@ CONFIG_DEFINE_ENUM_LOCALE(EChannelConfiguration) { ELanguage::German, { - { EChannelConfiguration::Stereo, { "STEREO", "" } }, - { EChannelConfiguration::Surround, { "SURROUND", "" } } + { EChannelConfiguration::Stereo, { "Stereo", "" } }, + { EChannelConfiguration::Surround, { "Surround", "" } } } }, { ELanguage::French, { - { EChannelConfiguration::Stereo, { "STÉRÉO", "" } }, - { EChannelConfiguration::Surround, { "SURROUND", "" } } + { EChannelConfiguration::Stereo, { "Stéréo", "" } }, + { EChannelConfiguration::Surround, { "Surround", "" } } } }, { ELanguage::Spanish, { - { EChannelConfiguration::Stereo, { "ESTÉREO", "" } }, - { EChannelConfiguration::Surround, { "ENVOLVENTE", "" } } + { EChannelConfiguration::Stereo, { "Estéreo", "" } }, + { EChannelConfiguration::Surround, { "Envolvente", "" } } } }, { ELanguage::Italian, { - { EChannelConfiguration::Stereo, { "STEREO", "" } }, - { EChannelConfiguration::Surround, { "SURROUND", "" } } + { EChannelConfiguration::Stereo, { "Stereo", "" } }, + { EChannelConfiguration::Surround, { "Surround", "" } } } } }; -CONFIG_DEFINE_LOCALE(VoiceLanguage) -{ - { ELanguage::English, { "Voice Language", "Change the language used for character voices." } }, - { ELanguage::Japanese, { "音声言語", "ゲーム内の\u200B音声言語を\u200B変更できます" } }, - { ELanguage::German, { "Stimmeinstellung", "Ändere die Sprache, die für Charakterstimmen benutzt wird." } }, - { ELanguage::French, { "Langue de doublage", "Modifie la langue utilisée pour la voix des personnages." } }, - { ELanguage::Spanish, { "Idioma de voz", "Cambia el idioma utilizado para las voces de los personajes." } }, - { ELanguage::Italian, { "Lingua delle voci", "Modifica la lingua utilizzata per le voci dei personaggi." } } -}; - -CONFIG_DEFINE_LOCALE(Subtitles) +CONFIG_DEFINE_LOCALE(MuteOnFocusLost) { - { ELanguage::English, { "Subtitles", "Show subtitles during dialogue." } }, - { ELanguage::Japanese, { "字幕", "字幕の表示を\u200B選択できます" } }, - { ELanguage::German, { "Untertitel", "Zeige Untertitel bei Dialogen." } }, - { ELanguage::French, { "Sous-titres", "Affiche les sous-titres pendant les dialogues." } }, - { ELanguage::Spanish, { "Subtítulos", "Muestra subtítulos durante los diálogos." } }, - { ELanguage::Italian, { "Sottotitoli", "Mostra i sottotitoli durante i dialoghi." } } + { ELanguage::English, { "Mute on Focus Lost", "Mute the game's audio when the window is not in focus." } }, + { ELanguage::Japanese, { "フォーカスロストミュート", "ウィンドウがフォーカスされていないときにゲームのオーディオをミュートします" } }, + { ELanguage::German, { "Stummstellen wenn nicht fokussiert", "Stellt das Audio des Spiels stumm solange das Fenster nicht im Fokus ist." } }, + { ELanguage::French, { "Muet si fenêtre inactive", "Coupe le son du jeu lorsque la fenêtre n'est pas active." } }, + { ELanguage::Spanish, { "Silenciar al perder el foco", "Silencia el audio del juego cuando la ventana no esté en primer plano." } }, + { ELanguage::Italian, { "Audio muto con finestra inattiva", "Disattiva l'audio del gioco quando la finestra non è attiva." } } }; -CONFIG_DEFINE_LOCALE(BattleTheme) +CONFIG_DEFINE_LOCALE(MusicAttenuation) { - { ELanguage::English, { "Battle Theme", "Play the Werehog battle theme during combat.\n\nThis option will apply the next time you're in combat.\n\nExorcism missions and miniboss themes will be unaffected." } }, - { ELanguage::Japanese, { "バトルテーマ", "バトル中に\u200Bウェアホッグの\u200Bバトルテーマを\u200B再生するか\u200B選択できます\n\nこのオプションは\u200B次回のバトルから\u200B適用されます\n\n\u2005除\u2005霊\u2005ミッションと\u200Bミニボステーマには\u200B\u2005影響\u2005しません" } }, - { ELanguage::German, { "Kampfmusik", "Spiele die Kampfmusik des Werehogs während dem Kämpfen ab.\n\nDiese Option tritt das nächste Mal, wenn du in einen Kampf gerätst, in Kraft.\n\nExorzismen und Mini-Bosse werden hiervon nicht beeinflusst." } }, - { ELanguage::French, { "Thème de combat", "Joue le thème de combat du Werehog pendant ces derniers.\n\nCette option s'appliquera la prochaine fois que vous serez en combat.\n\nLes missions d'exorcisme et les thèmes des miniboss ne seront pas affectés." } }, - { ELanguage::Spanish, { "Tema de batalla", "Reproduce el tema de batalla del Werehog durante el combate.\n\nEsta opción se aplicará la próxima vez que entres en combate.\n\nLas misiones de exorcismo y los temas de los minijefes no se verán afectados." } }, - { ELanguage::Italian, { "Musica di combattimento", "Riproduci la musica di combattimento del Werehog quando inizi una battaglia.\n\nQuesta opzione verrà applicata la prossima volta che sei in battaglia.\n\nLa traccia musicale verrà riprodotta ugualmente nelle missioni di Esorcismo e i miniboss." } } + { ELanguage::English, { "Music Attenuation", "Fade out the game's music when external media is playing." } }, + { ELanguage::Japanese, { "BGM減衰", "外部メディアを再生するとゲームの音楽をフェードアウトします" } }, + { ELanguage::German, { "Musikdämpfung", "Stelle die Musik des Spiels stumm während externe Medien abgespielt werden." } }, + { ELanguage::French, { "Atténuation audio", "Abaisse le volume des musiques du jeu lorsqu'un média externe est en cours de lecture." } }, + { ELanguage::Spanish, { "Atenuación de música", "Atenúa la música del juego cuando un reproductor multimedia se encuentra activo." } }, + { ELanguage::Italian, { "Attenuazione musica", "Abbassa il volume della musica di sottofondo quando un'altra applicazione riproduce dei suoni." } } }; CONFIG_DEFINE_LOCALE(WindowSize) { { ELanguage::English, { "Window Size", "Adjust the size of the game window in windowed mode." } }, - { ELanguage::Japanese, { "ウィンドウサイズ", "ウィンドウ\u200Bモードでの\u200Bゲームの\u200Bウィンドウサイズを\u200B調整できます" } }, + { ELanguage::Japanese, { "ウィンドウサイズ", "ウィンドウモードでのゲームのウィンドウサイズを調整できます" } }, { ELanguage::German, { "Fenstergröße", "Ändere die Größe des Spielfensters im Fenstermodus." } }, { ELanguage::French, { "Taille de la fenêtre", "Modifie la taille de la fenêtre de jeu en mode fenêtré." } }, { ELanguage::Spanish, { "Tamaño de ventana", "Ajusta el tamaño de la ventana de juego." } }, @@ -445,7 +546,7 @@ CONFIG_DEFINE_LOCALE(WindowSize) CONFIG_DEFINE_LOCALE(Monitor) { { ELanguage::English, { "Monitor", "Change which monitor to display the game on." } }, - { ELanguage::Japanese, { "モニター選択", "ゲームを表示する\u200Bモニターを\u200B変更できます" } }, + { ELanguage::Japanese, { "モニター選択", "ゲームを表示するモニターを変更できます" } }, { ELanguage::German, { "Monitor", "Ändere auf welchem Monitor das Spiel angezeigt wird." } }, { ELanguage::French, { "Moniteur", "Change le moniteur sur lequel le jeu sera affiché." } }, { ELanguage::Spanish, { "Pantalla", "Cambia la pantalla en la cuál se muestra el juego." } }, @@ -455,7 +556,7 @@ CONFIG_DEFINE_LOCALE(Monitor) CONFIG_DEFINE_LOCALE(AspectRatio) { { ELanguage::English, { "Aspect Ratio", "Change the aspect ratio." } }, - { ELanguage::Japanese, { "アスペクト比", "アスペクト比を\u200B変更できます" } }, + { ELanguage::Japanese, { "アスペクト比", "アスペクト比を変更できます" } }, { ELanguage::German, { "Seitenverhältnis", "Verändere das Seitenverhältnis." } }, { ELanguage::French, { "Format d'image", "Modifie le format d'image." } }, { ELanguage::Spanish, { "Relación de aspecto", "Cambia la relación de aspecto." } }, @@ -467,73 +568,61 @@ CONFIG_DEFINE_ENUM_LOCALE(EAspectRatio) { ELanguage::English, { - { EAspectRatio::Auto, { "AUTO", "Auto: the aspect ratio will dynamically adjust to the window size." } }, - { EAspectRatio::Wide, { "16:9", "16:9: locks the game to a widescreen aspect ratio." } }, - { EAspectRatio::Narrow, { "4:3", "4:3: locks the game to a narrow aspect ratio." } }, - { EAspectRatio::OriginalNarrow, { "ORIGINAL 4:3", "Original 4:3: locks the game to a narrow aspect ratio and retains parity with the game's original implementation." } } + { EAspectRatio::Auto, { "Auto", "Auto: the aspect ratio will dynamically adjust to the window size." } }, + { EAspectRatio::Original, { "Original", "Original: locks the game to a widescreen aspect ratio." } } } }, { ELanguage::Japanese, { - { EAspectRatio::Auto, { "自動", "自動: アスペクト比は\u200Bウィンドウサイズに\u200B合わせて\u200B調整されます" } }, - { EAspectRatio::Wide, { "16:9", "16:9: ワイドスクリーンの\u200Bアスペクト比に\u200B固定されます" } }, - { EAspectRatio::Narrow, { "4:3", "4:3: ナローの\u200Bアスペクト比に\u200B固定されます" } }, - { EAspectRatio::OriginalNarrow, { "オリジナル 4:3", "オリジナル 4:3: オリジナルの\u200Bアスペクト比に\u200B固定されます" } } + { EAspectRatio::Auto, { "自動", "自動: アスペクト比はウィンドウサイズに合わせて調整されます" } }, + { EAspectRatio::Original, { "オリジナル", "オリジナル: ワイドスクリーンのアスペクト比に固定されます" } } } }, { ELanguage::German, { - { EAspectRatio::Auto, { "AUTO", "Auto: Das Seitenverhältnis passt sich automatisch der Fenstergröße an." } }, - { EAspectRatio::Wide, { "16:9", "16:9: Stellt das Spiel in einem Breitbildschirm-Format dar." } }, - { EAspectRatio::Narrow, { "4:3", "4:3: Stellt das Spiel in einem Mittel-Format dar." } }, - { EAspectRatio::OriginalNarrow, { "ORIGINAL 4:3", "Original 4:3: Stellt das Spiel in einem Mittel-Format dar, was der ursprünglichen Implementation originalgetreut bleibt." } } + { EAspectRatio::Auto, { "Auto", "Auto: Das Seitenverhältnis passt sich automatisch der Fenstergröße an." } }, + { EAspectRatio::Original, { "Original", "Original: Stellt das Spiel in einem Breitbildschirm-Format dar." } } } }, { ELanguage::French, { - { EAspectRatio::Auto, { "AUTO", "Auto : le format d'image s'adapte automatiquement à la taille de la fenêtre." } }, - { EAspectRatio::Wide, { "16:9", "16:9 : force le jeu sur un format d'image large." } }, - { EAspectRatio::Narrow, { "4:3", "4:3 : force le jeu sur un format d'image carré." } }, - { EAspectRatio::OriginalNarrow, { "4:3 ORIGINAL", "4:3 original : force le jeu à un format d'image carré et conserve la parité avec l'implémentation d'origine du jeu." } } + { EAspectRatio::Auto, { "Auto", "Auto : le format d'image s'adapte automatiquement à la taille de la fenêtre." } }, + { EAspectRatio::Original, { "Original", "Original : force le jeu sur un format d'image large." } } } }, { ELanguage::Spanish, { - { EAspectRatio::Auto, { "AUTO", "Auto: la relación de aspecto se ajusta de forma dinámica al tamaño de la ventana." } }, - { EAspectRatio::Wide, { "16:9", "16:9: muestra el juego en relación de aspecto de pantalla ancha." } }, - { EAspectRatio::Narrow, { "4:3", "4:3: muestra el juego en relación de aspecto de pantalla estrecha." } }, - { EAspectRatio::OriginalNarrow, { "ORIGINAL 4:3", "Original 4:3: muestra el juego en relación de aspecto de pantalla estrecha y mantiene paridad con la implementación original del juego." } } + { EAspectRatio::Auto, { "Auto", "Auto: la relación de aspecto se ajusta de forma dinámica al tamaño de la ventana." } }, + { EAspectRatio::Original, { "Original", "Original: muestra el juego en relación de aspecto de pantalla ancha." } } } }, { ELanguage::Italian, { - { EAspectRatio::Auto, { "AUTO", "Auto: il rapporto d'aspetto verra cambiato automaticamente in base alle dimensioni della finestra." } }, - { EAspectRatio::Wide, { "16:9", "16:9: blocca il gioco a un rapporto d'aspetto widescreen." } }, - { EAspectRatio::Narrow, { "4:3", "4:3: blocca il gioco a un rapporto d'aspetto stretto." } }, - { EAspectRatio::OriginalNarrow, { "4:3 ORIGINALE", "4:3 Originale: blocca il gioco a un rapporto d'aspetto stretto e mantiene la parità con l'implementazione originale del gioco." } } + { EAspectRatio::Auto, { "Auto", "Auto: il rapporto d'aspetto verra cambiato automaticamente in base alle dimensioni della finestra." } }, + { EAspectRatio::Original, { "Originale", "Originale: blocca il gioco a un rapporto d'aspetto widescreen." } } } } }; CONFIG_DEFINE_LOCALE(ResolutionScale) { - { ELanguage::English, { "Resolution Scale", "Adjust the internal resolution of the game.\n\n%dx%d" } }, - { ELanguage::Japanese, { "解像度スケール", "ゲームの\u200B内部解像度を\u200B調整できます\n\n%dx%d" } }, - { ELanguage::German, { "Rendering-Auflösung", "Passe die Auflösung der internen Darstellung an.\n\n%dx%d" } }, - { ELanguage::French, { "Échelle de rendu", "Modifie la résolution interne du jeu.\n\n%dx%d" } }, - { ELanguage::Spanish, { "Escala de resolución", "Ajusta la resolución interna del juego.\n\n%dx%d" } }, - { ELanguage::Italian, { "Scala risoluzione", "Regola la risoluzione interna del gioco.\n\n%dx%d" } } + { ELanguage::English, { "Resolution Scale", "Adjust the internal resolution of the game." } }, + { ELanguage::Japanese, { "解像度スケール", "ゲームの内部解像度を調整できます" } }, + { ELanguage::German, { "Rendering-Auflösung", "Passe die Auflösung der internen Darstellung an." } }, + { ELanguage::French, { "Échelle de rendu", "Modifie la résolution interne du jeu." } }, + { ELanguage::Spanish, { "Escala de resolución", "Ajusta la resolución interna del juego." } }, + { ELanguage::Italian, { "Scala risoluzione", "Regola la risoluzione interna del gioco." } } }; CONFIG_DEFINE_LOCALE(Fullscreen) { { ELanguage::English, { "Fullscreen", "Toggle between borderless fullscreen or windowed mode." } }, - { ELanguage::Japanese, { "フルスクリーン", "ボーダーレス\u200Bフルスクリーンか\u200Bウィンドウモードを\u200B選択できます" } }, + { ELanguage::Japanese, { "フルスクリーン", "ボーダーレスフルスクリーンかウィンドウモードを選択できます" } }, { ELanguage::German, { "Vollbild", "Wechsle zwischen dem randlosen Vollbildmodus und dem Fenstermodus." } }, { ELanguage::French, { "Plein écran", "Alterne entre le mode plein écran sans bordures et le mode fenêtré." } }, { ELanguage::Spanish, { "Pantalla completa", "Cambia entre modo de pantalla completa o ventana." } }, @@ -543,7 +632,7 @@ CONFIG_DEFINE_LOCALE(Fullscreen) CONFIG_DEFINE_LOCALE(VSync) { { ELanguage::English, { "V-Sync", "Synchronize the game to the refresh rate of the display to prevent screen tearing." } }, - { ELanguage::Japanese, { "垂直同期", "垂直同期の\u200B設定を\u200B変更できます" } }, + { ELanguage::Japanese, { "垂直同期", "垂直同期の設定を変更できます" } }, { ELanguage::German, { "V-Sync", "Synchronisiere das Spiel mit der Bildwiederholrate deines Bildschirms um Bildverzerrungen zu vermeiden." } }, { ELanguage::French, { "V-Sync", "Synchronise le jeu avec la fréquence de rafraîchissement de l'écran pour éviter le screen tearing." } }, { ELanguage::Spanish, { "V-Sync", "Sincroniza el juego a la tasa de refresco de la pantalla para prevenir el rasgado de la imagen." } }, @@ -552,28 +641,28 @@ CONFIG_DEFINE_LOCALE(VSync) CONFIG_DEFINE_LOCALE(FPS) { - { ELanguage::English, { "FPS", "Set the max frame rate the game can run at.\n\nWARNING: this may introduce glitches at frame rates higher than 60 FPS." } }, - { ELanguage::Japanese, { "フレームレート上限", "ゲームの\u200B最大フレームレートを\u200B設定できます\n\n警告: 60 FPSを\u200B超えるフレームレートで\u200B不具合が\u200B発生する\u200B可能性が\u200Bあります" } }, - { ELanguage::German, { "FPS", "Setze die maximale Anzahl der Bilder pro Sekunde, die das Spiel darstellen kann.\n\nWARNUNG: Das Spiel kann bei höheren FPS als 60 ungewolltes Verhalten aufweisen." } }, - { ELanguage::French, { "IPS", "Détermine la fréquence d'images maximale du jeu.\n\nATTENTION : cela peut entraîner des problèmes à des taux de rafraîchissement supérieurs à 60 IPS." } }, - { ELanguage::Spanish, { "FPS", "Establece la tasa de fotogramas máxima a la que puede correr el juego.\n\nADVERTENCIA: esto puede introducir fallos en tasas mayores a 60 FPS." } }, - { ELanguage::Italian, { "FPS", "Imposta il frame rate massimo del gioco.\n\nATTENZIONE: questa opzione può causare dei glitch a frame rate più alti di 60 FPS." } } + { ELanguage::English, { "FPS", "Set the max frame rate the game can run at. WARNING: this may introduce glitches at frame rates other than 60 FPS." } }, + { ELanguage::Japanese, { "フレームレート上限", "ゲームが実行できる最大フレームレートを設定します 警告:60FPS以外のフレームレートでは不具合が発生する可能性があります" } }, + { ELanguage::German, { "FPS", "Bestimmt die maximale Bildwiederholrate. WARNUNG: es können Fehler bei einer Bildwiederholrate über 60 FPS auftreten." } }, + { ELanguage::French, { "IPS", "Limiter le nombre d'images par seconde. ATTENTION : Cela peut provoquer des bugs à des fréquences autres que 60 IPS." } }, + { ELanguage::Spanish, { "FPS", "Establece la tasa máxima de fotogramas a la que puede ejecutarse el juego. ADVERTENCIA: esto puede provocar fallos en velocidades distintas a 60 FPS." } }, + { ELanguage::Italian, { "FPS", "Imposta il framerate massimo del gioco. ATTENZIONE: questa opzione può causare problemi con dei framerate rate superiori a 60 FPS." } } }; CONFIG_DEFINE_LOCALE(Brightness) { - { ELanguage::English, { "Brightness", "Adjust the brightness level until the symbol on the left is barely visible." } }, - { ELanguage::Japanese, { "明るさの設定", "画面の\u200B明るさを\u200B調整できます" } }, - { ELanguage::German, { "Helligkeit", "Passe die Helligkeit des Spiels an bis das linke Symbol noch gerade so sichtbar ist." } }, - { ELanguage::French, { "Luminosité", "Réglez le niveau de luminosité jusqu'à ce que le symbole à gauche soit à peine visible." } }, - { ELanguage::Spanish, { "Brillo", "Ajusta el nivel de brillo hasta que el símbolo a la izquierda sea apenas visible." } }, - { ELanguage::Italian, { "Luminosità", "Regola la luminosità dello schermo fino a quando il simbolo a sinistra diventa leggermente visibile." } } + { ELanguage::English, { "Brightness", "Adjust the brightness level." } }, + { ELanguage::Japanese, { "明るさの設定", "明るさレベルを調整します" } }, + { ELanguage::German, { "Helligkeit", "Stelle die Helligkeit ein." } }, + { ELanguage::French, { "Luminosité", "Modifier le niveau de luminosité." } }, + { ELanguage::Spanish, { "Brillo", "Ajusta el nivel de brillo." } }, + { ELanguage::Italian, { "Luminosità", "Regola il livello di luminosità." } } }; CONFIG_DEFINE_LOCALE(AntiAliasing) { { ELanguage::English, { "Anti-Aliasing", "Adjust the amount of smoothing applied to jagged edges." } }, - { ELanguage::Japanese, { "アンチエイリアス", "アンチエイリアスの\u200B種類を\u200B選択できます" } }, + { ELanguage::Japanese, { "アンチエイリアス", "アンチエイリアスの種類を選択できます" } }, { ELanguage::German, { "Kantenglättung", "Passe die Menge an Kantenglättung an." } }, { ELanguage::French, { "Anticrénelage", "Ajuste le niveau d'anticrénelage appliqué aux bords des objets." } }, { ELanguage::Spanish, { "Anti-Aliasing", "Ajusta el nivel de suavizado aplicado a los dientes de sierra." } }, @@ -585,45 +674,45 @@ CONFIG_DEFINE_ENUM_LOCALE(EAntiAliasing) { ELanguage::English, { - { EAntiAliasing::None, { "NONE", "" } } + { EAntiAliasing::Off, { "Off", "" } } } }, { ELanguage::Japanese, { - { EAntiAliasing::None, { "オフ", "" } }, + { EAntiAliasing::Off, { "オフ", "" } }, } }, { ELanguage::German, { - { EAntiAliasing::None, { "KEINE", "" } } + { EAntiAliasing::Off, { "Aus", "" } } } }, { ELanguage::French, { - { EAntiAliasing::None, { "SANS", "" } } + { EAntiAliasing::Off, { "Non", "" } } } }, { ELanguage::Spanish, { - { EAntiAliasing::None, { "NO", "" } }, + { EAntiAliasing::Off, { "No", "" } }, } }, { ELanguage::Italian, { - { EAntiAliasing::None, { "NULLO", "" } } + { EAntiAliasing::Off, { "No", "" } } } - }, + } }; CONFIG_DEFINE_LOCALE(TransparencyAntiAliasing) { { ELanguage::English, { "Transparency Anti-Aliasing", "Apply anti-aliasing to alpha transparent textures." } }, - { ELanguage::Japanese, { "透明度のアンチエイリアス", "透過テクスチャに\u200Bアンチエイリアスを\u200B適用します" } }, + { ELanguage::Japanese, { "透明度のアンチエイリアス", "透過テクスチャにアンチエイリアスを適用します" } }, { ELanguage::German, { "Transparenz-Kantenglättung", "Wende Kantenglättung auf Alpha-Transparenz-Texturen an." } }, { ELanguage::French, { "Anticrénelage de transparence", "Applique l'anticrénelage sur les textures transparentes." } }, { ELanguage::Spanish, { "Anti-Aliasing de transparencias", "Aplica antialiasing a las texturas transparentes." } }, @@ -633,20 +722,107 @@ CONFIG_DEFINE_LOCALE(TransparencyAntiAliasing) CONFIG_DEFINE_LOCALE(ShadowResolution) { { ELanguage::English, { "Shadow Resolution", "Set the resolution of real-time shadows." } }, - { ELanguage::Japanese, { "影の解像度", "影の解像度を\u200B設定できます" } }, + { ELanguage::Japanese, { "影の解像度", "影の解像度を設定できます" } }, { ELanguage::German, { "Schattenauflösung", "Stelle die Auflösung der Echtzeit-Schatten ein." } }, { ELanguage::French, { "Résolution des ombres", "Définit la résolution des ombres en temps réel." } }, - { ELanguage::Spanish, { "Resolución de sombras", "Establece la resolución de las sombras de tiempo real." } }, + { ELanguage::Spanish, { "Resolución de sombras", "Establece la resolución de las sombras en tiempo real." } }, { ELanguage::Italian, { "Risoluzione ombre", "Imposta la risoluzioni delle ombre in tempo reale." } } }; +CONFIG_DEFINE_ENUM_LOCALE(EShadowResolution) {}; + +CONFIG_DEFINE_LOCALE(ReflectionResolution) +{ + { ELanguage::English, { "Reflection Resolution", "Set the resolution of real-time reflections." } }, + { ELanguage::Japanese, { "反射解像度", "リアルタイム反射の解像度を設定します" } }, + { ELanguage::German, { "Reflektionsauflösung", "Bestimmt die Auflösung der Echtzeitreflektionen." } }, + { ELanguage::French, { "Résolution des reflets", "Définir la résolution des reflets en temps réel." } }, + { ELanguage::Spanish, { "Resolución de reflejos", "Establece la resolución de los reflejos en tiempo real." } }, + { ELanguage::Italian, { "Risoluzione riflessi", "Imposta la risoluzione dei riflessi in tempo reale." } } +}; + +CONFIG_DEFINE_ENUM_LOCALE(EReflectionResolution) +{ + { + ELanguage::English, + { + { EReflectionResolution::Eighth, { "12.5%", "" } }, + { EReflectionResolution::Quarter, { "25%", "" } }, + { EReflectionResolution::Half, { "50%", "" } }, + { EReflectionResolution::Full, { "100%", "" } } + } + } +}; + +CONFIG_DEFINE_LOCALE(RadialBlur) +{ + { ELanguage::English, { "Radial Blur", "Change the quality of the radial blur." } }, + { ELanguage::Japanese, { "放射状ぼかし", "放射状ぼかしの品質を変更します" } }, + { ELanguage::German, { "Radiale Unschärfe", "Verändere die Qualität der radialen Unschärfe." } }, + { ELanguage::French, { "Flou Radial", "Modifier la qualité du flou radial." } }, + { ELanguage::Spanish, { "Desenfoque radial", "Cambia la calidad del desenfoque radial." } }, + { ELanguage::Italian, { "Sfocatura radiale", "Modifica la qualità della sfocatura radiale." } } +}; + +CONFIG_DEFINE_ENUM_LOCALE(ERadialBlur) +{ + { + ELanguage::English, + { + { ERadialBlur::Off, { "Off", "" } }, + { ERadialBlur::Original, { "Original", "" } }, + { ERadialBlur::Enhanced, { "Enhanced", "Enhanced: uses more samples for smoother radial blur." } } + } + }, + { + ELanguage::Japanese, + { + { ERadialBlur::Off, { "オフ", "" } }, + { ERadialBlur::Original, { "オリジナル", "" } }, + { ERadialBlur::Enhanced, { "エンハンスド", "エンハンスド:より多くのサンプルを使用してよりスムーズな放射状ぼかしを実現します" } } + } + }, + { + ELanguage::German, + { + { ERadialBlur::Off, { "Aus", "" } }, + { ERadialBlur::Original, { "Original", "" } }, + { ERadialBlur::Enhanced, { "Verbessert", "Verbessert: Benutzt mehr Samples um eine weichere radiale Unschärfe zu erzeugen." } } + } + }, + { + ELanguage::French, + { + { ERadialBlur::Off, { "Non", "" } }, + { ERadialBlur::Original, { "Original", "" } }, + { ERadialBlur::Enhanced, { "Amélioré", "Amélioré : utilise plus d'échantillons pour un flou radial plus lisse." } } + } + }, + { + ELanguage::Spanish, + { + { ERadialBlur::Off, { "No", "" } }, + { ERadialBlur::Original, { "Original", "" } }, + { ERadialBlur::Enhanced, { "Mejorado", "Mejorado: utiliza más muestras para un desenfoque radial más suave." } } + } + }, + { + ELanguage::Italian, + { + { ERadialBlur::Off, { "No", "" } }, + { ERadialBlur::Original, { "Originale", "" } }, + { ERadialBlur::Enhanced, { "Migliorato", "Migliorato: utilizza più campioni per una sfocatura radiale più uniforme." } } + } + } +}; + CONFIG_DEFINE_LOCALE(CutsceneAspectRatio) { { ELanguage::English, { "Cutscene Aspect Ratio", "Change the aspect ratio of the real-time cutscenes." } }, - { ELanguage::Japanese, { "アスペクト比のカットシーン", "リアルタイム\u200Bカットシーンの\u200Bアスペクト比を\u200B変更できます" } }, + { ELanguage::Japanese, { "アスペクト比のカットシーン", "リアルタイムカットシーンのアスペクト比を変更できます" } }, { ELanguage::German, { "Zwischensequenz-Seitenverhältnis", "Verändere das Seitenverhältnis der Echtzeit-Zwischensequenzen." } }, { ELanguage::French, { "Format des cinématiques", "Modifie le format d'image des cinématiques en temps réel." } }, - { ELanguage::Spanish, { "Relación de aspecto de cinemáticas", "Cambia la relación de aspecto de las cinemáticas de tiempo real." } }, + { ELanguage::Spanish, { "Relación de aspecto de cinemáticas", "Cambia la relación de aspecto de las cinemáticas en tiempo real." } }, { ELanguage::Italian, { "Rapporto d'aspetto dei filmati", "Cambia il rapporto d'aspetto dei filmati in tempo reale." } } }; @@ -655,43 +831,43 @@ CONFIG_DEFINE_ENUM_LOCALE(ECutsceneAspectRatio) { ELanguage::English, { - { ECutsceneAspectRatio::Original, { "ORIGINAL", "Original: locks cutscenes to their original 16:9 aspect ratio." } }, - { ECutsceneAspectRatio::Unlocked, { "UNLOCKED", "Unlocked: allows cutscenes to adjust their aspect ratio to the window size.\n\nWARNING: this will introduce visual oddities past the original 16:9 aspect ratio." } } + { ECutsceneAspectRatio::Original, { "Original", "Original: locks cutscenes to their original 16:9 aspect ratio." } }, + { ECutsceneAspectRatio::Unlocked, { "Unlocked", "Unlocked: allows cutscenes to adjust their aspect ratio to the window size. WARNING: this will introduce visual oddities past the original 16:9 aspect ratio." } } } }, { ELanguage::Japanese, { - { ECutsceneAspectRatio::Original, { "オリジナル", "オリジナル: カットシーンを\u200B元の\u200B16:9の\u200Bアスペクト比に\u200B固定します" } }, - { ECutsceneAspectRatio::Unlocked, { "解除", "解除: カットシーンの\u200Bアスペクト比を\u200Bウィンドウサイズに\u200B合わせて\u200B調整します\n\n警告: 元の\u200B16:9の\u200Bアスペクト比を\u200B超えると\u200B視覚的な\u200B異常が\u200B発生します" } }, + { ECutsceneAspectRatio::Original, { "オリジナル", "オリジナル: カットシーンを元の16:9のアスペクト比に固定します" } }, + { ECutsceneAspectRatio::Unlocked, { "解除", "解除: カットシーンのアスペクト比をウィンドウサイズに合わせて調整します 警告: 元の16:9のアスペクト比を超えると視覚的な異常が発生します" } }, } }, { ELanguage::German, { - { ECutsceneAspectRatio::Original, { "ORIGINAL", "Original: Behält die Zwischensequenzen in ihrem originalen 16:9 Seitenverhältnis." } }, - { ECutsceneAspectRatio::Unlocked, { "ENTSPERRT", "Entsperrt: Erlaubt Zwischensequenzen ihr Seitenverhältnis der Fenstergröße anzupassen.\n\nWARNUNG: Diese Option kann zu visuellen Fehlern außerhalb der Grenzen des ursprünglichen Seitenverhältnisses führen." } } + { ECutsceneAspectRatio::Original, { "Original", "Original: Behält die Zwischensequenzen in ihrem originalen 16:9 Seitenverhältnis." } }, + { ECutsceneAspectRatio::Unlocked, { "Entsperrt", "Entsperrt: Erlaubt Zwischensequenzen ihr Seitenverhältnis der Fenstergröße anzupassen. WARNUNG: Diese Option kann zu visuellen Fehlern außerhalb der Grenzen des ursprünglichen Seitenverhältnisses führen." } } } }, { ELanguage::French, { - { ECutsceneAspectRatio::Original, { "ORIGINAL", "Original : force les cinématiques dans leur format 16:9 d'origine." } }, - { ECutsceneAspectRatio::Unlocked, { "LIBRE", "Libre : permet aux cinématiques d'adapter leur format d'image à la taille de la fenêtre.\n\nATTENTION : au delà du format 16:9 d'origine, des bugs visuels apparaitront." } }, + { ECutsceneAspectRatio::Original, { "Original", "Original : force les cinématiques dans leur format 16:9 d'origine." } }, + { ECutsceneAspectRatio::Unlocked, { "Libre", "Libre : permet aux cinématiques d'adapter leur format d'image à la taille de la fenêtre. ATTENTION : au delà du format 16:9 d'origine, des bugs visuels apparaitront." } }, } }, { ELanguage::Spanish, { - { ECutsceneAspectRatio::Original, { "ORIGINAL", "Original: muestra las cinemáticas en su relación de aspecto original de 16:9." } }, - { ECutsceneAspectRatio::Unlocked, { "DESBLOQUEADO", "Desbloqueado: permite que las cinemáticas ajusten su relación de aspecto al tamaño de la ventana.\n\nADVERTENCIA: esto introducirá rarezas visuales más allá de la relación de aspecto original de 16:9." } }, + { ECutsceneAspectRatio::Original, { "Original", "Original: muestra las cinemáticas en su relación de aspecto original de 16:9." } }, + { ECutsceneAspectRatio::Unlocked, { "Desbloqueado", "Desbloqueado: permite que las cinemáticas ajusten su relación de aspecto al tamaño de la ventana. ADVERTENCIA: esto introducirá rarezas visuales más allá de la relación de aspecto original de 16:9." } }, } }, { ELanguage::Italian, { - { ECutsceneAspectRatio::Original, { "ORIGINALE", "Originale: blocca il rapporto d'aspetto dei filmati a 16:9." } }, - { ECutsceneAspectRatio::Unlocked, { "SBLOCCATO", "Sbloccato: il rapporto d'aspetto verrà regolato in base alle dimensioni della finestra.\n\nATTENZIONE: questa opzione potrebbe causare dei problemi visivi se il rapporto d'aspetto è oltre 16:9." } } + { ECutsceneAspectRatio::Original, { "Originale", "Originale: blocca il rapporto d'aspetto dei filmati a 16:9." } }, + { ECutsceneAspectRatio::Unlocked, { "Sbloccato", "Sbloccato: il rapporto d'aspetto verrà regolato in base alle dimensioni della finestra. ATTENZIONE: questa opzione potrebbe causare dei problemi visivi se il rapporto d'aspetto è oltre 16:9." } } } } }; @@ -699,7 +875,7 @@ CONFIG_DEFINE_ENUM_LOCALE(ECutsceneAspectRatio) CONFIG_DEFINE_LOCALE(UIAlignmentMode) { { ELanguage::English, { "UI Alignment Mode", "Change how the UI aligns with the display." } }, - { ELanguage::Japanese, { "UIアライメントモード", "UIとディスプレイの\u200B配置を\u200B変更できます" } }, + { ELanguage::Japanese, { "UIアライメントモード", "UIとディスプレイの配置を変更できます" } }, { ELanguage::German, { "Benutzeroberflächenausrichtung", "Verändere wie die Benutzeroberfläche sich mit dem Bildschirm ausrichtet." } }, { ELanguage::French, { "Alignement de l'IU", "Modifie l'alignement de l'interface utilisateur sur l'écran." } }, { ELanguage::Spanish, { "Modo de alineamiento de UI", "Cambia la alineación de la interfaz de usuario con la pantalla." } }, @@ -711,43 +887,43 @@ CONFIG_DEFINE_ENUM_LOCALE(EUIAlignmentMode) { ELanguage::English, { - { EUIAlignmentMode::Edge, { "EDGE", "Edge: the UI will align with the edges of the display." } }, - { EUIAlignmentMode::Centre, { "CENTER", "Center: the UI will align with the center of the display." } } + { EUIAlignmentMode::Edge, { "Edge", "Edge: the UI will align with the edges of the display." } }, + { EUIAlignmentMode::Centre, { "Center", "Center: the UI will align with the center of the display." } } } }, { ELanguage::Japanese, { - { EUIAlignmentMode::Edge, { "エッジ", "エッジ: UIがディスプレイの\u200B端に\u200B揃います" } }, - { EUIAlignmentMode::Centre, { "センター", "センター: UIがディスプレイの\u200B中央に\u200B揃います" } }, + { EUIAlignmentMode::Edge, { "エッジ", "エッジ: UIがディスプレイの端に揃います" } }, + { EUIAlignmentMode::Centre, { "センター", "センター: UIがディスプレイの中央に揃います" } }, } }, { ELanguage::German, { - { EUIAlignmentMode::Edge, { "RAND", "Rand: Die Benutzeroberfläche richtet sich zum Rand des Bildschirms aus." } }, - { EUIAlignmentMode::Centre, { "MITTE", "Mitte: Die Benutzeroberfläche richtet sich zur Mitte des Bildschirms aus." } } + { EUIAlignmentMode::Edge, { "Rand", "Rand: Die Benutzeroberfläche richtet sich zum Rand des Bildschirms aus." } }, + { EUIAlignmentMode::Centre, { "Mitte", "Mitte: Die Benutzeroberfläche richtet sich zur Mitte des Bildschirms aus." } } } }, { ELanguage::French, { - { EUIAlignmentMode::Edge, { "BORD", "Bord : l'interface utilisateur sera alignée sur les bords de l'écran." } }, - { EUIAlignmentMode::Centre, { "CENTRÉE", "Centrée : l'interface utilisateur sera alignée sur le centre de l'écran." } }, + { EUIAlignmentMode::Edge, { "Bord", "Bord : l'interface utilisateur sera alignée sur les bords de l'écran." } }, + { EUIAlignmentMode::Centre, { "Centrée", "Centrée : l'interface utilisateur sera alignée sur le centre de l'écran." } }, } }, { ELanguage::Spanish, { - { EUIAlignmentMode::Edge, { "BORDE", "Borde: la interfaz de usuario se alineará con los bordes de la pantalla." } }, - { EUIAlignmentMode::Centre, { "CENTRO", "Centro: la interfaz de usuario se alineará con el centro de la pantalla." } }, + { EUIAlignmentMode::Edge, { "Borde", "Borde: la interfaz de usuario se alineará con los bordes de la pantalla." } }, + { EUIAlignmentMode::Centre, { "Centro", "Centro: la interfaz de usuario se alineará con el centro de la pantalla." } }, } }, { ELanguage::Italian, { - { EUIAlignmentMode::Edge, { "BORDI", "Bordi: l'interfaccia si allineerà con i bordi dello schermo." } }, - { EUIAlignmentMode::Centre, { "CENTRO", "Centro: l'interfaccia si allineerà con il centro dello schermo." } } + { EUIAlignmentMode::Edge, { "Bordi", "Bordi: l'interfaccia si allineerà con i bordi dello schermo." } }, + { EUIAlignmentMode::Centre, { "Centro", "Centro: l'interfaccia si allineerà con il centro dello schermo." } } } } }; diff --git a/MarathonRecomp/locale/locale.cpp b/MarathonRecomp/locale/locale.cpp index 4e554e9b4..7412caa9d 100644 --- a/MarathonRecomp/locale/locale.cpp +++ b/MarathonRecomp/locale/locale.cpp @@ -47,7 +47,7 @@ std::unordered_map> "Options_Header_Name", { { ELanguage::English, "OPTIONS" }, - { ELanguage::Japanese, "OPTION" }, + { ELanguage::Japanese, "OPTIONS" }, { ELanguage::German, "OPTIONEN" }, { ELanguage::French, "OPTIONS" }, { ELanguage::Spanish, "OPCIONES" }, @@ -57,45 +57,111 @@ std::unordered_map> { "Options_Category_System", { - { ELanguage::English, "SYSTEM" }, - { ELanguage::Japanese, "SYSTEM" }, - { ELanguage::German, "SYSTEM" }, - { ELanguage::French, "SYSTÈME" }, - { ELanguage::Spanish, "SISTEMA" }, - { ELanguage::Italian, "SISTEMA" } + { ELanguage::English, "System settings" }, + { ELanguage::Japanese, "システム設定" }, + { ELanguage::German, "System-Einstellungen" }, + { ELanguage::French, "Paramètres système" }, + { ELanguage::Spanish, "Configuración del sistema" }, + { ELanguage::Italian, "Impostazioni sistema" } + } + }, + { + "Options_Desc_Category_System", + { + { ELanguage::English, "Adjust system settings." }, + { ELanguage::Japanese, "システムの設定変更します" }, + { ELanguage::German, "Verändere System-Einstellungen." }, + { ELanguage::French, "Modifier les paramètres système." }, + { ELanguage::Spanish, "Ajustar la configuración del sistema." }, + { ELanguage::Italian, "Modifica le impostazioni di sistema." } } }, { "Options_Category_Input", { - { ELanguage::English, "INPUT" }, - { ELanguage::Japanese, "INPUT" }, - { ELanguage::German, "EINGABE" }, - { ELanguage::French, "COMMANDES" }, - { ELanguage::Spanish, "CONTROLES" }, - { ELanguage::Italian, "COMANDI" } + { ELanguage::English, "Input settings" }, + { ELanguage::Japanese, "入力設定" }, + { ELanguage::German, "Eingabe-Einstellungen" }, + { ELanguage::French, "Paramètres d'entrée" }, + { ELanguage::Spanish, "Configuración de entrada" }, + { ELanguage::Italian, "Impostazioni input" } + } + }, + { + "Options_Desc_Category_Input", + { + { ELanguage::English, "Adjust input settings." }, + { ELanguage::Japanese, "入力の設定変更します" }, + { ELanguage::German, "Verändere Eingabe-Einstellungen." }, + { ELanguage::French, "Modifier les paramètres d'entrée." }, + { ELanguage::Spanish, "Ajustar la configuración de entrada." }, + { ELanguage::Italian, "Modifica le impostazioni input." } } }, { "Options_Category_Audio", { - { ELanguage::English, "AUDIO" }, - { ELanguage::Japanese, "AUDIO" }, - { ELanguage::German, "AUDIO" }, - { ELanguage::French, "SON" }, - { ELanguage::Spanish, "AUDIO" }, - { ELanguage::Italian, "AUDIO" } + { ELanguage::English, "Audio settings" }, + { ELanguage::Japanese, "オーディオ設定" }, + { ELanguage::German, "Audio-Einstellungen" }, + { ELanguage::French, "Paramètres audio" }, + { ELanguage::Spanish, "Configuración de audio" }, + { ELanguage::Italian, "Impostazioni audio" } + } + }, + { + "Options_Desc_Category_Audio", + { + { ELanguage::English, "Adjust audio settings." }, + { ELanguage::Japanese, "オーディオの設定を変更します" }, + { ELanguage::German, "Verändere Audio-Einstellungen." }, + { ELanguage::French, "Modifier les paramètres audio." }, + { ELanguage::Spanish, "Ajustar la configuración de audio." }, + { ELanguage::Italian, "Modifica le impostazioni audio." } } }, { "Options_Category_Video", { - { ELanguage::English, "VIDEO" }, - { ELanguage::Japanese, "VIDEO" }, - { ELanguage::German, "VIDEO" }, - { ELanguage::French, "AFFICHAGE" }, - { ELanguage::Spanish, "VÍDEO" }, - { ELanguage::Italian, "VIDEO" } + { ELanguage::English, "Video settings" }, + { ELanguage::Japanese, "ビデオ設定" }, + { ELanguage::German, "Video-Einstellungen" }, + { ELanguage::French, "Paramètres vidéo" }, + { ELanguage::Spanish, "Configuración de vídeo" }, + { ELanguage::Italian, "Impostazioni video" } + } + }, + { + "Options_Desc_Category_Video", + { + { ELanguage::English, "Adjust video settings." }, + { ELanguage::Japanese, "ビデオの設定を変更します" }, + { ELanguage::German, "Verändere Video-Einstellungen." }, + { ELanguage::French, "Modifier les paramètres vidéo." }, + { ELanguage::Spanish, "Ajustar la configuración de vídeo." }, + { ELanguage::Italian, "Modifica le impostazioni video." } + } + }, + { + "Options_Category_Debug", + { + { ELanguage::English, "Debug settings" }, + { ELanguage::Japanese, "デバッグ設定" }, + { ELanguage::German, "Debug-Einstellungen" }, + { ELanguage::French, "Paramètres de débogage" }, + { ELanguage::Spanish, "Configuración de depuración" }, + { ELanguage::Italian, "Impostazioni debug" } + } + }, + { + "Options_Desc_Category_Debug", + { + { ELanguage::English, "Adjust debug settings." }, + { ELanguage::Japanese, "デバッグの設定を変更します" }, + { ELanguage::German, "Verändere Debug-Einstellungen." }, + { ELanguage::French, "Modifier les paramètres de débogage." }, + { ELanguage::Spanish, "Ajustar la configuración de depuración." }, + { ELanguage::Italian, "Modifica le impostazioni debug." } } }, { @@ -125,7 +191,7 @@ std::unordered_map> "Options_Desc_WindowSize", { { ELanguage::English, "Adjust the size of the game window in windowed mode." }, - { ELanguage::Japanese, "ゲームの\u200Bウィンドウサイズを\u200B[設定:せってい]できます" }, + { ELanguage::Japanese, "ゲームのウィンドウサイズを設定できます" }, { ELanguage::German, "Passe die Fenstergröße des Spiels im Fenstermodus an." }, { ELanguage::French, "Définir la résolution de jeu en mode fenêtré." }, { ELanguage::Spanish, "Ajusta el tamaño de la ventana de juego en modo ventana." }, @@ -133,15 +199,27 @@ std::unordered_map> } }, { - // Notes: description for options that cannot be accessed anywhere but the title screen or world map (e.g. Language). + // Notes: description for options that cannot be accessed during gameplay (e.g. Language). "Options_Desc_NotAvailable", { - { ELanguage::English, "This option is not available at this location." }, - { ELanguage::Japanese, "この\u200Bオプションは\u200B[現在:げんざい]の\u200B[画面:がめん]では\u200B[変更:へんこう]\u200Bできません" }, - { ELanguage::German, "Diese Option ist an dieser Stelle nicht verfügbar." }, - { ELanguage::French, "Cette option n'est pas disponible pour l'instant." }, - { ELanguage::Spanish, "Esta opción no está disponible en este momento." }, - { ELanguage::Italian, "Questa opzione non può essere modificata in questo momento." } + { ELanguage::English, "This option is not available during gameplay." }, + { ELanguage::Japanese, "このオプションはゲームプレイ中は使用できません" }, + { ELanguage::German, "Diese Einstellung kann während des Spiels nicht verändert werden." }, + { ELanguage::French, "Cette option est indisponible en cours de jeu." }, + { ELanguage::Spanish, "Esta opción no está disponible durante la partida." }, + { ELanguage::Italian, "Questa opzione non è disponibile durante il gioco." } + } + }, + { + // Notes: description for options that are not implemented yet in development builds. + "Options_Desc_NotImplemented", + { + { ELanguage::English, "This option is not implemented yet." }, + { ELanguage::Japanese, "このオプションはまだ実装されていません" }, + { ELanguage::German, "Diese Einstellung wurde noch nicht implementiert." }, + { ELanguage::French, "Cette option n'est pas encore implémentée." }, + { ELanguage::Spanish, "Esta opción aún no está implementada." }, + { ELanguage::Italian, "Questa opzione non è ancora implementata." } } }, { @@ -149,7 +227,7 @@ std::unordered_map> "Options_Desc_NotAvailableFullscreen", { { ELanguage::English, "This option is not available in fullscreen mode." }, - { ELanguage::Japanese, "この\u200Bオプションは\u200Bフルスクリーンモードでは\u200B[変更:へんこう]\u200Bできません" }, + { ELanguage::Japanese, "このオプションはフルスクリーンモードでは変更できません" }, { ELanguage::German, "Diese Option ist im Vollbildmodus nicht verfügbar." }, { ELanguage::French, "Cette option n'est pas disponible en mode plein écran." }, { ELanguage::Spanish, "Esta opción no está disponible en modo pantalla completa." }, @@ -161,7 +239,7 @@ std::unordered_map> "Options_Desc_NotAvailableWindowed", { { ELanguage::English, "This option is not available in windowed mode." }, - { ELanguage::Japanese, "この\u200Bオプションは\u200Bウィンドウモードでは\u200B[変更:へんこう]\u200Bできません" }, + { ELanguage::Japanese, "このオプションはウィンドウモードでは変更できません" }, { ELanguage::German, "Diese Option ist im Fenstermodus nicht verfügbar." }, { ELanguage::French, "Cette option n'est pas disponible en mode fenêtré." }, { ELanguage::Spanish, "Esta opción no está disponible en modo ventana." }, @@ -173,7 +251,7 @@ std::unordered_map> "Options_Desc_NotAvailableHardware", { { ELanguage::English, "This option is not available with your current hardware configuration." }, - { ELanguage::Japanese, "この\u200Bオプションは\u200B[現在:げんざい]の\u200Bハードウェア[構成:こうせい]で\u200B[変更:へんこう]\u200Bできません" }, + { ELanguage::Japanese, "このオプションは現在のハードウェア構成で変更できません" }, { ELanguage::German, "Diese Option ist mit der momentanen Hardwarekonfiguration nicht verfügbar." }, { ELanguage::French, "Cette option n'est pas disponible avec votre configuration matérielle actuelle." }, { ELanguage::Spanish, "Esta opción no está disponible con tu configuración actual de hardware." }, @@ -185,7 +263,7 @@ std::unordered_map> "Options_Desc_NotAvailableMSAA", { { ELanguage::English, "This option is not available without MSAA." }, - { ELanguage::Japanese, "この\u200Bオプションは\u200BMSAAなしで\u200B[変更:へんこう]\u200Bできません" }, + { ELanguage::Japanese, "このオプションはMSAAなしで変更できません" }, { ELanguage::German, "Diese Option ist ohne MSAA nicht verfügbar." }, { ELanguage::French, "Cette option n'est pas disponible sans MSAA." }, { ELanguage::Spanish, "Esta opción no está disponible sin MSAA." }, @@ -197,23 +275,22 @@ std::unordered_map> "Options_Desc_OSNotSupported", { { ELanguage::English, "This option is not supported by your operating system." }, - { ELanguage::Japanese, "この\u200Bオプションは\u200B[現在:げんざい]の\u200BOSで\u200B[変更:へんこう]\u200Bできません" }, + { ELanguage::Japanese, "このオプションは現在のOSで変更できません" }, { ELanguage::German, "Diese Option wird von diesem Betriebssystem nicht unterstützt." }, { ELanguage::French, "Cette option n'est pas prise en charge par votre système d'exploitation." }, - { ELanguage::Spanish, "Esta opción no está soportada por tu sistema operativo." }, + { ELanguage::Spanish, "Esta opción no es compatible con tu sistema operativo." }, { ELanguage::Italian, "Questa opzione non è disponibile con il tuo sistema operativo." } } }, { - // Notes: message appears when changing the Language option and backing out of the options menu. "Options_Message_Restart", { - { ELanguage::English, "The game will now restart." }, - { ELanguage::Japanese, "ゲームが[再起動:さいきどう]されます" }, - { ELanguage::German, "Das Spiel wird jetzt neu starten." }, - { ELanguage::French, "Le jeu va maintenant redémarrer." }, - { ELanguage::Spanish, "El juego se va a reiniciar." }, - { ELanguage::Italian, "Il gioco verrà riavviato." } + { ELanguage::English, "The game needs to restart to apply\nthe following changes. OK?\n" }, + { ELanguage::Japanese, "以下の変更を適用するには\nゲームを再起動する必要があります\nよろしいですか?\n" }, + { ELanguage::German, "Das Spiel muss neu gestartet werden um die\nfolgenden Änderungen zu speichern. OK?\n" }, + { ELanguage::French, "Le jeu doit redémarrer pour appliquer\nles modifications suivantes. OK ?\n" }, + { ELanguage::Spanish, "Se necesita reiniciar el juego para\naplicar los siguientes cambios. ¿OK?\n" }, + { ELanguage::Italian, "Il gioco deve essere riavviato per\napplicare le seguenti modifiche. OK?\n" } } }, { @@ -277,7 +354,7 @@ std::unordered_map> "Installer_Page_SelectLanguage", { { ELanguage::English, "Please select a language." }, - { ELanguage::Japanese, "[言語:げんご]を[選択:せんたく]してください" }, + { ELanguage::Japanese, "言語を選択してください" }, { ELanguage::German, "Bitte eine Sprache auswählen." }, { ELanguage::French, "Choisissez une langue." }, { ELanguage::Spanish, "Selecciona un idioma." }, @@ -287,19 +364,19 @@ std::unordered_map> { "Installer_Page_Introduction", { - { ELanguage::English, "Welcome to Marathon Recompiled!\n\nYou'll need an Xbox 360 copy\nof Sonic the Hedgehog (2006) in order to proceed with the installation." }, - { ELanguage::Japanese, "Marathon Recompiledへようこそ!\nインストールにはXbox 360[版:ばん]の\n「ソニック・ザ・ヘッジホッグ (2006)」\nが必要です" }, - { ELanguage::German, "Willkommen zu Marathon Recompiled!\n\nEs wird eine Xbox 360 Kopie von\nSonic the Hedgehog (2006) benötigt um mit der Installation fortfahren zu können." }, - { ELanguage::French, "Bienvenue sur Marathon Recompiled !\n\nVous aurez besoin d'une copie de\nSonic the Hedgehog (2006) pour\nXbox 360 pour procéder à l'installation." }, - { ELanguage::Spanish, "¡Bienvenido a Marathon Recompiled!\n\nNecesitas una copia de\nSonic the Hedgehog (2006) de\nXbox 360 para continuar con la instalación." }, - { ELanguage::Italian, "Benvenuto a Marathon Recompiled!\n\nDovrai avere una copia di\nSonic the Hedgehog (2006) per la\nXbox 360 per proseguire con l'installazione." } + { ELanguage::English, "Welcome to Marathon Recompiled!\n\nYou'll need an Xbox 360 copy of\nSONIC THE HEDGEHOG in order to proceed with the installation." }, + { ELanguage::Japanese, "Marathon Recompiledへようこそ!\nインストールにはXbox 360版の\n「ソニック・ザ・ヘッジホッグ」\nが必要です" }, + { ELanguage::German, "Willkommen zu Marathon Recompiled!\n\nEs wird eine Xbox 360 Kopie von\nSONIC THE HEDGEHOG benötigt um mit der Installation fortfahren zu können." }, + { ELanguage::French, "Bienvenue sur Marathon Recompiled !\n\nVous aurez besoin d'une copie de\nSONIC THE HEDGEHOG pour\nXbox 360 pour procéder à l'installation." }, + { ELanguage::Spanish, "¡Bienvenido a Marathon Recompiled!\n\nNecesitas una copia de\nSONIC THE HEDGEHOG de\nXbox 360 para continuar con la instalación." }, + { ELanguage::Italian, "Benvenuto a Marathon Recompiled!\n\nDovrai avere una copia di\nSONIC THE HEDGEHOG per la\nXbox 360 per proseguire con l'installazione." } } }, { "Installer_Page_SelectGame", { { ELanguage::English, "Add the sources for the game." }, - { ELanguage::Japanese, "ゲームのソースを[追加:ついか]" }, + { ELanguage::Japanese, "ゲームのソースを追加" }, { ELanguage::German, "Füge die Quellen für das Spiel." }, { ELanguage::French, "Ajouter les fichiers du jeu." }, { ELanguage::Spanish, "Añade las fuentes para el juego." }, @@ -310,7 +387,7 @@ std::unordered_map> "Installer_Page_SelectDLC", { { ELanguage::English, "Add the sources for the DLC." }, - { ELanguage::Japanese, "DLCのソースを[追加:ついか]" }, + { ELanguage::Japanese, "DLCのソースを追加" }, { ELanguage::German, "Füge die Quellen für die Erweiterungen des Spiels hinzu." }, { ELanguage::French, "Ajouter les fichiers pour les DLCs." }, { ELanguage::Spanish, "Añade las fuentes para el DLC." }, @@ -332,7 +409,7 @@ std::unordered_map> "Installer_Page_Installing", { { ELanguage::English, "Please wait while the content is being installed..." }, - { ELanguage::Japanese, "コンテンツのインストール[中:ちゅう]はお[待:ま]ち\nください" }, + { ELanguage::Japanese, "コンテンツのインストール中はお待ち\nください" }, { ELanguage::German, "Bitte warten. Der Inhalt wird installiert..." }, { ELanguage::French, "Veuillez patienter pendant l'installation du contenu..." }, { ELanguage::Spanish, "Por favor, espera mientras el contenido se instala... " }, @@ -343,7 +420,7 @@ std::unordered_map> "Installer_Page_InstallSucceeded", { { ELanguage::English, "Installation complete!\nThis project is brought to you by:" }, - { ELanguage::Japanese, "インストール[完了:かんりょう]!\nプロジェクト[制作:せいさく]:" }, + { ELanguage::Japanese, "インストール完了!\nプロジェクト制作:" }, { ELanguage::German, "Installation abgeschlossen!\nDieses Projekt wird präsentiert von:" }, { ELanguage::French, "Installation terminée !\nCe projet vous est présenté\npar :" }, { ELanguage::Spanish, "¡Instalación completada!\nEste proyecto ha sido posible gracias a:" }, @@ -354,7 +431,7 @@ std::unordered_map> "Installer_Page_InstallFailed", { { ELanguage::English, "Installation failed.\n\nError: " }, - { ELanguage::Japanese, "インストールに[失敗:しっぱい]しました\n\nエラー: " }, + { ELanguage::Japanese, "インストールに失敗しました\n\nエラー: " }, { ELanguage::German, "Installation fehlgeschlagen.\n\nFehler: " }, { ELanguage::French, "L'installation a échoué.\n\nErreur : " }, { ELanguage::Spanish, "La instalación falló.\n\nError: " }, @@ -376,7 +453,7 @@ std::unordered_map> "Installer_Step_RequiredSpace", { { ELanguage::English, "Required space: %2.2f GiB" }, - { ELanguage::Japanese, "[必要:ひつよう]な[容量:ようりょう]: %2.2f GiB" }, + { ELanguage::Japanese, "必要な容量: %2.2f GiB" }, { ELanguage::German, "Benötigter Speicherplatz:\n%2.2f GiB" }, { ELanguage::French, "Espace nécessaire :\n%2.2f Gio" }, { ELanguage::Spanish, "Espacio necesario: %2.2f GiB" }, @@ -387,7 +464,7 @@ std::unordered_map> "Installer_Step_AvailableSpace", { { ELanguage::English, "Available space: %2.2f GiB" }, - { ELanguage::Japanese, "[使用:しよう][可能:かのう]な[容量:ようりょう]: %2.2f GiB" }, + { ELanguage::Japanese, "使用可能な容量: %2.2f GiB" }, { ELanguage::German, "Verfügbarer Speicherplatz:\n%2.2f GiB" }, { ELanguage::French, "Espace disponible :\n%2.2f Gio" }, { ELanguage::Spanish, "Espacio disponible: %2.2f GiB" }, @@ -454,7 +531,7 @@ std::unordered_map> "Installer_Message_InvalidFilesList", { { ELanguage::English, "The following selected files are invalid:" }, - { ELanguage::Japanese, "[選択:せんたく]した[次:つぎ]のファイルは[無効:むこう]です:" }, + { ELanguage::Japanese, "選択した次のファイルは無効です:" }, { ELanguage::German, "Die folgenden Dateien sind ungültig:" }, { ELanguage::French, "Les fichiers suivants ne sont pas valides :" }, { ELanguage::Spanish, "Los siguientes archivos no son válidos:" }, @@ -466,7 +543,7 @@ std::unordered_map> "Installer_Message_InvalidFiles", { { ELanguage::English, "Some of the files that have\nbeen provided are not valid.\n\nPlease make sure all the\nspecified files are correct\nand try again." }, - { ELanguage::Japanese, "[提供:ていきょう]されたファイルの[一部:いちぶ]が[有効:ゆうこう]ではありません\n[指定:してい]されたファイルがすべて[正:ただ]しいことを[確認:かくにん]して\nもう[一度:いちど]お[試:ため]しください" }, + { ELanguage::Japanese, "提供されたファイルの一部が有効ではありません\n指定されたファイルがすべて正しいことを確認して\nもう一度お試しください" }, { ELanguage::German, "Einige Dateien, die bereitgestellt\nwurden sind ungültig.\n\nBitte stelle sicher, dass\ndie angegebenen Dateien korrekt\nsind und versuche es erneut." }, { ELanguage::French, "Certains fichiers fournis ne\nsont pas valides.\n\nVeuillez vous assurer que tous\nles fichiers spécifiés sont\ncorrects et réessayez." }, { ELanguage::Spanish, "Algunos de los archivos\nseleccionados no son válidos.\n\nPor favor, asegúrate de que\ntodos los archivos son correctos\ne inténtalo de nuevo.\n" }, @@ -478,7 +555,7 @@ std::unordered_map> "Installer_Message_FilePickerTutorial", { { ELanguage::English, "Select a digital dump with\ncontent from the game.\n\nThese files can be obtained from\nyour Xbox 360 hard drive by\nfollowing the instructions on\nthe GitHub page.\n\nFor choosing a folder with extracted\nand unmodified game files, use\nthe \"Add Folder\" option instead." }, - { ELanguage::Japanese, "ゲームのコンテンツを[含:ふく]む デジタルダンプを[選択:せんたく]してください\n\nこれらのファイルは GitHubページの[指示:しじ]に[従:したが]って\nXbox 360ハードドライブから[取得:しゅとく]できます\n\n[抽出:ちゅうしゅつ]された[変更:へんこう]されていない\nゲームファイルを[含:ふく]むフォルダーを[選択:せんたく]するには\n[代:か]わりに「フォルダの[追加:ついか]」オプションを[使用:しよう]してください" }, + { ELanguage::Japanese, "ゲームのコンテンツを含む デジタルダンプを選択してください\n\nこれらのファイルは GitHubページの指示に従って\nXbox 360ハードドライブから取得できます\n\n抽出された変更されていない\nゲームファイルを含むフォルダーを選択するには\n代わりに「フォルダの追加」オプションを使用してください" }, { ELanguage::German, "Wähle einen digitalen Dump von dem Spiel.\n\nDie Dateien können über die Festplatte deiner\nXbox 360 erlangt werden.\nFolge hierfür den Anweisungen auf der GitHub Seite.\n\nUm einen Ordner mit unmodifizierten Spieldateien auszuwählen, benutze die \"Ordner Hinzufügen\" Option stattdessen." }, { ELanguage::French, "Sélectionnez une copie\ndématérialisée avec le contenu du\njeu de base.\n\nCes fichiers peuvent être obtenus\nà partir du disque dur de votre\nXbox 360 en suivant les\ninstructions de la page GitHub.\n\nPour choisir un dossier contenant\nles fichiers de jeu extraits et\nnon modifiés, utilisez plutôt\nl'option \"Ajouter un dossier\"." }, { ELanguage::Spanish, "Selecciona una copia digital\ncon contenido del juego.\n\nPuedes obtener los archivos\nde tu disco duro de Xbox 360\nsiguiendo las instrucciones de\nla página de GitHub.\n\nPara elegir una carpeta con\narchivos extraídos sin modificar,\nutiliza la opción \"Añadir Carpeta\"." }, @@ -490,7 +567,7 @@ std::unordered_map> "Installer_Message_FolderPickerTutorial", { { ELanguage::English, "Select a folder that contains the\nunmodified files that have been\nextracted from the game.\n\nThese files can be obtained from\nyour Xbox 360 hard drive by\nfollowing the instructions on\nthe GitHub page.\n\nFor choosing a digital dump,\nuse the \"Add Files\" option instead." }, - { ELanguage::Japanese, "ゲームから[抽出:ちゅうしゅつ]された[変更:へんこう]されていない\nファイルを含むフォルダを[選択:せんたく]してください\n\nこれらのファイルは GitHubページの[指示:しじ]に[従:したが]って\nXbox 360ハードドライブから[取得:しゅとく]できます\n\nデジタルダンプを[選択:せんたく]するには\n[代:か]わりに「ファイルの[追加:ついか]」オプションを[使用:しよう]してください" }, + { ELanguage::Japanese, "ゲームから抽出された変更されていない\nファイルを含むフォルダを選択してください\n\nこれらのファイルは GitHubページの指示に従って\nXbox 360ハードドライブから取得できます\n\nデジタルダンプを選択するには\n代わりに「ファイルの追加」オプションを使用してください" }, { ELanguage::German, "Wähle einen Ordner, der unmodifizierte Dateien, die vom Spiel extrahiert wurden enthält.\n\nDie Dateien können über die Festplatte deiner\nXbox 360 erlangt werden.\nFolge hierfür den Anweisungen auf der GitHub Seite.\n\nUm einen digitalen Dump auszuwählen, benutze die \"Datei Hinzufügen\" Option stattdessen." }, { ELanguage::French, "Sélectionnez un dossier contenant\nles fichiers extraits du jeu de\nbase.\n\nCes fichiers peuvent être obtenus\nà partir du disque dur de votre\nXbox 360 en suivant les\ninstructions de la page GitHub.\n\nPour choisir une copie\ndématérialisée, utilisez plutôt\nl'option \"Ajouter des fichiers\"." }, { ELanguage::Spanish, "Selecciona una carpeta que\ncontenga los archivos sin\nmodificar extraídos del juego.\n\nPuedes obtener los archivos\nde tu disco duro de Xbox 360\nsiguiendo las instrucciones de\nla página de GitHub.\n\nPara elegir una copia digital,\nutiliza la opción \"Añadir Archivos\"." }, @@ -501,12 +578,12 @@ std::unordered_map> // Notes: message appears when choosing the Install option at the title screen when the user is missing DLC content. "Installer_Message_TitleMissingDLC", { - { ELanguage::English, "This will restart the game to\nallow you to install any DLC\nthat you are missing.\n\nInstalling DLC will improve the\nlighting quality across the game.\n\nWould you like to install missing\ncontent?" }, - { ELanguage::Japanese, "これによりゲームが[再起動:さいきどう]し[不足:ふそく]しているDLCを\nインストールできるようになります\n\nDLCをインストールすると\nゲーム[全体:ぜんたい]の [照明品質:しょうめいひんしつ] が[向上:こうじょう]します\n\n[不足:ふそく]しているコンテンツを\nインストールしますか?" }, - { ELanguage::German, "Das Spiel wird neu gestartet\num die Installation einer fehlenden\nErweiterung zu ermöglichen.\n\nDie Installation einer\nErweiterung erhöht die Qualität\nder Beleuchtung im gesamten Spiel.\n\nMöchtest du den fehlenden\nInhalt installieren?" }, - { ELanguage::French, "Cela redémarrera le jeu pour vous\npermettre d'installer les DLC\nmanquants.\n\nL'installation du DLC améliorera\nla qualité de l'éclairage dans le\njeu.\n\nSouhaitez-vous installer le\ncontenu manquant ?" }, - { ELanguage::Spanish, "Esta opción reiniciará el juego\npara permitirte instalar los DLC\nque falten.\n\nInstalar el DLC mejorará la calidad\nde iluminación en todo el juego.\n\n¿Quieres instalar el contenido\nque falta?" }, - { ELanguage::Italian, "Questa opzione riavviera il gioco\nper farti installare qualsiasi DLC\nche non hai installato.\n\nL'installazione dei DLC migliorerà la qualità\ndell'illuminazione del gioco.\n\nVuoi installare i DLC mancanti?" } + { ELanguage::English, "This will restart the game to\nallow you to install any DLC\nthat you are missing.\n\nWould you like to install missing\ncontent?" }, + { ELanguage::Japanese, "これによりゲームが再起動し不足しているDLCを\nインストールできるようになります\n\n不足しているコンテンツを\nインストールしますか?" }, + { ELanguage::German, "Das Spiel wird neu gestartet\num die Installation einer fehlenden\nErweiterung zu ermöglichen.\n\nMöchtest du den fehlenden\nInhalt installieren?" }, + { ELanguage::French, "Cela redémarrera le jeu pour vous\npermettre d'installer les DLC\nmanquants.\n\nSouhaitez-vous installer le\ncontenu manquant ?" }, + { ELanguage::Spanish, "Esta opción reiniciará el juego\npara permitirte instalar los DLC\nque falten.\n\n¿Quieres instalar el contenido\nque falta?" }, + { ELanguage::Italian, "Questa opzione riavviera il gioco\nper farti installare qualsiasi DLC\nche non hai installato.\n\nVuoi installare i DLC mancanti?" } } }, { @@ -514,7 +591,7 @@ std::unordered_map> "Installer_Message_Title", { { ELanguage::English, "This restarts the game to\nallow you to install any DLC\nthat you may be missing.\n\nYou are not currently\nmissing any DLC.\n\nWould you like to proceed\nanyway?" }, - { ELanguage::Japanese, "これによりゲームが[再起動:さいきどう]され\n[不足:ふそく]しているDLCを\nインストールできるようになります\n\n[現在:げんざい] [不足:ふそく]しているDLCはありません\n\nそれでも[続行:ぞっこう]しますか?" }, + { ELanguage::Japanese, "これによりゲームが再起動され\n不足しているDLCを\nインストールできるようになります\n\n現在 不足しているDLCはありません\n\nそれでも続行しますか?" }, { ELanguage::German, "Das Spiel wird neu gestartet\num die Installation einer fehlenden\nErweiterung zu ermöglichen.\n\nEs kann keine weitere Erweiterung\ninstalliert werden.\n\nMöchtest du trotzdem fortfahren?" }, { ELanguage::French, "Cela redémarrera le jeu pour vous\npermettre d'installer les DLC\nmanquants.\n\nIl ne vous manque aucun DLC.\n\nVoulez-vous quand même continuer ?" }, { ELanguage::Spanish, "Esto reiniciará el juego\npara permitirte instalar\nlos DLC que falten.\n\nActualmente, no falta ningún\nDLC por instalarse.\n\n¿Quieres continuar de todos\nmodos?" }, @@ -526,11 +603,11 @@ std::unordered_map> "Installer_Message_Quit", { { ELanguage::English, "Exit the installer.\nOK?" }, - { ELanguage::Japanese, "" }, - { ELanguage::German, "" }, - { ELanguage::French, "" }, - { ELanguage::Spanish, "" }, - { ELanguage::Italian, "" } + { ELanguage::Japanese, "インストーラーを終了します\nよろしいですか?" }, + { ELanguage::German, "Die Installation verlassen.\nOK?" }, + { ELanguage::French, "Quitter l'installateur.\nOK ?" }, + { ELanguage::Spanish, "¿Salir del instalador?" }, + { ELanguage::Italian, "Esci dall'installatore.\nOK?" } } }, { @@ -538,11 +615,11 @@ std::unordered_map> "Installer_Message_Cancel", { { ELanguage::English, "Cancel the installation.\nOK?" }, - { ELanguage::Japanese, "" }, - { ELanguage::German, "" }, - { ELanguage::French, "" }, - { ELanguage::Spanish, "" }, - { ELanguage::Italian, "" } + { ELanguage::Japanese, "インストールをキャンセルします\nよろしいですか?" }, + { ELanguage::German, "Die Installation abbrechen.\nOK?" }, + { ELanguage::French, "Annuler l'installation.\nOK ?" }, + { ELanguage::Spanish, "¿Cancelar la instalación?" }, + { ELanguage::Italian, "Annulla l'installazione.\nOK?" } } }, { @@ -550,25 +627,11 @@ std::unordered_map> "Title_Message_Quit", { { ELanguage::English, "Exit the game.\nOK?" }, - { ELanguage::Japanese, "" }, - { ELanguage::German, "" }, - { ELanguage::French, "" }, - { ELanguage::Spanish, "" }, - { ELanguage::Italian, "" } - } - }, - { - // Notes: message appears when SYS-DATA is corrupted (mismatching file size) upon pressing start at the title screen. - // To make this occur, open the file in any editor and just remove a large chunk of data. - // Do not localise this unless absolutely necessary, these strings are from the XEX. - "Title_Message_SaveDataCorrupt", - { - { ELanguage::English, "The save file appears to be\ncorrupted and cannot be loaded." }, - { ELanguage::Japanese, "ゲームデータの読み込みに失敗しました。\nこのまま続けるとゲームデータをセーブすることはできません" }, - { ELanguage::German, "Diese Speicherdatei ist beschädigt\nund kann nicht geladen werden." }, - { ELanguage::French, "Le fichier de sauvegarde semble être\nendommagé et ne peut être chargé." }, - { ELanguage::Spanish, "El archivo parece estar dañado\ny no se puede cargar." }, - { ELanguage::Italian, "I file di salvataggio sembrano danneggiati\ne non possono essere caricati." } + { ELanguage::Japanese, "ゲームを終了します\nよろしいですか?" }, + { ELanguage::German, "Das Spiel verlassen.\nOK?" }, + { ELanguage::French, "Quitter le jeu.\nOK ?" }, + { ELanguage::Spanish, "¿Salir del juego?" }, + { ELanguage::Italian, "Esci dal gioco.\nOK?" } } }, { @@ -577,7 +640,7 @@ std::unordered_map> "Title_Message_AchievementDataCorrupt", { { ELanguage::English, "The achievement data appears to be\ncorrupted and cannot be loaded.\n\nProceeding from this point will\nclear your achievement data." }, - { ELanguage::Japanese, "[実績:じっせき]データが[破損:はそん]しているため\n[読:よ]み[込:こ]むことができません\n\nこの[先:さき]に[進:すす]むと[実績:じっせき]データが\n[消去:しょうきょ]されます" }, + { ELanguage::Japanese, "実績データが破損しているため\n読み込むことができません\n\nこの先に進むと実績データが\n消去されます" }, { ELanguage::German, "Die Erfolgsdaten sind möglicherweise\nfehlerhaft und können nicht\ngeladen werden.\n\nDurch das Fortfahren werden\ndeine bisherigen Erfolgsdaten gelöscht." }, { ELanguage::French, "Les données des succès semblent être\nendommagées et ne peuvent être\nchargées.\n\nSi vous continuez, vos données\nseront écrasées." }, { ELanguage::Spanish, "Los datos de logros parecen estar\ncorruptos y no pueden cargarse.\n\nContinuar a partir de este punto\neliminará los datos de logros." }, @@ -590,7 +653,7 @@ std::unordered_map> "Title_Message_AchievementDataIOError", { { ELanguage::English, "The achievement data could not be loaded.\nYour achievements will not be saved." }, - { ELanguage::Japanese, "[実績:じっせき]データを[読:よ]み[込:こ]めませんでした\n[実績:じっせき]は[保存:ほぞん]されません。" }, + { ELanguage::Japanese, "実績データを読み込めませんでした\n実績は保存されません" }, { ELanguage::German, "Die Erfolgsdaten konnten nicht geladen werden.\nDeine Erfolge werden nicht gespeichert." }, { ELanguage::French, "Les données des succès ne\npeuvent être chargées.\nVos succès ne seront pas\nsauvegardés." }, { ELanguage::Spanish, "Los datos de logros no pueden cargarse.\nTus logros no serán guardados." }, @@ -601,7 +664,7 @@ std::unordered_map> "Title_Message_UpdateAvailable", { { ELanguage::English, "An update is available!\n\nWould you like to visit the\nreleases page to download it?" }, - { ELanguage::Japanese, "アップデートが[利用:りよう][可能:かのう]です\n\nリリースページにアクセスして\nダウンロードしますか?" }, + { ELanguage::Japanese, "アップデートが利用可能です\n\nリリースページにアクセスして\nダウンロードしますか?" }, { ELanguage::German, "Ein Update ist verfügbar!\n\nMöchtest du die Release-Seite\nbesuchen um es herunterzuladen?" }, { ELanguage::French, "Une mise à jour est disponible !\n\nVoulez-vous visiter la page\ndes mises à jour pour la\ntélécharger ?" }, { ELanguage::Spanish, "¡Hay una actualización disponible!\n\n¿Quieres ir a la página\npara descargarla?" }, @@ -634,9 +697,9 @@ std::unordered_map> "System_MemoryAllocationFailed", { { ELanguage::English, "Failed to allocate game memory.\n\nPlease make sure that:\n\n- You meet the minimum system requirements (8 GB).\n- Your page file is configured with at least 4-8 GB of virtual memory." }, - { ELanguage::Japanese, "ゲームメモリの割り当てに失敗しました\n\n次の点を確認してください:\n\n※最小システム要件(8 GB)を満たしていること。\n※ページファイルに少なくとも4~8 GBの仮想メモリが設定されていること" }, + { ELanguage::Japanese, "ゲームメモリの割り当てに失敗しました\n\n次の点を確認してください:\n\n※最小システム要件(8 GB)を満たしていること\n※ページファイルに少なくとも4~8 GBの仮想メモリが設定されていること" }, { ELanguage::German, "Fehler beim Zuweisen des Spielspeichers.\n\nBitte stelle sicher, dass:\n\n- Die Mindestanforderungen für das System erfüllt sind (8 GB).\n- Die Auslagerungsdatei mit mindestens 4-8 GB virtuellem Speicher konfiguriert ist." }, - { ELanguage::French, "Échec d'allocation de la mémoire du jeu.\n\nVeuillez vous assurer que :\n\n- Vous disposez de la configuration minimale requise (8 Go).\n- Votre fichier d’échange est configuré avec au moins 4 à 8 Go de mémoire virtuelle." }, + { ELanguage::French, "Échec d'allocation de la mémoire du jeu.\n\nVeuillez vous assurer que :\n\n- Vous disposez de la configuration minimale requise (8 Go).\n- Votre fichier d'échange est configuré avec au moins 4 à 8 Go de mémoire virtuelle." }, { ELanguage::Spanish, "Fallo al asignar memoria del juego.\n\nPor favor, asegúrate de que:\n\n- Cumples los requisitos mínimos del sistema (8 GB).\n- Tu archivo de páginación está configurado con al menos 4 u 8 GB de memoria virtual." }, { ELanguage::Italian, "Impossibile allocare la memoria per il gioco.\n\nAssicurati che:\n\n- Soddisfi i requisiti minimi di sistema (8 GB).\n- Il tuo file di paging sia configurato con almeno 4 o 8 GB di memoria virtuale." } } @@ -677,23 +740,23 @@ std::unordered_map> { "Common_On", { - { ELanguage::English, "ON" }, + { ELanguage::English, "On" }, { ELanguage::Japanese, "オン" }, - { ELanguage::German, "EIN" }, - { ELanguage::French, "OUI" }, - { ELanguage::Spanish, "SÍ" }, - { ELanguage::Italian, "SÌ" } + { ELanguage::German, "An" }, + { ELanguage::French, "Oui" }, + { ELanguage::Spanish, "Act." }, + { ELanguage::Italian, "Sì" } } }, { "Common_Off", { - { ELanguage::English, "OFF" }, + { ELanguage::English, "Off" }, { ELanguage::Japanese, "オフ" }, - { ELanguage::German, "AUS" }, - { ELanguage::French, "NON" }, - { ELanguage::Spanish, "NO" }, - { ELanguage::Italian, "NO" } + { ELanguage::German, "Aus" }, + { ELanguage::French, "Non" }, + { ELanguage::Spanish, "Desact." }, + { ELanguage::Italian, "No" } } }, { @@ -703,7 +766,7 @@ std::unordered_map> { ELanguage::Japanese, "はい" }, { ELanguage::German, "Ja" }, { ELanguage::French, "Oui" }, - { ELanguage::Spanish, "Sí" }, + { ELanguage::Spanish, "Sí" }, { ELanguage::Italian, "Sì" } } }, @@ -725,7 +788,7 @@ std::unordered_map> { ELanguage::Japanese, "次へ" }, { ELanguage::German, "Weiter" }, { ELanguage::French, "Suivant" }, - { ELanguage::Spanish, "Siguiente" }, + { ELanguage::Spanish, "Siguiente" }, { ELanguage::Italian, "Avanti" } } }, @@ -735,7 +798,7 @@ std::unordered_map> { ELanguage::English, "Select" }, { ELanguage::Japanese, "決定" }, { ELanguage::German, "Auswählen" }, - { ELanguage::French, "Choisir" }, + { ELanguage::French, "Sélectionner" }, { ELanguage::Spanish, "Seleccionar" }, { ELanguage::Italian, "Seleziona" } } @@ -744,7 +807,7 @@ std::unordered_map> "Common_Back", { { ELanguage::English, "Back" }, - { ELanguage::Japanese, "もどる" }, + { ELanguage::Japanese, "戻る" }, { ELanguage::German, "Zurück" }, { ELanguage::French, "Retour" }, { ELanguage::Spanish, "Atrás" }, @@ -755,11 +818,11 @@ std::unordered_map> "Common_Quit", { { ELanguage::English, "Quit" }, - { ELanguage::Japanese, "終了" }, - { ELanguage::German, "Verlassen" }, - { ELanguage::French, "Quitter" }, - { ELanguage::Spanish, "Salir" }, - { ELanguage::Italian, "Esci" } + { ELanguage::Japanese, "やめる" }, + { ELanguage::German, "Abbrechen" }, + { ELanguage::French, "Annuler" }, + { ELanguage::Spanish, "Cancelar" }, + { ELanguage::Italian, "Annulla" } } }, { @@ -780,7 +843,7 @@ std::unordered_map> { ELanguage::Japanese, "リセット" }, { ELanguage::German, "Zurücksetzen" }, { ELanguage::French, "Par défaut" }, - { ELanguage::Spanish, "Reiniciar" }, + { ELanguage::Spanish, "Restablecer" }, { ELanguage::Italian, "Ripristina" } } }, @@ -794,7 +857,52 @@ std::unordered_map> { ELanguage::Spanish, "Cambiar" }, { ELanguage::Italian, "Cambia" } } - } + }, + { + "Button_Cancel", + { + { ELanguage::English, "${picture(button_b)}${locale(Common_Cancel)}" }, + { ELanguage::Spanish, "${picture(button_b)} ${locale(Common_Cancel)}" } + } + }, + { + "Button_Back", + { + { ELanguage::English, "${picture(button_b)}${locale(Common_Back)}" }, + { ELanguage::Spanish, "${picture(button_b)} ${locale(Common_Back)}" } + } + }, + { + "Button_Select", + { + { ELanguage::English, "${picture(button_a)}${locale(Common_Select)}" }, + { ELanguage::Spanish, "${picture(button_a)} ${locale(Common_Select)}" }, + } + }, + { + "Button_SelectQuit", + { + { ELanguage::English, "${picture(button_a)}${locale(Common_Select)} ${picture(button_b)}${locale(Common_Quit)}" }, + { ELanguage::German, "${picture(button_a)}${locale(Common_Select)}  ${picture(button_b)}${locale(Common_Quit)}" }, + { ELanguage::Spanish, "${picture(button_a)} ${locale(Common_Select)} ${picture(button_b)} ${locale(Common_Quit)}" }, + } + }, + { + "Button_SelectBack", + { + { ELanguage::English, "${picture(button_a)}${locale(Common_Select)} ${picture(button_b)}${locale(Common_Back)}" }, + { ELanguage::German, "${picture(button_a)}${locale(Common_Select)}  ${picture(button_b)}${locale(Common_Back)}" }, + { ELanguage::Spanish, "${picture(button_a)} ${locale(Common_Select)} ${picture(button_b)} ${locale(Common_Back)}" }, + } + }, + { + "Button_ResetSelectBack", + { + { ELanguage::English, "${picture(button_x)}${locale(Common_Reset)} ${picture(button_a)}${locale(Common_Select)} ${picture(button_b)}${locale(Common_Back)}" }, + { ELanguage::German, "${picture(button_x)}${locale(Common_Reset)}  ${picture(button_a)}${locale(Common_Select)}  ${picture(button_b)}${locale(Common_Back)}" }, + { ELanguage::Spanish, "${picture(button_x)} ${locale(Common_Reset)} ${picture(button_a)} ${locale(Common_Select)} ${picture(button_b)} ${locale(Common_Back)}" }, + } + }, }; std::string& Localise(const std::string_view& key) diff --git a/MarathonRecomp/main.cpp b/MarathonRecomp/main.cpp index 6c9c4e529..600d1848e 100644 --- a/MarathonRecomp/main.cpp +++ b/MarathonRecomp/main.cpp @@ -29,6 +29,7 @@ #include #include #include +#include #ifdef _WIN32 #include @@ -190,6 +191,7 @@ int main(int argc, char *argv[]) useDefaultWorkingDirectory = useDefaultWorkingDirectory || (strcmp(argv[i], "--use-cwd") == 0); forceInstallationCheck = forceInstallationCheck || (strcmp(argv[i], "--install-check") == 0); graphicsApiRetry = graphicsApiRetry || (strcmp(argv[i], "--graphics-api-retry") == 0); + App::s_isSkipLogos = App::s_isSkipLogos || (strcmp(argv[i], "--skip-logos") == 0); if (strcmp(argv[i], "--sdl-video-driver") == 0) { diff --git a/MarathonRecomp/patches/MainMenuTask_patches.cpp b/MarathonRecomp/patches/MainMenuTask_patches.cpp index 3c83651d9..f672c1a41 100644 --- a/MarathonRecomp/patches/MainMenuTask_patches.cpp +++ b/MarathonRecomp/patches/MainMenuTask_patches.cpp @@ -1,10 +1,100 @@ #include "MainMenuTask_patches.h" +#include +#include // Sonicteam::MainMenuTask::Update PPC_FUNC_IMPL(__imp__sub_824FFCF8); PPC_FUNC(sub_824FFCF8) { auto pMainMenuTask = (Sonicteam::MainMenuTask*)(base + ctx.r3.u32); + auto pHUDMainMenu = pMainMenuTask->m_pHUDMainMenu; + +#ifdef MARATHON_RECOMP_OPTIONS_MENU + if (pMainMenuTask->m_State == Sonicteam::MainMenuTask::MainMenuState_MainMenu && pMainMenuTask->m_MainMenuSelectedIndex == 3) + { + if (!OptionsMenu::s_isVisible && (pMainMenuTask->m_PressedButtons.get() & 0x10) != 0) + { + OptionsMenu::s_pMainMenuTask = pMainMenuTask; + OptionsMenu::Open(); + + Game_PlaySound("main_deside"); + + pMainMenuTask->m_State = Sonicteam::MainMenuTask::MainMenuState_MainMenu; + pMainMenuTask->m_PressedButtons = 0; + + guest_stack_var msgHUDMainMenuSetCursor + ( + Sonicteam::HUDMainMenu::HUDMainMenuState_MainCursorOutro, + pMainMenuTask->m_MainMenuSelectedIndex + ); + + // Play cursor outro animation. + pHUDMainMenu->ProcessMessage(msgHUDMainMenuSetCursor.get()); + + guest_stack_var msgHUDMainMenuTransition + ( + Sonicteam::HUDMainMenu::HUDMainMenuState_OptionsOutro, 3 + ); + + // Play main menu -> options transition. + pHUDMainMenu->ProcessMessage(msgHUDMainMenuTransition.get()); + } + } + + static bool s_isReturningFromOptionsMenu{}; + static float s_buttonWindowTextOffsetY{}; + + auto& rButtonWindowTextOffsetY = pMainMenuTask->m_pButtonWindowTask->m_pHUDButtonWindow->m_pHudTextParts->m_OffsetY; + + if (pHUDMainMenu) + { + // Hide original "OPTIONS" title. + if (auto pOptionsSelect = pHUDMainMenu->m_pHudTextRoot->Find("options_select", "options")) + pOptionsSelect->m_Priority = -1.0f; + } + + if (OptionsMenu::s_isVisible) + { + pMainMenuTask->m_PressedButtons = 0; + + switch (OptionsMenu::s_state) + { + case OptionsMenuState::Opening: + { + static constexpr double HIDE_TEXT_OFFSET = -100000.0f; + + if (rButtonWindowTextOffsetY == HIDE_TEXT_OFFSET) + break; + + // Move original button window text very far off screen to hide it. + s_buttonWindowTextOffsetY = rButtonWindowTextOffsetY; + rButtonWindowTextOffsetY = HIDE_TEXT_OFFSET; + + break; + } + + case OptionsMenuState::Closing: + s_isReturningFromOptionsMenu = true; + break; + } + } + else if (s_isReturningFromOptionsMenu) + { + // Restore original button window text offset. + rButtonWindowTextOffsetY = s_buttonWindowTextOffsetY; + + if ((pHUDMainMenu->m_CursorFlags.get() & 2) != 0) + { + // Prevent inputs leaking from the + // options menu to the main menu. + pMainMenuTask->m_PressedButtons = 0; + } + else + { + s_isReturningFromOptionsMenu = false; + } + } +#endif MainMenuTaskPatches::State = (Sonicteam::MainMenuTask::MainMenuState)pMainMenuTask->m_State.get(); diff --git a/MarathonRecomp/patches/TitleTask_patches.cpp b/MarathonRecomp/patches/TitleTask_patches.cpp index 0fe1c5df2..70e114deb 100644 --- a/MarathonRecomp/patches/TitleTask_patches.cpp +++ b/MarathonRecomp/patches/TitleTask_patches.cpp @@ -1,6 +1,7 @@ #include #include #include +#include #include #include #include @@ -16,6 +17,19 @@ static double g_titleExitOutroTime{}; static bool g_quitMessageOpen{}; static bool g_saveDataExists{}; +static bool g_isSecretDone{}; +static uint32_t g_secretFlags{}; + +enum +{ + SECRET_NONE, + SECRET_UP = 1 << 0, + SECRET_DOWN = 1 << 1, + SECRET_LEFT = 1 << 2, + SECRET_RIGHT = 1 << 3, + SECRET_ALL = SECRET_UP | SECRET_DOWN | SECRET_LEFT | SECRET_RIGHT +}; + bool ProcessQuitMessage(Sonicteam::TitleTask* pTitleTask) { static int s_quitMessageResult = -1; @@ -91,13 +105,50 @@ PPC_FUNC(sub_825126A0) break; } - case Sonicteam::TitleTask::TitleState_Proceed: + case Sonicteam::TitleTask::TitleState_Wait: { - g_saveDataExists = std::filesystem::exists(GetSaveFilePath(false)); + if (g_isSecretDone) + break; - // Redirect PRESS START proceed to options open. - if (g_saveDataExists) - GuestToHostFunction(sub_82511CA0, pTitleTask, (int)Sonicteam::TitleTask::TitleState_OptionsOpen); + if (auto& spInputManager = App::s_pApp->m_pDoc->m_vspInputManager[0]) + { + auto& rPadState = spInputManager->m_PadState; + + if (rPadState.IsPressed(Sonicteam::SoX::Input::KeyState_DpadUp)) + g_secretFlags = SECRET_UP; + + if ((g_secretFlags & SECRET_UP) != 0 && rPadState.IsPressed(Sonicteam::SoX::Input::KeyState_DpadDown)) + g_secretFlags |= SECRET_DOWN; + + if ((g_secretFlags & SECRET_DOWN) != 0 && rPadState.IsPressed(Sonicteam::SoX::Input::KeyState_DpadLeft)) + g_secretFlags |= SECRET_LEFT; + + if ((g_secretFlags & SECRET_LEFT) != 0 && rPadState.IsPressed(Sonicteam::SoX::Input::KeyState_DpadRight)) + g_secretFlags |= SECRET_RIGHT; + } + + if (g_secretFlags == SECRET_ALL) + { + Game_PlaySound("totalring_count"); + g_isSecretDone = true; + } + + break; + } + + case Sonicteam::TitleTask::TitleState_OptionsWait: + { + if (auto& spInputManager = App::s_pApp->m_pDoc->m_vspInputManager[0]) + { + auto& rPadState = spInputManager->m_PadState; + + if (g_secretFlags == SECRET_ALL && + rPadState.IsDown(Sonicteam::SoX::Input::KeyState_A) && + rPadState.IsDown(Sonicteam::SoX::Input::KeyState_Start)) + { + OptionsMenu::s_isDebugUnlocked = true; + } + } break; } @@ -115,6 +166,17 @@ PPC_FUNC(sub_825126A0) break; } + + case Sonicteam::TitleTask::TitleState_Proceed: + { + g_saveDataExists = std::filesystem::exists(GetSaveFilePath(false)); + + // Redirect PRESS START proceed to options open. + if (g_saveDataExists) + GuestToHostFunction(sub_82511CA0, pTitleTask, (int)Sonicteam::TitleTask::TitleState_OptionsOpen); + + break; + } } if (pTitleTask->m_State != Sonicteam::TitleTask::TitleState_OptionsProceed) diff --git a/MarathonRecomp/patches/aspect_ratio_patches.cpp b/MarathonRecomp/patches/aspect_ratio_patches.cpp index 7aad517d6..3f97b9eba 100644 --- a/MarathonRecomp/patches/aspect_ratio_patches.cpp +++ b/MarathonRecomp/patches/aspect_ratio_patches.cpp @@ -8,6 +8,7 @@ #include #include #include +#include #include #include @@ -92,7 +93,7 @@ static class LoadingPillarboxEvent : public HookEvent void Update(float deltaTime) override { if (g_aspectRatio > WIDE_ASPECT_RATIO) - BlackBar::g_isVisible = true; + BlackBar::Show(); } } g_loadingPillarboxEvent{}; @@ -175,11 +176,13 @@ void AspectRatioPatches::ComputeOffsets() g_aspectRatioOffsetY = (height - width / NARROW_ASPECT_RATIO) / 2.0f; g_aspectRatioScale = width / 960.0f; g_aspectRatioGameplayScale = ComputeScale(NARROW_ASPECT_RATIO); - } + } g_aspectRatioMultiplayerOffsetX = g_aspectRatioOffsetX / 2.0f; - g_aspectRatioNarrowScale = std::clamp((g_aspectRatio - NARROW_ASPECT_RATIO) / (WIDE_ASPECT_RATIO - NARROW_ASPECT_RATIO), 0.0f, 1.0f); + g_aspectRatioNarrowMargin = std::lerp(50.0f, 0.0f, g_aspectRatioNarrowScale); + g_horzCentre = g_aspectRatioOffsetX + 640.0f * (1.0f - g_aspectRatioGameplayScale) * g_aspectRatioScale; + g_vertCentre = g_aspectRatioOffsetY + 360.0f * (1.0f - g_aspectRatioGameplayScale) * g_aspectRatioScale; g_radarMapScale = 256 * g_aspectRatioScale * g_aspectRatioGameplayScale; } @@ -407,6 +410,10 @@ void Draw(PPCContext& ctx, uint8_t* base, PPCFunc* original, uint32_t stride) modifier = g_sceneModifier.value(); } + // Hide original button window whilst the options menu is visible. + if ((modifier.Flags & CSD_BUTTON_WINDOW) != 0 && OptionsMenu::s_isVisible) + return; + // Remove all flags if the aspect ratio is above 16:9. if ((modifier.Flags & CSD_MODIFIER_ULTRAWIDE_ONLY) != 0 && g_aspectRatio <= WIDE_ASPECT_RATIO) modifier.Flags &= (~modifier.Flags) | CSD_MODIFIER_ULTRAWIDE_ONLY; @@ -443,13 +450,13 @@ void Draw(PPCContext& ctx, uint8_t* base, PPCFunc* original, uint32_t stride) // Draw black bars if this cast is drawn. if ((modifier.Flags & CSD_BLACK_BAR) != 0) - BlackBar::g_isVisible = true; + BlackBar::Show(); // Prohibit black bars from being drawn if this cast is drawn. if ((modifier.Flags & CSD_PROHIBIT_BLACK_BAR) != 0) - BlackBar::g_isVisible = false; + BlackBar::Hide(); - if (Config::UIAlignmentMode == EUIAlignmentMode::Centre || BlackBar::g_isVisible) + if (Config::UIAlignmentMode == EUIAlignmentMode::Centre || BlackBar::IsVisible()) { // Prevent chevron arrows from being unaligned by centred aspect ratio. if ((modifier.Flags & CSD_CHEVRON) == 0) @@ -534,7 +541,7 @@ void Draw(PPCContext& ctx, uint8_t* base, PPCFunc* original, uint32_t stride) if ((modifier.Flags & CSD_ALIGN_RIGHT) != 0) offsetX += 1280.0f * (1.0f - g_aspectRatioGameplayScale) * g_aspectRatioScale; else if ((modifier.Flags & CSD_ALIGN_LEFT) == 0) - offsetX += 640.0f * (1.0f - g_aspectRatioGameplayScale) * g_aspectRatioScale; + offsetX += g_horzCentre - g_aspectRatioOffsetX; offsetX += pivotX * g_aspectRatioScale; } @@ -561,7 +568,7 @@ void Draw(PPCContext& ctx, uint8_t* base, PPCFunc* original, uint32_t stride) if ((modifier.Flags & CSD_ALIGN_BOTTOM) != 0) offsetY += 720.0f * (1.0f - g_aspectRatioGameplayScale) * g_aspectRatioScale; else if ((modifier.Flags & CSD_ALIGN_TOP) == 0) - offsetY += 360.0f * (1.0f - g_aspectRatioGameplayScale) * g_aspectRatioScale; + offsetY += g_vertCentre - g_aspectRatioOffsetY; offsetY += pivotY * g_aspectRatioScale; } @@ -1120,7 +1127,7 @@ void Draw(PPCContext& ctx, uint8_t* base, PPCFunc* original, uint32_t stride) drawOriginal(); } } - else + else if (g_aspectRatio < WIDE_ASPECT_RATIO) { ///////////////////////////////////////////////// // Scale metal borders to narrow aspect ratios // @@ -1148,18 +1155,6 @@ void Draw(PPCContext& ctx, uint8_t* base, PPCFunc* original, uint32_t stride) getVertex(0)->V = getVertex(0)->V + 0.005f; getVertex(2)->V = getVertex(2)->V + 0.005f; - if (g_aspectRatio < NARROW_ASPECT_RATIO) - { - // Extend to the top of the screen - // if the first clone no longer fits. - getVertex(1)->Y = 0.0f; - getVertex(3)->Y = 0.0f; - - // Crop bottom UVs to remove metal notch. - getVertex(1)->V = getVertex(1)->V + -0.067f; - getVertex(3)->V = getVertex(3)->V + -0.067f; - } - drawOriginal(); } @@ -1185,21 +1180,14 @@ void Draw(PPCContext& ctx, uint8_t* base, PPCFunc* original, uint32_t stride) getVertex(1)->V = getVertex(1)->V + -0.005f; getVertex(3)->V = getVertex(3)->V + -0.005f; - if (g_aspectRatio < NARROW_ASPECT_RATIO) - { - // Extend to the bottom of the screen - // if the first clone no longer fits. - getVertex(0)->Y = vpHeight; - getVertex(2)->Y = vpHeight; - - // Crop top UVs to remove metal dip. - getVertex(0)->V = getVertex(0)->V + 0.065f; - getVertex(2)->V = getVertex(2)->V + 0.065f; - } - drawOriginal(); } } + else + { + if (isMainMenuPanels) + drawOriginal(); + } ctx.r1.u32 += size; } @@ -1241,7 +1229,7 @@ PPC_FUNC_IMPL(__imp__sub_8264AC48); PPC_FUNC(sub_8264AC48) { if (Config::CutsceneAspectRatio == ECutsceneAspectRatio::Original) - BlackBar::g_isVisible = true; + BlackBar::Show(); __imp__sub_8264AC48(ctx, base); } @@ -1250,16 +1238,19 @@ PPC_FUNC(sub_8264AC48) PPC_FUNC_IMPL(__imp__sub_824F4D80); PPC_FUNC(sub_824F4D80) { - BlackBar::g_isVisible = true; + BlackBar::Show(); __imp__sub_824F4D80(ctx, base); } -// Sonicteam::HUDBattleResult::Update PPC_FUNC_IMPL(__imp__sub_824D32C8); PPC_FUNC(sub_824D32C8) { - BlackBar::g_isVisible = true; + auto vftable = PPC_LOAD_U32(ctx.r3.u32); + + // Sonicteam::HUDBattleResult + if (vftable == 0x820363E0) + BlackBar::Show(); __imp__sub_824D32C8(ctx, base); } @@ -1268,7 +1259,7 @@ PPC_FUNC(sub_824D32C8) PPC_FUNC_IMPL(__imp__sub_824A4A40); PPC_FUNC(sub_824A4A40) { - BlackBar::g_isVisible = true; + BlackBar::Show(); __imp__sub_824A4A40(ctx, base); } @@ -1355,7 +1346,7 @@ PPC_FUNC(sub_8264CC90) LOGFN_UTILITY("Movie: {} - {}x{}", pMovieObjectWmv->m_FilePath.c_str(), pMovieObjectWmv->m_Width.get(), pMovieObjectWmv->m_Height.get()); } - auto movieModifier = FindMovieModifier(movieNameHash); + auto movieModifier = FindHash(g_movieModifiers, movieNameHash); g_aspectRatioMovie = (float)pMovieObjectWmv->m_Width / (float)pMovieObjectWmv->m_Height; @@ -1471,11 +1462,12 @@ void ReplaceTextVariables(Sonicteam::TextEntity* pTextEntity) isPlayStation = hid::g_inputDeviceController == hid::EInputDevice::PlayStation; auto& pftModifier = isPlayStation - ? g_pftModifierPS3 - : g_pftModifierXenon; + ? g_buttonCropsPS3 + : g_buttonCropsXenon; - auto baseParams = FindFontPictureModifier(g_pftModifierXenon, variable.second); - auto newParams = FindFontPictureModifier(pftModifier, variable.second); + auto hash = HashStr(variable.second); + auto baseParams = FindHash(g_buttonCropsXenon, hash); + auto newParams = FindHash(pftModifier, hash); auto uv = PIXELS_TO_UV_COORDS(g_fontPictureWidth, g_fontPictureHeight, newParams.X, newParams.Y, newParams.Width, newParams.Height); auto& min = std::get<0>(uv); @@ -1569,7 +1561,7 @@ PPC_FUNC(sub_8262D868) auto offsetY = 0.0f; auto scale = g_aspectRatioScale; - if (Config::UIAlignmentMode == EUIAlignmentMode::Centre || BlackBar::g_isVisible) + if (Config::UIAlignmentMode == EUIAlignmentMode::Centre || BlackBar::IsVisible()) { if (g_aspectRatio > WIDE_ASPECT_RATIO) { @@ -1648,16 +1640,21 @@ PPC_FUNC(sub_824E2978) PPC_FUNC_IMPL(__imp__sub_824E11D0); PPC_FUNC(sub_824E11D0) { - auto pHUDMainMenu = (Sonicteam::HUDMainMenu*)(base + ctx.r3.u32); - auto pHudTextRoot = pHUDMainMenu->m_pHudTextRoot->m_pNext; + auto pHUDMainMenu = (Sonicteam::HUDMainMenu*)(base + ctx.r3.u32 - 8); + auto pHudTextRoot = pHUDMainMenu->m_pHudTextRoot; + + static bool s_preservedTextParams{}; + static float s_multiplayerTextOffsetY{}; + static float s_tagTextOffsetY{}; + static float s_battleTextOffsetY{}; - static bool s_preservedTextPositions{}; - static float s_multiplayerTextOffsetX{}; - static float s_tagTextOffsetX{}; - static float s_battleTextOffsetX{}; + static constexpr double HIDE_TEXT_OFFSET = -100000.0f; auto isTrialSelect = MainMenuTaskPatches::State >= 12 && MainMenuTaskPatches::State <= 15; - auto isTag = MainMenuTaskPatches::State == Sonicteam::MainMenuTask::MainMenuState_Tag; + + auto isTag = MainMenuTaskPatches::State == Sonicteam::MainMenuTask::MainMenuState_Tag || + MainMenuTaskPatches::State == Sonicteam::MainMenuTask::MainMenuState_Tag1PSelect || + MainMenuTaskPatches::State == Sonicteam::MainMenuTask::MainMenuState_MainMenuExitToStage; while (pHudTextRoot) { @@ -1665,31 +1662,38 @@ PPC_FUNC(sub_824E11D0) { if (pHudTextRoot->m_CastName == "multi_player") { - if (!s_preservedTextPositions) - s_multiplayerTextOffsetX = pHudTextRoot->m_OffsetX; + if (!s_preservedTextParams) + s_multiplayerTextOffsetY = pHudTextRoot->m_OffsetY; - pHudTextRoot->m_OffsetX = isTrialSelect ? -10000.0f : s_multiplayerTextOffsetX; + pHudTextRoot->m_OffsetY = isTrialSelect ? HIDE_TEXT_OFFSET : s_multiplayerTextOffsetY; } else if (pHudTextRoot->m_CastName == "tag") { - if (!s_preservedTextPositions) - s_tagTextOffsetX = pHudTextRoot->m_OffsetX; + if (!s_preservedTextParams) + s_tagTextOffsetY = pHudTextRoot->m_OffsetY; - pHudTextRoot->m_OffsetX = (isTrialSelect || isTag) ? -10000.0f : s_tagTextOffsetX; + pHudTextRoot->m_OffsetY = (isTrialSelect || isTag) ? HIDE_TEXT_OFFSET : s_tagTextOffsetY; } else if (pHudTextRoot->m_CastName == "battle") { - if (!s_preservedTextPositions) - s_battleTextOffsetX = pHudTextRoot->m_OffsetX; + if (!s_preservedTextParams) + s_battleTextOffsetY = pHudTextRoot->m_OffsetY; - pHudTextRoot->m_OffsetX = isTrialSelect ? -10000.0f : s_battleTextOffsetX; + pHudTextRoot->m_OffsetY = isTrialSelect ? HIDE_TEXT_OFFSET : s_battleTextOffsetY; } } pHudTextRoot = pHudTextRoot->m_pNext; } - s_preservedTextPositions = true; + s_preservedTextParams = true; + + // Draw faded letterbox at tall aspect ratios. + if (!OptionsMenu::s_isVisible && g_aspectRatio < NARROW_ASPECT_RATIO) + { + BlackBar::Show(true); + BlackBar::SetBorderMargin(Scale(BlackBar::ms_MenuBorderMargin, true)); + } __imp__sub_824E11D0(ctx, base); } @@ -1761,7 +1765,7 @@ const xxHashMap g_csdModifiers = { HashStr("sprite/audio/audio/audio_cursor2"), { CSD_SCALE } }, // background - { HashStr("sprite/background/background/mainmenu_back"), { CSD_STRETCH_HORIZONTAL | CSD_PROHIBIT_BLACK_BAR } }, + { HashStr("sprite/background/background/mainmenu_back"), { CSD_MODIFIER_ULTRAWIDE_ONLY | CSD_STRETCH_HORIZONTAL | CSD_PROHIBIT_BLACK_BAR } }, { HashStr("sprite/background/background/tag"), { CSD_SCALE } }, { HashStr("sprite/background/background/movie"), { CSD_SCALE } }, { HashStr("sprite/background/background/main_menu"), { CSD_SCENE_DISABLE_MOTION | CSD_MODIFIER_ULTRAWIDE_ONLY } }, @@ -1859,8 +1863,8 @@ const xxHashMap g_csdModifiers = { HashStr("event/e1141/sonic_the_hedgehog/Scene_0000"), { CSD_ALIGN_BOTTOM_RIGHT | CSD_SCALE } }, // button_window - { HashStr("sprite/button_window/button_window/Scene_0000/Null_0000/Cast_0001"), { CSD_SCALE } }, - { HashStr("sprite/button_window/button_window/Scene_0000/Null_0000/Cast_0002"), { CSD_SCALE | CSD_EXTEND_RIGHT } }, + { HashStr("sprite/button_window/button_window/Scene_0000/Null_0000/Cast_0001"), { CSD_BUTTON_WINDOW | CSD_SCALE } }, + { HashStr("sprite/button_window/button_window/Scene_0000/Null_0000/Cast_0002"), { CSD_BUTTON_WINDOW | CSD_SCALE | CSD_EXTEND_RIGHT } }, // cri_logo { HashStr("sprite/logo/cri_logo/Scene_0000/Null_0002/bg"), { CSD_STRETCH } }, @@ -2254,46 +2258,6 @@ std::optional FindCsdModifier(uint32_t data) return {}; } -// -------------- TEXT MODIFIERS -------------- // - -const xxHashMap g_pftModifierXenon = -{ - { HashStr("button_a"), { 0, 0, 28, 28 } }, - { HashStr("button_b"), { 28, 0, 28, 28 } }, - { HashStr("button_x"), { 56, 0, 28, 28 } }, - { HashStr("button_y"), { 84, 0, 28, 28 } }, - { HashStr("button_lb"), { 112, 0, 53, 28 } }, - { HashStr("button_lt"), { 56, 28, 55, 28 } }, - { HashStr("button_rb"), { 168, 0, 53, 28 } }, - { HashStr("button_rt"), { 0, 28, 55, 28 } }, - { HashStr("button_start"), { 112, 28, 28, 28 } }, - { HashStr("button_back"), { 140, 28, 28, 28 } } -}; - -const xxHashMap g_pftModifierPS3 = -{ - { HashStr("button_a"), { 0, 56, 28, 28 } }, - { HashStr("button_b"), { 28, 56, 28, 28 } }, - { HashStr("button_x"), { 56, 56, 28, 28 } }, - { HashStr("button_y"), { 84, 56, 28, 28 } }, - { HashStr("button_lb"), { 112, 56, 48, 28 } }, - { HashStr("button_lt"), { 168, 56, 48, 28 } }, - { HashStr("button_rb"), { 0, 84, 48, 28 } }, - { HashStr("button_rt"), { 56, 84, 48, 28 } }, - { HashStr("button_start"), { 140, 84, 28, 28 } }, - { HashStr("button_back"), { 112, 84, 28, 28 } } -}; - -TextFontPictureModifier FindFontPictureModifier(xxHashMap pftModifier, std::string_view& name) -{ - auto findResult = pftModifier.find(HashStr(name)); - - if (findResult != pftModifier.end()) - return findResult->second; - - return {}; -} - // ------------- MOVIE MODIFIERS -------------- // const xxHashMap g_movieModifiers = @@ -2301,12 +2265,3 @@ const xxHashMap g_movieModifiers = { HashStr("sound\\title_loop_GBn.wmv"), { MOVIE_CROP_NARROW } } }; -MovieModifier FindMovieModifier(XXH64_hash_t nameHash) -{ - auto findResult = g_movieModifiers.find(nameHash); - - if (findResult != g_movieModifiers.end()) - return findResult->second; - - return {}; -} diff --git a/MarathonRecomp/patches/aspect_ratio_patches.h b/MarathonRecomp/patches/aspect_ratio_patches.h index 5dd140369..b60691808 100644 --- a/MarathonRecomp/patches/aspect_ratio_patches.h +++ b/MarathonRecomp/patches/aspect_ratio_patches.h @@ -17,6 +17,9 @@ inline float g_aspectRatioMultiplayerOffsetX; inline float g_aspectRatioScale; inline float g_aspectRatioGameplayScale; inline float g_aspectRatioNarrowScale; +inline float g_aspectRatioNarrowMargin; +inline float g_horzCentre; +inline float g_vertCentre; inline float g_radarMapScale; class AspectRatioPatches @@ -99,7 +102,9 @@ enum CsdFlags : uint64_t CSD_MAIN_MENU_PARTS_CAST_0221 = MAKE_BITFLAG64(37), CSD_MAIN_MENU_PARTS_CAST_0222 = MAKE_BITFLAG64(38), CSD_MAIN_MENU_PARTS_CAST_0226 = MAKE_BITFLAG64(39), - CSD_MAIN_MENU_PARTS_CAST_0227 = MAKE_BITFLAG64(40) + CSD_MAIN_MENU_PARTS_CAST_0227 = MAKE_BITFLAG64(40), + + CSD_BUTTON_WINDOW = MAKE_BITFLAG64(41) }; struct CsdUVs @@ -137,21 +142,6 @@ extern const xxHashMap g_csdModifiers; std::optional FindCsdModifier(uint32_t data); -// -------------- TEXT MODIFIERS -------------- // - -struct TextFontPictureModifier -{ - uint16_t X{}; - uint16_t Y{}; - uint16_t Width{}; - uint16_t Height{}; -}; - -extern const xxHashMap g_pftModifierXenon; -extern const xxHashMap g_pftModifierPS3; - -TextFontPictureModifier FindFontPictureModifier(xxHashMap pftModifier, std::string_view& name); - // ------------- MOVIE MODIFIERS -------------- // enum MovieFlags : uint32_t diff --git a/MarathonRecomp/patches/audio_patches.cpp b/MarathonRecomp/patches/audio_patches.cpp index 167211d24..d21fef900 100644 --- a/MarathonRecomp/patches/audio_patches.cpp +++ b/MarathonRecomp/patches/audio_patches.cpp @@ -52,6 +52,8 @@ void AudioPatches::Update(float deltaTime) { pAudioEngine->m_MusicVolume = musicVolume; } + + pAudioEngine->m_EffectsVolume = Config::EffectsVolume * Config::MasterVolume; } // Update function for CRI cues. diff --git a/MarathonRecomp/patches/camera_patches.cpp b/MarathonRecomp/patches/camera_patches.cpp index 653fa721f..3fbd05e67 100644 --- a/MarathonRecomp/patches/camera_patches.cpp +++ b/MarathonRecomp/patches/camera_patches.cpp @@ -35,7 +35,7 @@ void CameraImp_SetFOV(PPCRegister& f1) void SonicCamera_InvertAzDriveK(PPCRegister& az_driveK) { // X axis is inverted by default. - if (Config::HorizontalCamera != ECameraRotationMode::Normal) + if (Config::HorizontalCamera == ECameraRotationMode::Reverse) return; az_driveK.f64 = -az_driveK.f64; @@ -43,8 +43,27 @@ void SonicCamera_InvertAzDriveK(PPCRegister& az_driveK) void SonicCamera_InvertAltDriveK(PPCRegister& alt_driveK) { - if (Config::VerticalCamera != ECameraRotationMode::Reverse) + // Y axis is not inverted by default. + if (Config::VerticalCamera == ECameraRotationMode::Normal) return; alt_driveK.f64 = -alt_driveK.f64; } + +void DemoGMCamera_InvertHorizontal(PPCRegister& horz) +{ + // X axis is inverted by default. + if (Config::HorizontalCamera == ECameraRotationMode::Reverse) + return; + + horz.f64 = -horz.f64; +} + +void DemoGMCamera_InvertVertical(PPCRegister& vert) +{ + // Y axis is inverted by default. + if (Config::VerticalCamera == ECameraRotationMode::Reverse) + return; + + vert.f64 = -vert.f64; +} diff --git a/MarathonRecomp/patches/fps_patches.cpp b/MarathonRecomp/patches/fps_patches.cpp index 4ff0121ce..08ee56644 100644 --- a/MarathonRecomp/patches/fps_patches.cpp +++ b/MarathonRecomp/patches/fps_patches.cpp @@ -125,14 +125,14 @@ void ObjectInputWarp_ExtendMsgSuckPlayer(PPCRegister& phantom, PPCRegister& mess auto pPhantom = (Sonicteam::SoX::Physics::Phantom*)g_memory.Translate(phantom.u32); auto pMessage = (Sonicteam::Message::MsgSuckPlayer*)g_memory.Translate(message.u32); - auto pNewMessage = (MsgSuckPlayerEx*)g_userHeap.Alloc(sizeof(MsgSuckPlayerEx)); - pNewMessage->ID = pMessage->ID; - pNewMessage->Point = pMessage->Point; - pNewMessage->DeltaTime = deltaTime.f64; + auto pMsgSuckPlayerEx = (MsgSuckPlayerEx*)g_userHeap.Alloc(sizeof(MsgSuckPlayerEx)); + pMsgSuckPlayerEx->ID = pMessage->ID; + pMsgSuckPlayerEx->Point = pMessage->Point; + pMsgSuckPlayerEx->DeltaTime = deltaTime.f64; - pPhantom->OnMessageReceived(pNewMessage); + pPhantom->ProcessMessage(pMsgSuckPlayerEx); - g_userHeap.Free(pNewMessage); + g_userHeap.Free(pMsgSuckPlayerEx); } void PlayerObject_ProcessMsgSuckPlayer_FixForce(PPCRegister& message, PPCRegister& force) @@ -259,7 +259,7 @@ bool ObjectVehicleBike_EnemyShot_DisableVehicleCollisionLayer(PPCRegister& r3) { if (auto pGameMode = App::s_pApp->m_pDoc->GetDocMode()) { - auto pWorldHavok = pGameMode->m_pGameImp->GetPhysicsWorld(); + auto pWorldHavok = pGameMode->GetGame()->GetPhysicsWorld(); if (auto pWorld = pWorldHavok->m_pWorld) pWorld->updateCollisionFilterOnWorld(1, 1); diff --git a/MarathonRecomp/patches/input_patches.cpp b/MarathonRecomp/patches/input_patches.cpp new file mode 100644 index 000000000..4dd9bfaa4 --- /dev/null +++ b/MarathonRecomp/patches/input_patches.cpp @@ -0,0 +1,46 @@ +#include +#include + +static constexpr int INPUT_LISTENER_B_DOWN = 0x2000000; + +// Sonicteam::Player::Input::ListenerNormal::Update +PPC_FUNC_IMPL(__imp__sub_82222428); +PPC_FUNC(sub_82222428) +{ + auto pListenerNormal = (Sonicteam::Player::Input::ListenerNormal*)(base + ctx.r3.u32); + auto pInputManager = (Sonicteam::SoX::Input::Manager*)(base + ctx.r4.u32); + + __imp__sub_82222428(ctx, base); + + if (*pListenerNormal->m_pIsListening) + { + auto& rPadState = pInputManager->m_PadState; + + // Add B down support to the normal input listener. + if (rPadState.IsDown(Sonicteam::SoX::Input::KeyState_B)) + pListenerNormal->m_State = pListenerNormal->m_State.get() | INPUT_LISTENER_B_DOWN; + } +} + +void RemapAntigravityEnter(PPCRegister& r11, PPCRegister& r28) +{ + auto state = 0x800; + + if (Config::SlidingAttack == ESlidingAttack::B) + state = INPUT_LISTENER_B_DOWN; + + r11.u64 = (r28.u32 & state) != 0; +} + +void RemapAntigravityExit(PPCRegister& r11, PPCRegister& r30) +{ + if (Config::SlidingAttack == ESlidingAttack::X) + return; + + r11.u64 = (r30.u32 & INPUT_LISTENER_B_DOWN) == 0; +} + +void RemapLightDash(PPCRegister& r3, PPCRegister& r11) +{ + r11.u64 = ((r3.u32 >> (Config::LightDash == ELightDash::X ? 8 : 15)) & 1) != 0; +} diff --git a/MarathonRecomp/patches/misc_patches.cpp b/MarathonRecomp/patches/misc_patches.cpp index 0620ba93b..a8a8e3206 100644 --- a/MarathonRecomp/patches/misc_patches.cpp +++ b/MarathonRecomp/patches/misc_patches.cpp @@ -1,7 +1,9 @@ #include +#include #include #include #include +#include // TODO (Hyper): implement achievements menu. void AchievementManagerUnlockMidAsmHook(PPCRegister& id) @@ -103,18 +105,132 @@ void PedestrianAnimationLOD(PPCRegister& val) val.u32 = 0; } -bool DisableHints() +// Sonicteam::CommonObjectHint::Update +PPC_FUNC_IMPL(__imp__sub_822CE930); +PPC_FUNC(sub_822CE930) { - return !Config::Hints; + auto* pCommonObjectHint = (Sonicteam::CommonObjectHint*)(base + ctx.r3.u32); + auto* pGame = App::s_pApp->m_pDoc->GetDocMode()->GetGame(); + auto& rMessageName = pCommonObjectHint->m_MessageName; + + if (!Config::Hints && pCommonObjectHint->m_Type == Sonicteam::CommonObjectHint::CommonObjectHintType_HintRing) + { + pCommonObjectHint->Destroy(); + return; + } + + if (!Config::ControlTutorial || Config::SlidingAttack != ESlidingAttack::X) + { + // Get global flag for Sonic's Antigravity being unlocked to remove "hint_all03_h26_so". + guest_stack_var msgGetSonicAntigravityFlag(6001); + pGame->m_pMissionCore->ProcessMessage(msgGetSonicAntigravityFlag.get()); + + if (msgGetSonicAntigravityFlag->FlagValue != 0 && strcmp(rMessageName, "hint_twn01_e02_tl") == 0) + { + pCommonObjectHint->Destroy(); + return; + } + } + + if (!Config::ControlTutorial || Config::LightDash != ELightDash::X) + { + // Get global flag for Sonic's Light Dash being unlocked to remove "hint_twn01_e01_tl". + guest_stack_var msgGetSonicLightDashFlag(6000); + pGame->m_pMissionCore->ProcessMessage(msgGetSonicLightDashFlag.get()); + + // Get global flag for Shadow's Light Dash being unlocked to remove "hint_twn01_e44_rg". + guest_stack_var msgGetShadowLightDashFlag(6012); + pGame->m_pMissionCore->ProcessMessage(msgGetShadowLightDashFlag.get()); + + auto isSonicLightDashHint = msgGetSonicLightDashFlag->FlagValue != 0 && strcmp(rMessageName, "hint_twn01_e00_tl") == 0; + auto isShadowLightDashHint = msgGetShadowLightDashFlag->FlagValue != 0 && strcmp(rMessageName, "hint_twn01_e43_rg") == 0; + + if (isSonicLightDashHint || isShadowLightDashHint || + strcmp(rMessageName, "hint_all03_h00_so") == 0 || + strcmp(rMessageName, "hint_all03_h31_so") == 0) + { + pCommonObjectHint->Destroy(); + return; + } + } + + auto isPlayStation = Config::ControllerIcons == EControllerIcons::PlayStation; + + if (Config::ControllerIcons == EControllerIcons::Auto) + isPlayStation = hid::g_inputDeviceController == hid::EInputDevice::PlayStation; + + if (!Config::ControlTutorial || isPlayStation) + { + guest_stack_var stack{}; + + auto pspTextCard = GuestToHostFunction*>(sub_825ECB48, + stack.get(), App::s_pApp->GetGame()->m_pHintTextBook.get(), (const char*)rMessageName); + + if (auto pTextCard = pspTextCard->get()) + { + if (pTextCard->m_pVariables) + { + if (!Config::ControlTutorial) + { + if (strstr(pTextCard->m_pVariables, "picture(button_")) + { + pCommonObjectHint->Destroy(); + return; + } + } + + if (isPlayStation) + { + // L1/R1 and L2/R2 are flipped on PS3, leading + // to the voice lines being wrong for the hints. + // + // We'll provide an alternate control scheme to + // address this later on, but for now these should + // be hidden. + + if (strstr(pTextCard->m_pVariables, "button_lb") || strstr(pTextCard->m_pVariables, "button_rb")) + { + pCommonObjectHint->Destroy(); + return; + } + } + } + } + } + + __imp__sub_822CE930(ctx, base); +} + +PPC_FUNC_IMPL(__imp__sub_8244D288); +PPC_FUNC(sub_8244D288) +{ + auto isShadowEggCerberus = PPC_LOAD_U32(ctx.r3.u32 + 0x1C); + + // Prevent Eggman's voice line playing + // for Shadow's variant of Egg Cerberus. + if (!Config::Hints && isShadowEggCerberus) + return; + + __imp__sub_8244D288(ctx, base); +} + +bool Super3_DisableChangeRequestHint() +{ + return !Config::ControlTutorial; } PPC_FUNC_IMPL(__imp__sub_824A6EA8); PPC_FUNC(sub_824A6EA8) { - if (Config::SkipIntroLogos && ctx.r4.u32 == 1) + if ((App::s_isSkipLogos || Config::SkipIntroLogos) && ctx.r4.u32 == 1) ctx.r4.u32 = 4; __imp__sub_824A6EA8(ctx, base); } +PPC_FUNC(sub_82188460) +{ + ctx.r3.u64 = Config::Subtitles; +} + void NOP() {} diff --git a/MarathonRecomp/patches/pause_patches.cpp b/MarathonRecomp/patches/pause_patches.cpp new file mode 100644 index 000000000..d1a10509c --- /dev/null +++ b/MarathonRecomp/patches/pause_patches.cpp @@ -0,0 +1,111 @@ +#include +#include +#include + +void AddPauseMenuItem +( + Sonicteam::TextBook* in_pTextBook, + stdx::vector* in_pvActionNames, + stdx::vector* in_pvTextCards, + stdx::vector* in_pvEnabledItems, + const char* in_pActionName, + const char* in_pTextName, + bool in_isEnabled +) +{ + guest_stack_var actionName(in_pActionName); + guest_stack_var textName(in_pTextName); + guest_stack_var> spTextCard; + guest_stack_var isEnabled((int)in_isEnabled); + + GuestToHostFunction(sub_8217D608, in_pvActionNames, actionName.get()); + GuestToHostFunction(sub_825ECB48, spTextCard.get(), in_pTextBook, textName->c_str()); + GuestToHostFunction(sub_8239E8F0, in_pvTextCards, spTextCard.get()); + GuestToHostFunction(sub_823879C8, in_pvEnabledItems, isEnabled.get()); +} + +void GameImp_PauseMenu_AddQuitPrefix(PPCRegister& r1, PPCRegister& r30) +{ + auto pGameImp = (Sonicteam::GameImp*)g_memory.Translate(r30.u32); + auto pvActionNames = (stdx::vector*)g_memory.Translate(r1.u32 + 0x70); + auto pvTextCards = (stdx::vector*)g_memory.Translate(r1.u32 + 0x60); + auto pvEnabledItems = (stdx::vector*)g_memory.Translate(r1.u32 + 0x80); + + AddPauseMenuItem(pGameImp->m_pSystemTextBook, pvActionNames, pvTextCards, pvEnabledItems, "options", "msg_options", true); +} + +// Sonicteam::PauseAdapter::MapActionNameToID (speculatory) +PPC_FUNC_IMPL(__imp__sub_8216DA08); +PPC_FUNC(sub_8216DA08) +{ + auto pPauseAdapter = (Sonicteam::PauseAdapter*)(base + ctx.r3.u32); + auto pMsgPauseAdapterText = (Sonicteam::Message::MsgPauseAdapterText*)(base + ctx.r4.u32); + + __imp__sub_8216DA08(ctx, base); + + // Set selected ID to unused slot. + if (pMsgPauseAdapterText->SelectedName == "options") + pPauseAdapter->m_SelectedID = 6; +} + +// Sonicteam::PauseAdapter::DoAction (speculatory) +PPC_FUNC_IMPL(__imp__sub_82170E48); +PPC_FUNC(sub_82170E48) +{ + auto pPauseAdapter = (Sonicteam::PauseAdapter*)(base + ctx.r3.u32); + + if (pPauseAdapter->m_SelectedID == 6) + { + OptionsMenu::s_pBgmCue = pPauseAdapter->GetGame()->GetBgmCue(); + OptionsMenu::Open(true); + return; + } + + __imp__sub_82170E48(ctx, base); +} + +// Sonicteam::PauseTask::Update +PPC_FUNC_IMPL(__imp__sub_82509870); +PPC_FUNC(sub_82509870) +{ + auto pPauseTask = (Sonicteam::PauseTask*)(base + ctx.r3.u32); + + static bool s_isReturningFromOptionsMenu{}; + + switch (pPauseTask->m_State) + { + case Sonicteam::PauseTask::PauseTaskState_Opening: + case Sonicteam::PauseTask::PauseTaskState_Idle: + { + if (!s_isReturningFromOptionsMenu) + break; + + // Set cursor to Options (should always be above the last item). + pPauseTask->m_SelectedIndex = pPauseTask->m_ItemCount - 2; + + s_isReturningFromOptionsMenu = false; + + break; + } + + case Sonicteam::PauseTask::PauseTaskState_Closed: + { + if (OptionsMenu::s_isVisible) + { + if (OptionsMenu::s_state == OptionsMenuState::Closing) + { + pPauseTask->m_State = Sonicteam::PauseTask::PauseTaskState_Opened; + s_isReturningFromOptionsMenu = true; + } + else + { + return; + } + } + + break; + } + } + + __imp__sub_82509870(ctx, base); +} diff --git a/MarathonRecomp/patches/player_patches.cpp b/MarathonRecomp/patches/player_patches.cpp index 0df8a3770..26839e8be 100644 --- a/MarathonRecomp/patches/player_patches.cpp +++ b/MarathonRecomp/patches/player_patches.cpp @@ -4,6 +4,74 @@ #include #include +// Sonicteam::Player::Object::Update +PPC_FUNC_IMPL(__imp__sub_82195500); +PPC_FUNC(sub_82195500) +{ + auto pPlayer = (Sonicteam::Player::Object*)(base + ctx.r3.u32); + auto pInputManager = pPlayer->GetInputManager(); + + if (pPlayer->m_IsPlayer && pInputManager) + { + if (Config::EnableDebugMode) + { + switch (pPlayer->m_SetupModuleIndexPostfix) + { + case 1: + { + // Toggle debug posture on Select press. + if (pPlayer->m_SetupModuleIndexPrefix == 1 && pInputManager->m_PadState.IsPressed(Sonicteam::SoX::Input::KeyState_Select)) + { + pPlayer->m_SetupModuleIndexPostfix = 2; + + LOGN("Debug Mode: Enabled"); + } + + break; + } + + case 2: + { + // Toggle camera volume collision on B press. + if (pInputManager->m_PadState.IsPressed(Sonicteam::SoX::Input::KeyState_B)) + { + auto pGame = App::s_pApp->GetGame(); + auto pZock = pPlayer->GetPlugin("zock"); + auto collisionFilterInfo = pZock->m_spPhantomA->m_pRigidBody->m_collidable.m_broadPhaseHandle.m_collisionFilterInfo == 6 ? 0x383 : 6; + + LOGFN("Camera Volumes: {}", collisionFilterInfo != 6 ? "Enabled" : "Disabled"); + + pZock->m_spPhantomA->m_pRigidBody->m_collidable.m_broadPhaseHandle.m_collisionFilterInfo = collisionFilterInfo; + pGame->GetPhysicsWorld()->m_pWorld->updateCollisionFilterOnWorld(1, 1); + } + + break; + } + } + } + + // Toggle demo camera on right stick press. + if (Config::RestoreDemoCameraMode && pInputManager->m_PadState.IsPressed(Sonicteam::SoX::Input::KeyState_RightStick)) + { + auto pCameraman = static_cast(pPlayer->m_pCameraman.get()); + + if (auto pCameraMode = pCameraman->m_spCameraModeManager->m_spCameraMode.get()) + { + guest_stack_var msgCameramanChangeMode; + msgCameramanChangeMode->ControllerIndex = pInputManager->m_ControllerIndex; + msgCameramanChangeMode->TargetActorID = pPlayer->m_ActorID; + msgCameramanChangeMode->IsDemoCamera = pCameraMode->m_pVftable.ptr != 0x82002004; + + LOGFN("Demo Camera: {}", msgCameramanChangeMode->IsDemoCamera ? "Enabled" : "Disabled"); + + pCameraman->ProcessMessage(msgCameramanChangeMode.get()); + } + } + } + + __imp__sub_82195500(ctx, base); +} + // Sonicteam::Player::State::TailsContext::Update PPC_FUNC_IMPL(__imp__sub_8221A7D8); PPC_FUNC(sub_8221A7D8) @@ -19,12 +87,12 @@ PPC_FUNC(sub_8221A7D8) if (auto pGauge = pPlayer->GetGauge()) { - pGauge->m_Maximum = 100.0f; + pGauge->c_gauge_max = 100.0f; pGauge->m_Value = (100.0f / pTailsContext->m_FlightDuration) * pTailsContext->m_FlightTime; } auto pTailsFlight = pPlayer->m_spStateMachine->GetBase()->GetState(); - auto pGameImp = App::s_pApp->m_pDoc->GetDocMode()->m_pGameImp; + auto pGame = App::s_pApp->GetGame(); auto maturityValue = 1.0f; @@ -34,14 +102,14 @@ PPC_FUNC(sub_8221A7D8) for (int i = 0; i < 4; i++) { - if (pGameImp->m_PlayerData[i].ActorID == pPlayer->m_ActorID.get()) - pGameImp->m_PlayerData[i].MaturityValue = maturityValue; + if (pGame->m_PlayerData[i].ActorID == pPlayer->m_ActorID.get()) + pGame->m_PlayerData[i].MaturityValue = maturityValue; } __imp__sub_8221A7D8(ctx, base); } -// SonicTeam::Player::Score::Score +// Sonicteam::Player::Score::Score PPC_FUNC_IMPL(__imp__sub_821E8C48); PPC_FUNC(sub_821E8C48) { @@ -53,7 +121,7 @@ PPC_FUNC(sub_821E8C48) auto pPlayer = (Sonicteam::Player::Object*)(base + ctx.r4.u32); - if (pPlayer->m_PlayerLua == "player/tails.lua") + if (pPlayer->m_LuaFile == "player/tails.lua") { auto pSonicGauge = GuestToHostFunction(sub_8223F208, g_userHeap.Alloc(sizeof(Sonicteam::Player::SonicGauge))); @@ -71,16 +139,6 @@ PPC_FUNC(sub_821E8C48) __imp__sub_821E8C48(ctx, base); } -bool MidairMachSpeedControl() -{ - return Config::MidairControlForMachSpeed; -} - -bool MidairSnowboardControl() -{ - return Config::MidairControlForSnowboards; -} - // Add missing SetupModuleDebug to table. void PlayerDebugMode_RegisterLuaSetup(PPCRegister& str, PPCRegister& index) { @@ -105,71 +163,22 @@ void PlayerDebugMode_RegisterLuaSetup(PPCRegister& str, PPCRegister& index) } } -bool PlayerDebugMode_RemapDebugExitButton(PPCRegister& r_PadState, PPCRegister& r_out) +bool PlayerDebugMode_RemapDebugExitButton(PPCRegister& r30) { - auto pPadState = (Sonicteam::SoX::Input::PadState*)(g_memory.Translate(r_PadState.u32)); - - return pPadState->IsPressed(Sonicteam::SoX::Input::KeyState_Select); -} + auto pPadState = (Sonicteam::SoX::Input::PadState*)g_memory.Translate(r30.u32); -// Sonicteam::Player::Object::Update -PPC_FUNC_IMPL(__imp__sub_82195500); -PPC_FUNC(sub_82195500) -{ - if (!(Config::EnableDebugMode || Config::RestoreDemoCameraMode)) + if (pPadState->IsPressed(Sonicteam::SoX::Input::KeyState_Select)) { - __imp__sub_82195500(ctx, base); - return; + LOGN("Debug Mode: Disabled"); + return true; } - auto pPlayer = (Sonicteam::Player::Object*)(base + ctx.r3.u32); - auto pZock = pPlayer->GetPlugin("zock"); - auto pDoc = App::s_pApp->m_pDoc; - - if (auto pGameMode = pDoc->GetDocMode()) - { - if (pPlayer->m_IsPlayer) - { - auto playerIndex = pGameMode->m_pGameImp->PlayerActorIDToIndex(pPlayer->m_ActorID); - auto padID = pDoc->m_PlayerControllerID[playerIndex]; - auto& spManager = pDoc->m_vspInputManager[padID]; - auto pGameImp = App::s_pApp->m_pDoc->GetDocMode()->m_pGameImp.get(); - - // Disable collision on B press. - if (pPlayer->m_SetupModuleIndexPostfix == 2 && spManager->m_PadState.IsPressed(Sonicteam::SoX::Input::KeyState_B) && Config::EnableDebugMode) - { - auto value = pZock->m_spPhantomA->m_pRigidBody->m_collidable.m_broadPhaseHandle.m_collisionFilterInfo == 6 ? 0x383 : 6; - pZock->m_spPhantomA->m_pRigidBody->m_collidable.m_broadPhaseHandle.m_collisionFilterInfo = value; - pGameImp->GetPhysicsWorld()->m_pWorld->updateCollisionFilterOnWorld(1,1); - } - - // Switch to Camera <-> DemoGMCamera - if ((pPlayer->m_SetupModuleIndexPostfix == 2 || Config::RestoreDemoCameraMode) && spManager->m_PadState.IsPressed(Sonicteam::SoX::Input::KeyState_DpadUp)) - { - auto pCamera = static_cast(pPlayer->m_pCameraman.get()); - guest_stack_var m_initMessage; - m_initMessage->IsDemoCam = pCamera->m_spCameraModeManager->m_spCameraMode->m_pVftable.ptr.get() != 0x82002004; - m_initMessage->m_TargetActorID = pPlayer->m_ActorID; - m_initMessage->m_PadID = spManager->m_ControllerID; - pCamera->OnMessageReceived(m_initMessage.get()); - } - - // Enter debug posture on Select press. - if (pPlayer->m_SetupModuleIndexPostfix != 2 && - !(pPlayer->m_SetupModuleIndexPrefix == 2 && pPlayer->m_SetupModuleIndexPostfix == 1) && Config::EnableDebugMode && - spManager->m_PadState.IsPressed(Sonicteam::SoX::Input::KeyState_Select)) - { - pPlayer->m_SetupModuleIndexPostfix = 2; - } - } - } - - __imp__sub_82195500(ctx, base); + return false; } -bool ControllableTeleportDash() +bool AntigravityRetainsMomentum() { - return Config::ControllableTeleportDash; + return Config::AntigravityRetainsMomentum; } bool ControllableBoundAttack() @@ -190,9 +199,24 @@ bool ControllableSpinkick() return Config::ControllableSpinkick; } -bool RestoreChaosSpearFlips() +bool ControllableTeleportDash() { - return Config::RestoreChaosSpearFlips; + return Config::ControllableTeleportDash; +} + +bool DisablePushState() +{ + return Config::DisablePushState; +} + +bool MidairControlForMachSpeed() +{ + return Config::MidairControlForMachSpeed; +} + +bool MidairControlForSnowboards() +{ + return Config::MidairControlForSnowboards; } void RestoreChaosBoostJump(PPCRegister& r10, PPCRegister& r11) @@ -204,140 +228,145 @@ void RestoreChaosBoostJump(PPCRegister& r10, PPCRegister& r11) r11.u32 = 2; } -void RestoreChainJumpFlips(PPCRegister& r_ObjectPlayer, PPCRegister& r_Message, PPCRegister& r_ObjectContext, PPCRegister& f1, PPCRegister& f2, PPCRegister& f3) +void RestoreChainJumpFlips(PPCRegister& r31, PPCRegister& r30, PPCRegister& r11, PPCRegister& f1, PPCRegister& f2, PPCRegister& f3) { if (!Config::RestoreChainJumpFlips) return; - struct Message0x11047 + struct Message { - be m_id; - Sonicteam::SoX::Math::Quaternion m_rotation; - Sonicteam::SoX::Math::Vector m_position; - be m_ActorID; + be ID; + Sonicteam::SoX::Math::Quaternion Rotation; + Sonicteam::SoX::Math::Vector Position; + be ActorID; }; - auto pObjectPlayer = static_cast(g_memory.Translate(r_ObjectPlayer.u32)); - auto pMessage = static_cast(g_memory.Translate(r_Message.u32)); - auto pObjectContext = static_cast(g_memory.Translate(r_ObjectContext.u32)); - auto speedHorizontal = f1.f64; - auto speedForward = f2.f64; + auto pPlayer = (Sonicteam::Player::Object*)g_memory.Translate(r31.u32); + auto pMessage = (Message*)g_memory.Translate(r30.u32); + auto pPlayerContext = (Sonicteam::Player::State::ICommonContext*)g_memory.Translate(r11.u32); + auto pActorManager = App::s_pApp->m_pDoc->GetDocMode()->GetGame()->m_spActorManager.get(); - auto point = pObjectPlayer->m_spRootFrame->m_PositionF0; - auto target = pMessage->m_position; + auto origin = pPlayer->m_spRootFrame->m_PositionF0; + auto target = pMessage->Position; - if (pMessage->m_ActorID.get() != -1) + if (pMessage->ActorID != -1) { - auto pFixture = GuestToHostFunction(sub_821609D0,App::s_pApp->m_pDoc->GetDocMode()->m_pGameImp->m_spActorManager.get(), &pMessage->m_ActorID); - auto sMessage = guest_stack_var(); - sMessage->m_Rotation = { 0, 0, 0, 1 }; - sMessage->m_Position = { 0, 0, 0, 1 }; + auto pFixture = GuestToHostFunction(sub_821609D0, pActorManager, &pMessage->ActorID); - if (pFixture->OnMessageReceived(sMessage)) - { - target = sMessage->m_Position; - } + auto msgObjJump123GetNextPoint = guest_stack_var(); + msgObjJump123GetNextPoint->Rotation = { 0, 0, 0, 1 }; + msgObjJump123GetNextPoint->Position = { 0, 0, 0, 1 }; + + if (pFixture->ProcessMessage(msgObjJump123GetNextPoint.get())) + target = msgObjJump123GetNextPoint->Position; } - auto distance = point.DistanceTo(target); - double combinedSpeed = std::sqrt(speedHorizontal * speedHorizontal + speedForward * speedForward); - double timeValue = 1.0; // Default fallback + auto magnitudeHorz = f1.f64; + auto magnitudeForward = f2.f64; + auto distance = origin.DistanceTo(target); + auto magnitude = std::sqrt(magnitudeHorz * magnitudeHorz + magnitudeForward * magnitudeForward); + auto time = 1.0; - if (distance > 0.0 && combinedSpeed > 0.0) - { - timeValue = distance / combinedSpeed; - } + if (distance > 0.0 && magnitude > 0.0) + time = distance / magnitude; - // CommonContext has a slightly different algorithm to process chain flips - if (reinterpret_cast(pObjectContext)->m_pVftable.get() != g_memory.Translate(0x8200A728)) - { - timeValue *= 0.35; - } + // CommonContext has a slightly different algorithm to process chain flips. + if (((Sonicteam::Player::IPlugIn*)pPlayerContext)->m_pVftable.ptr != 0x8200A728) + time *= 0.35; - f3.f64 = timeValue; + f3.f64 = time; } -bool DisablePushState() +bool RestoreChaosSpearFlips() { - return Config::DisablePushState; + return Config::RestoreChaosSpearFlips; +} + +bool UnlimitedAntigravity() +{ + if (Config::SlidingAttack == ESlidingAttack::B) + return true; + + return Config::UnlimitedAntigravity; } -const Sonicteam::Player::State::SonicContext::GemSprite gemConversionTable[] = { - Sonicteam::Player::State::SonicContext::GemSprite_Blue, - Sonicteam::Player::State::SonicContext::GemSprite_Red, - Sonicteam::Player::State::SonicContext::GemSprite_Green, - Sonicteam::Player::State::SonicContext::GemSprite_Purple, - Sonicteam::Player::State::SonicContext::GemSprite_Sky, - Sonicteam::Player::State::SonicContext::GemSprite_White, - Sonicteam::Player::State::SonicContext::GemSprite_Yellow, - Sonicteam::Player::State::SonicContext::GemSprite_Super -}; - -// Check Gauge Drain -// SonicTeam::Player::SonicGauge (IVariable), IVariable::Init(RefSharedPointer) PPC_FUNC_IMPL(__imp__sub_82217FC0); -PPC_FUNC(sub_82217FC0) { +PPC_FUNC(sub_82217FC0) +{ if (!Config::RestoreSonicActionGauge) { __imp__sub_82217FC0(ctx, base); return; } - auto context = (Sonicteam::Player::State::SonicContext*)g_memory.Translate(ctx.r3.u32); - auto gauge = context->m_Gauge.get(); + auto pSonicContext = (Sonicteam::Player::State::SonicContext*)(base + ctx.r3.u32); + auto pSonicGauge = pSonicContext->m_Gauge.get(); using enum Sonicteam::Player::State::SonicContext::Gem; - auto gemId = (Sonicteam::Player::State::SonicContext::Gem)ctx.r4.u32; - switch (gemId) + auto gemIndex = (Sonicteam::Player::State::SonicContext::Gem)ctx.r4.u32; + + switch (gemIndex) { case Gem_Yellow: - if (context->m_ThunderGuard) - break; // Prevent Yellow Gem spam, useless anyway + { + // Prevent Yellow Gem spam. + if (pSonicContext->m_ThunderGuard) + break; + } + case Gem_Blue: case Gem_Green: case Gem_Sky: case Gem_White: case Gem_Super: { - size_t index = gemConversionTable[gemId - 1] - 1; - if (gauge->m_Value >= (&gauge->m_Green)[index].get()) + auto spriteIndex = Sonicteam::Player::State::SonicContext::ms_GemSpriteConversionTable[gemIndex - 1] - 1; + + if (pSonicGauge->m_Value >= (&pSonicGauge->c_gauge_green)[spriteIndex].get()) { ctx.r3.u64 = 1; return; } + break; } + case Gem_Red: case Gem_Purple: - if (context->m_24A == 0) + { + if (pSonicContext->m_Field24A == 0) { ctx.r3.u64 = 1; return; } + break; + } } ctx.r3.u64 = 0; } -// Gauge Drain PPC_FUNC_IMPL(__imp__sub_82218068); -PPC_FUNC(sub_82218068) { +PPC_FUNC(sub_82218068) +{ if (!Config::RestoreSonicActionGauge) { __imp__sub_82217FC0(ctx, base); return; } - auto context = (Sonicteam::Player::State::SonicContext*)g_memory.Translate(ctx.r3.u32); - auto gauge = context->m_Gauge.get(); + auto pSonicContext = (Sonicteam::Player::State::SonicContext*)(base + ctx.r3.u32); + auto pSonicGauge = pSonicContext->m_Gauge.get(); + auto deltaTime = ctx.f1.f64; using enum Sonicteam::Player::State::SonicContext::Gem; - auto gemId = (Sonicteam::Player::State::SonicContext::Gem)ctx.r4.u32; - double delta = ctx.f1.f64; - switch (gemId) + auto gemIndex = (Sonicteam::Player::State::SonicContext::Gem)ctx.r4.u32; + auto spriteIndex = Sonicteam::Player::State::SonicContext::ms_GemSpriteConversionTable[gemIndex - 1] - 1; + + switch (gemIndex) { case Gem_Blue: case Gem_Green: @@ -346,122 +375,146 @@ PPC_FUNC(sub_82218068) { case Gem_White: case Gem_Super: { - uint32_t index = gemConversionTable[gemId - 1] - 1; - gauge->m_Value = gauge->m_Value.get() - (&gauge->m_Green)[index].get(); - gauge->m_GroundedTime = 0.0; + pSonicGauge->m_Value = pSonicGauge->m_Value.get() - (&pSonicGauge->c_gauge_green)[spriteIndex].get(); + pSonicGauge->m_GroundedTime = 0.0; break; } + case Gem_Red: case Gem_Purple: { - uint32_t index = gemConversionTable[gemId - 1] - 1; - gauge->m_Value = gauge->m_Value.get() - (&gauge->m_Green)[index].get() * delta; - gauge->m_GroundedTime = 0.0; - if (gauge->m_Value <= 0) + pSonicGauge->m_Value = pSonicGauge->m_Value.get() - (&pSonicGauge->c_gauge_green)[spriteIndex].get() * deltaTime; + pSonicGauge->m_GroundedTime = 0.0; + + if (pSonicGauge->m_Value <= 0) { - gauge->m_Value = 0.0; - context->m_Shrink = 0; - context->m_SlowTime = 0; - context->m_24A = 1; + pSonicGauge->m_Value = 0.0; + pSonicContext->m_Shrink = 0; + pSonicContext->m_SlowTime = 0; + pSonicContext->m_Field24A = 1; } + break; } } } +// Sonicteam::Player::SonicGauge::IVariable::Init +// This hook redirects the incorrectly named Lua variables to the ones actually used in the scripts. PPC_FUNC_IMPL(__imp__sub_8223F360); -PPC_FUNC(sub_8223F360) { - auto iVariable = ctx.r3.u32; - auto refTypeLuaSystem = ctx.r4.u32; +PPC_FUNC(sub_8223F360) +{ + auto pIVariable = ctx.r3.u32; + auto pLuaSystem = ctx.r4.u32; __imp__sub_8223F360(ctx, base); if (!Config::RestoreSonicActionGauge) return; - auto gauge = (Sonicteam::Player::SonicGauge*)g_memory.Translate(iVariable - 0x20); - auto buffer = g_userHeap.Alloc(); + auto pSonicGauge = (Sonicteam::Player::SonicGauge*)g_memory.Translate(pIVariable - 0x20); + auto pVariableName = g_userHeap.Alloc(); + + *pVariableName = "c_gauge_green"; + + if (pSonicGauge->c_gauge_green == 0.0f) + pSonicGauge->c_gauge_green = GuestToHostFunction(sub_821EA350, pLuaSystem, pVariableName); + + *pVariableName = "c_gauge_red"; - // if (gauge->m_Gem == 0.0) if m_Gem not intitialized by __imp__sub_8223F360 - *buffer = "c_gauge_green"; - if (gauge->m_Green.get() == 0.0) - gauge->m_Green = GuestToHostFunction(sub_821EA350, refTypeLuaSystem, g_memory.MapVirtual(buffer)); + if (pSonicGauge->c_gauge_red == 0.0f) + pSonicGauge->c_gauge_red = GuestToHostFunction(sub_821EA350, pLuaSystem, pVariableName); - *buffer = "c_gauge_red"; - if (gauge->m_Red.get()== 0.0) - gauge->m_Red = GuestToHostFunction(sub_821EA350, refTypeLuaSystem, g_memory.MapVirtual(buffer)); + *pVariableName = "c_gauge_blue"; - *buffer = "c_gauge_blue"; - if (gauge->m_Blue.get() == 0.0) - gauge->m_Blue = GuestToHostFunction(sub_821EA350, refTypeLuaSystem, g_memory.MapVirtual(buffer)); + if (pSonicGauge->c_gauge_blue == 0.0f) + pSonicGauge->c_gauge_blue = GuestToHostFunction(sub_821EA350, pLuaSystem, pVariableName); - *buffer = "c_gauge_white"; - if (gauge->m_White.get() == 0.0) - gauge->m_White = GuestToHostFunction(sub_821EA350, refTypeLuaSystem, g_memory.MapVirtual(buffer)); + *pVariableName = "c_gauge_white"; - *buffer = "c_gauge_sky"; - if (gauge->m_Sky.get() == 0.0) - gauge->m_Sky = GuestToHostFunction(sub_821EA350, refTypeLuaSystem, g_memory.MapVirtual(buffer)); + if (pSonicGauge->c_gauge_white == 0.0f) + pSonicGauge->c_gauge_white = GuestToHostFunction(sub_821EA350, pLuaSystem, pVariableName); - *buffer = "c_gauge_yellow"; - if (gauge->m_Yellow.get() == 0.0) - gauge->m_Yellow = GuestToHostFunction(sub_821EA350, refTypeLuaSystem, g_memory.MapVirtual(buffer)); + *pVariableName = "c_gauge_sky"; - *buffer = "c_gauge_purple"; - if (gauge->m_Purple.get() == 0.0) - gauge->m_Purple = GuestToHostFunction(sub_821EA350, refTypeLuaSystem, g_memory.MapVirtual(buffer)); + if (pSonicGauge->c_gauge_sky == 0.0f) + pSonicGauge->c_gauge_sky = GuestToHostFunction(sub_821EA350, pLuaSystem, pVariableName); - *buffer = "c_gauge_super"; - if (gauge->m_Super.get() == 0.0) - gauge->m_Super = GuestToHostFunction(sub_821EA350, refTypeLuaSystem, g_memory.MapVirtual(buffer)); + *pVariableName = "c_gauge_yellow"; - buffer->~string(); - g_userHeap.Free(buffer); + if (pSonicGauge->c_gauge_yellow == 0.0f) + pSonicGauge->c_gauge_yellow = GuestToHostFunction(sub_821EA350, pLuaSystem, pVariableName); + + *pVariableName = "c_gauge_purple"; + + if (pSonicGauge->c_gauge_purple == 0.0f) + pSonicGauge->c_gauge_purple = GuestToHostFunction(sub_821EA350, pLuaSystem, pVariableName); + + *pVariableName = "c_gauge_super"; + + if (pSonicGauge->c_gauge_super == 0.0f) + pSonicGauge->c_gauge_super = GuestToHostFunction(sub_821EA350, pLuaSystem, pVariableName); + + pVariableName->~string(); + + g_userHeap.Free(pVariableName); } -void SonicGaugeRestorationGaugeGemSpriteResetFix(PPCRegister& r_GameImp) { - Sonicteam::GameImp* pGameImp = (Sonicteam::GameImp*)g_memory.Translate(r_GameImp.u32); +void SonicGauge_FixGemSprite(PPCRegister& r) +{ + auto pGame = (Sonicteam::GameImp*)g_memory.Translate(r.u32); for (int i = 0; i < 4; i++) - pGameImp->m_PlayerData[i].GemIndex = 0; + pGame->m_PlayerData[i].GemIndex = 0; } -void SonicGaugeRestorationGaugeFlagFix(PPCRegister& r_gauge, PPCRegister& r_context) { - if (!Config::RestoreSonicActionGauge || !r_gauge.u32) +void SonicGauge_FixFlags(PPCRegister& r3, PPCRegister& r31) +{ + if (!Config::RestoreSonicActionGauge || !r3.u32) return; - auto pGauge = (Sonicteam::Player::SonicGauge*)g_memory.Translate(r_gauge.u32); - auto pContext = (Sonicteam::Player::State::SonicContext*)g_memory.Translate(r_context.u32); + auto pSonicGauge = (Sonicteam::Player::SonicGauge*)g_memory.Translate(r3.u32); - if ((uint64_t)static_cast(pGauge)->m_pVftable.ptr.get() != 0x8200D4D8) // != SonicGauge + // Ensure this is SonicGauge. + if (((Sonicteam::Player::IPlugIn*)pSonicGauge)->m_pVftable.ptr != 0x8200D4D8) return; - auto weapons = pContext->m_spScore->m_pPlayer->GetPlugin("sonic_weapons"); + auto pSonicContext = (Sonicteam::Player::State::SonicContext*)g_memory.Translate(r31.u32); + auto pSonicWeapons = pSonicContext->m_spScore->m_pPlayer->GetPlugin("sonic_weapons"); - if (pContext->m_Tornado != 0 || pContext->m_AnimationID == 0xCB || pContext->m_AnimationID == 0xCC || pContext->m_AnimationID == 0x46 || pContext->m_AnimationID == 0xCE || weapons->m_GunDrive.m_pElement.get() != nullptr) + static constexpr uint8_t s_groundedAnims[4] = { 0xCB, 0xCC, 0x46, 0xCE }; + + for (auto i = 0; i < 4; i++) + { + if (pSonicContext->m_AnimationID == s_groundedAnims[i]) + pSonicGauge->m_GroundedFlags = 1; + } + + if (pSonicContext->m_Tornado != 0 || pSonicWeapons->m_GunDrive.m_pElement) { - pGauge->m_GroundedFlags = 1; // Lock gauge + pSonicGauge->m_GroundedFlags = 1; } else { using enum Sonicteam::Player::State::SonicContext::Gem; - if ((pContext->m_Buttons.get() & 0x10000) != 0) { - pContext->m_24A = 0; - } - if ((pContext->m_Buttons.get() & 0x20000) != 0 && (pContext->m_CurrentGem == Gem_Red || pContext->m_CurrentGem == Gem_Purple)) + if ((pSonicContext->m_Buttons.get() & 0x10000) != 0) + pSonicContext->m_Field24A = 0; + + if ((pSonicContext->m_Buttons.get() & 0x20000) != 0 && (pSonicContext->m_CurrentGem == Gem_Red || pSonicContext->m_CurrentGem == Gem_Purple)) { - pGauge->m_GroundedFlags = 1; - if (pContext->m_24A) + pSonicGauge->m_GroundedFlags = 1; + + if (pSonicContext->m_Field24A) { - pGauge->m_GroundedFlags = 0; - pContext->m_Shrink = 0; - pContext->m_SlowTime = 0; + pSonicGauge->m_GroundedFlags = 0; + pSonicContext->m_Shrink = 0; + pSonicContext->m_SlowTime = 0; } } - else if ((pContext->m_PostureFlag.get() & Sonicteam::Player::PostureControl::PostureFlag_Ground) != 0 || pContext->m_24A) + else if ((pSonicContext->m_PostureFlags.get() & Sonicteam::Player::PostureControl::PostureFlag_Grounded) != 0 || pSonicContext->m_Field24A) { - pGauge->m_GroundedFlags = 0; + pSonicGauge->m_GroundedFlags = 0; } } } diff --git a/MarathonRecomp/patches/text_patches.cpp b/MarathonRecomp/patches/text_patches.cpp index 38ecaef55..036ac4f4b 100644 --- a/MarathonRecomp/patches/text_patches.cpp +++ b/MarathonRecomp/patches/text_patches.cpp @@ -1,6 +1,9 @@ #include "text_patches.h" +#include #include #include +#include +#include // Load text card. PPC_FUNC_IMPL(__imp__sub_825ECB48); @@ -28,3 +31,54 @@ PPC_FUNC(sub_825ECB48) g_userHeap.Free(pNewMessage); } + +// Load text book. +PPC_FUNC_IMPL(__imp__sub_821735B8); +PPC_FUNC(sub_821735B8) +{ + auto* pTextBookPath = (const char*)(base + ctx.r5.u32); + void* pNewTextBookPath = nullptr; + + if (Config::IsControllerIconsPS3()) + { + static constexpr const char* MSG_HINT_PS3 = "text/msg_hint_ps3.mst"; + + if (strcmp(pTextBookPath, "text/msg_hint_xenon.mst") == 0) + { + pNewTextBookPath = g_userHeap.Alloc(strlen(MSG_HINT_PS3) + 1); + + strcpy((char*)pNewTextBookPath, MSG_HINT_PS3); + + ctx.r5.u32 = g_memory.MapVirtual(pNewTextBookPath); + } + } + + __imp__sub_821735B8(ctx, base); + + if (!pNewTextBookPath) + return; + + g_userHeap.Free(pNewTextBookPath); +} + +// Sonicteam::GameImp::OpenHintWindow (speculatory) +PPC_FUNC_IMPL(__imp__sub_82173838); +PPC_FUNC(sub_82173838) +{ + if (!Config::Hints) + { + auto pMessage = (const char*)(base + ctx.r4.u32); + + // Block specific hints from volumes. + for (auto& pattern : TextPatches::s_hintPatterns) + { + if (strcmpWildcard(pMessage, pattern)) + { + LOGFN_UTILITY("Blocked hint: {}", pMessage); + return; + } + } + } + + __imp__sub_82173838(ctx, base); +} diff --git a/MarathonRecomp/patches/text_patches.h b/MarathonRecomp/patches/text_patches.h index 5bfecfc5c..c53ad69bf 100644 --- a/MarathonRecomp/patches/text_patches.h +++ b/MarathonRecomp/patches/text_patches.h @@ -10,4 +10,108 @@ class TextPatches { HashStr("msg_deviceselect"), "msg_retry" }, // Replace "Select storage device." text with "Retry" for alert windows. { HashStr("msg_gamequitconfirm4"), "msg_backtotitle1" } // Replace "Exit the game." text with "Go back to the Title Screen." }; + + static inline std::vector s_hintPatterns = + { + "hint_all01_a0*", + "hint_all01_e06_*", + "hint_all03_a00_*", + "hint_all03_h3*", + "hint_all04_*", + "hint_all05_a0*", + "hint_all05_a1*", + "hint_all05_a2*", + "hint_all05_a30_*", + "hint_all05_a31_*", + "hint_all05_a32_*", + "hint_all06_*", + "hint_kdv01_a00_*", + "hint_kdv01_a02_sv", // Silver: Man, the staircase is damaged. Now I'll have to use my power. + "hint_kdv01_a04_rg", // Rouge: You can use this vehicle to get across the lake. + "hint_kdv01_a05_sv", // Silver: I can manage this cage with my power. + "hint_kdv01_a06_*", + "hint_kdv01_a07_sv", // Silver: That container might help me move forward. + "hint_kdv01_a08_sv", // Silver: I might be able to levitate to that spring. + "hint_kdv01_h*", + "hint_wvo01_a*", + "hint_tpj01_a01_*", + "hint_tpj01_a03_pr", // Elise: Over there! + "hint_tpj01_a04_*", + "hint_tpj01_a05_*", + "hint_tpj01_a06_*", + "hint_tpj01_a07_sv", // Silver: This hanging ruin might be useful. + "hint_tpj01_a08_sv", // Silver: Looks like I can use this to go up. + "hint_tpj01_a09_sv", // Silver: If I can hit that ball with this... + "hint_tpj01_a10_sv", // Silver: Is this for breaking walls? + "hint_tpj01_a11_*", + "hint_tpj01_a12_*", + "hint_tpj01_a13_*", + "hint_tpj01_e03_pr", // Elise: Sonic! To your left! + "hint_tpj01_e05_pr", // Elise: Sonic! To your right! + "hint_tpj01_e07_rg", // Rouge: It looks like you need to take them down. + "hint_tpj01_e09_pr", // Elise: Sonic! Above you! + "hint_tpj01_e10_sn", // Sonic: There's a route here. + "hint_tpj01_e13_pr", // Elise: Sonic! Look down! + "hint_tpj01_e18_sn", // Sonic: Oh? Is there a back road? + "hint_tpj01_e19_sn", // Sonic: Thank you, Elise! + "hint_tpj01_h*", + "hint_dtd01_a00_*", + "hint_dtd01_a02_sd", // Shadow: It looks like these pillars will lead me to him. + "hint_dtd01_a03_*", + "hint_dtd01_a04_sv", // Silver: I might be able to make a path leading up if I use my power over there. + "hint_dtd01_a05_sd", // Shadow: These big statues look pretty fragile. + "hint_dtd01_h*", + "hint_wap01_a*", + "hint_wap01_h*", + "hint_csc01_a03_sn", // Sonic: This lamp post... Maybe I can swing off of it? + "hint_csc01_a06_sv", // Silver: Blaze! Watch out for things flying out of the tornado. + "hint_csc01_a07_sv", // Silver: This steel bar has a green mark on it. If I use my Psychokinesis here... + "hint_csc01_a08_sv", // Silver: That road doesn't look too solid. + "hint_csc01_a09_sv", // Silver: I can wipe them out if I hit that pipe right. + "hint_csc01_a10_bz", // Blaze: Use your Psychokinesis! You should have no problem with the enemy's bullets! + "hint_csc01_a11_bz", // Blaze: It looks like you can take advantage of this concrete ramp. + "hint_flc01_a06_sv", // Silver: I'll have to get closer and use my power directly! + "hint_flc01_h*", + "hint_rct01_a03_sd", // Shadow: I'm going to have to destroy the train so it doesn't get away! + "hint_rct01_a04_sv", // Silver: There's no other way ahead. I guess I've got to break down the door. + "hint_rct01_a05_sv", // Silver: If I put weights on this scale, I'll be able to move forward. + "hint_rct01_a06_*", + "hint_rct01_a07_*", + "hint_rct01_a08_sn", // Sonic: I'll be able to move faster if I go on top of the train instead of being on the rails. + "hint_rct01_a09_sv", // Silver: I'll blow away these containers with my power! + "hint_rct01_a10_*", + "hint_rct01_a12_sd", // Shadow: I'm going to have to use Homing Missiles so he doesn't get away. + "hint_rct01_h*", + "hint_aqa01_a00_*", + "hint_aqa01_a01_tl", // Tails: If you use the power of this ball, you can get over there. + "hint_aqa01_a02_*", + "hint_aqa01_a03_tl", // Tails: If you attack the switch, the magnet will activate. + "hint_aqa01_a04_tl", // Tails: There are some magnets that repel if you push them twice... + "hint_aqa01_a05_tl", // Tails: Look! There's the magnet switch. Push it, and the path should open! + "hint_aqa01_a07_sn", // Sonic: If I slide, I can squeeze through. + "hint_aqa00_e*", + "hint_end01_e03_*", + "hint_end01_h*", + "hint_bos01_a*", + "hint_bos02_a*", + "hint_bos03_a*", + "hint_bos04_a*", + "hint_bos05_a*", + "hint_bos06_a*", + "hint_bos07_a*", + "hint_bos08_a*", + "hint_bos09_a*", + "hint_bos10_a*", + "hint_bos11_e*", + "hint_bos11_a*", + "hint_twn01_a*", + "hint_twn01_e0?_tl", + "hint_twn01_e05_kn", // Knuckles: Heh, there's a secret room here! Let's hurry to the White Acropolis! + "hint_twn01_e0?_pr", + "hint_twn01_e18_kn", // Knuckles: Ring three bells at once... Sonic, you should be able to do it! + "hint_twn01_e30_bz", // Blaze: You need to short out the electricity in order to stop this laser. We'll need to hit the switches at the same time. + "hint_twn01_e43_rg", // Rouge: The bridge is broken! Shadow, can't you do something? + "hint_twn01_h*", + "hint_tpj01_e20_pr" // Elise: If you jump when the bud is glowing, you may be able to jump higher. + }; }; diff --git a/MarathonRecomp/res/win32/res.rc.template b/MarathonRecomp/res/win32/res.rc.template index e7f0320ab..ac04757ad 100644 --- a/MarathonRecomp/res/win32/res.rc.template +++ b/MarathonRecomp/res/win32/res.rc.template @@ -30,7 +30,7 @@ BEGIN VALUE "FileVersion", MARATHON_RECOMP_VERSION_STR VALUE "ProductVersion", MARATHON_RECOMP_VERSION_STR VALUE "InternalName", "MarathonRecomp" - VALUE "OriginalFilename", "Marathon.exe" + VALUE "OriginalFilename", "marathon.exe" END END BLOCK "VarFileInfo" diff --git a/MarathonRecomp/sdl_listener.h b/MarathonRecomp/sdl_listener.h index f4f6bed6d..2f449ab03 100644 --- a/MarathonRecomp/sdl_listener.h +++ b/MarathonRecomp/sdl_listener.h @@ -17,5 +17,16 @@ class SDLEventListener : public ISDLEventListener GetEventListeners().emplace_back(this); } + ~SDLEventListener() override + { + auto& eventListeners = GetEventListeners(); + + auto it = std::find(eventListeners.begin(), eventListeners.end(), this); + + assert(it != eventListeners.end()); + + eventListeners.erase(it); + } + bool OnSDLEvent(SDL_Event* event) override { return false; } }; diff --git a/MarathonRecomp/ui/achievement_menu.cpp b/MarathonRecomp/ui/achievement_menu.cpp index 72622080b..9e74cacf7 100644 --- a/MarathonRecomp/ui/achievement_menu.cpp +++ b/MarathonRecomp/ui/achievement_menu.cpp @@ -6,7 +6,7 @@ #include #include #include -#include +#include #include #include #include @@ -761,7 +761,7 @@ void AchievementMenu::Open() return std::get<1>(a) > std::get<1>(b); }); - ButtonGuide::Open(Button("Common_Back", FLT_MAX, EButtonIcon::B, EFontQuality::Low)); + ButtonWindow::Open("Button_Back"); ResetSelection(); Game_PlaySound("sys_actstg_pausewinopen"); @@ -779,7 +779,7 @@ void AchievementMenu::Close() hid::SetProhibitedInputs(); } - ButtonGuide::Close(); + ButtonWindow::Close(); Game_PlaySound("sys_actstg_pausewinclose"); Game_PlaySound("sys_actstg_pausecansel"); diff --git a/MarathonRecomp/ui/black_bar.cpp b/MarathonRecomp/ui/black_bar.cpp index 549ad6d18..06c8ae4d4 100644 --- a/MarathonRecomp/ui/black_bar.cpp +++ b/MarathonRecomp/ui/black_bar.cpp @@ -1,30 +1,87 @@ #include "black_bar.h" #include +#include #include +static bool g_isVisible{}; +static bool g_isEdgeFade{}; + void BlackBar::Draw() { - if (g_isVisible) + s_pillarboxWidth = std::max(0.0f, (Video::s_viewportWidth - (Video::s_viewportHeight * WIDE_ASPECT_RATIO)) / 2.0f); + s_letterboxHeight = std::max(0.0f, (Video::s_viewportHeight - (Video::s_viewportWidth / WIDE_ASPECT_RATIO)) / 2.0f); + + if (!g_isVisible) + return; + + auto* drawList = ImGui::GetBackgroundDrawList(); + auto& res = ImGui::GetIO().DisplaySize; + + auto fadeSize = Scale(50, true); + + if (g_aspectRatio > WIDE_ASPECT_RATIO) { - auto drawList = ImGui::GetBackgroundDrawList(); - auto& res = ImGui::GetIO().DisplaySize; - - if (g_aspectRatio > WIDE_ASPECT_RATIO) - { - auto width = (res.x - (res.y * 16.0f / 9.0f)) / 2.0f; - - drawList->AddRectFilled({ 0.0f, 0.0f }, { width, res.y }, IM_COL32_BLACK); - drawList->AddRectFilled({ res.x - width, 0.0f }, res, IM_COL32_BLACK); - } - else if (WIDE_ASPECT_RATIO > g_aspectRatio) - { - auto height = (res.y - (res.x * 9.0f / 16.0f)) / 2.0f; - - drawList->AddRectFilled({ 0.0f, 0.0f }, { res.x, height }, IM_COL32_BLACK); - drawList->AddRectFilled({ 0.0f, res.y - height }, res, IM_COL32_BLACK); - } + ImVec2 leftPillarboxMin = { 0, 0 }; + ImVec2 leftPillarboxMax = { s_pillarboxWidth - s_margin, res.y }; + ImVec2 rightPillarboxMin = { (res.x - s_pillarboxWidth) + s_margin, 0 }; + ImVec2 rightPillarboxMax = { res.x, res.y }; + + if (g_isEdgeFade) + SetHorizontalGradient({ leftPillarboxMax.x - fadeSize, leftPillarboxMin.y }, leftPillarboxMax, IM_COL32_BLACK, IM_COL32_BLACK_TRANS); + + drawList->AddRectFilled(leftPillarboxMin, leftPillarboxMax, IM_COL32_BLACK); + + if (g_isEdgeFade) + SetHorizontalGradient(rightPillarboxMin, { rightPillarboxMin.x + fadeSize, rightPillarboxMax.y }, IM_COL32_BLACK_TRANS, IM_COL32_BLACK); + + drawList->AddRectFilled(rightPillarboxMin, rightPillarboxMax, IM_COL32_BLACK); + } + else if (WIDE_ASPECT_RATIO > g_aspectRatio) + { + ImVec2 topLetterboxMin = { 0, 0 }; + ImVec2 topLetterboxMax = { res.x, s_letterboxHeight - s_margin }; + ImVec2 bottomLetterboxMin = { 0, res.y - s_letterboxHeight + s_margin }; + ImVec2 bottomLetterboxMax = { res.x, res.y }; + + if (g_isEdgeFade) + SetVerticalGradient({ topLetterboxMin.x, topLetterboxMax.y - fadeSize }, topLetterboxMax, IM_COL32_BLACK, IM_COL32_BLACK_TRANS); + + drawList->AddRectFilled(topLetterboxMin, topLetterboxMax, IM_COL32_BLACK); + + if (g_isEdgeFade) + SetVerticalGradient(bottomLetterboxMin, { bottomLetterboxMax.x, bottomLetterboxMin.y + fadeSize }, IM_COL32_BLACK_TRANS, IM_COL32_BLACK); + + drawList->AddRectFilled(bottomLetterboxMin, bottomLetterboxMax, IM_COL32_BLACK); } - if (!App::s_isLoading) - g_isVisible = false; + if (g_isEdgeFade) + ResetGradient(); + + if (App::s_isLoading) + return; + + g_isVisible = false; + g_isEdgeFade = false; + s_margin = 0.0f; +} + +void BlackBar::Show(bool isEdgeFade) +{ + g_isVisible = true; + g_isEdgeFade = isEdgeFade; +} + +void BlackBar::Hide() +{ + g_isVisible = false; +} + +void BlackBar::SetBorderMargin(float margin) +{ + s_margin = margin; +} + +bool BlackBar::IsVisible() +{ + return g_isVisible; } diff --git a/MarathonRecomp/ui/black_bar.h b/MarathonRecomp/ui/black_bar.h index 655424f3b..29f949fc1 100644 --- a/MarathonRecomp/ui/black_bar.h +++ b/MarathonRecomp/ui/black_bar.h @@ -3,7 +3,15 @@ class BlackBar { public: - static inline bool g_isVisible; + static constexpr double ms_MenuBorderMargin = 70.0; + + static inline float s_pillarboxWidth{}; + static inline float s_letterboxHeight{}; + static inline float s_margin{}; static void Draw(); + static void Show(bool isEdgeFade = false); + static void Hide(); + static void SetBorderMargin(float margin); + static bool IsVisible(); }; diff --git a/MarathonRecomp/ui/button_guide.cpp b/MarathonRecomp/ui/button_guide.cpp deleted file mode 100644 index cc1adb1ba..000000000 --- a/MarathonRecomp/ui/button_guide.cpp +++ /dev/null @@ -1,322 +0,0 @@ -#include "button_guide.h" -#include "imgui_utils.h" -#include -#include -#include -#include -#include -#include -#include - -#include -#include - -constexpr float DEFAULT_SIDE_MARGINS = 379; - -ImFont* g_rodinFont; - -std::unique_ptr g_upControllerIcons; -std::unique_ptr g_upKBMIcons; - -float g_sideMargins = DEFAULT_SIDE_MARGINS; - -static std::vector