diff --git a/CMakeLists.txt b/CMakeLists.txt index 16cbaa03d2..3ebfe29dc2 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -411,7 +411,47 @@ if (DUSK_ENABLE_CODE_MODS) setup_symbol_manifest(dusklight) endif () -# Hook reliability: guaranteed patchable entries on the game ABI surface, and no identical-code folding. +# Hook reliability: prevent auto-inlining, guarantee patchable function entries, +# and disable identical-code folding for game functions. +set(DUSK_GAME_ABI_INLINE_OPTIONS) +if (CMAKE_CXX_COMPILER_FRONTEND_VARIANT STREQUAL "GNU") + if (CMAKE_CXX_COMPILER_ID MATCHES "Clang") + list(APPEND DUSK_GAME_ABI_INLINE_OPTIONS + $<$:-finline-hint-functions>) + elseif (CMAKE_CXX_COMPILER_ID STREQUAL "GNU") + list(APPEND DUSK_GAME_ABI_INLINE_OPTIONS + $<$:-flive-patching=inline-clone> + $<$:-fno-inline-functions> + $<$:-fno-inline-small-functions> + $<$:-fno-inline-functions-called-once> + $<$:-fno-early-inlining> + $<$:-fno-ipa-cp> + $<$:-fno-ipa-cp-clone> + $<$:-fno-ipa-sra> + $<$:-fno-partial-inlining>) + endif () +endif () + +if (DUSK_GAME_ABI_INLINE_OPTIONS) + set(_game_abi_files ${GAME_BASE_FILES} ${GAME_DEBUG_FILES}) + list(FILTER _game_abi_files EXCLUDE REGEX "^src/dusk/") + set_property(SOURCE ${_game_abi_files} APPEND PROPERTY + COMPILE_OPTIONS ${DUSK_GAME_ABI_INLINE_OPTIONS}) + + foreach(jsystem_lib IN LISTS JSYSTEM_LIBRARIES) + target_compile_options(${jsystem_lib} PRIVATE ${DUSK_GAME_ABI_INLINE_OPTIONS}) + endforeach() + foreach(_sdk_lib aurora_card aurora_core aurora_dvd aurora_gd aurora_gx aurora_mtx + aurora_os aurora_pad aurora_si aurora_vi) + if (TARGET ${_sdk_lib}) + get_target_property(_sdk_lib_imported ${_sdk_lib} IMPORTED) + if (NOT _sdk_lib_imported) + target_compile_options(${_sdk_lib} PRIVATE ${DUSK_GAME_ABI_INLINE_OPTIONS}) + endif () + endif () + endforeach () +endif () + if (MSVC) if (CMAKE_CXX_COMPILER_ID STREQUAL "Clang") set(DUSK_PATCHABLE_ENTRY_FLAG $<$:/hotpatch>) @@ -421,11 +461,11 @@ if (MSVC) else () target_link_options(dusklight PRIVATE /FUNCTIONPADMIN /OPT:NOICF) endif () -elseif (CMAKE_CXX_COMPILER_ID MATCHES "^(AppleClang|Clang)$") - if (CMAKE_SYSTEM_PROCESSOR STREQUAL "arm64" OR CMAKE_OSX_ARCHITECTURES MATCHES "arm64") +elseif (CMAKE_CXX_COMPILER_ID MATCHES "^(AppleClang|Clang|GNU)$") + if (CMAKE_SYSTEM_PROCESSOR MATCHES "^(arm64|aarch64)$" OR CMAKE_OSX_ARCHITECTURES MATCHES "arm64") set(DUSK_PATCHABLE_ENTRY_FLAG $<$:-fpatchable-function-entry=2,1>) else () - set(DUSK_PATCHABLE_ENTRY_FLAG $<$:-fpatchable-function-entry=10,5>) + set(DUSK_PATCHABLE_ENTRY_FLAG $<$:-fpatchable-function-entry=10,4>) endif () endif () @@ -520,6 +560,7 @@ if (DUSK_ENABLE_CODE_MODS AND CMAKE_SOURCE_DIR STREQUAL CMAKE_CURRENT_SOURCE_DIR add_subdirectory(mods/shadow_mod) add_subdirectory(mods/window_demo) add_subdirectory(mods/flow_demo) + add_subdirectory(mods/basic_cosmetics_mod) endif () if (APPLE) diff --git a/cmake/SymbolManifest.cmake b/cmake/SymbolManifest.cmake index 7ef57f7ced..48935acdf6 100644 --- a/cmake/SymbolManifest.cmake +++ b/cmake/SymbolManifest.cmake @@ -2,7 +2,7 @@ include_guard(GLOBAL) get_filename_component(_SYMBOL_MANIFEST_CMAKE_DIR "${CMAKE_CURRENT_LIST_FILE}" DIRECTORY) -set(_SYMGEN_VERSION "1.3.2") +set(_SYMGEN_VERSION "1.3.3") set(_SYMGEN_RELEASE_BASE_URL "https://github.com/encounter/symgen/releases/download/v${_SYMGEN_VERSION}") set(SYMGEN_PATH "" CACHE FILEPATH "Path to a symgen executable; empty downloads the pinned release") mark_as_advanced(SYMGEN_PATH) @@ -15,32 +15,32 @@ function(symgen_host_asset out_name out_hash) if (CMAKE_HOST_SYSTEM_NAME STREQUAL "Darwin") if (_host_processor MATCHES "^(arm64|aarch64)$") set(_asset "symgen-macos-arm64") - set(_asset_hash "SHA256=0344838d1674df09c17c3eeddcf26eb89c333fdb85dfd78f68adc436070eccbe") + set(_asset_hash "SHA256=e8420df1160242c83bd0e5197efeeb25ceb9fecc69dbc82bdc4927476381e948") elseif (_host_processor MATCHES "^(x86_64|amd64)$") set(_asset "symgen-macos-x86_64") - set(_asset_hash "SHA256=ae0674f4a1e9d0dedfa02d35939ac28cdd229276b331c1f507df5df809cbec7e") + set(_asset_hash "SHA256=e51d13bbf0e982d1519f56850ff3c7b5910ca5a7095dd5a82cd8e59750e2d013") endif () elseif (CMAKE_HOST_SYSTEM_NAME STREQUAL "Linux") if (_host_processor MATCHES "^(aarch64|arm64)$") set(_asset "symgen-linux-aarch64") - set(_asset_hash "SHA256=af766de2bfaeb0a06f6d7bc17bb2510b4a9c40f44a56e49bc4a4b798a6223042") + set(_asset_hash "SHA256=331190dd21ecee12a52e857b7f90a8b3e0a114608173813f7df74a31cf783f70") elseif (_host_processor MATCHES "^(x86_64|amd64)$") set(_asset "symgen-linux-x86_64") - set(_asset_hash "SHA256=ebd62fb9623acc942b6295609e2306f85a73043b0a8a117f2072b761dd08e68f") + set(_asset_hash "SHA256=d727e0ba43242f92a92865af1b69c47aa9d81a0242c4570ce53b90e1ecd15e84") elseif (_host_processor MATCHES "^(i[3-6]86|x86)$") set(_asset "symgen-linux-i686") - set(_asset_hash "SHA256=07780a4513fd29726578efc4ff2d88736b22f407ed821b32a68e35ff1e9af5f4") + set(_asset_hash "SHA256=0c9f94d36b7fa46d15a199c9d0f1a633b73eb7d9c02621a6a76a676b83a135c7") endif () elseif (CMAKE_HOST_WIN32) if (_host_processor MATCHES "^(arm64|aarch64)$") set(_asset "symgen-windows-arm64.exe") - set(_asset_hash "SHA256=5bb22b4a4a9b5ad45646af411bfb09b8321a732ff3a077eb4c9de1feaef27d2b") + set(_asset_hash "SHA256=c699192957e2086ed68912ed39fa77858e1ae894476ab8b557711804cf2aa7cb") elseif (_host_processor MATCHES "^(x86_64|amd64)$") set(_asset "symgen-windows-x86_64.exe") - set(_asset_hash "SHA256=1d1ac087f991a96932d108969e15998becfec643e88f3e7d182ca97ebfc6a46f") + set(_asset_hash "SHA256=6d56a45617c75065ab7a3192d09ca52ff735baf5637b0899f446138d46acc310") elseif (_host_processor MATCHES "^(i[3-6]86|x86)$") set(_asset "symgen-windows-x86.exe") - set(_asset_hash "SHA256=c113f4cd05f813efe2b1878dbfcf44d6302aee3974271736e0036430b0cced78") + set(_asset_hash "SHA256=6cccc3a8d29e7525a4d1ade1dc4d89327b7c3002a604ab1c7decb43eea6fd4ab") endif () endif () diff --git a/docs/modding.md b/docs/modding.md index d9726e3dc4..317ae32c54 100644 --- a/docs/modding.md +++ b/docs/modding.md @@ -474,8 +474,8 @@ per-window RCSS. A non-`MOD_OK` result from `build`/`update` fails your mod, as callback. **Controls:** `pane_add_control` adds an input row described by a `UiControlDesc`: `UI_CONTROL_BUTTON`, -`UI_CONTROL_TOGGLE`, `UI_CONTROL_NUMBER`, `UI_CONTROL_STRING`, or `UI_CONTROL_SELECT`. Values bind with callbacks or -directly to a config var. +`UI_CONTROL_GROUP`, `UI_CONTROL_TOGGLE`, `UI_CONTROL_NUMBER`, `UI_CONTROL_STRING`, `UI_CONTROL_SELECT`, or +`UI_CONTROL_COLOR`. Values bind with callbacks or directly to a config var. ```cpp UiControlDesc control = UI_CONTROL_DESC_INIT; @@ -488,9 +488,56 @@ svc_ui->pane_add_control(mod_ctx, leftPane, &control, nullptr); ``` `UI_BINDING_CONFIG_VAR` wires persistence, change notifications, and the modified indicator automatically. The var -type must match the control: `TOGGLE` = bool, `NUMBER` and `SELECT` = int, `STRING` = string. Float vars are not -bindable; use callbacks and convert. `help_rml` and `SELECT` option lists render in a help pane, so `SELECT` controls -are only available inside window tabs. +type must match the control: `TOGGLE` = bool, `NUMBER` and `SELECT` = int, `STRING` and `COLOR` = string. Float vars +are not bindable; use callbacks and convert. `help_rml` and `SELECT` option lists render in a help pane, so `SELECT` +controls are only available inside window tabs. + +`pane_add_group` adds a category button to a window tab's left pane. Focusing the button clears the paired right pane +and calls the group's build callback with that pane, which is useful for organizing related controls without adding +more tabs. + +**Lists:** `pane_add_list` adds a scrollable virtualized list of items that can be efficiently updated and filtered. +Keys must be unique and remain stable across replacements. + +```cpp +UiListHandle locationList = 0; + +void replace_locations(std::string_view query) { + std::vector items; + for (uint64_t i = 0; i < locations.size(); ++i) { + if (matches(locations[i], query)) { + UiListItem item = UI_LIST_ITEM_INIT; + item.key = i; + item.label = locations[i].c_str(); + items.push_back(item); + } + } + svc_ui->list_set_items(mod_ctx, locationList, items.data(), items.size()); +} + +void set_filter(ModContext*, void*, const UiControlValue* value) { + replace_locations(value->string_value); +} + +bool location_selected(ModContext*, UiListHandle, uint64_t key, void*) { + return selected_locations.contains(key); +} + +UiControlDesc filter = UI_CONTROL_DESC_INIT; +filter.kind = UI_CONTROL_STRING; +filter.label = "Filter"; +filter.get = get_filter; +filter.set = set_filter; +filter.string_set_mode = UI_STRING_SET_ON_CHANGE; /* invoke `set` while typing */ +svc_ui->pane_add_control(mod_ctx, pane, &filter, nullptr); + +UiListDesc list = UI_LIST_DESC_INIT; +/* items may be passed as a part of list creation, or set afterwards */ +list.on_pressed = location_pressed; +list.is_selected = location_selected; +svc_ui->pane_add_list(mod_ctx, pane, &list, &locationList); +replace_locations(""); /* calls `list_set_items` */ +``` **Windows:** `window_push` pushes a tabbed two-pane window onto the document stack and shows it. Each tab's `build` receives the window handle plus fresh left and right pane handles on every activation. The optional per-tab `update` @@ -512,10 +559,36 @@ svc_ui->window_push(mod_ctx, &desc, &window); ``` **Dialogs:** `dialog_push` shows a modal dialog. `variant` picks the style, `icon` optionally overrides the variant's -default icon, and actions become buttons. After an action's `on_pressed` returns, the dialog closes unless the action -sets `keep_open`. A `keep_open` action can close it later (or immediately) with `dialog_close`. Cancel fires -`on_dismiss` if present and always closes. `dialog_set_body`, `dialog_set_icon`, and `dialog_add_action` mutate a live -dialog. +default icon, and actions become buttons. The optional `build` callback allows you to add controls to a pane between +the body and actions. It uses the same text, progress, and control builders as panels. + +```cpp +ModResult build_dialog(ModContext*, UiElementHandle pane, void*, ModError*) { + UiControlDesc input = UI_CONTROL_DESC_INIT; + input.kind = UI_CONTROL_STRING; + input.label = "Name"; + input.get = get_name; + input.set = set_name; + return svc_ui->pane_add_control(mod_ctx, pane, &input, nullptr); +} + +UiDialogAction action = UI_DIALOG_ACTION_INIT; +action.label = "Save"; +action.on_pressed = save; +action.is_disabled = is_save_disabled; + +UiDialogDesc dialog = UI_DIALOG_DESC_INIT; +dialog.title = "New Preset"; +dialog.body_rml = "Choose a name for the preset."; +dialog.actions = &action; +dialog.action_count = 1; +dialog.build = build_dialog; +svc_ui->dialog_push(mod_ctx, &dialog, nullptr); +``` + +After an action's `on_pressed`, the dialog closes unless the action sets `keep_open`. It can then be closed later +(or immediately) with `dialog_close`. Cancel fires `on_dismiss` and always closes. `dialog_set_body` and +`dialog_set_icon` mutate a live dialog. **Toasts:** `push_toast` enqueues a notification. Titles and bodies accept RML. The optional `type` is applied as an RCSS class; `warning` uses the built-in warning appearance, and mods can define their own types. A duration of 0 uses diff --git a/extern/aurora b/extern/aurora index 0f15fb65d1..2c9c95cfed 160000 --- a/extern/aurora +++ b/extern/aurora @@ -1 +1 @@ -Subproject commit 0f15fb65d13e4a7145667934e0291bad09806bfd +Subproject commit 2c9c95cfed9a06610addcb0c00ad5e366e4e8c0d diff --git a/files.cmake b/files.cmake index f53b91d196..5fdac58cb9 100644 --- a/files.cmake +++ b/files.cmake @@ -1532,6 +1532,8 @@ set(DUSK_FILES src/dusk/ui/bool_button.hpp src/dusk/ui/button.cpp src/dusk/ui/button.hpp + src/dusk/ui/color_input.cpp + src/dusk/ui/color_input.hpp src/dusk/ui/component.cpp src/dusk/ui/component.hpp src/dusk/ui/controller_config.cpp @@ -1545,12 +1547,16 @@ set(DUSK_FILES src/dusk/ui/event.hpp src/dusk/ui/graphics_tuner.cpp src/dusk/ui/graphics_tuner.hpp + src/dusk/ui/group_button.cpp + src/dusk/ui/group_button.hpp src/dusk/ui/icon_provider.cpp src/dusk/ui/icon_provider.hpp src/dusk/ui/input.cpp src/dusk/ui/input.hpp src/dusk/ui/logs_window.cpp src/dusk/ui/logs_window.hpp + src/dusk/ui/list.cpp + src/dusk/ui/list.hpp src/dusk/ui/menu_bar.cpp src/dusk/ui/menu_bar.hpp src/dusk/ui/mod_texture_provider.cpp @@ -1562,12 +1568,16 @@ set(DUSK_FILES src/dusk/ui/mods_window.cpp src/dusk/ui/mods_window.hpp src/dusk/ui/nav_types.hpp + src/dusk/ui/nav_group.cpp + src/dusk/ui/nav_group.hpp src/dusk/ui/number_button.cpp src/dusk/ui/number_button.hpp src/dusk/ui/overlay.cpp src/dusk/ui/overlay.hpp src/dusk/ui/pane.cpp src/dusk/ui/pane.hpp + src/dusk/ui/popover.cpp + src/dusk/ui/popover.hpp src/dusk/ui/prelaunch.cpp src/dusk/ui/prelaunch.hpp src/dusk/ui/preset.cpp diff --git a/include/d/actor/d_a_alink.h b/include/d/actor/d_a_alink.h index 8728bc16a8..384891c8d5 100644 --- a/include/d/actor/d_a_alink.h +++ b/include/d/actor/d_a_alink.h @@ -8449,8 +8449,10 @@ struct daAlink_cutHorseParamTbl { /* 0xA */ u8 m_cutType; }; // Size: 0xC +#if !TARGET_PC inline BOOL dComIfGs_isTransformLV(int i_no); inline BOOL dComIfGs_isEventBit(const u16); +#endif static fopAc_ac_c* daAlink_searchPortal(fopAc_ac_c* i_actor, void* i_data); static fopAc_ac_c* daAlink_searchCanoe(fopAc_ac_c* i_actor, void* i_data); diff --git a/include/d/actor/d_a_e_hp.h b/include/d/actor/d_a_e_hp.h index 594c0de01f..86b092f915 100644 --- a/include/d/actor/d_a_e_hp.h +++ b/include/d/actor/d_a_e_hp.h @@ -97,7 +97,7 @@ public: /* 0xDEC */ u8 field_0xdec[0xdf9 - 0xdec]; /* 0xDF9 */ u8 field_0xdf9; #if TARGET_PC - bool mItemCheckOverridden; + bool mItemCheckHandled; #endif }; diff --git a/include/d/actor/d_a_itembase.h b/include/d/actor/d_a_itembase.h index da1f541cd7..374e4b7df2 100644 --- a/include/d/actor/d_a_itembase.h +++ b/include/d/actor/d_a_itembase.h @@ -32,6 +32,12 @@ struct daItemBase_data { class daItemBase_c : public fopAc_ac_c { public: u8 getItemNo(); +#if TARGET_PC + u8 getDisplayItemNo() const { + return mDisplayItemNo != 0xFF ? mDisplayItemNo : m_itemNo; + } + void setDisplayItemNo(u8 itemNo) { mDisplayItemNo = itemNo; } +#endif void hide(); void show(); void changeDraw(); @@ -79,6 +85,9 @@ public: /* 0x928 */ s16 m_get_timer; /* 0x92A */ u8 m_itemNo; /* 0x92B */ u8 field_0x92b; +#if TARGET_PC + u8 mDisplayItemNo = 0xFF; +#endif }; #endif /* D_A_D_A_ITEMBASE_H */ diff --git a/include/d/actor/d_a_midna.h b/include/d/actor/d_a_midna.h index 7793179066..2b07386ca7 100644 --- a/include/d/actor/d_a_midna.h +++ b/include/d/actor/d_a_midna.h @@ -423,7 +423,7 @@ public: static DUSK_GAME_DATA daMidna_texData_s const m_texDataTable[21]; static DUSK_GAME_DATA daMidna_anmData_s const m_anmDataTable[53]; -private: +// private: /* 0x568 */ request_of_phase_process_class mPhase; /* 0x570 */ J3DModel* mpModel; /* 0x574 */ J3DModel* mpShadowModel; diff --git a/include/d/actor/d_a_obj_life_container.h b/include/d/actor/d_a_obj_life_container.h index 1b98c1afe8..d832c63843 100644 --- a/include/d/actor/d_a_obj_life_container.h +++ b/include/d/actor/d_a_obj_life_container.h @@ -92,6 +92,7 @@ private: u8 mOriginalItemNo; bool mItemOverridden; bool mOverrideHover; + bool mGoldenWolfItem; #endif }; diff --git a/include/d/actor/d_a_player.h b/include/d/actor/d_a_player.h index 66139b54cf..ce6158fcf7 100644 --- a/include/d/actor/d_a_player.h +++ b/include/d/actor/d_a_player.h @@ -311,9 +311,11 @@ private: class daMidna_c; class daSpinner_c; class daPy_py_c; +#if !TARGET_PC inline daPy_py_c* dComIfGp_getLinkPlayer(); inline BOOL dComIfGs_isEventBit(const u16); inline u32 dComIfGs_getLastSceneMode(); +#endif class daPy_py_c : public fopAc_ac_c { public: diff --git a/include/d/d_a_itembase_static.h b/include/d/d_a_itembase_static.h index 36a0f55899..38ecb323eb 100644 --- a/include/d/d_a_itembase_static.h +++ b/include/d/d_a_itembase_static.h @@ -1,10 +1,15 @@ #ifndef D_A_D_A_ITEMBASE_STATIC_H #define D_A_D_A_ITEMBASE_STATIC_H +#include "dolphin/types.h" class fopAc_ac_c; int CheckFieldItemCreateHeap(fopAc_ac_c* actor); int CheckItemCreateHeap(fopAc_ac_c* i_this); +#if TARGET_PC +const char* dItem_fieldModelArc(u8 itemNo); +#endif + #endif /* D_A_D_A_ITEMBASE_STATIC_H */ diff --git a/include/d/d_com_inf_game.h b/include/d/d_com_inf_game.h index a598cbcc10..62b8744b51 100644 --- a/include/d/d_com_inf_game.h +++ b/include/d/d_com_inf_game.h @@ -20,11 +20,6 @@ #if defined(DUSK_BUILDING_GAME) #include #include "dusk/settings.h" -#else -#ifndef ZoneScoped -#define ZoneScoped -#define ZoneScopedN(name) -#endif #endif enum dComIfG_ButtonStatus { @@ -1276,6 +1271,938 @@ int dComIfGd_setShadow(u32 param_0, s8 param_1, J3DModel* param_2, cXyz* param_3 f32 param_5, f32 param_6, f32 param_7, cBgS_PolyInfo& param_8, dKy_tevstr_c* param_9, s16 param_10, f32 param_11, TGXTexObj* param_12); +#if TARGET_PC +DUSK_NOINLINE dSv_info_c* dComIfGs_getSaveInfo(); +DUSK_NOINLINE dSv_save_c* dComIfGs_getSaveData(); +DUSK_NOINLINE u16 dComIfGs_getMaxLife(); +DUSK_NOINLINE void dComIfGs_setMaxLife(u8 i_maxLife); +DUSK_NOINLINE u16 dComIfGs_getLife(); +DUSK_NOINLINE void dComIfGs_setLife(u16 i_life); +DUSK_NOINLINE u16 dComIfGs_getRupee(); +DUSK_NOINLINE void dComIfGs_setRupee(u16 i_rupees); +DUSK_NOINLINE u16 dComIfGs_getMaxOil(); +DUSK_NOINLINE void dComIfGs_setMaxOil(u16 i_maxOil); +DUSK_NOINLINE u16 dComIfGs_getOil(); +DUSK_NOINLINE void dComIfGs_setOil(u16 i_oil); +DUSK_NOINLINE u8 dComIfGs_getSelectEquipClothes(); +DUSK_NOINLINE u8 dComIfGs_getSelectEquipSword(); +DUSK_NOINLINE u8 dComIfGs_getSelectEquipShield(); +DUSK_NOINLINE u8 dComIfGs_getCollectSmell(); +DUSK_NOINLINE void dComIfGs_setCollectSmell(u8 smell); +DUSK_NOINLINE u8 dComIfGs_getBButtonItemKey(); +DUSK_NOINLINE void dComIfGs_setBButtonItemKey(u8 i_itemNo); +DUSK_NOINLINE u8 dComIfGs_getWalletSize(); +DUSK_NOINLINE void dComIfGs_setWalletSize(u8 i_size); +DUSK_NOINLINE u8 dComIfGs_getMaxMagic(); +DUSK_NOINLINE void dComIfGs_setMaxMagic(u8 i_maxMagic); +DUSK_NOINLINE u8 dComIfGs_getMagic(); +DUSK_NOINLINE void dComIfGs_setMagic(u8 i_magic); +DUSK_NOINLINE u8 dComIfGs_getTransformStatus(); +DUSK_NOINLINE void dComIfGs_setTransformStatus(u8 i_status); +DUSK_NOINLINE u8 dComIfGs_getSelectItemIndex(int i_no); +DUSK_NOINLINE u16 dComIfGs_getRupeeMax(); +DUSK_NOINLINE void dComIfGs_offGetMagicUseFlag(); +DUSK_NOINLINE s32 dComIfGs_isGetMagicUseFlag(); +DUSK_NOINLINE f32 dComIfGs_getTime(); +DUSK_NOINLINE void dComIfGs_setTime(f32 i_time); +DUSK_NOINLINE u16 dComIfGs_getDate(); +DUSK_NOINLINE void dComIfGs_setDate(u16 i_date); +DUSK_NOINLINE void dComIfGs_onDarkClearLV(int i_no); +DUSK_NOINLINE void dComIfGs_offDarkClearLV(int i_no); +DUSK_NOINLINE BOOL dComIfGs_isDarkClearLV(int i_no); +DUSK_NOINLINE void dComIfGs_onTransformLV(int i_no); +DUSK_NOINLINE void dComIfGs_offTransformLV(int i_no); +DUSK_NOINLINE BOOL dComIfGs_isTransformLV(int i_no); +DUSK_NOINLINE cXyz dComIfGs_getHorseRestartPos(); +DUSK_NOINLINE s16 dComIfGs_getHorseRestartAngleY(); +DUSK_NOINLINE const char* dComIfGs_getHorseRestartStageName(); +DUSK_NOINLINE s8 dComIfGs_getHorseRestartRoomNo(); +DUSK_NOINLINE void dComIfGs_setHorseRestart( + const char* i_stageName, cXyz& i_pos, s16 i_angle, s8 i_roomNo); +DUSK_NOINLINE cXyz dComIfGs_getPlayerFieldLastStayPos(); +DUSK_NOINLINE s16 dComIfGs_getPlayerFieldLastStayAngleY(); +DUSK_NOINLINE char* dComIfGs_getPlayerFieldLastStayName(); +DUSK_NOINLINE u8 dComIfGs_getPlayerFieldLastStayRegionNo(); +DUSK_NOINLINE bool dComIfGs_isPlayerFieldLastStayFieldDataExistFlag(); +DUSK_NOINLINE void dComIfGs_offPlayerFieldLastStayFieldDataExistFlag(); +DUSK_NOINLINE void dComIfGs_onPlayerFieldLastStayFieldDataExistFlag(); +DUSK_NOINLINE BOOL dComIfGs_isRegionBit(int i_region); +DUSK_NOINLINE void dComIfGs_onRegionBit(int i_region); +DUSK_NOINLINE void dComIfGs_setPlayerFieldLastStayInfo( + const char* i_stage, cXyz& i_pos, s16 i_angle, s8 i_point, u8 i_region); +DUSK_NOINLINE cXyz dComIfGs_getLastWarpMarkPlayerPos(); +DUSK_NOINLINE s16 dComIfGs_getLastWarpMarkPlayerAngleY(); +DUSK_NOINLINE const char* dComIfGs_getLastWarpMarkStageName(); +DUSK_NOINLINE u8 dComIfGs_getLastWarpMarkRoomNo(); +DUSK_NOINLINE s8 dComIfGs_getLastWarpAcceptStage(); +DUSK_NOINLINE void dComIfGs_setLastWarpAcceptStage(s8 param_0); +DUSK_NOINLINE void dComIfGs_resetLastWarpAcceptStage(); +DUSK_NOINLINE void dComIfGs_setItem(int i_slotNo, u8 i_itemNo); +DUSK_NOINLINE u8 dComIfGs_getItem(int i_slotNo, bool i_checkCombo); +DUSK_NOINLINE void dComIfGs_setLineUpItem(); +DUSK_NOINLINE u8 dComIfGs_getLineUpItem(int i_slotNo); +DUSK_NOINLINE void dComIfGs_setBottleItemIn(u8 curItem, u8 newItem); +DUSK_NOINLINE void dComIfGs_setEmptyBottleItemIn(u8 i_itemNo); +DUSK_NOINLINE void dComIfGs_setEmptyBottle(); +DUSK_NOINLINE void dComIfGs_setEmptyBottle(u8 i_itemNo); +DUSK_NOINLINE void dComIfGs_setEquipBottleItemIn(u8 i_curItem, u8 i_newItem); +DUSK_NOINLINE void dComIfGs_setEquipBottleItemEmpty(u8 i_curItem); +DUSK_NOINLINE u8 dComIfGs_checkBottle(u8 i_itemNo); +DUSK_NOINLINE u8 dComIfGs_checkInsectBottle(); +DUSK_NOINLINE u8 dComIfGs_checkEmptyBottle(); +DUSK_NOINLINE void dComIfGs_setEmptyBombBagItemIn(u8 i_newBomb, bool i_setNum); +DUSK_NOINLINE void dComIfGs_setEmptyBombBagItemIn(u8 i_newBomb, u8 i_bombNum, bool i_setNum); +DUSK_NOINLINE void dComIfGs_setEmptyBombBag(); +DUSK_NOINLINE void dComIfGs_setEmptyBombBag(u8 i_newBomb, u8 i_bombNum); +DUSK_NOINLINE u8 dComIfGs_checkBombBag(u8 i_itemNo); +DUSK_NOINLINE void dComIfGs_setWarashibeItem(u8 i_itemNo); +DUSK_NOINLINE void dComIfGs_setRodTypeLevelUp(); +DUSK_NOINLINE void dComIfGs_setBaitItem(u8 i_item); +DUSK_NOINLINE void dComIfGs_onItemFirstBit(u8 i_itemNo); +DUSK_NOINLINE void dComIfGs_offItemFirstBit(u8 i_itemNo); +DUSK_NOINLINE int dComIfGs_isItemFirstBit(u8 i_no); +DUSK_NOINLINE u8 dComIfGs_getArrowNum(); +DUSK_NOINLINE void dComIfGs_setArrowNum(u8 i_arrowNum); +DUSK_NOINLINE u8 dComIfGs_getPachinkoNum(); +DUSK_NOINLINE void dComIfGs_setPachinkoNum(u8 i_num); +DUSK_NOINLINE u8 dComIfGs_getPachinkoMax(); +DUSK_NOINLINE void dComIfGs_setBombNum(u8 i_num); +DUSK_NOINLINE void dComIfGs_setBombNum(u8 i_bagIdx, u8 i_bombNum); +DUSK_NOINLINE u8 dComIfGs_getBombNum(u8 i_bagIdx); +DUSK_NOINLINE void dComIfGs_setBottleNum(u8 i_bottleIdx, u8 i_bottleNum); +DUSK_NOINLINE void dComIfGs_addBottleNum(u8 i_bottleIdx, s16 i_num); +DUSK_NOINLINE u8 dComIfGs_getBottleNum(u8 i_bottleIdx); +DUSK_NOINLINE u8 dComIfGs_getArrowMax(); +DUSK_NOINLINE void dComIfGs_setArrowMax(u8 i_arrowMax); +DUSK_NOINLINE void dComIfGs_setBombMax(u8 i_max); +DUSK_NOINLINE void dComIfGs_setBombMax(u8 i_type, u8 i_max); +DUSK_NOINLINE u8 dComIfGs_getBombMax(); +DUSK_NOINLINE u8 dComIfGs_getBombMax(u8 i_bombType); +DUSK_NOINLINE void dComIfGs_setPohSpiritNum(u8 i_num); +DUSK_NOINLINE u8 dComIfGs_getPohSpiritNum(); +DUSK_NOINLINE void dComIfGs_addPohSpiritNum(); +DUSK_NOINLINE BOOL dComIfGs_isCollectClothes(u8 i_clothesNo); +DUSK_NOINLINE void dComIfGs_setCollectClothes(u8 i_clothesNo); +DUSK_NOINLINE void dComIfGs_setCollectSword(u8 i_swordNo); +DUSK_NOINLINE void dComIfGs_setCollectShield(u8 i_shieldNo); +DUSK_NOINLINE BOOL dComIfGs_isCollectClothing(u8 i_clothesNo); +DUSK_NOINLINE void dComIfGs_offCollectClothes(u8 i_clothesNo); +DUSK_NOINLINE BOOL dComIfGs_isCollectSword(u8 i_swordNo); +DUSK_NOINLINE void dComIfGs_offCollectSword(u8 i_swordNo); +DUSK_NOINLINE BOOL dComIfGs_isCollectShield(u8 i_item); +DUSK_NOINLINE void dComIfGs_offCollectShield(u8 i_shieldNo); +DUSK_NOINLINE void dComIfGs_onCollectCrystal(u8 i_item); +DUSK_NOINLINE void dComIfGs_offCollectCrystal(u8 i_item); +DUSK_NOINLINE bool dComIfGs_isCollectCrystal(u8 i_item); +DUSK_NOINLINE void dComIfGs_onCollectMirror(u8 i_item); +DUSK_NOINLINE void dComIfGs_offCollectMirror(u8 i_item); +DUSK_NOINLINE bool dComIfGs_isCollectMirror(u8 i_item); +DUSK_NOINLINE void dComIfGs_setLightDropNum(u8 i_level, u8 i_num); +DUSK_NOINLINE u8 dComIfGs_getLightDropNum(u8 i_nowLevel); +DUSK_NOINLINE void dComIfGs_onLightDropGetFlag(u8 i_nowLevel); +DUSK_NOINLINE void dComIfGs_offLightDropGetFlag(u8 i_level); +DUSK_NOINLINE BOOL dComIfGs_isLightDropGetFlag(u8 i_nowLevel); +DUSK_NOINLINE void dComIfGs_onLetterGetFlag(int i_no); +DUSK_NOINLINE BOOL dComIfGs_isLetterGetFlag(int i_no); +DUSK_NOINLINE void dComIfGs_onLetterReadFlag(int i_no); +DUSK_NOINLINE int dComIfGs_isLetterReadFlag(int i_no); +DUSK_NOINLINE u8 dComIfGs_getGetNumber(int i_no); +DUSK_NOINLINE void dComIfGs_setGetNumber(int i_no, u8 i_value); +DUSK_NOINLINE void dComIfGs_addFishNum(u8 param_0); +DUSK_NOINLINE u16 dComIfGs_getFishNum(u8 param_0); +DUSK_NOINLINE u8 dComIfGs_getFishSize(u8 param_0); +DUSK_NOINLINE void dComIfGs_setFishSize(u8 param_0, u8 param_1); +DUSK_NOINLINE OSTime dComIfGs_getTotalTime(); +DUSK_NOINLINE void dComIfGs_addDeathCount(); +DUSK_NOINLINE u16 dComIfGs_getDeathCount(); +DUSK_NOINLINE TEXT_SPAN dComIfGs_getPlayerName(); +DUSK_NOINLINE void dComIfGs_setPlayerName(const char* i_name); +DUSK_NOINLINE TEXT_SPAN dComIfGs_getHorseName(); +DUSK_NOINLINE void dComIfGs_setHorseName(const char* i_name); +DUSK_NOINLINE u8 dComIfGs_getClearCount(); + +// Ruby inline names are from TWW debug. +DUSK_NOINLINE u8 dComIfGs_getOptRuby(); +DUSK_NOINLINE void dComIfGs_setOptRuby(u8 i_ruby); +DUSK_NOINLINE u8 dComIfGs_getOptAttentionType(); +DUSK_NOINLINE void dComIfGs_setOptAttentionType(u8 i_attentionType); +DUSK_NOINLINE void dComIfGs_setOptCalibrateDist(u16 i_calibrateDist); +DUSK_NOINLINE void dComIfGs_setOptCalValue(s8 i_calValue); +DUSK_NOINLINE u8 dComIfGs_getOptCameraControl(); +DUSK_NOINLINE void dComIfGs_setOptCameraControl(u8 i_cameraControl); +DUSK_NOINLINE u8 dComIfGs_getOptPointer(); +DUSK_NOINLINE void dComIfGs_setOptPointer(u8 i_pointer); +DUSK_NOINLINE u8 dComIfGs_checkOptVibration(); +DUSK_NOINLINE u8 dComIfGs_getOptSound(); +DUSK_NOINLINE void dComIfGs_setOptSound(u8 i_mode); +DUSK_NOINLINE u8 dComIfGs_getOptVibration(); +DUSK_NOINLINE void dComIfGs_setOptVibration(u8 i_status); +DUSK_NOINLINE u8 dComIfGs_getPalLanguage(); +DUSK_NOINLINE BOOL dComIfGs_isSaveTbox(int i_stageNo, int i_no); +DUSK_NOINLINE void dComIfGs_onSaveSwitch(int i_stageNo, int i_no); +DUSK_NOINLINE void dComIfGs_offSaveSwitch(int i_stageNo, int i_no); +DUSK_NOINLINE BOOL dComIfGs_isSaveSwitch(int i_stageNo, int i_no); +DUSK_NOINLINE void dComIfGs_onSaveVisitedRoom(int param_0, int i_roomNo); +DUSK_NOINLINE void dComIfGs_offSaveVisitedRoom(int param_0, int i_roomNo); +DUSK_NOINLINE BOOL dComIfGs_isSaveVisitedRoom(int param_0, int i_roomNo); +DUSK_NOINLINE void* dComIfGs_getPEventBit(); +DUSK_NOINLINE void dComIfGs_onEventBit(const u16 i_flag); +DUSK_NOINLINE void dComIfGs_offEventBit(const u16 i_flag); +DUSK_NOINLINE BOOL dComIfGs_isEventBit(const u16 i_flag); +DUSK_NOINLINE void dComIfGs_setEventReg(u16 reg, u8 value); +DUSK_NOINLINE u8 dComIfGs_getEventReg(u16 reg); +DUSK_NOINLINE int dComIfGs_getHookGameTime(); +DUSK_NOINLINE void dComIfGs_setHookGameTime(u32 i_time); +DUSK_NOINLINE u32 dComIfGs_getBalloonScore(); +DUSK_NOINLINE void dComIfGs_setBalloonScore(u32 i_score); +DUSK_NOINLINE int dComIfGs_getRaceGameTime(); +DUSK_NOINLINE void dComIfGs_setRaceGameTime(int i_time); +DUSK_NOINLINE u8 dComIfGs_getKeyNum(); +DUSK_NOINLINE void dComIfGs_setKeyNum(u8 i_keyNum); +DUSK_NOINLINE void dComIfGs_onDungeonItemMap(); +DUSK_NOINLINE void dComIfGs_offDungeonItemMap(); +DUSK_NOINLINE s32 dComIfGs_isDungeonItemMap(); +DUSK_NOINLINE void dComIfGs_onDungeonItemCompass(); +DUSK_NOINLINE void dComIfGs_offDungeonItemCompass(); +DUSK_NOINLINE s32 dComIfGs_isDungeonItemCompass(); +DUSK_NOINLINE void dComIfGs_onDungeonItemBossKey(); +DUSK_NOINLINE void dComIfGs_offDungeonItemBossKey(); +DUSK_NOINLINE s32 dComIfGs_isDungeonItemBossKey(); +DUSK_NOINLINE void dComIfGs_onStageBossEnemy(); +DUSK_NOINLINE void dComIfGs_offStageBossEnemy(); +DUSK_NOINLINE s32 dComIfGs_isStageBossEnemy(); +DUSK_NOINLINE void dComIfGs_onStageLife(); +DUSK_NOINLINE void dComIfGs_offStageLife(); +DUSK_NOINLINE s32 dComIfGs_isStageLife(); +DUSK_NOINLINE void dComIfGs_onStageBossDemo(); +DUSK_NOINLINE void dComIfGs_offStageBossDemo(); +DUSK_NOINLINE s32 dComIfGs_isStageBossDemo(); +DUSK_NOINLINE void dComIfGs_onDungeonItemWarp(); +DUSK_NOINLINE void dComIfGs_offDungeonItemWarp(); +DUSK_NOINLINE s32 dComIfGs_isDungeonItemWarp(); +DUSK_NOINLINE void dComIfGs_onStageMiddleBoss(); +DUSK_NOINLINE void dComIfGs_offStageMiddleBoss(); +DUSK_NOINLINE BOOL dComIfGs_isStageMiddleBoss(); +DUSK_NOINLINE void dComIfGs_onTbox(int i_no); +DUSK_NOINLINE void dComIfGs_offTbox(int i_no); +DUSK_NOINLINE BOOL dComIfGs_isTbox(int i_no); +DUSK_NOINLINE void dComIfGs_onSaveSwitch(int i_no); +DUSK_NOINLINE void dComIfGs_offSaveSwitch(int i_no); +DUSK_NOINLINE BOOL dComIfGs_isSaveSwitch(int i_no); +DUSK_NOINLINE BOOL dComIfGs_isSaveItem(int i_no); +DUSK_NOINLINE void dComIfGs_onSaveDunSwitch(int i_swNo); +DUSK_NOINLINE void dComIfGs_offSaveDunSwitch(int i_swNo); +DUSK_NOINLINE BOOL dComIfGs_isSaveDunSwitch(int i_no); +DUSK_NOINLINE BOOL dComIfGs_isSaveDunItem(int i_no); +DUSK_NOINLINE void dComIfGs_resetDan(); +DUSK_NOINLINE void dComIfGs_initDan(s8 i_stageNo); +DUSK_NOINLINE void dComIfGs_clearRoomSwitch(int i_zoneNo); +DUSK_NOINLINE void dComIfGs_clearRoomItem(int i_zoneNo); +DUSK_NOINLINE void dComIfGs_onSvZoneSwitch(int i_zoneNo, int i_swBit); +DUSK_NOINLINE void dComIfGs_offSvZoneSwitch(int i_zoneNo, int i_swBit); +DUSK_NOINLINE BOOL dComIfGs_isSvZoneSwitch(int i_zoneNo, int i_swBit); +DUSK_NOINLINE void dComIfGs_onSvOneZoneSwitch(int i_zoneNo, int i_swBit); +DUSK_NOINLINE void dComIfGs_offSvOneZoneSwitch(int i_zoneNo, int i_swBit); +DUSK_NOINLINE BOOL dComIfGs_isSvOneZoneSwitch(int i_zoneNo, int i_swBit); +DUSK_NOINLINE void dComIfGs_onSvZoneItem(int i_zoneNo, int i_swBit); +DUSK_NOINLINE void dComIfGs_offSvZoneItem(int i_zoneNo, int i_swBit); +DUSK_NOINLINE BOOL dComIfGs_isSvZoneItem(int i_zoneNo, int i_swBit); +DUSK_NOINLINE void dComIfGs_onSvOneZoneItem(int i_zoneNo, int i_swBit); +DUSK_NOINLINE void dComIfGs_offSvOneZoneItem(int i_zoneNo, int i_swBit); +DUSK_NOINLINE BOOL dComIfGs_isSvOneZoneItem(int i_zoneNo, int i_swBit); +DUSK_NOINLINE void dComIfGs_removeZone(int i_zoneNo); +DUSK_NOINLINE s8 dComIfGs_getRestartRoomNo(); +DUSK_NOINLINE s16 dComIfGs_getStartPoint(); +DUSK_NOINLINE void dComIfGs_setStartPoint(s16 i_point); +DUSK_NOINLINE s16 dComIfGs_getRestartRoomAngleY(); +DUSK_NOINLINE const cXyz& dComIfGs_getRestartRoomPos(); +DUSK_NOINLINE u32 dComIfGs_getRestartRoomParam(); +DUSK_NOINLINE void dComIfGs_setRestartRoomParam(u32 i_param); +DUSK_NOINLINE f32 dComIfGs_getLastSceneSpeedF(); +DUSK_NOINLINE u32 dComIfGs_getLastSceneMode(); +DUSK_NOINLINE s16 dComIfGs_getLastSceneAngleY(); +DUSK_NOINLINE void dComIfGs_setRestartRoom(const cXyz& i_position, s16 i_angle, s8 i_roomNo); +DUSK_NOINLINE void dComIfGs_onTmpBit(const u16 i_flag); +DUSK_NOINLINE void dComIfGs_offTmpBit(const u16 i_flag); +DUSK_NOINLINE BOOL dComIfGs_isTmpBit(const u16 i_flag); +DUSK_NOINLINE void dComIfGs_setTmpReg(u16 i_reg, u8 i_no); +DUSK_NOINLINE u8 dComIfGs_getTmpReg(const u16 i_reg); +DUSK_NOINLINE dSv_turnRestart_c& dComIfGs_getTurnRestart(); +DUSK_NOINLINE const cXyz& dComIfGs_getTurnRestartPos(); +DUSK_NOINLINE u32 dComIfGs_getTurnRestartParam(); +DUSK_NOINLINE s16 dComIfGs_getTurnRestartAngleY(); +DUSK_NOINLINE s8 dComIfGs_getTurnRestartRoomNo(); +DUSK_NOINLINE void dComIfGs_setTurnRestart( + const cXyz& i_position, s16 i_angle, s8 param_2, u32 i_param); +DUSK_NOINLINE u8 dComIfGs_getDataNum(); +DUSK_NOINLINE void dComIfGs_setDataNum(u8 i_num); +DUSK_NOINLINE u8 dComIfGs_getNewFile(); +DUSK_NOINLINE void dComIfGs_setNewFile(u8 i_fileNo); +DUSK_NOINLINE u8 dComIfGs_getNoFile(); +DUSK_NOINLINE void dComIfGs_setNoFile(u8 i_file); +DUSK_NOINLINE s64 dComIfGs_getSaveStartTime(); +DUSK_NOINLINE void dComIfGs_setSaveStartTime(s64 i_time); +DUSK_NOINLINE s64 dComIfGs_getSaveTotalTime(); +DUSK_NOINLINE void dComIfGs_setSaveTotalTime(s64 i_time); +DUSK_NOINLINE void dComIfGs_init(); +DUSK_NOINLINE void dComIfGs_getSave(int i_stageNo); +DUSK_NOINLINE void dComIfGs_putSave(int i_stageNo); +DUSK_NOINLINE void dComIfGs_initZone(); +DUSK_NOINLINE int dComIfGs_createZone(int roomNo); +DUSK_NOINLINE void dComIfGs_onSwitch(int i_no, int i_roomNo); +DUSK_NOINLINE void dComIfGs_offSwitch(int i_no, int i_roomNo); +DUSK_NOINLINE BOOL dComIfGs_isSwitch(int i_no, int i_roomNo); +DUSK_NOINLINE void dComIfGs_revSwitch(int i_no, int i_roomNo); +DUSK_NOINLINE void dComIfGs_onItem(int i_bitNo, int i_roomNo); +DUSK_NOINLINE bool dComIfGs_isItem(int i_bitNo, int i_roomNo); +DUSK_NOINLINE void dComIfGs_onActor(int i_bitNo, int i_roomNo); +DUSK_NOINLINE void dComIfGs_offActor(int i_no, int i_roomNo); +DUSK_NOINLINE BOOL dComIfGs_isActor(int i_no, int i_roomNo); +DUSK_NOINLINE void dComIfGs_setMemoryToCard(u8* i_saveData, int i_dataNum); +DUSK_NOINLINE void dComIfGs_setCardToMemory(u8* card_ptr, int dataNum); +DUSK_NOINLINE void dComIfGs_setInitDataToCard(u8* i_saveData, int i_dataNum); +DUSK_NOINLINE u8 dComIfGs_getWolfAbility(int i_idx); +DUSK_NOINLINE s8 dComIfGs_Grass_hide_Check(); +DUSK_NOINLINE dStage_startStage_c* dComIfGp_getStartStage(); +DUSK_NOINLINE void dComIfGp_setStartStage(dStage_startStage_c* p_startStage); +DUSK_NOINLINE const char* dComIfGp_getStartStageName(); +DUSK_NOINLINE s16 dComIfGp_getStartStagePoint(); +DUSK_NOINLINE s8 dComIfGp_getStartStageRoomNo(); +DUSK_NOINLINE s8 dComIfGp_getStartStageLayer(); +DUSK_NOINLINE void dComIfGp_setStartStageLayer(s8 layer); +DUSK_NOINLINE s8 dComIfGp_getStartStageDarkArea(); +DUSK_NOINLINE void dComIfGp_setStartStageDarkArea(s8 darkArea); +DUSK_NOINLINE dStage_startStage_c* dComIfGp_getNextStartStage(); +DUSK_NOINLINE const char* dComIfGp_getNextStageName(); +DUSK_NOINLINE s16 dComIfGp_getNextStagePoint(); +DUSK_NOINLINE s16 dComIfGp_getNextStageRoomNo(); +DUSK_NOINLINE s16 dComIfGp_getNextStageLayer(); +DUSK_NOINLINE BOOL dComIfGp_isEnableNextStage(); +DUSK_NOINLINE void dComIfGp_offEnableNextStage(); +DUSK_NOINLINE s8 dComIfGp_getNextStageWipe(); +DUSK_NOINLINE u8 dComIfGp_getNextStageWipeSpeed(); +DUSK_NOINLINE dStage_stageDt_c* dComIfGp_getStage(); +DUSK_NOINLINE roomRead_class* dComIfGp_getStageRoom(); +DUSK_NOINLINE stage_palette_info_class* dComIfGp_getStagePaletteInfo(); +DUSK_NOINLINE stage_pselect_info_class* dComIfGp_getStagePselectInfo(); +DUSK_NOINLINE stage_envr_info_class* dComIfGp_getStageEnvrInfo(); +DUSK_NOINLINE stage_vrboxcol_info_class* dComIfGp_getStageVrboxcolInfo(); +DUSK_NOINLINE stage_plight_info_class* dComIfGp_getStagePlightInfo(); +DUSK_NOINLINE int dComIfGp_getStagePaletteNumInfo(); +DUSK_NOINLINE int dComIfGp_getStagePselectNumInfo(); +DUSK_NOINLINE int dComIfGp_getStageEnvrNumInfo(); +DUSK_NOINLINE int dComIfGp_getStageVrboxcolNumInfo(); +DUSK_NOINLINE int dComIfGp_getStagePlightNumInfo(); +DUSK_NOINLINE stage_stag_info_class* dComIfGp_getStageStagInfo(); +DUSK_NOINLINE stage_scls_info_dummy_class* dComIfGp_getStageSclsInfo(); +DUSK_NOINLINE dStage_Multi_c* dComIfGp_getMulti(); +DUSK_NOINLINE void dComIfGp_setOldMulti(); +DUSK_NOINLINE void dComIfGp_resetOldMulti(); +DUSK_NOINLINE s16 dComIfGp_getStageWorldRollAngleX(); +DUSK_NOINLINE s16 dComIfGp_getStageWorldRollDirAngleY(); +DUSK_NOINLINE int dComIfGp_roomControl_getStayNo(); +DUSK_NOINLINE BOOL dComIfGp_roomControl_getTimePass(); +DUSK_NOINLINE void dComIfGp_roomControl_setTimePass(int isPassing); +DUSK_NOINLINE dKy_tevstr_c* dComIfGp_roomControl_getTevStr(int i_roomNo); +DUSK_NOINLINE void dComIfGp_roomControl_setStatusFlag(int i_roomNo, u8 flag); +DUSK_NOINLINE void dComIfGp_roomControl_onStatusFlag(int i_roomNo, u8 flag); +DUSK_NOINLINE void dComIfGp_roomControl_offStatusFlag(int i_roomNo, u8 flag); +DUSK_NOINLINE u8 dComIfGp_roomControl_checkStatusFlag(int i_roomNo, u8 flag); +DUSK_NOINLINE s32 dComIfGp_roomControl_getZoneNo(int i_roomNo); +DUSK_NOINLINE void dComIfGp_roomControl_setZoneNo(int roomNo, int zoneNo); +DUSK_NOINLINE void dComIfGp_roomControl_init(); +DUSK_NOINLINE void dComIfGp_roomControl_initZone(); +DUSK_NOINLINE dStage_roomDt_c* dComIfGp_roomControl_getStatusRoomDt(int room_no); +DUSK_NOINLINE void dComIfGp_roomControl_setStayNo(int stayNo); +DUSK_NOINLINE BOOL dComIfGp_roomControl_checkRoomDisp(int i_roomNo); +DUSK_NOINLINE int dComIfGp_roomControl_loadRoom(int param_0, u8* param_1, bool param_2); +DUSK_NOINLINE void dComIfGp_roomControl_zoneCountCheck(int i_roomNo); +DUSK_NOINLINE dEvt_control_c* dComIfGp_getEvent(); +DUSK_NOINLINE u16 dComIfGp_event_chkEventFlag(u16 i_flag); +DUSK_NOINLINE void dComIfGp_event_onEventFlag(u16 i_flag); +DUSK_NOINLINE void dComIfGp_event_onHindFlag(u16 i_flag); +DUSK_NOINLINE void dComIfGp_event_offHindFlag(u16 i_flag); +DUSK_NOINLINE u8 dComIfGp_event_getMode(); +DUSK_NOINLINE BOOL dComIfGp_event_runCheck(); +DUSK_NOINLINE u16 dComIfGp_event_checkHind(u16 i_hindFlag); +DUSK_NOINLINE BOOL dComIfGp_event_chkTalkXY(); +DUSK_NOINLINE u8 dComIfGp_event_getPreItemNo(); +DUSK_NOINLINE f32 dComIfGp_event_getCullRate(); +DUSK_NOINLINE void dComIfGp_event_setCullRate(f32 i_rate); +DUSK_NOINLINE int dComIfGp_event_order(u16 i_type, u16 i_prio, u16 i_flags, u16 i_hindFlags, + void* i_requestActor, void* i_targetActor, s16 i_eventID, u8 i_mapToolId); +DUSK_NOINLINE void dComIfGp_event_reset(); +DUSK_NOINLINE int dComIfGp_event_moveApproval(void* i_actor); +DUSK_NOINLINE BOOL dComIfGp_event_compulsory( + void* i_actor, const char* i_eventname, u16 i_hindFlag); +DUSK_NOINLINE void dComIfGp_event_remove(); +DUSK_NOINLINE fopAc_ac_c* dComIfGp_event_getPt1(); +DUSK_NOINLINE fopAc_ac_c* dComIfGp_event_getPt2(); +DUSK_NOINLINE fopAc_ac_c* dComIfGp_event_getTalkPartner(); +DUSK_NOINLINE void dComIfGp_event_setTalkPartner(void* i_actor); +DUSK_NOINLINE fopAc_ac_c* dComIfGp_event_getItemPartner(); +DUSK_NOINLINE void dComIfGp_event_setItemPartner(void* i_actor); +DUSK_NOINLINE void dComIfGp_event_setItemPartnerId(fpc_ProcID i_id); +DUSK_NOINLINE fopAc_ac_c* dComIfGp_event_getDoorPartner(); +DUSK_NOINLINE void dComIfGp_event_setDoorPartner(void* i_partner); +DUSK_NOINLINE u8 dComIfGp_event_getGtItm(); +DUSK_NOINLINE void dComIfGp_event_setGtItm(u8 i_itemNo); +DUSK_NOINLINE dEvent_manager_c& dComIfGp_getEventManager(); +DUSK_NOINLINE dEvent_manager_c* dComIfGp_getPEvtManager(); +DUSK_NOINLINE int dComIfGp_evmng_cameraPlay(); +DUSK_NOINLINE int dComIfGp_evmng_startDemo(int i_mapToolId); +DUSK_NOINLINE void dComIfGp_evmng_create(); +DUSK_NOINLINE void dComIfGp_evmng_remove(); +DUSK_NOINLINE bool dComIfGp_evmng_existence(s16 eventId); +DUSK_NOINLINE s16 dComIfGp_evmng_getEventIdx(const char* eventName, u8 mapToolID); +DUSK_NOINLINE bool dComIfGp_evmng_existence(const char* eventname); +DUSK_NOINLINE BOOL dComIfGp_evmng_isMapToolCamera(u8 mapToolID); +DUSK_NOINLINE BOOL dComIfGp_evmng_startCheck(s16 i_eventId); +DUSK_NOINLINE BOOL dComIfGp_evmng_startCheck(char const* i_eventname); +DUSK_NOINLINE BOOL dComIfGp_evmng_endCheck(s16 i_eventID); +DUSK_NOINLINE BOOL dComIfGp_evmng_endCheck(const char* i_eventname); +DUSK_NOINLINE int dComIfGp_evmng_getMyStaffId( + const char* i_staffname, fopAc_ac_c* i_actor, int i_tagId); +DUSK_NOINLINE int dComIfGp_evmng_getIsAddvance(int i_staffId); +DUSK_NOINLINE int dComIfGp_evmng_getMyActIdx(int i_staffId, DUSK_CONST char* DUSK_CONST* i_actions, + int i_actionNum, BOOL param_3, BOOL param_4); +DUSK_NOINLINE f32* dComIfGp_evmng_getMyFloatP(int i_staffId, DUSK_CONST char* i_dataname); +DUSK_NOINLINE cXyz* dComIfGp_evmng_getMyXyzP(int i_staffId, DUSK_CONST char* i_dataname); +DUSK_NOINLINE int* dComIfGp_evmng_getMyIntegerP(int i_staffId, DUSK_CONST char* i_dataname); +DUSK_NOINLINE char* dComIfGp_evmng_getMyStringP(int i_staffId, DUSK_CONST char* i_dataname); +DUSK_NOINLINE int dComIfGp_evmng_getMySubstanceNum(int i_staffId, DUSK_CONST char* i_dataname); +DUSK_NOINLINE void dComIfGp_evmng_cutEnd(int i_staffId); +DUSK_NOINLINE void dComIfGp_evmng_setGoal(cXyz* i_pos); +DUSK_NOINLINE cXyz* dComIfGp_evmng_getGoal(); +DUSK_NOINLINE BOOL dComIfGp_evmng_ChkPresentEnd(); +DUSK_NOINLINE int dComIfGp_evmng_checkStartDemo(); +DUSK_NOINLINE dAttention_c* dComIfGp_getAttention(); +DUSK_NOINLINE fopAc_ac_c* dComIfGp_att_getZHint(); +DUSK_NOINLINE int dComIfGp_att_ZHintRequest(fopAc_ac_c* param_1, int param_2); +DUSK_NOINLINE fopAc_ac_c* dComIfGp_att_getCatghTarget(); +DUSK_NOINLINE u8 dComIfGp_att_getCatchChgItem(); +DUSK_NOINLINE int dComIfGp_att_CatchRequest(fopAc_ac_c* param_0, u8 param_1, f32 i_horizontalDist, + f32 i_upDist, f32 i_downDist, s16 i_angle, int param_5); +DUSK_NOINLINE fopAc_ac_c* dComIfGp_att_getLookTarget(); +DUSK_NOINLINE void dComIfGp_att_LookRequest(fopAc_ac_c* param_0, f32 i_horizontalDist, f32 i_upDist, + f32 i_downDist, s16 i_angle, int param_5); +DUSK_NOINLINE dVibration_c& dComIfGp_getVibration(); +DUSK_NOINLINE JKRAramArchive* dComIfGp_getFieldMapArchive2(); +DUSK_NOINLINE void dComIfGp_setFieldMapArchive2(JKRArchive* arc); +DUSK_NOINLINE JKRArchive* dComIfGp_getMsgArchive(int idx); +DUSK_NOINLINE void dComIfGp_setMsgArchive(int i, JKRArchive* arc); +DUSK_NOINLINE JKRArchive* dComIfGp_getDemoMsgArchive(); +DUSK_NOINLINE void dComIfGp_setDemoMsgArchive(JKRArchive* arc); +DUSK_NOINLINE JKRArchive* dComIfGp_getMeterButtonArchive(); +DUSK_NOINLINE void dComIfGp_setMeterButtonArchive(JKRArchive* arc); +DUSK_NOINLINE JKRArchive* dComIfGp_getFontArchive(); +DUSK_NOINLINE void dComIfGp_setFontArchive(JKRArchive* arc); +DUSK_NOINLINE JKRArchive* dComIfGp_getRubyArchive(); +DUSK_NOINLINE void dComIfGp_setRubyArchive(JKRArchive* arc); +DUSK_NOINLINE JKRArchive* dComIfGp_getAnmArchive(); +DUSK_NOINLINE void dComIfGp_setAnmArchive(JKRArchive* arc); +DUSK_NOINLINE JKRArchive* dComIfGp_getCollectResArchive(); +DUSK_NOINLINE void dComIfGp_setCollectResArchive(JKRArchive* arc); +DUSK_NOINLINE JKRArchive* dComIfGp_getFmapResArchive(); +DUSK_NOINLINE void dComIfGp_setFmapResArchive(JKRArchive* arc); +DUSK_NOINLINE JKRArchive* dComIfGp_getDmapResArchive(); +DUSK_NOINLINE void dComIfGp_setDmapResArchive(JKRArchive* arc); +DUSK_NOINLINE JKRArchive* dComIfGp_getOptionResArchive(); +DUSK_NOINLINE void dComIfGp_setOptionResArchive(JKRArchive* arc); +DUSK_NOINLINE JKRArchive* dComIfGp_getItemIconArchive(); +DUSK_NOINLINE void dComIfGp_setItemIconArchive(JKRArchive* arc); +DUSK_NOINLINE JKRArchive* dComIfGp_getNameResArchive(); +DUSK_NOINLINE void dComIfGp_setNameResArchive(JKRArchive* arc); +DUSK_NOINLINE void dComIfGp_setErrorResArchive(JKRArchive* arc); +DUSK_NOINLINE JKRArchive* dComIfGp_getAllMapArchive(); +DUSK_NOINLINE void dComIfGp_setAllMapArchive(JKRArchive* arc); +DUSK_NOINLINE JKRArchive* dComIfGp_getMsgCommonArchive(); +DUSK_NOINLINE void dComIfGp_setMsgCommonArchive(JKRArchive* arc); +DUSK_NOINLINE JKRArchive* dComIfGp_getRingResArchive(); +DUSK_NOINLINE void dComIfGp_setRingResArchive(JKRArchive* arc); +DUSK_NOINLINE JKRArchive* dComIfGp_getCardIconResArchive(); +DUSK_NOINLINE void dComIfGp_setCardIconResArchive(JKRArchive* arc); +DUSK_NOINLINE JKRArchive* dComIfGp_getMsgDtArchive(); +DUSK_NOINLINE JKRArchive* dComIfGp_getMsgDtArchive(int idx); +DUSK_NOINLINE void dComIfGp_setMsgDtArchive(int i, JKRArchive* arc); +DUSK_NOINLINE JKRArchive* dComIfGp_getMain2DArchive(); +DUSK_NOINLINE void dComIfGp_setMain2DArchive(JKRArchive* arc); +DUSK_NOINLINE JKRExpHeap* dComIfGp_particle_getResHeap(); +DUSK_NOINLINE void dComIfGp_particle_levelExecute(u32 param_0); +DUSK_NOINLINE void dComIfGp_particle_createCommon(const void* data); +DUSK_NOINLINE void dComIfGp_particle_readScene(u8 particle_no, mDoDvdThd_toMainRam_c** param_1); +DUSK_NOINLINE void dComIfGp_particle_createScene(const void* param_0); +DUSK_NOINLINE void dComIfGp_particle_removeScene(bool param_0); +DUSK_NOINLINE void dComIfGp_particle_cleanup(); +DUSK_NOINLINE void dComIfGp_particle_calc3D(); +DUSK_NOINLINE void dComIfGp_particle_calc2D(); +DUSK_NOINLINE void dComIfGp_particle_calcMenu(); +DUSK_NOINLINE void dComIfGp_particle_draw(JPADrawInfo* i_drawInfo); +DUSK_NOINLINE void dComIfGp_particle_drawFog(JPADrawInfo* i_drawInfo); +DUSK_NOINLINE void dComIfGp_particle_drawP1(JPADrawInfo* i_drawInfo); +DUSK_NOINLINE void dComIfGp_particle_drawProjection(JPADrawInfo* i_drawInfo); +DUSK_NOINLINE void dComIfGp_particle_drawNormalPri0_A(JPADrawInfo* i_drawInfo); +DUSK_NOINLINE void dComIfGp_particle_drawNormalPri0_B(JPADrawInfo* i_drawInfo); +DUSK_NOINLINE void dComIfGp_particle_drawFogPri0_A(JPADrawInfo* i_drawInfo); +DUSK_NOINLINE void dComIfGp_particle_drawFogPri0_B(JPADrawInfo* i_drawInfo); +DUSK_NOINLINE void dComIfGp_particle_drawFogPri1(JPADrawInfo* i_drawInfo); +DUSK_NOINLINE void dComIfGp_particle_drawFogPri2(JPADrawInfo* i_drawInfo); +DUSK_NOINLINE void dComIfGp_particle_drawFogPri3(JPADrawInfo* i_drawInfo); +DUSK_NOINLINE void dComIfGp_particle_drawFogPri4(JPADrawInfo* i_drawInfo); +DUSK_NOINLINE void dComIfGp_particle_drawDarkworld(JPADrawInfo* i_drawInfo); +DUSK_NOINLINE void dComIfGp_particle_drawScreen(JPADrawInfo* i_drawInfo); +DUSK_NOINLINE void dComIfGp_particle_draw2Dgame(JPADrawInfo* i_drawInfo); +DUSK_NOINLINE void dComIfGp_particle_draw2Dfore(JPADrawInfo* i_drawInfo); +DUSK_NOINLINE void dComIfGp_particle_draw2Dback(JPADrawInfo* i_drawInfo); +DUSK_NOINLINE void dComIfGp_particle_draw2DmenuFore(JPADrawInfo* i_drawInfo); +DUSK_NOINLINE void dComIfGp_particle_draw2DmenuBack(JPADrawInfo* i_drawInfo); +DUSK_NOINLINE void dComIfGp_setHitMark(u16 i_hitmark, fopAc_ac_c* param_1, const cXyz* param_2, + const csXyz* param_3, const cXyz* param_4, u32 i_atType); +DUSK_NOINLINE void dComIfGp_particle_setWaterRipple(u32* param_0, cBgS_PolyInfo& param_1, + const cXyz* param_2, f32 param_3, const dKy_tevstr_c* param_4, const cXyz* param_5, s8 param_6); +DUSK_NOINLINE u32 dComIfGp_particle_setPolyColor(u32 param_0, u16 param_1, cBgS_PolyInfo& param_2, + const cXyz* param_3, const dKy_tevstr_c* param_4, const csXyz* param_5, const cXyz* param_6, + int param_7, dPa_levelEcallBack* param_8, s8 param_9, const cXyz* param_10); +DUSK_NOINLINE JPABaseEmitter* dComIfGp_particle_setPolyColor(u16 param_1, cBgS_PolyInfo& param_2, + const cXyz* param_3, const dKy_tevstr_c* param_4, const csXyz* param_5, const cXyz* param_6, + int param_7, dPa_levelEcallBack* param_8, s8 param_9, const cXyz* param_10); +DUSK_NOINLINE void dComIfGp_particle_setSimple(u16 param_0, cXyz* i_pos, u8 param_2, + GXColor& param_3, GXColor& param_4, int param_5, float param_6); +DUSK_NOINLINE u32 dComIfGp_particle_setStopContinue(u32 param_0); +DUSK_NOINLINE u32 dComIfGp_particle_setSimpleFoot(u32 param_0, u32* param_1, cBgS_PolyInfo& param_2, + cXyz const* param_3, dKy_tevstr_c const* param_4, int param_5, csXyz const* param_6, + cXyz const* param_7, dPa_levelEcallBack* param_8, s8 param_9, cXyz const* param_10); +DUSK_NOINLINE u16 dComIfGp_particle_setCommonPoly(u32* param_0, cBgS_PolyInfo* param_1, + const cXyz* param_2, const cXyz* param_3, const dKy_tevstr_c* param_4, u32 param_5, u32 param_6, + const csXyz* param_7, const cXyz* param_8, s8 param_9); +DUSK_NOINLINE void dComIfGp_particle_levelEmitterOnEventMove(u32 param_0); +DUSK_NOINLINE JPABaseEmitter* dComIfGp_particle_getEmitter(u32 param_0); +DUSK_NOINLINE u32 dComIfGp_particle_set(u32 param_0, u16 param_1, const cXyz* i_pos, + const dKy_tevstr_c* param_3, const csXyz* i_rotation, const cXyz* i_scale, u8 i_alpha, + dPa_levelEcallBack* param_7, s8 param_8, const GXColor* param_9, const GXColor* param_10, + const cXyz* param_11); +DUSK_NOINLINE u32 dComIfGp_particle_set(u32 param_0, u16 param_1, const cXyz* i_pos, + const csXyz* i_rotation, const cXyz* i_scale, u8 param_5, dPa_levelEcallBack* param_6, + s8 param_7, const GXColor* param_8, const GXColor* param_9, const cXyz* param_10); +DUSK_NOINLINE JPABaseEmitter* dComIfGp_particle_set(u16 i_resID, const cXyz* i_pos, + const dKy_tevstr_c* param_3, const csXyz* i_rotation, const cXyz* i_scale, u8 i_alpha, + dPa_levelEcallBack* i_callback, s8 param_8, const GXColor* i_prmColor, + const GXColor* i_envColor, const cXyz* i_particleScale); +DUSK_NOINLINE JPABaseEmitter* dComIfGp_particle_set(u16 i_resID, const cXyz* i_pos, + const csXyz* i_rotation, const cXyz* i_scale, u8 i_alpha, dPa_levelEcallBack* i_callback, + s8 param_7, const GXColor* i_prmColor, const GXColor* i_envColor, const cXyz* i_particleScale); +DUSK_NOINLINE u32 dComIfGp_particle_set( + u32 param_0, u16 param_1, const cXyz* i_pos, const dKy_tevstr_c* param_3); +DUSK_NOINLINE JPABaseEmitter* dComIfGp_particle_set( + u16 i_resID, const cXyz* i_pos, const csXyz* i_rotation, const cXyz* i_scale); +DUSK_NOINLINE JPABaseEmitter* dComIfGp_particle_set(u16 i_resID, const cXyz* i_pos, + const dKy_tevstr_c* param_2, const csXyz* i_rotation, const cXyz* i_scale); +DUSK_NOINLINE u32 dComIfGp_particle_set( + u32 param_0, u16 param_1, const cXyz* i_pos, const csXyz* param_3, const cXyz* param_4); +DUSK_NOINLINE u32 dComIfGp_particle_setColor(u32 param_0, u16 param_1, const cXyz* i_pos, + const dKy_tevstr_c* param_3, const GXColor* param_4, const GXColor* param_5, f32 param_6, + u8 param_7, const csXyz* param_8, const cXyz* param_9, dPa_levelEcallBack* param_10, + s8 param_11, const cXyz* param_12); +DUSK_NOINLINE JPABaseEmitter* dComIfGp_particle_setColor(u16 param_0, const cXyz* i_pos, + const dKy_tevstr_c* param_2, const GXColor* param_3, const GXColor* param_4, f32 param_5, + u8 param_6, const csXyz* param_7, const cXyz* param_8, dPa_levelEcallBack* param_9, s8 param_10, + const cXyz* param_11); +DUSK_NOINLINE JPABaseEmitter* dComIfGp_particle_setColor(u16 param_0, const cXyz* i_pos, + const dKy_tevstr_c* param_2, const GXColor* param_3, const GXColor* param_4, f32 param_5, + u8 param_6); +DUSK_NOINLINE u32 dComIfGp_particle_getHeapSize(); +DUSK_NOINLINE u32 dComIfGp_particle_getSceneHeapSize(); +DUSK_NOINLINE int dComIfGp_particle_getEmitterNum(); +DUSK_NOINLINE int dComIfGp_particle_getParticleNum(); +DUSK_NOINLINE dSmplMdl_draw_c* dComIfGp_getSimpleModel(); +DUSK_NOINLINE int dComIfGp_getWindowNum(); +DUSK_NOINLINE void dComIfGp_setWindowNum(int num); +DUSK_NOINLINE s8 dComIfGp_getLayerOld(); +DUSK_NOINLINE s32 dComIfGp_checkStatus(u16 flags); +DUSK_NOINLINE void dComIfGp_setStatus(u16 status); +DUSK_NOINLINE void dComIfGp_onStatus(u16 i_status); +DUSK_NOINLINE dDlst_window_c* dComIfGp_getWindow(int i); +DUSK_NOINLINE void dComIfGp_setWindow(u8 i, f32 param_1, f32 param_2, f32 param_3, f32 param_4, + f32 param_5, f32 param_6, int camID, int mode); +DUSK_NOINLINE camera_process_class* dComIfGp_getCamera(int idx); +DUSK_NOINLINE void dComIfGp_setCamera(int i, camera_class* cam); +DUSK_NOINLINE int dComIfGp_getCameraWinID(int idx); +DUSK_NOINLINE int dComIfGp_getCameraPlayer1ID(int idx); +DUSK_NOINLINE int dComIfGp_getCameraPlayer2ID(int idx); +DUSK_NOINLINE u32 dComIfGp_getCameraAttentionStatus(int i_no); +DUSK_NOINLINE BOOL dComIfGp_checkCameraAttentionStatus(int i, u32 flag); +DUSK_NOINLINE void dComIfGp_onCameraAttentionStatus(int i, u32 flag); +DUSK_NOINLINE void dComIfGp_offCameraAttentionStatus(int i, u32 flag); +DUSK_NOINLINE void dComIfGp_setCameraInfo( + int camIdx, camera_class* p_cam, int param_2, int param_3, int param_4); +DUSK_NOINLINE f32 dComIfGp_getCameraZoomScale(int i_no); +DUSK_NOINLINE void dComIfGp_setCameraZoomScale(int i_no, f32 i_scale); +DUSK_NOINLINE f32 dComIfGp_getCameraZoomForcus(int i_no); +DUSK_NOINLINE void dComIfGp_setCameraZoomForcus(int i_no, f32 i_focus); +DUSK_NOINLINE const char* dComIfGp_getCameraParamFileName(int i); +DUSK_NOINLINE void dComIfGp_setCameraParamFileName(int i, char* name); +DUSK_NOINLINE void dComIfGp_saveCameraPosition( + int i, cXyz* i_pos, cXyz* i_target, f32 i_fovy, s16 i_bank); +DUSK_NOINLINE void dComIfGp_loadCameraPosition( + int i, cXyz* o_pos, cXyz* o_target, f32* o_fovy, s16* o_bank); +DUSK_NOINLINE fopAc_ac_c* dComIfGp_getPlayer(int idx); +DUSK_NOINLINE void dComIfGp_setPlayer(int i, fopAc_ac_c* player); +DUSK_NOINLINE int dComIfGp_getPlayerCameraID(int idx); +DUSK_NOINLINE void dComIfGp_setPlayerInfo(int plyrIdx, fopAc_ac_c* ptr, int camIdx); +DUSK_NOINLINE daPy_py_c* dComIfGp_getLinkPlayer(); +DUSK_NOINLINE daHorse_c* dComIfGp_getHorseActor(); +DUSK_NOINLINE void dComIfGp_setLinkPlayer(fopAc_ac_c* ptr); +DUSK_NOINLINE void dComIfGp_setHorseActor(fopAc_ac_c* i_horse); +DUSK_NOINLINE void dComIfGp_setPlayerPtr(int i, fopAc_ac_c* ptr); +DUSK_NOINLINE dMsgObject_c* dComIfGp_getMsgObjectClass(); +DUSK_NOINLINE void dComIfGp_setMsgObjectClass(dMsgObject_c* obj); +DUSK_NOINLINE f32 dComIfGp_getItemLifeCount(); +DUSK_NOINLINE u8 dComIfGp_getItemLifeCountType(); +DUSK_NOINLINE void dComIfGp_setItemLifeCount(f32 amount, u8 type); +DUSK_NOINLINE void dComIfGp_clearItemLifeCount(); +DUSK_NOINLINE s32 dComIfGp_getItemRupeeCount(); +DUSK_NOINLINE void dComIfGp_setItemRupeeCount(s32 amount); +DUSK_NOINLINE void dComIfGp_clearItemRupeeCount(); +DUSK_NOINLINE s16 dComIfGp_getItemKeyNumCount(); +DUSK_NOINLINE void dComIfGp_setItemKeyNumCount(s16 count); +DUSK_NOINLINE void dComIfGp_clearItemKeyNumCount(); +DUSK_NOINLINE s16 dComIfGp_getItemMaxLifeCount(); +DUSK_NOINLINE void dComIfGp_setItemMaxLifeCount(s16 count); +DUSK_NOINLINE void dComIfGp_clearItemMaxLifeCount(); +DUSK_NOINLINE void dComIfGp_setItemMagicCount(s16 count); +DUSK_NOINLINE void dComIfGp_setItemNowMagic(s16 magic); +DUSK_NOINLINE void dComIfGp_setItemMaxMagicCount(s16 count); +DUSK_NOINLINE s32 dComIfGp_getItemOilCount(); +DUSK_NOINLINE void dComIfGp_setItemOilCount(s32 oil); +DUSK_NOINLINE void dComIfGp_setItemMaxOilCount(s32 oil); +DUSK_NOINLINE void dComIfGp_clearItemOilCount(); +DUSK_NOINLINE s32 dComIfGp_getItemNowOil(); +DUSK_NOINLINE void dComIfGp_setItemNowOil(s32 oil); +DUSK_NOINLINE s32 dComIfGp_getItemMaxOilCount(); +DUSK_NOINLINE void dComIfGp_clearItemMaxOilCount(); +DUSK_NOINLINE int dComIfGp_getOxygen(); +DUSK_NOINLINE void dComIfGp_setOxygen(s32 oxygen); +DUSK_NOINLINE int dComIfGp_getNowOxygen(); +DUSK_NOINLINE void dComIfGp_setNowOxygen(s32 oxygen); +DUSK_NOINLINE s32 dComIfGp_getMaxOxygen(); +DUSK_NOINLINE void dComIfGp_setMaxOxygen(s32 i_oxygen); +DUSK_NOINLINE s32 dComIfGp_getOxygenCount(); +DUSK_NOINLINE void dComIfGp_setOxygenCount(s32 oxygen); +DUSK_NOINLINE void dComIfGp_clearOxygenCount(); +DUSK_NOINLINE void dComIfGp_setMaxOxygenCount(s32 oxygen); +DUSK_NOINLINE s32 dComIfGp_getMaxOxygenCount(); +DUSK_NOINLINE void dComIfGp_clearMaxOxygenCount(); +DUSK_NOINLINE s16 dComIfGp_getItemArrowNumCount(); +DUSK_NOINLINE void dComIfGp_setItemArrowNumCount(s16 count); +DUSK_NOINLINE void dComIfGp_clearItemArrowNumCount(); +DUSK_NOINLINE s16 dComIfGp_getItemPachinkoNumCount(); +DUSK_NOINLINE void dComIfGp_setItemPachinkoNumCount(s16 count); +DUSK_NOINLINE void dComIfGp_clearItemPachinkoNumCount(); +DUSK_NOINLINE s16 dComIfGp_getItemMaxArrowNumCount(); +DUSK_NOINLINE int dComIfGp_getMessageCountNumber(); +DUSK_NOINLINE void dComIfGp_setMessageCountNumber(s32 number); +DUSK_NOINLINE u16 dComIfGp_getItemNowLife(); +DUSK_NOINLINE void dComIfGp_setItemNowLife(u16 life); +DUSK_NOINLINE u8 dComIfGp_getMesgStatus(); +DUSK_NOINLINE u8 dComIfGp_getRStatus(); +DUSK_NOINLINE bool dComIfGp_isRSetFlag(u8 flag); +DUSK_NOINLINE void dComIfGp_setRStatus(u8 status, u8 flag); +DUSK_NOINLINE u8 dComIfGp_getRStatusForce(); +DUSK_NOINLINE u8 dComIfGp_getRSetFlagForce(); +DUSK_NOINLINE void dComIfGp_setRStatusForce(u8 status, u8 flag); +DUSK_NOINLINE u8 dComIfGp_getAStatus(); +DUSK_NOINLINE bool dComIfGp_isASetFlag(u8 flag); +DUSK_NOINLINE void dComIfGp_setAStatus(u8 status, u8 flag); +DUSK_NOINLINE u8 dComIfGp_getAStatusForce(); +DUSK_NOINLINE u8 dComIfGp_getASetFlagForce(); +DUSK_NOINLINE void dComIfGp_setAStatusForce(u8 status, u8 flag); +DUSK_NOINLINE u8 dComIfGp_getNunStatus(); +DUSK_NOINLINE bool dComIfGp_isNunSetFlag(u8 flag); +DUSK_NOINLINE void dComIfGp_setNunStatus(u8 status, u8 param_1, u8 flag); +DUSK_NOINLINE u8 dComIfGp_getBottleStatus(); +DUSK_NOINLINE bool dComIfGp_isBottleSetFlag(u8 flag); +DUSK_NOINLINE void dComIfGp_setBottleStatus(u8 param_0, u8 param_1); +DUSK_NOINLINE u8 dComIfGp_getBottleStatusForce(); +DUSK_NOINLINE u8 dComIfGp_getBottleSetFlagForce(); +DUSK_NOINLINE void dComIfGp_setBottleStatusForce(u8 param_0, u8 param_1); +DUSK_NOINLINE u8 dComIfGp_getRemoConStatus(); +DUSK_NOINLINE bool dComIfGp_isRemoConSetFlag(u8 flag); +DUSK_NOINLINE void dComIfGp_setRemoConStatus(u8 status, u8 param_1, u8 flag); +DUSK_NOINLINE u8 dComIfGp_getDoStatus(); +DUSK_NOINLINE bool dComIfGp_isDoSetFlag(u8 flag); +DUSK_NOINLINE void dComIfGp_setDoStatus(u8 status, u8 flag); +DUSK_NOINLINE u8 dComIfGp_getDoStatusForce(); +DUSK_NOINLINE u8 dComIfGp_getDoSetFlagForce(); +DUSK_NOINLINE void dComIfGp_setDoStatusForce(u8 status, u8 flag); +DUSK_NOINLINE u8 dComIfGp_get3DStatus(); +DUSK_NOINLINE u8 dComIfGp_get3DDirection(); +DUSK_NOINLINE bool dComIfGp_is3DSetFlag(u8 flag); +DUSK_NOINLINE void dComIfGp_set3DStatus(u8 status, u8 direction, u8 flag); +DUSK_NOINLINE u8 dComIfGp_get3DStatusForce(); +DUSK_NOINLINE u8 dComIfGp_get3DDirectionForce(); +DUSK_NOINLINE u8 dComIfGp_get3DSetFlagForce(); +DUSK_NOINLINE void dComIfGp_set3DStatusForce(u8 status, u8 direction, u8 flag); +DUSK_NOINLINE u8 dComIfGp_getCStickStatus(); +DUSK_NOINLINE u8 dComIfGp_getCStickDirection(); +DUSK_NOINLINE bool dComIfGp_isCStickSetFlag(u8 flag); +DUSK_NOINLINE void dComIfGp_setCStickStatus(u8 status, u8 param_1, u8 flag); +DUSK_NOINLINE u8 dComIfGp_getCStickStatusForce(); +DUSK_NOINLINE u8 dComIfGp_getCStickDirectionForce(); +DUSK_NOINLINE u8 dComIfGp_getCStickSetFlagForce(); +DUSK_NOINLINE void dComIfGp_setCStickStatusForce(u8 status, u8 param_1, u8 flag); +DUSK_NOINLINE u8 dComIfGp_getSButtonStatus(); +DUSK_NOINLINE bool dComIfGp_isSButtonSetFlag(u8 flag); +DUSK_NOINLINE void dComIfGp_setSButtonStatus(u8 status, u8 flag); +DUSK_NOINLINE u8 dComIfGp_getSButtonStatusForce(); +DUSK_NOINLINE u8 dComIfGp_getSButtonSetFlagForce(); +DUSK_NOINLINE void dComIfGp_setSButtonStatusForce(u8 status, u8 flag); +DUSK_NOINLINE u8 dComIfGp_getZStatus(); +DUSK_NOINLINE bool dComIfGp_isZSetFlag(u8 flag); +DUSK_NOINLINE void dComIfGp_setZStatus(u8 status, u8 flag); +DUSK_NOINLINE u8 dComIfGp_getZStatusForce(); +DUSK_NOINLINE u8 dComIfGp_getZSetFlagForce(); +DUSK_NOINLINE void dComIfGp_setZStatusForce(u8 status, u8 flag); +DUSK_NOINLINE u8 dComIfGp_getXStatus(); +DUSK_NOINLINE bool dComIfGp_isXSetFlag(u8 flag); +DUSK_NOINLINE void dComIfGp_setXStatus(u8 status, u8 flag); +DUSK_NOINLINE u8 dComIfGp_getXStatusForce(); +DUSK_NOINLINE u8 dComIfGp_getXSetFlagForce(); +DUSK_NOINLINE void dComIfGp_setXStatusForce(u8 status, u8 flag); +DUSK_NOINLINE u8 dComIfGp_getYStatus(); +DUSK_NOINLINE bool dComIfGp_isYSetFlag(u8 flag); +DUSK_NOINLINE void dComIfGp_setYStatus(u8 status, u8 flag); +DUSK_NOINLINE u8 dComIfGp_getYStatusForce(); +DUSK_NOINLINE u8 dComIfGp_getYSetFlagForce(); +DUSK_NOINLINE void dComIfGp_setYStatusForce(u8 status, u8 flag); +DUSK_NOINLINE u8 dComIfGp_getNunZStatus(); +DUSK_NOINLINE bool dComIfGp_isNunZSetFlag(u8 flag); +DUSK_NOINLINE void dComIfGp_setNunZStatus(u8 param_0, u8 param_1); +DUSK_NOINLINE u8 dComIfGp_getNunCStatus(); +DUSK_NOINLINE bool dComIfGp_isNunCSetFlag(u8 flag); +DUSK_NOINLINE void dComIfGp_setNunCStatus(u8 param_0, u8 param_1); +DUSK_NOINLINE void dComIfGp_setSelectEquipClothes(u8 i_clothNo); +DUSK_NOINLINE void dComIfGp_setSelectEquipSword(u8 i_swordNo); +DUSK_NOINLINE void dComIfGp_setSelectEquipShield(u8 i_shieldNo); +DUSK_NOINLINE u8 dComIfGp_getMesgAnimeAttrInfo(); +DUSK_NOINLINE void dComIfGp_setMesgAnimeAttrInfo(u8 param_1); +DUSK_NOINLINE void dComIfGp_clearMesgAnimeAttrInfo(); +DUSK_NOINLINE u8 dComIfGp_getMesgFaceAnimeAttrInfo(); +DUSK_NOINLINE void dComIfGp_setMesgFaceAnimeAttrInfo(u8 id); +DUSK_NOINLINE void dComIfGp_clearMesgFaceAnimeAttrInfo(); +DUSK_NOINLINE void dComIfGp_clearMesgAnimeTagInfo(); +DUSK_NOINLINE void dComIfGp_setItem(u8 slot, u8 i_no); +DUSK_NOINLINE u8 dComIfGp_getAdvanceDirection(); +DUSK_NOINLINE void dComIfGp_setAdvanceDirection(u8 i_dir); +DUSK_NOINLINE u8 dComIfGp_checkMesgCancelButton(); +DUSK_NOINLINE void dComIfGp_setMesgCancelButton(u8 button); +DUSK_NOINLINE u8 dComIfGp_getGameoverStatus(); +DUSK_NOINLINE void dComIfGp_setGameoverStatus(u8 i_status); +DUSK_NOINLINE u8 dComIfGp_isHeapLockFlag(); +DUSK_NOINLINE u8 dComIfGp_getSubHeapLockFlag(int idx); +DUSK_NOINLINE void dComIfGp_setSubHeapLockFlag(int idx, u8 status); +DUSK_NOINLINE u8 dComIfGp_getNeedLightDropNum(); +DUSK_NOINLINE void dComIfGp_setNeedLightDropNum(u8 i_num); +DUSK_NOINLINE u8 dComIfGp_checkMesgBgm(); +DUSK_NOINLINE void dComIfGp_setMesgBgmOff(); +DUSK_NOINLINE void dComIfGp_setMesgBgmOn(); +DUSK_NOINLINE u8 dComIfGp_isPauseFlag(); +DUSK_NOINLINE void dComIfGp_offPauseFlag(); +DUSK_NOINLINE void dComIfGp_onPauseFlag(); +DUSK_NOINLINE u8 dComIfGp_getOxygenShowFlag(); +DUSK_NOINLINE void dComIfGp_offOxygenShowFlag(); +DUSK_NOINLINE void dComIfGp_onOxygenShowFlag(); +DUSK_NOINLINE u8 dComIfGp_2dShowCheck(); +DUSK_NOINLINE void dComIfGp_2dShowOn(); +DUSK_NOINLINE void dComIfGp_2dShowOff(); +DUSK_NOINLINE JKRExpHeap* dComIfGp_getExpHeap2D(); +DUSK_NOINLINE void dComIfGp_setExpHeap2D(void* heap); +DUSK_NOINLINE JKRExpHeap* dComIfGp_getSubExpHeap2D(int idx); +DUSK_NOINLINE void dComIfGp_setSubExpHeap2D(int idx, void* heap); +DUSK_NOINLINE JKRExpHeap* dComIfGp_getMsgExpHeap(); +DUSK_NOINLINE void dComIfGp_setMsgExpHeap(void* heap); +DUSK_NOINLINE dComIfG_MesgCamInfo_c* dComIfGp_getMesgCameraInfo(); +DUSK_NOINLINE void dComIfGp_setMesgCameraTagInfo(int id); +DUSK_NOINLINE void dComIfGp_clearMesgCameraTagInfo(); +DUSK_NOINLINE void dComIfGp_setMesgCameraAttrInfo(int param_1); +DUSK_NOINLINE void dComIfGp_clearMesgCameraAttrInfo(); +DUSK_NOINLINE void dComIfGp_setMesgCameraInfoActor(fopAc_ac_c* param_1, fopAc_ac_c* param_2, + fopAc_ac_c* param_3, fopAc_ac_c* param_4, fopAc_ac_c* param_5, fopAc_ac_c* param_6, + fopAc_ac_c* param_7, fopAc_ac_c* param_8, fopAc_ac_c* param_9, fopAc_ac_c* param_10); +DUSK_NOINLINE u32 dComIfGp_checkPlayerStatus0(int param_0, u32 flag); +DUSK_NOINLINE u32 dComIfGp_checkPlayerStatus1(int param_0, u32 flag); +DUSK_NOINLINE void dComIfGp_setPlayerStatus0(int param_0, u32 flag); +DUSK_NOINLINE void dComIfGp_setPlayerStatus1(int param_0, u32 flag); +DUSK_NOINLINE void dComIfGp_clearPlayerStatus0(int param_0, u32 flag); +DUSK_NOINLINE void dComIfGp_clearPlayerStatus1(int param_0, u32 flag); +DUSK_NOINLINE void dComIfGp_setCurrentWindow(dDlst_window_c* i_window); +DUSK_NOINLINE void dComIfGp_setCurrentView(view_class* i_view); +DUSK_NOINLINE void dComIfGp_setCurrentViewport(view_port_class* i_viewport); +DUSK_NOINLINE J2DGrafContext* dComIfGp_getCurrentGrafPort(); +DUSK_NOINLINE void dComIfGp_setCurrentGrafPort(J2DOrthoGraph* i_graf); +DUSK_NOINLINE void* dComIfGp_getItemTable(); +DUSK_NOINLINE void dComIfGp_setItemTable(void* data); +DUSK_NOINLINE char* dComIfGp_getLastPlayStageName(); +DUSK_NOINLINE void dComIfGp_setLastPlayStageName(char* name); +DUSK_NOINLINE void dComIfGp_init(); +DUSK_NOINLINE void dComIfGp_itemDataInit(); +DUSK_NOINLINE void dComIfGp_setItemBombNumCount(u8 i_item, s16 count); +DUSK_NOINLINE s16 dComIfGp_getItemBombNumCount(u8 i_no); +DUSK_NOINLINE void dComIfGp_clearItemBombNumCount(u8 i_no); +DUSK_NOINLINE s16 dComIfGp_getItemMaxBombNumCount(); +DUSK_NOINLINE void dComIfGp_setNowVibration(u8 status); +DUSK_NOINLINE u32 dComIfGp_getNowVibration(); +DUSK_NOINLINE void dComIfGp_particle_create(); +DUSK_NOINLINE void dComIfGp_createSimpleModel(); +DUSK_NOINLINE void dComIfGp_deleteSimpleModel(); +DUSK_NOINLINE void dComIfGp_drawSimpleModel(); +DUSK_NOINLINE int dComIfGp_addSimpleModel(J3DModelData* i_modelData, int roomNo, u8 i_drawBG); +DUSK_NOINLINE void dComIfGp_removeSimpleModel(J3DModelData* i_modelData, int roomNo); +DUSK_NOINLINE void dComIfGp_entrySimpleModel(J3DModel* model, int roomNo); +DUSK_NOINLINE void dComIfG_ct(); +DUSK_NOINLINE dBgS& dComIfG_Bgsp(); +DUSK_NOINLINE dCcS* dComIfG_Ccsp(); +DUSK_NOINLINE dCcS& dComIfG_Ccsp2(); +DUSK_NOINLINE void dComIfG_setTimerNowTimeMs(int time); +DUSK_NOINLINE int dComIfG_getTimerNowTimeMs(); +DUSK_NOINLINE void dComIfG_setTimerLimitTimeMs(int i_time); +DUSK_NOINLINE int dComIfG_getTimerLimitTimeMs(); +DUSK_NOINLINE void dComIfG_setTimerMode(int mode); +DUSK_NOINLINE int dComIfG_getTimerMode(); +DUSK_NOINLINE void dComIfG_setTimerType(u8 i_type); +DUSK_NOINLINE u8 dComIfG_getTimerType(); +DUSK_NOINLINE void dComIfG_setTimerPtr(dTimer_c* i_ptr); +DUSK_NOINLINE dTimer_c* dComIfG_getTimerPtr(); + +/** + * Attempts to add a new Object Resource Archive (*.arc) into the Resource Control. + * @param i_arcName Name of archive to be added + * @param i_mountDirection The direction to mount the archive. mDoDvd_MOUNT_DIRECTION_HEAD or + * mDoDvd_MOUNT_DIRECTION_TAIL + * @param i_heap Pointer to heap to load resources into + * @return TRUE if successful, FALSE otherwise + */ +DUSK_NOINLINE int dComIfG_setObjectRes(const char* i_arcName, u8 i_mountDirection, JKRHeap* i_heap); +DUSK_NOINLINE int dComIfG_setObjectRes( + const char* i_arcName, void* i_archiveRes, u32 i_bufferSize, JKRHeap* i_heap); + +/** + * Attempts to add a new Stage Resource Archive (*.arc) into the Resource Control. + * @param i_arcName Name of archive to be added + * @param i_heap Pointer to heap to load resources into + * @return TRUE if successful, FALSE otherwise + */ +DUSK_NOINLINE int dComIfG_setStageRes(const char* i_arcName, JKRHeap* i_heap); +DUSK_NOINLINE int dComIfG_syncObjectRes(const char* i_arcName); +DUSK_NOINLINE int dComIfG_syncStageRes(const char* i_arcName); +DUSK_NOINLINE int dComIfG_deleteObjectResMain(const char* i_arcName); +DUSK_NOINLINE int dComIfG_deleteStageRes(const char* i_arcName); +DUSK_NOINLINE void* dComIfG_getStageRes(const char* i_arcName, const char* i_resName); +DUSK_NOINLINE void* dComIfG_getObjectRes(const char* i_arcName, const char* i_resName); +DUSK_NOINLINE void* dComIfG_getObjectRes(const char* i_arcName, int i_index); +DUSK_NOINLINE void dComIfG_dumpResControl(); +DUSK_NOINLINE dRes_info_c* dComIfG_getObjectResInfo(const char* i_arcName); +DUSK_NOINLINE dRes_info_c* dComIfG_getStageResInfo(const char* i_arcName); +DUSK_NOINLINE int dComIfG_syncAllObjectRes(); +DUSK_NOINLINE void* dComIfG_getObjectIDRes(const char* i_arcName, u16 i_resID); +DUSK_NOINLINE int dComIfG_getObjctResName2Index(const char* i_arcName, const char* i_resName); +DUSK_NOINLINE u8 dComIfG_getBrightness(); +DUSK_NOINLINE void dComIfG_setBrightness(u8 brightness); +DUSK_NOINLINE BOOL dComIfG_isDebugMode(); +DUSK_NOINLINE u32 dComIfG_getTrigB(u32 i_padNo); +#if DEBUG +DUSK_NOINLINE u32 dComIfG_getObjectAllSize(); +DUSK_NOINLINE u32 dComIfG_getStageAllSize(); +DUSK_NOINLINE u32 dComIfG_getObjectSize(const char* i_arcName); +DUSK_NOINLINE u32 dComIfG_getStageSize(const char* i_arcName); +DUSK_NOINLINE void dComIfG_initStopwatch(); +#endif + +DUSK_NOINLINE int dComIfGd_setRealShadow(u32 param_0, s8 param_1, J3DModel* param_2, cXyz* param_3, + f32 param_4, f32 param_5, dKy_tevstr_c* param_6); +DUSK_NOINLINE int dComIfGd_setSimpleShadow( + cXyz* pos, f32 param_1, f32 param_2, cXyz* param_3, s16 angle, f32 param_5, TGXTexObj* tex); +DUSK_NOINLINE bool dComIfGd_addRealShadow(u32 key, J3DModel* model); +DUSK_NOINLINE void dComIfGd_drawListItem3d(); + +#if VERSION > VERSION_GCN_JPN +DUSK_NOINLINE void dComIfGd_drawListCursor(); +#endif + +DUSK_NOINLINE void dComIfGd_reset(); +DUSK_NOINLINE void dComIfGd_set2DOpa(dDlst_base_c* dlst); +DUSK_NOINLINE void dComIfGd_set2DXlu(dDlst_base_c* dlst); +DUSK_NOINLINE void dComIfGd_set2DOpaTop(dDlst_base_c* dlst); +DUSK_NOINLINE void dComIfGd_setCopy2D(dDlst_base_c* dlst); +DUSK_NOINLINE view_class* dComIfGd_getView(); +DUSK_NOINLINE Mtx44* dComIfGd_getProjViewMtx(); +DUSK_NOINLINE MtxP dComIfGd_getInvViewMtx(); +DUSK_NOINLINE view_port_class* dComIfGd_getViewport(); +DUSK_NOINLINE MtxP dComIfGd_getViewRotMtx(); +DUSK_NOINLINE MtxP dComIfGd_getViewMtx(); +DUSK_NOINLINE J3DDrawBuffer* dComIfGd_getListFilter(); +DUSK_NOINLINE J3DDrawBuffer* dComIfGd_getOpaListIndScreen(); +DUSK_NOINLINE J3DDrawBuffer* dComIfGd_getListPacket(); +DUSK_NOINLINE void dComIfGd_setListSky(); +DUSK_NOINLINE void dComIfGd_setListDark(); +DUSK_NOINLINE void dComIfGd_setListInvisisble(); +DUSK_NOINLINE void dComIfGd_setListDarkBG(); +DUSK_NOINLINE void dComIfGd_setXluListDarkBG(); +DUSK_NOINLINE void dComIfGd_setList(); +DUSK_NOINLINE void dComIfGd_setListItem3D(); +DUSK_NOINLINE void dComIfGd_setList3Dlast(); +DUSK_NOINLINE void dComIfGd_setXluList2DScreen(); +DUSK_NOINLINE void dComIfGd_setXluListBG(); +DUSK_NOINLINE void dComIfGd_setListBG(); +DUSK_NOINLINE void dComIfGd_setListIndScreen(); +DUSK_NOINLINE void dComIfGd_setListMiddle(); +DUSK_NOINLINE void dComIfGd_setListZxlu(); +DUSK_NOINLINE J3DDrawBuffer* dComIfGd_getOpaList(); +DUSK_NOINLINE J3DDrawBuffer* dComIfGd_getOpaListBG(); +DUSK_NOINLINE J3DDrawBuffer* dComIfGd_getOpaListDark(); +DUSK_NOINLINE J3DDrawBuffer* dComIfGd_getXluListBG(); +DUSK_NOINLINE void dComIfGd_setListFilter(); +DUSK_NOINLINE void dComIfGd_init(); +DUSK_NOINLINE void dComIfGd_peekZ(s16 param_0, s16 param_1, u32* param_2); +DUSK_NOINLINE void dComIfGd_peekZdata(); +DUSK_NOINLINE void dComIfGd_setView(view_class* view); +DUSK_NOINLINE void dComIfGd_setWindow(dDlst_window_c* window); +DUSK_NOINLINE void dComIfGd_setViewport(view_port_class* port); +DUSK_NOINLINE void dComIfGd_entryZSortListZxlu(J3DPacket* i_packet, cXyz& param_1); +DUSK_NOINLINE void dComIfGd_entryZSortXluList(J3DPacket* i_packet, cXyz& param_1); +DUSK_NOINLINE void dComIfGd_drawCopy2D(); +DUSK_NOINLINE void dComIfGd_drawOpaListSky(); +DUSK_NOINLINE void dComIfGd_drawXluListSky(); +DUSK_NOINLINE void dComIfGd_drawOpaListBG(); +DUSK_NOINLINE void dComIfGd_drawOpaListDarkBG(); +DUSK_NOINLINE void dComIfGd_drawOpaListMiddle(); +DUSK_NOINLINE void dComIfGd_drawOpaList(); +DUSK_NOINLINE void dComIfGd_drawOpaListDark(); +DUSK_NOINLINE void dComIfGd_drawOpaListPacket(); +DUSK_NOINLINE void dComIfGd_drawXluListBG(); +DUSK_NOINLINE void dComIfGd_drawXluListDarkBG(); +DUSK_NOINLINE void dComIfGd_drawXluList(); +DUSK_NOINLINE void dComIfGd_drawXluListDark(); +DUSK_NOINLINE void dComIfGd_drawXluListInvisible(); +DUSK_NOINLINE void dComIfGd_drawOpaListInvisible(); +DUSK_NOINLINE void dComIfGd_drawXluListZxlu(); +DUSK_NOINLINE void dComIfGd_drawXluList2DScreen(); +DUSK_NOINLINE void dComIfGd_drawOpaList3Dlast(); +DUSK_NOINLINE void dComIfGd_draw2DOpa(); +DUSK_NOINLINE void dComIfGd_draw2DOpaTop(); +DUSK_NOINLINE void dComIfGd_draw2DXlu(); +DUSK_NOINLINE void dComIfGd_drawOpaListFilter(); +DUSK_NOINLINE void dComIfGd_drawIndScreen(); +DUSK_NOINLINE void dComIfGd_drawListZxlu(); +DUSK_NOINLINE void dComIfGd_drawShadow(Mtx param_0); +DUSK_NOINLINE void dComIfGd_imageDrawShadow(Mtx param_0); +DUSK_NOINLINE void dComIfGd_set3DlineMat(mDoExt_3DlineMat_c* param_0); +DUSK_NOINLINE void dComIfGd_set3DlineMatDark(mDoExt_3DlineMat_c* param_0); + +#if PLATFORM_WII || VERSION == VERSION_SHIELD_DEBUG +DUSK_NOINLINE void dComIfGd_setListCursor(); +#endif + +#else inline dSv_info_c* dComIfGs_getSaveInfo() { return &g_dComIfG_gameInfo.info; } @@ -1440,11 +2367,7 @@ inline BOOL dComIfGs_isTransformLV(int i_no) { return g_dComIfG_gameInfo.info.getPlayer().getPlayerStatusB().isTransformLV(i_no); } -#if TARGET_PC -inline cXyz dComIfGs_getHorseRestartPos() { -#else inline cXyz& dComIfGs_getHorseRestartPos() { -#endif return g_dComIfG_gameInfo.info.getPlayer().getHorsePlace().getPos(); } @@ -1465,11 +2388,7 @@ inline void dComIfGs_setHorseRestart(const char* i_stageName, cXyz& i_pos, s16 i g_dComIfG_gameInfo.info.getPlayer().getHorsePlace().set(i_stageName, i_pos, i_angle, i_roomNo); } -#if TARGET_PC -inline cXyz dComIfGs_getPlayerFieldLastStayPos() { -#else inline cXyz& dComIfGs_getPlayerFieldLastStayPos() { -#endif return g_dComIfG_gameInfo.info.getPlayer().getPlayerFieldLastStayInfo().getPos(); } @@ -1511,11 +2430,7 @@ inline void dComIfGs_setPlayerFieldLastStayInfo(const char* i_stage, cXyz& i_pos i_point, i_region); } -#if TARGET_PC -inline cXyz dComIfGs_getLastWarpMarkPlayerPos() { -#else inline cXyz& dComIfGs_getLastWarpMarkPlayerPos() { -#endif return g_dComIfG_gameInfo.info.getPlayer().getPlayerLastMarkInfo().getPos(); } @@ -1853,12 +2768,6 @@ inline void dComIfGs_addDeathCount() { g_dComIfG_gameInfo.info.getPlayer().getPlayerInfo().addDeathCount(); } -#if TARGET_PC -inline u16 dComIfGs_getDeathCount() { - return g_dComIfG_gameInfo.info.getPlayer().getPlayerInfo().getDeathCount(); -} -#endif - inline TEXT_SPAN dComIfGs_getPlayerName() { return g_dComIfG_gameInfo.info.getPlayer().getPlayerInfo().getPlayerName(); } @@ -3125,133 +4034,114 @@ inline void dComIfGp_particle_calcMenu() { } inline void dComIfGp_particle_draw(JPADrawInfo* i_drawInfo) { - ZoneScoped; if (g_dComIfG_gameInfo.play.getParticle() != NULL) { g_dComIfG_gameInfo.play.getParticle()->drawNormal(i_drawInfo); } } inline void dComIfGp_particle_drawFog(JPADrawInfo* i_drawInfo) { - ZoneScoped; if (g_dComIfG_gameInfo.play.getParticle() != NULL) { g_dComIfG_gameInfo.play.getParticle()->drawNormalFog(i_drawInfo); } } inline void dComIfGp_particle_drawP1(JPADrawInfo* i_drawInfo) { - ZoneScoped; if (g_dComIfG_gameInfo.play.getParticle() != NULL) { g_dComIfG_gameInfo.play.getParticle()->drawNormalP1(i_drawInfo); } } inline void dComIfGp_particle_drawProjection(JPADrawInfo* i_drawInfo) { - ZoneScoped; if (g_dComIfG_gameInfo.play.getParticle() != NULL) { g_dComIfG_gameInfo.play.getParticle()->drawProjection(i_drawInfo); } } inline void dComIfGp_particle_drawNormalPri0_A(JPADrawInfo* i_drawInfo) { - ZoneScoped; if (g_dComIfG_gameInfo.play.getParticle() != NULL) { g_dComIfG_gameInfo.play.getParticle()->drawNormalPri0_A(i_drawInfo); } } inline void dComIfGp_particle_drawNormalPri0_B(JPADrawInfo* i_drawInfo) { - ZoneScoped; if (g_dComIfG_gameInfo.play.getParticle() != NULL) { g_dComIfG_gameInfo.play.getParticle()->drawNormalPri0_B(i_drawInfo); } } inline void dComIfGp_particle_drawFogPri0_A(JPADrawInfo* i_drawInfo) { - ZoneScoped; if (g_dComIfG_gameInfo.play.getParticle() != NULL) { g_dComIfG_gameInfo.play.getParticle()->drawFogPri0_A(i_drawInfo); } } inline void dComIfGp_particle_drawFogPri0_B(JPADrawInfo* i_drawInfo) { - ZoneScoped; if (g_dComIfG_gameInfo.play.getParticle() != NULL) { g_dComIfG_gameInfo.play.getParticle()->drawFogPri0_B(i_drawInfo); } } inline void dComIfGp_particle_drawFogPri1(JPADrawInfo* i_drawInfo) { - ZoneScoped; if (g_dComIfG_gameInfo.play.getParticle() != NULL) { g_dComIfG_gameInfo.play.getParticle()->drawFogPri1(i_drawInfo); } } inline void dComIfGp_particle_drawFogPri2(JPADrawInfo* i_drawInfo) { - ZoneScoped; if (g_dComIfG_gameInfo.play.getParticle() != NULL) { g_dComIfG_gameInfo.play.getParticle()->drawFogPri2(i_drawInfo); } } inline void dComIfGp_particle_drawFogPri3(JPADrawInfo* i_drawInfo) { - ZoneScoped; if (g_dComIfG_gameInfo.play.getParticle() != NULL) { g_dComIfG_gameInfo.play.getParticle()->drawFogPri3(i_drawInfo); } } inline void dComIfGp_particle_drawFogPri4(JPADrawInfo* i_drawInfo) { - ZoneScoped; if (g_dComIfG_gameInfo.play.getParticle() != NULL) { g_dComIfG_gameInfo.play.getParticle()->drawFogPri4(i_drawInfo); } } inline void dComIfGp_particle_drawDarkworld(JPADrawInfo* i_drawInfo) { - ZoneScoped; if (g_dComIfG_gameInfo.play.getParticle() != NULL) { g_dComIfG_gameInfo.play.getParticle()->drawDarkworld(i_drawInfo); } } inline void dComIfGp_particle_drawScreen(JPADrawInfo* i_drawInfo) { - ZoneScoped; if (g_dComIfG_gameInfo.play.getParticle() != NULL) { g_dComIfG_gameInfo.play.getParticle()->drawFogScreen(i_drawInfo); } } inline void dComIfGp_particle_draw2Dgame(JPADrawInfo* i_drawInfo) { - ZoneScoped; if (g_dComIfG_gameInfo.play.getParticle() != NULL) { g_dComIfG_gameInfo.play.getParticle()->draw2Dgame(i_drawInfo); } } inline void dComIfGp_particle_draw2Dfore(JPADrawInfo* i_drawInfo) { - ZoneScoped; if (g_dComIfG_gameInfo.play.getParticle() != NULL) { g_dComIfG_gameInfo.play.getParticle()->draw2Dfore(i_drawInfo); } } inline void dComIfGp_particle_draw2Dback(JPADrawInfo* i_drawInfo) { - ZoneScoped; if (g_dComIfG_gameInfo.play.getParticle() != NULL) { g_dComIfG_gameInfo.play.getParticle()->draw2Dback(i_drawInfo); } } inline void dComIfGp_particle_draw2DmenuFore(JPADrawInfo* i_drawInfo) { - ZoneScoped; if (g_dComIfG_gameInfo.play.getParticle() != NULL) { g_dComIfG_gameInfo.play.getParticle()->draw2DmenuFore(i_drawInfo); } } inline void dComIfGp_particle_draw2DmenuBack(JPADrawInfo* i_drawInfo) { - ZoneScoped; if (g_dComIfG_gameInfo.play.getParticle() != NULL) { g_dComIfG_gameInfo.play.getParticle()->draw2DmenuBack(i_drawInfo); } @@ -4771,150 +5661,114 @@ inline void dComIfGd_setViewport(view_port_class* port) { } inline void dComIfGd_entryZSortListZxlu(J3DPacket* i_packet, cXyz& param_1) { - ZoneScoped; g_dComIfG_gameInfo.drawlist.entryZSortListZxlu(i_packet, param_1); } inline void dComIfGd_entryZSortXluList(J3DPacket* i_packet, cXyz& param_1) { - ZoneScoped; g_dComIfG_gameInfo.drawlist.entryZSortXluList(i_packet, param_1); } inline void dComIfGd_drawCopy2D() { - ZoneScoped; g_dComIfG_gameInfo.drawlist.drawCopy2D(); } inline void dComIfGd_drawOpaListSky() { - ZoneScoped; g_dComIfG_gameInfo.drawlist.drawOpaListSky(); } inline void dComIfGd_drawXluListSky() { - ZoneScoped; g_dComIfG_gameInfo.drawlist.drawXluListSky(); } inline void dComIfGd_drawOpaListBG() { - ZoneScoped; g_dComIfG_gameInfo.drawlist.drawOpaListBG(); } inline void dComIfGd_drawOpaListDarkBG() { - ZoneScoped; g_dComIfG_gameInfo.drawlist.drawOpaListDarkBG(); } inline void dComIfGd_drawOpaListMiddle() { - ZoneScoped; g_dComIfG_gameInfo.drawlist.drawOpaListMiddle(); } inline void dComIfGd_drawOpaList() { - ZoneScoped; g_dComIfG_gameInfo.drawlist.drawOpaList(); } inline void dComIfGd_drawOpaListDark() { - ZoneScoped; g_dComIfG_gameInfo.drawlist.drawOpaListDark(); } inline void dComIfGd_drawOpaListPacket() { - ZoneScoped; g_dComIfG_gameInfo.drawlist.drawOpaListPacket(); } inline void dComIfGd_drawXluListBG() { - ZoneScoped; g_dComIfG_gameInfo.drawlist.drawXluListBG(); } inline void dComIfGd_drawXluListDarkBG() { - ZoneScoped; g_dComIfG_gameInfo.drawlist.drawXluListDarkBG(); } inline void dComIfGd_drawXluList() { - ZoneScoped; g_dComIfG_gameInfo.drawlist.drawXluList(); } inline void dComIfGd_drawXluListDark() { - ZoneScoped; g_dComIfG_gameInfo.drawlist.drawXluListDark(); } -#if TARGET_PC -void dComIfGd_drawXluListInvisible(); -#else inline void dComIfGd_drawXluListInvisible() { - ZoneScoped; g_dComIfG_gameInfo.drawlist.drawXluListInvisible(); } -#endif -#if TARGET_PC -void dComIfGd_drawOpaListInvisible(); -#else inline void dComIfGd_drawOpaListInvisible() { - ZoneScoped; g_dComIfG_gameInfo.drawlist.drawOpaListInvisible(); } -#endif inline void dComIfGd_drawXluListZxlu() { - ZoneScoped; g_dComIfG_gameInfo.drawlist.drawXluListZxlu(); } inline void dComIfGd_drawXluList2DScreen() { - ZoneScoped; g_dComIfG_gameInfo.drawlist.drawXluList2DScreen(); } inline void dComIfGd_drawOpaList3Dlast() { - ZoneScoped; g_dComIfG_gameInfo.drawlist.drawOpaList3Dlast(); } inline void dComIfGd_draw2DOpa() { - ZoneScoped; g_dComIfG_gameInfo.drawlist.draw2DOpa(); } inline void dComIfGd_draw2DOpaTop() { - ZoneScoped; g_dComIfG_gameInfo.drawlist.draw2DOpaTop(); } inline void dComIfGd_draw2DXlu() { - ZoneScoped; g_dComIfG_gameInfo.drawlist.draw2DXlu(); } inline void dComIfGd_drawOpaListFilter() { - ZoneScoped; g_dComIfG_gameInfo.drawlist.drawOpaListFilter(); } inline void dComIfGd_drawIndScreen() { - ZoneScoped; g_dComIfG_gameInfo.drawlist.drawOpaListP0(); } inline void dComIfGd_drawListZxlu() { - ZoneScoped; g_dComIfG_gameInfo.drawlist.drawXluListZxlu(); } inline void dComIfGd_drawShadow(Mtx param_0) { - ZoneScoped; g_dComIfG_gameInfo.drawlist.drawShadow(param_0); } inline void dComIfGd_imageDrawShadow(Mtx param_0) { - ZoneScoped; g_dComIfG_gameInfo.drawlist.imageDrawShadow(param_0); } @@ -4933,4 +5787,6 @@ inline void dComIfGd_setListCursor() { } #endif +#endif + #endif /* D_COM_D_COM_INF_GAME_H */ diff --git a/include/d/d_file_sel_info.h b/include/d/d_file_sel_info.h index 973349c469..37dadbeb1b 100644 --- a/include/d/d_file_sel_info.h +++ b/include/d/d_file_sel_info.h @@ -37,7 +37,7 @@ public: CPaneMgrAlpha* getNoDatBase() { return mNoDatBase; } void draw() { _draw(); } -private: +// private: /* 0x04 */ JKRArchive* mArchive; /* 0x08 */ dDlst_FileInfo_c mFileInfo; /* 0x1C */ u8 field_0x1c[4]; diff --git a/include/d/d_file_select.h b/include/d/d_file_select.h index 41349acac3..48d81d9ad5 100644 --- a/include/d/d_file_select.h +++ b/include/d/d_file_select.h @@ -16,39 +16,6 @@ class dFile_info_c; class J2DPicture; -#if TARGET_PC -static PaneCache mSelDtPanes[] = { - {MULTI_CHAR('tate_n0'), 0.0f, 0.0f, false}, - {MULTI_CHAR('tate_n1'), 0.0f, 0.0f, false}, - {MULTI_CHAR('ken_n0'), 0.0f, 0.0f, false}, - {MULTI_CHAR('ken_n1'), 0.0f, 0.0f, false}, - {MULTI_CHAR('fuku_n0'), 0.0f, 0.0f, false}, - {MULTI_CHAR('fuku_n1'), 0.0f, 0.0f, false}, - {MULTI_CHAR('fuku_n2'), 0.0f, 0.0f, false}, - {MULTI_CHAR('gray_n'), 0.0f, 0.0f, false}, - {MULTI_CHAR('b_base'), 0.0f, 0.0f, false}, - {MULTI_CHAR('b_base1'), 0.0f, 0.0f, false}, -}; - -static PaneCache fileSelPanes[] = { - {MULTI_CHAR('w_uzu00'), 0.0f, 0.0f, false}, - {MULTI_CHAR('w_uzu01'), 0.0f, 0.0f, false}, - {MULTI_CHAR('w_uzu02'), 0.0f, 0.0f, false}, - {MULTI_CHAR('w_uzu03'), 0.0f, 0.0f, false}, - {MULTI_CHAR('w_uzu04'), 0.0f, 0.0f, false}, - {MULTI_CHAR('w_uzu05'), 0.0f, 0.0f, false}, - {MULTI_CHAR('w_uzu06'), 0.0f, 0.0f, false}, - {MULTI_CHAR('w_uzu07'), 0.0f, 0.0f, false}, - {MULTI_CHAR('w_uzu08'), 0.0f, 0.0f, false}, - {MULTI_CHAR('w_uzu09'), 0.0f, 0.0f, false}, - {MULTI_CHAR('w_er_msg'), 0.0f, 0.0f, false}, - {MULTI_CHAR('w_er_msE'), 0.0f, 0.0f, false}, - {MULTI_CHAR('w_er_msR'), 0.0f, 0.0f, false}, - {MULTI_CHAR('er_for0'), 0.0f, 0.0f, false}, - {MULTI_CHAR('er_for1'), 0.0f, 0.0f, false}, -}; -#endif - class dDlst_FileSel_c : public dDlst_base_c { public: void draw(); diff --git a/include/d/d_item_data.h b/include/d/d_item_data.h index 0044573976..7672174c87 100644 --- a/include/d/d_item_data.h +++ b/include/d/d_item_data.h @@ -142,7 +142,12 @@ enum { /* 0x2F */ dItemNo_WEAR_KOKIRI_e, /* 0x30 */ dItemNo_ARMOR_e, /* 0x31 */ dItemNo_WEAR_ZORA_e, +#if TARGET_PC /* 0x32 */ dItemNo_MAGIC_LV1_e, + dItemNo_SHADOW_CRYSTAL_e = dItemNo_MAGIC_LV1_e, +#else + /* 0x32 */ dItemNo_MAGIC_LV1_e, +#endif /* 0x33 */ dItemNo_DUNGEON_EXIT_2_e, /* 0x34 */ dItemNo_WALLET_LV1_e, /* 0x35 */ dItemNo_WALLET_LV2_e, diff --git a/include/d/d_kantera_icon_meter.h b/include/d/d_kantera_icon_meter.h index 04466df8be..67e2dff278 100644 --- a/include/d/d_kantera_icon_meter.h +++ b/include/d/d_kantera_icon_meter.h @@ -30,7 +30,7 @@ public: void drawSelf() { mpKanteraIcon->draw(); } -private: +// private: /* 0x04 */ dDlst_KanteraIcon_c* mpKanteraIcon; /* 0x08 */ CPaneMgr* mpParent; /* 0x0C */ CPaneMgr* mpGauge; diff --git a/include/d/d_menu_collect.h b/include/d/d_menu_collect.h index b7d5ec2976..0811fb00a6 100644 --- a/include/d/d_menu_collect.h +++ b/include/d/d_menu_collect.h @@ -15,49 +15,6 @@ class dMenu_Fishing_c; class dMenu_Skill_c; class dMenu_Insect_c; class dSelect_cursor_c; - -#if TARGET_PC -struct PaneCache { - u64 tag; - f32 origTransX; - f32 origTransY; - bool cached; -}; - -static PaneCache mpScreenPanes[] = { - {MULTI_CHAR('sa_tex_n'), 0.0f, 0.0f, false}, - {MULTI_CHAR('op_tex_n'), 0.0f, 0.0f, false}, - {MULTI_CHAR('heart_n'), 0.0f, 0.0f, false}, - {MULTI_CHAR('wolf_n'), 0.0f, 0.0f, false}, - {MULTI_CHAR('item_0_n'), 0.0f, 0.0f, false}, - {MULTI_CHAR('item_1_n'), 0.0f, 0.0f, false}, - {MULTI_CHAR('item_2_n'), 0.0f, 0.0f, false}, - {MULTI_CHAR('fish_3_n'), 0.0f, 0.0f, false}, - {MULTI_CHAR('lett_4_n'), 0.0f, 0.0f, false}, - {MULTI_CHAR('maki_5_n'), 0.0f, 0.0f, false}, - {MULTI_CHAR('fuku_n0'), 0.0f, 0.0f, false}, - {MULTI_CHAR('fuku_n1'), 0.0f, 0.0f, false}, - {MULTI_CHAR('fuku_n2'), 0.0f, 0.0f, false}, - {MULTI_CHAR('tate_n0'), 0.0f, 0.0f, false}, - {MULTI_CHAR('tate_n1'), 0.0f, 0.0f, false}, - {MULTI_CHAR('ken_n0'), 0.0f, 0.0f, false}, - {MULTI_CHAR('ken_n1'), 0.0f, 0.0f, false}, - {MULTI_CHAR('kabu_6n'), 0.0f, 0.0f, false}, - {MULTI_CHAR('t_t00'), 0.0f, 0.0f, false}, - {MULTI_CHAR('f_t00'), 0.0f, 0.0f, false}, - {MULTI_CHAR('itemn_n'), 0.0f, 0.0f, false}, - {MULTI_CHAR('infotxtn'), 0.0f, 0.0f, false}, - {MULTI_CHAR('sa_op_n'), 0.0f, 0.0f, false}, - {MULTI_CHAR('title_n'), 0.0f, 0.0f, false}, - {MULTI_CHAR('menu_n'), 0.0f, 0.0f, false}, - {MULTI_CHAR('w_er_n'), 0.0f, 0.0f, false}, - {MULTI_CHAR('center_n'), 0.0f, 0.0f, false}, - {MULTI_CHAR('info_n'), 0.0f, 0.0f, false}, - {MULTI_CHAR('lavel_n'), 0.0f, 0.0f, false}, - {MULTI_CHAR('modelbgn'), 0.0f, 0.0f, false}, -}; -#endif - class dMenu_Collect2D_c; class dMenu_Collect2DTop_c : public dDlst_base_c { public: @@ -172,7 +129,7 @@ public: J2DPicture* getBlackTex() { return mpBlackTex; } u8 getSubWindowOpenCheck() { return mSubWindowOpenCheck; } -private: +// private: /* 0x004 */ JKRExpHeap* mpHeap; /* 0x008 */ JKRExpHeap* mpSubHeap; /* 0x00C */ void* field_0xc; diff --git a/include/d/d_menu_fishing.h b/include/d/d_menu_fishing.h index 972aa8f7c4..f2e9419ce3 100644 --- a/include/d/d_menu_fishing.h +++ b/include/d/d_menu_fishing.h @@ -43,7 +43,7 @@ public: u8 getStatus() { return mStatus; } -private: +// private: /* 0x004 */ JKRExpHeap* mpHeap; /* 0x008 */ JKRArchive* mpArchive; /* 0x00C */ STControl* mpStick; diff --git a/include/d/d_menu_fmap.h b/include/d/d_menu_fmap.h index 110298798a..2e5ee95772 100644 --- a/include/d/d_menu_fmap.h +++ b/include/d/d_menu_fmap.h @@ -270,7 +270,7 @@ public: static DUSK_GAME_DATA dMenu_Fmap_c* MyClass; -private: +// private: /* 0x004 */ JKRExpHeap* mpHeap; /* 0x008 */ JKRExpHeap* mpTalkHeap; /* 0x00C */ STControl* mpStick; diff --git a/include/d/d_menu_insect.h b/include/d/d_menu_insect.h index 90cfca7d5a..5e0b453949 100644 --- a/include/d/d_menu_insect.h +++ b/include/d/d_menu_insect.h @@ -60,7 +60,7 @@ public: u8 getStatus() { return mStatus; } -private: +// private: /* 0x04 */ JKRExpHeap* mpHeap; /* 0x08 */ JKRArchive* mpArchive; /* 0x0C */ STControl* mpStick; diff --git a/include/d/d_menu_letter.h b/include/d/d_menu_letter.h index 208f8b65a9..21747c7e78 100644 --- a/include/d/d_menu_letter.h +++ b/include/d/d_menu_letter.h @@ -64,7 +64,7 @@ public: u8 getStatus() { return mStatus; } -private: +// private: /* 0x004 */ JKRExpHeap* mpHeap; /* 0x008 */ JKRArchive* mpArchive; /* 0x00C */ STControl* mpStick; diff --git a/include/d/d_menu_option.h b/include/d/d_menu_option.h index 49e81f98ae..f158498dd7 100644 --- a/include/d/d_menu_option.h +++ b/include/d/d_menu_option.h @@ -117,7 +117,7 @@ public: return ((u8)mUseFlag & (u8)i_flag) != 0 ? true : false; } -private: +// private: /* 0x004 */ J2DScreen* mpBackScreen; /* 0x008 */ J2DScreen* mpScreen; /* 0x00C */ J2DScreen* mpClipScreen; diff --git a/include/d/d_menu_ring.h b/include/d/d_menu_ring.h index c7467d2a4b..d0f021339e 100644 --- a/include/d/d_menu_ring.h +++ b/include/d/d_menu_ring.h @@ -84,7 +84,7 @@ public: void drawFlag0() { mDrawFlag = 0; } void setStatus(u8 i_status) { mStatus = i_status; } -private: +// private: /* 0x004 */ JKRExpHeap* mpHeap; /* 0x008 */ STControl* mpStick; /* 0x00C */ CSTControl* mpCStick; diff --git a/include/d/d_menu_save.h b/include/d/d_menu_save.h index d9d052aa33..7e94d1d1c9 100644 --- a/include/d/d_menu_save.h +++ b/include/d/d_menu_save.h @@ -278,7 +278,7 @@ public: u8 getEndStatus() { return mEndStatus; } void setUseType(u8 type) { mUseType = type; } -private: +// private: /* 0x0004 */ JKRArchive* mpArchive; /* 0x0008 */ mDoDvdThd_mountArchive_c* mpMount; /* 0x000C */ STControl* stick; diff --git a/include/d/d_menu_skill.h b/include/d/d_menu_skill.h index 2f9097b165..d21332c341 100644 --- a/include/d/d_menu_skill.h +++ b/include/d/d_menu_skill.h @@ -58,7 +58,7 @@ public: u8 getStatus() { return mStatus; } -private: +// private: /* 0x004 */ JKRExpHeap* mpHeap; /* 0x008 */ JKRArchive* mpArchive; /* 0x00C */ STControl* mpStick; diff --git a/include/d/d_meter2_draw.h b/include/d/d_meter2_draw.h index 10cded803d..aaad9dec70 100644 --- a/include/d/d_meter2_draw.h +++ b/include/d/d_meter2_draw.h @@ -154,7 +154,7 @@ public: } #endif -private: +// private: /* 0x004 */ item_params mItemParams[4]; /* 0x074 */ JKRExpHeap* heap; /* 0x078 */ J2DScreen* mpScreen; diff --git a/include/d/d_meter2_info.h b/include/d/d_meter2_info.h index 410cf642b1..377f51c34b 100644 --- a/include/d/d_meter2_info.h +++ b/include/d/d_meter2_info.h @@ -328,6 +328,150 @@ void dMeter2Info_onWide2D(); void dMeter2Info_offWide2D(); #endif +#if TARGET_PC +DUSK_NOINLINE void dMeter2Info_Initialize(); +DUSK_NOINLINE dMeterMap_c* dMeter2Info_getMeterMapClass(); +DUSK_NOINLINE dMw_c* dMeter2Info_getMenuWindowClass(); +DUSK_NOINLINE void dMeter2Info_setWindowStatus(u8 i_status); +DUSK_NOINLINE CPaneMgr* dMeter2Info_getMeterItemPanePtr(s32 i_idx); +DUSK_NOINLINE void dMeter2Info_getString( + u32 i_stringID, TEXT_SPAN o_string, JMSMesgEntry_c* i_msgEntry); +DUSK_NOINLINE void dMeter2Info_getStringKanji( + u32 i_stringID, TEXT_SPAN o_string, JMSMesgEntry_c* i_msgEntry); +DUSK_NOINLINE void dMeter2Info_getStringKana( + u32 i_stringID, TEXT_SPAN o_string, JMSMesgEntry_c* i_msgEntry); +DUSK_NOINLINE f32 dMeter2Info_getStringLength( + JUTFont* i_font, f32 param_2, f32 param_3, char* i_string); +DUSK_NOINLINE f32 dMeter2Info_getStringLength(J2DTextBox* i_textbox, char* i_string); +DUSK_NOINLINE void dMeter2Info_setHotSpringTimer(u8 i_slotNo); +DUSK_NOINLINE u16 dMeter2Info_getOilGaugeBackUp(); +DUSK_NOINLINE void dMeter2Info_setOilGaugeBackUp(u16 param_1); +DUSK_NOINLINE void dMeter2Info_setSaveStageName(const char* i_stageName); +DUSK_NOINLINE u8 dMeter2Info_getInsectSelectType(); +DUSK_NOINLINE void dMeter2Info_setInsectSelectType(u8 i_type); +DUSK_NOINLINE u8 dMeter2Info_getWarpStatus(); +DUSK_NOINLINE void dMeter2Info_setWarpStatus(u8 i_status); +DUSK_NOINLINE int dMeter2Info_readItemTexture(u8 i_itemNo, void* i_texBuf1, J2DPicture* i_pic1, + void* i_texBuf2, J2DPicture* i_pic2, void* i_texBuf3, J2DPicture* i_pic3, void* i_texBuf4, + J2DPicture* i_pic4, int param_9); +DUSK_NOINLINE void dMeter2Info_setItemColor( + u8 i_itemNo, J2DPicture* i_pic1, J2DPicture* i_pic2, J2DPicture* i_pic3, J2DPicture* i_pic4); +DUSK_NOINLINE u8 dMeter2Info_getWarpRoomNo(); +DUSK_NOINLINE u8 dMeter2Info_getWarpPlayerNo(); +DUSK_NOINLINE cXyz& dMeter2Info_getWarpPos(); +DUSK_NOINLINE const char* dMeter2Info_getWarpStageName(); +DUSK_NOINLINE void dMeter2Info_setNowCount(u8 i_count); +DUSK_NOINLINE void dMeter2Info_setMaxCount(u8 i_count); +DUSK_NOINLINE BOOL dMeter2Info_isDirectUseItem(int param_0); +DUSK_NOINLINE bool dMeter2Info_isUseButton(int i_buttonBit); +DUSK_NOINLINE void dMeter2Info_setMeterMapClass(dMeterMap_c* i_map); +DUSK_NOINLINE void dMeter2Info_decHotSpringTimer(); +DUSK_NOINLINE void dMeter2Info_allUseButton(); +DUSK_NOINLINE void dMeter2Info_offUseButton(int i_buttonBit); +DUSK_NOINLINE void dMeter2Info_resetGameStatus(); +DUSK_NOINLINE void dMeter2Info_onGameStatus(int i_status); +DUSK_NOINLINE void dMeter2Info_setMapStatus(u8 i_status); +DUSK_NOINLINE u8 dMeter2Info_getMapStatus(); +DUSK_NOINLINE void dMeter2Info_setPauseStatus(u8 i_status); +DUSK_NOINLINE void dMeter2Info_resetPauseStatus(); +DUSK_NOINLINE u8 dMeter2Info_getPauseStatus(); +DUSK_NOINLINE bool dMeter2Info_isGameStatus(int i_status); +DUSK_NOINLINE bool dMeter2Info_isTouchKeyCheck(int i_status); +DUSK_NOINLINE void dMeter2Info_setMapKeyDirection(u16 i_direction); +DUSK_NOINLINE bool dMeter2Info_isSub2DStatus(int i_flag); +DUSK_NOINLINE void dMeter2Info_offMenuInForce(int i_flag); +DUSK_NOINLINE bool dMeter2Info_isMenuInForce(int i_flag); +DUSK_NOINLINE void dMeter2Info_setMenuWindowClass(dMw_c* i_menu); +DUSK_NOINLINE void dMeter2Info_resetWarpStatus(); +DUSK_NOINLINE u16 dMeter2Info_getMapKeyDirection(); +DUSK_NOINLINE u8 dMeter2Info_getWindowStatus(); +DUSK_NOINLINE void dMeter2Info_setMsgResource(void* i_res); +DUSK_NOINLINE void dMeter2Info_setStageMsgResource(void* i_res); +DUSK_NOINLINE void dMeter2Info_setMsgUnitResource(void* i_res); +DUSK_NOINLINE void* dMeter2Info_getMsgResource(); +DUSK_NOINLINE void* dMeter2Info_getStageMsgResource(); +DUSK_NOINLINE void* dMeter2Info_getMsgUnitResource(); +DUSK_NOINLINE u8 dMeter2Info_getLightDropGetFlag(int i_no); +DUSK_NOINLINE s32 dMeter2Info_getMeterStringType(); +DUSK_NOINLINE void dMeter2Info_setMeterClass(dMeter2_c* i_meter); +DUSK_NOINLINE void dMeter2Info_onLifeGaugeSE(); +DUSK_NOINLINE void dMeter2Info_offLifeGaugeSE(); +DUSK_NOINLINE u8 dMeter2Info_getLifeGaugeSE(); +DUSK_NOINLINE const char* dMeter2Info_getSaveStageName(); +DUSK_NOINLINE void dMeter2Info_onShopTalkFlag(); +DUSK_NOINLINE void dMeter2Info_setLightDropGetFlag(int i_no, u8 i_flag); +DUSK_NOINLINE u8 dMeter2Info_getRentalBombBag(); +DUSK_NOINLINE u8 dMeter2Info_getMiniGameItemSetFlag(); +DUSK_NOINLINE void dMeter2Info_setMiniGameItem(u8 i_minigameFlag); +DUSK_NOINLINE void dMeter2Info_resetMiniGameItem(bool i_saveItem); +DUSK_NOINLINE void dMeter2Info_setTableMapRegionNo(u8 i_regionNo); +DUSK_NOINLINE void dMeter2Info_setGoldWolfMapType(u8 i_mapType); +DUSK_NOINLINE void dMeter2Info_changeWater(u8 i_slotNo); +DUSK_NOINLINE void dMeter2Info_warpInProc(); +DUSK_NOINLINE void dMeter2Info_warpOutProc(); +DUSK_NOINLINE dMeter2_c* dMeter2Info_getMeterClass(); +DUSK_NOINLINE s16 dMeter2Info_getMsgKeyWaitTimer(); +DUSK_NOINLINE void dMeter2Info_onDirectUseItem(int param_0); +DUSK_NOINLINE void dMeter2Info_setFloatingFlow(u16 i_flowID, s16 i_msgTimer, bool i_wakuVisible); +DUSK_NOINLINE u8 dMeter2Info_getGameOverType(); +DUSK_NOINLINE void dMeter2Info_setGameOverType(u8 i_gameoverType); +DUSK_NOINLINE void dMeter2Info_setMsgKeyWaitTimer(s16 i_waitTimer); +DUSK_NOINLINE s32 dMeter2Info_getMsgTimeMs(); +DUSK_NOINLINE s32 dMeter2Info_getTimeMs(); +DUSK_NOINLINE void dMeter2Info_setMsgTimeMs(s32 i_msgTime); +DUSK_NOINLINE void dMeter2Info_setTimeMs(s32 i_time); +DUSK_NOINLINE u8 dMeter2Info_getNowCount(); +DUSK_NOINLINE u8 dMeter2Info_getMaxCount(); +DUSK_NOINLINE void dMeter2Info_setScopeZoomPointer(u8 param_0); +DUSK_NOINLINE void dMeter2Info_decMsgKeyWaitTimer(); +DUSK_NOINLINE bool dMeter2Info_isFloatingMessageVisible(); +DUSK_NOINLINE u8 dMeter2Info_getItemExplainWindowStatus(); +DUSK_NOINLINE void dMeter2Info_setItemExplainWindowStatus(u8 i_value); +DUSK_NOINLINE void dMeter2Info_resetDirectUseItem(); +DUSK_NOINLINE u16 dMeter2Info_getFloatingFlowID(); +DUSK_NOINLINE u8 dMeter2Info_getCollectCursorPosX(); +DUSK_NOINLINE u8 dMeter2Info_getCollectCursorPosY(); +DUSK_NOINLINE void dMeter2Info_setCollectCursorPosXY(u8 x, u8 y); +DUSK_NOINLINE void dMeter2Info_onBlinkButton(int i_flag); +DUSK_NOINLINE bool dMeter2Info_isFloatingMessageWakuVisible(); +DUSK_NOINLINE bool dMeter2Info_isBlinkButton(int i_flag); +DUSK_NOINLINE void dMeter2Info_resetBlinkButton(); +DUSK_NOINLINE void dMeter2Info_resetFloatingMessage(); +DUSK_NOINLINE s16 dMeter2Info_decFloatingMessageTimer(); +DUSK_NOINLINE s16 dMeter2Info_getFloatingMessageTimer(); +DUSK_NOINLINE u16 dMeter2Info_getFloatingMessageID(); +DUSK_NOINLINE s16 dMeter2Info_getHorseLifeCount(); +DUSK_NOINLINE void dMeter2Info_setMeterString(s32 i_string); +DUSK_NOINLINE void dMeter2Info_resetMeterString(); +DUSK_NOINLINE void dMeter2Info_setMeterItemPanePtr(int i_no, CPaneMgr* i_pane); +DUSK_NOINLINE bool dMeter2Info_isShopTalkFlag(); +DUSK_NOINLINE void dMeter2Info_setMapDrugFlag(bool i_flag); +DUSK_NOINLINE bool dMeter2Info_isTempBit(int i_bit); +DUSK_NOINLINE void dMeter2Info_offSub2DStatus(int i_bit); +DUSK_NOINLINE void dMeter2Info_onSub2DStatus(int i_bit); +DUSK_NOINLINE void dMeter2Info_set2DWidth(f32 i_width); +DUSK_NOINLINE void dMeter2Info_set2DHeight(f32 i_height); +DUSK_NOINLINE void dMeter2Info_set2DPosH(f32 i_posH); +DUSK_NOINLINE void dMeter2Info_set2DPosV(f32 i_posV); +DUSK_NOINLINE void dMeter2Info_offShopTalkFlag(); +DUSK_NOINLINE void dMeter2Info_onUseButton(int i_button); +DUSK_NOINLINE f32 dMeter2Info_get2DWidth(); +DUSK_NOINLINE f32 dMeter2Info_get2DHeight(); +DUSK_NOINLINE void dMeter2Info_setWarpInfo(const char* i_stageName, const cXyz& i_position, + s16 i_angle, u8 i_roomNo, u8 param_4, u8 i_warpPlayerNo); +DUSK_NOINLINE u8 dMeter2Info_getTableMapRegionNo(); +DUSK_NOINLINE u8 dMeter2Info_getGoldWolfMapType(); +DUSK_NOINLINE bool dMeter2Info_isWindowAccept(int param_0); +DUSK_NOINLINE void dMeter2Info_setHorseLifeCount(s16 i_count); +DUSK_NOINLINE void dMeter2Info_offTempBit(int i_bit); +DUSK_NOINLINE void dMeter2Info_onTempBit(int i_bit); +DUSK_NOINLINE void dMeter2Info_setFloatingMessage(u16 i_msgID, s16 i_msgTimer, bool i_wakuVisible); +DUSK_NOINLINE void dMeter2Info_setMiniGameCount(s8 i_count); +DUSK_NOINLINE void dMeter2Info_onWindowAccept(int param_0); +DUSK_NOINLINE void dMeter2Info_offWindowAccept(int param_0); +DUSK_NOINLINE void dMeter2Info_onMenuInForce(int param_0); + +#else inline void dMeter2Info_Initialize() { g_meter2_info.init(); } @@ -865,4 +1009,6 @@ inline void dMeter2Info_onMenuInForce(int param_0) { g_meter2_info.onMenuInForce(param_0); } +#endif + #endif /* D_METER_D_METER2_INFO_H */ diff --git a/include/d/d_msg_class.h b/include/d/d_msg_class.h index 2735561c05..c70345ca92 100644 --- a/include/d/d_msg_class.h +++ b/include/d/d_msg_class.h @@ -121,6 +121,25 @@ struct jmessage_tReference : public JMessage::TReference { void setDemoFrame(u32 i_frame) { mDemoFrame = i_frame; } void setTopColorType(u8 i_colorType) { mTopColorType = i_colorType; } void setNowColorType(u8 i_colorType) { mNowColorType = i_colorType; } +#if TARGET_PC + void resetColors() { + mNowCCColor = 0xFFFFFFFF; + mNowGCColor = 0xFFFFFFFF; + mTopCCColor = 0xFFFFFFFF; + mTopGCColor = 0xFFFFFFFF; + mNowFullColor = false; + mTopFullColor = false; + } + void setFullColor(u32 ccColor, u32 gcColor) { + mNowCCColor = ccColor; + mNowGCColor = gcColor; + mNowFullColor = true; + } + void clearNowFullColor() { mNowFullColor = false; } + bool hasTopFullColor() { return mTopFullColor; } + u32 getTopCCColor() { return mTopCCColor; } + u32 getTopGCColor() { return mTopGCColor; } +#endif void setTopTagScale(u16 i_tagScale) { mTopTagScale = i_tagScale; } void setNowTagScale(u16 i_tagScale) { mNowTagScale = i_tagScale; } void setRevoMessageID(u32 i_msgID) { mRevoMessageID = i_msgID; } @@ -365,6 +384,14 @@ struct jmessage_tReference : public JMessage::TReference { /* 0x1274 */ bool mSelectSetCancelFlag; /* 0x1275 */ bool mBombNameUseFlag; /* 0x1276 */ u8 mBatchColorFlag; +#if TARGET_PC + u32 mNowCCColor; + u32 mNowGCColor; + u32 mTopCCColor; + u32 mTopGCColor; + bool mNowFullColor; + bool mTopFullColor; +#endif }; // Size: 0x1278 struct jmessage_tMeasureProcessor : public JMessage::TRenderingProcessor { @@ -462,6 +489,9 @@ struct jmessage_tRenderingProcessor : public JMessage::TRenderingProcessor { void do_selwidthcenter(int); void do_heightcenter(); void do_color(u8); +#if TARGET_PC + void do_fullcolor(u32 ccColor, u32 gcColor); +#endif void do_scale(f32); void do_linedown(s16); void do_transY(s16, bool); @@ -640,6 +670,9 @@ struct jmessage_string_tRenderingProcessor : public JMessage::TRenderingProcesso void do_rubystrcat(char*); void do_outfont(u8); void do_color(u8); +#if TARGET_PC + void do_fullcolor(u32 ccColor, u32 gcColor); +#endif void do_scale(f32); void do_linedown(s16); void do_numset(s16); diff --git a/include/d/d_msg_out_font.h b/include/d/d_msg_out_font.h index 2b2d0fa33d..c6715757eb 100644 --- a/include/d/d_msg_out_font.h +++ b/include/d/d_msg_out_font.h @@ -25,7 +25,7 @@ public: void setTextBoxPtr(J2DTextBox* p_textBox) { mpTextBoxPtr = p_textBox; } void resetType() { mType = 0x47; } -private: +// private: /* 0x04 */ J2DTextBox* mpTextBoxPtr; /* 0x08 */ f32 mPosX; /* 0x0C */ f32 mPosY; @@ -53,7 +53,7 @@ public: void setRupeeColor(u8 color) { mRupeeColor = color; } -private: +// private: /* 0x004 */ COutFontSet_c* mpOfs[35]; /* 0x090 */ J2DPicture* mpPane[70]; /* 0x1A8 */ f32 mAlphaRatio; diff --git a/include/d/d_name.h b/include/d/d_name.h index 68a4930baf..ddd99127c6 100644 --- a/include/d/d_name.h +++ b/include/d/d_name.h @@ -12,34 +12,6 @@ class J2DTextBox; class JUTFont; class STControl; -#if TARGET_PC -struct PaneCache { - u64 tag; - f32 origTransX; - f32 origTransY; - bool cached; -}; - -static PaneCache l_tagName[] = { - {MULTI_CHAR('m_00_0'), 0.0f, 0.0f, false}, {MULTI_CHAR('m_00_1'), 0.0f, 0.0f, false}, {MULTI_CHAR('m_00_2'), 0.0f, 0.0f, false}, {MULTI_CHAR('m_00_3'), 0.0f, 0.0f, false}, {MULTI_CHAR('m_00_4'), 0.0f, 0.0f, false}, {MULTI_CHAR('m_01_0'), 0.0f, 0.0f, false}, {MULTI_CHAR('m_01_1'), 0.0f, 0.0f, false}, {MULTI_CHAR('m_01_2'), 0.0f, 0.0f, false}, {MULTI_CHAR('m_01_3'), 0.0f, 0.0f, false}, - {MULTI_CHAR('m_01_4'), 0.0f, 0.0f, false}, {MULTI_CHAR('m_02_0'), 0.0f, 0.0f, false}, {MULTI_CHAR('m_02_1'), 0.0f, 0.0f, false}, {MULTI_CHAR('m_02_2'), 0.0f, 0.0f, false}, {MULTI_CHAR('m_02_3'), 0.0f, 0.0f, false}, {MULTI_CHAR('m_02_4'), 0.0f, 0.0f, false}, {MULTI_CHAR('m03_0'), 0.0f, 0.0f, false}, {MULTI_CHAR('m03_1'), 0.0f, 0.0f, false}, {MULTI_CHAR('m03_2'), 0.0f, 0.0f, false}, - {MULTI_CHAR('m03_3'), 0.0f, 0.0f, false}, {MULTI_CHAR('m03_4'), 0.0f, 0.0f, false}, {MULTI_CHAR('m_04_0'), 0.0f, 0.0f, false}, {MULTI_CHAR('m_04_1'), 0.0f, 0.0f, false}, {MULTI_CHAR('m_04_2'), 0.0f, 0.0f, false}, {MULTI_CHAR('m_04_3'), 0.0f, 0.0f, false}, {MULTI_CHAR('m_04_4'), 0.0f, 0.0f, false}, {MULTI_CHAR('m_05_0'), 0.0f, 0.0f, false}, {MULTI_CHAR('m_05_1'), 0.0f, 0.0f, false}, - {MULTI_CHAR('m_05_2'), 0.0f, 0.0f, false}, {MULTI_CHAR('m_05_3'), 0.0f, 0.0f, false}, {MULTI_CHAR('m_05_4'), 0.0f, 0.0f, false}, {MULTI_CHAR('m_06_0'), 0.0f, 0.0f, false}, {MULTI_CHAR('m_06_1'), 0.0f, 0.0f, false}, {MULTI_CHAR('m_06_2'), 0.0f, 0.0f, false}, {MULTI_CHAR('m_06_3'), 0.0f, 0.0f, false}, {MULTI_CHAR('m_06_4'), 0.0f, 0.0f, false}, {MULTI_CHAR('m_07_0'), 0.0f, 0.0f, false}, - {MULTI_CHAR('m_07_1'), 0.0f, 0.0f, false}, {MULTI_CHAR('m_07_2'), 0.0f, 0.0f, false}, {MULTI_CHAR('m_07_3'), 0.0f, 0.0f, false}, {MULTI_CHAR('m_07_4'), 0.0f, 0.0f, false}, {MULTI_CHAR('m_08_0'), 0.0f, 0.0f, false}, {MULTI_CHAR('m_08_1'), 0.0f, 0.0f, false}, {MULTI_CHAR('m_08_2'), 0.0f, 0.0f, false}, {MULTI_CHAR('m_08_3'), 0.0f, 0.0f, false}, {MULTI_CHAR('m_08_4'), 0.0f, 0.0f, false}, - {MULTI_CHAR('m_09_0'), 0.0f, 0.0f, false}, {MULTI_CHAR('m_09_1'), 0.0f, 0.0f, false}, {MULTI_CHAR('m_09_2'), 0.0f, 0.0f, false}, {MULTI_CHAR('m_09_3'), 0.0f, 0.0f, false}, {MULTI_CHAR('m_09_4'), 0.0f, 0.0f, false}, {MULTI_CHAR('m_10_0'), 0.0f, 0.0f, false}, {MULTI_CHAR('m_10_1'), 0.0f, 0.0f, false}, {MULTI_CHAR('m_10_2'), 0.0f, 0.0f, false}, {MULTI_CHAR('m_10_3'), 0.0f, 0.0f, false}, - {MULTI_CHAR('m_10_4'), 0.0f, 0.0f, false}, {MULTI_CHAR('m_11_0'), 0.0f, 0.0f, false}, {MULTI_CHAR('m_11_1'), 0.0f, 0.0f, false}, {MULTI_CHAR('m_11_2'), 0.0f, 0.0f, false}, {MULTI_CHAR('m_11_3'), 0.0f, 0.0f, false}, {MULTI_CHAR('m_11_4'), 0.0f, 0.0f, false}, {MULTI_CHAR('m12_0'), 0.0f, 0.0f, false}, {MULTI_CHAR('m12_1'), 0.0f, 0.0f, false}, {MULTI_CHAR('m12_2'), 0.0f, 0.0f, false}, - {MULTI_CHAR('m12_3'), 0.0f, 0.0f, false}, {MULTI_CHAR('m12_4'), 0.0f, 0.0f, false}, {MULTI_CHAR('p_end_2'), 0.0f, 0.0f, false}, {MULTI_CHAR('p_end_1'), 0.0f, 0.0f, false}, {MULTI_CHAR('p_end_0'), 0.0f, 0.0f, false}, -}; - -static PaneCache l_nameTagName[] = { - {MULTI_CHAR('name_00'), 0.0f, 0.0f, false}, {MULTI_CHAR('name_01'), 0.0f, 0.0f, false}, {MULTI_CHAR('name_02'), 0.0f, 0.0f, false}, {MULTI_CHAR('name_03'), 0.0f, 0.0f, false}, {MULTI_CHAR('name_04'), 0.0f, 0.0f, false}, {MULTI_CHAR('name_05'), 0.0f, 0.0f, false}, {MULTI_CHAR('name_06'), 0.0f, 0.0f, false}, {MULTI_CHAR('name_07'), 0.0f, 0.0f, false}, -}; - -static PaneCache l_nameCurTagName[] = { - {MULTI_CHAR('s__n_00'), 0.0f, 0.0f, false}, {MULTI_CHAR('s__n_01'), 0.0f, 0.0f, false}, {MULTI_CHAR('s__n_02'), 0.0f, 0.0f, false}, {MULTI_CHAR('s__n_03'), 0.0f, 0.0f, false}, {MULTI_CHAR('s__n_04'), 0.0f, 0.0f, false}, {MULTI_CHAR('s__n_05'), 0.0f, 0.0f, false}, {MULTI_CHAR('s__n_06'), 0.0f, 0.0f, false}, {MULTI_CHAR('s__n_07'), 0.0f, 0.0f, false}, -}; -#endif - class dNm_HIO_c { public: dNm_HIO_c(); diff --git a/include/f_op/f_op_actor_mng.h b/include/f_op/f_op_actor_mng.h index b23fc40383..7aa3bf2156 100644 --- a/include/f_op/f_op_actor_mng.h +++ b/include/f_op/f_op_actor_mng.h @@ -532,10 +532,12 @@ s32 fopAcM_delete(fpc_ProcID i_actorID); fpc_ProcID fopAcM_create(s16 i_procName, u16 i_setId, u32 i_parameters, const cXyz* i_pos, int i_roomNo, const csXyz* i_angle, const cXyz* i_scale, s8 i_argument, - createFunc i_createFunc IF_DUSK_ARG(u32 i_itemGiveTag = 0)); + createFunc i_createFunc IF_DUSK_ARG(u32 i_itemGiveTag = 0) + IF_DUSK_ARG(u8 i_itemOriginalNo = 0xFF)); fpc_ProcID fopAcM_create(s16 i_procName, u32 i_parameters, const cXyz* i_pos, int i_roomNo, - const csXyz* i_angle, const cXyz* i_scale, s8 i_argument IF_DUSK_ARG(u32 i_itemGiveTag = 0)); + const csXyz* i_angle, const cXyz* i_scale, s8 i_argument IF_DUSK_ARG(u32 i_itemGiveTag = 0) + IF_DUSK_ARG(u8 i_itemOriginalNo = 0xFF)); inline fpc_ProcID fopAcM_Create(s16 i_procName, createFunc i_createFunc, void* params) { return fpcM_Create(i_procName, i_createFunc,params); diff --git a/include/global.h b/include/global.h index 4a86f0678f..c16020936e 100644 --- a/include/global.h +++ b/include/global.h @@ -123,6 +123,14 @@ inline int __builtin_clz(unsigned int v) { #endif #define DUSK_GAME_EXTERN extern DUSK_GAME_DATA +#if defined(_MSC_VER) +#define DUSK_NOINLINE __declspec(noinline) +#elif defined(__GNUC__) +#define DUSK_NOINLINE __attribute__((noinline)) +#else +#define DUSK_NOINLINE +#endif + #define FAST_DIV(x, n) (x >> (n / 2)) #define SQUARE(x) ((x) * (x)) @@ -259,13 +267,19 @@ using std::isnan; #if TARGET_PC && defined(DUSK_BUILDING_GAME) #include "dusk/mods/item.hpp" #define DUSK_ITEM_CHECK(name, item_no, giver) \ - (item_no) = ::dusk::mods::item_check(name, (item_no), giver) + (item_no) = ::dusk::mods::item_check_commit(name, (item_no), giver).itemNo #define DUSK_ITEM_CHECK_EXPR(name, item_no, giver) \ + (::dusk::mods::item_check_commit(name, (item_no), giver).itemNo) +#define DUSK_ITEM_CHECK_PREVIEW(name, item_no, giver) \ + (item_no) = ::dusk::mods::item_check(name, (item_no), giver) +#define DUSK_ITEM_CHECK_PREVIEW_EXPR(name, item_no, giver) \ (::dusk::mods::item_check(name, (item_no), giver)) #define DUSK_GIVE_TAG(name) IF_DUSK_ARG(::dusk::mods::item_give_tag(name)) #else #define DUSK_ITEM_CHECK(name, item_no, giver) #define DUSK_ITEM_CHECK_EXPR(name, item_no, giver) (item_no) +#define DUSK_ITEM_CHECK_PREVIEW(name, item_no, giver) +#define DUSK_ITEM_CHECK_PREVIEW_EXPR(name, item_no, giver) (item_no) #define DUSK_GIVE_TAG(name) #endif diff --git a/include/m_Do/m_Do_dvd_thread.h b/include/m_Do/m_Do_dvd_thread.h index dcb3f2fc65..ebb4253838 100644 --- a/include/m_Do/m_Do_dvd_thread.h +++ b/include/m_Do/m_Do_dvd_thread.h @@ -68,7 +68,7 @@ public: JKRMemArchive* getArchive() const { return mArchive; } JKRHeap* getHeap() const { return mHeap; } -private: +// private: /* 0x14 */ u8 mMountDirection; /* 0x18 */ s32 mEntryNumber; /* 0x1C */ JKRMemArchive* mArchive; diff --git a/libs/JSystem/include/JSystem/J3DGraphLoader/J3DModelLoader.h b/libs/JSystem/include/JSystem/J3DGraphLoader/J3DModelLoader.h index 05fc99785b..a0711fd796 100644 --- a/libs/JSystem/include/JSystem/J3DGraphLoader/J3DModelLoader.h +++ b/libs/JSystem/include/JSystem/J3DGraphLoader/J3DModelLoader.h @@ -9,6 +9,7 @@ class J3DModelData; class J3DMaterialTable; struct J3DModelHierarchy; +class J3DVertexData; #if TARGET_PC #define OFFSET_PTR_V0 BE(u32) diff --git a/mods/basic_cosmetics_mod/CMakeLists.txt b/mods/basic_cosmetics_mod/CMakeLists.txt new file mode 100644 index 0000000000..f00540864b --- /dev/null +++ b/mods/basic_cosmetics_mod/CMakeLists.txt @@ -0,0 +1,35 @@ +cmake_minimum_required(VERSION 3.25) +project(basic_cosmetics_mod CXX) + +if (CMAKE_SOURCE_DIR STREQUAL CMAKE_CURRENT_SOURCE_DIR) + set(DUSK_DIR "${CMAKE_CURRENT_SOURCE_DIR}/../.." CACHE PATH "Path to dusk source root") + option(DUSK_MOD_USE_FULL_TREE "Use full build instead of the minimal mod SDK" OFF) + set(CMAKE_POSITION_INDEPENDENT_CODE ON) + if (DUSK_MOD_USE_FULL_TREE) + add_subdirectory("${DUSK_DIR}" dusk EXCLUDE_FROM_ALL) + else () + add_subdirectory("${DUSK_DIR}/sdk" dusk-sdk EXCLUDE_FROM_ALL) + endif () +endif () + +include(FetchContent) + +message(STATUS "basic_cosmetics_mod: Fetching xxhash") +FetchContent_Declare( + xxhash + GIT_REPOSITORY https://github.com/Cyan4973/xxHash.git + GIT_TAG v0.8.3 +) +FetchContent_MakeAvailable(xxhash) + +set(COSMETIC_SOURCES src/color_utils.cpp src/midna_hair_color.cpp src/texture_utils.cpp src/hooks.cpp) + +add_mod(basic_cosmetics_mod + FEATURES game fmt + SOURCES src/mod.cpp ${COSMETIC_SOURCES} + MOD_JSON mod.json + RES_DIR res + BUNDLE +) + +target_link_libraries(basic_cosmetics_mod PRIVATE xxHash::xxhash) diff --git a/mods/basic_cosmetics_mod/mod.json b/mods/basic_cosmetics_mod/mod.json new file mode 100644 index 0000000000..d6c258bfe9 --- /dev/null +++ b/mods/basic_cosmetics_mod/mod.json @@ -0,0 +1,7 @@ +{ + "id": "dev.twilitrealm.basic_cosmetics", + "name": "Basic Cosmetics", + "version": "1.0.0", + "author": "Twilit Realm", + "description": "Change Basic Cosmetic Colors" +} diff --git a/mods/basic_cosmetics_mod/res/.gitkeep b/mods/basic_cosmetics_mod/res/.gitkeep new file mode 100644 index 0000000000..e69de29bb2 diff --git a/mods/basic_cosmetics_mod/src/color_utils.cpp b/mods/basic_cosmetics_mod/src/color_utils.cpp new file mode 100644 index 0000000000..d1dc2eb096 --- /dev/null +++ b/mods/basic_cosmetics_mod/src/color_utils.cpp @@ -0,0 +1,88 @@ +#include "color_utils.hpp" + +uint8_t desaturate_rgb_565(uint16_t rgb565Val) { + const uint32_t r = (rgb565Val & 0xf800) >> 11; + const uint32_t g = (rgb565Val & 0x7e0) >> 5; + const uint32_t b = rgb565Val & 0x1f; + + // Here we are doing a quicker (0.22 * r + 0.72 * g + 0.06 * b) which + // uses multiplies and shifts rather than division. + const uint32_t combined = 30480413 * r + 49085341 * g + 8312839 * b; + uint8_t shifted = (combined >> 24) & 0xff; + + // Check if should round up shifted value. + if (shifted < 0xff && combined & 0x00800000) { + shifted += 1; + } + + return shifted; +} + +uint16_t blend_overlay_rgb_565(uint8_t grayVal, GXColor color) { + uint32_t rTimes255, gTimes255, bTimes255; + + if (grayVal <= 0x7f) { + const uint32_t grayTimesTwo = 2 * grayVal; + + rTimes255 = grayTimesTwo * color.r; + gTimes255 = grayTimesTwo * color.g; + bTimes255 = grayTimesTwo * color.b; + } else { + const uint32_t multiplier = 2 * (255 - grayVal); + + rTimes255 = 255 * 255 - multiplier * (255 - color.r); + gTimes255 = 255 * 255 - multiplier * (255 - color.g); + bTimes255 = 255 * 255 - multiplier * (255 - color.b); + } + + // Divide each by 255 + const uint32_t r = (rTimes255 + 1 + (rTimes255 >> 8)) >> 8; + const uint32_t g = (gTimes255 + 1 + (gTimes255 >> 8)) >> 8; + const uint32_t b = (bTimes255 + 1 + (bTimes255 >> 8)) >> 8; + + return ((r & 0xf8) << 8) | ((g & 0xfc) << 3) | ((b & 0xf8) >> 3); +} + +// Helper function to perform overlay blending on a single 8-bit color channel +uint8_t blend_overlay_channel(uint8_t base, uint8_t blend) { + if (base < 128) { + return static_cast((2 * base * blend) / 255); + } + + return static_cast(255 - (2 * (255 - base) * (255 - blend)) / 255); +} + +bool is_valid_hex_color_str(std::string_view hexStr) { + return hexStr.find_first_not_of("0123456789ABCDEFabcdef") == std::string_view::npos && + hexStr.length() == 6; +} + +GXColor hex_color_str_to_gx_color(const std::string& hexColorStr) { + u8 r = std::stoi(hexColorStr.substr(0, 2), nullptr, 16); + u8 g = std::stoi(hexColorStr.substr(2, 2), nullptr, 16); + u8 b = std::stoi(hexColorStr.substr(4, 2), nullptr, 16); + return GXColor{r, g, b}; +} + +static f32 rainbowPhaseAngle = 0.f; + +GXColor get_rainbow_rgb(f32 amplitude) { + f32 phase_rad = rainbowPhaseAngle * M_PI / 180.0f; + + u8 r_val = (u8)(amplitude * (sinf(phase_rad) + 1.0f) + 0.5f); + u8 g_val = (u8)(amplitude * (sinf(phase_rad + 2.0f * M_PI / 3.0f) + 1.0f) + 0.5f); + u8 b_val = (u8)(amplitude * (sinf(phase_rad + 4.0f * M_PI / 3.0f) + 1.0f)); + GXColor rgbColor; + rgbColor.r = r_val; + rgbColor.g = g_val; + rgbColor.b = b_val; + rgbColor.a = 0xff; + return rgbColor; +} + +void update_rainbow_rgb(f32 increment) { + rainbowPhaseAngle += increment; + if (rainbowPhaseAngle >= 360.0f) { + rainbowPhaseAngle -= 360.0f; + } +} \ No newline at end of file diff --git a/mods/basic_cosmetics_mod/src/color_utils.hpp b/mods/basic_cosmetics_mod/src/color_utils.hpp new file mode 100644 index 0000000000..94e1ce62a8 --- /dev/null +++ b/mods/basic_cosmetics_mod/src/color_utils.hpp @@ -0,0 +1,30 @@ +#pragma once + +/** + * File originally copied from console TPR with permission from isaac + * https://github.com/zsrtp/libtp_rel/blob/master/include/util/color_utils.h + */ + +#include + +#include +#include + +// Desaturates an RGB565 color to a u8 gray value (0xFF being white and 0x00 +// being black). +uint8_t desaturate_rgb_565(uint16_t rgb565Val); + +// Performs an "Overlay" blend of a u8 gray value and a pointer to a u8 +// array of {r,g,b}. Returns the result as an RGB565. +uint16_t blend_overlay_rgb_565(uint8_t grayVal, GXColor color); + +// Perform overlay blending on a single 8-bit color channel +uint8_t blend_overlay_channel(uint8_t base, uint8_t blend); + +bool is_valid_hex_color_str(std::string_view hexStr); + +GXColor hex_color_str_to_gx_color(const std::string& hexColorStr); + +GXColor get_rainbow_rgb(f32 amplitude); + +void update_rainbow_rgb(f32 increment); diff --git a/mods/basic_cosmetics_mod/src/hooks.cpp b/mods/basic_cosmetics_mod/src/hooks.cpp new file mode 100644 index 0000000000..e90e76d8b3 --- /dev/null +++ b/mods/basic_cosmetics_mod/src/hooks.cpp @@ -0,0 +1,731 @@ +#include "hooks.hpp" + +#include "color_utils.hpp" +#include "midna_hair_color.hpp" +#include "mod.hpp" +#include "types.h" + +#include "mods/svc/hook.hpp" +#include "mods/svc/log.hpp" + +#include "SSystem/SComponent/c_phase.h" +#include "d/actor/d_a_alink.h" +#include "d/actor/d_a_midna.h" +#include "d/d_a_item_static.h" +#include "d/d_bright_check.h" +#include "d/d_file_sel_info.h" +#include "d/d_file_select.h" +#include "d/d_kankyo.h" +#include "d/d_kantera_icon_meter.h" +#include "d/d_menu_collect.h" +#include "d/d_menu_fishing.h" +#include "d/d_menu_fmap2D.h" +#include "d/d_menu_insect.h" +#include "d/d_menu_letter.h" +#include "d/d_menu_option.h" +#include "d/d_menu_ring.h" +#include "d/d_menu_save.h" +#include "d/d_menu_skill.h" +#include "d/d_meter2.h" +#include "d/d_meter2_draw.h" +#include "d/d_meter2_info.h" +#include "d/d_meter_button.h" +#include "d/d_meter_hakusha.h" +#include "d/d_msg_object.h" +#include "d/d_msg_out_font.h" +#include "d/d_msg_scrn_base.h" +#include "d/d_pane_class.h" + +// Lantern ambience color +DEFINE_HOOK(&dKy_WolfEyeLight_set, WolfEyeLightSet); +void wolf_eye_light_set_post(ModContext*, void*, void*, void*) { + auto maybeLanternColor = get_config_var_color(get_cvars().lanternGlowColor, true); + if (maybeLanternColor.has_value()) { + auto lanternColor = maybeLanternColor.value(); + + dScnKy_env_light_c* kankyo = dKy_getEnvlight(); + kankyo->field_0x0c18[0].mColor.r = lanternColor.r; + kankyo->field_0x0c18[0].mColor.g = lanternColor.g; + kankyo->field_0x0c18[0].mColor.b = lanternColor.b; + } +} + +// Lantern Sphere color +DEFINE_HOOK(&daAlink_c::preKandelaarDraw, PreKandelaarDraw); +void pre_kandelaar_draw_post(ModContext*, void*, void*, void*) { + auto maybeLanternColor = get_config_var_color(get_cvars().lanternGlowColor, true); + if (maybeLanternColor.has_value()) { + auto lanternColor = maybeLanternColor.value(); + + J3DMaterial* mat_p = daAlink_getAlinkActorClass() + ->mpKanteraGlowModel->getModelData() + ->getMaterialNodePointer(0); + + J3DGXColorS10 color; + color.r = lanternColor.r; + color.g = lanternColor.g; + color.b = lanternColor.b; + color.a = 255; + mat_p->setTevColor(1, &color); + + color.r = lanternColor.r; + color.g = lanternColor.g; + color.b = lanternColor.b; + mat_p->setTevColor(2, &color); + } +} + +// Main Lantern Meter Color +DEFINE_HOOK(&CPaneMgr::setBlackWhite, CPaneMgrSetBlackWhite); +HookAction cpane_mgr_set_black_white_pre(ModContext*, void* args, void*, void*) { + // Check for magic meter + auto pane = mods::arg(args, 0); + if (dMeter2Info_getMeterClass() == NULL || + pane != dMeter2Info_getMeterClass()->getMeterDrawPtr()->mpMagicMeter) + { + return HOOK_CONTINUE; + } + + // If magic meter, check to see we're setting lantern colors + auto& black = mods::arg_ref(args, 1); + auto& white = mods::arg_ref(args, 2); + if (black != JUtility::TColor(255, 255, 140, 255) && + white != JUtility::TColor(230, 170, 0, 255)) + { + return HOOK_CONTINUE; + } + + auto maybeLanternColor = get_config_var_color(get_cvars().lanternGlowColor, true); + if (maybeLanternColor.has_value()) { + auto lanternColor = maybeLanternColor.value(); + black = JUtility::TColor(lanternColor.r, lanternColor.g, lanternColor.b, 255); + white = JUtility::TColor(lanternColor.r, lanternColor.g, lanternColor.b, 255); + } + + return HOOK_CONTINUE; +} + +// Lantern Icon Meter Color +DEFINE_HOOK(&dKantera_icon_c::setNowGauge, KanteraIconSetNowGauge); +void kantera_icon_set_now_gauge_post(ModContext*, void* args, void*, void*) { + auto maybeLanternColor = get_config_var_color(get_cvars().lanternGlowColor, true); + if (maybeLanternColor.has_value()) { + auto lanternColor = maybeLanternColor.value(); + + auto kanteraIcon = mods::arg(args, 0); + kanteraIcon->mpGauge->setBlackWhite( + JUtility::TColor(lanternColor.r, lanternColor.g, lanternColor.b, 255), + JUtility::TColor(lanternColor.r, lanternColor.g, lanternColor.b, 255)); + } +} + +// Light Sword Effect Color +DEFINE_HOOK(&daAlink_c::setLightningSwordEffect, SetLightningSwordEffect); +void set_lightning_sword_effect_post(ModContext*, void* args, void*, void*) { + auto maybeGlowColor = get_config_var_color(get_cvars().lightSwordGlowColor, true); + if (maybeGlowColor.has_value()) { + auto glowColor = maybeGlowColor.value(); + + auto link = mods::arg(args, 0); + // Check copied from inside the hooked function + if (link->mEquipItem == 0x103 && link->checkNoResetFlg3(daPy_py_c::FLG3_UNK_100000)) { + for (size_t i = 0; i < 3; i++) { + auto emitter = dComIfGp_particle_getEmitter(link->field_0x327c[i]); + if (emitter != NULL) { + emitter->setGlobalEnvColor(glowColor.r, glowColor.g, glowColor.b); + emitter->setGlobalPrmColor(glowColor.r, glowColor.g, glowColor.b); + } + } + } + } +} + +void recolor_ui_button(ConfigVarHandle option, u64 tag, J2DScreen* screen) { + auto buttonColorStr = get_str_option(option, ""); + if (is_valid_hex_color_str(buttonColorStr)) { + auto color = hex_color_str_to_gx_color(buttonColorStr); + auto element = static_cast(screen->search(tag)); + if (element != nullptr) { + element->setBlackWhite( + JUtility::TColor(0, 0, 0, 0), JUtility::TColor(color.r, color.g, color.b, 0xFF)); + } + } +} + +// Main gameplay UI. Top left hearts and top right buttons +DEFINE_HOOK(&dMeter2Draw_c::init, dMeter2Init); +void d_meter_2_init_post(ModContext*, void* args, void*, void*) { + auto dMeter2Draw = mods::arg(args, 0); + auto screen = dMeter2Draw->getMainScreenPtr(); + + // Heart tags on main UI + static constexpr std::array kHeartTags = {MULTI_CHAR('hear_00'), MULTI_CHAR('hear_01'), + MULTI_CHAR('hear_02'), MULTI_CHAR('hear_03'), MULTI_CHAR('hear_04'), MULTI_CHAR('hear_05'), + MULTI_CHAR('hear_06'), MULTI_CHAR('hear_07'), MULTI_CHAR('hear_08'), MULTI_CHAR('hear_09'), + MULTI_CHAR('hear_10'), MULTI_CHAR('hear_11'), MULTI_CHAR('hear_12'), MULTI_CHAR('hear_13'), + MULTI_CHAR('hear_14'), MULTI_CHAR('hear_15'), MULTI_CHAR('hear_16'), MULTI_CHAR('hear_17'), + MULTI_CHAR('hear_18'), MULTI_CHAR('hear_19'), MULTI_CHAR('bigh_00'), MULTI_CHAR('bigh_01'), + MULTI_CHAR('bigh_02'), MULTI_CHAR('bigh_03')}; + + auto maybeHeartColor = get_config_var_color(get_cvars().heartColor); + if (maybeHeartColor.has_value()) { + auto heartColor = maybeHeartColor.value(); + for (auto tag : kHeartTags) { + auto element = static_cast(screen->search(tag)); + if (element != nullptr) { + element->setBlackWhite(heartColor, JUtility::TColor(200, 200, 200, 255)); + } + } + } + + recolor_ui_button(get_cvars().aButtonColor, MULTI_CHAR('a_btn'), screen); + recolor_ui_button(get_cvars().bButtonColor, MULTI_CHAR('b_btn'), screen); + recolor_ui_button(get_cvars().xButtonColor, MULTI_CHAR('x_btn'), screen); + recolor_ui_button(get_cvars().yButtonColor, MULTI_CHAR('y_btn'), screen); + recolor_ui_button(get_cvars().zButtonColor, MULTI_CHAR('zbtn'), screen); +} + +// Hearts on the file select screen +DEFINE_HOOK(&dFile_info_c::setHeartCnt, FileInfoSetHeartCount); +void file_info_set_heart_count_post(ModContext*, void* args, void*, void*) { + auto fileInfo = mods::arg(args, 0); + + // Heart tags on file select + static constexpr std::array kFileSelectHeartTags{ + MULTI_CHAR('hear_20'), + MULTI_CHAR('hear_21'), + MULTI_CHAR('hear_22'), + MULTI_CHAR('hear_23'), + MULTI_CHAR('hear_24'), + MULTI_CHAR('hear_25'), + MULTI_CHAR('hear_26'), + MULTI_CHAR('hear_27'), + MULTI_CHAR('hear_28'), + MULTI_CHAR('hear_29'), + MULTI_CHAR('hear_30'), + MULTI_CHAR('hear_31'), + MULTI_CHAR('hear_32'), + MULTI_CHAR('hear_33'), + MULTI_CHAR('hear_34'), + MULTI_CHAR('hear_35'), + MULTI_CHAR('hear_36'), + MULTI_CHAR('hear_37'), + MULTI_CHAR('hear_38'), + MULTI_CHAR('hear_39'), + }; + + auto maybeHeartColor = get_config_var_color(get_cvars().heartColor); + if (maybeHeartColor.has_value()) { + auto heartColor = maybeHeartColor.value(); + for (auto tag : kFileSelectHeartTags) { + auto element = static_cast(fileInfo->mFileInfo.Scr->search(tag)); + if (element != nullptr) { + element->setBlackWhite(heartColor, JUtility::TColor(200, 200, 200, 255)); + } + } + } +} + +// Buttons that appear contextually at the bottom of the screen during gameplay +// (Are X, Y ever used there?) +DEFINE_HOOK(&dMeterButton_c::screenInitButton, ScreenInitButton); +void screen_init_button_post(ModContext*, void* args, void*, void*) { + auto meterButton = mods::arg(args, 0); + auto screen = meterButton->mpButtonScreen; + + recolor_ui_button(get_cvars().aButtonColor, MULTI_CHAR('a_btn1'), screen); + recolor_ui_button(get_cvars().bButtonColor, MULTI_CHAR('b_btn'), screen); + recolor_ui_button(get_cvars().xButtonColor, MULTI_CHAR('x_btn'), screen); + recolor_ui_button(get_cvars().yButtonColor, MULTI_CHAR('y_btn'), screen); + recolor_ui_button(get_cvars().zButtonColor, MULTI_CHAR('zbtn'), screen); +} + +// A and B buttons when saving a file +DEFINE_HOOK(&dMenu_save_c::screenSet, MenuSaveScreenSet); +void menu_save_screen_set_post(ModContext*, void* args, void*, void*) { + auto menuSave = mods::arg(args, 0); + auto screen = menuSave->mSaveSel.Scr; + + recolor_ui_button(get_cvars().aButtonColor, MULTI_CHAR('wabtn'), screen); + recolor_ui_button(get_cvars().bButtonColor, MULTI_CHAR('wbbtn'), screen); +} + +// A and B buttons when selecting a file +DEFINE_HOOK(&dFile_select_c::screenSet, FileSelectScreenSet); +void file_select_screen_set_post(ModContext*, void* args, void*, void*) { + auto fileSelect = mods::arg(args, 0); + auto screen = fileSelect->fileSel.Scr; + + recolor_ui_button(get_cvars().aButtonColor, MULTI_CHAR('wabtn'), screen); + recolor_ui_button(get_cvars().bButtonColor, MULTI_CHAR('wbbtn'), screen); +} + +// A button on brightness check screen +DEFINE_HOOK(&dBrightCheck_c::screenSet, BrightCheckScreenSet); +void bright_check_screen_set_post(ModContext*, void* args, void*, void*) { + auto brightCheck = mods::arg(args, 0); + auto screen = brightCheck->mBrightCheck.Scr; + + recolor_ui_button(get_cvars().aButtonColor, MULTI_CHAR('a_btn1'), screen); +} + +// X and Y buttons on the item wheel screen +DEFINE_HOOK(&dMenu_Ring_c::_create, MenuRingCreate); +void menu_ring_create_post(ModContext*, void* args, void*, void*) { + auto menuRing = mods::arg(args, 0); + auto screen = menuRing->mpScreen; + + recolor_ui_button(get_cvars().xButtonColor, MULTI_CHAR('xbtn'), screen); + recolor_ui_button(get_cvars().yButtonColor, MULTI_CHAR('ybtn'), screen); +} + +// A and B buttons on the main pause screen +DEFINE_HOOK(&dMenu_Collect2D_c::_create, MenuCollect2DCreate); +void menu_collect_2D_create_post(ModContext*, void* args, void*, void*) { + auto menuCollect2D = mods::arg(args, 0); + auto screen = menuCollect2D->mpScreenIcon; + + recolor_ui_button(get_cvars().aButtonColor, MULTI_CHAR('a_btn'), screen); + recolor_ui_button(get_cvars().bButtonColor, MULTI_CHAR('b_btn'), screen); +} + +// A and B buttons on the fishing journal screen +DEFINE_HOOK(&dMenu_Fishing_c::screenSetDoIcon, MenuFishingScreenSetDoIcon); +void menu_fishing_screen_set_do_icon_post(ModContext*, void* args, void*, void*) { + auto menuFishing = mods::arg(args, 0); + auto screen = menuFishing->mpIconScreen; + + recolor_ui_button(get_cvars().aButtonColor, MULTI_CHAR('a_btn'), screen); + recolor_ui_button(get_cvars().bButtonColor, MULTI_CHAR('b_btn'), screen); +} + +// A and B buttons on the insect collection screen +DEFINE_HOOK(&dMenu_Insect_c::screenSetDoIcon, MenuInsectScreenSetDoIcon); +void menu_insect_screen_set_do_icon_post(ModContext*, void* args, void*, void*) { + auto menuInsect = mods::arg(args, 0); + auto screen = menuInsect->mpIconScreen; + + recolor_ui_button(get_cvars().aButtonColor, MULTI_CHAR('a_btn'), screen); + recolor_ui_button(get_cvars().bButtonColor, MULTI_CHAR('b_btn'), screen); +} + +// A and B buttons on the letters screen +DEFINE_HOOK(&dMenu_Letter_c::screenSetDoIcon, MenuLetterScreenSetDoIcon); +void menu_letter_screen_set_do_icon_post(ModContext*, void* args, void*, void*) { + auto menuLetter = mods::arg(args, 0); + auto screen = menuLetter->mpIconScreen; + + recolor_ui_button(get_cvars().aButtonColor, MULTI_CHAR('a_btn'), screen); + recolor_ui_button(get_cvars().bButtonColor, MULTI_CHAR('b_btn'), screen); +} + +// A, B, and Z buttons on option screen +DEFINE_HOOK(&dMenu_Option_c::_create, MenuOptionCreate); +void menu_option_create_post(ModContext*, void* args, void*, void*) { + auto menuOption = mods::arg(args, 0); + auto screen = menuOption->mpScreenIcon; + auto backScreen = menuOption->mpBackScreen; + auto tvScreen = menuOption->mpTVScreen; + + recolor_ui_button(get_cvars().aButtonColor, MULTI_CHAR('a_btn'), screen); + recolor_ui_button(get_cvars().bButtonColor, MULTI_CHAR('b_btn'), screen); + recolor_ui_button(get_cvars().zButtonColor, MULTI_CHAR('g_zbtn'), backScreen); + + // A Button on option's brightness check screen + recolor_ui_button(get_cvars().aButtonColor, MULTI_CHAR('a_btn1'), tvScreen); +} + +// A and B buttons on the hidden skills screen +DEFINE_HOOK(&dMenu_Skill_c::screenSetDoIcon, MenuSkillScreenSetDoIcon); +void menu_skill_screen_set_do_icon_post(ModContext*, void* args, void*, void*) { + auto menuSkill = mods::arg(args, 0); + auto screen = menuSkill->mpIconScreen; + + recolor_ui_button(get_cvars().aButtonColor, MULTI_CHAR('a_btn'), screen); + recolor_ui_button(get_cvars().bButtonColor, MULTI_CHAR('b_btn'), screen); +} + +// A, B, and Z buttons on the map screen +DEFINE_HOOK(&dMenu_Fmap_c::_create, MenuFMapCreate); +void menu_fmap_create_post(ModContext*, void* args, void*, void*) { + auto menuFMap = mods::arg(args, 0); + auto screen = menuFMap->mpDraw2DTop->mpTitleScreen; + + recolor_ui_button(get_cvars().aButtonColor, MULTI_CHAR('a_btn'), screen); + recolor_ui_button(get_cvars().bButtonColor, MULTI_CHAR('b_btn1'), screen); + recolor_ui_button(get_cvars().zButtonColor, MULTI_CHAR('zbtn'), screen); +} + +// A button on the howling screen +DEFINE_HOOK(&dMsgObject_c::talkStartInit, MsgObjectTalkStartInit); +void msg_object_talk_start_init_post(ModContext*, void* args, void*, void*) { + auto msgObject = mods::arg(args, 0); + + // If textbox kind is howling + if (msgObject->mFukiKind == 17) { + auto screen = msgObject->mpScrnDraw->mpScreen; + + recolor_ui_button(get_cvars().aButtonColor, MULTI_CHAR('abtn'), screen); + } +} + +// A button when on Epona +DEFINE_HOOK(&dMeterHakusha_c::_create, MeterHakushaCreate); +void meter_hakusha_create_post(ModContext*, void* args, void*, void*) { + auto meterHakusha = mods::arg(args, 0); + auto screen = meterHakusha->mpButtonScreen; + + recolor_ui_button(get_cvars().aButtonColor, MULTI_CHAR('a_btn1'), screen); +} + +// A, B, X, and Y button icons in text +DEFINE_HOOK(&COutFont_c::createPane, OutFontCreatePane); +void out_font_create_pane_post(ModContext*, void* args, void*, void*) { + auto outFont = mods::arg(args, 0); + auto paneArr = outFont->mpPane; + + auto maybeAButtonColor = get_config_var_color(get_cvars().aButtonColor); + if (maybeAButtonColor.has_value()) { + auto aButtonColor = maybeAButtonColor.value(); + paneArr[0]->setBlackWhite(JUtility::TColor(255, 255, 255, 0), + JUtility::TColor(aButtonColor.r, aButtonColor.g, aButtonColor.b, 255)); + } + + auto maybeBButtonColor = get_config_var_color(get_cvars().bButtonColor); + if (maybeBButtonColor.has_value()) { + auto bButtonColor = maybeBButtonColor.value(); + paneArr[1]->setBlackWhite(JUtility::TColor(255, 255, 255, 0), + JUtility::TColor(bButtonColor.r, bButtonColor.g, bButtonColor.b, 255)); + } + + // Condition copied from hooked function + auto xyBlack = JUtility::TColor(255, 255, 255, 0); + if (outFont->field_0x242 == 1) { + xyBlack = JUtility::TColor(0, 0, 0, 0); + } + + auto maybeXButtonColor = get_config_var_color(get_cvars().xButtonColor); + if (maybeXButtonColor.has_value()) { + auto xButtonColor = maybeXButtonColor.value(); + paneArr[5]->setBlackWhite( + xyBlack, JUtility::TColor(xButtonColor.r, xButtonColor.g, xButtonColor.b, 255)); + } + + auto maybeYButtonColor = get_config_var_color(get_cvars().yButtonColor); + if (maybeYButtonColor.has_value()) { + auto yButtonColor = maybeYButtonColor.value(); + paneArr[6]->setBlackWhite( + xyBlack, JUtility::TColor(yButtonColor.r, yButtonColor.g, yButtonColor.b, 255)); + } +} + +// Heart icon in text +DEFINE_HOOK(&COutFontSet_c::drawFont, OutFontSetDrawFont); +void out_font_set_draw_font_post(ModContext*, void* args, void*, void*) { + auto outFontSet = mods::arg(args, 0); + + auto maybeHeartColor = get_config_var_color(get_cvars().heartColor); + if (maybeHeartColor.has_value()) { + auto heartColor = maybeHeartColor.value(); + u32 heartColor_u32 = heartColor.r << 24 | heartColor.g << 16 | heartColor.b << 8 | 0xFF; + if (outFontSet->getType() == 0x1B) { // Heart icon type + outFontSet->mColor = heartColor_u32; + } + } +} + +// Heart Drop/Piece of Heart/Heart Container model color +DEFINE_HOOK(&daItemBase_c::CreateItemHeap, ItemBaseCreateItemHeap); +void item_base_create_item_heap_post(ModContext*, void* args, void*, void*) { + auto itemBase = mods::arg(args, 0); + if (itemBase == NULL) { + return; + } + auto itemNo = itemBase->m_itemNo; + if (itemNo == dItemNo_HEART_e || itemNo == dItemNo_UTAWA_HEART_e || + itemNo == dItemNo_KAKERA_HEART_e) + { + auto maybeHeartColor = get_config_var_color(get_cvars().heartColor); + if (maybeHeartColor.has_value()) { + auto heartColor = maybeHeartColor.value(); + auto heartColorS10 = GXColorS10(heartColor.r, heartColor.g, heartColor.b, heartColor.a); + + // Edit inner heart material color for Piece of Heart / Heart Container + if (itemNo == dItemNo_UTAWA_HEART_e || itemNo == dItemNo_KAKERA_HEART_e) { + *itemBase->mpModel->getModelData()->getMaterialNodePointer(3)->getTevKColor(1) = + heartColor; + *itemBase->mpModel->getModelData()->getMaterialNodePointer(3)->getTevColor(1) = + heartColorS10; + } + + const u8 heartColorRGB[3] = {heartColor.r, heartColor.g, heartColor.b}; + u8** cRegTable = + reinterpret_cast(&itemBase->mpBrkAnm->getBrkAnm()->mAnmCRegDataR); + u8** kRegTable = + reinterpret_cast(&itemBase->mpBrkAnm->getBrkAnm()->mAnmKRegDataR); + + for (int i = 0; i < 3; i++) { + u8* cReg = cRegTable[i]; + u8* kReg = kRegTable[i]; + + auto curColor = heartColorRGB[i]; + + // Set heart drop inner heart color + cReg[0x3] = curColor; + cReg[0xB] = curColor; + + // Set heart drop outer heart color + kReg[0x3] = curColor; + kReg[0xB] = curColor; + + if (itemNo == dItemNo_KAKERA_HEART_e) { + cReg[0x13] = curColor; + cReg[0x1B] = curColor; + kReg[0x13] = curColor; + kReg[0x1B] = curColor; + } + if (itemNo == dItemNo_UTAWA_HEART_e) { + cReg[0x13] = curColor; + kReg[0x13] = curColor; + kReg[0x1B] = curColor; + kReg[0x23] = curColor; + kReg[0x2B] = curColor; + } + } + } + } +} + +// Midna Hair Color +DEFINE_HOOK(&daMidna_c::create, MidnaCreate); +void midna_create_post(ModContext*, void* args, void* retval, void*) { + auto step = reinterpret_cast(retval); + // Don't set colors if midna isn't done loading + if (*step != cPhs_COMPLEATE_e) { + return; + } + + auto midna = mods::arg(args, 0); + midna->field_0x6e0 = g_currentMidnaHairColors.normalColor; + if (dKy_darkworld_check()) { + midna->field_0x6e8 = g_currentMidnaHairColors.normalKColor; + midna->field_0x6ec = g_currentMidnaHairColors.normalKColor2; + } else { + midna->field_0x6e8 = g_currentMidnaHairColors.lNormalKColor; + midna->field_0x6ec = g_currentMidnaHairColors.lNormalKColor2; + } +} + +// Override Midna Hair Color Part 2 +DEFINE_HOOK(&daMidna_c::setBodyPartMatrix, MidnaSetBodyPartMatrix); + +static GXColorS10 midnaField0x6e0{}; +static GXColor midnaField0x6e8{}; +static GXColor midnaField0x6ec{}; + +// Copy the original values before setBodyPartMatrix runs +HookAction midna_set_body_part_matrix_pre(ModContext*, void* args, void* retval, void* userdata) { + auto midna = mods::arg(args, 0); + + midnaField0x6e0 = midna->field_0x6e0; + midnaField0x6e8 = midna->field_0x6e8; + midnaField0x6ec = midna->field_0x6ec; + + return HOOK_CONTINUE; +} + +void midna_set_body_part_matrix_post(ModContext*, void* args, void* retval, void* userdata) { + auto midna = mods::arg(args, 0); + if (midna->mpHairhandBmd != NULL) { + // Restore the original values from before setBodyPartMatrix ran (this undoes the chase) + midna->field_0x6e0 = midnaField0x6e0; + midna->field_0x6e8 = midnaField0x6e8; + midna->field_0x6ec = midnaField0x6ec; + + // Statement copied from inside function to determine colors + bool bigColors = + midna->checkStateFlg0(daMidna_c::FLG0_UNK_10000000) || + midna->mBckHeap[2].getIdx() == daMidna_c::m_anmDataTable[daMidna_c::ANM_HAIR].mResID || + midna->mBckHeap[2].getIdx() == + daMidna_c::m_anmDataTable[daMidna_c::ANM_S_TAKES].mResID || + midna->mBckHeap[2].getIdx() == + daMidna_c::m_anmDataTable[daMidna_c::ANM_S_WAITS].mResID || + midna->mBckHeap[2].getIdx() == + daMidna_c::m_anmDataTable[daMidna_c::ANM_S_PACKAWAY].mResID || + midna->mBckHeap[2].getIdx() == + daMidna_c::m_anmDataTable[daMidna_c::ANM_GRABST].mResID || + midna->checkEndResetStateFlg0(daMidna_c::ERFLG0_UNK_40) || + dComIfGp_checkPlayerStatus1(0, 0x800000); + + GXColorS10 color{}; + GXColor kcolor1{}; + GXColor kcolor2{}; + + // Set our own colors + if (bigColors) { + kcolor1 = g_currentMidnaHairColors.bigKColor; + if (dKy_darkworld_check()) { + color = g_currentMidnaHairColors.bigColor; + kcolor2 = g_currentMidnaHairColors.normalKColor2; + } else { + color = g_currentMidnaHairColors.lBigColor; + kcolor2 = g_currentMidnaHairColors.lBigKColor2; + } + } else { + color = g_currentMidnaHairColors.normalColor; + if (dKy_darkworld_check()) { + kcolor1 = g_currentMidnaHairColors.normalKColor; + kcolor2 = g_currentMidnaHairColors.normalKColor2; + } else { + kcolor1 = g_currentMidnaHairColors.lNormalKColor; + kcolor2 = g_currentMidnaHairColors.lNormalKColor2; + } + } + + // Reapply the chase that happens in the function + cLib_chaseS(&midna->field_0x6e0.r, color.r, 10); + cLib_chaseS(&midna->field_0x6e0.g, color.g, 10); + cLib_chaseS(&midna->field_0x6e0.b, color.b, 10); + cLib_chaseUC(&midna->field_0x6e8.r, kcolor1.r, 10); + cLib_chaseUC(&midna->field_0x6e8.g, kcolor1.g, 10); + cLib_chaseUC(&midna->field_0x6e8.b, kcolor1.b, 10); + cLib_chaseUC(&midna->field_0x6ec.r, kcolor2.r, 10); + cLib_chaseUC(&midna->field_0x6ec.g, kcolor2.g, 10); + cLib_chaseUC(&midna->field_0x6ec.b, kcolor2.b, 10); + } +} + +// Midna Charge Ring Color +DEFINE_HOOK(&daAlink_c::setWolfLockDomeModel, SetWolfLockDomeModel); +void wolf_lock_dome_model_post(ModContext*, void*, void*, void*) { + auto domeRingColorStr = get_str_option(get_cvars().midnaChargeRingColor, ""); + if (is_valid_hex_color_str(domeRingColorStr)) { + auto domeRingColor = hex_color_str_to_gx_color(domeRingColorStr); + const u8 domeWave1RGBA[3] = {domeRingColor.r, domeRingColor.g, domeRingColor.b}; + const u8 domeWave2RGBA[3] = {domeRingColor.r, domeRingColor.g, domeRingColor.b}; + u8** chromaRegisterTable = + reinterpret_cast(&daAlink_getAlinkActorClass()->field_0x0724->mAnmCRegDataR); + + for (int i = 0; i < 3; i++) { + u8* currentTable = chromaRegisterTable[i]; + const u8 currentWave1Color = domeWave1RGBA[i]; + const u8 currentWave2Color = domeWave2RGBA[i]; + const u8 currentBaseColor = (currentWave1Color + currentWave2Color) / 2; + + currentTable[0x3] = currentBaseColor; // Set Alpha for the ring base + currentTable[0x13] = currentWave1Color; // Set Alpha for ring wave 1 + currentTable[0x23] = currentWave2Color; // Set Alpha for ring wave 2 + currentTable[0xB] = currentBaseColor; // Set Alpha for darkworld ring base + currentTable[0x1B] = currentWave1Color; // Set Alpha for darkworld ring wave 1 + currentTable[0x2B] = currentWave2Color; // Set Alpha for darkworld ring wave 2 + } + } +} + +#define ADD_POST_HOOK(defined_hook, function, original) \ + result = mods::hook::add_post(function); \ + if (result != MOD_OK) { \ + mods::log::debug( \ + "failed to add post hook to" #original ", Result {}", static_cast(result)); \ + return result; \ + } + +#define ADD_PRE_HOOK(defined_hook, function, original) \ + result = mods::hook::add_pre(function); \ + if (result != MOD_OK) { \ + mods::log::debug( \ + "failed to add pre hook to" #original ", Result {}", static_cast(result)); \ + return result; \ + } + +ModResult add_all_hooks() { + ModResult result{}; + + // Hooks for lantern glow + ADD_POST_HOOK(WolfEyeLightSet, wolf_eye_light_set_post, dKy_WolfEyeLight_set) + ADD_POST_HOOK(PreKandelaarDraw, pre_kandelaar_draw_post, daAlink_c::preKandelaarDraw) + + // Hooks for lantern meter color + ADD_PRE_HOOK(CPaneMgrSetBlackWhite, cpane_mgr_set_black_white_pre, CPaneMgr::setBlackWhite) + ADD_POST_HOOK( + KanteraIconSetNowGauge, kantera_icon_set_now_gauge_post, dKantera_icon_c::setNowGauge) + + // Hook for midna charge ring + ADD_POST_HOOK(SetWolfLockDomeModel, wolf_lock_dome_model_post, daAlink_c::setWolfLockDomeModel) + + // Hook for light sword glow + ADD_POST_HOOK(SetLightningSwordEffect, set_lightning_sword_effect_post, + daAlink_c::setLightningSwordEffect) + + // Hooks for Midna Hair Color + ADD_POST_HOOK(MidnaCreate, midna_create_post, daMidna_c::create) + ADD_PRE_HOOK( + MidnaSetBodyPartMatrix, midna_set_body_part_matrix_pre, daMidna_c::setBodyPartMatrix) + ADD_POST_HOOK( + MidnaSetBodyPartMatrix, midna_set_body_part_matrix_post, daMidna_c::setBodyPartMatrix) + + // Hooks for UI colors + ADD_POST_HOOK(dMeter2Init, d_meter_2_init_post, dMeter2Draw_c::init) + ADD_POST_HOOK(FileInfoSetHeartCount, file_info_set_heart_count_post, dFile_info_c::setHeartCnt) + ADD_POST_HOOK(ScreenInitButton, screen_init_button_post, dMeterButton_c::screenInitButton) + ADD_POST_HOOK(MenuSaveScreenSet, menu_save_screen_set_post, dMenu_save_c::screenSet) + ADD_POST_HOOK(FileSelectScreenSet, file_select_screen_set_post, dFile_select_c::screenSet) + ADD_POST_HOOK(BrightCheckScreenSet, bright_check_screen_set_post, dBrightCheck_c::screenSet) + ADD_POST_HOOK(MenuRingCreate, menu_ring_create_post, dMenu_Ring_c::_create) + ADD_POST_HOOK(MenuCollect2DCreate, menu_collect_2D_create_post, dMenu_Collect2D_c::_create) + ADD_POST_HOOK(MenuFishingScreenSetDoIcon, menu_fishing_screen_set_do_icon_post, + dMenu_Fishing_c::screenSetDoIcon) + ADD_POST_HOOK(MenuInsectScreenSetDoIcon, menu_insect_screen_set_do_icon_post, + dMenu_Insect_c::screenSetDoIcon) + ADD_POST_HOOK(MenuLetterScreenSetDoIcon, menu_letter_screen_set_do_icon_post, + dMenu_Letter_c::screenSetDoIcon) + ADD_POST_HOOK(MenuOptionCreate, menu_option_create_post, dMenu_Option_c::_create) + ADD_POST_HOOK(MenuSkillScreenSetDoIcon, menu_skill_screen_set_do_icon_post, + dMenu_Skill_c::screenSetDoIcon) + ADD_POST_HOOK(OutFontCreatePane, out_font_create_pane_post, COutFont_c::createPane) + ADD_POST_HOOK(OutFontSetDrawFont, out_font_set_draw_font_post, COutFontSet_c::drawFont) + ADD_POST_HOOK(MenuFMapCreate, menu_fmap_create_post, dMenu_Fmap_c::_create) + ADD_POST_HOOK( + MsgObjectTalkStartInit, msg_object_talk_start_init_post, dMsgObject_c::talkStartInit) + ADD_POST_HOOK(MeterHakushaCreate, meter_hakusha_create_post, dMeterHakusha_c::_create) + + // Heart Model Color + ADD_POST_HOOK( + ItemBaseCreateItemHeap, item_base_create_item_heap_post, daItemBase_c::CreateItemHeap) + + return MOD_OK; +} + +#define UNINSTALL_HOOK(defined_hook) mods::hook::uninstall(svc_hook); + +ModResult remove_all_hooks() { + UNINSTALL_HOOK(WolfEyeLightSet) + UNINSTALL_HOOK(PreKandelaarDraw) + UNINSTALL_HOOK(CPaneMgrSetBlackWhite) + UNINSTALL_HOOK(KanteraIconSetNowGauge) + UNINSTALL_HOOK(SetWolfLockDomeModel) + UNINSTALL_HOOK(SetLightningSwordEffect) + UNINSTALL_HOOK(MidnaCreate) + UNINSTALL_HOOK(MidnaSetBodyPartMatrix) + UNINSTALL_HOOK(MidnaSetBodyPartMatrix) + UNINSTALL_HOOK(dMeter2Init) + UNINSTALL_HOOK(FileInfoSetHeartCount) + UNINSTALL_HOOK(ScreenInitButton) + UNINSTALL_HOOK(MenuSaveScreenSet) + UNINSTALL_HOOK(FileSelectScreenSet) + UNINSTALL_HOOK(BrightCheckScreenSet) + UNINSTALL_HOOK(MenuRingCreate) + UNINSTALL_HOOK(MenuCollect2DCreate) + UNINSTALL_HOOK(MenuFishingScreenSetDoIcon) + UNINSTALL_HOOK(MenuInsectScreenSetDoIcon) + UNINSTALL_HOOK(MenuLetterScreenSetDoIcon) + UNINSTALL_HOOK(MenuOptionCreate) + UNINSTALL_HOOK(MenuSkillScreenSetDoIcon) + UNINSTALL_HOOK(OutFontCreatePane) + UNINSTALL_HOOK(OutFontSetDrawFont) + UNINSTALL_HOOK(MenuFMapCreate) + UNINSTALL_HOOK(MsgObjectTalkStartInit) + UNINSTALL_HOOK(MeterHakushaCreate) + UNINSTALL_HOOK(ItemBaseCreateItemHeap) + return MOD_OK; +} diff --git a/mods/basic_cosmetics_mod/src/hooks.hpp b/mods/basic_cosmetics_mod/src/hooks.hpp new file mode 100644 index 0000000000..62bb77cde9 --- /dev/null +++ b/mods/basic_cosmetics_mod/src/hooks.hpp @@ -0,0 +1,7 @@ +#pragma once + +#include "mods/service.hpp" + +ModResult add_all_hooks(); + +ModResult remove_all_hooks(); \ No newline at end of file diff --git a/mods/basic_cosmetics_mod/src/midna_hair_color.cpp b/mods/basic_cosmetics_mod/src/midna_hair_color.cpp new file mode 100644 index 0000000000..905a4345ff --- /dev/null +++ b/mods/basic_cosmetics_mod/src/midna_hair_color.cpp @@ -0,0 +1,115 @@ +#include "midna_hair_color.hpp" +#include "mod.hpp" + +#include "mods/svc/log.hpp" + +#include + +namespace { +constexpr std::array, 10> kMidnaHairColors = {{ + // Default + {{ + /*l_lNormalKColor*/ /*l_normalKColor*/ /*l_normalColor*/ + {0xFF, 0xDC, 0x00}, {0xB4, 0x87, 0x00}, {0x50, 0x00, 0x00}, + /*l_bigKColor*/ /*l_lBigColor*/ /*l_bigColor*/ + {0x1E, 0x00, 0x00}, {0xFF, 0x78, 0x00}, {0xFF, 0x64, 0x78}, + /*l_lNormalKColor2*//*l_normalKColor2*/ /*l_lBigKColor2*/ + {0x00, 0xC3, 0xEB}, {0x00, 0xC3, 0xC3}, {0xAA, 0xFF, 0xC3} + }}, + // Pink + {{ + {0xF5, 0xCF, 0xF3}, {0xAD, 0x7F, 0x7F}, {0x1B, 0x00, 0x20}, + {0x3C, 0x02, 0x58}, {0xE3, 0x72, 0xF2}, {0xE3, 0x5F, 0xF8}, + {0xDD, 0x00, 0xEB}, {0xDD, 0x00, 0xC3}, {0xF6, 0x4C, 0xFF} + }}, + // Red + {{ + {0xE4, 0x65, 0x41}, {0xA1, 0x3E, 0x22}, {0x21, 0x00, 0x00}, + {0x4F, 0x02, 0x01}, {0xF0, 0x3A, 0x25}, {0xF0, 0x30, 0x8C}, + {0xEB, 0x00, 0x00}, {0xEB, 0x00, 0x00}, {0xFF, 0x4F, 0x3A} + }}, + // Yellow + {{ + {0x91, 0x83, 0x0E}, {0x66, 0x50, 0x07}, {0x0E, 0x0B, 0x00}, + {0x24, 0x25, 0x02}, {0xCB, 0xB7, 0x00}, {0xCB, 0x99, 0x78}, + {0xEB, 0xDE, 0x00}, {0xEB, 0xDE, 0x00}, {0xFF, 0xF8, 0xBF} + }}, + // Green + {{ + {0x35, 0x79, 0x53}, {0x25, 0x4A, 0x2B}, {0x00, 0x0E, 0x05}, + {0x0A, 0x29, 0x10}, {0x00, 0xB6, 0x6F}, {0x00, 0x98, 0xB3}, + {0x1F, 0xEB, 0x00}, {0x1F, 0xEB, 0x00}, {0x9A, 0xFF, 0x81} + }}, + // Blue + {{ + {0x00, 0x72, 0xFF}, {0x00, 0x46, 0x85}, {0x00, 0x08, 0x28}, + {0x16, 0x1B, 0x5D}, {0x00, 0x60, 0xFF}, {0x00, 0x50, 0xFF}, + {0x00, 0x48, 0xEB}, {0x00, 0x48, 0xC3}, {0x3A, 0x66, 0xFF} + }}, + // Purple + {{ + {0x6F, 0x34, 0xFF}, {0x4E, 0x20, 0x85}, {0x0D, 0x00, 0x34}, + {0x15, 0x08, 0x79}, {0x62, 0x00, 0xFF}, {0x62, 0x00, 0xFF}, + {0x7B, 0x00, 0xEB}, {0x7B, 0x00, 0xC3}, {0x94, 0x3E, 0xFF} + }}, + // Brown + {{ + {0x00, 0x00, 0x00}, {0x00, 0x00, 0x00}, {0x1A, 0x05, 0x00}, + {0x3C, 0x19, 0x0E}, {0x3F, 0x1D, 0x0B}, {0x3F, 0x18, 0x7E}, + {0x3F, 0x1D, 0x0B}, {0x3F, 0x1D, 0x09}, {0x59, 0x32, 0x1E} + }}, + // White + {{ + {0xF0, 0xF1, 0xF1}, {0xA9, 0x94, 0x7E}, {0x09, 0x0B, 0x0C}, + {0x22, 0x24, 0x24}, {0xFF, 0xFF, 0xFF}, {0xFF, 0xD5, 0xFF}, + {0xEA, 0xEA, 0xEA}, {0xEA, 0xEA, 0xC2}, {0xF3, 0xF3, 0xF3} + }}, + // Black + {{ + {0x00, 0x00, 0x00}, {0x00, 0x00, 0x00}, {0x0B, 0x0B, 0x0B}, + {0x23, 0x23, 0x23}, {0x00, 0x00, 0x00}, {0x00, 0x00, 0x78}, + {0x00, 0x00, 0x00}, {0x00, 0x00, 0x00}, {0x00, 0x00, 0x00} + }} +}}; + +size_t get_midna_hair_color_index(ConfigVarHandle handle) { + const auto optionIndex = get_int_option(handle, 0); + if (optionIndex < 0 || optionIndex >= static_cast(kMidnaHairColors.size())) { + return 0; + } + return static_cast(optionIndex); +} +} + +MidnaHairColors g_currentMidnaHairColors = { + .normalColor = {0x50, 0x00, 0x00, 0x00}, + .normalKColor = {0xB4, 0x87, 0x00, 0x00}, + .normalKColor2 = {0x00, 0xC3, 0xC3, 0x00}, + .bigColor = {0xFF, 0x64, 0x78, 0x00}, + .bigKColor = {0x1E, 0x00, 0x00, 0x00}, + .lNormalKColor = {0xFF, 0xDC, 0x00, 0x00}, + .lNormalKColor2 = {0x00, 0xC3, 0xEB, 0x00}, + .lBigColor = {0xFF, 0x78, 0x00, 0x00}, + .lBigKColor2 = {0xAA, 0xFF, 0xC3, 0x00}, +}; + +void set_all_midna_hair_colors() { + auto& g_cvars = get_cvars(); + auto hairBaseColor = get_midna_hair_color_index(g_cvars.midnaHairBaseColor); + auto hairTipsColor = get_midna_hair_color_index(g_cvars.midnaHairTipsColor); + + // Colors we have to convert to GXColorS10 + auto& normalColor = kMidnaHairColors.at(hairBaseColor)[2]; + auto& bigColor = kMidnaHairColors.at(hairBaseColor)[5]; + auto& lBigColor = kMidnaHairColors.at(hairBaseColor)[4]; + + g_currentMidnaHairColors.normalColor = GXColorS10{normalColor.r, normalColor.g, normalColor.b}; + g_currentMidnaHairColors.normalKColor = kMidnaHairColors.at(hairBaseColor)[1]; + g_currentMidnaHairColors.normalKColor2 = kMidnaHairColors.at(hairTipsColor)[7]; + g_currentMidnaHairColors.bigColor = GXColorS10{bigColor.r, bigColor.g, bigColor.b}; + g_currentMidnaHairColors.bigKColor = kMidnaHairColors.at(hairBaseColor)[3]; + g_currentMidnaHairColors.lNormalKColor = kMidnaHairColors.at(hairBaseColor)[0]; + g_currentMidnaHairColors.lNormalKColor2 = kMidnaHairColors.at(hairTipsColor)[6]; + g_currentMidnaHairColors.lBigColor = GXColorS10{lBigColor.r, lBigColor.g, lBigColor.b}; + g_currentMidnaHairColors.lBigKColor2 = kMidnaHairColors.at(hairTipsColor)[8]; +} diff --git a/mods/basic_cosmetics_mod/src/midna_hair_color.hpp b/mods/basic_cosmetics_mod/src/midna_hair_color.hpp new file mode 100644 index 0000000000..ad08f7c8c6 --- /dev/null +++ b/mods/basic_cosmetics_mod/src/midna_hair_color.hpp @@ -0,0 +1,19 @@ +#pragma once + +#include + +struct MidnaHairColors { + GXColorS10 normalColor; + GXColor normalKColor; + GXColor normalKColor2; + GXColorS10 bigColor; + GXColor bigKColor; + GXColor lNormalKColor; + GXColor lNormalKColor2; + GXColorS10 lBigColor; + GXColor lBigKColor2; +}; + +extern MidnaHairColors g_currentMidnaHairColors; + +void set_all_midna_hair_colors(); diff --git a/mods/basic_cosmetics_mod/src/mod.cpp b/mods/basic_cosmetics_mod/src/mod.cpp new file mode 100644 index 0000000000..89a321da9c --- /dev/null +++ b/mods/basic_cosmetics_mod/src/mod.cpp @@ -0,0 +1,653 @@ +#include "mod.hpp" +#include "color_utils.hpp" +#include "hooks.hpp" +#include "midna_hair_color.hpp" +#include "texture_utils.hpp" + +#include "mods/service.hpp" +#include "mods/svc/config.h" +#include "mods/svc/hook.hpp" +#include "mods/svc/log.h" +#include "mods/svc/log.hpp" +#include "mods/svc/ui.h" + +#include "d/d_com_inf_game.h" + +#include + +#include +#include +#include + +DEFINE_MOD(); +IMPORT_SERVICE(LogService, svc_log); +IMPORT_SERVICE(ConfigService, svc_config); +IMPORT_SERVICE(HookService, svc_hook); +IMPORT_SERVICE(TextureService, svc_texture); +IMPORT_SERVICE(UiService, svc_ui); + +static cvars g_cvars; + +cvars& get_cvars() { + return g_cvars; +} + +std::string get_str_option(ConfigVarHandle handle, const std::string& fallback) { + std::string value{}; + size_t outLength{}; + svc_config->get_string(mod_ctx, handle, NULL, 0, &outLength); + value.resize(outLength); + if (handle == 0 || svc_config->get_string( + mod_ctx, handle, value.data(), value.size() + 1, &outLength) != MOD_OK) + { + return fallback; + } + return value; +} + +int64_t get_int_option(ConfigVarHandle handle, int64_t fallback) { + int64_t value = fallback; + if (handle == 0 || svc_config->get_int(mod_ctx, handle, &value) != MOD_OK) { + return fallback; + } + return value; +} + +// Helper for getting configVar color +std::optional get_config_var_color(ConfigVarHandle handle, bool allowRainbow) { + auto colorStr = get_str_option(handle, ""); + // Convert to lowercase + for (auto& c : colorStr) { + c = static_cast(std::tolower(static_cast(c))); + } + if (colorStr == "rainbow" && allowRainbow) { + auto color = get_rainbow_rgb(127.5f); + color.r /= 2; + color.g /= 2; + color.b /= 2; + return color; + } + if (is_valid_hex_color_str(colorStr)) { + return hex_color_str_to_gx_color(colorStr); + } + return std::nullopt; +} + +namespace { +UiWindowHandle g_cosmeticsWindow = 0; +bool g_loadedAllBaseTextures = false; +constexpr uint32_t kTextureLoadRetryFrames = 30; +uint32_t g_textureLoadRetryCountdown = 0; + +constexpr const char* kOverlayPresets[] = { + "ab706e", + "6382a0", + "94749a", + "ec8644", + "b9ab00", + "ec9fc8", + "505154", + "f8f7f4", + "91723e", +}; + +constexpr const char* kLightPresets[] = { + "ff0000", + "f68821", + "f6f321", + "00ff00", + "0000ff", + "8000ff", + "a0a0a0", + "30d0d0", +}; + +constexpr const char* kRainbowLightPresets[] = { + "rainbow", + "ff0000", + "f68821", + "f6f321", + "00ff00", + "0000ff", + "8000ff", + "a0a0a0", +}; + +constexpr const char* kAButtonPresets[] = { + "ff0000", + "ff5000", + "ffaf00", + "0080ff", + "0000ff", + "8000ff", + "5555ff", + "ff20ff", +}; + +constexpr const char* kBButtonPresets[] = { + "ffff40", + "ffa0ff", + "00e87b", + "00aaff", + "6078ff", + "000000", + "00f3ff", +}; + +constexpr const char* kXyButtonPresets[] = { + "ff0000", + "ff8200", + "f7df00", + "70ff00", + "00bd11", + "0000ff", + "800088", + "000000", + "ff00aa", + "00ffff", +}; + +constexpr const char* kZButtonPresets[] = { + "ff0000", + "ff8200", + "f7df00", + "70ff00", + "00bd11", + "800088", + "000000", + "00ffff", +}; + +constexpr const char* kChargeRingPresets[] = { + "ff9f9f", + "ff0000", + "ffff00", + "00ff00", + "0000ff", + "ff00ff", + "331900", + "feffff", + "000000", +}; + +ModResult register_str_option( + const char* name, const char* defaultValue, ConfigVarHandle& outHandle, ModError* error) { + ConfigVarDesc cvarDesc = CONFIG_VAR_DESC_INIT; + cvarDesc.name = name; + cvarDesc.type = CONFIG_VAR_STRING; + cvarDesc.default_string = defaultValue; + if (svc_config->register_var(mod_ctx, &cvarDesc, &outHandle) != MOD_OK) { + return mods::set_error(error, MOD_ERROR, "failed to register cosmetics option"); + } + return MOD_OK; +} + +ModResult register_int_option( + const char* name, int64_t defaultValue, ConfigVarHandle& outHandle, ModError* error) { + ConfigVarDesc cvarDesc = CONFIG_VAR_DESC_INIT; + cvarDesc.name = name; + cvarDesc.type = CONFIG_VAR_INT; + cvarDesc.default_int = defaultValue; + if (svc_config->register_var(mod_ctx, &cvarDesc, &outHandle) != MOD_OK) { + return mods::set_error(error, MOD_ERROR, "failed to register cosmetics option"); + } + return MOD_OK; +} + +void add_control(UiElementHandle pane, const UiControlDesc& desc) { + auto result = svc_ui->pane_add_control(mod_ctx, pane, &desc, nullptr); + if (result != MOD_OK) { + mods::log::debug("pane_add_control failed {}", static_cast(result)); + } +} + +template +void add_cosmetic_option( + UiElementHandle pane, ConfigVarHandle cvar, const char* name, const char* const (&presets)[N]) { + UiControlDesc control = UI_CONTROL_DESC_INIT; + control.kind = UI_CONTROL_COLOR; + control.label = name; + control.binding = UI_BINDING_CONFIG_VAR; + control.config_var = cvar; + control.color_presets = presets; + control.color_preset_count = N; + add_control(pane, control); +} + +void add_midna_hair_option(UiElementHandle left, ConfigVarHandle cvar, const std::string& name) { + static const char* kMidnaHairOptions[] = { + "Default", "Pink", "Red", "Yellow", "Green", "Blue", "Purple", "Brown", "White", "Black"}; + UiControlDesc control = UI_CONTROL_DESC_INIT; + control.kind = UI_CONTROL_SELECT; + control.label = name.c_str(); + control.help_rml = "Choose Midna's hair color."; + control.binding = UI_BINDING_CONFIG_VAR; + control.config_var = cvar; + control.options = kMidnaHairOptions; + control.option_count = 10; + add_control(left, control); +} + +void add_group( + UiElementHandle groups, UiElementHandle colors, const char* label, UiGroupBuildFn build) { + UiGroupDesc group = UI_GROUP_DESC_INIT; + group.label = label; + group.build = build; + const auto result = svc_ui->pane_add_group(mod_ctx, groups, colors, &group, nullptr); + if (result != MOD_OK) { + mods::log::debug("pane_add_group failed {}", static_cast(result)); + } +} + +ModResult build_hero_tunic_colors(ModContext*, UiElementHandle pane, void*, ModError*) { + svc_ui->pane_add_section(mod_ctx, pane, "Hero's Tunic"); + add_cosmetic_option(pane, g_cvars.herosTunicCapColor, "Cap", kOverlayPresets); + add_cosmetic_option(pane, g_cvars.herosTunicTorsoColor, "Body", kOverlayPresets); + add_cosmetic_option(pane, g_cvars.herosTunicSkirtColor, "Skirt", kOverlayPresets); + return MOD_OK; +} + +ModResult build_zora_armor_colors(ModContext*, UiElementHandle pane, void*, ModError*) { + svc_ui->pane_add_section(mod_ctx, pane, "Zora Armor"); + add_cosmetic_option(pane, g_cvars.zoraArmorCapColor, "Cap", kOverlayPresets); + add_cosmetic_option(pane, g_cvars.zoraArmorHelmetColor, "Helmet", kOverlayPresets); + add_cosmetic_option(pane, g_cvars.zoraArmorTorsoColor, "Torso", kOverlayPresets); + add_cosmetic_option(pane, g_cvars.zoraArmorScalesColor, "Scales", kOverlayPresets); + add_cosmetic_option(pane, g_cvars.zoraArmorFlippersColor, "Flippers", kOverlayPresets); + return MOD_OK; +} + +ModResult build_sword_colors(ModContext*, UiElementHandle pane, void*, ModError*) { + svc_ui->pane_add_section(mod_ctx, pane, "Swords"); + add_cosmetic_option(pane, g_cvars.woodenSwordColor, "Wooden Sword", kOverlayPresets); + add_cosmetic_option(pane, g_cvars.ordonSwordBladeColor, "Ordon Blade", kLightPresets); + add_cosmetic_option(pane, g_cvars.ordonSwordHandleColor, "Ordon Handle", kLightPresets); + add_cosmetic_option(pane, g_cvars.msBladeColor, "Master Sword Blade", kLightPresets); + add_cosmetic_option(pane, g_cvars.msHandleColor, "Master Sword Handle", kLightPresets); + add_cosmetic_option( + pane, g_cvars.lightSwordGlowColor, "Light Sword Glow", kRainbowLightPresets); + return MOD_OK; +} + +ModResult build_equipment_colors(ModContext*, UiElementHandle pane, void*, ModError*) { + svc_ui->pane_add_section(mod_ctx, pane, "Equipment"); + add_cosmetic_option(pane, g_cvars.lanternGlowColor, "Lantern Glow", kRainbowLightPresets); + add_cosmetic_option(pane, g_cvars.boomerangColor, "Gale Boomerang", kOverlayPresets); + add_cosmetic_option(pane, g_cvars.ironBootsColor, "Iron Boots", kOverlayPresets); + add_cosmetic_option(pane, g_cvars.spinnerColor, "Spinner", kOverlayPresets); + return MOD_OK; +} + +ModResult build_button_colors(ModContext*, UiElementHandle pane, void*, ModError*) { + svc_ui->pane_add_section(mod_ctx, pane, "Buttons"); + add_cosmetic_option(pane, g_cvars.aButtonColor, "A Button", kAButtonPresets); + add_cosmetic_option(pane, g_cvars.bButtonColor, "B Button", kBButtonPresets); + add_cosmetic_option(pane, g_cvars.xButtonColor, "X Button", kXyButtonPresets); + add_cosmetic_option(pane, g_cvars.yButtonColor, "Y Button", kXyButtonPresets); + add_cosmetic_option(pane, g_cvars.zButtonColor, "Z Button", kZButtonPresets); + return MOD_OK; +} + +ModResult build_hud_colors(ModContext*, UiElementHandle pane, void*, ModError*) { + svc_ui->pane_add_section(mod_ctx, pane, "HUD"); + add_cosmetic_option(pane, g_cvars.heartColor, "Hearts", kBButtonPresets); + return MOD_OK; +} + +ModResult build_link_colors(ModContext*, UiElementHandle pane, void*, ModError*) { + svc_ui->pane_add_section(mod_ctx, pane, "Link"); + add_cosmetic_option(pane, g_cvars.linkHairColor, "Hair", kOverlayPresets); + return MOD_OK; +} + +ModResult build_midna_colors(ModContext*, UiElementHandle pane, void*, ModError*) { + svc_ui->pane_add_section(mod_ctx, pane, "Midna"); + add_cosmetic_option(pane, g_cvars.midnaChargeRingColor, "Charge Ring", kChargeRingPresets); + return MOD_OK; +} + +ModResult build_companion_colors(ModContext*, UiElementHandle pane, void*, ModError*) { + svc_ui->pane_add_section(mod_ctx, pane, "Companions"); + add_cosmetic_option(pane, g_cvars.wolfLinkColor, "Wolf Link", kOverlayPresets); + add_cosmetic_option(pane, g_cvars.eponaColor, "Epona", kOverlayPresets); + return MOD_OK; +} + +ModResult build_equipment_colors_tab( + ModContext*, UiWindowHandle, UiElementHandle left, UiElementHandle right, void*, ModError*) { + svc_ui->pane_add_section(mod_ctx, left, "Color Groups"); + add_group(left, right, "Hero's Tunic", build_hero_tunic_colors); + add_group(left, right, "Zora Armor", build_zora_armor_colors); + add_group(left, right, "Swords", build_sword_colors); + add_group(left, right, "Equipment", build_equipment_colors); + + return MOD_OK; +} + +ModResult build_ui_colors_tab( + ModContext*, UiWindowHandle, UiElementHandle left, UiElementHandle right, void*, ModError*) { + svc_ui->pane_add_section(mod_ctx, left, "Color Groups"); + add_group(left, right, "Buttons", build_button_colors); + add_group(left, right, "HUD", build_hud_colors); + + return MOD_OK; +} + +ModResult build_misc_colors_tab( + ModContext*, UiWindowHandle, UiElementHandle left, UiElementHandle right, void*, ModError*) { + svc_ui->pane_add_section(mod_ctx, left, "Hair Presets"); + add_midna_hair_option(left, g_cvars.midnaHairBaseColor, "Midna's Hair Base Color"); + add_midna_hair_option(left, g_cvars.midnaHairTipsColor, "Midna's Hair Tips Color"); + svc_ui->pane_add_section(mod_ctx, left, "Color Groups"); + add_group(left, right, "Link", build_link_colors); + add_group(left, right, "Midna", build_midna_colors); + add_group(left, right, "Companions", build_companion_colors); + + return MOD_OK; +} + +void on_cosmetics_menu_window_closed(ModContext*, UiWindowHandle, void*) { + g_cosmeticsWindow = 0; +} + +void on_open_cosmetics_menu(ModContext*, void*) { + if (g_cosmeticsWindow != 0) { + return; + } + UiTabDesc tabs[] = {UI_TAB_DESC_INIT, UI_TAB_DESC_INIT, UI_TAB_DESC_INIT}; + tabs[0].title = "Equipment"; + tabs[0].build = build_equipment_colors_tab; + tabs[1].title = "Interface"; + tabs[1].build = build_ui_colors_tab; + tabs[2].title = "Characters"; + tabs[2].build = build_misc_colors_tab; + UiWindowDesc desc = UI_WINDOW_DESC_INIT; + desc.tabs = tabs; + desc.tab_count = ARRAY_SIZE(tabs); + desc.on_closed = on_cosmetics_menu_window_closed; + if (svc_ui->window_push(mod_ctx, &desc, &g_cosmeticsWindow) != MOD_OK) { + svc_log->error(mod_ctx, "failed to open basic cosmetics window"); + } +} + +ModResult build_panel(ModContext*, UiElementHandle panel, void*, ModError*) { + UiControlDesc control = UI_CONTROL_DESC_INIT; + control.kind = UI_CONTROL_GROUP; + control.label = "Open Cosmetics Menu"; + control.on_pressed = on_open_cosmetics_menu; + add_control(panel, control); + return MOD_OK; +} +} // namespace + +void load_base_texture_data() { + // Go through each texture we can recolor and attempt to load and store + // the texture data for future recoloring + for (auto& replacements : get_texture_replacements() | std::views::values) { + for (auto& replacement : replacements) { + // If we've already loaded the texture data, don't load it again + if (replacement.loadedTextureData) { + continue; + } + + // Avoid noisy resource lookups until the archive has finished loading. + auto* resInfo = dComIfG_getObjectResInfo(replacement.arc); + if (resInfo == nullptr || resInfo->getArchive() == nullptr) { + continue; + } + + // Try to get the model this texture is part of. If we can't get it, try again later + auto model = static_cast( + dComIfG_getObjectRes(replacement.arc, replacement.modelFileName)); + if (model == nullptr) { + continue; + } + + J3DTexture* tex = model->getTexture(); + JUTNameTab* nametable = model->getTextureName(); + if (tex != nullptr && nametable != nullptr) { + for (u16 i = 0; i < tex->getNum(); i++) { + const char* texName = nametable->getName(i); + if (texName != nullptr && std::strcmp(texName, replacement.textureName) == 0) { + // Once we've found the texture, set all our TextureKey and TextureData + // fields that we can set right now. + auto imageHeader = tex->getResTIMG(i); + auto& key = replacement.key; + auto& data = replacement.data; + key.kind = TEXTURE_KEY_SOURCE; + key.has_tlut = imageHeader->numColors > 0; + key.width = imageHeader->width; + key.height = imageHeader->height; + key.gx_format = imageHeader->format; + + // Currently, no replaced textures have a tlut + key.tlut_hash = replacement.tlutHash; + + // Calculate the size of the image data + const uint32_t mipCount = + imageHeader->mipmapEnabled ? + std::max(imageHeader->mipmapCount, 1) : + 1; + auto size = get_image_data_size( + imageHeader->format, imageHeader->width, imageHeader->height, mipCount); + replacement.baseTextureData.resize(size); + std::memcpy( + replacement.baseTextureData.data(), tex->getImgDataPtr(i), size); + + // Source texture keys hash only the base mip level. + const auto baseMipSize = get_image_data_size( + imageHeader->format, imageHeader->width, imageHeader->height, 1); + auto textureHash = + XXH64(replacement.baseTextureData.data(), baseMipSize, 0); + replacement.key.texture_hash = textureHash; + + mods::log::debug("Loaded base texture data for {}. size: {:X} hash: {:X}", + replacement.textureName, size, textureHash); + replacement.loadedTextureData = true; + + data.width = imageHeader->width; + data.height = imageHeader->height; + data.mip_count = mipCount; + data.size = size; + data.gx_format = imageHeader->format; + + break; + } + } + } + } + } + + // If we've loaded all base textures for recoloring, then we don't need to call this function + // again + g_loadedAllBaseTextures = std::ranges::all_of( + get_texture_replacements() | std::views::values, [](auto& replacementList) { + return std::ranges::all_of( + replacementList, [](const TextureReplacementData& replacement) { + return replacement.loadedTextureData; + }); + }); +} + +ModResult check_and_set_recolored_textures() { + for (auto& [configVar, replacements] : get_texture_replacements()) { + // If the configvar hasn't been set, don't continue + if (configVar == 0) { + continue; + } + + auto maybeColor = get_config_var_color(configVar); + if (!maybeColor.has_value()) { + // An empty or invalid option means the original texture should be restored. + for (auto& replacement : replacements) { + if (replacement.handle != 0) { + auto result = svc_texture->unregister(mod_ctx, replacement.handle); + if (result != MOD_OK) { + mods::log::debug("Could not unregister replacement for {}. Result: {}", + replacement.textureName, static_cast(result)); + } + replacement.handle = 0; + } + replacement.curColor.reset(); + } + continue; + } + + auto color = maybeColor.value(); + for (auto& replacement : replacements) { + // If we haven't loaded the base texture yet, don't try to recolor it + if (!replacement.loadedTextureData) { + continue; + } + + // If our color hasn't changed, don't try to recolor + auto& curColor = replacement.curColor; + if (curColor == std::nullopt || curColor.value().r != color.r || + curColor.value().g != color.g || curColor.value().b != color.b) + { + // Make a copy of the base texture data to recolor + auto newTexture = replacement.baseTextureData; + recolor_texture(replacement, color, newTexture); + + TextureData newTextureData = replacement.data; + newTextureData.data = newTexture.data(); + newTextureData.size = newTexture.size(); + + // Keep the current replacement active if registering the new one fails. + TextureReplacementHandle newHandle{}; + auto result = svc_texture->register_data( + mod_ctx, &replacement.key, &newTextureData, &newHandle); + if (result != MOD_OK) { + mods::log::debug("Could not register_data for {}. Result: {}", + replacement.textureName, static_cast(result)); + } else { + mods::log::debug("Registered replacement for {}.", replacement.textureName, + static_cast(result)); + auto oldHandle = replacement.handle; + replacement.handle = newHandle; + curColor = color; + + if (oldHandle != 0) { + result = svc_texture->unregister(mod_ctx, oldHandle); + if (result != MOD_OK) { + mods::log::debug( + "Could not unregister previous replacement for {}. Result: {}", + replacement.textureName, static_cast(result)); + } + } + } + } + } + } + + return MOD_OK; +} + +void unregister_all_texture_handles() { + for (auto& replacements : get_texture_replacements() | std::views::values) { + for (auto& replacement : replacements) { + if (replacement.handle != 0) { + svc_texture->unregister(mod_ctx, replacement.handle); + replacement.handle = 0; + } + replacement.curColor.reset(); + } + } +} + +#define REGISTER_COSMETIC_OPTION(option) \ + result = register_str_option(#option, NULL, g_cvars.option, error); \ + if (result != MOD_OK) { \ + return result; \ + } + +extern "C" { +MOD_EXPORT ModResult mod_initialize(ModError* error) { + svc_log->info(mod_ctx, "basic_cosmetics_mod initialized"); + + ModResult result{}; + + REGISTER_COSMETIC_OPTION(herosTunicCapColor) + REGISTER_COSMETIC_OPTION(herosTunicTorsoColor) + REGISTER_COSMETIC_OPTION(herosTunicSkirtColor) + REGISTER_COSMETIC_OPTION(zoraArmorCapColor) + REGISTER_COSMETIC_OPTION(zoraArmorHelmetColor) + REGISTER_COSMETIC_OPTION(zoraArmorTorsoColor) + REGISTER_COSMETIC_OPTION(zoraArmorScalesColor) + REGISTER_COSMETIC_OPTION(zoraArmorFlippersColor) + REGISTER_COSMETIC_OPTION(lanternGlowColor) + REGISTER_COSMETIC_OPTION(woodenSwordColor) + REGISTER_COSMETIC_OPTION(ordonSwordBladeColor) + REGISTER_COSMETIC_OPTION(ordonSwordHandleColor) + REGISTER_COSMETIC_OPTION(msBladeColor) + REGISTER_COSMETIC_OPTION(msHandleColor) + REGISTER_COSMETIC_OPTION(lightSwordGlowColor) + REGISTER_COSMETIC_OPTION(boomerangColor) + REGISTER_COSMETIC_OPTION(ironBootsColor) + REGISTER_COSMETIC_OPTION(spinnerColor) + REGISTER_COSMETIC_OPTION(aButtonColor) + REGISTER_COSMETIC_OPTION(bButtonColor) + REGISTER_COSMETIC_OPTION(xButtonColor) + REGISTER_COSMETIC_OPTION(yButtonColor) + REGISTER_COSMETIC_OPTION(zButtonColor) + REGISTER_COSMETIC_OPTION(heartColor) + + result = register_int_option("midnaHairBaseColor", 0, g_cvars.midnaHairBaseColor, error); + if (result != MOD_OK) { + return result; + } + + result = register_int_option("midnaHairTipsColor", 0, g_cvars.midnaHairTipsColor, error); + if (result != MOD_OK) { + return result; + } + + REGISTER_COSMETIC_OPTION(midnaChargeRingColor) + REGISTER_COSMETIC_OPTION(linkHairColor) + REGISTER_COSMETIC_OPTION(wolfLinkColor) + REGISTER_COSMETIC_OPTION(eponaColor) + + UiModsPanelDesc panelDesc = UI_MODS_PANEL_DESC_INIT; + panelDesc.build = build_panel; + svc_ui->register_mods_panel(mod_ctx, &panelDesc); + + // Add all our hooks + result = add_all_hooks(); + if (result != MOD_OK) { + return result; + } + + g_loadedAllBaseTextures = false; + g_textureLoadRetryCountdown = 0; + return MOD_OK; +} + +MOD_EXPORT ModResult mod_update(ModError*) { + update_rainbow_rgb(1.0f); + set_all_midna_hair_colors(); + + if (!g_loadedAllBaseTextures) { + if (g_textureLoadRetryCountdown == 0) { + load_base_texture_data(); + g_textureLoadRetryCountdown = kTextureLoadRetryFrames; + } else { + --g_textureLoadRetryCountdown; + } + } + + check_and_set_recolored_textures(); + + return MOD_OK; +} + +MOD_EXPORT ModResult mod_shutdown(ModError*) { + svc_log->info(mod_ctx, "basic_cosmetics_mod unloaded"); + g_cosmeticsWindow = 0; + remove_all_hooks(); + unregister_all_texture_handles(); + get_texture_replacements().clear(); + g_loadedAllBaseTextures = false; + g_textureLoadRetryCountdown = 0; + return MOD_OK; +} +} diff --git a/mods/basic_cosmetics_mod/src/mod.hpp b/mods/basic_cosmetics_mod/src/mod.hpp new file mode 100644 index 0000000000..6d77949b03 --- /dev/null +++ b/mods/basic_cosmetics_mod/src/mod.hpp @@ -0,0 +1,65 @@ +#pragma once + +#include "mods/svc/config.h" +#include "mods/svc/texture.h" + +#include + +#include +#include +#include + +struct cvars { + ConfigVarHandle herosTunicCapColor = 0; + ConfigVarHandle herosTunicTorsoColor = 0; + ConfigVarHandle herosTunicSkirtColor = 0; + ConfigVarHandle zoraArmorCapColor = 0; + ConfigVarHandle zoraArmorHelmetColor = 0; + ConfigVarHandle zoraArmorTorsoColor = 0; + ConfigVarHandle zoraArmorScalesColor = 0; + ConfigVarHandle zoraArmorFlippersColor = 0; + ConfigVarHandle lanternGlowColor = 0; + ConfigVarHandle woodenSwordColor = 0; + ConfigVarHandle ordonSwordBladeColor = 0; + ConfigVarHandle ordonSwordHandleColor = 0; + ConfigVarHandle msBladeColor = 0; + ConfigVarHandle msHandleColor = 0; + ConfigVarHandle lightSwordGlowColor = 0; + ConfigVarHandle boomerangColor = 0; + ConfigVarHandle ironBootsColor = 0; + ConfigVarHandle spinnerColor = 0; + ConfigVarHandle heartColor = 0; + ConfigVarHandle aButtonColor = 0; + ConfigVarHandle bButtonColor = 0; + ConfigVarHandle xButtonColor = 0; + ConfigVarHandle yButtonColor = 0; + ConfigVarHandle zButtonColor = 0; + ConfigVarHandle midnaHairBaseColor = 0; + ConfigVarHandle midnaHairTipsColor = 0; + ConfigVarHandle midnaChargeRingColor = 0; + ConfigVarHandle linkHairColor = 0; + ConfigVarHandle wolfLinkColor = 0; + ConfigVarHandle eponaColor = 0; +}; + +struct TextureReplacementData { + const char* arc{}; + const char* modelFileName{}; + const char* textureName{}; + uint64_t textureHash{}; + uint64_t tlutHash{}; + TextureKey key = TEXTURE_KEY_INIT; + TextureData data = TEXTURE_DATA_INIT; + TextureReplacementHandle handle{}; + std::vector baseTextureData{}; + bool loadedTextureData = false; + std::optional curColor{}; +}; + +cvars& get_cvars(); + +std::string get_str_option(ConfigVarHandle handle, const std::string& fallback); + +int64_t get_int_option(ConfigVarHandle handle, int64_t fallback); + +std::optional get_config_var_color(ConfigVarHandle handle, bool allowRainbow = false); \ No newline at end of file diff --git a/mods/basic_cosmetics_mod/src/texture_utils.cpp b/mods/basic_cosmetics_mod/src/texture_utils.cpp new file mode 100644 index 0000000000..98c60dbad3 --- /dev/null +++ b/mods/basic_cosmetics_mod/src/texture_utils.cpp @@ -0,0 +1,682 @@ +#include "texture_utils.hpp" +#include "color_utils.hpp" +#include "mod.hpp" + +#include "mods/svc/config.h" +#include "mods/svc/log.hpp" + +#include "JSystem/J3DGraphLoader/J3DModelLoader.h" +#include "JSystem/JSupport/JSupport.h" +#include "JSystem/JUtility/JUTNameTab.h" +#include "d/actor/d_a_alink.h" + +static void get_gx_tile_info(uint8_t format, uint32_t& tileWidth, uint32_t& tileHeight, uint32_t& tileSize) { + switch (format) { + case GX_TF_I8: + case GX_TF_IA4: + case GX_TF_C8: + tileWidth = 8; tileHeight = 4; tileSize = 32; + break; + case GX_TF_IA8: + case GX_TF_RGB565: + case GX_TF_RGB5A3: + case GX_TF_C14X2: + tileWidth = 4; tileHeight = 4; tileSize = 32; + break; + case GX_TF_RGBA8: + tileWidth = 4; tileHeight = 4; tileSize = 64; + break; + case GX_TF_I4: + case GX_TF_C4: + case GX_TF_CMPR: + default: + tileWidth = 8; tileHeight = 8; tileSize = 32; + break; + } +} + +uint32_t get_image_data_size(uint32_t format, uint32_t width, uint32_t height, uint32_t mipmapCount) { + + uint32_t tileWidth, tileHeight, tileSize; + get_gx_tile_info(format, tileWidth, tileHeight, tileSize); + + uint32_t totalSize = 0; + + for (uint8_t i = 0; i < mipmapCount; ++i) { + // Round dimensions up to nearest tile boundary + uint32_t paddedWidth = (width + tileWidth - 1) & ~(tileWidth - 1); + uint32_t paddedHeight = (height + tileHeight - 1) & ~(tileHeight - 1); + + uint32_t tilesX = paddedWidth / tileWidth; + uint32_t tilesY = paddedHeight / tileHeight; + + totalSize += tilesX * tilesY * tileSize; + + // Downscale dimensions for next mipmap level + width = std::max(1u, width >> 1); + height = std::max(1u, height >> 1); + } + + return totalSize; +} + +// When left is greater than right +// 0b00 points to the left color +// 0b01 points to the right color +// 0b10 is closer to left color +// 0b11 is closer to right color + +// When left is not greater than right +// 0b00 points to the left color +// 0b01 points to the right color +// 0b10 is midway between the colors +// 0b11 is transparent + +// That means when maintaining the relative order, if we have to swap the colors: + +// in the case of left being greater than right: +// 0b00 will swap to 0b01 +// 0b01 will swap to 0b00 +// 0b10 will swap to 0b11 +// 0b11 will swap to 0b10 +// So the left bit stays the same, and the right bit changes +// Can do xor (^) like 0b01010101 or 0x55 for each u16 + +// in the case of left not being greater than right: +// 0b00 will swap to 0b01 +// 0b01 will swap to 0b00 +// 0b10 will stay the same +// 0b11 will stay the same +// so if the left bit is a 0, the right bit will change +uint32_t swap_index_bits(bool leftIsGreater, uint32_t bits) { + if (leftIsGreater) { + return bits ^ 0x55555555; + } + + const uint32_t mask = ((bits >> 1) & 0x55555555) ^ 0x55555555; + return bits ^ mask; +} + +void recolor_cmpr_texture(const TextureReplacementData& replacementData, const GXColor color, std::vector& newTextureDataOut) +{ + uint16_t recolors[0x100]; + for (int32_t i = 0; i < 0x100; i++) { + recolors[i] = blend_overlay_rgb_565(i, color); + } + + const uint8_t mipCount = (replacementData.data.mip_count > 0) ? replacementData.data.mip_count : 1; + uint32_t mipWidth = replacementData.key.width; + uint32_t mipHeight = replacementData.key.height; + + uint8_t* currentAddr = newTextureDataOut.data(); + + for (uint8_t mip = 0; mip < mipCount; ++mip) { + // Round dimensions up to the nearest 8x8 tile boundary + const uint32_t roundedWidth = (mipWidth + 7) & ~7; + const uint32_t roundedHeight = (mipHeight + 7) & ~7; + + const uint32_t numBlocks = (roundedWidth / 8) * (roundedHeight / 8); + const uint32_t iterations = numBlocks * 4; // 4 CMPR sub-blocks per 8x8 tile + + for (uint32_t i = 0; i < iterations; i++) { + auto* rgb565Ptr = reinterpret_cast*>(currentAddr); + + auto leftRgb565 = rgb565Ptr[0]; + auto rightRgb565 = rgb565Ptr[1]; + const bool leftIsGreater = leftRgb565 > rightRgb565; + + const uint32_t leftGrayVal = desaturate_rgb_565(leftRgb565); + const uint32_t rightGrayVal = desaturate_rgb_565(rightRgb565); + + uint16_t leftNewRgb565 = recolors[leftGrayVal]; + uint16_t rightNewRgb565 = recolors[rightGrayVal]; + + bool needsBitSwap = false; + + if (leftIsGreater) { + if (leftNewRgb565 == rightNewRgb565) { + // Need to make sure that subtracting 1 does not mess + // everything up. For example, 0x1000 - 1 => 0x0fff which is + // a completely different color. + if ((leftNewRgb565 & 0x1f) == 0) { + // If left value has 0 blue, we change its blue to 1. + leftNewRgb565 += 1; + } + rightNewRgb565 = leftNewRgb565 - 1; + } + else if (leftNewRgb565 < rightNewRgb565) { + needsBitSwap = true; + } + } + else if (leftNewRgb565 > rightNewRgb565) { + needsBitSwap = true; + } + + if (needsBitSwap) { + // The left and right colors are swapping so that their values + // are relative in the same way. We need to update the bits + // referencing the palette entries to handle the swap. + const uint16_t temp = leftNewRgb565; + leftNewRgb565 = rightNewRgb565; + rightNewRgb565 = temp; + + auto wordPtr = reinterpret_cast*>(currentAddr); + const uint32_t bits = wordPtr[1]; + + const uint32_t newBits = swap_index_bits(leftIsGreater, bits); + wordPtr[1] = newBits; + } + + rgb565Ptr[0] = leftNewRgb565; + rgb565Ptr[1] = rightNewRgb565; + + currentAddr += 8; + } + + // Halve dimensions for the next mipmap level + mipWidth = std::max(1u, mipWidth >> 1); + mipHeight = std::max(1u, mipHeight >> 1); + } +} + +void recolor_rgb5a3_texture(const TextureReplacementData& replacementData, const GXColor color, std::vector& newTextureDataOut) +{ + // Precompute lookup tables for both RGB555 (opaque) and RGB444 (translucent) modes + uint16_t recolors_rgb555[0x100]; + uint16_t recolors_rgb444[0x100]; + + for (int32_t i = 0; i < 0x100; i++) { + const uint8_t r = blend_overlay_channel(i, color.r); + const uint8_t g = blend_overlay_channel(i, color.g); + const uint8_t b = blend_overlay_channel(i, color.b); + + // Pack as RGB555: Bit 15 set to 1 + 5 bits R, G, B + recolors_rgb555[i] = 0x8000 | ((r >> 3) << 10) | ((g >> 3) << 5) | (b >> 3); + + // Pack as RGB444: 4 bits R, G, B (Bit 15 remains 0) + recolors_rgb444[i] = ((r >> 4) << 8) | ((g >> 4) << 4) | (b >> 4); + } + + const uint8_t mipCount = + replacementData.data.mip_count > 0 ? replacementData.data.mip_count : 1; + uint32_t mipWidth = replacementData.key.width; + uint32_t mipHeight = replacementData.key.height; + auto* pixelPtr = reinterpret_cast*>(newTextureDataOut.data()); + + for (uint8_t mip = 0; mip < mipCount; ++mip) { + const uint32_t roundedWidth = (mipWidth + 3) & ~3; + const uint32_t roundedHeight = (mipHeight + 3) & ~3; + const uint32_t totalPixels = roundedWidth * roundedHeight; + + for (uint32_t i = 0; i < totalPixels; i++) { + const uint16_t rawPixel = pixelPtr[i]; + + // MSB determines if pixel is opaque or translucent + if (rawPixel & 0x8000) { + // Pixel is opaque + const uint8_t r5 = (rawPixel >> 10) & 0x1F; + const uint8_t g5 = (rawPixel >> 5) & 0x1F; + const uint8_t b5 = rawPixel & 0x1F; + + // Expand 5-bit to 8-bit + const uint8_t r8 = (r5 << 3) | (r5 >> 2); + const uint8_t g8 = (g5 << 3) | (g5 >> 2); + const uint8_t b8 = (b5 << 3) | (b5 >> 2); + + const uint8_t grayVal = static_cast((r8 * 77 + g8 * 150 + b8 * 29) >> 8); + + pixelPtr[i] = recolors_rgb555[grayVal]; + } else { + // Pixel is translucent + const uint16_t alpha3 = rawPixel & 0x7000; + + const uint8_t r4 = (rawPixel >> 8) & 0x0F; + const uint8_t g4 = (rawPixel >> 4) & 0x0F; + const uint8_t b4 = rawPixel & 0x0F; + + // Expand 4-bit to 8-bit + const uint8_t r8 = (r4 << 4) | r4; + const uint8_t g8 = (g4 << 4) | g4; + const uint8_t b8 = (b4 << 4) | b4; + + const uint8_t grayVal = static_cast((r8 * 77 + g8 * 150 + b8 * 29) >> 8); + + // Combine original alpha with recolored RGB444 + pixelPtr[i] = alpha3 | recolors_rgb444[grayVal]; + } + } + + pixelPtr += totalPixels; + mipWidth = std::max(1u, mipWidth >> 1); + mipHeight = std::max(1u, mipHeight >> 1); + } +} + +// Function to encode a single 4x4 sub-block (16 pixels) into an 8-byte CMPR block +static void encode_cmpr_sub_block(uint8_t* dst, const uint8_t pixels[16]) { + uint8_t min_val = 255; + uint8_t max_val = 0; + + for (int i = 0; i < 16; ++i) { + if (pixels[i] < min_val) min_val = pixels[i]; + if (pixels[i] > max_val) max_val = pixels[i]; + } + + auto intensity_to_rgb565 = [](uint8_t val) -> uint16_t { + uint16_t r5 = val >> 3; + uint16_t g6 = val >> 2; + uint16_t b5 = val >> 3; + return static_cast((r5 << 11) | (g6 << 5) | b5); + }; + + uint16_t c0_565 = intensity_to_rgb565(max_val); + uint16_t c1_565 = intensity_to_rgb565(min_val); + uint32_t indices = 0; + + if (max_val > min_val) { + // Enforce c0_565 > c1_565 in unsigned 16-bit representation to use 4-color mode + if (c0_565 == c1_565) { + if ((c0_565 & 0x001F) < 0x001F) { + c0_565 += 1; + } else { + c1_565 -= 1; + } + } + + // Interpolated 8-bit intensity values for quantization + const int c0 = max_val; + const int c1 = min_val; + const int c2 = (2 * max_val + min_val) / 3; + const int c3 = (max_val + 2 * min_val) / 3; + + // Map each pixel to the nearest palette entry + for (int i = 0; i < 16; ++i) { + const int p = pixels[i]; + const int d0 = std::abs(p - c0); + const int d1 = std::abs(p - c1); + const int d2 = std::abs(p - c2); + const int d3 = std::abs(p - c3); + + uint32_t best_idx = 0; + int min_d = d0; + + if (d1 < min_d) { min_d = d1; best_idx = 1; } + if (d2 < min_d) { min_d = d2; best_idx = 2; } + if (d3 < min_d) { min_d = d3; best_idx = 3; } + + indices |= (best_idx << (30 - (2 * i))); + } + } + + // Account for big endian data expectation + dst[0] = static_cast(c0_565 >> 8); + dst[1] = static_cast(c0_565 & 0xFF); + dst[2] = static_cast(c1_565 >> 8); + dst[3] = static_cast(c1_565 & 0xFF); + dst[4] = static_cast(indices >> 24); + dst[5] = static_cast((indices >> 16) & 0xFF); + dst[6] = static_cast((indices >> 8) & 0xFF); + dst[7] = static_cast(indices & 0xFF); +} + +bool convert_i8_to_cmpr(TextureReplacementData& replacementData, std::vector& cmprOut) { + if (cmprOut.empty()) { + return false; + } + + const uint8_t mipCount = (replacementData.data.mip_count > 0) ? replacementData.data.mip_count : 1; + const auto expectedInputSize = get_image_data_size( + GX_TF_I8, replacementData.key.width, replacementData.key.height, mipCount); + if (cmprOut.size() < expectedInputSize) { + return false; + } + + const auto sourceData = cmprOut; + std::vector convertedData(get_image_data_size( + GX_TF_CMPR, replacementData.key.width, replacementData.key.height, mipCount)); + uint32_t mipWidth = replacementData.key.width; + uint32_t mipHeight = replacementData.key.height; + + const uint8_t* readPtr = sourceData.data(); + uint8_t* writePtr = convertedData.data(); + + for (uint8_t mip = 0; mip < mipCount; ++mip) { + const uint32_t paddedWidthI8 = (mipWidth + 7) & ~7; + const uint32_t paddedHeightI8 = (mipHeight + 3) & ~3; + const uint32_t tilesX_I8 = paddedWidthI8 / 8; + + const uint32_t paddedWidthCMPR = (mipWidth + 7) & ~7; + const uint32_t paddedHeightCMPR = (mipHeight + 7) & ~7; + const uint32_t blocksX_CMPR = paddedWidthCMPR / 8; + const uint32_t blocksY_CMPR = paddedHeightCMPR / 8; + + for (uint32_t by = 0; by < blocksY_CMPR; ++by) { + for (uint32_t bx = 0; bx < blocksX_CMPR; ++bx) { + uint8_t subBlockPixels[4][16]{}; + + for (uint32_t subBlockY = 0; subBlockY < 2; ++subBlockY) { + for (uint32_t subBlockX = 0; subBlockX < 2; ++subBlockX) { + const uint32_t subBlock = subBlockY * 2 + subBlockX; + for (uint32_t row = 0; row < 4; ++row) { + for (uint32_t col = 0; col < 4; ++col) { + const uint32_t x = bx * 8 + subBlockX * 4 + col; + const uint32_t y = by * 8 + subBlockY * 4 + row; + if (x >= mipWidth || y >= mipHeight) { + continue; + } + + const uint32_t tile = (y / 4) * tilesX_I8 + (x / 8); + const uint32_t tileOffset = (y % 4) * 8 + (x % 8); + subBlockPixels[subBlock][row * 4 + col] = + readPtr[tile * 32 + tileOffset]; + } + } + } + } + + for (const auto& subBlockPixel : subBlockPixels) { + encode_cmpr_sub_block(writePtr, subBlockPixel); + writePtr += 8; + } + } + } + + const uint32_t tilesY_I8 = paddedHeightI8 / 4; + readPtr += tilesX_I8 * tilesY_I8 * 32; + + mipWidth = std::max(1u, mipWidth >> 1); + mipHeight = std::max(1u, mipHeight >> 1); + } + + cmprOut.swap(convertedData); + + // Update format + replacementData.data.gx_format = GX_TF_CMPR; + + return true; +} + +void recolor_texture(TextureReplacementData& replacementData, GXColor color, std::vector& newTextureDataOut) { + + switch (replacementData.key.gx_format) { + case GX_TF_CMPR: + recolor_cmpr_texture(replacementData, color, newTextureDataOut); + break; + case GX_TF_RGB5A3: + recolor_rgb5a3_texture(replacementData, color, newTextureDataOut); + break; + case GX_TF_I8: + if (convert_i8_to_cmpr(replacementData, newTextureDataOut)) { + recolor_cmpr_texture(replacementData, color, newTextureDataOut); + } else { + mods::log::debug("Could not convert {} from i8 to cmpr", replacementData.textureName); + } + break; + default: + break; + } +} + +std::unordered_map>& get_texture_replacements() { + static std::unordered_map> replacements{}; + + if (replacements.empty()) { + replacements = { + {get_cvars().herosTunicCapColor, { + { + .arc = "Kmdl", + .modelFileName = "al_head.bmd", + .textureName = "al_cap", + } + }}, + {get_cvars().herosTunicTorsoColor, { + { + .arc = "Kmdl", + .modelFileName = "al.bmd", + .textureName = "al_upbody", + } + }}, + {get_cvars().herosTunicSkirtColor, { + { + .arc = "Kmdl", + .modelFileName = "al.bmd", + .textureName = "al_lowbody", + } + }}, + {get_cvars().zoraArmorCapColor, { + { + .arc = "Zmdl", + .modelFileName = "zl_head.bmd", + .textureName = "zl_cap", + } + }}, + {get_cvars().zoraArmorHelmetColor, { + { + .arc = "Zmdl", + .modelFileName = "zl_head.bmd", + .textureName = "zl_helmet", + } + }}, + {get_cvars().zoraArmorTorsoColor, { + { + .arc = "Zmdl", + .modelFileName = "zl.bmd", + .textureName = "zl_armor", + }, + { + .arc = "Zmdl", + .modelFileName = "zl.bmd", + .textureName = "zl_armL", + } + }}, + {get_cvars().zoraArmorScalesColor, { + { + .arc = "Zmdl", + .modelFileName = "zl.bmd", + .textureName = "zl_body", + } + }}, + {get_cvars().zoraArmorFlippersColor, { + { + .arc = "Zmdl", + .modelFileName = "zl.bmd", + .textureName = "zl_boots", + } + }}, + {get_cvars().woodenSwordColor, { + { + .arc = "Bmdl", // Ordon Clothes Model + .modelFileName = "al_swb.bmd", + .textureName = "al_SWB", + }, + { + .arc = "Kmdl", // Hero's Tunic Model + .modelFileName = "al_swb.bmd", + .textureName = "al_SWB", + }, + { + .arc = "Zmdl", // Zora Armor Model + .modelFileName = "al_swb.bmd", + .textureName = "al_SWB", + }, + { + .arc = "Mmdl", // Magic Armor Model + .modelFileName = "al_swb.bmd", + .textureName = "al_SWB", + }, + { + .arc = "O_gD_SWB", // Get Item Model + .modelFileName = "o_gd_al_swb.bmd", + .textureName = "al_SWB", + } + }}, + {get_cvars().ordonSwordHandleColor, { + { + .arc = "Alink", + .modelFileName = "al_swa.bmd", + .textureName = "al_SWgripA", + }, + { + .arc = "O_gD_SWA", // Get Item Model + .modelFileName = "o_gd_al_swa.bmd", + .textureName = "al_SWgripA", + } + }}, + {get_cvars().ordonSwordBladeColor, { + { + .arc = "Alink", + .modelFileName = "al_swa.bmd", + .textureName = "al_SWA", + } + }}, + {get_cvars().msHandleColor, { + { + .arc = "Alink", + .modelFileName = "al_swm.bmd", + .textureName = "al_SWgripM", + } + }}, + {get_cvars().msBladeColor, { + { + .arc = "Alink", + .modelFileName = "al_swm.bmd", + .textureName = "al_SWM", + } + }}, + {get_cvars().boomerangColor, { + { + .arc = "Alink", // Boomerang in Link's hand + .modelFileName = "al_boom.bmd", + .textureName = "L_al_boom00", + }, + { + .arc = "E_mk", // Boomerang in Ook's hand + .modelFileName = "bm.bmd", + .textureName = "L_al_boom00", + }, + { + .arc = "E_mk", // Boomerang in Ook's hand + .modelFileName = "bm.bmd", + .textureName = "bm_boom", + }, + { + .arc = "O_gD_boom", // Get Item Model + .modelFileName = "o_gd_boom.bmd", + .textureName = "L_al_boom00", + } + }}, + {get_cvars().ironBootsColor, { + { + .arc = "Bmdl", // Ordon Clothes Model + .modelFileName = "al_bootsh.bmd", + .textureName = "al_bootsH", + }, + { + .arc = "Kmdl", // Hero's Tunic Model + .modelFileName = "al_bootsh.bmd", + .textureName = "al_bootsH", + }, + { + .arc = "Zmdl", // Zora Armor Model + .modelFileName = "al_bootsh.bmd", + .textureName = "al_bootsH", + }, + { + .arc = "Mmdl", // Magic Armor Model + .modelFileName = "al_bootsh.bmd", + .textureName = "al_bootsH", + }, + { + .arc = "O_gD_boot", // Get Item Model + .modelFileName = "o_gd_al_bootsh.bmd", + .textureName = "al_bootsH", + } + }}, + {get_cvars().spinnerColor, { + { + .arc = "Alink", // Spinner used by Link + .modelFileName = "al_sp.bmd", + .textureName = "al_SP", + }, + { + .arc = "O_gD_SP", // Get Item Model + .modelFileName = "o_gd_al_sp.bmd", + .textureName = "al_SP", + } + }}, + {get_cvars().linkHairColor, { + { + .arc = "Bmdl", // Ordon Clothes Model + .modelFileName = "bl_head.bmd", + .textureName = "bl_hair", + }, + { + .arc = "Kmdl", // Hero's Tunic Model + .modelFileName = "al_head.bmd", + .textureName = "al_hair", + }, + { + .arc = "Mmdl", // Magic Armor Model + .modelFileName = "ml_head.bmd", + .textureName = "al_hair", + } + }}, + {get_cvars().wolfLinkColor, { + { + .arc = "Wmdl", + .modelFileName = "wl.bmd", + .textureName = "wl_body", + }, + { + .arc = "Wmdl", + .modelFileName = "wl.bmd", + .textureName = "wl_eye.1", + }, + { + .arc = "Wmdl", + .modelFileName = "wl.bmd", + .textureName = "wl_eye.2", + }, + { + .arc = "Wmdl", + .modelFileName = "wl.bmd", + .textureName = "wl_eye.3", + }, + { + .arc = "Wmdl", + .modelFileName = "wl.bmd", + .textureName = "wl_eye.4", + }, + { + .arc = "Wmdl", + .modelFileName = "wl.bmd", + .textureName = "wl_eye.5", + } + }}, + {get_cvars().eponaColor, { + { + .arc = "Horse", + .modelFileName = "hs.bmd", + .textureName = "hs_body", + }, + { + .arc = "Horse", + .modelFileName = "hs.bmd", + .textureName = "hs_eye.1", + }, + { + .arc = "Horse", + .modelFileName = "hs.bmd", + .textureName = "hs_eye.2", + }, + { + .arc = "Horse", + .modelFileName = "hs.bmd", + .textureName = "hs_eye.3", + }, + }}, + }; + } + + return replacements; +} diff --git a/mods/basic_cosmetics_mod/src/texture_utils.hpp b/mods/basic_cosmetics_mod/src/texture_utils.hpp new file mode 100644 index 0000000000..49dd0df81a --- /dev/null +++ b/mods/basic_cosmetics_mod/src/texture_utils.hpp @@ -0,0 +1,21 @@ +#pragma once + +/** + * File originally copied from console TPR with permission from isaac + * https://github.com/zsrtp/libtp_rel/blob/master/include/util/texture_utils.h + */ + +#include "mod.hpp" + +#include + +#include +#include + +uint32_t get_image_data_size( + uint32_t format, uint32_t width, uint32_t height, uint32_t mipmapCount); + +void recolor_texture( + TextureReplacementData& replacementData, GXColor color, std::vector& newTextureDataOut); + +std::unordered_map>& get_texture_replacements(); diff --git a/mods/flow_demo/src/mod.cpp b/mods/flow_demo/src/mod.cpp index e4d18a90f0..a05150458b 100644 --- a/mods/flow_demo/src/mod.cpp +++ b/mods/flow_demo/src/mod.cpp @@ -177,18 +177,20 @@ MOD_EXPORT ModResult mod_initialize(ModError* outError) { if (result == MOD_OK) { result = add_message(mods::flow::MessageBuilder{kResponseStyle} .text_color(MESSAGE_COLOR_DEFAULT) - .text("Hello from ") - .text_color(MESSAGE_COLOR_RED) - .text("FlowService") + .text("Custom ") + .text_color(0xFF0000FF) + .text("colors") + .text_color(MESSAGE_COLOR_DEFAULT) + .text(" and even ") + .text_color(0x00FF00FF, 0x00FFFFFF) + .text("gradients") .text_color(MESSAGE_COLOR_DEFAULT) - .text(", ") - .player_name() .text("!\n") .character_delay(3) .text("This text is slow. ") .character_delay(0) .pause(12) - .text_scale(125) + .text_scale(150) .text("Big") .text_scale(100) .text(" text too.") diff --git a/mods/shadow_mod/CMakeLists.txt b/mods/shadow_mod/CMakeLists.txt index ae44eca49c..3f2e6b9412 100644 --- a/mods/shadow_mod/CMakeLists.txt +++ b/mods/shadow_mod/CMakeLists.txt @@ -17,5 +17,4 @@ add_mod(shadow_mod SOURCES src/mod.cpp MOD_JSON mod.json RES_DIR res - BUNDLE ) diff --git a/mods/window_demo/CMakeLists.txt b/mods/window_demo/CMakeLists.txt index 9150ec7de6..4257f9686e 100644 --- a/mods/window_demo/CMakeLists.txt +++ b/mods/window_demo/CMakeLists.txt @@ -16,5 +16,4 @@ add_mod(window_demo FEATURES fmt webgpu SOURCES src/logging.cpp src/mod.cpp MOD_JSON mod.json - BUNDLE ) diff --git a/mods/window_demo/src/mod.cpp b/mods/window_demo/src/mod.cpp index 00d6f1240b..0a1e9333ff 100644 --- a/mods/window_demo/src/mod.cpp +++ b/mods/window_demo/src/mod.cpp @@ -188,8 +188,6 @@ MOD_EXPORT ModResult mod_initialize(ModError* error) { g_stageHook = 0; return mods::set_error(error, MOD_ERROR, "failed to register mod panel"); } - - mods::log::info("auxiliary WebGPU window ready"); return MOD_OK; } diff --git a/res/rml/popover.rcss b/res/rml/popover.rcss new file mode 100644 index 0000000000..1db4f64a05 --- /dev/null +++ b/res/rml/popover.rcss @@ -0,0 +1,184 @@ +*, *:before, *:after { + box-sizing: border-box; +} + +body { + width: 100%; + height: 100%; + z-index: 10; +} + +popover { + position: absolute; + display: flex; + flex-flow: column; + font-family: "Fira Sans"; + font-size: 14dp; + color: #E0DBC8; + border-radius: 14dp; + border: 2dp #92875B; + background-color: rgba(21, 22, 16, 96%); + backdrop-filter: blur(5dp); + box-shadow: 0 6dp 24dp 2dp rgba(0, 0, 0, 55%); + filter: opacity(0); + transform: scale(0.95); + transform-origin: center; + transition: filter transform 0.15s cubic-in-out; + focus: auto; +} + +popover[open] { + filter: opacity(1); + transform: scale(1); +} + +popover.color-picker { + width: 280dp; + padding: 18dp; + gap: 10dp; +} + +color-sv { + display: block; + position: relative; + width: 240dp; + height: 150dp; + border-radius: 8dp; + box-shadow: rgba(146, 135, 91, 50%) 0 0 0 1dp; + drag: drag; + focus: auto; +} + +color-hue, +color-alpha { + display: block; + position: relative; + width: 240dp; + height: 14dp; + border-radius: 7dp; + box-shadow: rgba(146, 135, 91, 50%) 0 0 0 1dp; + drag: drag; + focus: auto; +} + +color-sv:focus-visible, +color-hue:focus-visible, +color-alpha:focus-visible { + box-shadow: #C2A42D 0 0 0 2dp; +} + +color-sv.adjusting, +color-hue.adjusting, +color-alpha.adjusting { + box-shadow: #FFFFFF 0 0 0 3dp; +} + +color-hue { + decorator: linear-gradient(90deg, #ff0000, #ffff00, #00ff00, #00ffff, #0000ff, #ff00ff, #ff0000); +} + +color-cursor { + display: block; + position: absolute; + width: 14dp; + height: 14dp; + border-radius: 7dp; + border: 2dp #ffffff; + box-shadow: 0 0 4dp 1dp rgba(0, 0, 0, 70%); + pointer-events: none; +} + +color-heading { + display: block; + margin-top: 2dp; + font-family: "Fira Sans Condensed"; + font-weight: bold; + font-size: 13dp; + text-transform: uppercase; + color: rgba(224, 219, 200, 55%); +} + +color-presets { + display: flex; + flex-flow: row wrap; + gap: 5dp; +} + +color-history { + display: flex; + flex-flow: row wrap; + gap: 5dp; +} + +button.color-swatch-button { + width: 25dp; + height: 25dp; + padding: 0; + border-radius: 7dp; +} + +color-chip { + display: block; + flex: 0 0 20dp; + width: 20dp; + height: 20dp; + border-radius: 5dp; + box-shadow: rgba(255, 255, 255, 45%) 0 0 0 1dp; +} + +button.color-swatch-button color-chip { + width: 25dp; + height: 25dp; + border-radius: 7dp; +} + +color-chip.empty, +color-swatch.empty { + background-color: rgba(224, 219, 200, 12%); + decorator: linear-gradient(135deg, rgba(224, 219, 200, 0) 45%, + rgba(194, 164, 45, 70%) 48%, rgba(194, 164, 45, 70%) 52%, + rgba(224, 219, 200, 0) 55%); +} + +color-footer { + display: flex; + align-items: center; + gap: 6dp; + padding-top: 2dp; +} + +button { + background-color: rgba(17, 16, 10, 35%); + padding: 4dp 8dp; + border-radius: 8dp; + box-shadow: rgba(146, 135, 91, 30%) 0 0 0 1dp; + color: #E0DBC8; + cursor: pointer; + focus: auto; +} + +button:hover, +button:focus-visible { + background-color: rgba(204, 184, 119, 20%); + box-shadow: #C2A42D 0 0 0 2dp; +} + +button:active { + background-color: rgba(204, 184, 119, 40%); +} + +color-value { + display: block; + flex: 1 1 auto; + text-align: right; + font-family: "Noto Mono"; + font-size: 12dp; + color: #FFFFFF; + cursor: pointer; + focus: auto; +} + +color-value:hover, +color-value:focus-visible { + color: #C2A42D; +} diff --git a/res/rml/window.rcss b/res/rml/window.rcss index 8ca2f80760..98b63dfcd9 100644 --- a/res/rml/window.rcss +++ b/res/rml/window.rcss @@ -48,6 +48,12 @@ window.modal { max-width: 640dp; } +@media (max-height: 896dp) { + window.modal { + max-height: 100%; + } +} + window[open] { filter: opacity(1); transform: scale(1); @@ -62,6 +68,16 @@ window[open] { } } +@media (max-width: 768dp) { + body { + padding: 16dp; + } + window.modal { + width: 100%; + max-width: 100%; + } +} + window tab-bar { flex: 0 0 64dp; height: 64dp; @@ -91,7 +107,6 @@ window content pane { min-width: 0; min-height: 0; padding: 24dp; - padding-bottom: 0dp; gap: 8dp; overflow: hidden auto; font-size: 20dp; @@ -105,6 +120,76 @@ window content pane > * { flex: 0 0 auto; } +ui-list { + display: flex; + flex-flow: column; + flex: 1 1 0; + min-width: 0; + min-height: 0; +} + +window content pane > ui-list, +.modal-content pane > ui-list { + flex: 1 1 0; + min-width: 0; + min-height: 0; +} + +ui-list-viewport { + display: block; + flex: 1 1 0; + min-width: 0; + min-height: 0; + overflow: hidden auto; +} + +ui-list-content { + display: flex; + flex-flow: column; + gap: 8dp; + min-width: 0; +} + +ui-list-content > button.ui-list-row { + flex: 0 0 auto; +} + +ui-list-empty { + display: block; + padding: 16dp; + text-align: center; + opacity: 0.45; +} + +window content pane > ui-list { + margin-left: -24dp; + margin-right: -24dp; +} + +window content pane > ui-list:first-child { + margin-top: -24dp; +} + +window content pane > ui-list:last-child { + margin-bottom: -24dp; +} + +window content pane > ui-list ui-list-content, +window content pane > ui-list ui-list-empty { + padding-left: 24dp; + padding-right: 24dp; +} + +window content pane > ui-list:first-child ui-list-content, +window content pane > ui-list:first-child ui-list-empty { + padding-top: 24dp; +} + +window content pane > ui-list:last-child ui-list-content, +window content pane > ui-list:last-child ui-list-empty { + padding-bottom: 24dp; +} + window content pane:last-of-type > div { line-height: 1.625; } @@ -115,14 +200,6 @@ window content pane:last-of-type > div { color: rgba(224, 219, 200, 65%); } -window content pane > spacer { - display: block; - /* Completes the 24dp bottom inset after the pane's 8dp gap. */ - flex: 0 0 16dp; - height: 16dp; - pointer-events: none; -} - scrollbarvertical { width: 8dp; margin: 4dp 4dp 4dp 0; @@ -278,6 +355,40 @@ select-button input { font-size: 20dp; } +select-button.group-button icon { + flex: 0 0 24dp; + margin-left: auto; + width: 24dp; + height: 24dp; + font-size: 24dp; + color: inherit; + decorator: text("" center center); +} + +select-button.group-button value { + display: none; +} + +select-button.color-input value { + min-width: 0; + font-family: "Noto Mono"; + font-size: 15dp; +} + +select-button.color-input color-swatch { + display: block; + flex: 0 0 48dp; + width: 48dp; + height: 24dp; + border-radius: 7dp; + box-shadow: rgba(255, 255, 255, 45%) 0 0 0 1dp; +} + +select-button.color-input color-swatch.empty { + background-color: rgba(224, 219, 200, 12%); + decorator: linear-gradient(135deg, rgba(224, 219, 200, 0) 45%, rgba(194, 164, 45, 70%) 48%, rgba(194, 164, 45, 70%) 52%, rgba(224, 219, 200, 0) 55%); +} + icon { width: 1em; height: 1em; @@ -385,14 +496,17 @@ progress { margin: 6dp 0 2dp 0; } +progress fill { + background-color: rgba(194, 164, 45, 80%); + border-radius: 3dp; +} + progress.progress-done fill { background-color: #44aa22; - border-radius: 3dp; } progress.progress-ongoing fill { background-color: #2255bb; - border-radius: 3dp; } button.achievement-clear { @@ -432,7 +546,9 @@ button.achievement-clear { padding: 24dp; gap: 20dp; flex: 0 1 auto; + min-height: 0; width: 100%; + overflow: hidden; text-align: left; } @@ -473,7 +589,7 @@ window.modal.danger .modal-header icon { .modal-body { display: block; width: 100%; - flex: 0 1 auto; + flex: 0 0 auto; min-width: 0; font-size: 20dp; color: #FFFFFF; @@ -485,6 +601,33 @@ window.modal.danger .modal-header icon { color: #92875B; } +.modal-content { + display: none; + width: 100%; + flex: 1 1 auto; + min-height: 0; + overflow: hidden; +} + +.modal-content.active { + display: flex; + flex-direction: column; +} + +.modal-content pane { + display: flex; + flex: 1 1 auto; + flex-direction: column; + min-height: 0; + width: 100%; + gap: 8dp; + overflow: hidden auto; +} + +.modal-content pane > * { + flex: 0 0 auto; +} + .verification-progress { display: flex; flex-direction: column; @@ -529,3 +672,25 @@ progress.verification-progress-bar { flex: 0 0 auto; width: 100%; } + +@media (max-height: 640dp) { + .modal-dialog { + padding: 16dp; + gap: 12dp; + } + + .modal-body { + font-size: 17dp; + } +} + +@media (max-width: 640dp) { + .modal-actions { + flex-direction: column; + } + + .modal-actions button.modal-btn { + flex: 0 0 auto; + width: 100%; + } +} diff --git a/sdk/include/mods/items.h b/sdk/include/mods/items.h new file mode 100644 index 0000000000..b79563026c --- /dev/null +++ b/sdk/include/mods/items.h @@ -0,0 +1,65 @@ +#pragma once + +/* + * ItemService check names. + */ + +#define ITEM_CHECK_BOSS_PREFIX "boss:" /* */ +#define ITEM_CHECK_BUG_PREFIX "bug:" /* */ +#define ITEM_CHECK_CHEST_PREFIX "chest:" /* : */ +#define ITEM_CHECK_FREESTANDING_PREFIX "freestanding:" /* : */ +#define ITEM_CHECK_GOLDEN_WOLF_PREFIX "golden_wolf:" /* */ +#define ITEM_CHECK_POE_PREFIX "poe:" /* : */ +#define ITEM_CHECK_SHOP_PREFIX "shop:" /* : */ +#define ITEM_CHECK_SKY_PREFIX "sky:" /* : */ +#define ITEM_CHECK_DUNGEON_REWARD_PREFIX "dungeon_reward:" /* */ + +#define ITEM_CHECK_ARCHERY_REWARD "archery_reward:F_SP109" +#define ITEM_CHECK_ASHEI_SKETCH "ashei_sketch" +#define ITEM_CHECK_AURU_MEMO "auru_memo" +#define ITEM_CHECK_BALL_AND_CHAIN "ball_and_chain:D_MN11" +#define ITEM_CHECK_BULBLIN_KEY "bulblin_key:D_MN09" +#define ITEM_CHECK_CORAL_EARRING "coral_earring" +#define ITEM_CHECK_CORO_BOTTLE "coro_bottle" +#define ITEM_CHECK_DUNGEON_MAP_SNOWPEAK "dungeon_map:D_MN11" +#define ITEM_CHECK_FAIRY_REWARD "fairy_reward:D_SB01" +#define ITEM_CHECK_FISHING_BOTTLE "fishing_bottle" +#define ITEM_CHECK_FISHING_HEART_PIECE "fishing_heart_piece" +#define ITEM_CHECK_GOATS_REWARD "goats_reward" +#define ITEM_CHECK_GORON_REWARD "goron_reward:F_SP113" +#define ITEM_CHECK_GORON_SPRINGWATER_RUSH "goron_springwater_rush" +#define ITEM_CHECK_ILIA_CHARM "ilia_charm" +#define ITEM_CHECK_ILIA_MEMORY "ilia_memory" +#define ITEM_CHECK_IZA_REWARD_1 "iza_reward_1" +#define ITEM_CHECK_IZA_REWARD_2 "iza_reward_2" +#define ITEM_CHECK_JOVANI_REWARD_1 "jovani_reward_1" +#define ITEM_CHECK_JOVANI_REWARD_2 "jovani_reward_2" +#define ITEM_CHECK_KEY_SHARD_1 "key_shard_1:D_MN04" +#define ITEM_CHECK_KEY_SHARD_2 "key_shard_2:D_MN04" +#define ITEM_CHECK_KEY_SHARD_3 "key_shard_3:D_MN04" +#define ITEM_CHECK_ORDON_SHIELD "ordon_shield" +#define ITEM_CHECK_ORDON_SWORD "ordon_sword" +#define ITEM_CHECK_PLUMM_REWARD "plumm_minigame_reward" +#define ITEM_CHECK_PRAYER_REWARD "prayer_reward" +#define ITEM_CHECK_RENADO_LETTER "renado_letter" +#define ITEM_CHECK_SERA_REWARD "sera_reward" +#define ITEM_CHECK_SHAD_DOMINION_ROD "shad_dominion_rod" +#define ITEM_CHECK_SKYBOOK "skybook" +#define ITEM_CHECK_SNOWBOARD_REWARD "snowboard_race_reward" +#define ITEM_CHECK_STAR_REWARD_1 "star_reward_1" +#define ITEM_CHECK_STAR_REWARD_2 "star_reward_2" +#define ITEM_CHECK_TELMA_INVOICE "telma_invoice" +#define ITEM_CHECK_ULI_CRADLE_REWARD "uli_cradle_reward" +#define ITEM_CHECK_WOOD_STATUE "wood_statue" +#define ITEM_CHECK_ZORA_ARMOR "zora_armor" + +#define ITEM_CHECK_DUNGEON_REWARD_FOREST "dungeon_reward:D_MN05" +#define ITEM_CHECK_DUNGEON_REWARD_GORON "dungeon_reward:D_MN04" +#define ITEM_CHECK_DUNGEON_REWARD_LAKEBED "dungeon_reward:D_MN01" +#define ITEM_CHECK_DUNGEON_REWARD_ARBITERS "dungeon_reward:D_MN10" +#define ITEM_CHECK_DUNGEON_REWARD_SNOWPEAK "dungeon_reward:D_MN11" +#define ITEM_CHECK_DUNGEON_REWARD_TIME "dungeon_reward:D_MN06" +#define ITEM_CHECK_DUNGEON_REWARD_CITY "dungeon_reward:D_MN07" + +#define ITEM_CHECK_MASTER_SWORD "master_sword" +#define ITEM_CHECK_SHADOW_CRYSTAL "shadow_crystal" diff --git a/sdk/include/mods/svc/flow.hpp b/sdk/include/mods/svc/flow.hpp index 2b1cb1b594..c7671f69a6 100644 --- a/sdk/include/mods/svc/flow.hpp +++ b/sdk/include/mods/svc/flow.hpp @@ -100,6 +100,7 @@ public: NodeRef next(uint16_t target) const; /* Set a branch node's result targets */ NodeRef results(std::initializer_list targets) const; + NodeRef results(std::span targets) const; uint16_t id() const { return mId; } operator uint16_t() const { return mId; } @@ -153,6 +154,35 @@ public: } return *this; } + GraphBuilder& patch_branch(uint16_t nodeIndex, FlowQueryId query, uint16_t parameter, + std::span targets) { + if (mResult != MOD_OK || targets.empty() || targets.size() > 0xff) { + if (mResult == MOD_OK) { + mResult = MOD_INVALID_ARGUMENT; + } + return *this; + } + uint16_t first = 0; + mResult = svc_flow->add_edges( + mod_ctx, mHandle, targets.data(), static_cast(targets.size()), &first); + if (mResult == MOD_OK) { + patch_node(nodeIndex, + branch(static_cast(targets.size()), query, parameter, first)); + } + return *this; + } + GraphBuilder& patch_event(uint16_t nodeIndex, FlowEventId eventId, + std::array params, uint16_t target) { + if (mResult != MOD_OK) { + return *this; + } + uint16_t edge = 0; + mResult = svc_flow->add_edges(mod_ctx, mHandle, &target, 1, &edge); + if (mResult == MOD_OK) { + patch_node(nodeIndex, event(eventId, edge, params)); + } + return *this; + } Graph commit() { for (const auto& node : mNodes) { @@ -232,7 +262,7 @@ private: } } - void set_results(uint16_t id, std::initializer_list targets) { + void set_results(uint16_t id, std::span targets) { if (mResult != MOD_OK) { return; } @@ -246,7 +276,7 @@ private: node->wired = true; uint16_t first = 0; mResult = svc_flow->add_edges( - mod_ctx, mHandle, targets.begin(), static_cast(targets.size()), &first); + mod_ctx, mHandle, targets.data(), static_cast(targets.size()), &first); if (mResult == MOD_OK) { node->data.bytes[1] = static_cast(targets.size()); write_bits(node->data.bytes + 6, first); @@ -266,6 +296,10 @@ inline NodeRef NodeRef::next(uint16_t target) const { } inline NodeRef NodeRef::results(std::initializer_list targets) const { + return results(std::span{targets.begin(), targets.size()}); +} + +inline NodeRef NodeRef::results(std::span targets) const { if (mBuilder != nullptr) { mBuilder->set_results(mId, targets); } @@ -368,6 +402,10 @@ public: [[nodiscard]] constexpr MessageStyle face_anim(uint8_t value) const { return set_u8(17, value); } + /* INF1 bytes 18-19, normally 0x0400. */ + [[nodiscard]] constexpr MessageStyle trailing_data(uint16_t value) const { + return set_u16(18, value); + } [[nodiscard]] constexpr const MessageEntryData& data() const { return mData; } private: @@ -432,6 +470,9 @@ public: MessageBuilder& camera_attr(uint8_t value) { return style(&MessageStyle::camera_attr, value); } MessageBuilder& talk_anim(uint8_t value) { return style(&MessageStyle::talk_anim, value); } MessageBuilder& face_anim(uint8_t value) { return style(&MessageStyle::face_anim, value); } + MessageBuilder& trailing_data(uint16_t value) { + return style(&MessageStyle::trailing_data, value); + } /* Content builder functions */ MessageBuilder& text(std::string_view value) { @@ -459,7 +500,20 @@ public: } MessageBuilder& text_color(MessageTextColor color) { const auto index = static_cast(color); - return raw_tag(255, 0, {&index, 1}); + return raw_tag(0xFF, 0, {&index, 1}); + } + /* Full 32-bit text color (Dusklight extension) */ + MessageBuilder& text_color(uint32_t rgba) { + std::array arguments{}; + write_bits(arguments.data(), rgba); + return raw_tag(0xFF, 0, arguments); + } + /* Full 32-bit text vertical gradient colors (Dusklight extension) */ + MessageBuilder& text_color(uint32_t upperRgba, uint32_t lowerRgba) { + std::array arguments{}; + write_bits(arguments.data(), upperRgba); + write_bits(arguments.data() + sizeof(upperRgba), lowerRgba); + return raw_tag(0xFF, 0, arguments); } MessageBuilder& text_scale(uint16_t percent) { return timed_tag(255, 1, percent); } MessageBuilder& character_delay(uint16_t frames) { return timed_tag(0, 6, frames); } diff --git a/sdk/include/mods/svc/item.h b/sdk/include/mods/svc/item.h index 81a2589f6d..94fec6fb6c 100644 --- a/sdk/include/mods/svc/item.h +++ b/sdk/include/mods/svc/item.h @@ -8,7 +8,7 @@ #define ITEM_SERVICE_ID "dev.twilitrealm.dusklight.item" #define ITEM_SERVICE_MAJOR 2u -#define ITEM_SERVICE_MINOR 0u +#define ITEM_SERVICE_MINOR 1u /* 0 is never a valid handle. */ typedef uint64_t ItemCheckHandle; @@ -17,10 +17,12 @@ typedef uint64_t ItemGiveHandle; /* * Item check resolution and inventory grants. * - * Check names are case-sensitive. Resolvers must be free of side effects because the game may - * resolve a check more than once, including once for display and again when granting the item. - * Registrations and pending grants are removed when the calling mod is detached. Callbacks run - * on the game thread. + * Check names are case-sensitive. Resolvers must be free of side effects because previews may be + * resolved repeatedly. For checks representing a non-item side effect, vanilla_item is 0xFF: + * resolving to 0xFF preserves that side effect, while resolving to another item replaces it. + * + * Registrations and pending grants are removed when the calling mod is detached. Callbacks run on + * the game thread. Check names are listed in . */ /* Host-owned callback data, valid only for the duration of the callback. */ @@ -29,11 +31,17 @@ typedef struct ItemCheckInfo { const void* giver_actor; /* fopAc_ac_c*, or NULL when unavailable */ uint8_t vanilla_item; uint8_t current_item; + uint8_t current_display_item; } ItemCheckInfo; -/* Return true and write out_item to replace current_item, or false to leave it unchanged. */ +typedef struct ItemCheckResolution { + uint8_t item; + uint8_t display_item; /* leave unset (0xFF/NONE) to use the item */ +} ItemCheckResolution; + +/* Return true and write out_result to replace the result, or false to leave it unchanged. */ typedef bool (*ItemCheckResolveFn)( - ModContext* ctx, const ItemCheckInfo* info, uint8_t* out_item, void* user_data); + ModContext* ctx, const ItemCheckInfo* info, ItemCheckResolution* out_result, void* user_data); typedef enum ItemGiveOrigin { ITEM_GIVE_ORIGIN_GAME = 0, @@ -72,14 +80,14 @@ typedef struct ItemService { ModResult (*clear_check_resolver)(ModContext* ctx, ItemCheckHandle handle); - /* Resolve without granting an item or notifying give observers. */ + /* Resolve a live preview without granting an item or notifying give observers. */ ModResult (*resolve_check)( ModContext* ctx, const char* name, uint8_t vanilla_item, uint8_t* out_item); /* * Add a grant to the global FIFO. check_name may be NULL unless ITEM_GIVE_RESOLVE is set. - * Returns MOD_UNAVAILABLE when the queue is full. Entries wait until gameplay is in a safe - * state and are cleared when the active save slot changes. + * Entries wait until gameplay is in a safe state and are cleared when the active save slot + * changes. */ ModResult (*give_item)( ModContext* ctx, const char* check_name, uint8_t item_no, uint32_t flags); diff --git a/sdk/include/mods/svc/message.h b/sdk/include/mods/svc/message.h index 172dce4895..b170e6f09b 100644 --- a/sdk/include/mods/svc/message.h +++ b/sdk/include/mods/svc/message.h @@ -8,7 +8,7 @@ #define MESSAGE_SERVICE_ID "dev.twilitrealm.dusklight.message" #define MESSAGE_SERVICE_MAJOR 1u -#define MESSAGE_SERVICE_MINOR 0u +#define MESSAGE_SERVICE_MINOR 1u typedef uint16_t MessageId; typedef uint64_t MessageHandle; diff --git a/sdk/include/mods/svc/ui.h b/sdk/include/mods/svc/ui.h index e265f306fa..ea8abe2d7c 100644 --- a/sdk/include/mods/svc/ui.h +++ b/sdk/include/mods/svc/ui.h @@ -8,8 +8,8 @@ #endif #define UI_SERVICE_ID "dev.twilitrealm.dusklight.ui" -#define UI_SERVICE_MAJOR 1u -#define UI_SERVICE_MINOR 2u +#define UI_SERVICE_MAJOR 2u +#define UI_SERVICE_MINOR 1u /* * UI primitives: a panel inside the host Mods window, mod-owned windows, dialogs, toasts, @@ -51,6 +51,8 @@ typedef enum UiControlKind { UI_CONTROL_NUMBER = 2, /* integer stepper with min/max/step */ UI_CONTROL_STRING = 3, /* text input */ UI_CONTROL_SELECT = 4, /* one of `options`; the value is the option index */ + UI_CONTROL_COLOR = 5, /* RGB/RGBA color string with a picker */ + UI_CONTROL_GROUP = 6, /* navigation row (on_pressed) */ } UiControlKind; typedef enum UiControlBinding { @@ -60,14 +62,19 @@ typedef enum UiControlBinding { /* The control reads and writes `config_var` (a ConfigService handle owned by the calling mod) * directly: persistence, change notifications and the modified indicator (value != default) are * wired automatically. The var type must match the control kind: TOGGLE = bool, NUMBER and - * SELECT = int, STRING = string. Float vars are not bindable; use callbacks. */ + * SELECT = int, STRING and COLOR = string. Float vars are not bindable; use callbacks. */ UI_BINDING_CONFIG_VAR = 1, } UiControlBinding; +typedef enum UiStringSetMode { + UI_STRING_SET_ON_COMMIT = 0, /* invokes `set` when input is committed */ + UI_STRING_SET_ON_CHANGE = 1, /* invokes `set` on every text change (e.g. while typing) */ +} UiStringSetMode; + /* Tagged by the control's kind: TOGGLE reads bool_value, NUMBER and SELECT read int_value, STRING - * reads string_value. string_value passed to a setter is only valid during the call; a getter - * should point it at storage owned by the mod (e.g. a static buffer) that stays valid until the - * next call into the mod — the host copies it right after the getter returns. */ + * and COLOR read string_value. string_value passed to a setter is only valid during the call; a + * getter should point it at storage owned by the mod (e.g. a static buffer) that stays valid until + * the next call into the mod — the host copies it right after the getter returns. */ typedef struct UiControlValue { uint32_t struct_size; bool bool_value; @@ -91,16 +98,16 @@ typedef struct UiControlDesc { /* Optional RML shown as contextual help when the control is focused or hovered. Only rendered * where a help pane exists (mod window tabs). */ const char* help_rml; - UiControlBinding binding; /* ignored for BUTTON */ + UiControlBinding binding; /* ignored for BUTTON and GROUP */ ConfigVarHandle config_var; /* UI_BINDING_CONFIG_VAR */ - UiControlGetFn get; /* UI_BINDING_CALLBACKS (all kinds but BUTTON) */ - UiControlSetFn set; /* UI_BINDING_CALLBACKS (all kinds but BUTTON) */ - UiPressedFn on_pressed; /* BUTTON only. Required for BUTTON. */ + UiControlGetFn get; /* UI_BINDING_CALLBACKS (all kinds but BUTTON/GROUP) */ + UiControlSetFn set; /* UI_BINDING_CALLBACKS (all kinds but BUTTON/GROUP) */ + UiPressedFn on_pressed; /* BUTTON/GROUP only. Required for both. */ UiPredicateFn is_disabled; /* optional */ /* Optional override for the modified indicator. CONFIG_VAR controls derive it from value != * default when this is NULL. */ UiPredicateFn is_modified; - /* Passed to every callback above. */ + /* Passed to every callback. */ void* user_data; /* NUMBER: inclusive clamp range and step. min == max means the defaults (0 .. INT32_MAX); step * < 1 means 1. */ @@ -115,17 +122,56 @@ typedef struct UiControlDesc { const char* const* options; size_t option_count; int32_t max_length; /* STRING: maximum input length; < 1 means unlimited */ + /* COLOR: optional RRGGBB/RRGGBBAA values for presets. "rainbow" is a special value. */ + const char* const* color_presets; + size_t color_preset_count; + bool color_alpha; /* COLOR: use RRGGBBAA values instead of RRGGBB */ + UiPredicateFn is_selected; /* BUTTON/GROUP: optional selected state */ + UiStringSetMode string_set_mode; /* STRING: when to invoke the setter */ } UiControlDesc; #define UI_CONTROL_DESC_INIT \ {sizeof(UiControlDesc), UI_CONTROL_BUTTON, NULL, NULL, UI_BINDING_CALLBACKS, 0u, NULL, NULL, \ - NULL, NULL, NULL, NULL, 0, 0, 1, NULL, NULL, NULL, 0u, 0} + NULL, NULL, NULL, NULL, 0, 0, 1, NULL, NULL, NULL, 0u, 0, NULL, 0u, false, NULL, \ + UI_STRING_SET_ON_COMMIT} + +typedef uint64_t UiListHandle; + +/* Must be initialized with UI_LIST_ITEM_INIT */ +typedef struct UiListItem { + uint32_t struct_size; + uint64_t key; /* required; unique, stable item key */ + const char* label; /* required; visible item text */ +} UiListItem; + +#define UI_LIST_ITEM_INIT {sizeof(UiListItem), 0u, NULL} + +typedef void (*UiListPressedFn)( + ModContext* ctx, UiListHandle list, uint64_t item_key, void* user_data); +typedef bool (*UiListPredicateFn)( + ModContext* ctx, UiListHandle list, uint64_t item_key, void* user_data); + +/* Must be initialized with UI_LIST_DESC_INIT */ +typedef struct UiListDesc { + uint32_t struct_size; + const UiListItem* items; /* optional; initial set of items */ + size_t item_count; + UiListPressedFn on_pressed; /* required */ + UiListPredicateFn is_selected; /* optional; polled only for render-visible rows */ + UiListPredicateFn is_disabled; /* optional; polled only for render-visible rows */ + void* user_data; +} UiListDesc; + +#define UI_LIST_DESC_INIT {sizeof(UiListDesc), NULL, 0u, NULL, NULL, NULL, NULL} + +/* Build pane contents. A non-MOD_OK result fails the mod. */ +typedef ModResult (*UiPaneBuildFn)( + ModContext* ctx, UiElementHandle pane, void* user_data, ModError* out_error); /* Build the panel contents. `panel` accepts the pane_add_* functions; it and * every element created in it are destroyed (handles invalidated) whenever the * panel is rebuilt, e.g. on tab switches. A non-MOD_OK result fails the mod. */ -typedef ModResult (*UiPanelBuildFn)( - ModContext* ctx, UiElementHandle panel, void* user_data, ModError* out_error); +typedef UiPaneBuildFn UiPanelBuildFn; /* Called every frame while the panel is the visible tab. */ typedef ModResult (*UiPanelUpdateFn)(ModContext* ctx, void* user_data, ModError* out_error); @@ -139,6 +185,19 @@ typedef struct UiModsPanelDesc { #define UI_MODS_PANEL_DESC_INIT {sizeof(UiModsPanelDesc), NULL, NULL, NULL} +/* Builds the contents associated with a group button. The target pane is cleared immediately + * before this callback and is valid only while its tab remains built. */ +typedef UiPaneBuildFn UiGroupBuildFn; + +typedef struct UiGroupDesc { + uint32_t struct_size; + const char* label; /* required */ + UiGroupBuildFn build; /* required */ + void* user_data; +} UiGroupDesc; + +#define UI_GROUP_DESC_INIT {sizeof(UiGroupDesc), NULL, NULL, NULL} + /* Build one tab of a mod window. `left_pane` is the interactive column, * `right_pane` shows contextual help (controls' help_rml and SELECT options * render there). Rebuilt on every tab activation. */ @@ -174,15 +233,17 @@ typedef struct UiWindowDesc { typedef void (*UiDialogActionFn)(ModContext* ctx, UiDialogHandle dialog, void* user_data); -/* Note: array element without struct_size; a future change requires appending - * a v2 desc struct rather than growing this one. */ typedef struct UiDialogAction { + uint32_t struct_size; const char* label; /* required */ UiDialogActionFn on_pressed; void* user_data; - bool keep_open; /* false = the dialog closes after on_pressed returns */ + bool keep_open; /* false = the dialog closes after on_pressed returns */ + UiPredicateFn is_disabled; /* optional; polled every frame while the dialog is visible */ } UiDialogAction; +#define UI_DIALOG_ACTION_INIT {sizeof(UiDialogAction), NULL, NULL, NULL, false, NULL} + typedef struct UiDialogDesc { uint32_t struct_size; const char* title; /* plain text; required */ @@ -196,11 +257,14 @@ typedef struct UiDialogDesc { /* Fired on cancel (B/Escape) before the dialog closes; the dialog always * closes on dismiss. */ UiDialogActionFn on_dismiss; - void* user_data; /* passed to on_dismiss */ + void* user_data; /* passed to build and on_dismiss */ + /* Optional content builder. The pane is rendered below body_rml and above the actions. Its + * handle and all child element handles remain valid until the dialog closes. */ + UiPaneBuildFn build; } UiDialogDesc; #define UI_DIALOG_DESC_INIT \ - {sizeof(UiDialogDesc), NULL, NULL, UI_DIALOG_NORMAL, NULL, NULL, 0u, NULL, NULL} + {sizeof(UiDialogDesc), NULL, NULL, UI_DIALOG_NORMAL, NULL, NULL, 0u, NULL, NULL, NULL} /* A tab added to the in-game menu bar. */ typedef struct UiMenuTabDesc { @@ -242,6 +306,10 @@ typedef struct UiService { ModContext* ctx, UiElementHandle pane, float value, UiElementHandle* out_elem); ModResult (*pane_add_control)(ModContext* ctx, UiElementHandle pane, const UiControlDesc* desc, UiElementHandle* out_elem); + /* Add a group button to one pane that builds controls in its paired pane. + * The panes must be the left and right handles from the same UiTabBuildFn call. */ + ModResult (*pane_add_group)(ModContext* ctx, UiElementHandle group_pane, + UiElementHandle target_pane, const UiGroupDesc* desc, UiElementHandle* out_elem); /* Element updates. The handle kind must match the setter (text/rml on text * rows, progress on progress bars). */ @@ -263,9 +331,6 @@ typedef struct UiService { ModResult (*dialog_set_body)(ModContext* ctx, UiDialogHandle dialog, const char* body_rml); /* Replace the dialog icon ("" removes it; names as in UiDialogDesc.icon). */ ModResult (*dialog_set_icon)(ModContext* ctx, UiDialogHandle dialog, const char* icon); - /* Append one action button (same callback rules as at push). */ - ModResult (*dialog_add_action)( - ModContext* ctx, UiDialogHandle dialog, const UiDialogAction* action); /* Whether any focus-stack document is currently visible (visible documents block gamepad * input). */ @@ -292,9 +357,16 @@ typedef struct UiService { /* Enqueue a toast notification. */ ModResult (*push_toast)(ModContext* ctx, const UiToastDesc* desc); - /* Minor version 2 */ - ModResult (*get_clipboard_text)(ModContext* ctx, char* buffer, size_t bufferSize, size_t* outLength); + ModResult (*get_clipboard_text)( + ModContext* ctx, char* buffer, size_t bufferSize, size_t* outLength); ModResult (*set_clipboard_text)(ModContext* ctx, const char* text); + + /* A scrollable virtualized list of items. */ + ModResult (*pane_add_list)( + ModContext* ctx, UiElementHandle pane, const UiListDesc* desc, UiListHandle* out_list); + /* Replace all items in a list with a new set. */ + ModResult (*list_set_items)( + ModContext* ctx, UiListHandle list, const UiListItem* items, size_t item_count); } UiService; MOD_DECLARE_SERVICE(UiService, svc_ui, UI_SERVICE_ID, UI_SERVICE_MAJOR, UI_SERVICE_MINOR); diff --git a/src/d/actor/d_a_alink_demo.inc b/src/d/actor/d_a_alink_demo.inc index e8812c6e41..f16c8a6887 100644 --- a/src/d/actor/d_a_alink_demo.inc +++ b/src/d/actor/d_a_alink_demo.inc @@ -1027,6 +1027,9 @@ void daAlink_c::setGetItemFace(u16 i_itemNo) { || i_itemNo == dItemNo_ANCIENT_DOCUMENT2_e || i_itemNo == dItemNo_DROP_CONTAINER_e || i_itemNo == dItemNo_DROP_CONTAINER02_e +#if TARGET_PC + || i_itemNo == dItemNo_SHADOW_CRYSTAL_e +#endif || i_itemNo == dItemNo_DROP_CONTAINER03_e) { setFaceBasicBck(dRes_ID_ALANM_BCK_FI_e); @@ -2009,7 +2012,11 @@ void daAlink_c::setGetSubBgm(int i_itemNo) { /* dItemNo_WEAR_KOKIRI_e */ SETYPE_NONE, /* dItemNo_ARMOR_e */ SETYPE_ITEM_GET, /* dItemNo_WEAR_ZORA_e */ SETYPE_ITEM_GET, +#if TARGET_PC + /* dItemNo_SHADOW_CRYSTAL_e */ SETYPE_ITEM_GET, +#else /* dItemNo_MAGIC_LV1_e */ SETYPE_NONE, +#endif /* dItemNo_DUNGEON_EXIT_2_e */ SETYPE_ITEM_GET_MINI, /* dItemNo_WALLET_LV1_e */ SETYPE_NONE, /* dItemNo_WALLET_LV2_e */ SETYPE_ITEM_GET, @@ -2307,8 +2314,13 @@ int daAlink_c::procCoGetItemInit() { item_no = dComIfGp_event_getGtItm(); } +#if TARGET_PC + const u32 giveTag = mDemo.getParam0() != 0x100 && mDemo.getParam1() != 0 ? + static_cast(mDemo.getParam1()) : + dusk::mods::item_give_queue_take_tag(); +#endif fpc_ProcID item_partner_id = fopAcM_createItemForPresentDemo(¤t.pos, item_no, 0, -1, - fopAcM_GetRoomNo(this), NULL, NULL IF_DUSK_ARG(dusk::mods::item_give_queue_take_tag())); + fopAcM_GetRoomNo(this), NULL, NULL IF_DUSK_ARG(giveTag)); if (item_partner_id != fpcM_ERROR_PROCESS_ID_e) { dComIfGp_event_setItemPartnerId(item_partner_id); } @@ -2533,6 +2545,16 @@ int daAlink_c::procCoGetItem() { } else if (mProcVar2.field_0x300c == 0x23 && checkStageName("D_MN11")) { field_0x32cc = 0x5C0; } else if (mProcVar2.field_0x300c == 0xE0) { +#if TARGET_PC + // Dusklight increments the Poe count when the displayed item is granted. + if (dComIfGs_getPohSpiritNum() + 1 == 20) { + field_0x32cc = 0x4CF; + } else if (dComIfGs_getPohSpiritNum() + 1 == 60) { + field_0x32cc = 0x4D0; + } else { + field_0x32cc = mProcVar2.field_0x300c + 0x65; + } +#else if (dComIfGs_getPohSpiritNum() == 20) { field_0x32cc = 0x4CF; } else if (dComIfGs_getPohSpiritNum() == 60) { @@ -2540,6 +2562,7 @@ int daAlink_c::procCoGetItem() { } else { field_0x32cc = mProcVar2.field_0x300c + 0x65; } +#endif } else if (mProcVar2.field_0x300c == 0x21) { static u32 const heartPieceMessage[5] = {0x86, 0x9C, 0x9D, 0x9E, 0x9F}; field_0x32cc = heartPieceMessage[dComIfGs_getMaxLife() % 5]; diff --git a/src/d/actor/d_a_b_ds.cpp b/src/d/actor/d_a_b_ds.cpp index e0623acaba..efa1c289a9 100644 --- a/src/d/actor/d_a_b_ds.cpp +++ b/src/d/actor/d_a_b_ds.cpp @@ -19,6 +19,10 @@ #include "f_op/f_op_actor_enemy.h" #include "Z2AudioLib/Z2Instances.h" +#if TARGET_PC +#include "mods/items.h" +#endif + enum daB_DS_Joint { DS_JNT_BACKBONE1, DS_JNT_BACKBONE2, @@ -4086,7 +4090,8 @@ void daB_DS_c::executeBattle2Dead() { dComIfGs_onStageBossEnemy(0x13); #if TARGET_PC // This reward has no original grant at this point in the cutscene. - dusk::mods::item_check_enqueue("Arbiters Grounds Dungeon Reward", dItemNo_NONE_e); + dusk::mods::item_check_enqueue_deferred( + ITEM_CHECK_DUNGEON_REWARD_ARBITERS, dItemNo_NONE_e); #endif /* dSv_event_flag_c::F_0265 - Arbiter's Grounds - Arbiter's Grounds clear */ dComIfGs_onEventBit(0x2010); diff --git a/src/d/actor/d_a_demo00.cpp b/src/d/actor/d_a_demo00.cpp index b737083598..60a99d4d54 100644 --- a/src/d/actor/d_a_demo00.cpp +++ b/src/d/actor/d_a_demo00.cpp @@ -1090,6 +1090,13 @@ inline int daDemo00_c::execute() { break; } case 1: +#if TARGET_PC + // Suppress demo22_01's M_077 write. On Dusklight, the transform flag + // is set by the Shadow Crystal item. + if (dSv_event_flag_c::saveBitLabels[sp0E] == dSv_event_flag_c::M_077) { + break; + } +#endif dComIfGs_onEventBit(dSv_event_flag_c::saveBitLabels[sp0E]); break; diff --git a/src/d/actor/d_a_demo_item.cpp b/src/d/actor/d_a_demo_item.cpp index 5876c26718..465532a5f0 100644 --- a/src/d/actor/d_a_demo_item.cpp +++ b/src/d/actor/d_a_demo_item.cpp @@ -449,7 +449,7 @@ int daDitem_c::Delete() { endInsectEffect(); mSound.deleteObject(); - return DeleteBase(dItem_data::getArcName(m_itemNo)); + return DeleteBase(dItem_data::getArcName(DUSK_IF_ELSE(getDisplayItemNo(), m_itemNo))); } static int daDitem_Delete(daDitem_c* i_this) { @@ -461,8 +461,16 @@ int daDitem_c::create() { m_itemNo = daDitem_prm::getNo(this); +#if TARGET_PC + const auto [item, displayItem] = dusk::mods::item_check_resolve(mItemGiveTag, m_itemNo, this); + m_itemNo = item; + setDisplayItemNo(displayItem); + const char* arc_name = dItem_data::getArcName(displayItem); + s16 bmd_name = dItem_data::getBmdName(displayItem); +#else const char* arc_name = dItem_data::getArcName(m_itemNo); s16 bmd_name = dItem_data::getBmdName(m_itemNo); +#endif if (bmd_name < 0 || arc_name == NULL) { if (bmd_name == 0) { @@ -476,9 +484,13 @@ int daDitem_c::create() { } m_itemNo = dItemNo_GREEN_RUPEE_e; +#if TARGET_PC + setDisplayItemNo(dItemNo_NONE_e); +#endif } - int phase_state = dComIfG_resLoad(&mPhase, dItem_data::getArcName(m_itemNo)); + int phase_state = dComIfG_resLoad( + &mPhase, dItem_data::getArcName(DUSK_IF_ELSE(getDisplayItemNo(), m_itemNo))); if (phase_state == cPhs_COMPLEATE_e) { if (!fopAcM_entrySolidHeap(this, CheckItemCreateHeap, 0x80003390)) { return cPhs_ERROR_e; diff --git a/src/d/actor/d_a_e_hp.cpp b/src/d/actor/d_a_e_hp.cpp index 8c9d9398ea..29ae9d43f5 100644 --- a/src/d/actor/d_a_e_hp.cpp +++ b/src/d/actor/d_a_e_hp.cpp @@ -727,19 +727,26 @@ void daE_HP_c::executeDead() { } #if TARGET_PC - mItemCheckOverridden = - dusk::mods::item_check_poe(bitSw, dItemNo_POU_SPIRIT_e, this) != dItemNo_POU_SPIRIT_e; - if (mItemCheckOverridden) { - dusk::mods::item_check_enqueue_poe(bitSw, dItemNo_POU_SPIRIT_e); - } else + const auto itemCheck = dusk::mods::item_check_commit( + dusk::mods::item_give_tag_poe(bitSw), dItemNo_POU_SPIRIT_e, this); + mItemCheckHandled = true; + if (itemCheck.itemNo == dItemNo_NONE_e) { + dusk::mods::item_check_complete(itemCheck, this); + } else { + daAlink_getAlinkActorClass()->procWolfAtnActorMoveInit(); + dusk::mods::item_check_enqueue(itemCheck, dusk::mods::ItemGiveMode::ForcedDemo); + } +#else + dComIfGs_addPohSpiritNum(); #endif - dComIfGs_addPohSpiritNum(); field_0x784 = -1; - if (dComIfGs_getPohSpiritNum() == 20 IF_DUSK(&&!mItemCheckOverridden)) { +#if !TARGET_PC + if (dComIfGs_getPohSpiritNum() == 20) { dComIfGs_onEventBit(dSv_event_flag_c::saveBitLabels[0x1c9]); } +#endif movemode++; } @@ -759,7 +766,7 @@ void daE_HP_c::executeDead() { field_0x788 = 1; } } - } else if (field_0x788 != 0 IF_DUSK(|| mItemCheckOverridden)) { + } else if (field_0x788 != 0 IF_DUSK(|| mItemCheckHandled)) { fopAcM_createDisappear(this, ¤t.pos, 8, 3, 0xff); fopAcM_delete(this); } else { diff --git a/src/d/actor/d_a_e_po.cpp b/src/d/actor/d_a_e_po.cpp index f2971f23a3..a7a7be6dd1 100644 --- a/src/d/actor/d_a_e_po.cpp +++ b/src/d/actor/d_a_e_po.cpp @@ -1132,20 +1132,14 @@ static void e_po_dead(e_po_class* i_this) { camera_player->mCamera.Start(); camera_player->mCamera.SetTrimSize(0); dComIfGp_event_reset(); -#if TARGET_PC - if (dusk::mods::item_check_poe(i_this->BitSW, dItemNo_POU_SPIRIT_e, a_this) == - dItemNo_POU_SPIRIT_e) - { -#endif - dComIfGs_addPohSpiritNum(); +#if !TARGET_PC + dComIfGs_addPohSpiritNum(); #if !PLATFORM_SHIELD if (dComIfGs_getPohSpiritNum() == 0x14) { /* dSv_event_flag_c::F_0457 - Castle Town - Revived cat */ dComIfGs_onEventBit(dSv_event_flag_c::saveBitLabels[457]); } #endif -#if TARGET_PC - } #endif daPy_getPlayerActorClass()->cancelOriginalDemo(); } else if (mArg0Check(i_this, 0) != 0) { @@ -1274,10 +1268,16 @@ static void e_po_dead(e_po_class* i_this) { } else { if (i_this->field_0x75C == -1) { #if TARGET_PC - const u8 itemNo = - dusk::mods::item_check_poe(i_this->BitSW, dItemNo_POU_SPIRIT_e, a_this); - i_this->field_0x75C = fopAcM_createItemForPresentDemo(&a_this->current.pos, itemNo, - 0, -1, -1, NULL, NULL, dusk::mods::item_give_tag_poe(i_this->BitSW)); + const auto itemCheck = dusk::mods::item_check_commit( + dusk::mods::item_give_tag_poe(i_this->BitSW), dItemNo_POU_SPIRIT_e, a_this); + if (itemCheck.itemNo == dItemNo_NONE_e) { + dusk::mods::item_check_complete(itemCheck, a_this); + i_this->field_0x75B = 1; + } else { + i_this->field_0x75C = fopAcM_createItemForPresentDemo( + &a_this->current.pos, itemCheck.itemNo, 0, -1, -1, NULL, NULL, + itemCheck.tag); + } #else i_this->field_0x75C = fopAcM_createItemForPresentDemo(&a_this->current.pos, 0xE0, 0, -1, -1, NULL, NULL); diff --git a/src/d/actor/d_a_e_rdb.cpp b/src/d/actor/d_a_e_rdb.cpp index c467f38fd6..0e6fbbdafd 100644 --- a/src/d/actor/d_a_e_rdb.cpp +++ b/src/d/actor/d_a_e_rdb.cpp @@ -16,6 +16,10 @@ #include "f_op/f_op_camera_mng.h" #include +#if TARGET_PC +#include "mods/items.h" +#endif + class daE_RDB_HIO_c : public JORReflexible { public: daE_RDB_HIO_c(); @@ -1250,9 +1254,18 @@ static void demo_camera(e_rdb_class* i_this) { } if (iVar1 != 0) { - daPy_getPlayerActorClass()->changeDemoMode(11, - DUSK_ITEM_CHECK_EXPR("bulblin_key:D_MN09", dItemNo_SMALL_KEY_e, &i_this->enemy), 0, - 0); +#if TARGET_PC + const auto itemCheck = dusk::mods::item_check_commit( + ITEM_CHECK_BULBLIN_KEY, dItemNo_SMALL_KEY_e, &i_this->enemy); + if (itemCheck.itemNo == dItemNo_NONE_e) { + dusk::mods::item_check_complete(itemCheck, &i_this->enemy); + } + daPy_getPlayerActorClass()->changeDemoMode( + 11, itemCheck.itemNo == dItemNo_NONE_e ? 0 : itemCheck.itemNo, + itemCheck.itemNo == dItemNo_NONE_e ? 0 : static_cast(itemCheck.tag), 0); +#else + daPy_getPlayerActorClass()->changeDemoMode(11, dItemNo_SMALL_KEY_e, 0, 0); +#endif i_this->mDemoMode = 12; i_this->field_0x10aa = 0; i_this->field_0xfe5 = 1; diff --git a/src/d/actor/d_a_itembase.cpp b/src/d/actor/d_a_itembase.cpp index 084fb5221f..474b03c784 100644 --- a/src/d/actor/d_a_itembase.cpp +++ b/src/d/actor/d_a_itembase.cpp @@ -242,21 +242,21 @@ BOOL daItemBase_c::chkFlag(int i_flag) { } s8 daItemBase_c::getTevFrm() { - return dItem_data::getTevFrm(m_itemNo); + return dItem_data::getTevFrm(DUSK_IF_ELSE(getDisplayItemNo(), m_itemNo)); } s8 daItemBase_c::getBtpFrm() { - return dItem_data::getBtpFrm(m_itemNo); + return dItem_data::getBtpFrm(DUSK_IF_ELSE(getDisplayItemNo(), m_itemNo)); } u8 daItemBase_c::getShadowSize() { - return dItem_data::getShadowSize(m_itemNo); + return dItem_data::getShadowSize(DUSK_IF_ELSE(getDisplayItemNo(), m_itemNo)); } u8 daItemBase_c::getCollisionH() { - return dItem_data::getH(m_itemNo); + return dItem_data::getH(DUSK_IF_ELSE(getDisplayItemNo(), m_itemNo)); } u8 daItemBase_c::getCollisionR() { - return dItem_data::getR(m_itemNo); + return dItem_data::getR(DUSK_IF_ELSE(getDisplayItemNo(), m_itemNo)); } diff --git a/src/d/actor/d_a_mg_rod.cpp b/src/d/actor/d_a_mg_rod.cpp index 545b6c3069..6cf1e76024 100644 --- a/src/d/actor/d_a_mg_rod.cpp +++ b/src/d/actor/d_a_mg_rod.cpp @@ -27,8 +27,10 @@ #if TARGET_PC #include "dusk/frame_interpolation.h" +#include "dusk/mods/item.hpp" #include "dusk/settings.h" #include "dusk/version.hpp" +#include "mods/items.h" #endif class dmg_rod_HIO_c : public JORReflexible { @@ -2955,7 +2957,17 @@ static void lure_heart(dmg_rod_class* i_this) { if (obj_life != NULL) { fopAcM_delete(obj_life); fopAcM_onItem(obj_life, 0x80); +#if TARGET_PC + const auto itemCheck = dusk::mods::item_check_commit( + ITEM_CHECK_FISHING_HEART_PIECE, dItemNo_KAKERA_HEART_e, actor); + if (itemCheck.itemNo == dItemNo_KAKERA_HEART_e) { + execItemGet(dItemNo_KAKERA_HEART_e, itemCheck.tag, actor); + } else if (itemCheck.itemNo == dItemNo_NONE_e) { + dusk::mods::item_check_complete(itemCheck, actor); + } +#else execItemGet(dItemNo_KAKERA_HEART_e); +#endif u8 eventReg = dComIfGs_getEventReg(0xECFF); eventReg |= (u8)0x40; dComIfGs_setEventReg(0xECFF, eventReg); @@ -4090,7 +4102,15 @@ static void uki_catch(dmg_rod_class* i_this) { } else if (mgfish->mCaughtType == MG_CATCH_BIN) { i_this->msgflow.init(actor, 0x139A, 0, NULL); dComIfGs_onEventBit(dSv_event_flag_c::saveBitLabels[468]); +#if TARGET_PC + const auto itemCheck = dusk::mods::item_check_commit( + ITEM_CHECK_FISHING_BOTTLE, dItemNo_EMPTY_BOTTLE_e, actor); + if (itemCheck.itemNo == dItemNo_EMPTY_BOTTLE_e) { + dComIfGs_setEmptyBottle(); + } +#else dComIfGs_setEmptyBottle(); +#endif } else if (mgfish->mCaughtType == MG_CATCH_KN) { i_this->msgflow.init(actor, 0x139C, 0, NULL); } else if (mgfish->mCaughtType == MG_CATCH_ED) { @@ -4167,6 +4187,18 @@ static void uki_catch(dmg_rod_class* i_this) { if (mgfish->mCaughtType == MG_CATCH_LH) { dComIfGp_setItemRupeeCount(10.0f + cM_rndF(40.9f)); } +#if TARGET_PC + else if (mgfish->mCaughtType == MG_CATCH_BIN) + { + const auto itemCheck = dusk::mods::item_check_commit( + ITEM_CHECK_FISHING_BOTTLE, dItemNo_EMPTY_BOTTLE_e, actor); + if (itemCheck.itemNo == dItemNo_EMPTY_BOTTLE_e || + itemCheck.itemNo == dItemNo_NONE_e) + { + dusk::mods::item_check_complete(itemCheck, actor); + } + } +#endif } else { dComIfGs_addFishNum(fish_kind); if (i_this->field_0x14c0 != 0) { diff --git a/src/d/actor/d_a_npc_chin.cpp b/src/d/actor/d_a_npc_chin.cpp index fb91bd79d8..ae629e5d34 100644 --- a/src/d/actor/d_a_npc_chin.cpp +++ b/src/d/actor/d_a_npc_chin.cpp @@ -1806,17 +1806,21 @@ int daNpcChin_c::_Evt_GameSucceed_CutMain(const int& param_0) { #if TARGET_PC const char* itemCheckName = nullptr; + u32 itemGiveTag = 0; if (itemId1 == dItemNo_ARROW_LV2_e) { itemCheckName = "star_reward_1"; } else if (itemId1 == dItemNo_ARROW_LV3_e) { itemCheckName = "star_reward_2"; } if (itemCheckName != nullptr) { - itemId1 = dusk::mods::item_check(itemCheckName, itemId1, this); + const auto itemCheck = + dusk::mods::item_check_commit(itemCheckName, itemId1, this); + itemId1 = itemCheck.itemNo; + itemGiveTag = itemCheck.tag; } #endif fpc_ProcID itemId2 = fopAcM_createItemForPresentDemo(¤t.pos, itemId1, 0, -1, -1, - 0, 0 IF_DUSK_ARG(dusk::mods::item_give_tag(itemCheckName))); + 0, 0 IF_DUSK_ARG(itemGiveTag)); if (itemId2 != -1) { dComIfGp_event_setItemPartnerId(itemId2); } diff --git a/src/d/actor/d_a_npc_gra.cpp b/src/d/actor/d_a_npc_gra.cpp index 4300348ff9..e5e0d6eed0 100644 --- a/src/d/actor/d_a_npc_gra.cpp +++ b/src/d/actor/d_a_npc_gra.cpp @@ -12,6 +12,9 @@ #include "d/actor/d_a_npc_gra.h" #include "d/actor/d_a_tag_gra.h" #include "Z2AudioLib/Z2Instances.h" +#if TARGET_PC +#include "mods/items.h" +#endif #include DUSK_GAME_DATA const daNpc_grA_HIOParam daNpc_grA_Param_c::m = { @@ -1323,7 +1326,7 @@ BOOL daNpc_grA_c::isDelete() { return FALSE; } fopAcM_createItemForBoss(¤t.pos, 0x21, fopAcM_GetRoomNo(this), NULL, NULL, 0.0f, 0.0f, - 0x80); + 0x80 IF_DUSK_ARG(ITEM_CHECK_GORON_SPRINGWATER_RUSH)); return TRUE; } return TRUE; @@ -2812,7 +2815,7 @@ BOOL daNpc_grA_c::ECut_carrySpaWater(int i_staffID) { c.y += 200.0f; csXyz c2(0, fopAcM_searchPlayerAngleY(this), 0); fopAcM_createItemForBoss(&c, 0x21, fopAcM_GetRoomNo(this), &c2, NULL, 0.0f, 20.0f, - 0x80); + 0x80 IF_DUSK_ARG(ITEM_CHECK_GORON_SPRINGWATER_RUSH)); } break; } } @@ -4019,14 +4022,16 @@ BOOL daNpc_grA_c::talk(void*) { if (r26 && talkProc(NULL, TRUE, NULL)) { if (mFlow.getEventId(&sp8) == 1) { #if TARGET_PC - const char* itemCheckName = nullptr; + u32 itemGiveTag = 0; if (sp8 == dItemNo_BOMB_IN_BAG_e) { - itemCheckName = "goron_reward:F_SP113"; - sp8 = dusk::mods::item_check(itemCheckName, sp8, this); + const auto itemCheck = + dusk::mods::item_check_commit("goron_reward:F_SP113", sp8, this); + sp8 = itemCheck.itemNo; + itemGiveTag = itemCheck.tag; } #endif field_0x1480 = fopAcM_createItemForPresentDemo(¤t.pos, sp8, 0, -1, -1, NULL, - NULL IF_DUSK_ARG(dusk::mods::item_give_tag(itemCheckName))); + NULL IF_DUSK_ARG(itemGiveTag)); if (field_0x1480 != fpcM_ERROR_PROCESS_ID_e) { s16 r25 = dComIfGp_getEventManager().getEventIdx(this, "DEFAULT_GETITEM", 0xff); dComIfGp_getEvent()->reset(this); diff --git a/src/d/actor/d_a_npc_ins.cpp b/src/d/actor/d_a_npc_ins.cpp index ede3f53664..7dfdec325e 100644 --- a/src/d/actor/d_a_npc_ins.cpp +++ b/src/d/actor/d_a_npc_ins.cpp @@ -1495,9 +1495,11 @@ int daNpcIns_c::talk(void* param_1) { #if TARGET_PC u32 itemGiveTag = 0; if (s_givenInsectId != dItemNo_NONE_e) { - itemNo = dusk::mods::item_check_bug( - s_givenInsectId, itemNo & 0xFF, this); - itemGiveTag = dusk::mods::item_give_tag_bug(s_givenInsectId); + const auto itemCheck = dusk::mods::item_check_commit( + dusk::mods::item_give_tag_bug(s_givenInsectId), itemNo & 0xFF, + this); + itemNo = itemCheck.itemNo; + itemGiveTag = itemCheck.tag; s_givenInsectId = dItemNo_NONE_e; } #endif diff --git a/src/d/actor/d_a_npc_kkri.cpp b/src/d/actor/d_a_npc_kkri.cpp index 4d9c882d03..755257bff7 100644 --- a/src/d/actor/d_a_npc_kkri.cpp +++ b/src/d/actor/d_a_npc_kkri.cpp @@ -1182,15 +1182,17 @@ int daNpc_Kkri_c::talk(void*) { case 1: if (mItemPartnerId == fpcM_ERROR_PROCESS_ID_e) { #if TARGET_PC - const char* itemCheckName = nullptr; + u32 itemGiveTag = 0; if (item_no == dItemNo_OIL_BOTTLE3_e) { - itemCheckName = "coro_bottle"; - item_no = dusk::mods::item_check(itemCheckName, item_no, this); + const auto itemCheck = + dusk::mods::item_check_commit("coro_bottle", item_no, this); + item_no = itemCheck.itemNo; + itemGiveTag = itemCheck.tag; } #endif mItemPartnerId = fopAcM_createItemForPresentDemo(¤t.pos, item_no, 0, -1, -1, NULL, - NULL IF_DUSK_ARG(dusk::mods::item_give_tag(itemCheckName))); + NULL IF_DUSK_ARG(itemGiveTag)); } if (fopAcM_IsExecuting(mItemPartnerId)) { diff --git a/src/d/actor/d_a_npc_myna2.cpp b/src/d/actor/d_a_npc_myna2.cpp index faa5301bb8..9b7bc973fc 100644 --- a/src/d/actor/d_a_npc_myna2.cpp +++ b/src/d/actor/d_a_npc_myna2.cpp @@ -1192,14 +1192,16 @@ int daNpc_myna2_c::ECut_gameGoalSuccess(int i_staffId) { int itemNo = 0; if (mFlow.getEventId(&itemNo) == 1) { #if TARGET_PC - const char* itemCheckName = nullptr; + u32 itemGiveTag = 0; if (itemNo == dItemNo_KAKERA_HEART_e) { - itemCheckName = "plumm_minigame_reward"; - itemNo = dusk::mods::item_check(itemCheckName, itemNo, this); + const auto itemCheck = + dusk::mods::item_check_commit("plumm_minigame_reward", itemNo, this); + itemNo = itemCheck.itemNo; + itemGiveTag = itemCheck.tag; } #endif mItemPid = fopAcM_createItemForPresentDemo(¤t.pos, itemNo, 0, -1, -1, NULL, - NULL IF_DUSK_ARG(dusk::mods::item_give_tag(itemCheckName))); + NULL IF_DUSK_ARG(itemGiveTag)); } break; } diff --git a/src/d/actor/d_a_npc_pouya.cpp b/src/d/actor/d_a_npc_pouya.cpp index 6101b64a93..5b9ad82755 100644 --- a/src/d/actor/d_a_npc_pouya.cpp +++ b/src/d/actor/d_a_npc_pouya.cpp @@ -960,17 +960,21 @@ int daNpc_Pouya_c::cutHaveFavorToAsk(int param_0) { if (mItemPartnerId == fpcM_ERROR_PROCESS_ID_e) { #if TARGET_PC const char* itemCheckName = nullptr; + u32 itemGiveTag = 0; if (local_64 == dItemNo_DROP_BOTTLE_e) { itemCheckName = "jovani_reward_1"; } else if (local_64 == dItemNo_SILVER_RUPEE_e) { itemCheckName = "jovani_reward_2"; } if (itemCheckName != nullptr) { - local_64 = dusk::mods::item_check(itemCheckName, local_64, this); + const auto itemCheck = + dusk::mods::item_check_commit(itemCheckName, local_64, this); + local_64 = itemCheck.itemNo; + itemGiveTag = itemCheck.tag; } #endif mItemPartnerId = fopAcM_createItemForPresentDemo(¤t.pos, local_64, 0, - -1, -1, 0, 0 IF_DUSK_ARG(dusk::mods::item_give_tag(itemCheckName))); + -1, -1, 0, 0 IF_DUSK_ARG(itemGiveTag)); } if (fopAcM_IsExecuting(mItemPartnerId)) { field_0xfce = 1; diff --git a/src/d/actor/d_a_npc_zra.inc b/src/d/actor/d_a_npc_zra.inc index 70426d5f99..5cdb380423 100644 --- a/src/d/actor/d_a_npc_zra.inc +++ b/src/d/actor/d_a_npc_zra.inc @@ -2611,17 +2611,21 @@ BOOL daNpc_zrA_c::ECut_thanksBlast(int i_staffID) { if (mFlow.getEventId(&item_id) == 1) { #if TARGET_PC const char* itemCheckName = nullptr; + u32 itemGiveTag = 0; if (item_id == dItemNo_BOMB_IN_BAG_e) { itemCheckName = "iza_reward_1"; } else if (item_id == dItemNo_BOMB_BAG_LV2_e) { itemCheckName = "iza_reward_2"; } if (itemCheckName != nullptr) { - item_id = dusk::mods::item_check(itemCheckName, item_id, this); + const auto itemCheck = + dusk::mods::item_check_commit(itemCheckName, item_id, this); + item_id = itemCheck.itemNo; + itemGiveTag = itemCheck.tag; } #endif mItemID = fopAcM_createItemForPresentDemo(¤t.pos, item_id, 0, -1, -1, NULL, - NULL IF_DUSK_ARG(dusk::mods::item_give_tag(itemCheckName))); + NULL IF_DUSK_ARG(itemGiveTag)); } field_0x9eb = true; break; diff --git a/src/d/actor/d_a_obj_bosswarp.cpp b/src/d/actor/d_a_obj_bosswarp.cpp index e286ce1640..5bf510d04a 100644 --- a/src/d/actor/d_a_obj_bosswarp.cpp +++ b/src/d/actor/d_a_obj_bosswarp.cpp @@ -14,6 +14,11 @@ #include "d/actor/d_a_obj_ystone.h" #include +#if TARGET_PC +#include "dusk/mods/item.hpp" +#include "mods/items.h" +#endif + static DUSK_CONST char* l_arcName = "ef_Portal"; static char const* l_clearEvName[9] = { @@ -77,6 +82,27 @@ static int getNowLevel() { return -1; } +#if TARGET_PC +static const char* dungeon_reward_check_name(int level) { + switch (level) { + case 0: + return ITEM_CHECK_DUNGEON_REWARD_FOREST; + case 1: + return ITEM_CHECK_DUNGEON_REWARD_GORON; + case 2: + return ITEM_CHECK_DUNGEON_REWARD_LAKEBED; + case 4: + return ITEM_CHECK_DUNGEON_REWARD_SNOWPEAK; + case 5: + return ITEM_CHECK_DUNGEON_REWARD_TIME; + case 6: + return ITEM_CHECK_DUNGEON_REWARD_CITY; + default: + return nullptr; + } +} +#endif + void daObjBossWarp_c::initBaseMtx() { scale.y = 0.15f; mpModel->setBaseScale(scale); @@ -485,6 +511,9 @@ int daObjBossWarp_c::demoProc() { player->onSceneChangeArea(scene, 0xff, 0); break; case 4: // STONE_FALL +#if TARGET_PC + { +#endif if (ystone != NULL) { mYstonePos = ystone->current.pos; if (getNowLevel() < 3) { @@ -506,28 +535,52 @@ int daObjBossWarp_c::demoProc() { mDoMtx_stack_c::multVec(&mYstoneTargetPos, &mYstoneTargetPos); mYstonePos.x = mYstoneTargetPos.x; mYstonePos.z = mYstoneTargetPos.z; - switch (getNowLevel()) { - case 0: - dComIfGs_onCollectCrystal(0); - break; - case 1: - dComIfGs_onCollectCrystal(1); - break; - case 2: - dComIfGs_onCollectCrystal(2); - break; - case 4: - dComIfGs_onCollectMirror(1); - break; - case 5: - dComIfGs_onCollectMirror(2); - break; - case 6: - dComIfGs_onCollectMirror(3); - break; +#if TARGET_PC + int level = getNowLevel(); + const char* checkName = dungeon_reward_check_name(level); + dusk::mods::ItemCheckResult itemCheck{}; + bool applyVanillaReward = true; + if (checkName != nullptr) { + itemCheck = dusk::mods::item_check_commit(checkName, dItemNo_NONE_e, this); + applyVanillaReward = itemCheck.itemNo == dItemNo_NONE_e; } + if (applyVanillaReward) { + switch (level) { +#else + switch (getNowLevel()) { +#endif + case 0: + dComIfGs_onCollectCrystal(0); + break; + case 1: + dComIfGs_onCollectCrystal(1); + break; + case 2: + dComIfGs_onCollectCrystal(2); + break; + case 4: + dComIfGs_onCollectMirror(1); + break; + case 5: + dComIfGs_onCollectMirror(2); + break; + case 6: + dComIfGs_onCollectMirror(3); + break; + } +#if TARGET_PC + if (checkName != nullptr) { + dusk::mods::item_check_complete(itemCheck, this); + } + } else { + dusk::mods::item_check_enqueue(itemCheck, dusk::mods::ItemGiveMode::Silent); + } +#endif mCounter = 0; break; +#if TARGET_PC + } +#endif case 5: // STONE_MIDNA mCounter = 0; break; diff --git a/src/d/actor/d_a_obj_item.cpp b/src/d/actor/d_a_obj_item.cpp index 1176f9aab3..fba0ad7d91 100644 --- a/src/d/actor/d_a_obj_item.cpp +++ b/src/d/actor/d_a_obj_item.cpp @@ -158,8 +158,8 @@ void daItem_c::CreateInit() { mCcCyl.SetCoHitCallback(itemGetCoCallBack); mCcCyl.SetTgHitCallback(itemGetTgCallBack); - f32 cylHeight = dItem_data::getH(m_itemNo); - f32 cylRadius = dItem_data::getR(m_itemNo); + f32 cylHeight = DUSK_IF_ELSE(getCollisionH(), dItem_data::getH(m_itemNo)); + f32 cylRadius = DUSK_IF_ELSE(getCollisionR(), dItem_data::getR(m_itemNo)); if (scale.x > 1.0f) { cylHeight *= scale.x; @@ -267,12 +267,13 @@ int daItem_c::_daItem_create() { #if TARGET_PC const u32 params = fopAcM_GetParam(this); mOriginalItemNo = params & 0xFF; - const u8 resolvedItem = dusk::mods::item_check_freestanding( - daItem_prm::getItemBitNo(this), mOriginalItemNo, this); - mItemOverridden = resolvedItem != mOriginalItemNo; mItemGiveTag = dusk::mods::item_give_tag_freestanding(daItem_prm::getItemBitNo(this)); + const auto [item, displayItem] = + dusk::mods::item_check_resolve(mItemGiveTag, mOriginalItemNo, this); + mItemOverridden = item != mOriginalItemNo; + setDisplayItemNo(displayItem); if (mItemOverridden) { - fopAcM_SetParam(this, (params & 0xFFFFFF00) | resolvedItem); + fopAcM_SetParam(this, (params & 0xFFFFFF00) | item); } #endif field_0x95d = true; @@ -287,7 +288,11 @@ int daItem_c::_daItem_create() { BOOL flag = dItem_data::chkFlag(m_itemNo, 2); #if DEBUG +#if TARGET_PC + if (dItem_fieldModelArc(getDisplayItemNo()) == NULL) { +#else if (dItem_data::getFieldArc(m_itemNo) == NULL) { +#endif // "Item Num<%d>: No Resource Archive specified!!\n" OS_REPORT_ERROR("アイテム番号<%d>:リソースのアーカイブ指定がありません!!\n", m_itemNo); return cPhs_ERROR_e; @@ -319,10 +324,22 @@ int daItem_c::_daItem_create() { if (flag) { CreateInit(); } else { +#if TARGET_PC + const u8 displayItemNo = getDisplayItemNo(); + phase_state = dComIfG_resLoad(&mPhase, dItem_fieldModelArc(displayItemNo)); +#else phase_state = dComIfG_resLoad(&mPhase, dItem_data::getFieldArc(m_itemNo)); +#endif if (phase_state == cPhs_COMPLEATE_e) { +#if TARGET_PC + const bool useModelFallback = dItem_data::getFieldArc(displayItemNo) == NULL; + if (!fopAcM_entrySolidHeap(this, + useModelFallback ? CheckItemCreateHeap : CheckFieldItemCreateHeap, + useModelFallback ? 0x4000 : dItem_data::getFieldHeapSize(displayItemNo))) +#else if (!fopAcM_entrySolidHeap(this, CheckFieldItemCreateHeap, dItem_data::getFieldHeapSize(m_itemNo))) +#endif { return cPhs_ERROR_e; } @@ -339,7 +356,7 @@ int daItem_c::_daItem_execute() { CountTimer(); eyePos = current.pos; - eyePos.y += (f32)dItem_data::getH(m_itemNo) / 2; + eyePos.y += (f32)DUSK_IF_ELSE(getCollisionH(), dItem_data::getH(m_itemNo)) / 2; attention_info.position = current.pos; @@ -412,7 +429,11 @@ int daItem_c::_daItem_delete() { mSparkleEmtr.remove(); } +#if TARGET_PC + DeleteBase(dItem_fieldModelArc(getDisplayItemNo())); +#else DeleteBase(dItem_data::getFieldArc(m_itemNo)); +#endif return 1; } @@ -520,9 +541,10 @@ void daItem_c::procInitGetDemoEvent() { #if TARGET_PC const u8 displayItemNo = m_itemNo; - if (mItemOverridden) { - m_itemNo = dusk::mods::item_check_tagged(mItemGiveTag, mOriginalItemNo, this); - } + const auto itemCheck = dusk::mods::item_check_commit(mItemGiveTag, mOriginalItemNo, this); + m_itemNo = itemCheck.itemNo; + mItemGiveTag = itemCheck.tag; + mItemOverridden = m_itemNo != mOriginalItemNo; #endif m_item_id = fopAcM_createItemForTrBoxDemo( ¤t.pos, m_itemNo, -1, fopAcM_GetRoomNo(this), NULL, NULL IF_DUSK_ARG(mItemGiveTag)); @@ -581,8 +603,8 @@ void daItem_c::procInitBoomerangCarry() { scale = mItemScale; mBoomerangMove.initOffset(¤t.pos); - u8 height = dItem_data::getH(m_itemNo); - u8 radius = dItem_data::getR(m_itemNo); + u8 height = DUSK_IF_ELSE(getCollisionH(), dItem_data::getH(m_itemNo)); + u8 radius = DUSK_IF_ELSE(getCollisionR(), dItem_data::getR(m_itemNo)); mCcCyl.SetR((f32)radius * 2.0f); mCcCyl.SetH((f32)height * 2.0f); mCcCyl.OnCoSPrmBit(1); @@ -907,9 +929,10 @@ void daItem_c::itemGetNextExecute() { void daItem_c::itemGet() { #if TARGET_PC const u8 displayItemNo = m_itemNo; - if (mItemOverridden) { - m_itemNo = dusk::mods::item_check_tagged(mItemGiveTag, mOriginalItemNo, this); - } + const auto itemCheck = dusk::mods::item_check_commit(mItemGiveTag, mOriginalItemNo, this); + m_itemNo = itemCheck.itemNo; + mItemGiveTag = itemCheck.tag; + mItemOverridden = m_itemNo != mOriginalItemNo; #endif switch (m_itemNo) { #if TARGET_PC diff --git a/src/d/actor/d_a_obj_life_container.cpp b/src/d/actor/d_a_obj_life_container.cpp index 3c800e946f..b2eb30167a 100644 --- a/src/d/actor/d_a_obj_life_container.cpp +++ b/src/d/actor/d_a_obj_life_container.cpp @@ -6,6 +6,7 @@ #include "d/dolzel_rel.h" // IWYU pragma: keep #include "d/actor/d_a_obj_life_container.h" +#include "d/d_a_itembase_static.h" #include "d/d_com_inf_game.h" #include "d/actor/d_a_player.h" #include "d/d_item_data.h" @@ -87,8 +88,8 @@ int daObjLife_c::Create() { mCcCyl.SetStts(&mCcStts); mCcCyl.SetCoHitCallback(lifeGetCoCallBack); mCcCyl.SetTgHitCallback(lifeGetTgCallBack); - mCcCyl.SetR(dItem_data::getR(m_itemNo)); - mCcCyl.SetH(dItem_data::getH(m_itemNo)); + mCcCyl.SetR(DUSK_IF_ELSE(getCollisionR(), dItem_data::getR(m_itemNo))); + mCcCyl.SetH(DUSK_IF_ELSE(getCollisionH(), dItem_data::getH(m_itemNo))); fopAcM_SetCullSize(this, fopAc_CULLSPHERE_0_e); fopAcM_SetGravity(this, -3.2f); @@ -151,16 +152,30 @@ int daObjLife_c::create() { const u8 parameterItemNo = params & 0xFF; if (mItemGiveOriginalNo == dItemNo_NONE_e) { mOriginalItemNo = parameterItemNo; - const u8 resolvedItem = - dusk::mods::item_check_freestanding(getSaveBitNo(), mOriginalItemNo, this); mItemGiveTag = dusk::mods::item_give_tag_freestanding(getSaveBitNo()); - mItemOverridden = resolvedItem != mOriginalItemNo; + const auto [item, displayItem] = + dusk::mods::item_check_resolve(mItemGiveTag, mOriginalItemNo, this); + setDisplayItemNo(displayItem); + mItemOverridden = item != mOriginalItemNo; if (mItemOverridden) { - fopAcM_SetParam(this, (params & 0xFFFFFF00) | resolvedItem); + fopAcM_SetParam(this, (params & 0xFFFFFF00) | item); + } + } else if (mGoldenWolfItem) { + mOriginalItemNo = mItemGiveOriginalNo; + mItemGiveTag = dusk::mods::item_give_tag_golden_wolf(static_cast(field_0x938)); + const auto [item, displayItem] = + dusk::mods::item_check_resolve(mItemGiveTag, mOriginalItemNo, this); + setDisplayItemNo(displayItem); + mItemOverridden = item != mOriginalItemNo; + if (item != parameterItemNo) { + fopAcM_SetParam(this, (params & 0xFFFFFF00) | item); } } else { mOriginalItemNo = mItemGiveOriginalNo; - mItemOverridden = parameterItemNo != mItemGiveOriginalNo; + setDisplayItemNo( + dusk::mods::item_check_resolve(mItemGiveTag, parameterItemNo, this) + .display_item); + mItemOverridden = parameterItemNo != mOriginalItemNo; } mOverrideHover = mItemOverridden && @@ -184,11 +199,24 @@ int daObjLife_c::create() { return cPhs_ERROR_e; } +#if TARGET_PC + // Resolved items may have no field model; display their get-demo model instead. + const u8 displayItemNo = getDisplayItemNo(); + const bool useGetModel = dItem_data::getFieldArc(displayItemNo) == NULL; + int phase_state = dComIfG_resLoad(&mPhase, dItem_fieldModelArc(displayItemNo)); + if (phase_state == cPhs_COMPLEATE_e) { + if (!fopAcM_entrySolidHeap( + this, useGetModel ? CheckItemCreateHeap : CheckFieldItemCreateHeap, 0x4000)) + { + return cPhs_ERROR_e; + } +#else int phase_state = dComIfG_resLoad(&mPhase, dItem_data::getFieldArc(m_itemNo)); if (phase_state == cPhs_COMPLEATE_e) { if (!fopAcM_entrySolidHeap(this, CheckFieldItemCreateHeap, 0x4000)) { return cPhs_ERROR_e; } +#endif if (!Create()) { return cPhs_ERROR_e; @@ -325,9 +353,10 @@ int daObjLife_c::initActionOrderGetDemo() { #if TARGET_PC const u8 displayItemNo = m_itemNo; - if (mItemOverridden) { - m_itemNo = dusk::mods::item_check_tagged(mItemGiveTag, mOriginalItemNo, this); - } + const auto itemCheck = dusk::mods::item_check_commit(mItemGiveTag, mOriginalItemNo, this); + m_itemNo = itemCheck.itemNo; + mItemGiveTag = itemCheck.tag; + mItemOverridden = m_itemNo != mOriginalItemNo; #endif mItemId = fopAcM_createItemForTrBoxDemo( ¤t.pos, m_itemNo, -1, fopAcM_GetRoomNo(this), NULL, NULL IF_DUSK_ARG(mItemGiveTag)); @@ -397,8 +426,8 @@ int daObjLife_c::actionInitBoomerangCarry() { mCcCyl.OnTgSPrmBit(1); mCcCyl.OnCoSPrmBit(1); - f32 height = dItem_data::getH(m_itemNo) * 4.0f; - f32 radius = dItem_data::getR(m_itemNo) * 4.0f; + f32 height = DUSK_IF_ELSE(getCollisionH(), dItem_data::getH(m_itemNo)) * 4.0f; + f32 radius = DUSK_IF_ELSE(getCollisionR(), dItem_data::getR(m_itemNo)) * 4.0f; mCcCyl.SetR(radius); mCcCyl.SetH(height); @@ -519,7 +548,11 @@ int daObjLife_c::_delete() { endEffect00(); endEffect02(); +#if TARGET_PC + DeleteBase(dItem_fieldModelArc(getDisplayItemNo())); +#else DeleteBase(dItem_data::getFieldArc(m_itemNo)); +#endif return 1; } diff --git a/src/d/actor/d_a_obj_master_sword.cpp b/src/d/actor/d_a_obj_master_sword.cpp index 820f603363..36fa786808 100644 --- a/src/d/actor/d_a_obj_master_sword.cpp +++ b/src/d/actor/d_a_obj_master_sword.cpp @@ -1,6 +1,6 @@ /** * @file d_a_obj_master_sword.cpp - * + * */ #include "d/dolzel_rel.h" // IWYU pragma: keep @@ -10,6 +10,12 @@ #include "d/d_com_inf_game.h" #include "d/d_meter2_info.h" +#if TARGET_PC +#include "d/d_item.h" +#include "dusk/mods/item.hpp" +#include "mods/items.h" +#endif + DUSK_GAME_DATA daObjMasterSword_Attr_c const daObjMasterSword_c::mAttr = {1.0f}; void daObjMasterSword_c::initBaseMtx() { @@ -145,7 +151,11 @@ void daObjMasterSword_c::create_init() { int daObjMasterSword_c::create() { fopAcM_ct(this, daObjMasterSword_c); +#if TARGET_PC + if (dComIfGs_isEventBit(dSv_event_flag_c::F_0264)) { +#else if (dComIfGs_isEventBit(dSv_event_flag_c::saveBitLabels[getFlagNo()])) { +#endif return cPhs_ERROR_e; } @@ -186,12 +196,41 @@ int daObjMasterSword_c::execute() { mBrk.play(); if (dComIfGs_isTmpBit(dSv_event_tmp_flag_c::tempBitLabels[73])) { +#if TARGET_PC + const auto masterSword = dusk::mods::item_check_commit( + ITEM_CHECK_MASTER_SWORD, dItemNo_MASTER_SWORD_e, this); + if (masterSword.itemNo == dItemNo_MASTER_SWORD_e) { + dComIfGs_onItemFirstBit(dItemNo_MASTER_SWORD_e); + dMeter2Info_setSword(dItemNo_MASTER_SWORD_e, false); + dComIfGs_setSelectEquipSword(dItemNo_MASTER_SWORD_e); + dusk::mods::item_check_complete(masterSword, this); + } else if (masterSword.itemNo == dItemNo_NONE_e) { + dusk::mods::item_check_complete(masterSword, this); + } else { + dusk::mods::item_check_enqueue(masterSword, dusk::mods::ItemGiveMode::Demo); + } + + dComIfGp_setItemLifeCount(dComIfGs_getMaxLife(), 0); + + const auto shadowCrystal = dusk::mods::item_check_commit( + ITEM_CHECK_SHADOW_CRYSTAL, dItemNo_SHADOW_CRYSTAL_e, this); + if (shadowCrystal.itemNo == dItemNo_SHADOW_CRYSTAL_e) { + execItemGet(shadowCrystal.itemNo, shadowCrystal.tag, this); + } else if (shadowCrystal.itemNo == dItemNo_NONE_e) { + dusk::mods::item_check_complete(shadowCrystal, this); + } else { + dusk::mods::item_check_enqueue(shadowCrystal, dusk::mods::ItemGiveMode::Demo); + } + + dComIfGs_onEventBit(dSv_event_flag_c::F_0264); +#else dComIfGs_onItemFirstBit(dItemNo_MASTER_SWORD_e); dMeter2Info_setSword(dItemNo_MASTER_SWORD_e, false); dComIfGs_setSelectEquipSword(dItemNo_MASTER_SWORD_e); dComIfGp_setItemLifeCount(dComIfGs_getMaxLife(), 0); dComIfGs_onEventBit(dSv_event_flag_c::saveBitLabels[getFlagNo()]); +#endif fopAcM_delete(this); } diff --git a/src/d/actor/d_a_obj_shield.cpp b/src/d/actor/d_a_obj_shield.cpp index abe56ad6c8..5cc63c9a89 100644 --- a/src/d/actor/d_a_obj_shield.cpp +++ b/src/d/actor/d_a_obj_shield.cpp @@ -109,7 +109,7 @@ int daItemShield_c::__CreateHeap() { int daItemShield_c::create() { fopAcM_ct(this, daItemShield_c); m_itemNo = dItemNo_WOOD_SHIELD_e; - DUSK_ITEM_CHECK("ordon_shield", m_itemNo, this); + DUSK_ITEM_CHECK_PREVIEW("ordon_shield", m_itemNo, this); if (fopAcM_isSwitch(this, getSwBit2())) { OS_REPORT("木の盾:もう取ったので出ません\n"); return cPhs_ERROR_e; diff --git a/src/d/actor/d_a_obj_smallkey.cpp b/src/d/actor/d_a_obj_smallkey.cpp index 9bf8face57..6914cee5f0 100644 --- a/src/d/actor/d_a_obj_smallkey.cpp +++ b/src/d/actor/d_a_obj_smallkey.cpp @@ -1,6 +1,6 @@ /** * @file d_a_obj_smallkey.cpp - * + * */ #include "d/dolzel_rel.h" // IWYU pragma: keep @@ -119,9 +119,9 @@ int daKey_c::Create() { mCcCyl.SetStts(&mCcStts); mCcCyl.SetCoHitCallback(keyGetCoCallBack); mCcCyl.SetTgHitCallback(keyGetTgCallBack); - mCcCyl.SetR(dItem_data::getR(m_itemNo)); - mCcCyl.SetH(dItem_data::getH(m_itemNo)); - + mCcCyl.SetR(DUSK_IF_ELSE(getCollisionR(), dItem_data::getR(m_itemNo))); + mCcCyl.SetH(DUSK_IF_ELSE(getCollisionH(), dItem_data::getH(m_itemNo))); + fopAcM_SetCullSize(this, fopAc_CULLSPHERE_0_e); if (getSwNo() == 0xFF) { @@ -155,7 +155,21 @@ int daKey_c::create() { mIsPrmInit = TRUE; } +#if TARGET_PC + mItemGiveTag = dusk::mods::item_give_tag_freestanding(getSaveBitNo()); + const auto [item, displayItem] = + dusk::mods::item_check_resolve(mItemGiveTag, dItemNo_SMALL_KEY_e, this); + m_itemNo = item; + if (m_itemNo == dItemNo_NONE_e) { + // Keep the pickup visible until the empty check is collected. + m_itemNo = dItemNo_SMALL_KEY_e; + setDisplayItemNo(dItemNo_NONE_e); + } else { + setDisplayItemNo(displayItem); + } +#else m_itemNo = dItemNo_SMALL_KEY_e; +#endif if (strcmp(dComIfGp_getStartStageName(), "F_SP118") == 0) { OS_REPORT(" SMKEY 0\n"); @@ -170,9 +184,21 @@ int daKey_c::create() { return cPhs_ERROR_e; } +#if TARGET_PC + const u8 displayItemNo = getDisplayItemNo(); + int phase_state = dComIfG_resLoad(&mPhase, dItem_fieldModelArc(displayItemNo)); +#else int phase_state = dComIfG_resLoad(&mPhase, dItem_data::getFieldArc(m_itemNo)); +#endif if (phase_state == cPhs_COMPLEATE_e) { +#if TARGET_PC + const bool useModelFallback = dItem_data::getFieldArc(displayItemNo) == NULL; + if (!fopAcM_entrySolidHeap( + this, useModelFallback ? CheckItemCreateHeap : CheckFieldItemCreateHeap, 0x4000)) + { +#else if (!fopAcM_entrySolidHeap(this, CheckFieldItemCreateHeap, 0x840)) { +#endif return cPhs_ERROR_e; } @@ -317,10 +343,26 @@ int daKey_c::initActionOrderGetDemo() { hide(); effectStop(); +#if TARGET_PC + const auto itemCheck = + dusk::mods::item_check_commit(mItemGiveTag, dItemNo_SMALL_KEY_e, this); + m_itemNo = itemCheck.itemNo; + if (m_itemNo == dItemNo_NONE_e) { + dusk::mods::item_check_complete(itemCheck, this); + dComIfGs_onTbox(getSaveBitNo()); + dTres_c::offStatus(getSaveBitNo(), 1); + dComIfGp_event_reset(); + fopAcM_delete(this); + return 1; + } +#endif + fopAcM_orderItemEvent(this, 0, 0); eventInfo.onCondition(8); - mItemId = fopAcM_createItemForTrBoxDemo(¤t.pos, m_itemNo, -1, fopAcM_GetRoomNo(this), NULL, NULL); + mItemId = fopAcM_createItemForTrBoxDemo( + ¤t.pos, m_itemNo, -1, fopAcM_GetRoomNo(this), NULL, + NULL IF_DUSK_ARG(itemCheck.tag)); JUT_ASSERT(699, mItemId != fpcM_ERROR_PROCESS_ID_e); setStatus(STATUS_ORDER_GET_DEMO_e); @@ -387,8 +429,8 @@ int daKey_c::actionInitBoomerangCarry() { mCcCyl.OnTgSPrmBit(1); mCcCyl.OnCoSPrmBit(1); - u8 height = dItem_data::getH(m_itemNo); - u8 radius = dItem_data::getR(m_itemNo); + u8 height = DUSK_IF_ELSE(getCollisionH(), dItem_data::getH(m_itemNo)); + u8 radius = DUSK_IF_ELSE(getCollisionR(), dItem_data::getR(m_itemNo)); mCcCyl.SetR(4.0f * radius); mCcCyl.SetH(4.0f * height); @@ -527,7 +569,11 @@ int daKey_c::draw() { int daKey_c::_delete() { effectStop(); +#if TARGET_PC + DeleteBase(dItem_fieldModelArc(getDisplayItemNo())); +#else DeleteBase(dItem_data::getFieldArc(m_itemNo)); +#endif return 1; } diff --git a/src/d/actor/d_a_obj_sword.cpp b/src/d/actor/d_a_obj_sword.cpp index d7bf0cfaab..f87d078512 100644 --- a/src/d/actor/d_a_obj_sword.cpp +++ b/src/d/actor/d_a_obj_sword.cpp @@ -37,7 +37,7 @@ int daObjSword_c::Create() { cPhs_Step daObjSword_c::create() { fopAcM_ct(this, daObjSword_c); m_itemNo = 0x28; - DUSK_ITEM_CHECK("ordon_sword", m_itemNo, this); + DUSK_ITEM_CHECK_PREVIEW("ordon_sword", m_itemNo, this); if (fopAcM_isItem(this, getItemBit())) { return cPhs_ERROR_e; } diff --git a/src/d/actor/d_a_obj_zcloth.cpp b/src/d/actor/d_a_obj_zcloth.cpp index 7d9ca8fc51..74a957fa8d 100644 --- a/src/d/actor/d_a_obj_zcloth.cpp +++ b/src/d/actor/d_a_obj_zcloth.cpp @@ -32,7 +32,7 @@ int daObjZCloth_c::Create() { int daObjZCloth_c::create() { fopAcM_ct(this, daObjZCloth_c); m_itemNo = 0x31; - DUSK_ITEM_CHECK("zora_armor", m_itemNo, this); + DUSK_ITEM_CHECK_PREVIEW("zora_armor", m_itemNo, this); int phase = dComIfG_resLoad(&mPhase, dItem_data::getFieldArc(m_itemNo)); if (phase == cPhs_COMPLEATE_e) { if (!fopAcM_entrySolidHeap(this, (heapCallbackFunc)CheckFieldItemCreateHeap, 0x2fb0)) { diff --git a/src/d/actor/d_a_shop_item.cpp b/src/d/actor/d_a_shop_item.cpp index 3e768a1684..a7a159ab1c 100644 --- a/src/d/actor/d_a_shop_item.cpp +++ b/src/d/actor/d_a_shop_item.cpp @@ -105,17 +105,19 @@ const char* daShopItem_c::getShopArcname() { #if TARGET_PC if (m_itemNo != dItemNo_NONE_e && mItemGiveOriginalNo == dItemNo_NONE_e) { mItemGiveOriginalNo = m_itemNo; - const u8 resolvedItem = dusk::mods::item_check_shop(mItemGiveOriginalNo, this); - mItemOverridden = resolvedItem != mItemGiveOriginalNo; + mItemGiveTag = dusk::mods::item_give_tag_shop(mItemGiveOriginalNo); + const auto [_, displayItem] = + dusk::mods::item_check_resolve(mItemGiveTag, mItemGiveOriginalNo, this); + mItemOverridden = displayItem != mItemGiveOriginalNo; if (mItemOverridden) { mOverrideData = mData[mShopItemID]; - mOverrideData.mArcName = dItem_data::getArcName(resolvedItem); - mOverrideData.mBmdName = dItem_data::getBmdName(resolvedItem); - mOverrideData.mBtkName = dItem_data::getBtkName(resolvedItem); - mOverrideData.mBckName = dItem_data::getBckName(resolvedItem); - mOverrideData.mBrkName = dItem_data::getBrkName(resolvedItem); - mOverrideData.mBtpName = dItem_data::getBtpName(resolvedItem); - mOverrideData.mTevFrm = dItem_data::getTevFrm(resolvedItem); + mOverrideData.mArcName = dItem_data::getArcName(displayItem); + mOverrideData.mBmdName = dItem_data::getBmdName(displayItem); + mOverrideData.mBtkName = dItem_data::getBtkName(displayItem); + mOverrideData.mBckName = dItem_data::getBckName(displayItem); + mOverrideData.mBrkName = dItem_data::getBrkName(displayItem); + mOverrideData.mBtpName = dItem_data::getBtpName(displayItem); + mOverrideData.mTevFrm = dItem_data::getTevFrm(displayItem); mOverrideData.mBtpFrm = -1; mOverrideData.mFlag = static_cast(-1); mOverrideData.mOffsetY = mShopItemID == SHOP_ITEMNO_ARMOR ? 60.0f : 15.0f; diff --git a/src/d/actor/d_a_tag_statue_evt.cpp b/src/d/actor/d_a_tag_statue_evt.cpp index de5666aef9..cdd0db19ad 100644 --- a/src/d/actor/d_a_tag_statue_evt.cpp +++ b/src/d/actor/d_a_tag_statue_evt.cpp @@ -363,10 +363,13 @@ int daTagStatue_c::demoProc() { } #if TARGET_PC - item = dusk::mods::item_check_sky_character(item & 0xFF, this); + const auto itemCheck = dusk::mods::item_check_commit( + dusk::mods::item_give_tag_sky_character(), item & 0xFF, this); + item = itemCheck.itemNo; #endif - mItemId = fopAcM_createItemForTrBoxDemo(¤t.pos, item, -1, - fopAcM_GetRoomNo(this), 0, 0 IF_DUSK_ARG(dusk::mods::item_give_tag_sky_character())); + mItemId = + fopAcM_createItemForTrBoxDemo(¤t.pos, item, -1, fopAcM_GetRoomNo(this), 0, + 0 IF_DUSK_ARG(itemCheck.tag)); JUT_ASSERT(580, mItemId != fpcM_ERROR_PROCESS_ID_e); diff --git a/src/d/actor/d_a_tbox.cpp b/src/d/actor/d_a_tbox.cpp index c77478da91..f8048478ee 100644 --- a/src/d/actor/d_a_tbox.cpp +++ b/src/d/actor/d_a_tbox.cpp @@ -1391,8 +1391,9 @@ u8 daTbox_c::getBombItemNoMain(u8 i_itemNo) { int daTbox_c::setGetDemoItem() { u8 item_no = getItemNo(); #if TARGET_PC - const u32 giveTag = dusk::mods::item_give_tag_chest(getTboxNo()); - item_no = dusk::mods::item_check_tagged(giveTag, mOriginalItemNo, this); + const auto itemCheck = dusk::mods::item_check_commit( + dusk::mods::item_give_tag_chest(getTboxNo()), mOriginalItemNo, this); + item_no = itemCheck.itemNo; #endif if (item_no == dItemNo_BOMB_5_e || item_no == dItemNo_BOMB_10_e || item_no == dItemNo_BOMB_20_e || item_no == dItemNo_BOMB_30_e || item_no == dItemNo_WATER_BOMB_5_e || item_no == dItemNo_WATER_BOMB_10_e || item_no == dItemNo_WATER_BOMB_20_e || item_no == dItemNo_WATER_BOMB_30_e || @@ -1404,10 +1405,10 @@ int daTbox_c::setGetDemoItem() { fpc_ProcID item_id; if (field_0x718) { item_id = fopAcM_createItemForPresentDemo( - ¤t.pos, item_no, 1, -1, -1, NULL, NULL IF_DUSK_ARG(giveTag)); + ¤t.pos, item_no, 1, -1, -1, NULL, NULL IF_DUSK_ARG(itemCheck.tag)); } else { item_id = fopAcM_createItemForTrBoxDemo( - ¤t.pos, item_no, -1, -1, NULL, NULL IF_DUSK_ARG(giveTag)); + ¤t.pos, item_no, -1, -1, NULL, NULL IF_DUSK_ARG(itemCheck.tag)); } if (item_id != fpcM_ERROR_PROCESS_ID_e) { diff --git a/src/d/actor/d_a_tbox2.cpp b/src/d/actor/d_a_tbox2.cpp index 54c3e3135e..2d35e8285f 100644 --- a/src/d/actor/d_a_tbox2.cpp +++ b/src/d/actor/d_a_tbox2.cpp @@ -383,15 +383,18 @@ int daTbox2_c::setGetDemoItem() { u8 item_no = getItemNo(); #if TARGET_PC int tboxNo = fopAcM_GetParamBit(this, 16, 8); - const u32 giveTag = dusk::mods::item_give_tag_chest(tboxNo); - item_no = dusk::mods::item_check_tagged(giveTag, mOriginalItemNo, this); + const auto itemCheck = dusk::mods::item_check_commit( + dusk::mods::item_give_tag_chest(tboxNo), mOriginalItemNo, this); + item_no = itemCheck.itemNo; #endif u32 partner_id; if (mReturnRupee) { - partner_id = fopAcM_createItemForPresentDemo(¤t.pos, item_no, 1, -1, -1, NULL, NULL IF_DUSK_ARG(giveTag)); + partner_id = fopAcM_createItemForPresentDemo( + ¤t.pos, item_no, 1, -1, -1, NULL, NULL IF_DUSK_ARG(itemCheck.tag)); } else { - partner_id = fopAcM_createItemForTrBoxDemo(¤t.pos, item_no, -1, -1, NULL, NULL IF_DUSK_ARG(giveTag)); + partner_id = fopAcM_createItemForTrBoxDemo( + ¤t.pos, item_no, -1, -1, NULL, NULL IF_DUSK_ARG(itemCheck.tag)); } if (partner_id != -1) { diff --git a/src/d/d_a_itembase_static.cpp b/src/d/d_a_itembase_static.cpp index 5e98a20409..ec3610a787 100644 --- a/src/d/d_a_itembase_static.cpp +++ b/src/d/d_a_itembase_static.cpp @@ -50,17 +50,24 @@ bool daItemBase_c::chkDead() { int CheckItemCreateHeap(fopAc_ac_c* i_this) { daItemBase_c* a_this = static_cast(i_this); - u8 item_no = a_this->getItemNo(); + u8 item_no = DUSK_IF_ELSE(a_this->getDisplayItemNo(), a_this->getItemNo()); return a_this->CreateItemHeap(dItem_data::getArcName(item_no), dItem_data::getBmdName(item_no), dItem_data::getBtkName(item_no), dItem_data::getBpkName(item_no), dItem_data::getBckName(item_no), dItem_data::getBxaName(item_no), dItem_data::getBrkName(item_no), dItem_data::getBtpName(item_no)); } +#if TARGET_PC +const char* dItem_fieldModelArc(u8 itemNo) { + const char* arcName = dItem_data::getFieldArc(itemNo); + return arcName != NULL ? arcName : dItem_data::getArcName(itemNo); +} +#endif + int CheckFieldItemCreateHeap(fopAc_ac_c* i_this) { daItemBase_c* a_this = static_cast(i_this); - u8 item_no = a_this->getItemNo(); + u8 item_no = DUSK_IF_ELSE(a_this->getDisplayItemNo(), a_this->getItemNo()); return a_this->CreateItemHeap( dItem_data::getFieldArc(item_no), dItem_data::getItemBmdName(item_no), dItem_data::getItemBtkName(item_no), dItem_data::getItemBpkName(item_no), diff --git a/src/d/d_com_inf_game.cpp b/src/d/d_com_inf_game.cpp index 61aa0dc179..ecd0b796a0 100644 --- a/src/d/d_com_inf_game.cpp +++ b/src/d/d_com_inf_game.cpp @@ -1503,7 +1503,11 @@ static void dummy1() { } BOOL dComIfGs_isStageTbox(int i_stageNo, int i_no) { +#if TARGET_PC + if (dComIfGp_getStageStagInfo() && i_stageNo == dStage_stagInfo_GetSaveTbl(dComIfGp_getStageStagInfo())) { +#else if (i_stageNo == dStage_stagInfo_GetSaveTbl(dComIfGp_getStageStagInfo())) { +#endif return dComIfGs_isTbox(i_no); } else { return dComIfGs_isSaveTbox(i_stageNo, i_no); @@ -1511,7 +1515,11 @@ BOOL dComIfGs_isStageTbox(int i_stageNo, int i_no) { } void dComIfGs_onStageSwitch(int i_stageNo, int i_no) { +#if TARGET_PC + if (dComIfGp_getStageStagInfo() && i_stageNo == dStage_stagInfo_GetSaveTbl(dComIfGp_getStageStagInfo())) { +#else if (i_stageNo == dStage_stagInfo_GetSaveTbl(dComIfGp_getStageStagInfo())) { +#endif dComIfGs_onSwitch(i_no, -1); } @@ -1527,7 +1535,11 @@ void dComIfGs_offStageSwitch(int i_stageNo, int i_no) { } BOOL dComIfGs_isStageSwitch(int i_stageNo, int i_no) { +#if TARGET_PC + if (dComIfGp_getStageStagInfo() && i_stageNo == dStage_stagInfo_GetSaveTbl(dComIfGp_getStageStagInfo())) { +#else if (i_stageNo == dStage_stagInfo_GetSaveTbl(dComIfGp_getStageStagInfo())) { +#endif return dComIfGs_isSwitch(i_no, -1); } else { return dComIfGs_isSaveSwitch(i_stageNo, i_no); @@ -1535,7 +1547,11 @@ BOOL dComIfGs_isStageSwitch(int i_stageNo, int i_no) { } void dComIfGs_onDungeonItemMap(int i_stageNo) { +#if TARGET_PC + if (dComIfGp_getStageStagInfo() && i_stageNo == dStage_stagInfo_GetSaveTbl(dComIfGp_getStageStagInfo())) { +#else if (i_stageNo == dStage_stagInfo_GetSaveTbl(dComIfGp_getStageStagInfo())) { +#endif dComIfGs_onDungeonItemMap(); } @@ -1551,7 +1567,11 @@ void dComIfGs_offDungeonItemMap(int i_stageNo) { } s32 dComIfGs_isDungeonItemMap(int i_stageNo) { +#if TARGET_PC + if (dComIfGp_getStageStagInfo() && i_stageNo == dStage_stagInfo_GetSaveTbl(dComIfGp_getStageStagInfo())) { +#else if (i_stageNo == dStage_stagInfo_GetSaveTbl(dComIfGp_getStageStagInfo())) { +#endif return dComIfGs_isDungeonItemMap(); } @@ -1559,7 +1579,11 @@ s32 dComIfGs_isDungeonItemMap(int i_stageNo) { } void dComIfGs_onDungeonItemCompass(int i_stageNo) { +#if TARGET_PC + if (dComIfGp_getStageStagInfo() && i_stageNo == dStage_stagInfo_GetSaveTbl(dComIfGp_getStageStagInfo())) { +#else if (i_stageNo == dStage_stagInfo_GetSaveTbl(dComIfGp_getStageStagInfo())) { +#endif dComIfGs_onDungeonItemCompass(); } @@ -1575,7 +1599,11 @@ void dComIfGs_offDungeonItemCompass(int i_stageNo) { } s32 dComIfGs_isDungeonItemCompass(int i_stageNo) { +#if TARGET_PC + if (dComIfGp_getStageStagInfo() && i_stageNo == dStage_stagInfo_GetSaveTbl(dComIfGp_getStageStagInfo())) { +#else if (i_stageNo == dStage_stagInfo_GetSaveTbl(dComIfGp_getStageStagInfo())) { +#endif return dComIfGs_isDungeonItemCompass(); } @@ -1583,7 +1611,11 @@ s32 dComIfGs_isDungeonItemCompass(int i_stageNo) { } void dComIfGs_onDungeonItemBossKey(int i_stageNo) { +#if TARGET_PC + if (dComIfGp_getStageStagInfo() && i_stageNo == dStage_stagInfo_GetSaveTbl(dComIfGp_getStageStagInfo())) { +#else if (i_stageNo == dStage_stagInfo_GetSaveTbl(dComIfGp_getStageStagInfo())) { +#endif dComIfGs_onDungeonItemBossKey(); } @@ -1599,7 +1631,11 @@ void dComIfGs_offDungeonItemBossKey(int i_stageNo) { } s32 dComIfGs_isDungeonItemBossKey(int i_stageNo) { +#if TARGET_PC + if (dComIfGp_getStageStagInfo() && i_stageNo == dStage_stagInfo_GetSaveTbl(dComIfGp_getStageStagInfo())) { +#else if (i_stageNo == dStage_stagInfo_GetSaveTbl(dComIfGp_getStageStagInfo())) { +#endif return dComIfGs_isDungeonItemBossKey(); } @@ -2996,6 +3032,3602 @@ DUSK_GAME_DATA GXColor g_whiteColor = {255, 255, 255, 255}; DUSK_GAME_DATA GXColor g_saftyWhiteColor = {160, 160, 160, 255}; #if TARGET_PC +dSv_info_c* dComIfGs_getSaveInfo() { + return &g_dComIfG_gameInfo.info; +} + +dSv_save_c* dComIfGs_getSaveData() { + return &g_dComIfG_gameInfo.info.getSavedata(); +} + +u16 dComIfGs_getMaxLife() { + return g_dComIfG_gameInfo.info.getPlayer().getPlayerStatusA().getMaxLife(); +} + +void dComIfGs_setMaxLife(u8 i_maxLife) { + g_dComIfG_gameInfo.info.getPlayer().getPlayerStatusA().setMaxLife(i_maxLife); +} + +u16 dComIfGs_getLife() { + return g_dComIfG_gameInfo.info.getPlayer().getPlayerStatusA().getLife(); +} + +void dComIfGs_setLife(u16 i_life) { + g_dComIfG_gameInfo.info.getPlayer().getPlayerStatusA().setLife(i_life); +} + +u16 dComIfGs_getRupee() { + return g_dComIfG_gameInfo.info.getPlayer().getPlayerStatusA().getRupee(); +} + +void dComIfGs_setRupee(u16 i_rupees) { + g_dComIfG_gameInfo.info.getPlayer().getPlayerStatusA().setRupee(i_rupees); +} + +u16 dComIfGs_getMaxOil() { + return g_dComIfG_gameInfo.info.getPlayer().getPlayerStatusA().getMaxOil(); +} + +void dComIfGs_setMaxOil(u16 i_maxOil) { + g_dComIfG_gameInfo.info.getPlayer().getPlayerStatusA().setMaxOil(i_maxOil); +} + +u16 dComIfGs_getOil() { + return g_dComIfG_gameInfo.info.getPlayer().getPlayerStatusA().getOil(); +} + +void dComIfGs_setOil(u16 i_oil) { + g_dComIfG_gameInfo.info.getPlayer().getPlayerStatusA().setOil(i_oil); +} + +u8 dComIfGs_getSelectEquipClothes() { + return g_dComIfG_gameInfo.info.getPlayer().getPlayerStatusA().getSelectEquip(COLLECT_CLOTHING); +} + +u8 dComIfGs_getSelectEquipSword() { + return g_dComIfG_gameInfo.info.getPlayer().getPlayerStatusA().getSelectEquip(COLLECT_SWORD); +} + +u8 dComIfGs_getSelectEquipShield() { + return g_dComIfG_gameInfo.info.getPlayer().getPlayerStatusA().getSelectEquip(COLLECT_SHIELD); +} + +u8 dComIfGs_getCollectSmell() { + return g_dComIfG_gameInfo.info.getPlayer().getPlayerStatusA().getSelectEquip(COLLECT_SMELL); +} + +void dComIfGs_setCollectSmell(u8 smell) { + g_dComIfG_gameInfo.info.getPlayer().getPlayerStatusA().setSelectEquip(COLLECT_SMELL, smell); +} + +u8 dComIfGs_getBButtonItemKey() { + return g_dComIfG_gameInfo.info.getPlayer().getPlayerStatusA().getSelectEquip(B_BUTTON_ITEM); +} + +void dComIfGs_setBButtonItemKey(u8 i_itemNo) { + g_dComIfG_gameInfo.info.getPlayer().getPlayerStatusA().setSelectEquip(B_BUTTON_ITEM, i_itemNo); +} + +u8 dComIfGs_getWalletSize() { + return g_dComIfG_gameInfo.info.getPlayer().getPlayerStatusA().getWalletSize(); +} + +void dComIfGs_setWalletSize(u8 i_size) { + g_dComIfG_gameInfo.info.getPlayer().getPlayerStatusA().setWalletSize(i_size); +} + +u8 dComIfGs_getMaxMagic() { + return g_dComIfG_gameInfo.info.getPlayer().getPlayerStatusA().getMaxMagic(); +} + +void dComIfGs_setMaxMagic(u8 i_maxMagic) { + g_dComIfG_gameInfo.info.getPlayer().getPlayerStatusA().setMaxMagic(i_maxMagic); +} + +u8 dComIfGs_getMagic() { + return g_dComIfG_gameInfo.info.getPlayer().getPlayerStatusA().getMagic(); +} + +void dComIfGs_setMagic(u8 i_magic) { + g_dComIfG_gameInfo.info.getPlayer().getPlayerStatusA().setMagic(i_magic); +} + +u8 dComIfGs_getTransformStatus() { + return g_dComIfG_gameInfo.info.getPlayer().getPlayerStatusA().getTransformStatus(); +} + +void dComIfGs_setTransformStatus(u8 i_status) { + g_dComIfG_gameInfo.info.getPlayer().getPlayerStatusA().setTransformStatus(i_status); +} + +u8 dComIfGs_getSelectItemIndex(int i_no) { + return g_dComIfG_gameInfo.info.getPlayer().getPlayerStatusA().getSelectItemIndex(i_no); +} + +u16 dComIfGs_getRupeeMax() { + return g_dComIfG_gameInfo.info.getPlayer().getPlayerStatusA().getRupeeMax(); +} + +void dComIfGs_offGetMagicUseFlag() { + g_dComIfG_gameInfo.info.getPlayer().getPlayerStatusA().offMagicFlag(0); +} + +s32 dComIfGs_isGetMagicUseFlag() { + return g_dComIfG_gameInfo.info.getPlayer().getPlayerStatusA().isMagicFlag(0); +} + +f32 dComIfGs_getTime() { + return g_dComIfG_gameInfo.info.getPlayer().getPlayerStatusB().getTime(); +} + +void dComIfGs_setTime(f32 i_time) { + return g_dComIfG_gameInfo.info.getPlayer().getPlayerStatusB().setTime(i_time); +} + +u16 dComIfGs_getDate() { + return g_dComIfG_gameInfo.info.getPlayer().getPlayerStatusB().getDate(); +} + +void dComIfGs_setDate(u16 i_date) { + return g_dComIfG_gameInfo.info.getPlayer().getPlayerStatusB().setDate(i_date); +} + +void dComIfGs_onDarkClearLV(int i_no) { + g_dComIfG_gameInfo.info.getPlayer().getPlayerStatusB().onDarkClearLV(i_no); +} + +void dComIfGs_offDarkClearLV(int i_no) { + g_dComIfG_gameInfo.info.getPlayer().getPlayerStatusB().offDarkClearLV(i_no); +} + +BOOL dComIfGs_isDarkClearLV(int i_no) { + return g_dComIfG_gameInfo.info.getPlayer().getPlayerStatusB().isDarkClearLV(i_no); +} + +void dComIfGs_onTransformLV(int i_no) { + g_dComIfG_gameInfo.info.getPlayer().getPlayerStatusB().onTransformLV(i_no); +} + +void dComIfGs_offTransformLV(int i_no) { + g_dComIfG_gameInfo.info.getPlayer().getPlayerStatusB().offTransformLV(i_no); +} + +BOOL dComIfGs_isTransformLV(int i_no) { + return g_dComIfG_gameInfo.info.getPlayer().getPlayerStatusB().isTransformLV(i_no); +} + +cXyz dComIfGs_getHorseRestartPos() { + return g_dComIfG_gameInfo.info.getPlayer().getHorsePlace().getPos(); +} + +s16 dComIfGs_getHorseRestartAngleY() { + return g_dComIfG_gameInfo.info.getPlayer().getHorsePlace().getAngleY(); +} + +const char* dComIfGs_getHorseRestartStageName() { + return g_dComIfG_gameInfo.info.getPlayer().getHorsePlace().getStageName(); +} + +s8 dComIfGs_getHorseRestartRoomNo() { + return g_dComIfG_gameInfo.info.getPlayer().getHorsePlace().getRoomNo(); +} + +void dComIfGs_setHorseRestart(const char* i_stageName, cXyz& i_pos, s16 i_angle, s8 i_roomNo) { + g_dComIfG_gameInfo.info.getPlayer().getHorsePlace().set(i_stageName, i_pos, i_angle, i_roomNo); +} + +cXyz dComIfGs_getPlayerFieldLastStayPos() { + return g_dComIfG_gameInfo.info.getPlayer().getPlayerFieldLastStayInfo().getPos(); +} + +s16 dComIfGs_getPlayerFieldLastStayAngleY() { + return g_dComIfG_gameInfo.info.getPlayer().getPlayerFieldLastStayInfo().getAngleY(); +} + +char* dComIfGs_getPlayerFieldLastStayName() { + return g_dComIfG_gameInfo.info.getPlayer().getPlayerFieldLastStayInfo().getName(); +} + +u8 dComIfGs_getPlayerFieldLastStayRegionNo() { + return g_dComIfG_gameInfo.info.getPlayer().getPlayerFieldLastStayInfo().getRegionNo(); +} + +bool dComIfGs_isPlayerFieldLastStayFieldDataExistFlag() { + return g_dComIfG_gameInfo.info.getPlayer().getPlayerFieldLastStayInfo().isFieldDataExistFlag(); +} + +void dComIfGs_offPlayerFieldLastStayFieldDataExistFlag() { + g_dComIfG_gameInfo.info.getPlayer().getPlayerFieldLastStayInfo().offFieldDataExistFlag(); +} + +void dComIfGs_onPlayerFieldLastStayFieldDataExistFlag() { + g_dComIfG_gameInfo.info.getPlayer().getPlayerFieldLastStayInfo().onFieldDataExistFlag(); +} + +BOOL dComIfGs_isRegionBit(int i_region) { + return g_dComIfG_gameInfo.info.getPlayer().getPlayerFieldLastStayInfo().isRegionBit(i_region); +} + +void dComIfGs_onRegionBit(int i_region) { + g_dComIfG_gameInfo.info.getPlayer().getPlayerFieldLastStayInfo().onRegionBit(i_region); +} + +void dComIfGs_setPlayerFieldLastStayInfo( + const char* i_stage, cXyz& i_pos, s16 i_angle, s8 i_point, u8 i_region) { + g_dComIfG_gameInfo.info.getPlayer().getPlayerFieldLastStayInfo().set( + i_stage, i_pos, i_angle, i_point, i_region); +} + +cXyz dComIfGs_getLastWarpMarkPlayerPos() { + return g_dComIfG_gameInfo.info.getPlayer().getPlayerLastMarkInfo().getPos(); +} + +s16 dComIfGs_getLastWarpMarkPlayerAngleY() { + return g_dComIfG_gameInfo.info.getPlayer().getPlayerLastMarkInfo().getAngleY(); +} + +const char* dComIfGs_getLastWarpMarkStageName() { + return g_dComIfG_gameInfo.info.getPlayer().getPlayerLastMarkInfo().getName(); +} + +u8 dComIfGs_getLastWarpMarkRoomNo() { + return g_dComIfG_gameInfo.info.getPlayer().getPlayerLastMarkInfo().getRoomNo(); +} + +s8 dComIfGs_getLastWarpAcceptStage() { + return g_dComIfG_gameInfo.info.getPlayer().getPlayerLastMarkInfo().getWarpAcceptStage(); +} + +void dComIfGs_setLastWarpAcceptStage(s8 param_0) { + g_dComIfG_gameInfo.info.getPlayer().getPlayerLastMarkInfo().setWarpAcceptStage(param_0); +} + +void dComIfGs_resetLastWarpAcceptStage() { + g_dComIfG_gameInfo.info.getPlayer().getPlayerLastMarkInfo().resetWarpAcceptStage(); +} + +void dComIfGs_setItem(int i_slotNo, u8 i_itemNo) { + g_dComIfG_gameInfo.info.getPlayer().getItem().setItem(i_slotNo, i_itemNo); +} + +u8 dComIfGs_getItem(int i_slotNo, bool i_checkCombo) { + return g_dComIfG_gameInfo.info.getPlayer().getItem().getItem(i_slotNo, i_checkCombo); +} + +void dComIfGs_setLineUpItem() { + g_dComIfG_gameInfo.info.getPlayer().getItem().setLineUpItem(); +} + +u8 dComIfGs_getLineUpItem(int i_slotNo) { + return g_dComIfG_gameInfo.info.getPlayer().getItem().getLineUpItem(i_slotNo); +} + +void dComIfGs_setBottleItemIn(u8 curItem, u8 newItem) { + g_dComIfG_gameInfo.info.getPlayer().getItem().setBottleItemIn(curItem, newItem); +} + +void dComIfGs_setEmptyBottleItemIn(u8 i_itemNo) { + g_dComIfG_gameInfo.info.getPlayer().getItem().setEmptyBottleItemIn(i_itemNo); +} + +void dComIfGs_setEmptyBottle() { + g_dComIfG_gameInfo.info.getPlayer().getItem().setEmptyBottle(); +} + +void dComIfGs_setEmptyBottle(u8 i_itemNo) { + g_dComIfG_gameInfo.info.getPlayer().getItem().setEmptyBottle(i_itemNo); +} + +void dComIfGs_setEquipBottleItemIn(u8 i_curItem, u8 i_newItem) { + g_dComIfG_gameInfo.info.getPlayer().getItem().setEquipBottleItemIn(i_curItem, i_newItem); +} + +void dComIfGs_setEquipBottleItemEmpty(u8 i_curItem) { + g_dComIfG_gameInfo.info.getPlayer().getItem().setEquipBottleItemEmpty(i_curItem); +} + +u8 dComIfGs_checkBottle(u8 i_itemNo) { + return g_dComIfG_gameInfo.info.getPlayer().getItem().checkBottle(i_itemNo); +} + +u8 dComIfGs_checkInsectBottle() { + return g_dComIfG_gameInfo.info.getPlayer().getItem().checkInsectBottle(); +} + +u8 dComIfGs_checkEmptyBottle() { + return g_dComIfG_gameInfo.info.getPlayer().getItem().checkEmptyBottle(); +} + +void dComIfGs_setEmptyBombBagItemIn(u8 i_newBomb, bool i_setNum) { + g_dComIfG_gameInfo.info.getPlayer().getItem().setEmptyBombBagItemIn(i_newBomb, i_setNum); +} + +void dComIfGs_setEmptyBombBagItemIn(u8 i_newBomb, u8 i_bombNum, bool i_setNum) { + g_dComIfG_gameInfo.info.getPlayer().getItem().setEmptyBombBagItemIn( + i_newBomb, i_bombNum, i_setNum); +} + +void dComIfGs_setEmptyBombBag() { + g_dComIfG_gameInfo.info.getPlayer().getItem().setEmptyBombBag(); +} + +void dComIfGs_setEmptyBombBag(u8 i_newBomb, u8 i_bombNum) { + g_dComIfG_gameInfo.info.getPlayer().getItem().setEmptyBombBag(i_newBomb, i_bombNum); +} + +u8 dComIfGs_checkBombBag(u8 i_itemNo) { + return g_dComIfG_gameInfo.info.getPlayer().getItem().checkBombBag(i_itemNo); +} + +void dComIfGs_setWarashibeItem(u8 i_itemNo) { + g_dComIfG_gameInfo.info.getPlayer().getItem().setWarashibeItem(i_itemNo); +} + +void dComIfGs_setRodTypeLevelUp() { + g_dComIfG_gameInfo.info.getPlayer().getItem().setRodTypeLevelUp(); +} + +void dComIfGs_setBaitItem(u8 i_item) { + g_dComIfG_gameInfo.info.getPlayer().getItem().setBaitItem(i_item); +} + +void dComIfGs_onItemFirstBit(u8 i_itemNo) { + g_dComIfG_gameInfo.info.getPlayer().getGetItem().onFirstBit(i_itemNo); +} + +void dComIfGs_offItemFirstBit(u8 i_itemNo) { + g_dComIfG_gameInfo.info.getPlayer().getGetItem().offFirstBit(i_itemNo); +} + +int dComIfGs_isItemFirstBit(u8 i_no) { + return g_dComIfG_gameInfo.info.getPlayer().getGetItem().isFirstBit(i_no); +} + +u8 dComIfGs_getArrowNum() { + return g_dComIfG_gameInfo.info.getPlayer().getItemRecord().getArrowNum(); +} + +void dComIfGs_setArrowNum(u8 i_arrowNum) { + g_dComIfG_gameInfo.info.getPlayer().getItemRecord().setArrowNum(i_arrowNum); +} + +u8 dComIfGs_getPachinkoNum() { + return g_dComIfG_gameInfo.info.getPlayer().getItemRecord().getPachinkoNum(); +} + +void dComIfGs_setPachinkoNum(u8 i_num) { + g_dComIfG_gameInfo.info.getPlayer().getItemRecord().setPachinkoNum(i_num); +} + +u8 dComIfGs_getPachinkoMax() { + return 50; +} + +void dComIfGs_setBombNum(u8 i_num) { + g_dComIfG_gameInfo.info.getPlayer().getItemRecord().setBombNum(0, i_num); +} + +void dComIfGs_setBombNum(u8 i_bagIdx, u8 i_bombNum) { + g_dComIfG_gameInfo.info.getPlayer().getItemRecord().setBombNum(i_bagIdx, i_bombNum); +} + +u8 dComIfGs_getBombNum(u8 i_bagIdx) { + return g_dComIfG_gameInfo.info.getPlayer().getItemRecord().getBombNum(i_bagIdx); +} + +void dComIfGs_setBottleNum(u8 i_bottleIdx, u8 i_bottleNum) { + g_dComIfG_gameInfo.info.getPlayer().getItemRecord().setBottleNum(i_bottleIdx, i_bottleNum); +} + +void dComIfGs_addBottleNum(u8 i_bottleIdx, s16 i_num) { + g_dComIfG_gameInfo.info.getPlayer().getItemRecord().addBottleNum(i_bottleIdx, i_num); +} + +u8 dComIfGs_getBottleNum(u8 i_bottleIdx) { + return g_dComIfG_gameInfo.info.getPlayer().getItemRecord().getBottleNum(i_bottleIdx); +} + +u8 dComIfGs_getArrowMax() { + return g_dComIfG_gameInfo.info.getPlayer().getItemMax().getArrowNum(); +} + +void dComIfGs_setArrowMax(u8 i_arrowMax) { + g_dComIfG_gameInfo.info.getPlayer().getItemMax().setArrowNum(i_arrowMax); +} + +void dComIfGs_setBombMax(u8 i_max) { + g_dComIfG_gameInfo.info.getPlayer().getItemMax().setBombNum(0, i_max); +} + +void dComIfGs_setBombMax(u8 i_type, u8 i_max) { + g_dComIfG_gameInfo.info.getPlayer().getItemMax().setBombNum(i_type, i_max); +} + +u8 dComIfGs_getBombMax() { + return g_dComIfG_gameInfo.info.getPlayer().getItemMax().getBombNum(0); +} + +u8 dComIfGs_getBombMax(u8 i_bombType) { + return g_dComIfG_gameInfo.info.getPlayer().getItemMax().getBombNum(i_bombType); +} + +void dComIfGs_setPohSpiritNum(u8 i_num) { + g_dComIfG_gameInfo.info.getPlayer().getCollect().setPohNum(i_num); +} + +u8 dComIfGs_getPohSpiritNum() { + return g_dComIfG_gameInfo.info.getPlayer().getCollect().getPohNum(); +} + +void dComIfGs_addPohSpiritNum() { + g_dComIfG_gameInfo.info.getPlayer().getCollect().addPohNum(); +} + +BOOL dComIfGs_isCollectClothes(u8 i_clothesNo) { + return g_dComIfG_gameInfo.info.getPlayer().getCollect().isCollect( + COLLECT_CLOTHING, i_clothesNo); +} + +void dComIfGs_setCollectClothes(u8 i_clothesNo) { + g_dComIfG_gameInfo.info.getPlayer().getCollect().setCollect(COLLECT_CLOTHING, i_clothesNo); +} + +void dComIfGs_setCollectSword(u8 i_swordNo) { + g_dComIfG_gameInfo.info.getPlayer().getCollect().setCollect(COLLECT_SWORD, i_swordNo); +} + +void dComIfGs_setCollectShield(u8 i_shieldNo) { + g_dComIfG_gameInfo.info.getPlayer().getCollect().setCollect(COLLECT_SHIELD, i_shieldNo); +} + +BOOL dComIfGs_isCollectClothing(u8 i_clothesNo) { + return g_dComIfG_gameInfo.info.getPlayer().getCollect().isCollect( + COLLECT_CLOTHING, i_clothesNo); +} + +void dComIfGs_offCollectClothes(u8 i_clothesNo) { + g_dComIfG_gameInfo.info.getPlayer().getCollect().offCollect(COLLECT_CLOTHING, i_clothesNo); +} + +BOOL dComIfGs_isCollectSword(u8 i_swordNo) { + return g_dComIfG_gameInfo.info.getPlayer().getCollect().isCollect(COLLECT_SWORD, i_swordNo); +} + +void dComIfGs_offCollectSword(u8 i_swordNo) { + g_dComIfG_gameInfo.info.getPlayer().getCollect().offCollect(COLLECT_SWORD, i_swordNo); +} + +BOOL dComIfGs_isCollectShield(u8 i_item) { + return g_dComIfG_gameInfo.info.getPlayer().getCollect().isCollect(COLLECT_SHIELD, i_item); +} + +void dComIfGs_offCollectShield(u8 i_shieldNo) { + g_dComIfG_gameInfo.info.getPlayer().getCollect().offCollect(COLLECT_SHIELD, i_shieldNo); +} + +void dComIfGs_onCollectCrystal(u8 i_item) { + g_dComIfG_gameInfo.info.getPlayer().getCollect().onCollectCrystal(i_item); +} + +void dComIfGs_offCollectCrystal(u8 i_item) { + g_dComIfG_gameInfo.info.getPlayer().getCollect().offCollectCrystal(i_item); +} + +bool dComIfGs_isCollectCrystal(u8 i_item) { + return g_dComIfG_gameInfo.info.getPlayer().getCollect().isCollectCrystal(i_item); +} + +void dComIfGs_onCollectMirror(u8 i_item) { + g_dComIfG_gameInfo.info.getPlayer().getCollect().onCollectMirror(i_item); +} + +void dComIfGs_offCollectMirror(u8 i_item) { + g_dComIfG_gameInfo.info.getPlayer().getCollect().offCollectMirror(i_item); +} + +bool dComIfGs_isCollectMirror(u8 i_item) { + return g_dComIfG_gameInfo.info.getPlayer().getCollect().isCollectMirror(i_item); +} + +void dComIfGs_setLightDropNum(u8 i_level, u8 i_num) { + g_dComIfG_gameInfo.info.getPlayer().getLightDrop().setLightDropNum(i_level, i_num); +} + +u8 dComIfGs_getLightDropNum(u8 i_nowLevel) { + return g_dComIfG_gameInfo.info.getPlayer().getLightDrop().getLightDropNum(i_nowLevel); +} + +void dComIfGs_onLightDropGetFlag(u8 i_nowLevel) { + g_dComIfG_gameInfo.info.getPlayer().getLightDrop().onLightDropGetFlag(i_nowLevel); +} + +void dComIfGs_offLightDropGetFlag(u8 i_level) { + g_dComIfG_gameInfo.info.getPlayer().getLightDrop().offLightDropGetFlag(i_level); +} + +BOOL dComIfGs_isLightDropGetFlag(u8 i_nowLevel) { + return g_dComIfG_gameInfo.info.getPlayer().getLightDrop().isLightDropGetFlag(i_nowLevel); +} + +void dComIfGs_onLetterGetFlag(int i_no) { + g_dComIfG_gameInfo.info.getPlayer().getLetterInfo().onLetterGetFlag(i_no); +} + +BOOL dComIfGs_isLetterGetFlag(int i_no) { + return g_dComIfG_gameInfo.info.getPlayer().getLetterInfo().isLetterGetFlag(i_no); +} + +void dComIfGs_onLetterReadFlag(int i_no) { + g_dComIfG_gameInfo.info.getPlayer().getLetterInfo().onLetterReadFlag(i_no); +} + +int dComIfGs_isLetterReadFlag(int i_no) { + return g_dComIfG_gameInfo.info.getPlayer().getLetterInfo().isLetterReadFlag(i_no); +} + +u8 dComIfGs_getGetNumber(int i_no) { + return g_dComIfG_gameInfo.info.getPlayer().getLetterInfo().getGetNumber(i_no); +} + +void dComIfGs_setGetNumber(int i_no, u8 i_value) { + g_dComIfG_gameInfo.info.getPlayer().getLetterInfo().setGetNumber(i_no, i_value); +} + +void dComIfGs_addFishNum(u8 param_0) { + g_dComIfG_gameInfo.info.getPlayer().getFishingInfo().addFishCount(param_0); +} + +u16 dComIfGs_getFishNum(u8 param_0) { + return g_dComIfG_gameInfo.info.getPlayer().getFishingInfo().getFishCount(param_0); +} + +u8 dComIfGs_getFishSize(u8 param_0) { + return g_dComIfG_gameInfo.info.getPlayer().getFishingInfo().getMaxSize(param_0); +} + +void dComIfGs_setFishSize(u8 param_0, u8 param_1) { + g_dComIfG_gameInfo.info.getPlayer().getFishingInfo().setMaxSize(param_0, param_1); +} + +OSTime dComIfGs_getTotalTime() { + return g_dComIfG_gameInfo.info.getPlayer().getPlayerInfo().getTotalTime(); +} + +void dComIfGs_addDeathCount() { + g_dComIfG_gameInfo.info.getPlayer().getPlayerInfo().addDeathCount(); +} + +u16 dComIfGs_getDeathCount() { + return g_dComIfG_gameInfo.info.getPlayer().getPlayerInfo().getDeathCount(); +} + +TEXT_SPAN dComIfGs_getPlayerName() { + return g_dComIfG_gameInfo.info.getPlayer().getPlayerInfo().getPlayerName(); +} + +void dComIfGs_setPlayerName(const char* i_name) { + g_dComIfG_gameInfo.info.getPlayer().getPlayerInfo().setPlayerName(i_name); +} + +TEXT_SPAN dComIfGs_getHorseName() { + return g_dComIfG_gameInfo.info.getPlayer().getPlayerInfo().getHorseName(); +} + +void dComIfGs_setHorseName(const char* i_name) { + g_dComIfG_gameInfo.info.getPlayer().getPlayerInfo().setHorseName(i_name); +} + +u8 dComIfGs_getClearCount() { + return g_dComIfG_gameInfo.info.getPlayer().getPlayerInfo().getClearCount(); +} + +// Ruby inline names are from TWW debug. +u8 dComIfGs_getOptRuby() { + return g_dComIfG_gameInfo.info.getPlayer().getConfig().getRuby(); +} + +void dComIfGs_setOptRuby(u8 i_ruby) { + g_dComIfG_gameInfo.info.getPlayer().getConfig().setRuby(i_ruby); +} + +u8 dComIfGs_getOptAttentionType() { + return g_dComIfG_gameInfo.info.getPlayer().getConfig().getAttentionType(); +} + +void dComIfGs_setOptAttentionType(u8 i_attentionType) { + g_dComIfG_gameInfo.info.getPlayer().getConfig().setAttentionType(i_attentionType); +} + +void dComIfGs_setOptCalibrateDist(u16 i_calibrateDist) { + g_dComIfG_gameInfo.info.getPlayer().getConfig().setCalibrateDist(i_calibrateDist); +} + +void dComIfGs_setOptCalValue(s8 i_calValue) { + g_dComIfG_gameInfo.info.getPlayer().getConfig().setCalValue(i_calValue); +} + +u8 dComIfGs_getOptCameraControl() { + return g_dComIfG_gameInfo.info.getPlayer().getConfig().getCameraControl(); +} + +void dComIfGs_setOptCameraControl(u8 i_cameraControl) { + g_dComIfG_gameInfo.info.getPlayer().getConfig().setCameraControl(i_cameraControl); +} + +u8 dComIfGs_getOptPointer() { + return g_dComIfG_gameInfo.info.getPlayer().getConfig().getPointer(); +} + +void dComIfGs_setOptPointer(u8 i_pointer) { + g_dComIfG_gameInfo.info.getPlayer().getConfig().setPointer(i_pointer); +} + +u8 dComIfGs_checkOptVibration() { + return g_dComIfG_gameInfo.info.getPlayer().getConfig().checkVibration(); +} + +u8 dComIfGs_getOptSound() { + return g_dComIfG_gameInfo.info.getPlayer().getConfig().getSound(); +} + +void dComIfGs_setOptSound(u8 i_mode) { + g_dComIfG_gameInfo.info.getPlayer().getConfig().setSound(i_mode); +} + +u8 dComIfGs_getOptVibration() { + return g_dComIfG_gameInfo.info.getPlayer().getConfig().getVibration(); +} + +void dComIfGs_setOptVibration(u8 i_status) { + g_dComIfG_gameInfo.info.getPlayer().getConfig().setVibration(i_status); +} + +u8 dComIfGs_getPalLanguage() { + return g_dComIfG_gameInfo.info.getPlayer().getConfig().getPalLanguage(); +} + +BOOL dComIfGs_isSaveTbox(int i_stageNo, int i_no) { + return g_dComIfG_gameInfo.info.getSavedata().getSave(i_stageNo).getBit().isTbox(i_no); +} + +void dComIfGs_onSaveSwitch(int i_stageNo, int i_no) { + g_dComIfG_gameInfo.info.getSavedata().getSave(i_stageNo).getBit().onSwitch(i_no); +} + +void dComIfGs_offSaveSwitch(int i_stageNo, int i_no) { + g_dComIfG_gameInfo.info.getSavedata().getSave(i_stageNo).getBit().offSwitch(i_no); +} + +BOOL dComIfGs_isSaveSwitch(int i_stageNo, int i_no) { + return g_dComIfG_gameInfo.info.getSavedata().getSave(i_stageNo).getBit().isSwitch(i_no); +} + +void dComIfGs_onSaveVisitedRoom(int param_0, int i_roomNo) { + return g_dComIfG_gameInfo.info.getSavedata().getSave2(param_0)->onVisitedRoom(i_roomNo); +} + +void dComIfGs_offSaveVisitedRoom(int param_0, int i_roomNo) { + return g_dComIfG_gameInfo.info.getSavedata().getSave2(param_0)->offVisitedRoom(i_roomNo); +} + +BOOL dComIfGs_isSaveVisitedRoom(int param_0, int i_roomNo) { + return g_dComIfG_gameInfo.info.getSavedata().getSave2(param_0)->isVisitedRoom(i_roomNo); +} + +void* dComIfGs_getPEventBit() { + return g_dComIfG_gameInfo.info.getEvent().getPEventBit(); +} + +void dComIfGs_onEventBit(const u16 i_flag) { + g_dComIfG_gameInfo.info.getEvent().onEventBit(i_flag); +} + +void dComIfGs_offEventBit(const u16 i_flag) { + g_dComIfG_gameInfo.info.getEvent().offEventBit(i_flag); +} + +BOOL dComIfGs_isEventBit(const u16 i_flag) { + return g_dComIfG_gameInfo.info.getEvent().isEventBit(i_flag); +} + +void dComIfGs_setEventReg(u16 reg, u8 value) { + g_dComIfG_gameInfo.info.getEvent().setEventReg(reg, value); +} + +u8 dComIfGs_getEventReg(u16 reg) { + return g_dComIfG_gameInfo.info.getEvent().getEventReg(reg); +} + +int dComIfGs_getHookGameTime() { + return g_dComIfG_gameInfo.info.getMiniGame().getHookGameTime(); +} + +void dComIfGs_setHookGameTime(u32 i_time) { + g_dComIfG_gameInfo.info.getMiniGame().setHookGameTime(i_time); +} + +u32 dComIfGs_getBalloonScore() { + return g_dComIfG_gameInfo.info.getMiniGame().getBalloonScore(); +} + +void dComIfGs_setBalloonScore(u32 i_score) { + g_dComIfG_gameInfo.info.getMiniGame().setBalloonScore(i_score); +} + +int dComIfGs_getRaceGameTime() { + return g_dComIfG_gameInfo.info.getMiniGame().getRaceGameTime(); +} + +void dComIfGs_setRaceGameTime(int i_time) { + g_dComIfG_gameInfo.info.getMiniGame().setRaceGameTime(i_time); +} + +u8 dComIfGs_getKeyNum() { + return g_dComIfG_gameInfo.info.getMemory().getBit().getKeyNum(); +} + +void dComIfGs_setKeyNum(u8 i_keyNum) { + g_dComIfG_gameInfo.info.getMemory().getBit().setKeyNum(i_keyNum); +} + +void dComIfGs_onDungeonItemMap() { + g_dComIfG_gameInfo.info.getMemory().getBit().onDungeonItemMap(); +} + +void dComIfGs_offDungeonItemMap() { + g_dComIfG_gameInfo.info.getMemory().getBit().offDungeonItemMap(); +} + +s32 dComIfGs_isDungeonItemMap() { + return g_dComIfG_gameInfo.info.getMemory().getBit().isDungeonItemMap(); +} + +void dComIfGs_onDungeonItemCompass() { + g_dComIfG_gameInfo.info.getMemory().getBit().onDungeonItemCompass(); +} + +void dComIfGs_offDungeonItemCompass() { + g_dComIfG_gameInfo.info.getMemory().getBit().offDungeonItemCompass(); +} + +s32 dComIfGs_isDungeonItemCompass() { + return g_dComIfG_gameInfo.info.getMemory().getBit().isDungeonItemCompass(); +} + +void dComIfGs_onDungeonItemBossKey() { + g_dComIfG_gameInfo.info.getMemory().getBit().onDungeonItemBossKey(); +} + +void dComIfGs_offDungeonItemBossKey() { + g_dComIfG_gameInfo.info.getMemory().getBit().offDungeonItemBossKey(); +} + +s32 dComIfGs_isDungeonItemBossKey() { + return g_dComIfG_gameInfo.info.getMemory().getBit().isDungeonItemBossKey(); +} + +void dComIfGs_onStageBossEnemy() { + g_dComIfG_gameInfo.info.getMemory().getBit().onStageBossEnemy(); +} + +void dComIfGs_offStageBossEnemy() { + g_dComIfG_gameInfo.info.getMemory().getBit().offStageBossEnemy(); +} + +s32 dComIfGs_isStageBossEnemy() { + return g_dComIfG_gameInfo.info.getMemory().getBit().isStageBossEnemy(); +} + +void dComIfGs_onStageLife() { + g_dComIfG_gameInfo.info.getMemory().getBit().onStageLife(); +} + +void dComIfGs_offStageLife() { + g_dComIfG_gameInfo.info.getMemory().getBit().offStageLife(); +} + +s32 dComIfGs_isStageLife() { + return g_dComIfG_gameInfo.info.getMemory().getBit().isStageLife(); +} + +void dComIfGs_onStageBossDemo() { + g_dComIfG_gameInfo.info.getMemory().getBit().onStageBossDemo(); +} + +void dComIfGs_offStageBossDemo() { + g_dComIfG_gameInfo.info.getMemory().getBit().offStageBossDemo(); +} + +s32 dComIfGs_isStageBossDemo() { + return g_dComIfG_gameInfo.info.getMemory().getBit().isStageBossDemo(); +} + +void dComIfGs_onDungeonItemWarp() { + g_dComIfG_gameInfo.info.getMemory().getBit().onDungeonItemWarp(); +} + +void dComIfGs_offDungeonItemWarp() { + g_dComIfG_gameInfo.info.getMemory().getBit().offDungeonItemWarp(); +} + +s32 dComIfGs_isDungeonItemWarp() { + return g_dComIfG_gameInfo.info.getMemory().getBit().isDungeonItemWarp(); +} + +void dComIfGs_onStageMiddleBoss() { + g_dComIfG_gameInfo.info.getMemory().getBit().onStageBossEnemy2(); +} + +void dComIfGs_offStageMiddleBoss() { + g_dComIfG_gameInfo.info.getMemory().getBit().offStageBossEnemy2(); +} + +BOOL dComIfGs_isStageMiddleBoss() { + return g_dComIfG_gameInfo.info.getMemory().getBit().isStageBossEnemy2(); +} + +void dComIfGs_onTbox(int i_no) { + g_dComIfG_gameInfo.info.getMemory().getBit().onTbox(i_no); +} + +void dComIfGs_offTbox(int i_no) { + g_dComIfG_gameInfo.info.getMemory().getBit().offTbox(i_no); +} + +BOOL dComIfGs_isTbox(int i_no) { + return g_dComIfG_gameInfo.info.getMemory().getBit().isTbox(i_no); +} + +void dComIfGs_onSaveSwitch(int i_no) { + g_dComIfG_gameInfo.info.getMemory().getBit().onSwitch(i_no); +} + +void dComIfGs_offSaveSwitch(int i_no) { + g_dComIfG_gameInfo.info.getMemory().getBit().offSwitch(i_no); +} + +BOOL dComIfGs_isSaveSwitch(int i_no) { + return g_dComIfG_gameInfo.info.getMemory().getBit().isSwitch(i_no); +} + +BOOL dComIfGs_isSaveItem(int i_no) { + return g_dComIfG_gameInfo.info.getMemory().getBit().isItem(i_no); +} + +void dComIfGs_onSaveDunSwitch(int i_swNo) { + g_dComIfG_gameInfo.info.getDan().onSwitch(i_swNo); +} + +void dComIfGs_offSaveDunSwitch(int i_swNo) { + g_dComIfG_gameInfo.info.getDan().offSwitch(i_swNo); +} + +BOOL dComIfGs_isSaveDunSwitch(int i_no) { + return g_dComIfG_gameInfo.info.getDan().isSwitch(i_no); +} + +BOOL dComIfGs_isSaveDunItem(int i_no) { + return g_dComIfG_gameInfo.info.getDan().isItem(i_no); +} + +void dComIfGs_resetDan() { + g_dComIfG_gameInfo.info.resetDan(); +} + +void dComIfGs_initDan(s8 i_stageNo) { + g_dComIfG_gameInfo.info.initDan(i_stageNo); +} + +void dComIfGs_clearRoomSwitch(int i_zoneNo) { + g_dComIfG_gameInfo.info.getZone(i_zoneNo).getBit().clearRoomSwitch(); +} + +void dComIfGs_clearRoomItem(int i_zoneNo) { + g_dComIfG_gameInfo.info.getZone(i_zoneNo).getBit().clearRoomItem(); +} + +void dComIfGs_onSvZoneSwitch(int i_zoneNo, int i_swBit) { + g_dComIfG_gameInfo.info.getZone(i_zoneNo).getBit().onSwitch(i_swBit); +} + +void dComIfGs_offSvZoneSwitch(int i_zoneNo, int i_swBit) { + g_dComIfG_gameInfo.info.getZone(i_zoneNo).getBit().offSwitch(i_swBit); +} + +BOOL dComIfGs_isSvZoneSwitch(int i_zoneNo, int i_swBit) { + return g_dComIfG_gameInfo.info.getZone(i_zoneNo).getBit().isSwitch(i_swBit); +} + +void dComIfGs_onSvOneZoneSwitch(int i_zoneNo, int i_swBit) { + g_dComIfG_gameInfo.info.getZone(i_zoneNo).getBit().onOneSwitch(i_swBit); +} + +void dComIfGs_offSvOneZoneSwitch(int i_zoneNo, int i_swBit) { + g_dComIfG_gameInfo.info.getZone(i_zoneNo).getBit().offOneSwitch(i_swBit); +} + +BOOL dComIfGs_isSvOneZoneSwitch(int i_zoneNo, int i_swBit) { + return g_dComIfG_gameInfo.info.getZone(i_zoneNo).getBit().isOneSwitch(i_swBit); +} + +void dComIfGs_onSvZoneItem(int i_zoneNo, int i_swBit) { + g_dComIfG_gameInfo.info.getZone(i_zoneNo).getBit().onItem(i_swBit); +} + +void dComIfGs_offSvZoneItem(int i_zoneNo, int i_swBit) { + g_dComIfG_gameInfo.info.getZone(i_zoneNo).getBit().offItem(i_swBit); +} + +BOOL dComIfGs_isSvZoneItem(int i_zoneNo, int i_swBit) { + return g_dComIfG_gameInfo.info.getZone(i_zoneNo).getBit().isItem(i_swBit); +} + +void dComIfGs_onSvOneZoneItem(int i_zoneNo, int i_swBit) { + g_dComIfG_gameInfo.info.getZone(i_zoneNo).getBit().onOneItem(i_swBit); +} + +void dComIfGs_offSvOneZoneItem(int i_zoneNo, int i_swBit) { + g_dComIfG_gameInfo.info.getZone(i_zoneNo).getBit().offOneItem(i_swBit); +} + +BOOL dComIfGs_isSvOneZoneItem(int i_zoneNo, int i_swBit) { + return g_dComIfG_gameInfo.info.getZone(i_zoneNo).getBit().isOneItem(i_swBit); +} + +void dComIfGs_removeZone(int i_zoneNo) { + g_dComIfG_gameInfo.info.removeZone(i_zoneNo); +} + +s8 dComIfGs_getRestartRoomNo() { + return g_dComIfG_gameInfo.info.getRestart().getRoomNo(); +} + +s16 dComIfGs_getStartPoint() { + return g_dComIfG_gameInfo.info.getRestart().getStartPoint(); +} + +void dComIfGs_setStartPoint(s16 i_point) { + g_dComIfG_gameInfo.info.getRestart().setStartPoint(i_point); +} + +s16 dComIfGs_getRestartRoomAngleY() { + return g_dComIfG_gameInfo.info.getRestart().getRoomAngleY(); +} + +const cXyz& dComIfGs_getRestartRoomPos() { + return g_dComIfG_gameInfo.info.getRestart().getRoomPos(); +} + +u32 dComIfGs_getRestartRoomParam() { + return g_dComIfG_gameInfo.info.getRestart().getRoomParam(); +} + +void dComIfGs_setRestartRoomParam(u32 i_param) { + g_dComIfG_gameInfo.info.getRestart().setRoomParam(i_param); +} + +f32 dComIfGs_getLastSceneSpeedF() { + return g_dComIfG_gameInfo.info.getRestart().getLastSpeedF(); +} + +u32 dComIfGs_getLastSceneMode() { + return g_dComIfG_gameInfo.info.getRestart().getLastMode(); +} + +s16 dComIfGs_getLastSceneAngleY() { + return g_dComIfG_gameInfo.info.getRestart().getLastAngleY(); +} + +void dComIfGs_setRestartRoom(const cXyz& i_position, s16 i_angle, s8 i_roomNo) { + g_dComIfG_gameInfo.info.getRestart().setRoom(i_position, i_angle, i_roomNo); +} + +void dComIfGs_onTmpBit(const u16 i_flag) { + g_dComIfG_gameInfo.info.getTmp().onEventBit(i_flag); +} + +void dComIfGs_offTmpBit(const u16 i_flag) { + g_dComIfG_gameInfo.info.getTmp().offEventBit(i_flag); +} + +BOOL dComIfGs_isTmpBit(const u16 i_flag) { + return g_dComIfG_gameInfo.info.getTmp().isEventBit(i_flag); +} + +void dComIfGs_setTmpReg(u16 i_reg, u8 i_no) { + g_dComIfG_gameInfo.info.getTmp().setEventReg(i_reg, i_no); +} + +u8 dComIfGs_getTmpReg(const u16 i_reg) { + return g_dComIfG_gameInfo.info.getTmp().getEventReg(i_reg); +} + +dSv_turnRestart_c& dComIfGs_getTurnRestart() { + return g_dComIfG_gameInfo.info.getTurnRestart(); +} + +const cXyz& dComIfGs_getTurnRestartPos() { + return g_dComIfG_gameInfo.info.getTurnRestart().getPos(); +} + +u32 dComIfGs_getTurnRestartParam() { + return g_dComIfG_gameInfo.info.getTurnRestart().getParam(); +} + +s16 dComIfGs_getTurnRestartAngleY() { + return g_dComIfG_gameInfo.info.getTurnRestart().getAngleY(); +} + +s8 dComIfGs_getTurnRestartRoomNo() { + return g_dComIfG_gameInfo.info.getTurnRestart().getRoomNo(); +} + +void dComIfGs_setTurnRestart(const cXyz& i_position, s16 i_angle, s8 param_2, u32 i_param) { + g_dComIfG_gameInfo.info.getTurnRestart().set(i_position, i_angle, param_2, i_param); +} + +u8 dComIfGs_getDataNum() { + return g_dComIfG_gameInfo.info.getDataNum(); +} + +void dComIfGs_setDataNum(u8 i_num) { + return g_dComIfG_gameInfo.info.setDataNum(i_num); +} + +u8 dComIfGs_getNewFile() { + return g_dComIfG_gameInfo.info.getNewFile(); +} + +void dComIfGs_setNewFile(u8 i_fileNo) { + return g_dComIfG_gameInfo.info.setNewFile(i_fileNo); +} + +u8 dComIfGs_getNoFile() { + return g_dComIfG_gameInfo.info.getNoFile(); +} + +void dComIfGs_setNoFile(u8 i_file) { + g_dComIfG_gameInfo.info.setNoFile(i_file); +} + +s64 dComIfGs_getSaveStartTime() { + return g_dComIfG_gameInfo.info.getStartTime(); +} + +void dComIfGs_setSaveStartTime(s64 i_time) { + g_dComIfG_gameInfo.info.setStartTime(i_time); +} + +s64 dComIfGs_getSaveTotalTime() { + return g_dComIfG_gameInfo.info.getSaveTotalTime(); +} + +void dComIfGs_setSaveTotalTime(s64 i_time) { + g_dComIfG_gameInfo.info.setSaveTotalTime(i_time); +} + +void dComIfGs_init() { + g_dComIfG_gameInfo.info.init(); +} + +void dComIfGs_getSave(int i_stageNo) { + g_dComIfG_gameInfo.info.getSave(i_stageNo); +} + +void dComIfGs_putSave(int i_stageNo) { + g_dComIfG_gameInfo.info.putSave(i_stageNo); +} + +void dComIfGs_initZone() { + g_dComIfG_gameInfo.info.initZone(); +} + +int dComIfGs_createZone(int roomNo) { + return g_dComIfG_gameInfo.info.createZone(roomNo); +} + +void dComIfGs_onSwitch(int i_no, int i_roomNo) { + g_dComIfG_gameInfo.info.onSwitch(i_no, i_roomNo); +} + +void dComIfGs_offSwitch(int i_no, int i_roomNo) { + g_dComIfG_gameInfo.info.offSwitch(i_no, i_roomNo); +} + +BOOL dComIfGs_isSwitch(int i_no, int i_roomNo) { + return g_dComIfG_gameInfo.info.isSwitch(i_no, i_roomNo); +} + +void dComIfGs_revSwitch(int i_no, int i_roomNo) { + g_dComIfG_gameInfo.info.revSwitch(i_no, i_roomNo); +} + +void dComIfGs_onItem(int i_bitNo, int i_roomNo) { + g_dComIfG_gameInfo.info.onItem(i_bitNo, i_roomNo); +} + +bool dComIfGs_isItem(int i_bitNo, int i_roomNo) { + return g_dComIfG_gameInfo.info.isItem(i_bitNo, i_roomNo); +} + +void dComIfGs_onActor(int i_bitNo, int i_roomNo) { + g_dComIfG_gameInfo.info.onActor(i_bitNo, i_roomNo); +} + +void dComIfGs_offActor(int i_no, int i_roomNo) { + g_dComIfG_gameInfo.info.offActor(i_no, i_roomNo); +} + +BOOL dComIfGs_isActor(int i_no, int i_roomNo) { + return g_dComIfG_gameInfo.info.isActor(i_no, i_roomNo); +} + +void dComIfGs_setMemoryToCard(u8* i_saveData, int i_dataNum) { + g_dComIfG_gameInfo.info.memory_to_card((char*)i_saveData, i_dataNum); +} + +void dComIfGs_setCardToMemory(u8* card_ptr, int dataNum) { + g_dComIfG_gameInfo.info.card_to_memory((char*)card_ptr, dataNum); +} + +void dComIfGs_setInitDataToCard(u8* i_saveData, int i_dataNum) { + g_dComIfG_gameInfo.info.initdata_to_card((char*)i_saveData, i_dataNum); +} + +u8 dComIfGs_getWolfAbility(int i_idx) { + return g_dComIfG_gameInfo.play.getWolfAbility(i_idx); +} + +s8 dComIfGs_Grass_hide_Check() { + return g_dComIfG_gameInfo.field_0x1ddfc; +} + +dStage_startStage_c* dComIfGp_getStartStage() { + return g_dComIfG_gameInfo.play.getStartStage(); +} + +void dComIfGp_setStartStage(dStage_startStage_c* p_startStage) { + g_dComIfG_gameInfo.play.setStartStage(p_startStage); +} + +const char* dComIfGp_getStartStageName() { + return g_dComIfG_gameInfo.play.getStartStageName(); +} + +s16 dComIfGp_getStartStagePoint() { + return g_dComIfG_gameInfo.play.getStartStagePoint(); +} + +s8 dComIfGp_getStartStageRoomNo() { + return g_dComIfG_gameInfo.play.getStartStageRoomNo(); +} + +s8 dComIfGp_getStartStageLayer() { + return g_dComIfG_gameInfo.play.getStartStageLayer(); +} + +void dComIfGp_setStartStageLayer(s8 layer) { + g_dComIfG_gameInfo.play.setStartStageLayer(layer); +} + +s8 dComIfGp_getStartStageDarkArea() { + return g_dComIfG_gameInfo.play.getStartStageDarkArea(); +} + +void dComIfGp_setStartStageDarkArea(s8 darkArea) { + g_dComIfG_gameInfo.play.setStartStageDarkArea(darkArea); +} + +dStage_startStage_c* dComIfGp_getNextStartStage() { + return g_dComIfG_gameInfo.play.getNextStartStage(); +} + +const char* dComIfGp_getNextStageName() { + return g_dComIfG_gameInfo.play.getNextStageName(); +} + +s16 dComIfGp_getNextStagePoint() { + return g_dComIfG_gameInfo.play.getNextStagePoint(); +} + +s16 dComIfGp_getNextStageRoomNo() { + return g_dComIfG_gameInfo.play.getNextStageRoomNo(); +} + +s16 dComIfGp_getNextStageLayer() { + return g_dComIfG_gameInfo.play.getNextStageLayer(); +} + +BOOL dComIfGp_isEnableNextStage() { + return g_dComIfG_gameInfo.play.isEnableNextStage(); +} + +void dComIfGp_offEnableNextStage() { + g_dComIfG_gameInfo.play.offEnableNextStage(); +} + +s8 dComIfGp_getNextStageWipe() { + return g_dComIfG_gameInfo.play.getNextStageWipe(); +} + +u8 dComIfGp_getNextStageWipeSpeed() { + return g_dComIfG_gameInfo.play.getNextStageWipeSpeed(); +} + +dStage_stageDt_c* dComIfGp_getStage() { + return &g_dComIfG_gameInfo.play.getStage(); +} + +roomRead_class* dComIfGp_getStageRoom() { + return g_dComIfG_gameInfo.play.getStage().getRoom(); +} + +stage_palette_info_class* dComIfGp_getStagePaletteInfo() { + return g_dComIfG_gameInfo.play.getStage().getPaletteInfo(); +} + +stage_pselect_info_class* dComIfGp_getStagePselectInfo() { + return g_dComIfG_gameInfo.play.getStage().getPselectInfo(); +} + +stage_envr_info_class* dComIfGp_getStageEnvrInfo() { + return g_dComIfG_gameInfo.play.getStage().getEnvrInfo(); +} + +stage_vrboxcol_info_class* dComIfGp_getStageVrboxcolInfo() { + return g_dComIfG_gameInfo.play.getStage().getVrboxcolInfo(); +} + +stage_plight_info_class* dComIfGp_getStagePlightInfo() { + return g_dComIfG_gameInfo.play.getStage().getPlightInfo(); +} + +int dComIfGp_getStagePaletteNumInfo() { + return g_dComIfG_gameInfo.play.getStage().getPaletteNumInfo(); +} + +int dComIfGp_getStagePselectNumInfo() { + return g_dComIfG_gameInfo.play.getStage().getPselectNumInfo(); +} + +int dComIfGp_getStageEnvrNumInfo() { + return g_dComIfG_gameInfo.play.getStage().getEnvrNumInfo(); +} + +int dComIfGp_getStageVrboxcolNumInfo() { + return g_dComIfG_gameInfo.play.getStage().getVrboxcolNumInfo(); +} + +int dComIfGp_getStagePlightNumInfo() { + return g_dComIfG_gameInfo.play.getStage().getPlightNumInfo(); +} + +stage_stag_info_class* dComIfGp_getStageStagInfo() { + return g_dComIfG_gameInfo.play.getStage().getStagInfo(); +} + +stage_scls_info_dummy_class* dComIfGp_getStageSclsInfo() { + return g_dComIfG_gameInfo.play.getStage().getSclsInfo(); +} + +dStage_Multi_c* dComIfGp_getMulti() { + return g_dComIfG_gameInfo.play.getStage().getMulti(); +} + +void dComIfGp_setOldMulti() { + g_dComIfG_gameInfo.play.getStage().setOldMulti(); +} + +void dComIfGp_resetOldMulti() { + g_dComIfG_gameInfo.play.getStage().resetOldMulti(); +} + +s16 dComIfGp_getStageWorldRollAngleX() { + return g_dComIfG_gameInfo.play.getStage().getWorldRollAngleX(); +} + +s16 dComIfGp_getStageWorldRollDirAngleY() { + return g_dComIfG_gameInfo.play.getStage().getWorldRollDirAngleY(); +} + +int dComIfGp_roomControl_getStayNo() { + return dStage_roomControl_c::getStayNo(); +} + +BOOL dComIfGp_roomControl_getTimePass() { + return g_dComIfG_gameInfo.play.getRoomControl()->GetTimePass(); +} + +void dComIfGp_roomControl_setTimePass(int isPassing) { + g_dComIfG_gameInfo.play.getRoomControl()->SetTimePass(isPassing); +} + +dKy_tevstr_c* dComIfGp_roomControl_getTevStr(int i_roomNo) { + return g_dComIfG_gameInfo.play.getRoomControl()->getTevStr(i_roomNo); +} + +void dComIfGp_roomControl_setStatusFlag(int i_roomNo, u8 flag) { + return g_dComIfG_gameInfo.play.getRoomControl()->setStatusFlag(i_roomNo, flag); +} + +void dComIfGp_roomControl_onStatusFlag(int i_roomNo, u8 flag) { + return g_dComIfG_gameInfo.play.getRoomControl()->onStatusFlag(i_roomNo, flag); +} + +void dComIfGp_roomControl_offStatusFlag(int i_roomNo, u8 flag) { + return g_dComIfG_gameInfo.play.getRoomControl()->offStatusFlag(i_roomNo, flag); +} + +u8 dComIfGp_roomControl_checkStatusFlag(int i_roomNo, u8 flag) { + return g_dComIfG_gameInfo.play.getRoomControl()->checkStatusFlag(i_roomNo, flag); +} + +s32 dComIfGp_roomControl_getZoneNo(int i_roomNo) { + return g_dComIfG_gameInfo.play.getRoomControl()->getZoneNo(i_roomNo); +} + +void dComIfGp_roomControl_setZoneNo(int roomNo, int zoneNo) { + g_dComIfG_gameInfo.play.getRoomControl()->setZoneNo(roomNo, zoneNo); +} + +void dComIfGp_roomControl_init() { + g_dComIfG_gameInfo.play.getRoomControl()->init(); +} + +void dComIfGp_roomControl_initZone() { + g_dComIfG_gameInfo.play.getRoomControl()->initZone(); +} + +dStage_roomDt_c* dComIfGp_roomControl_getStatusRoomDt(int room_no) { + return g_dComIfG_gameInfo.play.getRoomControl()->getStatusRoomDt(room_no); +} + +void dComIfGp_roomControl_setStayNo(int stayNo) { + g_dComIfG_gameInfo.play.mRoomControl.setStayNo(stayNo); +} + +BOOL dComIfGp_roomControl_checkRoomDisp(int i_roomNo) { + return g_dComIfG_gameInfo.play.getRoomControl()->checkRoomDisp(i_roomNo); +} + +int dComIfGp_roomControl_loadRoom(int param_0, u8* param_1, bool param_2) { + return g_dComIfG_gameInfo.play.getRoomControl()->loadRoom(param_0, param_1, param_2); +} + +void dComIfGp_roomControl_zoneCountCheck(int i_roomNo) { + g_dComIfG_gameInfo.play.getRoomControl()->zoneCountCheck(i_roomNo); +} + +dEvt_control_c* dComIfGp_getEvent() { + return g_dComIfG_gameInfo.play.getEvent(); +} + +u16 dComIfGp_event_chkEventFlag(u16 i_flag) { + return g_dComIfG_gameInfo.play.getEvent()->chkEventFlag(i_flag); +} + +void dComIfGp_event_onEventFlag(u16 i_flag) { + g_dComIfG_gameInfo.play.getEvent()->onEventFlag(i_flag); +} + +void dComIfGp_event_onHindFlag(u16 i_flag) { + g_dComIfG_gameInfo.play.getEvent()->onHindFlag(i_flag); +} + +void dComIfGp_event_offHindFlag(u16 i_flag) { + g_dComIfG_gameInfo.play.getEvent()->offHindFlag(i_flag); +} + +u8 dComIfGp_event_getMode() { + return g_dComIfG_gameInfo.play.getEvent()->getMode(); +} + +BOOL dComIfGp_event_runCheck() { + return g_dComIfG_gameInfo.play.getEvent()->runCheck(); +} + +u16 dComIfGp_event_checkHind(u16 i_hindFlag) { + if (!dComIfGp_event_runCheck()) { + return false; + } + return g_dComIfG_gameInfo.play.getEvent()->checkHind(i_hindFlag); +} + +BOOL dComIfGp_event_chkTalkXY() { + return g_dComIfG_gameInfo.play.getEvent()->chkTalkXY(); +} + +u8 dComIfGp_event_getPreItemNo() { + return g_dComIfG_gameInfo.play.getEvent()->getPreItemNo(); +} + +f32 dComIfGp_event_getCullRate() { + return g_dComIfG_gameInfo.play.getEvent()->getCullRate(); +} + +void dComIfGp_event_setCullRate(f32 i_rate) { + g_dComIfG_gameInfo.play.getEvent()->setCullRate(i_rate); +} + +int dComIfGp_event_order(u16 i_type, u16 i_prio, u16 i_flags, u16 i_hindFlags, void* i_requestActor, + void* i_targetActor, s16 i_eventID, u8 i_mapToolId) { + return g_dComIfG_gameInfo.play.getEvent()->order(i_type, i_prio, i_flags, i_hindFlags, + i_requestActor, i_targetActor, i_eventID, i_mapToolId); +} + +void dComIfGp_event_reset() { + g_dComIfG_gameInfo.play.getEvent()->reset(); +} + +int dComIfGp_event_moveApproval(void* i_actor) { + return g_dComIfG_gameInfo.play.getEvent()->moveApproval(i_actor); +} + +BOOL dComIfGp_event_compulsory(void* i_actor, const char* i_eventname, u16 i_hindFlag) { + return g_dComIfG_gameInfo.play.getEvent()->compulsory(i_actor, i_eventname, i_hindFlag); +} + +void dComIfGp_event_remove() { + g_dComIfG_gameInfo.play.getEvent()->remove(); +} + +fopAc_ac_c* dComIfGp_event_getPt1() { + return g_dComIfG_gameInfo.play.getEvent()->getPt1(); +} + +fopAc_ac_c* dComIfGp_event_getPt2() { + return g_dComIfG_gameInfo.play.getEvent()->getPt2(); +} + +fopAc_ac_c* dComIfGp_event_getTalkPartner() { + return g_dComIfG_gameInfo.play.getEvent()->getPtT(); +} + +void dComIfGp_event_setTalkPartner(void* i_actor) { + g_dComIfG_gameInfo.play.getEvent()->setPtT(i_actor); +} + +fopAc_ac_c* dComIfGp_event_getItemPartner() { + return g_dComIfG_gameInfo.play.getEvent()->getPtI(); +} + +void dComIfGp_event_setItemPartner(void* i_actor) { + g_dComIfG_gameInfo.play.getEvent()->setPtI(i_actor); +} + +void dComIfGp_event_setItemPartnerId(fpc_ProcID i_id) { + g_dComIfG_gameInfo.play.getEvent()->setPtI_Id(i_id); +} + +fopAc_ac_c* dComIfGp_event_getDoorPartner() { + return g_dComIfG_gameInfo.play.getEvent()->getPtD(); +} + +void dComIfGp_event_setDoorPartner(void* i_partner) { + g_dComIfG_gameInfo.play.getEvent()->setPtD(i_partner); +} + +u8 dComIfGp_event_getGtItm() { + return g_dComIfG_gameInfo.play.getEvent()->getGtItm(); +} + +void dComIfGp_event_setGtItm(u8 i_itemNo) { + g_dComIfG_gameInfo.play.getEvent()->setGtItm(i_itemNo); +} + +dEvent_manager_c& dComIfGp_getEventManager() { + return g_dComIfG_gameInfo.play.getEvtManager(); +} + +dEvent_manager_c* dComIfGp_getPEvtManager() { + return &g_dComIfG_gameInfo.play.getEvtManager(); +} + +int dComIfGp_evmng_cameraPlay() { + return dComIfGp_getPEvtManager()->cameraPlay(); +} + +int dComIfGp_evmng_startDemo(int i_mapToolId) { + return dComIfGp_getPEvtManager()->setStartDemo(i_mapToolId); +} + +void dComIfGp_evmng_create() { + g_dComIfG_gameInfo.play.getEvtManager().create(); +} + +void dComIfGp_evmng_remove() { + g_dComIfG_gameInfo.play.getEvtManager().remove(); +} + +bool dComIfGp_evmng_existence(s16 eventId) { + return g_dComIfG_gameInfo.play.getEvtManager().getEventData(eventId) != NULL; +} + +s16 dComIfGp_evmng_getEventIdx(const char* eventName, u8 mapToolID) { + return g_dComIfG_gameInfo.play.getEvtManager().getEventIdx(eventName, mapToolID, -1); +} + +bool dComIfGp_evmng_existence(const char* eventname) { + return g_dComIfG_gameInfo.play.getEvtManager().getEventData( + dComIfGp_evmng_getEventIdx(eventname, 0xFF)) != NULL; +} + +BOOL dComIfGp_evmng_isMapToolCamera(u8 mapToolID) { + return g_dComIfG_gameInfo.play.getEvtManager().isMapToolCamera(mapToolID, -1); +} + +BOOL dComIfGp_evmng_startCheck(s16 i_eventId) { + return g_dComIfG_gameInfo.play.getEvtManager().startCheck(i_eventId); +} + +BOOL dComIfGp_evmng_startCheck(char const* i_eventname) { + return g_dComIfG_gameInfo.play.getEvtManager().startCheckOld(i_eventname); +} + +BOOL dComIfGp_evmng_endCheck(s16 i_eventID) { + return g_dComIfG_gameInfo.play.getEvtManager().endCheck(i_eventID); +} + +BOOL dComIfGp_evmng_endCheck(const char* i_eventname) { + return g_dComIfG_gameInfo.play.getEvtManager().endCheckOld(i_eventname); +} + +int dComIfGp_evmng_getMyStaffId(const char* i_staffname, fopAc_ac_c* i_actor, int i_tagId) { + return dComIfGp_getPEvtManager()->getMyStaffId(i_staffname, i_actor, i_tagId); +} + +int dComIfGp_evmng_getIsAddvance(int i_staffId) { + return dComIfGp_getPEvtManager()->getIsAddvance(i_staffId); +} + +int dComIfGp_evmng_getMyActIdx(int i_staffId, DUSK_CONST char* DUSK_CONST* i_actions, + int i_actionNum, BOOL param_3, BOOL param_4) { + return dComIfGp_getPEvtManager()->getMyActIdx( + i_staffId, i_actions, i_actionNum, param_3, param_4); +} + +f32* dComIfGp_evmng_getMyFloatP(int i_staffId, DUSK_CONST char* i_dataname) { + return (f32*)dComIfGp_getPEvtManager()->getMySubstanceP( + i_staffId, i_dataname, dEvDtData_c::TYPE_FLOAT); +} + +cXyz* dComIfGp_evmng_getMyXyzP(int i_staffId, DUSK_CONST char* i_dataname) { + return (cXyz*)dComIfGp_getPEvtManager()->getMySubstanceP( + i_staffId, i_dataname, dEvDtData_c::TYPE_VEC); +} + +int* dComIfGp_evmng_getMyIntegerP(int i_staffId, DUSK_CONST char* i_dataname) { + return (int*)dComIfGp_getPEvtManager()->getMySubstanceP( + i_staffId, i_dataname, dEvDtData_c::TYPE_INT); +} + +char* dComIfGp_evmng_getMyStringP(int i_staffId, DUSK_CONST char* i_dataname) { + return (char*)dComIfGp_getPEvtManager()->getMySubstanceP( + i_staffId, i_dataname, dEvDtData_c::TYPE_STRING); +} + +int dComIfGp_evmng_getMySubstanceNum(int i_staffId, DUSK_CONST char* i_dataname) { + return dComIfGp_getPEvtManager()->getMySubstanceNum(i_staffId, i_dataname); +} + +void dComIfGp_evmng_cutEnd(int i_staffId) { + dComIfGp_getPEvtManager()->cutEnd(i_staffId); +} + +void dComIfGp_evmng_setGoal(cXyz* i_pos) { + dComIfGp_getPEvtManager()->setGoal(i_pos); +} + +cXyz* dComIfGp_evmng_getGoal() { + return dComIfGp_getPEvtManager()->getGoal(); +} + +BOOL dComIfGp_evmng_ChkPresentEnd() { + return dComIfGp_getPEvtManager()->ChkPresentEnd(); +} + +int dComIfGp_evmng_checkStartDemo() { + return dComIfGp_getPEvtManager()->checkStartDemo(); +} + +dAttention_c* dComIfGp_getAttention() { + return g_dComIfG_gameInfo.play.getAttention(); +} + +fopAc_ac_c* dComIfGp_att_getZHint() { + return dComIfGp_getAttention()->getZHintTarget(); +} + +int dComIfGp_att_ZHintRequest(fopAc_ac_c* param_1, int param_2) { + return dComIfGp_getAttention()->ZHintRequest(param_1, param_2); +} + +fopAc_ac_c* dComIfGp_att_getCatghTarget() { + return dComIfGp_getAttention()->getCatghTarget(); +} + +u8 dComIfGp_att_getCatchChgItem() { + return dComIfGp_getAttention()->getCatchChgItem(); +} + +int dComIfGp_att_CatchRequest(fopAc_ac_c* param_0, u8 param_1, f32 i_horizontalDist, f32 i_upDist, + f32 i_downDist, s16 i_angle, int param_5) { + return dComIfGp_getAttention()->CatchRequest( + param_0, param_1, i_horizontalDist, i_upDist, i_downDist, i_angle, param_5); +} + +fopAc_ac_c* dComIfGp_att_getLookTarget() { + return dComIfGp_getAttention()->getLookTarget(); +} + +void dComIfGp_att_LookRequest(fopAc_ac_c* param_0, f32 i_horizontalDist, f32 i_upDist, + f32 i_downDist, s16 i_angle, int param_5) { + dComIfGp_getAttention()->LookRequest( + param_0, i_horizontalDist, i_upDist, i_downDist, i_angle, param_5); +} + +dVibration_c& dComIfGp_getVibration() { + return g_dComIfG_gameInfo.play.getVibration(); +} + +JKRAramArchive* dComIfGp_getFieldMapArchive2() { + return g_dComIfG_gameInfo.play.getFieldMapArchive2(); +} + +void dComIfGp_setFieldMapArchive2(JKRArchive* arc) { + g_dComIfG_gameInfo.play.setFieldMapArchive2(arc); +} + +JKRArchive* dComIfGp_getMsgArchive(int idx) { + return g_dComIfG_gameInfo.play.getMsgArchive(idx); +} + +void dComIfGp_setMsgArchive(int i, JKRArchive* arc) { + g_dComIfG_gameInfo.play.setMsgArchive(i, arc); +} + +JKRArchive* dComIfGp_getDemoMsgArchive() { + return g_dComIfG_gameInfo.play.getDemoMsgArchive(); +} + +void dComIfGp_setDemoMsgArchive(JKRArchive* arc) { + g_dComIfG_gameInfo.play.setDemoMsgArchive(arc); +} + +JKRArchive* dComIfGp_getMeterButtonArchive() { + return g_dComIfG_gameInfo.play.getMeterButtonArchive(); +} + +void dComIfGp_setMeterButtonArchive(JKRArchive* arc) { + g_dComIfG_gameInfo.play.setMeterButtonArchive(arc); +} + +JKRArchive* dComIfGp_getFontArchive() { + return g_dComIfG_gameInfo.play.getFontArchive(); +} + +void dComIfGp_setFontArchive(JKRArchive* arc) { + g_dComIfG_gameInfo.play.setFontArchive(arc); +} + +JKRArchive* dComIfGp_getRubyArchive() { + return g_dComIfG_gameInfo.play.getRubyArchive(); +} + +void dComIfGp_setRubyArchive(JKRArchive* arc) { + g_dComIfG_gameInfo.play.setRubyArchive(arc); +} + +JKRArchive* dComIfGp_getAnmArchive() { + return g_dComIfG_gameInfo.play.getAnmArchive(); +} + +void dComIfGp_setAnmArchive(JKRArchive* arc) { + g_dComIfG_gameInfo.play.setAnmArchive(arc); +} + +JKRArchive* dComIfGp_getCollectResArchive() { + return g_dComIfG_gameInfo.play.getCollectResArchive(); +} + +void dComIfGp_setCollectResArchive(JKRArchive* arc) { + g_dComIfG_gameInfo.play.setCollectResArchive(arc); +} + +JKRArchive* dComIfGp_getFmapResArchive() { + return g_dComIfG_gameInfo.play.getFmapResArchive(); +} + +void dComIfGp_setFmapResArchive(JKRArchive* arc) { + g_dComIfG_gameInfo.play.setFmapResArchive(arc); +} + +JKRArchive* dComIfGp_getDmapResArchive() { + return g_dComIfG_gameInfo.play.getDmapResArchive(); +} + +void dComIfGp_setDmapResArchive(JKRArchive* arc) { + g_dComIfG_gameInfo.play.setDmapResArchive(arc); +} + +JKRArchive* dComIfGp_getOptionResArchive() { + return g_dComIfG_gameInfo.play.getOptionResArchive(); +} + +void dComIfGp_setOptionResArchive(JKRArchive* arc) { + g_dComIfG_gameInfo.play.setOptionResArchive(arc); +} + +JKRArchive* dComIfGp_getItemIconArchive() { + return g_dComIfG_gameInfo.play.getItemIconArchive(); +} + +void dComIfGp_setItemIconArchive(JKRArchive* arc) { + g_dComIfG_gameInfo.play.setItemIconArchive(arc); +} + +JKRArchive* dComIfGp_getNameResArchive() { + return g_dComIfG_gameInfo.play.getNameResArchive(); +} + +void dComIfGp_setNameResArchive(JKRArchive* arc) { + g_dComIfG_gameInfo.play.setNameResArchive(arc); +} + +void dComIfGp_setErrorResArchive(JKRArchive* arc) { + g_dComIfG_gameInfo.play.setErrorResArchive(arc); +} + +JKRArchive* dComIfGp_getAllMapArchive() { + return g_dComIfG_gameInfo.play.getAllMapArchive(); +} + +void dComIfGp_setAllMapArchive(JKRArchive* arc) { + g_dComIfG_gameInfo.play.setAllMapArchive(arc); +} + +JKRArchive* dComIfGp_getMsgCommonArchive() { + return g_dComIfG_gameInfo.play.getMsgCommonArchive(); +} + +void dComIfGp_setMsgCommonArchive(JKRArchive* arc) { + g_dComIfG_gameInfo.play.setMsgCommonArchive(arc); +} + +JKRArchive* dComIfGp_getRingResArchive() { + return g_dComIfG_gameInfo.play.getRingResArchive(); +} + +void dComIfGp_setRingResArchive(JKRArchive* arc) { + g_dComIfG_gameInfo.play.setRingResArchive(arc); +} + +JKRArchive* dComIfGp_getCardIconResArchive() { + return g_dComIfG_gameInfo.play.getCardIconResArchive(); +} + +void dComIfGp_setCardIconResArchive(JKRArchive* arc) { + g_dComIfG_gameInfo.play.setCardIconResArchive(arc); +} + +JKRArchive* dComIfGp_getMsgDtArchive() { + return g_dComIfG_gameInfo.play.getMsgDtArchive(); +} + +JKRArchive* dComIfGp_getMsgDtArchive(int idx) { + return g_dComIfG_gameInfo.play.getMsgDtArchive(idx); +} + +void dComIfGp_setMsgDtArchive(int i, JKRArchive* arc) { + g_dComIfG_gameInfo.play.setMsgDtArchive(i, arc); +} + +JKRArchive* dComIfGp_getMain2DArchive() { + return g_dComIfG_gameInfo.play.getMain2DArchive(); +} + +void dComIfGp_setMain2DArchive(JKRArchive* arc) { + g_dComIfG_gameInfo.play.setMain2DArchive(arc); +} + +JKRExpHeap* dComIfGp_particle_getResHeap() { + return g_dComIfG_gameInfo.play.getParticle()->getResHeap(); +} + +void dComIfGp_particle_levelExecute(u32 param_0) { + g_dComIfG_gameInfo.play.getParticle()->levelExecute(param_0); +} + +void dComIfGp_particle_createCommon(const void* data) { + g_dComIfG_gameInfo.play.getParticle()->createCommon(data); +} + +void dComIfGp_particle_readScene(u8 particle_no, mDoDvdThd_toMainRam_c** param_1) { + g_dComIfG_gameInfo.play.getParticle()->readScene(particle_no, param_1); +} + +void dComIfGp_particle_createScene(const void* param_0) { + g_dComIfG_gameInfo.play.getParticle()->createScene(param_0); +} + +void dComIfGp_particle_removeScene(bool param_0) { + g_dComIfG_gameInfo.play.getParticle()->removeScene(param_0); +} + +void dComIfGp_particle_cleanup() { + g_dComIfG_gameInfo.play.getParticle()->cleanup(); +} + +void dComIfGp_particle_calc3D() { + g_dComIfG_gameInfo.play.getParticle()->calc3D(); +} + +void dComIfGp_particle_calc2D() { + g_dComIfG_gameInfo.play.getParticle()->calc2D(); +} + +void dComIfGp_particle_calcMenu() { + if (g_dComIfG_gameInfo.play.getParticle() != NULL) { + g_dComIfG_gameInfo.play.getParticle()->calcMenu(); + } +} + +void dComIfGp_particle_draw(JPADrawInfo* i_drawInfo) { + ZoneScoped; + if (g_dComIfG_gameInfo.play.getParticle() != NULL) { + g_dComIfG_gameInfo.play.getParticle()->drawNormal(i_drawInfo); + } +} + +void dComIfGp_particle_drawFog(JPADrawInfo* i_drawInfo) { + ZoneScoped; + if (g_dComIfG_gameInfo.play.getParticle() != NULL) { + g_dComIfG_gameInfo.play.getParticle()->drawNormalFog(i_drawInfo); + } +} + +void dComIfGp_particle_drawP1(JPADrawInfo* i_drawInfo) { + ZoneScoped; + if (g_dComIfG_gameInfo.play.getParticle() != NULL) { + g_dComIfG_gameInfo.play.getParticle()->drawNormalP1(i_drawInfo); + } +} + +void dComIfGp_particle_drawProjection(JPADrawInfo* i_drawInfo) { + ZoneScoped; + if (g_dComIfG_gameInfo.play.getParticle() != NULL) { + g_dComIfG_gameInfo.play.getParticle()->drawProjection(i_drawInfo); + } +} + +void dComIfGp_particle_drawNormalPri0_A(JPADrawInfo* i_drawInfo) { + ZoneScoped; + if (g_dComIfG_gameInfo.play.getParticle() != NULL) { + g_dComIfG_gameInfo.play.getParticle()->drawNormalPri0_A(i_drawInfo); + } +} + +void dComIfGp_particle_drawNormalPri0_B(JPADrawInfo* i_drawInfo) { + ZoneScoped; + if (g_dComIfG_gameInfo.play.getParticle() != NULL) { + g_dComIfG_gameInfo.play.getParticle()->drawNormalPri0_B(i_drawInfo); + } +} + +void dComIfGp_particle_drawFogPri0_A(JPADrawInfo* i_drawInfo) { + ZoneScoped; + if (g_dComIfG_gameInfo.play.getParticle() != NULL) { + g_dComIfG_gameInfo.play.getParticle()->drawFogPri0_A(i_drawInfo); + } +} + +void dComIfGp_particle_drawFogPri0_B(JPADrawInfo* i_drawInfo) { + ZoneScoped; + if (g_dComIfG_gameInfo.play.getParticle() != NULL) { + g_dComIfG_gameInfo.play.getParticle()->drawFogPri0_B(i_drawInfo); + } +} + +void dComIfGp_particle_drawFogPri1(JPADrawInfo* i_drawInfo) { + ZoneScoped; + if (g_dComIfG_gameInfo.play.getParticle() != NULL) { + g_dComIfG_gameInfo.play.getParticle()->drawFogPri1(i_drawInfo); + } +} + +void dComIfGp_particle_drawFogPri2(JPADrawInfo* i_drawInfo) { + ZoneScoped; + if (g_dComIfG_gameInfo.play.getParticle() != NULL) { + g_dComIfG_gameInfo.play.getParticle()->drawFogPri2(i_drawInfo); + } +} + +void dComIfGp_particle_drawFogPri3(JPADrawInfo* i_drawInfo) { + ZoneScoped; + if (g_dComIfG_gameInfo.play.getParticle() != NULL) { + g_dComIfG_gameInfo.play.getParticle()->drawFogPri3(i_drawInfo); + } +} + +void dComIfGp_particle_drawFogPri4(JPADrawInfo* i_drawInfo) { + ZoneScoped; + if (g_dComIfG_gameInfo.play.getParticle() != NULL) { + g_dComIfG_gameInfo.play.getParticle()->drawFogPri4(i_drawInfo); + } +} + +void dComIfGp_particle_drawDarkworld(JPADrawInfo* i_drawInfo) { + ZoneScoped; + if (g_dComIfG_gameInfo.play.getParticle() != NULL) { + g_dComIfG_gameInfo.play.getParticle()->drawDarkworld(i_drawInfo); + } +} + +void dComIfGp_particle_drawScreen(JPADrawInfo* i_drawInfo) { + ZoneScoped; + if (g_dComIfG_gameInfo.play.getParticle() != NULL) { + g_dComIfG_gameInfo.play.getParticle()->drawFogScreen(i_drawInfo); + } +} + +void dComIfGp_particle_draw2Dgame(JPADrawInfo* i_drawInfo) { + ZoneScoped; + if (g_dComIfG_gameInfo.play.getParticle() != NULL) { + g_dComIfG_gameInfo.play.getParticle()->draw2Dgame(i_drawInfo); + } +} + +void dComIfGp_particle_draw2Dfore(JPADrawInfo* i_drawInfo) { + ZoneScoped; + if (g_dComIfG_gameInfo.play.getParticle() != NULL) { + g_dComIfG_gameInfo.play.getParticle()->draw2Dfore(i_drawInfo); + } +} + +void dComIfGp_particle_draw2Dback(JPADrawInfo* i_drawInfo) { + ZoneScoped; + if (g_dComIfG_gameInfo.play.getParticle() != NULL) { + g_dComIfG_gameInfo.play.getParticle()->draw2Dback(i_drawInfo); + } +} + +void dComIfGp_particle_draw2DmenuFore(JPADrawInfo* i_drawInfo) { + ZoneScoped; + if (g_dComIfG_gameInfo.play.getParticle() != NULL) { + g_dComIfG_gameInfo.play.getParticle()->draw2DmenuFore(i_drawInfo); + } +} + +void dComIfGp_particle_draw2DmenuBack(JPADrawInfo* i_drawInfo) { + ZoneScoped; + if (g_dComIfG_gameInfo.play.getParticle() != NULL) { + g_dComIfG_gameInfo.play.getParticle()->draw2DmenuBack(i_drawInfo); + } +} + +void dComIfGp_setHitMark(u16 i_hitmark, fopAc_ac_c* param_1, const cXyz* param_2, + const csXyz* param_3, const cXyz* param_4, u32 i_atType) { + g_dComIfG_gameInfo.play.getParticle()->setHitMark( + i_hitmark, param_1, param_2, param_3, param_4, i_atType); +} + +void dComIfGp_particle_setWaterRipple(u32* param_0, cBgS_PolyInfo& param_1, const cXyz* param_2, + f32 param_3, const dKy_tevstr_c* param_4, const cXyz* param_5, s8 param_6) { + g_dComIfG_gameInfo.play.getParticle()->setWaterRipple( + param_0, param_1, param_2, param_3, param_4, param_5, param_6); +} + +u32 dComIfGp_particle_setPolyColor(u32 param_0, u16 param_1, cBgS_PolyInfo& param_2, + const cXyz* param_3, const dKy_tevstr_c* param_4, const csXyz* param_5, const cXyz* param_6, + int param_7, dPa_levelEcallBack* param_8, s8 param_9, const cXyz* param_10) { + return g_dComIfG_gameInfo.play.getParticle()->setPoly(param_0, param_1, param_2, param_3, + param_4, param_5, param_6, param_7, param_8, param_9, param_10); +} + +JPABaseEmitter* dComIfGp_particle_setPolyColor(u16 param_1, cBgS_PolyInfo& param_2, + const cXyz* param_3, const dKy_tevstr_c* param_4, const csXyz* param_5, const cXyz* param_6, + int param_7, dPa_levelEcallBack* param_8, s8 param_9, const cXyz* param_10) { + return g_dComIfG_gameInfo.play.getParticle()->setPoly( + param_1, param_2, param_3, param_4, param_5, param_6, param_7, param_8, param_9, param_10); +} + +void dComIfGp_particle_setSimple(u16 param_0, cXyz* i_pos, u8 param_2, GXColor& param_3, + GXColor& param_4, int param_5, float param_6) { + g_dComIfG_gameInfo.play.getParticle()->setSimple( + param_0, i_pos, 0, param_2, param_3, param_4, param_5, param_6); +} + +u32 dComIfGp_particle_setStopContinue(u32 param_0) { + return g_dComIfG_gameInfo.play.getParticle()->setStopContinue(param_0); +} + +u32 dComIfGp_particle_setSimpleFoot(u32 param_0, u32* param_1, cBgS_PolyInfo& param_2, + cXyz const* param_3, dKy_tevstr_c const* param_4, int param_5, csXyz const* param_6, + cXyz const* param_7, dPa_levelEcallBack* param_8, s8 param_9, cXyz const* param_10) { + return g_dComIfG_gameInfo.play.getParticle()->setSimpleFoot(param_0, param_1, param_2, param_3, + param_4, param_5, param_6, param_7, param_8, param_9, param_10); +} + +u16 dComIfGp_particle_setCommonPoly(u32* param_0, cBgS_PolyInfo* param_1, const cXyz* param_2, + const cXyz* param_3, const dKy_tevstr_c* param_4, u32 param_5, u32 param_6, + const csXyz* param_7, const cXyz* param_8, s8 param_9) { + return g_dComIfG_gameInfo.play.getParticle()->setCommonPoly( + param_0, param_1, param_2, param_3, param_4, param_5, param_6, param_7, param_8, param_9); +} + +void dComIfGp_particle_levelEmitterOnEventMove(u32 param_0) { + g_dComIfG_gameInfo.play.getParticle()->forceOnEventMove(param_0); +} + +JPABaseEmitter* dComIfGp_particle_getEmitter(u32 param_0) { + return g_dComIfG_gameInfo.play.getParticle()->getEmitter(param_0); +} + +u32 dComIfGp_particle_set(u32 param_0, u16 param_1, const cXyz* i_pos, const dKy_tevstr_c* param_3, + const csXyz* i_rotation, const cXyz* i_scale, u8 i_alpha, dPa_levelEcallBack* param_7, + s8 param_8, const GXColor* param_9, const GXColor* param_10, const cXyz* param_11) { + return g_dComIfG_gameInfo.play.getParticle()->setNormal(param_0, param_1, i_pos, param_3, + i_rotation, i_scale, i_alpha, param_7, param_8, param_9, param_10, param_11, 1.0f); +} + +u32 dComIfGp_particle_set(u32 param_0, u16 param_1, const cXyz* i_pos, const csXyz* i_rotation, + const cXyz* i_scale, u8 param_5, dPa_levelEcallBack* param_6, s8 param_7, + const GXColor* param_8, const GXColor* param_9, const cXyz* param_10) { + return g_dComIfG_gameInfo.play.getParticle()->setNormal(param_0, param_1, i_pos, NULL, + i_rotation, i_scale, param_5, param_6, param_7, param_8, param_9, param_10, 1.0f); +} + +JPABaseEmitter* dComIfGp_particle_set(u16 i_resID, const cXyz* i_pos, const dKy_tevstr_c* param_3, + const csXyz* i_rotation, const cXyz* i_scale, u8 i_alpha, dPa_levelEcallBack* i_callback, + s8 param_8, const GXColor* i_prmColor, const GXColor* i_envColor, const cXyz* i_particleScale) { + return g_dComIfG_gameInfo.play.getParticle()->setNormal(i_resID, i_pos, param_3, i_rotation, + i_scale, i_alpha, i_callback, param_8, i_prmColor, i_envColor, i_particleScale, 1.0f); +} + +JPABaseEmitter* dComIfGp_particle_set(u16 i_resID, const cXyz* i_pos, const csXyz* i_rotation, + const cXyz* i_scale, u8 i_alpha, dPa_levelEcallBack* i_callback, s8 param_7, + const GXColor* i_prmColor, const GXColor* i_envColor, const cXyz* i_particleScale) { + return g_dComIfG_gameInfo.play.getParticle()->setNormal(i_resID, i_pos, NULL, i_rotation, + i_scale, i_alpha, i_callback, param_7, i_prmColor, i_envColor, i_particleScale, 1.0f); +} + +u32 dComIfGp_particle_set( + u32 param_0, u16 param_1, const cXyz* i_pos, const dKy_tevstr_c* param_3) { + return dComIfGp_particle_set( + param_0, param_1, i_pos, param_3, NULL, NULL, 0xFF, NULL, -1, NULL, NULL, NULL); +} + +JPABaseEmitter* dComIfGp_particle_set( + u16 i_resID, const cXyz* i_pos, const csXyz* i_rotation, const cXyz* i_scale) { + return dComIfGp_particle_set( + i_resID, i_pos, NULL, i_rotation, i_scale, 255, NULL, -1, NULL, NULL, NULL); +} + +JPABaseEmitter* dComIfGp_particle_set(u16 i_resID, const cXyz* i_pos, const dKy_tevstr_c* param_2, + const csXyz* i_rotation, const cXyz* i_scale) { + return dComIfGp_particle_set( + i_resID, i_pos, param_2, i_rotation, i_scale, 255, NULL, -1, NULL, NULL, NULL); +} + +u32 dComIfGp_particle_set( + u32 param_0, u16 param_1, const cXyz* i_pos, const csXyz* param_3, const cXyz* param_4) { + return dComIfGp_particle_set( + param_0, param_1, i_pos, param_3, param_4, 0xFF, NULL, -1, NULL, NULL, NULL); +} + +u32 dComIfGp_particle_setColor(u32 param_0, u16 param_1, const cXyz* i_pos, + const dKy_tevstr_c* param_3, const GXColor* param_4, const GXColor* param_5, f32 param_6, + u8 param_7, const csXyz* param_8, const cXyz* param_9, dPa_levelEcallBack* param_10, + s8 param_11, const cXyz* param_12) { + return g_dComIfG_gameInfo.play.getParticle()->setNormal(param_0, param_1, i_pos, param_3, + param_8, param_9, param_7, param_10, param_11, param_4, param_5, param_12, param_6); +} + +JPABaseEmitter* dComIfGp_particle_setColor(u16 param_0, const cXyz* i_pos, + const dKy_tevstr_c* param_2, const GXColor* param_3, const GXColor* param_4, f32 param_5, + u8 param_6, const csXyz* param_7, const cXyz* param_8, dPa_levelEcallBack* param_9, s8 param_10, + const cXyz* param_11) { + return g_dComIfG_gameInfo.play.getParticle()->setNormal(param_0, i_pos, param_2, param_7, + param_8, param_6, param_9, param_10, param_3, param_4, param_11, param_5); +} + +JPABaseEmitter* dComIfGp_particle_setColor(u16 param_0, const cXyz* i_pos, + const dKy_tevstr_c* param_2, const GXColor* param_3, const GXColor* param_4, f32 param_5, + u8 param_6) { + return dComIfGp_particle_setColor( + param_0, i_pos, param_2, param_3, param_4, param_5, param_6, NULL, NULL, NULL, -1, NULL); +} + +u32 dComIfGp_particle_getHeapSize() { + return g_dComIfG_gameInfo.play.getParticle()->getHeapSize(); +} + +u32 dComIfGp_particle_getSceneHeapSize() { + return g_dComIfG_gameInfo.play.getParticle()->getSceneHeapSize(); +} + +int dComIfGp_particle_getEmitterNum() { + return g_dComIfG_gameInfo.play.getParticle()->getEmitterNum(); +} + +int dComIfGp_particle_getParticleNum() { + return g_dComIfG_gameInfo.play.getParticle()->getParticleNum(); +} + +dSmplMdl_draw_c* dComIfGp_getSimpleModel() { + return g_dComIfG_gameInfo.play.getSimpleModel(); +} + +int dComIfGp_getWindowNum() { + return g_dComIfG_gameInfo.play.getWindowNum(); +} + +void dComIfGp_setWindowNum(int num) { + g_dComIfG_gameInfo.play.setWindowNum(num); +} + +s8 dComIfGp_getLayerOld() { + return g_dComIfG_gameInfo.play.getLayerOld(); +} + +s32 dComIfGp_checkStatus(u16 flags) { + return g_dComIfG_gameInfo.play.checkStatus(flags); +} + +void dComIfGp_setStatus(u16 status) { + g_dComIfG_gameInfo.play.setStatus(status); +} + +void dComIfGp_onStatus(u16 i_status) { + g_dComIfG_gameInfo.play.onStatus(i_status); +} + +dDlst_window_c* dComIfGp_getWindow(int i) { + return g_dComIfG_gameInfo.play.getWindow(i); +} + +void dComIfGp_setWindow(u8 i, f32 param_1, f32 param_2, f32 param_3, f32 param_4, f32 param_5, + f32 param_6, int camID, int mode) { + g_dComIfG_gameInfo.play.setWindow( + i, param_1, param_2, param_3, param_4, param_5, param_6, camID, mode); +} + +camera_process_class* dComIfGp_getCamera(int idx) { + return (camera_process_class*)g_dComIfG_gameInfo.play.getCamera(idx); +} + +void dComIfGp_setCamera(int i, camera_class* cam) { + g_dComIfG_gameInfo.play.setCamera(i, cam); +} + +int dComIfGp_getCameraWinID(int idx) { + return g_dComIfG_gameInfo.play.getCameraWinID(idx); +} + +int dComIfGp_getCameraPlayer1ID(int idx) { + return g_dComIfG_gameInfo.play.getCameraPlayer1ID(idx); +} + +int dComIfGp_getCameraPlayer2ID(int idx) { + return g_dComIfG_gameInfo.play.getCameraPlayer2ID(idx); +} + +u32 dComIfGp_getCameraAttentionStatus(int i_no) { + return g_dComIfG_gameInfo.play.getCameraAttentionStatus(i_no); +} + +BOOL dComIfGp_checkCameraAttentionStatus(int i, u32 flag) { + return g_dComIfG_gameInfo.play.checkCameraAttentionStatus(i, flag); +} + +void dComIfGp_onCameraAttentionStatus(int i, u32 flag) { + g_dComIfG_gameInfo.play.onCameraAttentionStatus(i, flag); +} + +void dComIfGp_offCameraAttentionStatus(int i, u32 flag) { + g_dComIfG_gameInfo.play.offCameraAttentionStatus(i, flag); +} + +void dComIfGp_setCameraInfo( + int camIdx, camera_class* p_cam, int param_2, int param_3, int param_4) { + g_dComIfG_gameInfo.play.setCameraInfo(camIdx, p_cam, param_2, param_3, param_4); +} + +f32 dComIfGp_getCameraZoomScale(int i_no) { + return g_dComIfG_gameInfo.play.getCameraZoomScale(i_no); +} + +void dComIfGp_setCameraZoomScale(int i_no, f32 i_scale) { + g_dComIfG_gameInfo.play.setCameraZoomScale(i_no, i_scale); +} + +f32 dComIfGp_getCameraZoomForcus(int i_no) { + return g_dComIfG_gameInfo.play.getCameraZoomForcus(i_no); +} + +void dComIfGp_setCameraZoomForcus(int i_no, f32 i_focus) { + g_dComIfG_gameInfo.play.setCameraZoomForcus(i_no, i_focus); +} + +const char* dComIfGp_getCameraParamFileName(int i) { + return g_dComIfG_gameInfo.play.getCameraParamFileName(i); +} + +void dComIfGp_setCameraParamFileName(int i, char* name) { + g_dComIfG_gameInfo.play.setCameraParamFileName(i, name); +} + +void dComIfGp_saveCameraPosition(int i, cXyz* i_pos, cXyz* i_target, f32 i_fovy, s16 i_bank) { + g_dComIfG_gameInfo.play.saveCameraPosition(i, i_pos, i_target, i_fovy, i_bank); +} + +void dComIfGp_loadCameraPosition(int i, cXyz* o_pos, cXyz* o_target, f32* o_fovy, s16* o_bank) { + g_dComIfG_gameInfo.play.loadCameraPosition(i, o_pos, o_target, o_fovy, o_bank); +} + +fopAc_ac_c* dComIfGp_getPlayer(int idx) { + return g_dComIfG_gameInfo.play.getPlayer(idx); +} + +void dComIfGp_setPlayer(int i, fopAc_ac_c* player) { + g_dComIfG_gameInfo.play.setPlayer(i, player); +} + +int dComIfGp_getPlayerCameraID(int idx) { + return g_dComIfG_gameInfo.play.getPlayerCameraID(idx); +} + +void dComIfGp_setPlayerInfo(int plyrIdx, fopAc_ac_c* ptr, int camIdx) { + g_dComIfG_gameInfo.play.setPlayerInfo(plyrIdx, ptr, camIdx); +} + +daPy_py_c* dComIfGp_getLinkPlayer() { + return (daPy_py_c*)g_dComIfG_gameInfo.play.getPlayerPtr(LINK_PTR); +} + +daHorse_c* dComIfGp_getHorseActor() { + return (daHorse_c*)g_dComIfG_gameInfo.play.getPlayerPtr(HORSE_PTR); +} + +void dComIfGp_setLinkPlayer(fopAc_ac_c* ptr) { + g_dComIfG_gameInfo.play.setPlayerPtr(0, ptr); +} + +void dComIfGp_setHorseActor(fopAc_ac_c* i_horse) { + g_dComIfG_gameInfo.play.setPlayerPtr(1, i_horse); +} + +void dComIfGp_setPlayerPtr(int i, fopAc_ac_c* ptr) { + g_dComIfG_gameInfo.play.setPlayerPtr(i, ptr); +} + +dMsgObject_c* dComIfGp_getMsgObjectClass() { + return g_dComIfG_gameInfo.play.getMsgObjectClass(); +} + +void dComIfGp_setMsgObjectClass(dMsgObject_c* obj) { + return g_dComIfG_gameInfo.play.setMsgObjectClass(obj); +} + +f32 dComIfGp_getItemLifeCount() { + return g_dComIfG_gameInfo.play.getItemLifeCount(); +} + +u8 dComIfGp_getItemLifeCountType() { + return g_dComIfG_gameInfo.play.getItemLifeCountType(); +} + +void dComIfGp_setItemLifeCount(f32 amount, u8 type) { + g_dComIfG_gameInfo.play.setItemLifeCount(amount, type); +} + +void dComIfGp_clearItemLifeCount() { + g_dComIfG_gameInfo.play.clearItemLifeCount(); +} + +s32 dComIfGp_getItemRupeeCount() { + return g_dComIfG_gameInfo.play.getItemRupeeCount(); +} + +void dComIfGp_setItemRupeeCount(s32 amount) { + g_dComIfG_gameInfo.play.setItemRupeeCount(amount); +} + +void dComIfGp_clearItemRupeeCount() { + g_dComIfG_gameInfo.play.clearItemRupeeCount(); +} + +s16 dComIfGp_getItemKeyNumCount() { + return g_dComIfG_gameInfo.play.getItemKeyNumCount(); +} + +void dComIfGp_setItemKeyNumCount(s16 count) { + g_dComIfG_gameInfo.play.setItemKeyNumCount(count); +} + +void dComIfGp_clearItemKeyNumCount() { + g_dComIfG_gameInfo.play.clearItemKeyNumCount(); +} + +s16 dComIfGp_getItemMaxLifeCount() { + return g_dComIfG_gameInfo.play.getItemMaxLifeCount(); +} + +void dComIfGp_setItemMaxLifeCount(s16 count) { + g_dComIfG_gameInfo.play.setItemMaxLifeCount(count); +} + +void dComIfGp_clearItemMaxLifeCount() { + g_dComIfG_gameInfo.play.clearItemMaxLifeCount(); +} + +void dComIfGp_setItemMagicCount(s16 count) { + g_dComIfG_gameInfo.play.setItemMagicCount(count); +} + +void dComIfGp_setItemNowMagic(s16 magic) { + g_dComIfG_gameInfo.play.setItemNowMagic(magic); +} + +void dComIfGp_setItemMaxMagicCount(s16 count) { + g_dComIfG_gameInfo.play.setItemMaxMagicCount(count); +} + +s32 dComIfGp_getItemOilCount() { + return g_dComIfG_gameInfo.play.getItemOilCount(); +} + +void dComIfGp_setItemOilCount(s32 oil) { + g_dComIfG_gameInfo.play.setItemOilCount(oil); +} + +void dComIfGp_setItemMaxOilCount(s32 oil) { + g_dComIfG_gameInfo.play.setItemMaxOilCount(oil); +} + +void dComIfGp_clearItemOilCount() { + g_dComIfG_gameInfo.play.clearItemOilCount(); +} + +s32 dComIfGp_getItemNowOil() { + return g_dComIfG_gameInfo.play.getItemNowOil(); +} + +void dComIfGp_setItemNowOil(s32 oil) { + g_dComIfG_gameInfo.play.setItemNowOil(oil); +} + +s32 dComIfGp_getItemMaxOilCount() { + return g_dComIfG_gameInfo.play.getItemMaxOilCount(); +} + +void dComIfGp_clearItemMaxOilCount() { + g_dComIfG_gameInfo.play.clearItemMaxOilCount(); +} + +int dComIfGp_getOxygen() { + return g_dComIfG_gameInfo.play.getOxygen(); +} + +void dComIfGp_setOxygen(s32 oxygen) { + g_dComIfG_gameInfo.play.setOxygen(oxygen); +} + +int dComIfGp_getNowOxygen() { + return g_dComIfG_gameInfo.play.getNowOxygen(); +} + +void dComIfGp_setNowOxygen(s32 oxygen) { + g_dComIfG_gameInfo.play.setNowOxygen(oxygen); +} + +s32 dComIfGp_getMaxOxygen() { + return g_dComIfG_gameInfo.play.getMaxOxygen(); +} + +void dComIfGp_setMaxOxygen(s32 i_oxygen) { + g_dComIfG_gameInfo.play.setMaxOxygen(i_oxygen); +} + +s32 dComIfGp_getOxygenCount() { + return g_dComIfG_gameInfo.play.getOxygenCount(); +} + +void dComIfGp_setOxygenCount(s32 oxygen) { + g_dComIfG_gameInfo.play.setOxygenCount(oxygen); +} + +void dComIfGp_clearOxygenCount() { + g_dComIfG_gameInfo.play.clearOxygenCount(); +} + +void dComIfGp_setMaxOxygenCount(s32 oxygen) { + g_dComIfG_gameInfo.play.setMaxOxygenCount(oxygen); +} + +s32 dComIfGp_getMaxOxygenCount() { + return g_dComIfG_gameInfo.play.getMaxOxygenCount(); +} + +void dComIfGp_clearMaxOxygenCount() { + g_dComIfG_gameInfo.play.clearMaxOxygenCount(); +} + +s16 dComIfGp_getItemArrowNumCount() { + return g_dComIfG_gameInfo.play.getItemArrowNumCount(); +} + +void dComIfGp_setItemArrowNumCount(s16 count) { + g_dComIfG_gameInfo.play.setItemArrowNumCount(count); +} + +void dComIfGp_clearItemArrowNumCount() { + g_dComIfG_gameInfo.play.clearItemArrowNumCount(); +} + +s16 dComIfGp_getItemPachinkoNumCount() { + return g_dComIfG_gameInfo.play.getItemPachinkoNumCount(); +} + +void dComIfGp_setItemPachinkoNumCount(s16 count) { + g_dComIfG_gameInfo.play.setItemPachinkoNumCount(count); +} + +void dComIfGp_clearItemPachinkoNumCount() { + g_dComIfG_gameInfo.play.clearItemPachinkoNumCount(); +} + +s16 dComIfGp_getItemMaxArrowNumCount() { + return g_dComIfG_gameInfo.play.getItemMaxArrowNumCount(); +} + +int dComIfGp_getMessageCountNumber() { + return g_dComIfG_gameInfo.play.getMessageCountNumber(); +} + +void dComIfGp_setMessageCountNumber(s32 number) { + g_dComIfG_gameInfo.play.setMessageCountNumber(number); +} + +u16 dComIfGp_getItemNowLife() { + return g_dComIfG_gameInfo.play.getItemNowLife(); +} + +void dComIfGp_setItemNowLife(u16 life) { + g_dComIfG_gameInfo.play.setItemNowLife(life); +} + +u8 dComIfGp_getMesgStatus() { + return g_dComIfG_gameInfo.play.getMesgStatus(); +} + +u8 dComIfGp_getRStatus() { + return g_dComIfG_gameInfo.play.getRStatus(); +} + +bool dComIfGp_isRSetFlag(u8 flag) { + return g_dComIfG_gameInfo.play.isRSetFlag(flag); +} + +void dComIfGp_setRStatus(u8 status, u8 flag) { + g_dComIfG_gameInfo.play.setRStatus(status, flag); +} + +u8 dComIfGp_getRStatusForce() { + return g_dComIfG_gameInfo.play.getRStatusForce(); +} + +u8 dComIfGp_getRSetFlagForce() { + return g_dComIfG_gameInfo.play.getRSetFlagForce(); +} + +void dComIfGp_setRStatusForce(u8 status, u8 flag) { + g_dComIfG_gameInfo.play.setRStatusForce(status, flag); +} + +u8 dComIfGp_getAStatus() { + return g_dComIfG_gameInfo.play.getAStatus(); +} + +bool dComIfGp_isASetFlag(u8 flag) { + return g_dComIfG_gameInfo.play.isASetFlag(flag); +} + +void dComIfGp_setAStatus(u8 status, u8 flag) { + g_dComIfG_gameInfo.play.setAStatus(status, flag); +} + +u8 dComIfGp_getAStatusForce() { + return g_dComIfG_gameInfo.play.getAStatusForce(); +} + +u8 dComIfGp_getASetFlagForce() { + return g_dComIfG_gameInfo.play.getASetFlagForce(); +} + +void dComIfGp_setAStatusForce(u8 status, u8 flag) { + g_dComIfG_gameInfo.play.setAStatusForce(status, flag); +} + +u8 dComIfGp_getNunStatus() { + return g_dComIfG_gameInfo.play.getNunStatus(); +} + +bool dComIfGp_isNunSetFlag(u8 flag) { + return g_dComIfG_gameInfo.play.isNunSetFlag(flag); +} + +void dComIfGp_setNunStatus(u8 status, u8 param_1, u8 flag) { + g_dComIfG_gameInfo.play.setNunStatus(status, param_1, flag); +} + +u8 dComIfGp_getBottleStatus() { + return g_dComIfG_gameInfo.play.getBottleStatus(); +} + +bool dComIfGp_isBottleSetFlag(u8 flag) { + return g_dComIfG_gameInfo.play.isBottleSetFlag(flag); +} + +void dComIfGp_setBottleStatus(u8 param_0, u8 param_1) { + g_dComIfG_gameInfo.play.setBottleStatus(param_0, param_1); +} + +u8 dComIfGp_getBottleStatusForce() { + return g_dComIfG_gameInfo.play.getBottleStatusForce(); +} + +u8 dComIfGp_getBottleSetFlagForce() { + return g_dComIfG_gameInfo.play.getBottleSetFlagForce(); +} + +void dComIfGp_setBottleStatusForce(u8 param_0, u8 param_1) { + g_dComIfG_gameInfo.play.setBottleStatusForce(param_0, param_1); +} + +u8 dComIfGp_getRemoConStatus() { + return g_dComIfG_gameInfo.play.getRemoConStatus(); +} + +bool dComIfGp_isRemoConSetFlag(u8 flag) { + return g_dComIfG_gameInfo.play.isRemoConSetFlag(flag); +} + +void dComIfGp_setRemoConStatus(u8 status, u8 param_1, u8 flag) { + g_dComIfG_gameInfo.play.setRemoConStatus(status, param_1, flag); +} + +u8 dComIfGp_getDoStatus() { + return g_dComIfG_gameInfo.play.getDoStatus(); +} + +bool dComIfGp_isDoSetFlag(u8 flag) { + return g_dComIfG_gameInfo.play.isDoSetFlag(flag); +} + +void dComIfGp_setDoStatus(u8 status, u8 flag) { + g_dComIfG_gameInfo.play.setDoStatus(status, flag); +} + +u8 dComIfGp_getDoStatusForce() { + return g_dComIfG_gameInfo.play.getDoStatusForce(); +} + +u8 dComIfGp_getDoSetFlagForce() { + return g_dComIfG_gameInfo.play.getDoSetFlagForce(); +} + +void dComIfGp_setDoStatusForce(u8 status, u8 flag) { + g_dComIfG_gameInfo.play.setDoStatusForce(status, flag); +} + +u8 dComIfGp_get3DStatus() { + return g_dComIfG_gameInfo.play.get3DStatus(); +} + +u8 dComIfGp_get3DDirection() { + return g_dComIfG_gameInfo.play.get3DDirection(); +} + +bool dComIfGp_is3DSetFlag(u8 flag) { + return g_dComIfG_gameInfo.play.is3DSetFlag(flag); +} + +void dComIfGp_set3DStatus(u8 status, u8 direction, u8 flag) { + g_dComIfG_gameInfo.play.set3DStatus(status, direction, flag); +} + +u8 dComIfGp_get3DStatusForce() { + return g_dComIfG_gameInfo.play.get3DStatusForce(); +} + +u8 dComIfGp_get3DDirectionForce() { + return g_dComIfG_gameInfo.play.get3DDirectionForce(); +} + +u8 dComIfGp_get3DSetFlagForce() { + return g_dComIfG_gameInfo.play.get3DSetFlagForce(); +} + +void dComIfGp_set3DStatusForce(u8 status, u8 direction, u8 flag) { + g_dComIfG_gameInfo.play.set3DStatusForce(status, direction, flag); +} + +u8 dComIfGp_getCStickStatus() { + return g_dComIfG_gameInfo.play.getCStickStatus(); +} + +u8 dComIfGp_getCStickDirection() { + return g_dComIfG_gameInfo.play.getCStickDirection(); +} + +bool dComIfGp_isCStickSetFlag(u8 flag) { + return g_dComIfG_gameInfo.play.isCStickSetFlag(flag); +} + +void dComIfGp_setCStickStatus(u8 status, u8 param_1, u8 flag) { + g_dComIfG_gameInfo.play.setCStickStatus(status, param_1, flag); +} + +u8 dComIfGp_getCStickStatusForce() { + return g_dComIfG_gameInfo.play.getCStickStatusForce(); +} + +u8 dComIfGp_getCStickDirectionForce() { + return g_dComIfG_gameInfo.play.getCStickDirectionForce(); +} + +u8 dComIfGp_getCStickSetFlagForce() { + return g_dComIfG_gameInfo.play.getCStickSetFlagForce(); +} + +void dComIfGp_setCStickStatusForce(u8 status, u8 param_1, u8 flag) { + g_dComIfG_gameInfo.play.setCStickStatusForce(status, param_1, flag); +} + +u8 dComIfGp_getSButtonStatus() { + return g_dComIfG_gameInfo.play.getSButtonStatus(); +} + +bool dComIfGp_isSButtonSetFlag(u8 flag) { + return g_dComIfG_gameInfo.play.isSButtonSetFlag(flag); +} + +void dComIfGp_setSButtonStatus(u8 status, u8 flag) { + g_dComIfG_gameInfo.play.setSButtonStatus(status, flag); +} + +u8 dComIfGp_getSButtonStatusForce() { + return g_dComIfG_gameInfo.play.getSButtonStatusForce(); +} + +u8 dComIfGp_getSButtonSetFlagForce() { + return g_dComIfG_gameInfo.play.getSButtonSetFlagForce(); +} + +void dComIfGp_setSButtonStatusForce(u8 status, u8 flag) { + g_dComIfG_gameInfo.play.setSButtonStatusForce(status, flag); +} + +u8 dComIfGp_getZStatus() { + return g_dComIfG_gameInfo.play.getZStatus(); +} + +bool dComIfGp_isZSetFlag(u8 flag) { + return g_dComIfG_gameInfo.play.isZSetFlag(flag); +} + +void dComIfGp_setZStatus(u8 status, u8 flag) { + g_dComIfG_gameInfo.play.setZStatus(status, flag); +} + +u8 dComIfGp_getZStatusForce() { + return g_dComIfG_gameInfo.play.getZStatusForce(); +} + +u8 dComIfGp_getZSetFlagForce() { + return g_dComIfG_gameInfo.play.getZSetFlagForce(); +} + +void dComIfGp_setZStatusForce(u8 status, u8 flag) { + g_dComIfG_gameInfo.play.setZStatusForce(status, flag); +} + +u8 dComIfGp_getXStatus() { + return g_dComIfG_gameInfo.play.getXStatus(); +} + +bool dComIfGp_isXSetFlag(u8 flag) { + return g_dComIfG_gameInfo.play.isXSetFlag(flag); +} + +void dComIfGp_setXStatus(u8 status, u8 flag) { + g_dComIfG_gameInfo.play.setXStatus(status, flag); +} + +u8 dComIfGp_getXStatusForce() { + return g_dComIfG_gameInfo.play.getXStatusForce(); +} + +u8 dComIfGp_getXSetFlagForce() { + return g_dComIfG_gameInfo.play.getXSetFlagForce(); +} + +void dComIfGp_setXStatusForce(u8 status, u8 flag) { + g_dComIfG_gameInfo.play.setXStatusForce(status, flag); +} + +u8 dComIfGp_getYStatus() { + return g_dComIfG_gameInfo.play.getYStatus(); +} + +bool dComIfGp_isYSetFlag(u8 flag) { + return g_dComIfG_gameInfo.play.isYSetFlag(flag); +} + +void dComIfGp_setYStatus(u8 status, u8 flag) { + g_dComIfG_gameInfo.play.setYStatus(status, flag); +} + +u8 dComIfGp_getYStatusForce() { + return g_dComIfG_gameInfo.play.getYStatusForce(); +} + +u8 dComIfGp_getYSetFlagForce() { + return g_dComIfG_gameInfo.play.getYSetFlagForce(); +} + +void dComIfGp_setYStatusForce(u8 status, u8 flag) { + g_dComIfG_gameInfo.play.setYStatusForce(status, flag); +} + +u8 dComIfGp_getNunZStatus() { + return g_dComIfG_gameInfo.play.getNunZStatus(); +} + +bool dComIfGp_isNunZSetFlag(u8 flag) { + return g_dComIfG_gameInfo.play.isNunZSetFlag(flag); +} + +void dComIfGp_setNunZStatus(u8 param_0, u8 param_1) { + g_dComIfG_gameInfo.play.setNunZStatus(param_0, param_1); +} + +u8 dComIfGp_getNunCStatus() { + return g_dComIfG_gameInfo.play.getNunCStatus(); +} + +bool dComIfGp_isNunCSetFlag(u8 flag) { + return g_dComIfG_gameInfo.play.isNunCSetFlag(flag); +} + +void dComIfGp_setNunCStatus(u8 param_0, u8 param_1) { + g_dComIfG_gameInfo.play.setNunCStatus(param_0, param_1); +} + +void dComIfGp_setSelectEquipClothes(u8 i_clothNo) { + g_dComIfG_gameInfo.play.setSelectEquip(COLLECT_CLOTHING, i_clothNo); +} + +void dComIfGp_setSelectEquipSword(u8 i_swordNo) { + g_dComIfG_gameInfo.play.setSelectEquip(COLLECT_SWORD, i_swordNo); +} + +void dComIfGp_setSelectEquipShield(u8 i_shieldNo) { + g_dComIfG_gameInfo.play.setSelectEquip(COLLECT_SHIELD, i_shieldNo); +} + +u8 dComIfGp_getMesgAnimeAttrInfo() { + return g_dComIfG_gameInfo.play.getBaseAnimeID(); +} + +void dComIfGp_setMesgAnimeAttrInfo(u8 param_1) { + g_dComIfG_gameInfo.play.setBaseAnimeID(param_1); +} + +void dComIfGp_clearMesgAnimeAttrInfo() { + g_dComIfG_gameInfo.play.clearBaseAnimeID(); +} + +u8 dComIfGp_getMesgFaceAnimeAttrInfo() { + return g_dComIfG_gameInfo.play.getFaceAnimeID(); +} + +void dComIfGp_setMesgFaceAnimeAttrInfo(u8 id) { + g_dComIfG_gameInfo.play.setFaceAnimeID(id); +} + +void dComIfGp_clearMesgFaceAnimeAttrInfo() { + g_dComIfG_gameInfo.play.clearFaceAnimeID(); +} + +void dComIfGp_clearMesgAnimeTagInfo() { + g_dComIfG_gameInfo.play.clearNowAnimeID(); +} + +void dComIfGp_setItem(u8 slot, u8 i_no) { + g_dComIfG_gameInfo.play.setItem(slot, i_no); +} + +u8 dComIfGp_getAdvanceDirection() { + return g_dComIfG_gameInfo.play.getDirection(); +} + +void dComIfGp_setAdvanceDirection(u8 i_dir) { + g_dComIfG_gameInfo.play.setDirection(i_dir); +} + +u8 dComIfGp_checkMesgCancelButton() { + return g_dComIfG_gameInfo.play.checkMesgCancelButton(); +} + +void dComIfGp_setMesgCancelButton(u8 button) { + g_dComIfG_gameInfo.play.setMesgCancelButton(button); +} + +u8 dComIfGp_getGameoverStatus() { + return g_dComIfG_gameInfo.play.getGameoverStatus(); +} + +void dComIfGp_setGameoverStatus(u8 i_status) { + return g_dComIfG_gameInfo.play.setGameoverStatus(i_status); +} + +u8 dComIfGp_isHeapLockFlag() { + return g_dComIfG_gameInfo.play.isHeapLockFlag(); +} + +u8 dComIfGp_getSubHeapLockFlag(int idx) { + return g_dComIfG_gameInfo.play.getSubHeapLockFlag(idx); +} + +void dComIfGp_setSubHeapLockFlag(int idx, u8 status) { + g_dComIfG_gameInfo.play.setSubHeapLockFlag(idx, status); +} + +u8 dComIfGp_getNeedLightDropNum() { + return g_dComIfG_gameInfo.play.getNeedLightDropNum(); +} + +void dComIfGp_setNeedLightDropNum(u8 i_num) { + g_dComIfG_gameInfo.play.setNeedLightDropNum(i_num); +} + +u8 dComIfGp_checkMesgBgm() { + return g_dComIfG_gameInfo.play.checkMesgBgm(); +} + +void dComIfGp_setMesgBgmOff() { + g_dComIfG_gameInfo.play.setMesgBgm(0); +} + +void dComIfGp_setMesgBgmOn() { + g_dComIfG_gameInfo.play.setMesgBgm(1); +} + +u8 dComIfGp_isPauseFlag() { + return g_dComIfG_gameInfo.play.isPauseFlag(); +} + +void dComIfGp_offPauseFlag() { + g_dComIfG_gameInfo.play.offPauseFlag(); +} + +void dComIfGp_onPauseFlag() { + g_dComIfG_gameInfo.play.onPauseFlag(); +} + +u8 dComIfGp_getOxygenShowFlag() { + return g_dComIfG_gameInfo.play.getOxygenShowFlag(); +} + +void dComIfGp_offOxygenShowFlag() { + g_dComIfG_gameInfo.play.setOxygenShowFlag(0); +} + +void dComIfGp_onOxygenShowFlag() { + g_dComIfG_gameInfo.play.setOxygenShowFlag(1); +} + +u8 dComIfGp_2dShowCheck() { + return g_dComIfG_gameInfo.play.show2dCheck(); +} + +void dComIfGp_2dShowOn() { + g_dComIfG_gameInfo.play.show2dOn(); +} + +void dComIfGp_2dShowOff() { + g_dComIfG_gameInfo.play.show2dOff(); +} + +JKRExpHeap* dComIfGp_getExpHeap2D() { + return g_dComIfG_gameInfo.play.getExpHeap2D(); +} + +void dComIfGp_setExpHeap2D(void* heap) { + g_dComIfG_gameInfo.play.setExpHeap2D(heap); +} + +JKRExpHeap* dComIfGp_getSubExpHeap2D(int idx) { + return g_dComIfG_gameInfo.play.getSubExpHeap2D(idx); +} + +void dComIfGp_setSubExpHeap2D(int idx, void* heap) { + g_dComIfG_gameInfo.play.setSubExpHeap2D(idx, heap); +} + +JKRExpHeap* dComIfGp_getMsgExpHeap() { + return g_dComIfG_gameInfo.play.getMsgExpHeap(); +} + +void dComIfGp_setMsgExpHeap(void* heap) { + g_dComIfG_gameInfo.play.setMsgExpHeap(heap); +} + +dComIfG_MesgCamInfo_c* dComIfGp_getMesgCameraInfo() { + return g_dComIfG_gameInfo.play.getMesgCamInfo(); +} + +void dComIfGp_setMesgCameraTagInfo(int id) { + g_dComIfG_gameInfo.play.setMesgCamInfoID(id); +} + +void dComIfGp_clearMesgCameraTagInfo() { + g_dComIfG_gameInfo.play.clearMesgCamInfoID(); +} + +void dComIfGp_setMesgCameraAttrInfo(int param_1) { + g_dComIfG_gameInfo.play.setMesgCamInfoBasicID(param_1); +} + +void dComIfGp_clearMesgCameraAttrInfo() { + g_dComIfG_gameInfo.play.clearMesgCamInfoBasicID(); +} + +void dComIfGp_setMesgCameraInfoActor(fopAc_ac_c* param_1, fopAc_ac_c* param_2, fopAc_ac_c* param_3, + fopAc_ac_c* param_4, fopAc_ac_c* param_5, fopAc_ac_c* param_6, fopAc_ac_c* param_7, + fopAc_ac_c* param_8, fopAc_ac_c* param_9, fopAc_ac_c* param_10) + +{ + g_dComIfG_gameInfo.play.setMesgCamInfoActor( + param_1, param_2, param_3, param_4, param_5, param_6, param_7, param_8, param_9, param_10); +} + +u32 dComIfGp_checkPlayerStatus0(int param_0, u32 flag) { + return g_dComIfG_gameInfo.play.checkPlayerStatus(param_0, 0, flag); +} + +u32 dComIfGp_checkPlayerStatus1(int param_0, u32 flag) { + return g_dComIfG_gameInfo.play.checkPlayerStatus(param_0, 1, flag); +} + +void dComIfGp_setPlayerStatus0(int param_0, u32 flag) { + g_dComIfG_gameInfo.play.setPlayerStatus(param_0, 0, flag); +} + +void dComIfGp_setPlayerStatus1(int param_0, u32 flag) { + g_dComIfG_gameInfo.play.setPlayerStatus(param_0, 1, flag); +} + +void dComIfGp_clearPlayerStatus0(int param_0, u32 flag) { + g_dComIfG_gameInfo.play.clearPlayerStatus(param_0, 0, flag); +} + +void dComIfGp_clearPlayerStatus1(int param_0, u32 flag) { + g_dComIfG_gameInfo.play.clearPlayerStatus(param_0, 1, flag); +} + +void dComIfGp_setCurrentWindow(dDlst_window_c* i_window) { + g_dComIfG_gameInfo.play.setCurrentWindow(i_window); +} + +void dComIfGp_setCurrentView(view_class* i_view) { + g_dComIfG_gameInfo.play.setCurrentView(i_view); +} + +void dComIfGp_setCurrentViewport(view_port_class* i_viewport) { + g_dComIfG_gameInfo.play.setCurrentViewport(i_viewport); +} + +J2DGrafContext* dComIfGp_getCurrentGrafPort() { + return g_dComIfG_gameInfo.play.getCurrentGrafPort(); +} + +void dComIfGp_setCurrentGrafPort(J2DOrthoGraph* i_graf) { + g_dComIfG_gameInfo.play.setCurrentGrafPort(i_graf); +} + +void* dComIfGp_getItemTable() { + return g_dComIfG_gameInfo.play.getItemTable(); +} + +void dComIfGp_setItemTable(void* data) { + g_dComIfG_gameInfo.play.setItemTable(data); +} + +char* dComIfGp_getLastPlayStageName() { + return g_dComIfG_gameInfo.play.getLastPlayStageName(); +} + +void dComIfGp_setLastPlayStageName(char* name) { + g_dComIfG_gameInfo.play.setLastPlayStageName(name); +} + +void dComIfGp_init() { + g_dComIfG_gameInfo.play.init(); +} + +void dComIfGp_itemDataInit() { + g_dComIfG_gameInfo.play.itemInit(); +} + +void dComIfGp_setItemBombNumCount(u8 i_item, s16 count) { + g_dComIfG_gameInfo.play.setItemBombNumCount(i_item, count); +} + +s16 dComIfGp_getItemBombNumCount(u8 i_no) { + return g_dComIfG_gameInfo.play.getItemBombNumCount(i_no); +} + +void dComIfGp_clearItemBombNumCount(u8 i_no) { + g_dComIfG_gameInfo.play.clearItemBombNumCount(i_no); +} + +s16 dComIfGp_getItemMaxBombNumCount() { + return g_dComIfG_gameInfo.play.getItemMaxBombNumCount(dItemNo_NORMAL_BOMB_e); +} + +void dComIfGp_setNowVibration(u8 status) { + g_dComIfG_gameInfo.play.setNowVibration(status); +} + +u32 dComIfGp_getNowVibration() { + return g_dComIfG_gameInfo.play.getNowVibration(); +} + +void dComIfGp_particle_create() { + g_dComIfG_gameInfo.play.createParticle(); +} + +void dComIfGp_createSimpleModel() { + g_dComIfG_gameInfo.play.createSimpleModel(); +} + +void dComIfGp_deleteSimpleModel() { + g_dComIfG_gameInfo.play.deleteSimpleModel(); +} + +void dComIfGp_drawSimpleModel() { + g_dComIfG_gameInfo.play.drawSimpleModel(); +} + +int dComIfGp_addSimpleModel(J3DModelData* i_modelData, int roomNo, u8 i_drawBG) { + return g_dComIfG_gameInfo.play.addSimpleModel(i_modelData, roomNo, i_drawBG); +} + +void dComIfGp_removeSimpleModel(J3DModelData* i_modelData, int roomNo) { + g_dComIfG_gameInfo.play.removeSimpleModel(i_modelData, roomNo); +} + +void dComIfGp_entrySimpleModel(J3DModel* model, int roomNo) { + g_dComIfG_gameInfo.play.entrySimpleModel(model, roomNo); +} + +void dComIfG_ct() { + g_dComIfG_gameInfo.ct(); +} + +dBgS& dComIfG_Bgsp() { + return g_dComIfG_gameInfo.play.mBgs; +} + +dCcS* dComIfG_Ccsp() { + return &g_dComIfG_gameInfo.play.mCcs; +} + +dCcS& dComIfG_Ccsp2() { + return g_dComIfG_gameInfo.play.mCcs; +} + +void dComIfG_setTimerNowTimeMs(int time) { + g_dComIfG_gameInfo.play.setTimerNowTimeMs(time); +} + +int dComIfG_getTimerNowTimeMs() { + return g_dComIfG_gameInfo.play.getTimerNowTimeMs(); +} + +void dComIfG_setTimerLimitTimeMs(int i_time) { + g_dComIfG_gameInfo.play.setTimerLimitTimeMs(i_time); +} + +int dComIfG_getTimerLimitTimeMs() { + return g_dComIfG_gameInfo.play.getTimerLimitTimeMs(); +} + +void dComIfG_setTimerMode(int mode) { + return g_dComIfG_gameInfo.play.setTimerMode(mode); +} + +int dComIfG_getTimerMode() { + return g_dComIfG_gameInfo.play.getTimerMode(); +} + +void dComIfG_setTimerType(u8 i_type) { + g_dComIfG_gameInfo.play.setTimerType(i_type); +} + +u8 dComIfG_getTimerType() { + return g_dComIfG_gameInfo.play.getTimerType(); +} + +void dComIfG_setTimerPtr(dTimer_c* i_ptr) { + g_dComIfG_gameInfo.play.setTimerPtr(i_ptr); +} + +dTimer_c* dComIfG_getTimerPtr() { + return g_dComIfG_gameInfo.play.getTimerPtr(); +} + +/** + * Attempts to add a new Object Resource Archive (*.arc) into the Resource Control. + * @param i_arcName Name of archive to be added + * @param i_mountDirection The direction to mount the archive. mDoDvd_MOUNT_DIRECTION_HEAD or + * mDoDvd_MOUNT_DIRECTION_TAIL + * @param i_heap Pointer to heap to load resources into + * @return TRUE if successful, FALSE otherwise + */ +int dComIfG_setObjectRes(const char* i_arcName, u8 i_mountDirection, JKRHeap* i_heap) { + return g_dComIfG_gameInfo.mResControl.setObjectRes(i_arcName, i_mountDirection, i_heap); +} + +int dComIfG_setObjectRes( + const char* i_arcName, void* i_archiveRes, u32 i_bufferSize, JKRHeap* i_heap) { + UNUSED(i_heap); + return g_dComIfG_gameInfo.mResControl.setObjectRes(i_arcName, i_archiveRes, i_bufferSize, NULL); +} + +/** + * Attempts to add a new Stage Resource Archive (*.arc) into the Resource Control. + * @param i_arcName Name of archive to be added + * @param i_heap Pointer to heap to load resources into + * @return TRUE if successful, FALSE otherwise + */ +int dComIfG_setStageRes(const char* i_arcName, JKRHeap* i_heap) { + return g_dComIfG_gameInfo.mResControl.setStageRes(i_arcName, i_heap); +} + +int dComIfG_syncObjectRes(const char* i_arcName) { + return g_dComIfG_gameInfo.mResControl.syncObjectRes(i_arcName); +} + +int dComIfG_syncStageRes(const char* i_arcName) { + return g_dComIfG_gameInfo.mResControl.syncStageRes(i_arcName); +} + +int dComIfG_deleteObjectResMain(const char* i_arcName) { + return g_dComIfG_gameInfo.mResControl.deleteObjectRes(i_arcName); +} + +int dComIfG_deleteStageRes(const char* i_arcName) { + return g_dComIfG_gameInfo.mResControl.deleteStageRes(i_arcName); +} + +void* dComIfG_getStageRes(const char* i_arcName, const char* i_resName) { + return g_dComIfG_gameInfo.mResControl.getStageRes(i_arcName, i_resName); +} + +void* dComIfG_getObjectRes(const char* i_arcName, const char* i_resName) { + return g_dComIfG_gameInfo.mResControl.getObjectRes(i_arcName, i_resName); +} + +void* dComIfG_getObjectRes(const char* i_arcName, int i_index) { + return g_dComIfG_gameInfo.mResControl.getObjectRes(i_arcName, i_index); +} + +void dComIfG_dumpResControl() { + g_dComIfG_gameInfo.mResControl.dump(); +} + +dRes_info_c* dComIfG_getObjectResInfo(const char* i_arcName) { + return g_dComIfG_gameInfo.mResControl.getObjectResInfo(i_arcName); +} + +dRes_info_c* dComIfG_getStageResInfo(const char* i_arcName) { + return g_dComIfG_gameInfo.mResControl.getStageResInfo(i_arcName); +} + +int dComIfG_syncAllObjectRes() { + return g_dComIfG_gameInfo.mResControl.syncAllObjectRes(); +} + +void* dComIfG_getObjectIDRes(const char* i_arcName, u16 i_resID) { + return g_dComIfG_gameInfo.mResControl.getObjectIDRes(i_arcName, i_resID); +} + +int dComIfG_getObjctResName2Index(const char* i_arcName, const char* i_resName) { + return g_dComIfG_gameInfo.mResControl.getObjectResName2Index(i_arcName, i_resName); +} + +u8 dComIfG_getBrightness() { + return g_dComIfG_gameInfo.mFadeBrightness; +} + +void dComIfG_setBrightness(u8 brightness) { + g_dComIfG_gameInfo.mFadeBrightness = brightness; +} + +BOOL dComIfG_isDebugMode() { + return g_dComIfG_gameInfo.mIsDebugMode; +} + +u32 dComIfG_getTrigB(u32 i_padNo) { + return mDoCPd_c::getTrig(i_padNo) & PAD_BUTTON_B; +} + +#if DEBUG +u32 dComIfG_getObjectAllSize() { + return g_dComIfG_gameInfo.mResControl.getObjectAllSize(); +} + +u32 dComIfG_getStageAllSize() { + return g_dComIfG_gameInfo.mResControl.getStageAllSize(); +} + +u32 dComIfG_getObjectSize(const char* i_arcName) { + return g_dComIfG_gameInfo.mResControl.getObjectSize(i_arcName); +} + +u32 dComIfG_getStageSize(const char* i_arcName) { + return g_dComIfG_gameInfo.mResControl.getStageSize(i_arcName); +} + +void dComIfG_initStopwatch() { + OSInitStopwatch(&g_dComIfG_gameInfo.mStopwatch, "dComIfG"); +} +#endif + +int dComIfGd_setRealShadow(u32 param_0, s8 param_1, J3DModel* param_2, cXyz* param_3, f32 param_4, + f32 param_5, dKy_tevstr_c* param_6) { + return g_dComIfG_gameInfo.drawlist.setRealShadow( + param_0, param_1, param_2, param_3, param_4, param_5, param_6); +} + +int dComIfGd_setSimpleShadow( + cXyz* pos, f32 param_1, f32 param_2, cXyz* param_3, s16 angle, f32 param_5, TGXTexObj* tex) { + return g_dComIfG_gameInfo.drawlist.setSimpleShadow( + pos, param_1, param_2, param_3, angle, param_5, tex); +} + +bool dComIfGd_addRealShadow(u32 key, J3DModel* model) { + return g_dComIfG_gameInfo.drawlist.addRealShadow(key, model); +} + +void dComIfGd_drawListItem3d() { + g_dComIfG_gameInfo.drawlist.drawOpaListItem3d(); + g_dComIfG_gameInfo.drawlist.drawXluListItem3d(); +} + +#if VERSION > VERSION_GCN_JPN +void dComIfGd_drawListCursor() { + g_dComIfG_gameInfo.drawlist.drawOpaListCursor(); + g_dComIfG_gameInfo.drawlist.drawXluListCursor(); +} +#endif + +void dComIfGd_reset() { + g_dComIfG_gameInfo.drawlist.reset(); +} + +void dComIfGd_set2DOpa(dDlst_base_c* dlst) { + g_dComIfG_gameInfo.drawlist.set2DOpa(dlst); +} + +void dComIfGd_set2DXlu(dDlst_base_c* dlst) { + g_dComIfG_gameInfo.drawlist.set2DXlu(dlst); +} + +void dComIfGd_set2DOpaTop(dDlst_base_c* dlst) { + g_dComIfG_gameInfo.drawlist.set2DOpaTop(dlst); +} + +void dComIfGd_setCopy2D(dDlst_base_c* dlst) { + g_dComIfG_gameInfo.drawlist.setCopy2D(dlst); +} + +view_class* dComIfGd_getView() { + return g_dComIfG_gameInfo.drawlist.getView(); +} + +Mtx44* dComIfGd_getProjViewMtx() { + return &(g_dComIfG_gameInfo.drawlist.getView()->projViewMtx); +} + +MtxP dComIfGd_getInvViewMtx() { + return g_dComIfG_gameInfo.drawlist.getView()->invViewMtx; +} + +view_port_class* dComIfGd_getViewport() { + return g_dComIfG_gameInfo.drawlist.getViewport(); +} + +MtxP dComIfGd_getViewRotMtx() { + return g_dComIfG_gameInfo.drawlist.getView()->viewMtxNoTrans; +} +MtxP dComIfGd_getViewMtx() { + return g_dComIfG_gameInfo.drawlist.getView()->viewMtx; +} + +J3DDrawBuffer* dComIfGd_getListFilter() { + return g_dComIfG_gameInfo.drawlist.getOpaListFilter(); +} + +J3DDrawBuffer* dComIfGd_getOpaListIndScreen() { + return g_dComIfG_gameInfo.drawlist.getOpaListP0(); +} + +J3DDrawBuffer* dComIfGd_getListPacket() { + return g_dComIfG_gameInfo.drawlist.getOpaListPacket(); +} + +void dComIfGd_setListSky() { + g_dComIfG_gameInfo.drawlist.setOpaListSky(); + g_dComIfG_gameInfo.drawlist.setXluListSky(); +} + +void dComIfGd_setListDark() { + g_dComIfG_gameInfo.drawlist.setOpaListDark(); + g_dComIfG_gameInfo.drawlist.setXluListDark(); +} + +void dComIfGd_setListInvisisble() { + g_dComIfG_gameInfo.drawlist.setOpaListInvisible(); + g_dComIfG_gameInfo.drawlist.setXluListInvisible(); +} + +void dComIfGd_setListDarkBG() { + g_dComIfG_gameInfo.drawlist.setOpaListDarkBG(); + g_dComIfG_gameInfo.drawlist.setXluListDarkBG(); +} + +void dComIfGd_setXluListDarkBG() { + g_dComIfG_gameInfo.drawlist.setXluListDarkBG(); +} + +void dComIfGd_setList() { + g_dComIfG_gameInfo.drawlist.setOpaList(); + g_dComIfG_gameInfo.drawlist.setXluList(); +} + +void dComIfGd_setListItem3D() { + g_dComIfG_gameInfo.drawlist.setOpaListItem3D(); + g_dComIfG_gameInfo.drawlist.setXluListItem3D(); +} + +void dComIfGd_setList3Dlast() { + g_dComIfG_gameInfo.drawlist.setOpaList3Dlast(); + g_dComIfG_gameInfo.drawlist.setXluList3Dlast(); +} + +void dComIfGd_setXluList2DScreen() { + g_dComIfG_gameInfo.drawlist.setXluList2DScreen(); +} + +void dComIfGd_setXluListBG() { + g_dComIfG_gameInfo.drawlist.setXluListBG(); +} + +void dComIfGd_setListBG() { + g_dComIfG_gameInfo.drawlist.setOpaListBG(); + g_dComIfG_gameInfo.drawlist.setXluListBG(); +} + +void dComIfGd_setListIndScreen() { + g_dComIfG_gameInfo.drawlist.setOpaListP0(); + g_dComIfG_gameInfo.drawlist.setXluListP0(); +} + +void dComIfGd_setListMiddle() { + g_dComIfG_gameInfo.drawlist.setOpaListMiddle(); + g_dComIfG_gameInfo.drawlist.setXluListMiddle(); +} + +void dComIfGd_setListZxlu() { + g_dComIfG_gameInfo.drawlist.setOpaListZxlu(); + g_dComIfG_gameInfo.drawlist.setXluListZxlu(); +} + +J3DDrawBuffer* dComIfGd_getOpaList() { + return g_dComIfG_gameInfo.drawlist.getOpaList(); +} + +J3DDrawBuffer* dComIfGd_getOpaListBG() { + return g_dComIfG_gameInfo.drawlist.getOpaListBG(); +} + +J3DDrawBuffer* dComIfGd_getOpaListDark() { + return g_dComIfG_gameInfo.drawlist.getOpaListDark(); +} + +J3DDrawBuffer* dComIfGd_getXluListBG() { + return g_dComIfG_gameInfo.drawlist.getXluListBG(); +} + +void dComIfGd_setListFilter() { + g_dComIfG_gameInfo.drawlist.setOpaListFilter(); + g_dComIfG_gameInfo.drawlist.setXluListFilter(); +} + +void dComIfGd_init() { + g_dComIfG_gameInfo.drawlist.init(); +} + +void dComIfGd_peekZ(s16 param_0, s16 param_1, u32* param_2) { + g_dComIfG_gameInfo.drawlist.newPeekZdata(param_0, param_1, param_2); +} + +void dComIfGd_peekZdata() { + g_dComIfG_gameInfo.drawlist.peekZdata(); +} + +void dComIfGd_setView(view_class* view) { + g_dComIfG_gameInfo.drawlist.setView(view); +} + +void dComIfGd_setWindow(dDlst_window_c* window) { + g_dComIfG_gameInfo.drawlist.setWindow(window); +} + +void dComIfGd_setViewport(view_port_class* port) { + g_dComIfG_gameInfo.drawlist.setViewport(port); +} + +void dComIfGd_entryZSortListZxlu(J3DPacket* i_packet, cXyz& param_1) { + ZoneScoped; + g_dComIfG_gameInfo.drawlist.entryZSortListZxlu(i_packet, param_1); +} + +void dComIfGd_entryZSortXluList(J3DPacket* i_packet, cXyz& param_1) { + ZoneScoped; + g_dComIfG_gameInfo.drawlist.entryZSortXluList(i_packet, param_1); +} + +void dComIfGd_drawCopy2D() { + ZoneScoped; + g_dComIfG_gameInfo.drawlist.drawCopy2D(); +} + +void dComIfGd_drawOpaListSky() { + ZoneScoped; + g_dComIfG_gameInfo.drawlist.drawOpaListSky(); +} + +void dComIfGd_drawXluListSky() { + ZoneScoped; + g_dComIfG_gameInfo.drawlist.drawXluListSky(); +} + +void dComIfGd_drawOpaListBG() { + ZoneScoped; + g_dComIfG_gameInfo.drawlist.drawOpaListBG(); +} + +void dComIfGd_drawOpaListDarkBG() { + ZoneScoped; + g_dComIfG_gameInfo.drawlist.drawOpaListDarkBG(); +} + +void dComIfGd_drawOpaListMiddle() { + ZoneScoped; + g_dComIfG_gameInfo.drawlist.drawOpaListMiddle(); +} + +void dComIfGd_drawOpaList() { + ZoneScoped; + g_dComIfG_gameInfo.drawlist.drawOpaList(); +} + +void dComIfGd_drawOpaListDark() { + ZoneScoped; + g_dComIfG_gameInfo.drawlist.drawOpaListDark(); +} + +void dComIfGd_drawOpaListPacket() { + ZoneScoped; + g_dComIfG_gameInfo.drawlist.drawOpaListPacket(); +} + +void dComIfGd_drawXluListBG() { + ZoneScoped; + g_dComIfG_gameInfo.drawlist.drawXluListBG(); +} + +void dComIfGd_drawXluListDarkBG() { + ZoneScoped; + g_dComIfG_gameInfo.drawlist.drawXluListDarkBG(); +} + +void dComIfGd_drawXluList() { + ZoneScoped; + g_dComIfG_gameInfo.drawlist.drawXluList(); +} + +void dComIfGd_drawXluListDark() { + ZoneScoped; + g_dComIfG_gameInfo.drawlist.drawXluListDark(); +} + +void dComIfGd_drawXluListZxlu() { + ZoneScoped; + g_dComIfG_gameInfo.drawlist.drawXluListZxlu(); +} + +void dComIfGd_drawXluList2DScreen() { + ZoneScoped; + g_dComIfG_gameInfo.drawlist.drawXluList2DScreen(); +} + +void dComIfGd_drawOpaList3Dlast() { + ZoneScoped; + g_dComIfG_gameInfo.drawlist.drawOpaList3Dlast(); +} + +void dComIfGd_draw2DOpa() { + ZoneScoped; + g_dComIfG_gameInfo.drawlist.draw2DOpa(); +} + +void dComIfGd_draw2DOpaTop() { + ZoneScoped; + g_dComIfG_gameInfo.drawlist.draw2DOpaTop(); +} + +void dComIfGd_draw2DXlu() { + ZoneScoped; + g_dComIfG_gameInfo.drawlist.draw2DXlu(); +} + +void dComIfGd_drawOpaListFilter() { + ZoneScoped; + g_dComIfG_gameInfo.drawlist.drawOpaListFilter(); +} + +void dComIfGd_drawIndScreen() { + ZoneScoped; + g_dComIfG_gameInfo.drawlist.drawOpaListP0(); +} + +void dComIfGd_drawListZxlu() { + ZoneScoped; + g_dComIfG_gameInfo.drawlist.drawXluListZxlu(); +} + +void dComIfGd_drawShadow(Mtx param_0) { + ZoneScoped; + g_dComIfG_gameInfo.drawlist.drawShadow(param_0); +} + +void dComIfGd_imageDrawShadow(Mtx param_0) { + ZoneScoped; + g_dComIfG_gameInfo.drawlist.imageDrawShadow(param_0); +} + +void dComIfGd_set3DlineMat(mDoExt_3DlineMat_c* param_0) { + g_dComIfG_gameInfo.drawlist.set3DlineMat(param_0); +} + +void dComIfGd_set3DlineMatDark(mDoExt_3DlineMat_c* param_0) { + g_dComIfG_gameInfo.drawlist.set3DlineMatDark(param_0); +} + +#if PLATFORM_WII || VERSION == VERSION_SHIELD_DEBUG +void dComIfGd_setListCursor() { + g_dComIfG_gameInfo.drawlist.setOpaListCursor(); + g_dComIfG_gameInfo.drawlist.setXluListCursor(); +} +#endif + void dComIfGd_drawXluListInvisible() { ZoneScoped; if (!dusk::getSettings().game.disableWaterRefraction) { diff --git a/src/d/d_file_select.cpp b/src/d/d_file_select.cpp index e075e2b8a6..4b23d3ded9 100644 --- a/src/d/d_file_select.cpp +++ b/src/d/d_file_select.cpp @@ -23,6 +23,7 @@ #include "m_Do/m_Do_graphic.h" #include +#include "dusk/utilities.hpp" #include "dusk/version.hpp" #if TARGET_PC @@ -4153,11 +4154,43 @@ bool dFile_select_c::yesnoWakuAlpahAnm(u8 param_1) { } #if TARGET_PC + +static dusk::utils::PaneCache mSelDtPanes[] = { + {MULTI_CHAR('tate_n0'), 0.0f, 0.0f, false}, + {MULTI_CHAR('tate_n1'), 0.0f, 0.0f, false}, + {MULTI_CHAR('ken_n0'), 0.0f, 0.0f, false}, + {MULTI_CHAR('ken_n1'), 0.0f, 0.0f, false}, + {MULTI_CHAR('fuku_n0'), 0.0f, 0.0f, false}, + {MULTI_CHAR('fuku_n1'), 0.0f, 0.0f, false}, + {MULTI_CHAR('fuku_n2'), 0.0f, 0.0f, false}, + {MULTI_CHAR('gray_n'), 0.0f, 0.0f, false}, + {MULTI_CHAR('b_base'), 0.0f, 0.0f, false}, + {MULTI_CHAR('b_base1'), 0.0f, 0.0f, false}, +}; + +static dusk::utils::PaneCache fileSelPanes[] = { + {MULTI_CHAR('w_uzu00'), 0.0f, 0.0f, false}, + {MULTI_CHAR('w_uzu01'), 0.0f, 0.0f, false}, + {MULTI_CHAR('w_uzu02'), 0.0f, 0.0f, false}, + {MULTI_CHAR('w_uzu03'), 0.0f, 0.0f, false}, + {MULTI_CHAR('w_uzu04'), 0.0f, 0.0f, false}, + {MULTI_CHAR('w_uzu05'), 0.0f, 0.0f, false}, + {MULTI_CHAR('w_uzu06'), 0.0f, 0.0f, false}, + {MULTI_CHAR('w_uzu07'), 0.0f, 0.0f, false}, + {MULTI_CHAR('w_uzu08'), 0.0f, 0.0f, false}, + {MULTI_CHAR('w_uzu09'), 0.0f, 0.0f, false}, + {MULTI_CHAR('w_er_msg'), 0.0f, 0.0f, false}, + {MULTI_CHAR('w_er_msE'), 0.0f, 0.0f, false}, + {MULTI_CHAR('w_er_msR'), 0.0f, 0.0f, false}, + {MULTI_CHAR('er_for0'), 0.0f, 0.0f, false}, + {MULTI_CHAR('er_for1'), 0.0f, 0.0f, false}, +}; + void dFile_select_c::fileSelectWide() { static bool cachedPanes = false; // Get pre-scale values for each pane if (!cachedPanes) { - for (PaneCache& entry : mSelDtPanes) { + for (dusk::utils::PaneCache& entry : mSelDtPanes) { J2DPane* pane = mSelDt.ScrDt->search(entry.tag); if (!entry.cached) { entry.origTransX = pane->getTranslateX(); @@ -4165,7 +4198,7 @@ void dFile_select_c::fileSelectWide() { entry.cached = true; } } - for (PaneCache& entry : fileSelPanes) { + for (dusk::utils::PaneCache& entry : fileSelPanes) { J2DPane* pane = fileSel.Scr->search(entry.tag); if (!entry.cached) { entry.origTransX = pane->getTranslateX(); @@ -4179,13 +4212,13 @@ void dFile_select_c::fileSelectWide() { // Reset all panes mSelDt.ScrDt->scale(1.0f, 1.0f); mSelDt.ScrDt->translate(0.0f, 0.0f); - for (PaneCache& entry : mSelDtPanes) { + for (dusk::utils::PaneCache& entry : mSelDtPanes) { J2DPane* pane = mSelDt.ScrDt->search(entry.tag); pane->setBasePosition(J2DBasePosition_4); pane->scale(1.0f, 1.0f); pane->translate(entry.origTransX, entry.origTransY); } - for (PaneCache& entry : fileSelPanes) { + for (dusk::utils::PaneCache& entry : fileSelPanes) { J2DPane* pane = fileSel.Scr->search(entry.tag); pane->setBasePosition(J2DBasePosition_4); pane->scale(1.0f, 1.0f); @@ -4257,7 +4290,7 @@ void dFile_select_c::fileSelectWide() { mSelDt.ScrDt->search(MULTI_CHAR('fuku_n2'))->scale(mDoGph_gInf_c::hudAspectScaleDown, 1.0f); // Spirals & Memory Card Text - for (PaneCache& entry : fileSelPanes) { + for (dusk::utils::PaneCache& entry : fileSelPanes) { J2DPane* pane = fileSel.Scr->search(entry.tag); pane->scale(mDoGph_gInf_c::hudAspectScaleDown, 1.0f); } @@ -4283,7 +4316,7 @@ void dFile_select_c::fileSelectWide() { const f32 wideShiftFactor = mSelDt.ScrDt->search(MULTI_CHAR('gray_n'))->getTranslateX() * (wideScaleFactor - mDoGph_gInf_c::hudAspectScaleDown); const f32 ultraShiftFactor = mSelDt.ScrDt->search(MULTI_CHAR('gray_n'))->getTranslateX() * (ultraScaleFactor - mDoGph_gInf_c::hudAspectScaleDown); - for (PaneCache& entry : mSelDtPanes) { + for (dusk::utils::PaneCache& entry : mSelDtPanes) { const size_t index = &entry - mSelDtPanes; J2DPane* pane = mSelDt.ScrDt->search(entry.tag); pane->setBasePosition(J2DBasePosition_0); @@ -4351,7 +4384,7 @@ void dFile_select_c::fileSelectWide() { } // Spirals & Memory Card Text - for (PaneCache& entry : fileSelPanes) { + for (dusk::utils::PaneCache& entry : fileSelPanes) { J2DPane* pane = fileSel.Scr->search(entry.tag); pane->scale(mDoGph_gInf_c::hudAspectScaleDown, 1.0f); } diff --git a/src/d/d_item.cpp b/src/d/d_item.cpp index 5484bd584a..a388ef155c 100644 --- a/src/d/d_item.cpp +++ b/src/d/d_item.cpp @@ -741,8 +741,12 @@ void item_func_ARMOR() {} void item_func_WEAR_ZORA() {} void item_func_MAGIC_LV1() { +#if TARGET_PC + dComIfGs_onEventBit(0xD04); +#else dComIfGp_setItemMagicCount(16); dComIfGp_setItemMaxMagicCount(16); +#endif } void item_func_DUNGEON_EXIT_2() { @@ -1152,7 +1156,15 @@ void item_func_M_MAYFLY() {} void item_func_F_MAYFLY() {} -void item_func_POU_SPIRIT() {} +void item_func_POU_SPIRIT() { +#if TARGET_PC + dComIfGs_addPohSpiritNum(); + if (dComIfGs_getPohSpiritNum() == 20) { + /* dSv_event_flag_c::F_0457 - Castle Town - Revived cat */ + dComIfGs_onEventBit(dSv_event_flag_c::saveBitLabels[457]); + } +#endif +} void item_func_ANCIENT_DOCUMENT() { dComIfGs_setItem(SLOT_22, dItemNo_ANCIENT_DOCUMENT_e); @@ -1411,7 +1423,11 @@ int item_getcheck_func_WEAR_ZORA() { } int item_getcheck_func_MAGIC_LV1() { +#if TARGET_PC + return dComIfGs_isEventBit(0xD04); +#else return -1; +#endif } int item_getcheck_func_DUNGEON_EXIT_2() { diff --git a/src/d/d_item_data.cpp b/src/d/d_item_data.cpp index 9ff4321aa5..a9aaab12d3 100644 --- a/src/d/d_item_data.cpp +++ b/src/d/d_item_data.cpp @@ -53,7 +53,11 @@ DUSK_GAME_DATA dItem_itemResource dItem_data::item_resource[] = { {"F_gD_rupy", 0x0004,-0x0001,-0x0001, 0x0007,-0x0001, 0x0, -0x1, 0x006B, 0x64, 0x0000}, {"O_gD_marm", 0x0003,-0x0001,-0x0001,-0x0001,-0x0001, -0x1, -0x1, 0x0041, 0x64, 0x01A9}, {"O_gD_zora", 0x0003,-0x0001,-0x0001,-0x0001,-0x0001, -0x1, -0x1, 0x004D, 0x64, 0x01AA}, +#if TARGET_PC + {"O_gD_Injy", 0x0003,-0x0001,-0x0001,-0x0001,-0x0001, -0x1, -0x1, 0x002E, 0x64, 0x0000}, +#else {"O_gD_Injy", 0x0003,-0x0001,-0x0001,-0x0001,-0x0001, -0x1, -0x1, 0x002D, 0x64, 0x0000}, +#endif {"O_gD_TKS", 0x0008,-0x0001, 0x0005,-0x0001,-0x0001, -0x1, -0x1, 0x0028, 0x64, 0x0000}, {"O_gD_puL2", 0x0003,-0x0001,-0x0001,-0x0001,-0x0001, -0x1, -0x1, 0x0047, 0x64, 0x0000}, {"O_gD_puL2", 0x0003,-0x0001,-0x0001,-0x0001,-0x0001, -0x1, -0x1, 0x0048, 0x64, 0x0000}, diff --git a/src/d/d_menu_collect.cpp b/src/d/d_menu_collect.cpp index 28f964ec10..32c0a360c2 100644 --- a/src/d/d_menu_collect.cpp +++ b/src/d/d_menu_collect.cpp @@ -39,6 +39,7 @@ #if TARGET_PC #include "dusk/menu_pointer.h" +#include "dusk/utilities.hpp" #endif typedef void (dMenu_Collect2D_c::*initFunc)(); @@ -101,11 +102,44 @@ dMenu_Collect2D_c::~dMenu_Collect2D_c() { } #if TARGET_PC +static dusk::utils::PaneCache mpScreenPanes[] = { + {MULTI_CHAR('sa_tex_n'), 0.0f, 0.0f, false}, + {MULTI_CHAR('op_tex_n'), 0.0f, 0.0f, false}, + {MULTI_CHAR('heart_n'), 0.0f, 0.0f, false}, + {MULTI_CHAR('wolf_n'), 0.0f, 0.0f, false}, + {MULTI_CHAR('item_0_n'), 0.0f, 0.0f, false}, + {MULTI_CHAR('item_1_n'), 0.0f, 0.0f, false}, + {MULTI_CHAR('item_2_n'), 0.0f, 0.0f, false}, + {MULTI_CHAR('fish_3_n'), 0.0f, 0.0f, false}, + {MULTI_CHAR('lett_4_n'), 0.0f, 0.0f, false}, + {MULTI_CHAR('maki_5_n'), 0.0f, 0.0f, false}, + {MULTI_CHAR('fuku_n0'), 0.0f, 0.0f, false}, + {MULTI_CHAR('fuku_n1'), 0.0f, 0.0f, false}, + {MULTI_CHAR('fuku_n2'), 0.0f, 0.0f, false}, + {MULTI_CHAR('tate_n0'), 0.0f, 0.0f, false}, + {MULTI_CHAR('tate_n1'), 0.0f, 0.0f, false}, + {MULTI_CHAR('ken_n0'), 0.0f, 0.0f, false}, + {MULTI_CHAR('ken_n1'), 0.0f, 0.0f, false}, + {MULTI_CHAR('kabu_6n'), 0.0f, 0.0f, false}, + {MULTI_CHAR('t_t00'), 0.0f, 0.0f, false}, + {MULTI_CHAR('f_t00'), 0.0f, 0.0f, false}, + {MULTI_CHAR('itemn_n'), 0.0f, 0.0f, false}, + {MULTI_CHAR('infotxtn'), 0.0f, 0.0f, false}, + {MULTI_CHAR('sa_op_n'), 0.0f, 0.0f, false}, + {MULTI_CHAR('title_n'), 0.0f, 0.0f, false}, + {MULTI_CHAR('menu_n'), 0.0f, 0.0f, false}, + {MULTI_CHAR('w_er_n'), 0.0f, 0.0f, false}, + {MULTI_CHAR('center_n'), 0.0f, 0.0f, false}, + {MULTI_CHAR('info_n'), 0.0f, 0.0f, false}, + {MULTI_CHAR('lavel_n'), 0.0f, 0.0f, false}, + {MULTI_CHAR('modelbgn'), 0.0f, 0.0f, false}, +}; + void dMenu_Collect2D_c::menuCollectWide() { static bool cachedPanes = false; // Get pre-scale values for each pane if (!cachedPanes) { - for (PaneCache& entry : mpScreenPanes) { + for (dusk::utils::PaneCache& entry : mpScreenPanes) { J2DPane* pane = mpScreen->search(entry.tag); if (!entry.cached) { entry.origTransX = pane->getTranslateX(); @@ -119,7 +153,7 @@ void dMenu_Collect2D_c::menuCollectWide() { // Reset all panes mpScreen->scale(1.0f, 1.0f); mpScreen->translate(0.0f, 0.0f); - for (PaneCache& entry : mpScreenPanes) { + for (dusk::utils::PaneCache& entry : mpScreenPanes) { J2DPane* pane = mpScreen->search(entry.tag); pane->scale(1.0f, 1.0f); pane->translate(entry.origTransX, entry.origTransY); diff --git a/src/d/d_meter2_info.cpp b/src/d/d_meter2_info.cpp index 4e55a330f9..15569a72d8 100644 --- a/src/d/d_meter2_info.cpp +++ b/src/d/d_meter2_info.cpp @@ -1900,3 +1900,542 @@ void dMeter2Info_set2DVibrationT() {} void dMeter2Info_set2DVibration() {} void dMeter2Info_set2DVibrationM() {} + +#if TARGET_PC +void dMeter2Info_Initialize() { + g_meter2_info.init(); +} + +dMeterMap_c* dMeter2Info_getMeterMapClass() { + return g_meter2_info.getMeterMapClass(); +} + +dMw_c* dMeter2Info_getMenuWindowClass() { + return g_meter2_info.getMenuWindowClass(); +} + +void dMeter2Info_setWindowStatus(u8 i_status) { + g_meter2_info.setWindowStatus(i_status); +} + +CPaneMgr* dMeter2Info_getMeterItemPanePtr(s32 i_idx) { + return g_meter2_info.getMeterItemPanePtr(i_idx); +} + +void dMeter2Info_getString(u32 i_stringID, TEXT_SPAN o_string, JMSMesgEntry_c* i_msgEntry) { + g_meter2_info.getString(i_stringID, o_string, i_msgEntry); +} + +void dMeter2Info_getStringKanji(u32 i_stringID, TEXT_SPAN o_string, JMSMesgEntry_c* i_msgEntry) { + g_meter2_info.getStringKanji(i_stringID, o_string, i_msgEntry); +} + +void dMeter2Info_getStringKana(u32 i_stringID, TEXT_SPAN o_string, JMSMesgEntry_c* i_msgEntry) { + g_meter2_info.getStringKana(i_stringID, o_string, i_msgEntry); +} + +f32 dMeter2Info_getStringLength(JUTFont* i_font, f32 param_2, f32 param_3, char* i_string) { + return g_meter2_info.getStringLength(i_font, param_2, param_3, i_string); +} + +f32 dMeter2Info_getStringLength(J2DTextBox* i_textbox, char* i_string) { + return g_meter2_info.getStringLength(i_textbox, i_string); +} + +void dMeter2Info_setHotSpringTimer(u8 i_slotNo) { + g_meter2_info.setHotSpringTimer(i_slotNo); +} + +u16 dMeter2Info_getOilGaugeBackUp() { + return g_meter2_info.getOilGaugeBackUp(); +} + +void dMeter2Info_setOilGaugeBackUp(u16 param_1) { + g_meter2_info.setOilGaugeBackUp(param_1); +} + +void dMeter2Info_setSaveStageName(const char* i_stageName) { + g_meter2_info.setSaveStageName(i_stageName); +} + +u8 dMeter2Info_getInsectSelectType() { + return g_meter2_info.getInsectSelectType(); +} + +void dMeter2Info_setInsectSelectType(u8 i_type) { + g_meter2_info.setInsectSelectType(i_type); +} + +u8 dMeter2Info_getWarpStatus() { + return g_meter2_info.getWarpStatus(); +} + +void dMeter2Info_setWarpStatus(u8 i_status) { + return g_meter2_info.setWarpStatus(i_status); +} + +int dMeter2Info_readItemTexture(u8 i_itemNo, void* i_texBuf1, J2DPicture* i_pic1, void* i_texBuf2, + J2DPicture* i_pic2, void* i_texBuf3, J2DPicture* i_pic3, void* i_texBuf4, J2DPicture* i_pic4, + int param_9) { + return g_meter2_info.readItemTexture(i_itemNo, i_texBuf1, i_pic1, i_texBuf2, i_pic2, i_texBuf3, + i_pic3, i_texBuf4, i_pic4, param_9); +} + +void dMeter2Info_setItemColor( + u8 i_itemNo, J2DPicture* i_pic1, J2DPicture* i_pic2, J2DPicture* i_pic3, J2DPicture* i_pic4) { + g_meter2_info.setItemColor(i_itemNo, i_pic1, i_pic2, i_pic3, i_pic4); +} + +u8 dMeter2Info_getWarpRoomNo() { + return g_meter2_info.getWarpRoomNo(); +} + +u8 dMeter2Info_getWarpPlayerNo() { + return g_meter2_info.getWarpPlayerNo(); +} + +cXyz& dMeter2Info_getWarpPos() { + return g_meter2_info.getWarpPos(); +} + +const char* dMeter2Info_getWarpStageName() { + return g_meter2_info.getWarpStageName(); +} + +void dMeter2Info_setNowCount(u8 i_count) { + g_meter2_info.setNowCount(i_count); +} + +void dMeter2Info_setMaxCount(u8 i_count) { + g_meter2_info.setMaxCount(i_count); +} + +BOOL dMeter2Info_isDirectUseItem(int param_0) { + return g_meter2_info.isDirectUseItem(param_0); +} + +bool dMeter2Info_isUseButton(int i_buttonBit) { + return g_meter2_info.isUseButton(i_buttonBit); +} + +void dMeter2Info_setMeterMapClass(dMeterMap_c* i_map) { + g_meter2_info.setMeterMapClass(i_map); +} + +void dMeter2Info_decHotSpringTimer() { + g_meter2_info.decHotSpringTimer(); +} + +void dMeter2Info_allUseButton() { + g_meter2_info.allUseButton(); +} + +void dMeter2Info_offUseButton(int i_buttonBit) { + g_meter2_info.offUseButton(i_buttonBit); +} + +void dMeter2Info_resetGameStatus() { + g_meter2_info.resetGameStatus(); +} + +void dMeter2Info_onGameStatus(int i_status) { + g_meter2_info.onGameStatus(i_status); +} + +void dMeter2Info_setMapStatus(u8 i_status) { + g_meter2_info.setMapStatus(i_status); +} + +u8 dMeter2Info_getMapStatus() { + return g_meter2_info.getMapStatus(); +} + +void dMeter2Info_setPauseStatus(u8 i_status) { + g_meter2_info.setPauseStatus(i_status); +} + +void dMeter2Info_resetPauseStatus() { + g_meter2_info.resetPauseStatus(); +} + +u8 dMeter2Info_getPauseStatus() { + return g_meter2_info.getPauseStatus(); +} + +bool dMeter2Info_isGameStatus(int i_status) { + return g_meter2_info.isGameStatus(i_status); +} + +bool dMeter2Info_isTouchKeyCheck(int i_status) { + return g_meter2_info.isTouchKeyCheck(i_status); +} + +void dMeter2Info_setMapKeyDirection(u16 i_direction) { + g_meter2_info.setMapKeyDirection(i_direction); +} + +bool dMeter2Info_isSub2DStatus(int i_flag) { + return g_meter2_info.isSub2DStatus(i_flag); +} + +void dMeter2Info_offMenuInForce(int i_flag) { + g_meter2_info.offMenuInForce(i_flag); +} + +bool dMeter2Info_isMenuInForce(int i_flag) { + return g_meter2_info.isMenuInForce(i_flag); +} + +void dMeter2Info_setMenuWindowClass(dMw_c* i_menu) { + g_meter2_info.setMenuWindowClass(i_menu); +} + +void dMeter2Info_resetWarpStatus() { + g_meter2_info.resetWarpStatus(); +} + +u16 dMeter2Info_getMapKeyDirection() { + return g_meter2_info.getMapKeyDirection(); +} + +u8 dMeter2Info_getWindowStatus() { + return g_meter2_info.getWindowStatus(); +} + +void dMeter2Info_setMsgResource(void* i_res) { + g_meter2_info.setMsgResource(i_res); +} + +void dMeter2Info_setStageMsgResource(void* i_res) { + g_meter2_info.setStageMsgResource(i_res); +} + +void dMeter2Info_setMsgUnitResource(void* i_res) { + g_meter2_info.setMsgUnitResource(i_res); +} + +void* dMeter2Info_getMsgResource() { + return g_meter2_info.getMsgResource(); +} + +void* dMeter2Info_getStageMsgResource() { + return g_meter2_info.getStageMsgResource(); +} + +void* dMeter2Info_getMsgUnitResource() { + return g_meter2_info.getMsgUnitResource(); +} + +u8 dMeter2Info_getLightDropGetFlag(int i_no) { + return g_meter2_info.getLightDropGetFlag(i_no); +} + +s32 dMeter2Info_getMeterStringType() { + return g_meter2_info.getMeterStringType(); +} + +void dMeter2Info_setMeterClass(dMeter2_c* i_meter) { + g_meter2_info.setMeterClass(i_meter); +} + +void dMeter2Info_onLifeGaugeSE() { + g_meter2_info.onLifeGaugeSE(); +} + +void dMeter2Info_offLifeGaugeSE() { + g_meter2_info.offLifeGaugeSE(); +} + +u8 dMeter2Info_getLifeGaugeSE() { + return g_meter2_info.getLifeGaugeSE(); +} + +const char* dMeter2Info_getSaveStageName() { + return g_meter2_info.getSaveStageName(); +} + +void dMeter2Info_onShopTalkFlag() { + g_meter2_info.onShopTalkFlag(); +} + +void dMeter2Info_setLightDropGetFlag(int i_no, u8 i_flag) { + g_meter2_info.setLightDropGetFlag(i_no, i_flag); +} + +u8 dMeter2Info_getRentalBombBag() { + return g_meter2_info.getRentalBombBag(); +} + +u8 dMeter2Info_getMiniGameItemSetFlag() { + return g_meter2_info.getMiniGameItemSetFlag(); +} + +void dMeter2Info_setMiniGameItem(u8 i_minigameFlag) { + g_meter2_info.setMiniGameItem(i_minigameFlag); +} + +void dMeter2Info_resetMiniGameItem(bool i_saveItem) { + g_meter2_info.resetMiniGameItem(i_saveItem); +} + +void dMeter2Info_setTableMapRegionNo(u8 i_regionNo) { + g_meter2_info.setTableMapRegionNo(i_regionNo); +} + +void dMeter2Info_setGoldWolfMapType(u8 i_mapType) { + g_meter2_info.setGoldWolfMapType(i_mapType); +} + +void dMeter2Info_changeWater(u8 i_slotNo) { + g_meter2_info.changeWater(i_slotNo); +} + +void dMeter2Info_warpInProc() { + g_meter2_info.warpInProc(); +} + +void dMeter2Info_warpOutProc() { + g_meter2_info.warpOutProc(); +} + +dMeter2_c* dMeter2Info_getMeterClass() { + return g_meter2_info.getMeterClass(); +} + +s16 dMeter2Info_getMsgKeyWaitTimer() { + return g_meter2_info.getMsgKeyWaitTimer(); +} + +void dMeter2Info_onDirectUseItem(int param_0) { + g_meter2_info.onDirectUseItem(param_0); +} + +void dMeter2Info_setFloatingFlow(u16 i_flowID, s16 i_msgTimer, bool i_wakuVisible) { + g_meter2_info.setFloatingFlow(i_flowID, i_msgTimer, i_wakuVisible); +} + +u8 dMeter2Info_getGameOverType() { + return g_meter2_info.getGameOverType(); +} + +void dMeter2Info_setGameOverType(u8 i_gameoverType) { + g_meter2_info.setGameOverType(i_gameoverType); +} + +void dMeter2Info_setMsgKeyWaitTimer(s16 i_waitTimer) { + g_meter2_info.setMsgKeyWaitTimer(i_waitTimer); +} + +s32 dMeter2Info_getMsgTimeMs() { + return g_meter2_info.getMsgTimeMs(); +} + +s32 dMeter2Info_getTimeMs() { + return g_meter2_info.getTimeMs(); +} + +void dMeter2Info_setMsgTimeMs(s32 i_msgTime) { + g_meter2_info.setMsgTimeMs(i_msgTime); +} + +void dMeter2Info_setTimeMs(s32 i_time) { + g_meter2_info.setTimeMs(i_time); +} + +u8 dMeter2Info_getNowCount() { + return g_meter2_info.getNowCount(); +} + +u8 dMeter2Info_getMaxCount() { + return g_meter2_info.getMaxCount(); +} + +void dMeter2Info_setScopeZoomPointer(u8 param_0) { + g_meter2_info.setScopeZoomPointer(param_0); +} + +void dMeter2Info_decMsgKeyWaitTimer() { + g_meter2_info.decMsgKeyWaitTimer(); +} + +bool dMeter2Info_isFloatingMessageVisible() { + return g_meter2_info.isFloatingMessageVisible(); +} + +u8 dMeter2Info_getItemExplainWindowStatus() { + return g_meter2_info.getItemExplainWindowStatus(); +} + +void dMeter2Info_setItemExplainWindowStatus(u8 i_value) { + g_meter2_info.setItemExplainWindowStatus(i_value); +} + +void dMeter2Info_resetDirectUseItem() { + g_meter2_info.resetDirectUseItem(); +} + +u16 dMeter2Info_getFloatingFlowID() { + return g_meter2_info.getFloatingFlowID(); +} + +u8 dMeter2Info_getCollectCursorPosX() { + return g_meter2_info.getCollectCursorPosX(); +} + +u8 dMeter2Info_getCollectCursorPosY() { + return g_meter2_info.getCollectCursorPosY(); +} + +void dMeter2Info_setCollectCursorPosXY(u8 x, u8 y) { + g_meter2_info.setCollectCursorPosXY(x, y); +} + +void dMeter2Info_onBlinkButton(int i_flag) { + g_meter2_info.onBlinkButton(i_flag); +} + +bool dMeter2Info_isFloatingMessageWakuVisible() { + return g_meter2_info.isFloatingMessageWakuVisible(); +} + +bool dMeter2Info_isBlinkButton(int i_flag) { + return g_meter2_info.isBlinkButton(i_flag); +} + +void dMeter2Info_resetBlinkButton() { + g_meter2_info.resetBlinkButton(); +} + +void dMeter2Info_resetFloatingMessage() { + g_meter2_info.resetFloatingMessage(); +} + +s16 dMeter2Info_decFloatingMessageTimer() { + return g_meter2_info.decFloatingMessageTimer(); +} + +s16 dMeter2Info_getFloatingMessageTimer() { + return g_meter2_info.getFloatingMessageTimer(); +} + +u16 dMeter2Info_getFloatingMessageID() { + return g_meter2_info.getFloatingMessageID(); +} + +s16 dMeter2Info_getHorseLifeCount() { + return g_meter2_info.getHorseLifeCount(); +} + +void dMeter2Info_setMeterString(s32 i_string) { + g_meter2_info.setMeterString(i_string); +} + +void dMeter2Info_resetMeterString() { + g_meter2_info.resetMeterString(); +} + +void dMeter2Info_setMeterItemPanePtr(int i_no, CPaneMgr* i_pane) { + g_meter2_info.setMeterItemPanePtr(i_no, i_pane); +} + +bool dMeter2Info_isShopTalkFlag() { + return g_meter2_info.isShopTalkFlag(); +} + +void dMeter2Info_setMapDrugFlag(bool i_flag) { + g_meter2_info.setMapDrugFlag(i_flag); +} + +bool dMeter2Info_isTempBit(int i_bit) { + return g_meter2_info.isTempBit(i_bit); +} + +void dMeter2Info_offSub2DStatus(int i_bit) { + g_meter2_info.offSub2DStatus(i_bit); +} + +void dMeter2Info_onSub2DStatus(int i_bit) { + g_meter2_info.onSub2DStatus(i_bit); +} + +void dMeter2Info_set2DWidth(f32 i_width) { + g_meter2_info.set2DWidth(i_width); +} + +void dMeter2Info_set2DHeight(f32 i_height) { + g_meter2_info.set2DHeight(i_height); +} + +void dMeter2Info_set2DPosH(f32 i_posH) { + g_meter2_info.set2DPosH(i_posH); +} + +void dMeter2Info_set2DPosV(f32 i_posV) { + g_meter2_info.set2DPosV(i_posV); +} + +void dMeter2Info_offShopTalkFlag() { + g_meter2_info.offShopTalkFlag(); +} + +void dMeter2Info_onUseButton(int i_button) { + g_meter2_info.onUseButton(i_button); +} + +f32 dMeter2Info_get2DWidth() { + return g_meter2_info.get2DWidth(); +} + +f32 dMeter2Info_get2DHeight() { + return g_meter2_info.get2DHeight(); +} + +void dMeter2Info_setWarpInfo(const char* i_stageName, const cXyz& i_position, s16 i_angle, + u8 i_roomNo, u8 param_4, u8 i_warpPlayerNo) { + g_meter2_info.setWarpInfo(i_stageName, i_position, i_angle, i_roomNo, param_4, i_warpPlayerNo); +} + +u8 dMeter2Info_getTableMapRegionNo() { + return g_meter2_info.getTableMapRegionNo(); +} + +u8 dMeter2Info_getGoldWolfMapType() { + return g_meter2_info.getGoldWolfMapType(); +} + +bool dMeter2Info_isWindowAccept(int param_0) { + return g_meter2_info.isWindowAccept(param_0); +} + +void dMeter2Info_setHorseLifeCount(s16 i_count) { + g_meter2_info.setHorseLifeCount(i_count); +} + +void dMeter2Info_offTempBit(int i_bit) { + g_meter2_info.offTempBit(i_bit); +} + +void dMeter2Info_onTempBit(int i_bit) { + g_meter2_info.onTempBit(i_bit); +} + +void dMeter2Info_setFloatingMessage(u16 i_msgID, s16 i_msgTimer, bool i_wakuVisible) { + g_meter2_info.setFloatingMessage(i_msgID, i_msgTimer, i_wakuVisible); +} + +void dMeter2Info_setMiniGameCount(s8 i_count) { + g_meter2_info.setMiniGameCount(i_count); +} + +void dMeter2Info_onWindowAccept(int param_0) { + g_meter2_info.onWindowAccept(param_0); +} + +void dMeter2Info_offWindowAccept(int param_0) { + g_meter2_info.offWindowAccept(param_0); +} + +void dMeter2Info_onMenuInForce(int param_0) { + g_meter2_info.onMenuInForce(param_0); +} +#endif diff --git a/src/d/d_msg_class.cpp b/src/d/d_msg_class.cpp index 46b246264a..4358d6d5d2 100644 --- a/src/d/d_msg_class.cpp +++ b/src/d/d_msg_class.cpp @@ -16,6 +16,21 @@ #if TARGET_PC #include "dusk/menu_pointer.h" #include "dusk/scope_guard.hpp" +#include "helpers/bits.hpp" + +static bool read_full_color(const void* data, u32 size, u32& ccColor, u32& gcColor) { + if (size == 4) { + ccColor = dusk::read_bits(data); + gcColor = ccColor; + return true; + } + if (size == 8) { + ccColor = dusk::read_bits(data); + gcColor = dusk::read_bits(static_cast(data) + sizeof(ccColor)); + return true; + } + return false; +} #endif #if TARGET_PC @@ -400,6 +415,9 @@ jmessage_tReference::jmessage_tReference() { resetCharCountBuffer(); mNowColorType = 0; mTopColorType = 0; +#if TARGET_PC + resetColors(); +#endif mButtonTagStopFlag = 0; mPageEndCount = 0; mSelectNum = 0; @@ -594,6 +612,13 @@ void jmessage_tReference::pageSend() { if (mNowColorType != mTopColorType) { mTopColorType = mNowColorType; } +#if TARGET_PC + mTopFullColor = mNowFullColor; + if (mNowFullColor) { + mTopCCColor = mNowCCColor; + mTopGCColor = mNowGCColor; + } +#endif mTopWordCount = mNowWordCount; mCharAlpha = 0.0f; @@ -1917,6 +1942,9 @@ void jmessage_tSequenceProcessor::do_begin(void const* pEntry, char const* pszTe pReference->resetCharCnt(); pReference->setNowColorType(0); pReference->setTopColorType(0); +#if TARGET_PC + pReference->resetColors(); +#endif pReference->setNowWordCount(0); pReference->setTopWordCount(0); pReference->setBatchColorFlag(0); @@ -2280,9 +2308,21 @@ bool jmessage_tSequenceProcessor::do_tag(u32 i_tag, void const* i_data, u32 i_si return true; case MSGTAG_GROUP(255): switch (i_tag) { - case MSGTAG_COLOR: + case MSGTAG_COLOR: { +#if TARGET_PC + u32 ccColor; + u32 gcColor; + if (read_full_color(i_data, i_size, ccColor, gcColor)) { + pReference->setFullColor(ccColor, gcColor); + } else if (i_size == 1) { + pReference->clearNowFullColor(); + pReference->setNowColorType(*(u8*)i_data & 0xFF); + } +#else pReference->setNowColorType(*(u8*)i_data & 0xFF); +#endif return true; + } case MSGTAG_SCALE: pReference->setNowTagScale(*(BE(u16)*)i_data & 0xFFFF); return true; @@ -2863,7 +2903,15 @@ void jmessage_tRenderingProcessor::do_begin(void const* pEntry, char const* pszT do_scale(field_0x44); } +#if TARGET_PC + if (pReference->hasTopFullColor()) { + do_fullcolor(pReference->getTopCCColor(), pReference->getTopGCColor()); + } else { + do_color(pReference->getTopColorType()); + } +#else do_color(pReference->getTopColorType()); +#endif pReference->resetDrawLightCount(); do_widthcenter(); @@ -3017,9 +3065,20 @@ bool jmessage_tRenderingProcessor::do_tag(u32 i_tag, void const* i_data, u32 i_s return 1; case MSGTAG_GROUP(255): switch (i_tag) { - case MSGTAG_COLOR: + case MSGTAG_COLOR: { +#if TARGET_PC + u32 ccColor; + u32 gcColor; + if (read_full_color(i_data, i_size, ccColor, gcColor)) { + do_fullcolor(ccColor, gcColor); + } else if (i_size == 1) { + do_color(*(u8*)i_data & 0xFF); + } +#else do_color(*(u8*)i_data & 0xFF); +#endif return 1; + } case MSGTAG_SCALE: field_0x13c = *(BE(u16)*)i_data & 0xFFFF; do_scale(field_0x13c / 100.0f); @@ -3630,6 +3689,18 @@ void jmessage_tRenderingProcessor::do_color(u8 i_colorNo) { do_strcat(buffer, false, false, false); } +#if TARGET_PC +void jmessage_tRenderingProcessor::do_fullcolor(u32 ccColor, u32 gcColor) { + mColorNo = 0xFF; + mCCColor = ccColor; + mGCColor = gcColor; + + char buffer[40]; + SAFE_SPRINTF(buffer, "\x1B" "CC[%08x]" "\x1B" "GC[%08x]", mCCColor, mGCColor); + do_strcat(buffer, false, false, false); +} +#endif + void jmessage_tRenderingProcessor::do_scale(f32 param_1) { jmessage_tReference* pReference = (jmessage_tReference*)getReference(); @@ -4684,9 +4755,20 @@ bool jmessage_string_tRenderingProcessor::do_tag(u32 i_tag, void const* i_data, switch(i_tag & 0xFF0000) { case MSGTAG_GROUP(255): switch(i_tag) { - case MSGTAG_COLOR: + case MSGTAG_COLOR: { +#if TARGET_PC + u32 ccColor; + u32 gcColor; + if (read_full_color(i_data, i_size, ccColor, gcColor)) { + do_fullcolor(ccColor, gcColor); + } else if (i_size == 1) { + do_color(*(u8*)i_data & 0xFF); + } +#else do_color(*(u8*)i_data & 0xFF); +#endif break; + } case MSGTAG_SCALE: do_scale(*(BE(u16)*)i_data / 100.0f); break; @@ -5336,6 +5418,14 @@ void jmessage_string_tRenderingProcessor::do_color(u8 i_colorNo) { do_strcat(buffer); } +#if TARGET_PC +void jmessage_string_tRenderingProcessor::do_fullcolor(u32 ccColor, u32 gcColor) { + char buffer[32]; + SAFE_SPRINTF(buffer, "\x1b" "CC[%08x]" "\x1b" "GC[%08x]", ccColor, gcColor); + do_strcat(buffer); +} +#endif + void jmessage_string_tRenderingProcessor::do_scale(f32 i_scale) { J2DTextBox::TFontSize fontSize; mpReference->getPanePtr()->getFontSize(fontSize); diff --git a/src/d/d_msg_flow.cpp b/src/d/d_msg_flow.cpp index 9b4ea2164c..8ce605e122 100644 --- a/src/d/d_msg_flow.cpp +++ b/src/d/d_msg_flow.cpp @@ -43,6 +43,11 @@ u16 message_id(const MessageEntryData& entry) { return static_cast(static_cast(entry.bytes[4]) << 8 | entry.bytes[5]); } +u16 flow_group(int flowId) { + const bool isCommonFlow = flowId >= 3000 && flowId < dusk::flow::kCustomNodeMin; + return isCommonFlow ? 0 : static_cast(dMsgObject_getGroupID()); +} + } // namespace #endif @@ -70,8 +75,7 @@ void dMsgFlow_c::init(fopAc_ac_c* i_partner, int i_flowID, int param_2, fopAc_ac dMsgObject_changeFlowGroup(i_flowID); #if TARGET_PC - dusk::flow::bind_resource(dMsgObject_getMsgDtPtr(), - i_flowID >= 3000 ? 0 : static_cast(dMsgObject_getGroupID())); + dusk::flow::bind_resource(dMsgObject_getMsgDtPtr(), flow_group(i_flowID)); #endif if (param_2 == 0) { @@ -399,8 +403,7 @@ void dMsgFlow_c::setInitValueGroupChange(int i_msgNo, fopAc_ac_c** i_talkPartner dMsgObject_changeFlowGroup(i_msgNo); #if TARGET_PC - dusk::flow::bind_resource(dMsgObject_getMsgDtPtr(), - i_msgNo >= 3000 ? 0 : static_cast(dMsgObject_getGroupID())); + dusk::flow::bind_resource(dMsgObject_getMsgDtPtr(), flow_group(i_msgNo)); #endif setInitValue(0); @@ -446,6 +449,12 @@ u8* dMsgFlow_c::getMsgDataBlock(char const* block_tag) { } u16 dMsgFlow_c::getInitNodeIndex(u16 param_1) { +#if TARGET_PC + if (param_1 >= dusk::flow::kCustomNodeMin) { + return param_1; + } +#endif + u8* var_r30 = NULL; u16 var_r27 = -1; diff --git a/src/d/d_msg_object.cpp b/src/d/d_msg_object.cpp index 3dbaa02dec..072bd5039b 100644 --- a/src/d/d_msg_object.cpp +++ b/src/d/d_msg_object.cpp @@ -36,6 +36,7 @@ #include "dusk/language.hpp" #include "dusk/logging.h" #include "dusk/menu_pointer.h" +#include "dusk/mods/item.hpp" #include "dusk/mods/svc/flow.hpp" #include "dusk/settings.h" #include "dusk/version.hpp" @@ -832,6 +833,9 @@ u32 dMsgObject_c::getMessageIndex(u32 param_0) { u32 dMsgObject_c::getRevoMessageIndex(u32 param_1) { #if TARGET_PC + const u16 sourceGroup = param_1 > 5000 ? static_cast(s_groupID) : 0; + param_1 = dusk::mods::item_check_message(sourceGroup, param_1); + u16 customGroup = 0; if (param_1 <= 0xffff && dusk::flow::custom_message_group(static_cast(param_1), customGroup)) @@ -1861,7 +1865,11 @@ void dMsgObject_c::readMessageGroupLocal(mDoDvdThd_mountXArchive_c** p_arcMount) void dMsgObject_c::changeFlowGroupLocal(s32 param_0) { mFlowChk = 1; +#if TARGET_PC + changeGroup(param_0 >= 3000 && param_0 < dusk::flow::kCustomNodeMin ? (s16)0 : s_groupID); +#else changeGroup(param_0 >= 3000 ? (s16)0 : s_groupID); +#endif } void dMsgObject_c::demoMessageGroupLocal() { diff --git a/src/d/d_name.cpp b/src/d/d_name.cpp index bf906f9285..aa01a39de4 100644 --- a/src/d/d_name.cpp +++ b/src/d/d_name.cpp @@ -10,6 +10,7 @@ #include #include "JSystem/J2DGraph/J2DAnmLoader.h" +#include "dusk/utilities.hpp" #include "dusk/version.hpp" #include "f_op/f_op_msg_mng.h" @@ -1512,11 +1513,31 @@ void dName_c::selectCursorPosSet(int row) { } #if TARGET_PC + +static dusk::utils::PaneCache l_tagName[] = { + {MULTI_CHAR('m_00_0'), 0.0f, 0.0f, false}, {MULTI_CHAR('m_00_1'), 0.0f, 0.0f, false}, {MULTI_CHAR('m_00_2'), 0.0f, 0.0f, false}, {MULTI_CHAR('m_00_3'), 0.0f, 0.0f, false}, {MULTI_CHAR('m_00_4'), 0.0f, 0.0f, false}, {MULTI_CHAR('m_01_0'), 0.0f, 0.0f, false}, {MULTI_CHAR('m_01_1'), 0.0f, 0.0f, false}, {MULTI_CHAR('m_01_2'), 0.0f, 0.0f, false}, {MULTI_CHAR('m_01_3'), 0.0f, 0.0f, false}, + {MULTI_CHAR('m_01_4'), 0.0f, 0.0f, false}, {MULTI_CHAR('m_02_0'), 0.0f, 0.0f, false}, {MULTI_CHAR('m_02_1'), 0.0f, 0.0f, false}, {MULTI_CHAR('m_02_2'), 0.0f, 0.0f, false}, {MULTI_CHAR('m_02_3'), 0.0f, 0.0f, false}, {MULTI_CHAR('m_02_4'), 0.0f, 0.0f, false}, {MULTI_CHAR('m03_0'), 0.0f, 0.0f, false}, {MULTI_CHAR('m03_1'), 0.0f, 0.0f, false}, {MULTI_CHAR('m03_2'), 0.0f, 0.0f, false}, + {MULTI_CHAR('m03_3'), 0.0f, 0.0f, false}, {MULTI_CHAR('m03_4'), 0.0f, 0.0f, false}, {MULTI_CHAR('m_04_0'), 0.0f, 0.0f, false}, {MULTI_CHAR('m_04_1'), 0.0f, 0.0f, false}, {MULTI_CHAR('m_04_2'), 0.0f, 0.0f, false}, {MULTI_CHAR('m_04_3'), 0.0f, 0.0f, false}, {MULTI_CHAR('m_04_4'), 0.0f, 0.0f, false}, {MULTI_CHAR('m_05_0'), 0.0f, 0.0f, false}, {MULTI_CHAR('m_05_1'), 0.0f, 0.0f, false}, + {MULTI_CHAR('m_05_2'), 0.0f, 0.0f, false}, {MULTI_CHAR('m_05_3'), 0.0f, 0.0f, false}, {MULTI_CHAR('m_05_4'), 0.0f, 0.0f, false}, {MULTI_CHAR('m_06_0'), 0.0f, 0.0f, false}, {MULTI_CHAR('m_06_1'), 0.0f, 0.0f, false}, {MULTI_CHAR('m_06_2'), 0.0f, 0.0f, false}, {MULTI_CHAR('m_06_3'), 0.0f, 0.0f, false}, {MULTI_CHAR('m_06_4'), 0.0f, 0.0f, false}, {MULTI_CHAR('m_07_0'), 0.0f, 0.0f, false}, + {MULTI_CHAR('m_07_1'), 0.0f, 0.0f, false}, {MULTI_CHAR('m_07_2'), 0.0f, 0.0f, false}, {MULTI_CHAR('m_07_3'), 0.0f, 0.0f, false}, {MULTI_CHAR('m_07_4'), 0.0f, 0.0f, false}, {MULTI_CHAR('m_08_0'), 0.0f, 0.0f, false}, {MULTI_CHAR('m_08_1'), 0.0f, 0.0f, false}, {MULTI_CHAR('m_08_2'), 0.0f, 0.0f, false}, {MULTI_CHAR('m_08_3'), 0.0f, 0.0f, false}, {MULTI_CHAR('m_08_4'), 0.0f, 0.0f, false}, + {MULTI_CHAR('m_09_0'), 0.0f, 0.0f, false}, {MULTI_CHAR('m_09_1'), 0.0f, 0.0f, false}, {MULTI_CHAR('m_09_2'), 0.0f, 0.0f, false}, {MULTI_CHAR('m_09_3'), 0.0f, 0.0f, false}, {MULTI_CHAR('m_09_4'), 0.0f, 0.0f, false}, {MULTI_CHAR('m_10_0'), 0.0f, 0.0f, false}, {MULTI_CHAR('m_10_1'), 0.0f, 0.0f, false}, {MULTI_CHAR('m_10_2'), 0.0f, 0.0f, false}, {MULTI_CHAR('m_10_3'), 0.0f, 0.0f, false}, + {MULTI_CHAR('m_10_4'), 0.0f, 0.0f, false}, {MULTI_CHAR('m_11_0'), 0.0f, 0.0f, false}, {MULTI_CHAR('m_11_1'), 0.0f, 0.0f, false}, {MULTI_CHAR('m_11_2'), 0.0f, 0.0f, false}, {MULTI_CHAR('m_11_3'), 0.0f, 0.0f, false}, {MULTI_CHAR('m_11_4'), 0.0f, 0.0f, false}, {MULTI_CHAR('m12_0'), 0.0f, 0.0f, false}, {MULTI_CHAR('m12_1'), 0.0f, 0.0f, false}, {MULTI_CHAR('m12_2'), 0.0f, 0.0f, false}, + {MULTI_CHAR('m12_3'), 0.0f, 0.0f, false}, {MULTI_CHAR('m12_4'), 0.0f, 0.0f, false}, {MULTI_CHAR('p_end_2'), 0.0f, 0.0f, false}, {MULTI_CHAR('p_end_1'), 0.0f, 0.0f, false}, {MULTI_CHAR('p_end_0'), 0.0f, 0.0f, false}, +}; + +static dusk::utils::PaneCache l_nameTagName[] = { + {MULTI_CHAR('name_00'), 0.0f, 0.0f, false}, {MULTI_CHAR('name_01'), 0.0f, 0.0f, false}, {MULTI_CHAR('name_02'), 0.0f, 0.0f, false}, {MULTI_CHAR('name_03'), 0.0f, 0.0f, false}, {MULTI_CHAR('name_04'), 0.0f, 0.0f, false}, {MULTI_CHAR('name_05'), 0.0f, 0.0f, false}, {MULTI_CHAR('name_06'), 0.0f, 0.0f, false}, {MULTI_CHAR('name_07'), 0.0f, 0.0f, false}, +}; + +static dusk::utils::PaneCache l_nameCurTagName[] = { + {MULTI_CHAR('s__n_00'), 0.0f, 0.0f, false}, {MULTI_CHAR('s__n_01'), 0.0f, 0.0f, false}, {MULTI_CHAR('s__n_02'), 0.0f, 0.0f, false}, {MULTI_CHAR('s__n_03'), 0.0f, 0.0f, false}, {MULTI_CHAR('s__n_04'), 0.0f, 0.0f, false}, {MULTI_CHAR('s__n_05'), 0.0f, 0.0f, false}, {MULTI_CHAR('s__n_06'), 0.0f, 0.0f, false}, {MULTI_CHAR('s__n_07'), 0.0f, 0.0f, false}, +}; + void dName_c::nameWide() { static bool cachedPanes = false; // Get pre-scale values for each pane if (!cachedPanes) { - for (PaneCache& entry : l_tagName) { + for (dusk::utils::PaneCache& entry : l_tagName) { J2DPane* pane = nameIn.NameInScr->search(entry.tag); if (!entry.cached) { entry.origTransX = pane->getTranslateX(); @@ -1524,7 +1545,7 @@ void dName_c::nameWide() { entry.cached = true; } } - for (PaneCache& entry : l_nameTagName) { + for (dusk::utils::PaneCache& entry : l_nameTagName) { J2DPane* pane = nameIn.NameInScr->search(entry.tag); if (!entry.cached) { entry.origTransX = pane->getTranslateX(); @@ -1532,7 +1553,7 @@ void dName_c::nameWide() { entry.cached = true; } } - for (PaneCache& entry : l_nameCurTagName) { + for (dusk::utils::PaneCache& entry : l_nameCurTagName) { J2DPane* pane = nameIn.NameInScr->search(entry.tag); if (!entry.cached) { entry.origTransX = pane->getTranslateX(); @@ -1546,19 +1567,19 @@ void dName_c::nameWide() { // Reset all panes nameIn.NameInScr->scale(1.0f, 1.0f); nameIn.NameInScr->translate(0.0f, 0.0f); - for (PaneCache& entry : l_tagName) { + for (dusk::utils::PaneCache& entry : l_tagName) { J2DPane* pane = nameIn.NameInScr->search(entry.tag); pane->setBasePosition(J2DBasePosition_4); pane->scale(1.0f, 1.0f); pane->translate(entry.origTransX, entry.origTransY); } - for (PaneCache& entry : l_nameTagName) { + for (dusk::utils::PaneCache& entry : l_nameTagName) { J2DPane* pane = nameIn.NameInScr->search(entry.tag); pane->setBasePosition(J2DBasePosition_4); pane->scale(1.0f, 1.0f); pane->translate(entry.origTransX, entry.origTransY); } - for (PaneCache& entry : l_nameCurTagName) { + for (dusk::utils::PaneCache& entry : l_nameCurTagName) { J2DPane* pane = nameIn.NameInScr->search(entry.tag); pane->setBasePosition(J2DBasePosition_4); pane->scale(1.0f, 1.0f); @@ -1574,17 +1595,17 @@ void dName_c::nameWide() { break; default: // Wii and Dusklight // List of Characters Box - for (PaneCache& entry : l_tagName) { + for (dusk::utils::PaneCache& entry : l_tagName) { J2DPane* pane = nameIn.NameInScr->search(entry.tag); pane->scale(mDoGph_gInf_c::hudAspectScaleDown, 1.0f); } // Letters being typed - for (PaneCache& entry : l_nameTagName) { + for (dusk::utils::PaneCache& entry : l_nameTagName) { J2DPane* pane = nameIn.NameInScr->search(entry.tag); pane->scale(mDoGph_gInf_c::hudAspectScaleDown, 1.0f); } // Underscores when typing below letters - for (PaneCache& entry : l_nameCurTagName) { + for (dusk::utils::PaneCache& entry : l_nameCurTagName) { J2DPane* pane = nameIn.NameInScr->search(entry.tag); pane->scale(mDoGph_gInf_c::hudAspectScaleDown, 1.0f); } diff --git a/src/d/d_s_play.cpp b/src/d/d_s_play.cpp index bb70465edb..78a6e07d97 100644 --- a/src/d/d_s_play.cpp +++ b/src/d/d_s_play.cpp @@ -43,7 +43,9 @@ #include "dusk/autosave.h" #include "dusk/d_trigger_view.h" #include "dusk/memory.h" +#include "dusk/mods/item.hpp" #include "dusk/ui/ui.hpp" +#include "mods/items.h" #endif #if DEBUG @@ -1197,11 +1199,35 @@ static int phase_1(dScnPly_c* i_this) { } // Stage: Ordon Spring, Room: Ordon Spring +#if TARGET_PC + const bool iliaMemoryArrival = + !strcmp(dComIfGp_getStartStageName(), "F_SP104") && dComIfGp_getStartStageRoomNo() == 1 && + dComIfGp_getStartStagePoint() == 23 && dComIfGp_getStartStageLayer() == 12; + const u32 iliaMemoryTag = dusk::mods::item_give_tag(ITEM_CHECK_ILIA_MEMORY); + if (!iliaMemoryArrival) { + dusk::mods::item_check_cancel(iliaMemoryTag); + } + if (iliaMemoryArrival) +#else if (!strcmp(dComIfGp_getStartStageName(), "F_SP104") && dComIfGp_getStartStageRoomNo() == 1 && dComIfGp_getStartStagePoint() == 23 && dComIfGp_getStartStageLayer() == 12) +#endif { - dComIfGs_onItemFirstBit(dItemNo_HORSE_FLUTE_e); - dComIfGs_setItem(SLOT_21, dItemNo_HORSE_FLUTE_e); +#if TARGET_PC + const auto itemCheck = + dusk::mods::item_check_commit(iliaMemoryTag, dItemNo_HORSE_FLUTE_e, nullptr); + if (itemCheck.itemNo == dItemNo_HORSE_FLUTE_e) { +#endif + dComIfGs_onItemFirstBit(dItemNo_HORSE_FLUTE_e); + dComIfGs_setItem(SLOT_21, dItemNo_HORSE_FLUTE_e); +#if TARGET_PC + dusk::mods::item_check_complete(itemCheck, nullptr); + } else if (itemCheck.itemNo == dItemNo_NONE_e) { + dusk::mods::item_check_complete(itemCheck, nullptr); + } else { + dusk::mods::item_check_enqueue(itemCheck, dusk::mods::ItemGiveMode::Silent); + } +#endif } if ((u8)dKy_darkworld_stage_check(dComIfGp_getStartStageName(), diff --git a/src/d/d_shop_system.cpp b/src/d/d_shop_system.cpp index bf2d3650af..1d7fed2406 100644 --- a/src/d/d_shop_system.cpp +++ b/src/d/d_shop_system.cpp @@ -906,15 +906,17 @@ int dShopSystem_c::seq_start(fopAc_ac_c* actor, dMsgFlow_c* i_flow) { if (mFlow.getEventId(&itemNo) == 1) { if (mItemPartnerId == fpcM_ERROR_PROCESS_ID_e) { #if TARGET_PC - const char* itemCheckName = nullptr; + u32 itemGiveTag = 0; if (itemNo == dItemNo_HALF_MILK_BOTTLE_e) { - itemCheckName = "sera_reward"; - itemNo = dusk::mods::item_check(itemCheckName, itemNo, actor); + const auto itemCheck = + dusk::mods::item_check_commit("sera_reward", itemNo, actor); + itemNo = itemCheck.itemNo; + itemGiveTag = itemCheck.tag; } #endif mItemPartnerId = fopAcM_createItemForPresentDemo(¤t.pos, itemNo, 0, -1, -1, NULL, - NULL IF_DUSK_ARG(dusk::mods::item_give_tag(itemCheckName))); + NULL IF_DUSK_ARG(itemGiveTag)); } if (fpcEx_IsExist(mItemPartnerId)) { @@ -1205,7 +1207,9 @@ int dShopSystem_c::seq_decide_yes(fopAc_ac_c* actor, dMsgFlow_c* i_flow) { if (mItemPartnerId == fpcM_ERROR_PROCESS_ID_e) { #if TARGET_PC const u32 itemGiveTag = dusk::mods::item_give_tag_shop(itemNo & 0xFF); - itemNo = dusk::mods::item_check_shop(itemNo & 0xFF, actor); + const auto itemCheck = + dusk::mods::item_check_commit(itemGiveTag, itemNo & 0xFF, actor); + itemNo = itemCheck.itemNo; #endif mItemPartnerId = fopAcM_createItemForPresentDemo( ¤t.pos, itemNo, 0, -1, -1, NULL, NULL IF_DUSK_ARG(itemGiveTag)); diff --git a/src/dusk/imgui/ImGuiSaveEditor.cpp b/src/dusk/imgui/ImGuiSaveEditor.cpp index ec2802de44..244b26e200 100644 --- a/src/dusk/imgui/ImGuiSaveEditor.cpp +++ b/src/dusk/imgui/ImGuiSaveEditor.cpp @@ -76,7 +76,7 @@ namespace dusk { { dItemNo_WEAR_KOKIRI_e, {"Hero's Clothes"} }, { dItemNo_ARMOR_e, {"Magic Armor"} }, { dItemNo_WEAR_ZORA_e, {"Zora Armor"} }, - { dItemNo_MAGIC_LV1_e, {"Magic Level 1"} }, + { dItemNo_SHADOW_CRYSTAL_e, {"Shadow Crystal"} }, { dItemNo_DUNGEON_EXIT_2_e, {"Ooccoo Sr.", ITEMTYPE_EQUIP_e} }, { dItemNo_WALLET_LV1_e, {"Wallet"} }, { dItemNo_WALLET_LV2_e, {"Big Wallet"} }, diff --git a/src/dusk/mods/item.hpp b/src/dusk/mods/item.hpp index ab98b899e3..bda0d4f7ee 100644 --- a/src/dusk/mods/item.hpp +++ b/src/dusk/mods/item.hpp @@ -1,37 +1,109 @@ #pragma once +#include "mods/svc/item.h" + #include +#include +#include class fopAc_ac_c; namespace dusk::mods { +enum class ItemGiveMode : uint8_t { + Demo, + Silent, + ForcedDemo, +}; + +struct ItemCheckResult { + uint32_t tag = 0; + uint8_t itemNo = 0; + uint8_t displayItemNo = 0; +}; + +ItemCheckResolution item_check_resolve(const char* name, uint8_t itemNo, fopAc_ac_c* giver); +ItemCheckResolution item_check_resolve(uint32_t giveTag, uint8_t itemNo, fopAc_ac_c* giver); uint8_t item_check(const char* name, uint8_t itemNo, fopAc_ac_c* giver); -uint8_t item_check_tagged(uint32_t giveTag, uint8_t itemNo, fopAc_ac_c* giver); +ItemCheckResult item_check_commit(const char* name, uint8_t itemNo, fopAc_ac_c* giver); +ItemCheckResult item_check_commit(uint32_t giveTag, uint8_t itemNo, fopAc_ac_c* giver); uint8_t item_check_chest(uint8_t boxNo, uint8_t itemNo, fopAc_ac_c* chest); uint8_t item_check_boss(uint8_t itemNo, fopAc_ac_c* boss); uint8_t item_check_freestanding(uint8_t bitNo, uint8_t itemNo, fopAc_ac_c* item); -uint8_t item_check_poe(uint8_t bitNo, uint8_t itemNo, fopAc_ac_c* poe); +uint8_t item_check_golden_wolf(uint16_t eventFlag, uint8_t itemNo, fopAc_ac_c* item); uint8_t item_check_shop(uint8_t itemNo, fopAc_ac_c* giver); -uint8_t item_check_bug(uint8_t insectId, uint8_t itemNo, fopAc_ac_c* agitha); -uint8_t item_check_sky_character(uint8_t itemNo, fopAc_ac_c* statue); uint32_t item_give_tag(const char* name); uint32_t item_give_tag_chest(uint8_t boxNo); uint32_t item_give_tag_boss(); uint32_t item_give_tag_freestanding(uint8_t bitNo); +uint32_t item_give_tag_golden_wolf(uint16_t eventFlag); uint32_t item_give_tag_poe(uint8_t bitNo); uint32_t item_give_tag_shop(uint8_t itemNo); uint32_t item_give_tag_bug(uint8_t insectId); uint32_t item_give_tag_sky_character(); -void item_check_enqueue(const char* name, uint8_t itemNo); -void item_check_enqueue_poe(uint8_t bitNo, uint8_t itemNo); +void item_check_enqueue_deferred(const char* name, uint8_t itemNo); +bool item_check_enqueue(ItemCheckResult check, ItemGiveMode mode); +void item_check_complete(ItemCheckResult check, fopAc_ac_c* giver); +void item_check_cancel(uint32_t giveTag); +void item_check_clear_committed(); void item_granted(uint8_t itemNo, uint32_t giveTag, fopAc_ac_c* giver); +uint32_t item_check_message(uint16_t group, uint32_t messageId); + bool item_give_queue_dispatching(); uint32_t item_give_queue_take_tag(); +namespace detail { +struct CommittedCheck { + uint8_t vanillaItem = 0; + ItemCheckResolution resolution{}; + bool queued = false; +}; + +class ItemCommitStore { +public: + CommittedCheck* find(uint32_t giveTag) { + const auto it = mChecks.find(giveTag); + return it != mChecks.end() ? &it->second : nullptr; + } + + const CommittedCheck* find(uint32_t giveTag) const { + const auto it = mChecks.find(giveTag); + return it != mChecks.end() ? &it->second : nullptr; + } + + template + CommittedCheck& commit(uint32_t giveTag, uint8_t vanillaItem, ResolveFn&& resolve) { + const auto existing = mChecks.find(giveTag); + if (existing != mChecks.end()) { + return existing->second; + } + + const ItemCheckResolution resolution = std::forward(resolve)(); + return mChecks + .emplace(giveTag, + CommittedCheck{ + .vanillaItem = vanillaItem, + .resolution = resolution, + }) + .first->second; + } + + bool contains(uint32_t giveTag) const { return mChecks.contains(giveTag); } + + void erase(uint32_t giveTag) { mChecks.erase(giveTag); } + + void clear() { mChecks.clear(); } + + bool empty() const { return mChecks.empty(); } + +private: + std::unordered_map mChecks; +}; +} // namespace detail + } // namespace dusk::mods diff --git a/src/dusk/mods/item_checks.cpp b/src/dusk/mods/item_checks.cpp index 79a6c993b9..fb145a48df 100644 --- a/src/dusk/mods/item_checks.cpp +++ b/src/dusk/mods/item_checks.cpp @@ -6,9 +6,14 @@ #include "aurora/lib/logging.hpp" #include "d/d_com_inf_game.h" +#include "d/d_item_data.h" +#include "mods/items.h" #include +#include +#include +#include #include #include #include @@ -45,6 +50,78 @@ struct PendingResolve { void* userData = nullptr; }; +struct MessageCheck { + uint16_t group = 0; + uint16_t messageId = 0; + const char* name = nullptr; + uint8_t vanillaItem = 0; + bool enqueueAtDisplay = true; +}; + +constexpr std::array kMessageChecks{ + MessageCheck{ + .group = 0, + .messageId = 1822, + .name = ITEM_CHECK_FISHING_BOTTLE, + .vanillaItem = dItemNo_EMPTY_BOTTLE_e, + }, + MessageCheck{ + .group = 7, + .messageId = 7564, + .name = ITEM_CHECK_FISHING_HEART_PIECE, + .vanillaItem = dItemNo_KAKERA_HEART_e, + }, + MessageCheck{ + .group = 7, + .messageId = 7578, + .name = ITEM_CHECK_FISHING_HEART_PIECE, + .vanillaItem = dItemNo_KAKERA_HEART_e, + }, + MessageCheck{ + .group = 5, + .messageId = 5001, + .name = ITEM_CHECK_DUNGEON_REWARD_FOREST, + .vanillaItem = dItemNo_NONE_e, + }, + MessageCheck{ + .group = 5, + .messageId = 6011, + .name = ITEM_CHECK_DUNGEON_REWARD_GORON, + .vanillaItem = dItemNo_NONE_e, + }, + MessageCheck{ + .group = 5, + .messageId = 7001, + .name = ITEM_CHECK_DUNGEON_REWARD_LAKEBED, + .vanillaItem = dItemNo_NONE_e, + }, + MessageCheck{ + .group = 5, + .messageId = 9301, + .name = ITEM_CHECK_DUNGEON_REWARD_SNOWPEAK, + .vanillaItem = dItemNo_NONE_e, + }, + MessageCheck{ + .group = 5, + .messageId = 9401, + .name = ITEM_CHECK_DUNGEON_REWARD_TIME, + .vanillaItem = dItemNo_NONE_e, + }, + MessageCheck{ + .group = 5, + .messageId = 11001, + .name = ITEM_CHECK_DUNGEON_REWARD_CITY, + .vanillaItem = dItemNo_NONE_e, + }, + MessageCheck{ + .group = 0, + .messageId = 233, + .name = ITEM_CHECK_ILIA_MEMORY, + .vanillaItem = dItemNo_HORSE_FLUTE_e, + .enqueueAtDisplay = false, + }, +}; + std::unordered_map s_modChecks; std::unordered_set s_warnedCollisions; ItemCheckHandle s_nextCheckHandle = 1; @@ -66,6 +143,10 @@ std::string freestanding_check_name(uint8_t bitNo) { return fmt::format("freestanding:{}:{}", current_stage_name(), bitNo); } +std::string golden_wolf_check_name(uint16_t eventFlag) { + return fmt::format("golden_wolf:{}", eventFlag); +} + std::string poe_check_name(uint8_t bitNo) { return fmt::format("poe:{}:{}", current_stage_name(), bitNo); } @@ -79,14 +160,35 @@ std::string bug_check_name(uint8_t insectId) { } std::string sky_character_check_name() { - return fmt::format("skychar:{}:{}", current_stage_name(), dStage_roomControl_c::getStayNo()); + return fmt::format("sky:{}:{}", current_stage_name(), dStage_roomControl_c::getStayNo()); +} + +bool ilia_memory_context() { + return std::strcmp(current_stage_name(), "R_SP109") == 0 && + dComIfGp_roomControl_getStayNo() == 0 && dComIfG_play_c::getLayerNo(0) == 9; +} + +uint16_t item_get_message(uint8_t itemNo) { + if (itemNo == dItemNo_KAKERA_HEART_e) { + constexpr std::array heartPieceMessages{0x86, 0x9C, 0x9D, 0x9E, 0x9F}; + return heartPieceMessages[dComIfGs_getMaxLife() % heartPieceMessages.size()]; + } + return static_cast(itemNo + 0x65); +} + +void invalidate_committed_check(const std::string& name) { + if (name.empty()) { + item_check_clear_committed(); + } else { + item_check_cancel(item_give_tag(name.c_str())); + } } } // namespace -uint8_t item_check(const char* name, uint8_t itemNo, fopAc_ac_c* giver) { +ItemCheckResolution item_check_resolve(const char* name, uint8_t itemNo, fopAc_ac_c* giver) { if (name == nullptr || *name == '\0' || s_modChecks.empty()) { - return itemNo; + return {.item = itemNo, .display_item = itemNo}; } // Callbacks may change registrations, so copy the applicable chain before invoking one. @@ -126,6 +228,7 @@ uint8_t item_check(const char* name, uint8_t itemNo, fopAc_ac_c* giver) { .giver_actor = giver, .vanilla_item = itemNo, .current_item = itemNo, + .current_display_item = itemNo, }; for (const auto& resolve : resolves) { if (!resolve.mod->active) { @@ -133,13 +236,21 @@ uint8_t item_check(const char* name, uint8_t itemNo, fopAc_ac_c* giver) { } if (resolve.fixedValue) { info.current_item = resolve.itemNo; + info.current_display_item = resolve.itemNo; continue; } - uint8_t resolvedItem = info.current_item; + ItemCheckResolution resolution{ + .item = info.current_item, + .display_item = dItemNo_NONE_e, + }; try { - if (resolve.fn(resolve.mod->context.get(), &info, &resolvedItem, resolve.userData)) { - info.current_item = resolvedItem; + if (resolve.fn(resolve.mod->context.get(), &info, &resolution, resolve.userData)) { + if (resolution.display_item == UINT8_MAX) { + resolution.display_item = resolution.item; + } + info.current_item = resolution.item; + info.current_display_item = resolution.display_item; } } catch (const std::exception& e) { fail_mod(*resolve.mod, MOD_ERROR, @@ -149,7 +260,14 @@ uint8_t item_check(const char* name, uint8_t itemNo, fopAc_ac_c* giver) { fmt::format("Unknown exception in item check resolver for '{}'", name)); } } - return info.current_item; + return { + .item = info.current_item, + .display_item = info.current_display_item, + }; +} + +uint8_t item_check(const char* name, uint8_t itemNo, fopAc_ac_c* giver) { + return item_check_resolve(name, itemNo, giver).item; } uint8_t item_check_chest(uint8_t boxNo, uint8_t itemNo, fopAc_ac_c* chest) { @@ -176,12 +294,12 @@ uint8_t item_check_freestanding(uint8_t bitNo, uint8_t itemNo, fopAc_ac_c* item) return item_check(name.c_str(), itemNo, item); } -uint8_t item_check_poe(uint8_t bitNo, uint8_t itemNo, fopAc_ac_c* poe) { +uint8_t item_check_golden_wolf(uint16_t eventFlag, uint8_t itemNo, fopAc_ac_c* item) { if (s_modChecks.empty()) { return itemNo; } - const auto name = poe_check_name(bitNo); - return item_check(name.c_str(), itemNo, poe); + const auto name = golden_wolf_check_name(eventFlag); + return item_check(name.c_str(), itemNo, item); } uint8_t item_check_shop(uint8_t itemNo, fopAc_ac_c* giver) { @@ -192,20 +310,24 @@ uint8_t item_check_shop(uint8_t itemNo, fopAc_ac_c* giver) { return item_check(name.c_str(), itemNo, giver); } -uint8_t item_check_bug(uint8_t insectId, uint8_t itemNo, fopAc_ac_c* agitha) { - if (s_modChecks.empty()) { - return itemNo; - } - const auto name = bug_check_name(insectId); - return item_check(name.c_str(), itemNo, agitha); -} +uint32_t item_check_message(uint16_t group, uint32_t messageId) { + for (const auto& check : kMessageChecks) { + if (check.group != group || check.messageId != messageId || + (check.group == 0 && check.messageId == 233 && !ilia_memory_context())) + { + continue; + } -uint8_t item_check_sky_character(uint8_t itemNo, fopAc_ac_c* statue) { - if (s_modChecks.empty()) { - return itemNo; + const ItemCheckResult result = item_check_commit(check.name, check.vanillaItem, nullptr); + if (result.itemNo == check.vanillaItem || result.itemNo == dItemNo_NONE_e) { + return messageId; + } + if (check.enqueueAtDisplay) { + item_check_enqueue(result, ItemGiveMode::Silent); + } + return item_get_message(result.itemNo); } - const auto name = sky_character_check_name(); - return item_check(name.c_str(), itemNo, statue); + return messageId; } uint32_t item_give_tag_chest(uint8_t boxNo) { @@ -220,6 +342,10 @@ uint32_t item_give_tag_freestanding(uint8_t bitNo) { return item_give_tag(freestanding_check_name(bitNo).c_str()); } +uint32_t item_give_tag_golden_wolf(uint16_t eventFlag) { + return item_give_tag(golden_wolf_check_name(eventFlag).c_str()); +} + uint32_t item_give_tag_poe(uint8_t bitNo) { return item_give_tag(poe_check_name(bitNo).c_str()); } @@ -236,10 +362,6 @@ uint32_t item_give_tag_sky_character() { return item_give_tag(sky_character_check_name().c_str()); } -void item_check_enqueue_poe(uint8_t bitNo, uint8_t itemNo) { - item_check_enqueue(poe_check_name(bitNo).c_str(), itemNo); -} - namespace svc { ModResult item_check_set_override(LoadedMod& mod, const char* name, uint8_t itemNo) { @@ -247,10 +369,12 @@ ModResult item_check_set_override(LoadedMod& mod, const char* name, uint8_t item for (auto& checkOverride : checks.overrides) { if (checkOverride.name == name) { checkOverride.itemNo = itemNo; + invalidate_committed_check(checkOverride.name); return MOD_OK; } } checks.overrides.push_back({.name = name, .itemNo = itemNo}); + invalidate_committed_check(checks.overrides.back().name); return MOD_OK; } @@ -261,6 +385,9 @@ ModResult item_check_clear_override(LoadedMod& mod, const char* name) { } const auto removed = std::erase_if(modIt->second.overrides, [&](const auto& checkOverride) { return checkOverride.name == name; }); + if (removed != 0) { + invalidate_committed_check(name); + } return removed != 0 ? MOD_OK : MOD_INVALID_ARGUMENT; } @@ -272,6 +399,7 @@ ModResult item_check_add_resolver(LoadedMod& mod, const char* name, ItemCheckRes resolver.fn = fn; resolver.userData = userData; outHandle = resolver.handle; + invalidate_committed_check(resolver.name); return MOD_OK; } @@ -280,12 +408,31 @@ ModResult item_check_remove_resolver(LoadedMod& mod, ItemCheckHandle handle) { if (modIt == s_modChecks.end()) { return MOD_INVALID_ARGUMENT; } - const auto removed = std::erase_if( - modIt->second.resolvers, [&](const auto& resolver) { return resolver.handle == handle; }); - return removed != 0 ? MOD_OK : MOD_INVALID_ARGUMENT; + const auto resolverIt = + std::find_if(modIt->second.resolvers.begin(), modIt->second.resolvers.end(), + [&](const auto& resolver) { return resolver.handle == handle; }); + if (resolverIt == modIt->second.resolvers.end()) { + return MOD_INVALID_ARGUMENT; + } + const std::string name = resolverIt->name; + modIt->second.resolvers.erase(resolverIt); + invalidate_committed_check(name); + return MOD_OK; } void item_checks_remove_mod(LoadedMod& mod) { + if (const auto modIt = s_modChecks.find(&mod); modIt != s_modChecks.end()) { + for (const auto& resolver : modIt->second.resolvers) { + if (resolver.name.empty()) { + item_check_clear_committed(); + break; + } + invalidate_committed_check(resolver.name); + } + for (const auto& checkOverride : modIt->second.overrides) { + invalidate_committed_check(checkOverride.name); + } + } s_modChecks.erase(&mod); s_warnedCollisions.clear(); } diff --git a/src/dusk/mods/item_gives.cpp b/src/dusk/mods/item_gives.cpp index bfe92d3cff..5d75dcfc15 100644 --- a/src/dusk/mods/item_gives.cpp +++ b/src/dusk/mods/item_gives.cpp @@ -17,6 +17,7 @@ #include #include #include +#include #include namespace dusk::mods { @@ -28,6 +29,8 @@ aurora::Module Log{"dusk::mods::item_gives"}; std::deque s_giveNames; std::unordered_map s_giveNameIds; +detail::ItemCommitStore s_committedChecks; + const char* item_give_name(uint32_t tag) { if (tag == 0 || tag > s_giveNames.size()) { return nullptr; @@ -92,7 +95,18 @@ void notify_gives(const char* checkName, uint8_t itemNo, fopAc_ac_c* giver, Item } } -constexpr size_t kGiveQueueLimit = 64; +void complete_check(uint8_t itemNo, uint32_t giveTag, fopAc_ac_c* giver, ItemGiveOrigin origin) { + if (const auto* committed = s_committedChecks.find(giveTag); + committed != nullptr && committed->resolution.item != itemNo) + { + Log.error("committed check '{}' completed with item {:#x} instead of {:#x}", + item_give_name(giveTag) != nullptr ? item_give_name(giveTag) : "", itemNo, + committed->resolution.item); + } + s_committedChecks.erase(giveTag); + notify_gives(item_give_name(giveTag), itemNo, giver, origin); +} + constexpr int kGiveMaxRetries = 5; struct QueuedGive { @@ -101,6 +115,7 @@ struct QueuedGive { uint8_t itemNo = 0; bool silent = false; bool resolveAtDispatch = false; + bool forced = false; }; std::deque s_giveQueue; @@ -111,6 +126,11 @@ bool s_inFlight = false; bool s_inFlightSpawned = false; bool s_dispatchingSilent = false; +bool has_forced_give() { + return std::any_of( + s_giveQueue.begin(), s_giveQueue.end(), [](const QueuedGive& give) { return give.forced; }); +} + bool safe_to_dispatch() { daAlink_c* link = daAlink_getAlinkActorClass(); if (link == nullptr) { @@ -142,13 +162,13 @@ bool safe_to_dispatch() { bool resolve_queued_give(const QueuedGive& give, ItemGiveOrigin origin, uint8_t& outItem) { outItem = give.itemNo; if (give.resolveAtDispatch) { - outItem = item_check(item_give_name(give.tag), give.itemNo, nullptr); + outItem = item_check_commit(give.tag, give.itemNo, nullptr).itemNo; } if (outItem != dItemNo_NONE_e) { return true; } - notify_gives(item_give_name(give.tag), dItemNo_NONE_e, nullptr, origin); + complete_check(dItemNo_NONE_e, give.tag, nullptr, origin); return false; } @@ -171,11 +191,40 @@ void dispatch_demo_give() { daAlink_c* link = daAlink_getAlinkActorClass(); dComIfGp_getEvent()->setGtItm(s_inFlightItem); - link->procCoGetItemInit(); + link->mProcID = daAlink_c::PROC_GET_ITEM; const s16 eventIndex = dComIfGp_getEventManager().getEventIdx(link, "DEFAULT_GETITEM", 0xFF); fopAcM_orderChangeEventId(link, eventIndex, 1, 0xFFFF); } +void dispatch_next_give() { + while (!s_giveQueue.empty()) { + while (!s_giveQueue.empty() && s_giveQueue.front().silent) { + const QueuedGive give = s_giveQueue.front(); + s_giveQueue.pop_front(); + dispatch_silent_give(give); + } + if (s_giveQueue.empty()) { + return; + } + + const QueuedGive give = s_giveQueue.front(); + s_giveQueue.pop_front(); + + uint8_t itemNo = 0; + if (!resolve_queued_give(give, ITEM_GIVE_ORIGIN_QUEUE, itemNo)) { + continue; + } + + s_inFlightGive = give; + s_inFlightItem = itemNo; + s_inFlightRetries = 0; + s_inFlight = true; + s_inFlightSpawned = false; + dispatch_demo_give(); + return; + } +} + } // namespace uint32_t item_give_tag(const char* name) { @@ -192,16 +241,47 @@ uint32_t item_give_tag(const char* name) { return tag; } -uint8_t item_check_tagged(uint32_t giveTag, uint8_t itemNo, fopAc_ac_c* giver) { +ItemCheckResolution item_check_resolve(uint32_t giveTag, uint8_t itemNo, fopAc_ac_c* giver) { + if (const auto* committed = s_committedChecks.find(giveTag); committed != nullptr) { + return committed->resolution; + } const char* name = item_give_name(giveTag); - return name != nullptr ? item_check(name, itemNo, giver) : itemNo; + return name != nullptr ? item_check_resolve(name, itemNo, giver) : + ItemCheckResolution{.item = itemNo, .display_item = itemNo}; } -void item_check_enqueue(const char* name, uint8_t itemNo) { - if (s_giveQueue.size() >= kGiveQueueLimit) { - Log.warn("item give queue is full; dropping check '{}'", name != nullptr ? name : ""); - return; +ItemCheckResult item_check_commit(uint32_t giveTag, uint8_t itemNo, fopAc_ac_c* giver) { + const char* name = item_give_name(giveTag); + if (name == nullptr) { + return {.tag = giveTag, .itemNo = itemNo, .displayItemNo = itemNo}; } + + if (const auto* committed = s_committedChecks.find(giveTag); committed != nullptr) { + if (committed->vanillaItem != itemNo) { + Log.error("committed check '{}' changed vanilla item from {:#x} to {:#x}", name, + committed->vanillaItem, itemNo); + } + return { + .tag = giveTag, + .itemNo = committed->resolution.item, + .displayItemNo = committed->resolution.display_item, + }; + } + + const auto& committed = s_committedChecks.commit( + giveTag, itemNo, [&] { return item_check_resolve(name, itemNo, giver); }); + return { + .tag = giveTag, + .itemNo = committed.resolution.item, + .displayItemNo = committed.resolution.display_item, + }; +} + +ItemCheckResult item_check_commit(const char* name, uint8_t itemNo, fopAc_ac_c* giver) { + return item_check_commit(item_give_tag(name), itemNo, giver); +} + +void item_check_enqueue_deferred(const char* name, uint8_t itemNo) { s_giveQueue.push_back({ .tag = item_give_tag(name), .itemNo = itemNo, @@ -209,6 +289,53 @@ void item_check_enqueue(const char* name, uint8_t itemNo) { }); } +bool item_check_enqueue(ItemCheckResult check, ItemGiveMode mode) { + auto* committed = s_committedChecks.find(check.tag); + if (committed == nullptr) { + Log.error("cannot enqueue uncommitted check '{}'", + item_give_name(check.tag) != nullptr ? item_give_name(check.tag) : ""); + return false; + } + if (committed->resolution.item != check.itemNo) { + Log.error("committed check '{}' changed item from {:#x} to {:#x}", + item_give_name(check.tag) != nullptr ? item_give_name(check.tag) : "", check.itemNo, + committed->resolution.item); + return false; + } + if (committed->queued) { + return false; + } + + committed->queued = true; + s_giveQueue.push_back({ + .tag = check.tag, + .itemNo = committed->resolution.item, + .silent = mode == ItemGiveMode::Silent, + .forced = mode == ItemGiveMode::ForcedDemo, + }); + if (mode == ItemGiveMode::ForcedDemo && !s_inFlight) { + dispatch_next_give(); + } + return true; +} + +void item_check_complete(ItemCheckResult check, fopAc_ac_c* giver) { + complete_check(check.itemNo, check.tag, giver, ITEM_GIVE_ORIGIN_GAME); +} + +void item_check_cancel(uint32_t giveTag) { + s_committedChecks.erase(giveTag); + std::erase_if(s_giveQueue, + [&](const QueuedGive& give) { return give.owner == nullptr && give.tag == giveTag; }); +} + +void item_check_clear_committed() { + std::erase_if(s_giveQueue, [&](const QueuedGive& give) { + return give.owner == nullptr && s_committedChecks.contains(give.tag); + }); + s_committedChecks.clear(); +} + void item_granted(uint8_t itemNo, uint32_t giveTag, fopAc_ac_c* giver) { ItemGiveOrigin origin = ITEM_GIVE_ORIGIN_GAME; if (s_dispatchingSilent) { @@ -218,7 +345,7 @@ void item_granted(uint8_t itemNo, uint32_t giveTag, fopAc_ac_c* giver) { s_inFlight = false; s_inFlightSpawned = false; } - notify_gives(item_give_name(giveTag), itemNo, giver, origin); + complete_check(itemNo, giveTag, giver, origin); } bool item_give_queue_dispatching() { @@ -236,17 +363,21 @@ uint32_t item_give_queue_take_tag() { namespace svc { void item_gives_tick() { - if ((!s_inFlight && s_giveQueue.empty()) || !safe_to_dispatch()) { + if (!s_inFlight && s_giveQueue.empty()) { return; } if (s_inFlight) { + if (!safe_to_dispatch()) { + return; + } if (++s_inFlightRetries > kGiveMaxRetries) { Log.error("item {:#x} for '{}' did not complete after {} attempts; dropping it", s_inFlightItem, item_give_name(s_inFlightGive.tag) != nullptr ? item_give_name(s_inFlightGive.tag) : "", kGiveMaxRetries); + item_check_cancel(s_inFlightGive.tag); s_inFlight = false; s_inFlightSpawned = false; return; @@ -256,29 +387,10 @@ void item_gives_tick() { return; } - while (!s_giveQueue.empty() && s_giveQueue.front().silent) { - const QueuedGive give = s_giveQueue.front(); - s_giveQueue.pop_front(); - dispatch_silent_give(give); - } - if (s_giveQueue.empty()) { + if (!has_forced_give() && !safe_to_dispatch()) { return; } - - const QueuedGive give = s_giveQueue.front(); - uint8_t itemNo = 0; - if (!resolve_queued_give(give, ITEM_GIVE_ORIGIN_QUEUE, itemNo)) { - s_giveQueue.pop_front(); - return; - } - - s_giveQueue.pop_front(); - s_inFlightGive = give; - s_inFlightItem = itemNo; - s_inFlightRetries = 0; - s_inFlight = true; - s_inFlightSpawned = false; - dispatch_demo_give(); + dispatch_next_give(); } void item_gives_clear() { @@ -289,12 +401,10 @@ void item_gives_clear() { s_giveQueue.clear(); s_inFlight = false; s_inFlightSpawned = false; + s_committedChecks.clear(); } ModResult item_give_enqueue(LoadedMod& mod, const char* checkName, uint8_t itemNo, uint32_t flags) { - if (s_giveQueue.size() >= kGiveQueueLimit) { - return MOD_UNAVAILABLE; - } s_giveQueue.push_back({ .owner = &mod, .tag = item_give_tag(checkName), diff --git a/src/dusk/mods/svc/flow.cpp b/src/dusk/mods/svc/flow.cpp index b55006c3b0..9c5af25e4c 100644 --- a/src/dusk/mods/svc/flow.cpp +++ b/src/dusk/mods/svc/flow.cpp @@ -11,6 +11,7 @@ #include "JSystem/JMessage/control.h" #include "JSystem/JMessage/processor.h" #include "JSystem/JMessage/resource.h" +#include "d/d_msg_class.h" #include #include @@ -467,11 +468,19 @@ bool valid_encoded_text(const uint8_t* text, size_t size) { if (text[offset] == 0) { return offset + 1 == size; } - if (text[offset] == 0x1a) { + if (text[offset] == JMessage::data::gcTagBegin) { if (offset + 2 > size || text[offset + 1] < 5 || text[offset + 1] > size - offset) { return false; } - offset += text[offset + 1]; + const size_t tagSize = text[offset + 1]; + const uint32_t tag = + MSGTAG_GROUP(text[offset + 2]) | read_bits(text + offset + 3); + const size_t argumentSize = tagSize - 5; + if (tag == MSGTAG_COLOR && argumentSize != 1 && argumentSize != 4 && argumentSize != 8) + { + return false; + } + offset += tagSize; } else { ++offset; } @@ -490,7 +499,7 @@ size_t encoded_text_size(const ResourceInfo& resource, const char* text) { if (bytes[offset] == 0) { return offset + 1; } - if (bytes[offset] == 0x1a) { + if (bytes[offset] == JMessage::data::gcTagBegin) { if (offset + 2 > maximum || bytes[offset + 1] < 5 || bytes[offset + 1] > maximum - offset) { diff --git a/src/dusk/mods/svc/registry.cpp b/src/dusk/mods/svc/registry.cpp index 68eeb58771..4f769c2dfe 100644 --- a/src/dusk/mods/svc/registry.cpp +++ b/src/dusk/mods/svc/registry.cpp @@ -214,6 +214,7 @@ void ModLoader::init_services() { &svc::g_overlayModule, &svc::g_textureModule, &svc::g_configModule, + &svc::g_uiModule_v1, &svc::g_uiModule, &svc::g_gameModule, &svc::g_cameraModule, diff --git a/src/dusk/mods/svc/registry.hpp b/src/dusk/mods/svc/registry.hpp index ba693dd958..90c3c44d84 100644 --- a/src/dusk/mods/svc/registry.hpp +++ b/src/dusk/mods/svc/registry.hpp @@ -72,6 +72,7 @@ extern const ServiceModule g_hookModule; extern const ServiceModule g_overlayModule; extern const ServiceModule g_textureModule; extern const ServiceModule g_configModule; +extern const ServiceModule g_uiModule_v1; extern const ServiceModule g_uiModule; extern const ServiceModule g_gameModule; extern const ServiceModule g_cameraModule; diff --git a/src/dusk/mods/svc/ui.cpp b/src/dusk/mods/svc/ui.cpp index 320d2549ae..8e5c61bf52 100644 --- a/src/dusk/mods/svc/ui.cpp +++ b/src/dusk/mods/svc/ui.cpp @@ -3,10 +3,13 @@ #include "config.hpp" #include "registry.hpp" #include "slot_map.hpp" +#include "ui_v1.hpp" #include #include "dusk/mod_loader.hpp" #include "dusk/mods/loader/loader.hpp" +#include "dusk/mods/log_buffer.hpp" +#include "dusk/ui/list.hpp" #include "dusk/ui/menu_bar.hpp" #include "dusk/ui/mod_window.hpp" #include "dusk/ui/modal.hpp" @@ -20,17 +23,33 @@ #include #include #include +#include #include #include +#include #include +#include #include #include +#include #include +#include #include #include #include "SDL3/SDL_clipboard.h" +namespace { + +constexpr size_t kUiControlSelectedSize = + offsetof(UiControlDesc, is_selected) + sizeof(UiPredicateFn); +constexpr size_t kUiControlStringSetModeSize = + offsetof(UiControlDesc, string_set_mode) + sizeof(UiStringSetMode); +constexpr size_t kUiListItemV21Size = offsetof(UiListItem, label) + sizeof(const char*); +constexpr size_t kUiListDescV21Size = offsetof(UiListDesc, user_data) + sizeof(void*); + +} // namespace + namespace dusk::mods::svc::ui_impl { namespace { @@ -43,6 +62,7 @@ enum class UiSlotKind : u8 { Text, Progress, Control, + List, Style, MenuTab, }; @@ -61,6 +81,8 @@ const char* slot_kind_name(UiSlotKind kind) { return "progress"; case UiSlotKind::Control: return "control"; + case UiSlotKind::List: + return "list"; case UiSlotKind::Style: return "style"; case UiSlotKind::MenuTab: @@ -79,6 +101,8 @@ struct UiSlot { // Pane payload ui::Pane* pane = nullptr; ui::Pane* helpPane = nullptr; + // List payload + ui::List* list = nullptr; // Window/Dialog payload (non-owning; the document stack owns the document) ui::Document* document = nullptr; UiWindowClosedFn onClosed = nullptr; @@ -248,18 +272,16 @@ void wire_callback_binding( if (!slot_live(guardHandle)) { return value; } - guarded_call(*modPtr, "control getter", [&] { - get(modPtr->context.get(), userData, &value); - }); + guarded_call( + *modPtr, "control getter", [&] { get(modPtr->context.get(), userData, &value); }); return value; }; const auto setValue = [modPtr, set, userData, guardHandle](const UiControlValue& value) { if (!slot_live(guardHandle)) { return; } - guarded_call(*modPtr, "control setter", [&] { - set(modPtr->context.get(), userData, &value); - }); + guarded_call( + *modPtr, "control setter", [&] { set(modPtr->context.get(), userData, &value); }); }; switch (desc.kind) { case UI_CONTROL_TOGGLE: @@ -280,6 +302,7 @@ void wire_callback_binding( }; break; case UI_CONTROL_STRING: + case UI_CONTROL_COLOR: spec.getString = [getValue]() -> Rml::String { const UiControlValue value = getValue(); return value.string_value != nullptr ? value.string_value : ""; @@ -358,7 +381,8 @@ bool wire_config_var_binding(LoadedMod& mod, const UiControlDesc& desc, ui::ModC } return true; } - case UI_CONTROL_STRING: { + case UI_CONTROL_STRING: + case UI_CONTROL_COLOR: { const auto find = [modPtr, varHandle] { return static_cast*>( config_find_var(*modPtr, varHandle, CONFIG_VAR_STRING)); @@ -401,9 +425,8 @@ void on_mod_window_destroyed(uint64_t handle) { const UiWindowClosedFn onClosed = released->value.onClosed; void* userData = released->value.onClosedUserData; if (mod != nullptr && onClosed != nullptr) { - guarded_call(*mod, "window on_closed callback", [&] { - onClosed(mod->context.get(), handle, userData); - }); + guarded_call(*mod, "window on_closed callback", + [&] { onClosed(mod->context.get(), handle, userData); }); } } @@ -439,10 +462,8 @@ void push_stacked_document(std::unique_ptr document) { } } -// Shared by dialog_push and dialog_add_action; the guard handle keeps a -// pressed callback from calling into a torn-down mod. ui::ModalAction make_dialog_action(LoadedMod& mod, uint64_t handle, const UiDialogAction& action) { - return { + ui::ModalAction result{ .label = action.label, .onPressed = [modPtr = &mod, handle, fn = action.on_pressed, userData = action.user_data, @@ -451,9 +472,8 @@ ui::ModalAction make_dialog_action(LoadedMod& mod, uint64_t handle, const UiDial return; // already being torn down } if (fn != nullptr) { - guarded_call(*modPtr, "dialog action callback", [&] { - fn(modPtr->context.get(), handle, userData); - }); + guarded_call(*modPtr, "dialog action callback", + [&] { fn(modPtr->context.get(), handle, userData); }); } // The callback may have closed the dialog already if (!keepOpen && dialog_open(handle)) { @@ -461,6 +481,17 @@ ui::ModalAction make_dialog_action(LoadedMod& mod, uint64_t handle, const UiDial } }, }; + if (action.is_disabled != nullptr) { + result.isDisabled = [modPtr = &mod, handle, fn = action.is_disabled, + userData = action.user_data] { + if (!dialog_open(handle)) { + return false; + } + return guarded_call(*modPtr, "dialog action is_disabled callback", false, + [&] { return fn(modPtr->context.get(), userData); }); + }; + } + return result; } } // namespace @@ -494,9 +525,8 @@ void ui_update_mods_panels(LoadedMod& mod) { if (!mod.active || panel.update == nullptr) { return; } - invoke_mod_ui_callback(mod, "mod UI panel update", [&](ModError* error) { - return panel.update(mod.context.get(), panel.userData, error); - }); + invoke_mod_ui_callback(mod, "mod UI panel update", + [&](ModError* error) { return panel.update(mod.context.get(), panel.userData, error); }); } ModResult ui_pane_add_section(LoadedMod& mod, uint64_t pane, const char* title) { @@ -568,15 +598,19 @@ ModResult ui_pane_add_control( spec.isModified = wrap_predicate(mod, desc.is_modified, desc.user_data, pane); switch (desc.kind) { case UI_CONTROL_BUTTON: - spec.kind = ui::ModControlSpec::Kind::Button; + case UI_CONTROL_GROUP: + spec.kind = desc.kind == UI_CONTROL_BUTTON ? ui::ModControlSpec::Kind::Button : + ui::ModControlSpec::Kind::Group; + if (desc.struct_size >= kUiControlSelectedSize) { + spec.isSelected = wrap_predicate(mod, desc.is_selected, desc.user_data, pane); + } spec.onPressed = [modPtr = &mod, fn = desc.on_pressed, userData = desc.user_data, guardHandle = pane] { if (!slot_live(guardHandle)) { return; } - guarded_call(*modPtr, "control on_pressed callback", [&] { - fn(modPtr->context.get(), userData); - }); + guarded_call(*modPtr, "control on_pressed callback", + [&] { fn(modPtr->context.get(), userData); }); }; break; case UI_CONTROL_TOGGLE: @@ -598,6 +632,15 @@ ModResult ui_pane_add_control( case UI_CONTROL_STRING: spec.kind = ui::ModControlSpec::Kind::String; spec.maxLength = desc.max_length < 1 ? -1 : desc.max_length; + spec.stringSetOnChange = desc.struct_size >= kUiControlStringSetModeSize && + desc.string_set_mode == UI_STRING_SET_ON_CHANGE; + break; + case UI_CONTROL_COLOR: + spec.kind = ui::ModControlSpec::Kind::Color; + spec.colorAlpha = desc.color_alpha; + for (size_t i = 0; i < desc.color_preset_count; ++i) { + spec.colorPresets.emplace_back(desc.color_presets[i]); + } break; case UI_CONTROL_SELECT: spec.kind = ui::ModControlSpec::Kind::Select; @@ -614,7 +657,7 @@ ModResult ui_pane_add_control( return MOD_INVALID_ARGUMENT; } - if (desc.kind != UI_CONTROL_BUTTON) { + if (desc.kind != UI_CONTROL_BUTTON && desc.kind != UI_CONTROL_GROUP) { if (desc.binding == UI_BINDING_CONFIG_VAR) { if (!wire_config_var_binding(mod, desc, spec)) { Log.error("[{}] pane_add_control: config var handle {:#x} is unknown or its type " @@ -641,6 +684,102 @@ ModResult ui_pane_add_control( return MOD_OK; } +ModResult ui_pane_add_list(LoadedMod& mod, uint64_t pane, const UiListDesc& desc, + std::vector items, uint64_t& outHandle) { + outHandle = 0; + auto* paneSlot = resolve(mod, pane, UiSlotKind::Pane, "pane_add_list"); + if (paneSlot == nullptr) { + return MOD_INVALID_ARGUMENT; + } + auto* paneComponent = paneSlot->pane; + + uint64_t handle = 0; + alloc_slot(mod, UiSlotKind::List, handle); + + ui::List::Props props; + props.items = std::move(items); + props.onPressed = [modPtr = &mod, handle, fn = desc.on_pressed, userData = desc.user_data]( + uint64_t key) { + if (!slot_live(handle)) { + return; + } + guarded_call(*modPtr, "list on_pressed callback", + [&] { fn(modPtr->context.get(), handle, key, userData); }); + }; + if (desc.is_selected != nullptr) { + props.isSelected = [modPtr = &mod, handle, fn = desc.is_selected, + userData = desc.user_data](uint64_t key) { + if (!slot_live(handle)) { + return false; + } + return guarded_call(*modPtr, "list is_selected callback", false, + [&] { return fn(modPtr->context.get(), handle, key, userData); }); + }; + } + if (desc.is_disabled != nullptr) { + props.isDisabled = [modPtr = &mod, handle, fn = desc.is_disabled, + userData = desc.user_data](uint64_t key) { + if (!slot_live(handle)) { + return false; + } + return guarded_call(*modPtr, "list is_disabled callback", false, + [&] { return fn(modPtr->context.get(), handle, key, userData); }); + }; + } + + auto& list = paneComponent->add_child(std::move(props)); + auto* listSlot = slot_from_handle(handle); + if (listSlot == nullptr) { + return MOD_ERROR; + } + listSlot->list = &list; + track_element(handle, *listSlot, *list.root()); + outHandle = handle; + return MOD_OK; +} + +ModResult ui_list_set_items(LoadedMod& mod, uint64_t handle, std::vector items) { + auto* slot = resolve(mod, handle, UiSlotKind::List, "list_set_items"); + if (slot == nullptr || slot->list == nullptr) { + return MOD_INVALID_ARGUMENT; + } + slot->list->set_items(std::move(items)); + return MOD_OK; +} + +ModResult ui_pane_add_group(LoadedMod& mod, uint64_t groupPaneHandle, uint64_t targetPaneHandle, + const UiGroupDesc& desc, uint64_t* outElem) { + auto* groupSlot = resolve(mod, groupPaneHandle, UiSlotKind::Pane, "pane_add_group"); + auto* targetSlot = resolve(mod, targetPaneHandle, UiSlotKind::Pane, "pane_add_group"); + if (groupSlot == nullptr || targetSlot == nullptr) { + return MOD_INVALID_ARGUMENT; + } + if (groupSlot->helpPane != targetSlot->pane) { + Log.error("[{}] pane_add_group: panes are not a paired tab layout", mod.metadata.id); + return MOD_UNSUPPORTED; + } + + auto* groupPane = groupSlot->pane; + auto* targetPane = targetSlot->pane; + auto& button = groupPane->add_group_button(ui::GroupButton::Props{.text = desc.label}); + groupPane->register_control(button, *targetPane, + [modPtr = &mod, groupPaneHandle, targetPaneHandle, build = desc.build, + userData = desc.user_data](ui::Pane&) { + if (!slot_live(groupPaneHandle) || !slot_live(targetPaneHandle) || !modPtr->active) { + return; + } + invoke_mod_ui_callback(*modPtr, "mod UI group build", [&](ModError* error) { + return build(modPtr->context.get(), targetPaneHandle, userData, error); + }); + }); + + if (outElem != nullptr) { + auto& elemSlot = alloc_slot(mod, UiSlotKind::Control, *outElem); + track_element(*outElem, elemSlot, *button.root()); + } + return MOD_OK; +} + ModResult ui_elem_set_text(LoadedMod& mod, uint64_t elem, const char* text) { auto* slot = resolve(mod, elem, UiSlotKind::Text, "elem_set_text"); if (slot == nullptr) { @@ -798,20 +937,32 @@ ModResult ui_dialog_push(LoadedMod& mod, const UiDialogDesc& desc, uint64_t& out return; // already being torn down } if (fn != nullptr) { - guarded_call(*modPtr, "dialog on_dismiss callback", [&] { - fn(modPtr->context.get(), handle, userData); - }); + guarded_call(*modPtr, "dialog on_dismiss callback", + [&] { fn(modPtr->context.get(), handle, userData); }); } if (dialog_open(handle)) { static_cast(modal).close(); } }; + auto* actionData = reinterpret_cast(desc.actions); for (size_t i = 0; i < desc.action_count; ++i) { - props.actions.push_back(make_dialog_action(mod, handle, desc.actions[i])); + const auto& action = *reinterpret_cast(actionData); + props.actions.push_back(make_dialog_action(mod, handle, action)); + actionData += action.struct_size; } - auto dialog = - std::make_unique(std::move(props), [handle] { on_mod_dialog_destroyed(handle); }); + auto dialog = std::make_unique( + std::move(props), [handle] { on_mod_dialog_destroyed(handle); }); + if (desc.build != nullptr) { + auto& pane = dialog->content_pane(); + const uint64_t paneHandle = wrap_pane(mod, pane, nullptr); + invoke_mod_ui_callback(mod, "mod UI dialog build", [&](ModError* error) { + return desc.build(mod.context.get(), paneHandle, desc.user_data, error); + }); + if (!mod.active) { + return MOD_ERROR; + } + } if (auto* slot = slot_from_handle(handle)) { slot->document = dialog.get(); } @@ -848,15 +999,6 @@ ModResult ui_dialog_set_icon(LoadedMod& mod, uint64_t handle, const char* icon) return MOD_OK; } -ModResult ui_dialog_add_action(LoadedMod& mod, uint64_t handle, const UiDialogAction& action) { - auto* slot = resolve(mod, handle, UiSlotKind::Dialog, "dialog_add_action"); - if (slot == nullptr || slot->document == nullptr) { - return MOD_INVALID_ARGUMENT; - } - static_cast(slot->document)->add_action(make_dialog_action(mod, handle, action)); - return MOD_OK; -} - ModResult ui_register_menu_tab(LoadedMod& mod, const UiMenuTabDesc& desc, uint64_t& outHandle) { outHandle = 0; for (const auto& [owner, tabs] : s_modMenuTabs) { @@ -915,9 +1057,8 @@ std::vector ui_mod_menu_tabs() { if (!slot_live(handle) || !modPtr->active) { return; // registered by a since-unloaded mod image } - guarded_call(*modPtr, "menu tab on_selected callback", [&] { - fn(modPtr->context.get(), userData); - }); + guarded_call(*modPtr, "menu tab on_selected callback", + [&] { fn(modPtr->context.get(), userData); }); }}); } } @@ -1038,7 +1179,8 @@ void ui_remove_mod(LoadedMod& mod) { } } -ModResult ui_get_clipboard_text(LoadedMod& mod, char* buffer, size_t bufferSize, size_t* outLength) { +ModResult ui_get_clipboard_text( + LoadedMod& mod, char* buffer, size_t bufferSize, size_t* outLength) { if (outLength != nullptr) { *outLength = 0; } @@ -1082,21 +1224,48 @@ namespace { // Validation of the tagged control descriptor: required fields per kind/binding. Value // translation and cvar wiring live in loader/ui.cpp. +bool valid_color_preset(const char* value, bool alpha) { + const std::string_view text{value}; + if (text == "rainbow") { + return true; + } + if (text.size() != 6 && (!alpha || text.size() != 8)) { + return false; + } + return std::ranges::all_of(text, [](char c) { + return (c >= '0' && c <= '9') || (c >= 'a' && c <= 'f') || (c >= 'A' && c <= 'F'); + }); +} + bool valid_control_desc(const UiControlDesc& desc) { - if (desc.struct_size < sizeof(UiControlDesc) || desc.label == nullptr) { + constexpr size_t kLegacyDescSize = offsetof(UiControlDesc, color_presets); + constexpr size_t kColorDescSize = offsetof(UiControlDesc, is_selected); + if (desc.struct_size < kLegacyDescSize || desc.label == nullptr) { return false; } switch (desc.kind) { case UI_CONTROL_BUTTON: + case UI_CONTROL_GROUP: return desc.on_pressed != nullptr; case UI_CONTROL_TOGGLE: case UI_CONTROL_NUMBER: case UI_CONTROL_STRING: case UI_CONTROL_SELECT: break; + case UI_CONTROL_COLOR: + if (desc.struct_size < kColorDescSize) { + return false; + } + break; default: return false; } + if (desc.kind == UI_CONTROL_STRING && desc.struct_size >= kUiControlStringSetModeSize && + desc.string_set_mode != UI_STRING_SET_ON_COMMIT && + desc.string_set_mode != UI_STRING_SET_ON_CHANGE) + { + return false; + } if (desc.kind == UI_CONTROL_SELECT) { if (desc.options == nullptr || desc.option_count == 0) { return false; @@ -1107,6 +1276,18 @@ bool valid_control_desc(const UiControlDesc& desc) { } } } + if (desc.kind == UI_CONTROL_COLOR && desc.color_preset_count != 0) { + if (desc.color_presets == nullptr) { + return false; + } + for (size_t i = 0; i < desc.color_preset_count; ++i) { + if (desc.color_presets[i] == nullptr || + !valid_color_preset(desc.color_presets[i], desc.color_alpha)) + { + return false; + } + } + } switch (desc.binding) { case UI_BINDING_CALLBACKS: return desc.get != nullptr && desc.set != nullptr; @@ -1117,6 +1298,36 @@ bool valid_control_desc(const UiControlDesc& desc) { } } +bool copy_list_items( + const UiListItem* items, size_t itemCount, std::vector& outItems) { + if (itemCount != 0 && items == nullptr) { + return false; + } + + std::vector copy; + copy.reserve(itemCount); + std::unordered_set keys; + keys.reserve(itemCount); + auto cursor = reinterpret_cast(items); + for (size_t i = 0; i < itemCount; ++i) { + const auto* item = reinterpret_cast(cursor); + const size_t recordSize = item->struct_size; + if (recordSize < kUiListItemV21Size || recordSize % alignof(UiListItem) != 0 || + cursor > std::numeric_limits::max() - recordSize) + { + return false; + } + if (item->label == nullptr || !keys.insert(item->key).second) { + return false; + } + copy.push_back({.key = item->key, .label = item->label}); + cursor += recordSize; + } + + outItems = std::move(copy); + return true; +} + ModResult ui_register_mods_panel(ModContext* context, const UiModsPanelDesc* desc) { auto* mod = mod_from_context(context); if (mod == nullptr || desc == nullptr || desc->struct_size < sizeof(UiModsPanelDesc) || @@ -1183,6 +1394,59 @@ ModResult ui_pane_add_control(ModContext* context, UiElementHandle pane, const U return ui_impl::ui_pane_add_control(*mod, pane, *desc, outElem); } +ModResult ui_pane_add_list( + ModContext* context, UiElementHandle pane, const UiListDesc* desc, UiListHandle* outList) { + if (outList != nullptr) { + *outList = 0; + } + auto* mod = mod_from_context(context); + if (mod == nullptr || pane == 0 || desc == nullptr || desc->struct_size < kUiListDescV21Size || + desc->on_pressed == nullptr) + { + return MOD_INVALID_ARGUMENT; + } + std::vector items; + if ((desc->items != nullptr || desc->item_count > 0) && + !copy_list_items(desc->items, desc->item_count, items)) + { + return MOD_INVALID_ARGUMENT; + } + + uint64_t handle = 0; + const ModResult result = ui_impl::ui_pane_add_list(*mod, pane, *desc, std::move(items), handle); + if (result == MOD_OK && outList != nullptr) { + *outList = handle; + } + return result; +} + +ModResult ui_list_set_items( + ModContext* context, UiListHandle list, const UiListItem* items, size_t itemCount) { + auto* mod = mod_from_context(context); + if (mod == nullptr || list == 0) { + return MOD_INVALID_ARGUMENT; + } + std::vector copiedItems; + if (!copy_list_items(items, itemCount, copiedItems)) { + return MOD_INVALID_ARGUMENT; + } + return ui_impl::ui_list_set_items(*mod, list, std::move(copiedItems)); +} + +ModResult ui_pane_add_group(ModContext* context, UiElementHandle groupPane, + UiElementHandle targetPane, const UiGroupDesc* desc, UiElementHandle* outElem) { + if (outElem != nullptr) { + *outElem = 0; + } + auto* mod = mod_from_context(context); + if (mod == nullptr || groupPane == 0 || targetPane == 0 || desc == nullptr || + desc->struct_size < sizeof(UiGroupDesc) || desc->label == nullptr || desc->build == nullptr) + { + return MOD_INVALID_ARGUMENT; + } + return ui_impl::ui_pane_add_group(*mod, groupPane, targetPane, *desc, outElem); +} + ModResult ui_elem_set_text(ModContext* context, UiElementHandle elem, const char* text) { auto* mod = mod_from_context(context); if (mod == nullptr || elem == 0 || text == nullptr) { @@ -1259,10 +1523,15 @@ ModResult ui_dialog_push(ModContext* context, const UiDialogDesc* desc, UiDialog { return MOD_INVALID_ARGUMENT; } + auto* actionData = reinterpret_cast(desc->actions); for (size_t i = 0; i < desc->action_count; ++i) { - if (desc->actions[i].label == nullptr) { + const auto* action = reinterpret_cast(actionData); + if (action->struct_size < sizeof(UiDialogAction) || + action->struct_size % alignof(UiDialogAction) != 0 || action->label == nullptr) + { return MOD_INVALID_ARGUMENT; } + actionData += action->struct_size; } uint64_t handle = 0; const auto result = ui_impl::ui_dialog_push(*mod, *desc, handle); @@ -1397,16 +1666,8 @@ ModResult ui_dialog_set_icon(ModContext* context, UiDialogHandle dialog, const c return ui_impl::ui_dialog_set_icon(*mod, dialog, icon); } -ModResult ui_dialog_add_action( - ModContext* context, UiDialogHandle dialog, const UiDialogAction* action) { - auto* mod = mod_from_context(context); - if (mod == nullptr || dialog == 0 || action == nullptr || action->label == nullptr) { - return MOD_INVALID_ARGUMENT; - } - return ui_impl::ui_dialog_add_action(*mod, dialog, *action); -} - -ModResult ui_get_clipboard_text(ModContext* ctx, char* buffer, size_t bufferSize, size_t* outLength) { +ModResult ui_get_clipboard_text( + ModContext* ctx, char* buffer, size_t bufferSize, size_t* outLength) { auto* mod = mod_from_context(ctx); if (mod == nullptr || (buffer == nullptr && bufferSize != 0)) { return MOD_INVALID_ARGUMENT; @@ -1423,8 +1684,55 @@ ModResult ui_set_clipboard_text(ModContext* ctx, const char* text) { return ui_impl::ui_set_clipboard_text(*mod, text); } -constexpr UiService s_uiService{ - .header = SERVICE_HEADER(UiService, UI_SERVICE_MAJOR, UI_SERVICE_MINOR), +ModResult ui_v1_dialog_push( + ModContext* context, const ui_v1::UiDialogDesc* desc, UiDialogHandle* outDialog) { + if (outDialog != nullptr) { + *outDialog = 0; + } + constexpr size_t kLegacyDescSize = offsetof(ui_v1::UiDialogDesc, build); + if (desc == nullptr || desc->struct_size < kLegacyDescSize || desc->actions == nullptr || + desc->action_count == 0) + { + return MOD_INVALID_ARGUMENT; + } + + std::vector actions; + actions.reserve(desc->action_count); + for (size_t i = 0; i < desc->action_count; ++i) { + UiDialogAction action = UI_DIALOG_ACTION_INIT; + action.label = desc->actions[i].label; + action.on_pressed = desc->actions[i].on_pressed; + action.user_data = desc->actions[i].user_data; + action.keep_open = desc->actions[i].keep_open; + actions.push_back(action); + } + + UiDialogDesc translated = UI_DIALOG_DESC_INIT; + translated.title = desc->title; + translated.body_rml = desc->body_rml; + translated.variant = desc->variant; + translated.icon = desc->icon; + translated.actions = actions.data(); + translated.action_count = actions.size(); + translated.on_dismiss = desc->on_dismiss; + translated.user_data = desc->user_data; + translated.build = desc->struct_size >= sizeof(ui_v1::UiDialogDesc) ? desc->build : nullptr; + return ui_dialog_push(context, &translated, outDialog); +} + +ModResult ui_v1_dialog_add_action( + ModContext* context, UiDialogHandle, const ui_v1::UiDialogAction*) { + auto* mod = mod_from_context(context); + if (mod == nullptr) { + return MOD_INVALID_ARGUMENT; + } + log::write( + mod->metadata.id, LOG_LEVEL_WARN, "UiService v1 dialog_add_action is no longer supported"); + return MOD_UNSUPPORTED; +} + +constexpr ui_v1::UiService s_uiService_v1{ + .header = SERVICE_HEADER(ui_v1::UiService, ui_v1::kMajorVersion, ui_v1::kMinorVersion), .register_mods_panel = ui_register_mods_panel, .pane_add_section = ui_pane_add_section, .pane_add_text = ui_pane_add_text, @@ -1437,11 +1745,11 @@ constexpr UiService s_uiService{ .elem_set_class = ui_elem_set_class, .window_push = ui_window_push, .window_close = ui_window_close, - .dialog_push = ui_dialog_push, + .dialog_push = ui_v1_dialog_push, .dialog_close = ui_dialog_close, .dialog_set_body = ui_dialog_set_body, .dialog_set_icon = ui_dialog_set_icon, - .dialog_add_action = ui_dialog_add_action, + .dialog_add_action = ui_v1_dialog_add_action, .is_any_document_visible = ui_is_any_document_visible, .register_styles = ui_register_styles, .register_styles_file = ui_register_styles_file, @@ -1451,6 +1759,39 @@ constexpr UiService s_uiService{ .push_toast = ui_push_toast, .get_clipboard_text = ui_get_clipboard_text, .set_clipboard_text = ui_set_clipboard_text, + .pane_add_group = ui_pane_add_group, +}; + +constexpr UiService s_uiService{ + .header = SERVICE_HEADER(UiService, UI_SERVICE_MAJOR, UI_SERVICE_MINOR), + .register_mods_panel = ui_register_mods_panel, + .pane_add_section = ui_pane_add_section, + .pane_add_text = ui_pane_add_text, + .pane_add_rml = ui_pane_add_rml, + .pane_add_progress = ui_pane_add_progress, + .pane_add_control = ui_pane_add_control, + .pane_add_group = ui_pane_add_group, + .elem_set_text = ui_elem_set_text, + .elem_set_rml = ui_elem_set_rml, + .elem_set_progress = ui_elem_set_progress, + .elem_set_class = ui_elem_set_class, + .window_push = ui_window_push, + .window_close = ui_window_close, + .dialog_push = ui_dialog_push, + .dialog_close = ui_dialog_close, + .dialog_set_body = ui_dialog_set_body, + .dialog_set_icon = ui_dialog_set_icon, + .is_any_document_visible = ui_is_any_document_visible, + .register_styles = ui_register_styles, + .register_styles_file = ui_register_styles_file, + .unregister_styles = ui_unregister_styles, + .register_menu_tab = ui_register_menu_tab, + .unregister_menu_tab = ui_unregister_menu_tab, + .push_toast = ui_push_toast, + .get_clipboard_text = ui_get_clipboard_text, + .set_clipboard_text = ui_set_clipboard_text, + .pane_add_list = ui_pane_add_list, + .list_set_items = ui_list_set_items, }; } // namespace @@ -1467,6 +1808,13 @@ std::vector ui_mod_menu_tabs() { return ui_impl::ui_mod_menu_tabs(); } +constinit const ServiceModule g_uiModule_v1{ + .id = UI_SERVICE_ID, + .majorVersion = ui_v1::kMajorVersion, + .minorVersion = ui_v1::kMinorVersion, + .service = &s_uiService_v1, +}; + constinit const ServiceModule g_uiModule{ .id = UI_SERVICE_ID, .majorVersion = UI_SERVICE_MAJOR, diff --git a/src/dusk/mods/svc/ui_v1.hpp b/src/dusk/mods/svc/ui_v1.hpp new file mode 100644 index 0000000000..ef70479f8e --- /dev/null +++ b/src/dusk/mods/svc/ui_v1.hpp @@ -0,0 +1,82 @@ +#pragma once + +#include "mods/svc/ui.h" + +namespace dusk::mods::svc::ui_v1 { + +constexpr uint16_t kMajorVersion = 1; +constexpr uint16_t kMinorVersion = 5; + +struct UiDialogAction { + const char* label; + UiDialogActionFn on_pressed; + void* user_data; + bool keep_open; +}; + +struct UiDialogDesc { + uint32_t struct_size; + const char* title; + const char* body_rml; + UiDialogVariant variant; + const char* icon; + const UiDialogAction* actions; + size_t action_count; + UiDialogActionFn on_dismiss; + void* user_data; + UiPaneBuildFn build; +}; + +struct UiService { + ServiceHeader header; + + ModResult (*register_mods_panel)(ModContext* ctx, const UiModsPanelDesc* desc); + ModResult (*pane_add_section)(ModContext* ctx, UiElementHandle pane, const char* title); + ModResult (*pane_add_text)( + ModContext* ctx, UiElementHandle pane, const char* text, UiElementHandle* out_elem); + ModResult (*pane_add_rml)( + ModContext* ctx, UiElementHandle pane, const char* rml, UiElementHandle* out_elem); + ModResult (*pane_add_progress)( + ModContext* ctx, UiElementHandle pane, float value, UiElementHandle* out_elem); + ModResult (*pane_add_control)(ModContext* ctx, UiElementHandle pane, const UiControlDesc* desc, + UiElementHandle* out_elem); + + ModResult (*elem_set_text)(ModContext* ctx, UiElementHandle elem, const char* text); + ModResult (*elem_set_rml)(ModContext* ctx, UiElementHandle elem, const char* rml); + ModResult (*elem_set_progress)(ModContext* ctx, UiElementHandle elem, float value); + ModResult (*elem_set_class)( + ModContext* ctx, UiElementHandle elem, const char* name, bool active); + + ModResult (*window_push)(ModContext* ctx, const UiWindowDesc* desc, UiWindowHandle* out_window); + ModResult (*window_close)(ModContext* ctx, UiWindowHandle window); + + ModResult (*dialog_push)(ModContext* ctx, const UiDialogDesc* desc, UiDialogHandle* out_dialog); + ModResult (*dialog_close)(ModContext* ctx, UiDialogHandle dialog); + ModResult (*dialog_set_body)(ModContext* ctx, UiDialogHandle dialog, const char* body_rml); + ModResult (*dialog_set_icon)(ModContext* ctx, UiDialogHandle dialog, const char* icon); + ModResult (*dialog_add_action)( + ModContext* ctx, UiDialogHandle dialog, const UiDialogAction* action); + + ModResult (*is_any_document_visible)(ModContext* ctx, bool* out_visible); + + ModResult (*register_styles)( + ModContext* ctx, UiStyleScope scope, const char* rcss, UiStyleHandle* out_style); + ModResult (*register_styles_file)( + ModContext* ctx, UiStyleScope scope, const char* path, UiStyleHandle* out_style); + ModResult (*unregister_styles)(ModContext* ctx, UiStyleHandle style); + + ModResult (*register_menu_tab)( + ModContext* ctx, const UiMenuTabDesc* desc, UiMenuTabHandle* out_tab); + ModResult (*unregister_menu_tab)(ModContext* ctx, UiMenuTabHandle tab); + + ModResult (*push_toast)(ModContext* ctx, const UiToastDesc* desc); + + ModResult (*get_clipboard_text)( + ModContext* ctx, char* buffer, size_t bufferSize, size_t* outLength); + ModResult (*set_clipboard_text)(ModContext* ctx, const char* text); + + ModResult (*pane_add_group)(ModContext* ctx, UiElementHandle group_pane, + UiElementHandle target_pane, const UiGroupDesc* desc, UiElementHandle* out_elem); +}; + +} // namespace dusk::mods::svc::ui_v1 diff --git a/src/dusk/settings.cpp b/src/dusk/settings.cpp index a6e01a68b2..25ae768dac 100644 --- a/src/dusk/settings.cpp +++ b/src/dusk/settings.cpp @@ -1,6 +1,7 @@ #include "dusk/settings.h" #include #include "dusk/config.hpp" +#include "dusk/ui/ui.hpp" #include "dusk/game_mode.hpp" namespace dusk { @@ -16,6 +17,7 @@ UserSettings g_userSettings = { .rememberWindowSize {"video.rememberWindowSize", false}, .lastWindowWidth {"video.lastWindowWidth", 0}, .lastWindowHeight {"video.lastWindowHeight", 0}, + .uiScale {"video.uiScale", 100}, }, .audio = { @@ -230,6 +232,8 @@ void registerSettings() { Register(g_userSettings.video.rememberWindowSize); Register(g_userSettings.video.lastWindowWidth); Register(g_userSettings.video.lastWindowHeight); + Register(g_userSettings.video.uiScale, + [](const int&, const int&) { dusk::ui::apply_scale(); }); // Audio Register(g_userSettings.audio.masterVolume); diff --git a/src/dusk/settings.h b/src/dusk/settings.h index 0f6f61f36e..48f9ed28c6 100644 --- a/src/dusk/settings.h +++ b/src/dusk/settings.h @@ -145,6 +145,7 @@ struct UserSettings { ConfigVar rememberWindowSize; ConfigVar lastWindowWidth; ConfigVar lastWindowHeight; + ConfigVar uiScale; } video; struct { diff --git a/src/dusk/ui/achievements.cpp b/src/dusk/ui/achievements.cpp index 9d25f1d82a..905fa57f59 100644 --- a/src/dusk/ui/achievements.cpp +++ b/src/dusk/ui/achievements.cpp @@ -185,8 +185,6 @@ AchievementsWindow::AchievementsWindow() { *confirmingAll = false; clearAllPtr->set_text("Clear All Achievements"); }); - - pane.finalize(); }); } } diff --git a/src/dusk/ui/color_input.cpp b/src/dusk/ui/color_input.cpp new file mode 100644 index 0000000000..9d3241f41c --- /dev/null +++ b/src/dusk/ui/color_input.cpp @@ -0,0 +1,744 @@ +#include "color_input.hpp" + +#include "button.hpp" +#include "input.hpp" +#include "nav_group.hpp" + +#include "m_Do/m_Do_audio.h" + +#include +#include + +#include +#include +#include +#include +#include + +namespace dusk::ui { +namespace { + +// These dimensions must match the controls in res/rml/popover.rcss. +constexpr float kSvWidthDp = 240.0f; +constexpr float kSvHeightDp = 150.0f; +constexpr float kBarHeightDp = 14.0f; +constexpr float kCursorDp = 14.0f; + +constexpr size_t kHistoryLimit = 8; +constexpr int kSwatchColumns = 8; +constexpr float kSvAnalogRate = 0.7f; +constexpr float kHueAnalogRate = 240.0f; +constexpr float kAlphaAnalogRate = 0.7f; +constexpr float kSvNudge = 1.0f / 255.0f; +constexpr float kHueNudge = 1.0f; +constexpr float kAlphaNudge = 1.0f / 255.0f; + +std::vector sColorHistory; + +bool directional_command(NavCommand command) { + return command == NavCommand::Up || command == NavCommand::Down || + command == NavCommand::Left || command == NavCommand::Right; +} + +float analog_response(float value) { + return value * std::abs(value); +} + +class AdjustmentRegion : public Component { +public: + struct Props { + std::function begin; + std::function cancel; + std::function nudge; + std::function adjust; + }; + + AdjustmentRegion(Rml::Element* root, Props props) : Component{root}, mProps{std::move(props)} { + listen(mRoot, Rml::EventId::Keydown, [this](Rml::Event& event) { + const auto command = map_nav_event(event); + if (command == NavCommand::Confirm) { + if (mActive) { + finish(); + } else { + if (mProps.begin) { + mProps.begin(); + } + mActive = true; + mAnalogReady = mAxis.x == 0.0f && mAxis.y == 0.0f; + mRoot->SetClass("adjusting", true); + } + event.StopPropagation(); + return; + } + if (command == NavCommand::Cancel && mActive) { + if (mProps.cancel) { + mProps.cancel(); + } + finish(); + event.StopPropagation(); + return; + } + if (directional_command(command) && (mActive || mAwaitingNeutral)) { + if (mActive && mAxis.x == 0.0f && mAxis.y == 0.0f && mProps.nudge) { + mProps.nudge(command); + } + event.StopPropagation(); + } + }); + listen(mRoot, Rml::String{input::kNavAxisEvent}, [this](Rml::Event& event) { + mAxis = { + event.GetParameter("x", 0.0f), + event.GetParameter("y", 0.0f), + }; + if (mAxis.x == 0.0f && mAxis.y == 0.0f) { + mAwaitingNeutral = false; + mAnalogReady = true; + } + const float deltaSeconds = event.GetParameter("dt", 0.0f); + if (mActive && mAnalogReady && deltaSeconds > 0.0f && mProps.adjust) { + mProps.adjust(mAxis.x, mAxis.y, deltaSeconds); + } + }); + listen(mRoot, Rml::EventId::Blur, [this](Rml::Event&) { + if (mActive) { + finish(); + } + }); + } + +private: + void finish() { + mActive = false; + mAnalogReady = false; + mAwaitingNeutral = mAxis.x != 0.0f || mAxis.y != 0.0f; + mRoot->SetClass("adjusting", false); + } + + Props mProps; + Rml::Vector2f mAxis; + bool mActive = false; + bool mAnalogReady = false; + bool mAwaitingNeutral = false; +}; + +const std::vector& default_presets() { + static const std::vector presets = { + "ff4d4d", + "ff8a3d", + "ffd43b", + "61c454", + "3dc7c2", + "4d88ff", + "8b5cf6", + "e56aa6", + "8b6a45", + "ffffff", + "888888", + "202020", + }; + return presets; +} + +int hex_digit(char value) { + if (value >= '0' && value <= '9') { + return value - '0'; + } + if (value >= 'a' && value <= 'f') { + return value - 'a' + 10; + } + if (value >= 'A' && value <= 'F') { + return value - 'A' + 10; + } + return -1; +} + +std::optional parse_color(std::string_view value, bool alpha) { + if (value.starts_with('#')) { + value.remove_prefix(1); + } + if (value.size() != 6 && (!alpha || value.size() != 8)) { + return std::nullopt; + } + + uint8_t channels[4] = {0, 0, 0, 255}; + for (size_t i = 0; i < value.size() / 2; ++i) { + const int high = hex_digit(value[i * 2]); + const int low = hex_digit(value[i * 2 + 1]); + if (high < 0 || low < 0) { + return std::nullopt; + } + channels[i] = static_cast((high << 4) | low); + } + return Rml::Colourb{channels[0], channels[1], channels[2], channels[3]}; +} + +Rml::String normalize_value(Rml::String value, bool alpha) { + if (value == "rainbow") { + return value; + } + const auto color = parse_color(value, alpha); + if (!color.has_value()) { + return value; + } + if (alpha && color->alpha != 255) { + return fmt::format( + "{:02x}{:02x}{:02x}{:02x}", color->red, color->green, color->blue, color->alpha); + } + return fmt::format("{:02x}{:02x}{:02x}", color->red, color->green, color->blue); +} + +Rml::String css_color(Rml::Colourb color) { + return fmt::format("rgba({},{},{},{})", color.red, color.green, color.blue, color.alpha); +} + +Rml::String format_color(Rml::Colourb color, bool hex, bool alpha) { + if (hex) { + if (alpha && color.alpha != 255) { + return fmt::format( + "#{:02X}{:02X}{:02X}{:02X}", color.red, color.green, color.blue, color.alpha); + } + return fmt::format("#{:02X}{:02X}{:02X}", color.red, color.green, color.blue); + } + if (alpha) { + return fmt::format("rgba({}, {}, {}, {:.0f}%)", color.red, color.green, color.blue, + static_cast(color.alpha) / 255.0f * 100.0f); + } + return fmt::format("rgb({}, {}, {})", color.red, color.green, color.blue); +} + +Rml::Colourb hsv_to_rgb(float hue, float sat, float val, float alpha) { + hue -= 360.0f * std::floor(hue / 360.0f); + const float chroma = val * sat; + const float intermediate = chroma * (1.0f - std::abs(std::fmod(hue / 60.0f, 2.0f) - 1.0f)); + const float offset = val - chroma; + float red = 0.0f; + float green = 0.0f; + float blue = 0.0f; + switch (static_cast(hue / 60.0f) % 6) { + case 0: + red = chroma; + green = intermediate; + break; + case 1: + red = intermediate; + green = chroma; + break; + case 2: + green = chroma; + blue = intermediate; + break; + case 3: + green = intermediate; + blue = chroma; + break; + case 4: + red = intermediate; + blue = chroma; + break; + case 5: + default: + red = chroma; + blue = intermediate; + break; + } + const auto toByte = [](float value) { + return static_cast(std::clamp(value, 0.0f, 1.0f) * 255.0f + 0.5f); + }; + return {toByte(red + offset), toByte(green + offset), toByte(blue + offset), toByte(alpha)}; +} + +void rgb_to_hsv(Rml::Colourb color, float& hue, float& sat, float& val) { + const float red = static_cast(color.red) / 255.0f; + const float green = static_cast(color.green) / 255.0f; + const float blue = static_cast(color.blue) / 255.0f; + const float maxChannel = std::max({red, green, blue}); + const float minChannel = std::min({red, green, blue}); + const float delta = maxChannel - minChannel; + + val = maxChannel; + sat = maxChannel > 0.0f ? delta / maxChannel : 0.0f; + if (delta <= 0.0f) { + hue = 0.0f; + return; + } + if (maxChannel == red) { + hue = 60.0f * std::fmod((green - blue) / delta + 6.0f, 6.0f); + } else if (maxChannel == green) { + hue = 60.0f * ((blue - red) / delta + 2.0f); + } else { + hue = 60.0f * ((red - green) / delta + 4.0f); + } +} + +void apply_swatch(Rml::Element* element, const Rml::String& value, bool alpha) { + element->RemoveProperty("background-color"); + element->RemoveProperty("decorator"); + element->SetClass("empty", false); + element->SetClass("rainbow", value == "rainbow"); + if (value == "rainbow") { + element->SetProperty("decorator", "linear-gradient(90deg, #ff4d4d, #ffd43b, #61c454, " + "#3dc7c2, #4d88ff, #8b5cf6, #e56aa6)"); + return; + } + const auto color = parse_color(value, alpha); + if (!color.has_value()) { + element->SetClass("empty", true); + return; + } + element->SetProperty("background-color", css_color(*color)); +} + +void remember_color(Rml::String value, bool alpha) { + value = normalize_value(std::move(value), alpha); + if (value != "rainbow" && !parse_color(value, alpha).has_value()) { + return; + } + std::erase(sColorHistory, value); + sColorHistory.insert(sColorHistory.begin(), std::move(value)); + if (sColorHistory.size() > kHistoryLimit) { + sColorHistory.resize(kHistoryLimit); + } +} + +} // namespace + +ColorInput::ColorInput(Rml::Element* parent, Props props) + : BaseControlledSelectButton{parent, {.key = props.key, .submit = false}}, + mProps{std::move(props)} { + mRoot->SetClass("color-input", true); + mSwatch = append(mRoot, "color-swatch"); + refresh_swatch(); +} + +ColorInput::~ColorInput() { + if (mPicker != nullptr) { + mPicker->on_close(nullptr); + mPicker->on_focus(nullptr); + mPicker->dismiss(); + } +} + +void ColorInput::update() { + refresh_swatch(); + if (mPickerNavigation != nullptr) { + mPickerNavigation->update(); + } + BaseControlledSelectButton::update(); +} + +bool ColorInput::modified() const { + return mProps.isModified ? mProps.isModified() : BaseControlledSelectButton::modified(); +} + +bool ColorInput::disabled() const { + return mProps.isDisabled ? mProps.isDisabled() : BaseControlledSelectButton::disabled(); +} + +Rml::String ColorInput::format_value() { + const Rml::String value = mProps.getValue ? mProps.getValue() : ""; + if (value == "rainbow") { + return "Rainbow"; + } + const auto color = parse_color(value, mProps.alpha); + if (color.has_value()) { + return format_color(*color, mHexFormat, mProps.alpha); + } + return value.empty() ? "Default" : value; +} + +bool ColorInput::handle_nav_command(NavCommand cmd) { + if (cmd == NavCommand::Confirm) { + toggle_picker(); + return true; + } + return false; +} + +void ColorInput::toggle_picker() { + if (mPicker != nullptr) { + mPicker->dismiss(); + return; + } + + mInitialValue = mProps.getValue ? mProps.getValue() : ""; + mInitialValueRemembered = false; + const auto initialColor = parse_color(mInitialValue, mProps.alpha); + const Rml::Colourb color = initialColor.value_or(Rml::Colourb{128, 128, 128, 255}); + rgb_to_hsv(color, mHue, mSat, mVal); + mAlpha = static_cast(color.alpha) / 255.0f; + + auto picker = std::make_unique(mRoot, mProps.side, "color-picker"); + mPicker = picker.get(); + mPicker->on_close([this] { + if (mInitialValueRemembered && mProps.getValue) { + remember_color(mProps.getValue(), mProps.alpha); + } + mPicker = nullptr; + mPickerNavigation.reset(); + mPickerListeners.clear(); + mSvArea = nullptr; + mSvCursor = nullptr; + mHueBar = nullptr; + mHueCursor = nullptr; + mAlphaBar = nullptr; + mAlphaCursor = nullptr; + mPickerValue = nullptr; + }); + build_picker(); + refresh_picker(); + mPicker->on_focus( + [this] { return mPickerNavigation != nullptr && mPickerNavigation->focus(); }); + push_document(std::move(picker)); +} + +void ColorInput::build_picker() { + auto* body = mPicker->body(); + mPickerNavigation = std::make_unique( + body, NavGroup::Props{ + .layout = NavGroup::Layout::Vertical, + .horizontalBoundary = NavGroup::Boundary::Stop, + .verticalBoundary = NavGroup::Boundary::Stop, + }); + + mSvArea = append(body, "color-sv"); + mSvCursor = append(mSvArea, "color-cursor"); + mPickerNavigation->add_existing_item( + mSvArea, AdjustmentRegion::Props{ + .begin = [this] { begin_adjustment(); }, + .cancel = [this] { cancel_adjustment(); }, + .nudge = [this](NavCommand direction) { nudge_sv(direction); }, + .adjust = [this](float x, float y, + float deltaSeconds) { adjust_sv(x, y, deltaSeconds); }, + }); + + mHueBar = append(body, "color-hue"); + mHueCursor = append(mHueBar, "color-cursor"); + mPickerNavigation->add_existing_item(mHueBar, + AdjustmentRegion::Props{ + .begin = [this] { begin_adjustment(); }, + .cancel = [this] { cancel_adjustment(); }, + .nudge = [this](NavCommand direction) { nudge_hue(direction); }, + .adjust = [this](float x, float, float deltaSeconds) { adjust_hue(x, deltaSeconds); }, + }); + + if (mProps.alpha) { + mAlphaBar = append(body, "color-alpha"); + mAlphaCursor = append(mAlphaBar, "color-cursor"); + mPickerNavigation->add_existing_item( + mAlphaBar, AdjustmentRegion::Props{ + .begin = [this] { begin_adjustment(); }, + .cancel = [this] { cancel_adjustment(); }, + .nudge = [this](NavCommand direction) { nudge_alpha(direction); }, + .adjust = [this](float x, float, + float deltaSeconds) { adjust_alpha(x, deltaSeconds); }, + }); + } + + add_presets(*mPickerNavigation); + add_history(*mPickerNavigation); + + auto* footer = append(body, "color-footer"); + auto& footerNavigation = mPickerNavigation->add_existing_item( + footer, NavGroup::Props{ + .layout = NavGroup::Layout::Horizontal, + .horizontalBoundary = NavGroup::Boundary::Stop, + .verticalBoundary = NavGroup::Boundary::Bubble, + }); + const auto formatLabel = [this] { + return mHexFormat ? "Hex" : (mProps.alpha ? "RGBA" : "RGB"); + }; + auto& formatButton = footerNavigation.add_item