mirror of
https://github.com/TwilitRealm/dusklight
synced 2026-08-17 20:43:07 -04:00
Compare commits
34 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| af17623e69 | |||
| c01610dc37 | |||
| f4700c9636 | |||
| 5d01c93839 | |||
| 0c546819f4 | |||
| 094f0cd78d | |||
| c251aba39d | |||
| c722cb1be0 | |||
| 0f5a248401 | |||
| 045fbd9b46 | |||
| 46da33be37 | |||
| 008a18c142 | |||
| 5b4def820a | |||
| 635901d3bd | |||
| 5abc956448 | |||
| 0c3bbbaba0 | |||
| 71b2eedc82 | |||
| 0da58ac91d | |||
| c29cafa8a2 | |||
| 5e669c8f0f | |||
| 3e625cf006 | |||
| c6f497b525 | |||
| 79d3c7c76a | |||
| 16dd1118d1 | |||
| e9918cc8ed | |||
| 058304dc26 | |||
| d55b44b5a5 | |||
| 469575fd65 | |||
| 4883c11182 | |||
| 7ac2340312 | |||
| 3352ea3dde | |||
| 6481d12a3d | |||
| 960d016113 | |||
| e02251a669 |
+1
-1
@@ -1,6 +1,6 @@
|
||||
[submodule "extern/aurora"]
|
||||
path = extern/aurora
|
||||
url = https://github.com/Lurs/aurora.git
|
||||
url = https://github.com/encounter/aurora.git
|
||||
[submodule "extern/borealis"]
|
||||
path = extern/borealis
|
||||
url = https://github.com/encounter/borealis.git
|
||||
|
||||
+2
-1
@@ -305,7 +305,7 @@ find_package(Threads REQUIRED)
|
||||
set(GAME_COMPILE_DEFS DUSK_BUILDING_GAME=1)
|
||||
set(GAME_LIBS aurora::core aurora::gx aurora::gd aurora::si aurora::vi aurora::pad aurora::mtx aurora::os aurora::dvd
|
||||
aurora::card borealis::cli borealis::crash borealis::data borealis::disc borealis::discord borealis::file_select borealis::log borealis::presentation borealis::sentry borealis::update freeverb cxxopts::cxxopts absl::flat_hash_map nlohmann_json::nlohmann_json TracyClient fmt::fmt
|
||||
Threads::Threads zstd::libzstd dusklight_game_headers ZLIB::ZLIB)
|
||||
Threads::Threads zstd::libzstd dusklight_game_headers)
|
||||
if (DUSK_HAS_FUNCHOOK)
|
||||
list(APPEND GAME_LIBS funchook-static)
|
||||
endif ()
|
||||
@@ -519,6 +519,7 @@ if (DUSK_ENABLE_CODE_MODS AND CMAKE_SOURCE_DIR STREQUAL CMAKE_CURRENT_SOURCE_DIR
|
||||
add_subdirectory(mods/ao_mod)
|
||||
add_subdirectory(mods/shadow_mod)
|
||||
add_subdirectory(mods/window_demo)
|
||||
add_subdirectory(mods/basic_cosmetics_mod)
|
||||
endif ()
|
||||
|
||||
if (APPLE)
|
||||
|
||||
@@ -4,7 +4,7 @@ include_guard(GLOBAL)
|
||||
get_filename_component(_game_root "${CMAKE_CURRENT_LIST_DIR}/.." ABSOLUTE)
|
||||
|
||||
# PARTIAL_DEBUG makes debug and release share one struct/vtable ABI so a mod binary loads into either
|
||||
set(_game_compile_defs TARGET_PC=1 WIDESCREEN_SUPPORT=1 AVOID_UB=1 VERSION=0 MTX_USE_PS=1 PARTIAL_DEBUG=1 DUSK_TPHD=1)
|
||||
set(_game_compile_defs TARGET_PC=1 WIDESCREEN_SUPPORT=1 AVOID_UB=1 VERSION=0 MTX_USE_PS=1 PARTIAL_DEBUG=1)
|
||||
if (ANDROID)
|
||||
list(APPEND _game_compile_defs TARGET_ANDROID=1)
|
||||
endif ()
|
||||
|
||||
Vendored
+1
-1
Submodule extern/aurora updated: 8bb7159d3e...1f84646de4
+6
-10
@@ -1436,6 +1436,7 @@ set(DUSK_FILES
|
||||
src/dusk/gamepad_color.cpp
|
||||
src/dusk/globals.cpp
|
||||
src/dusk/gyro.cpp
|
||||
src/dusk/hq_minimap.cpp
|
||||
src/dusk/imgui/ImGuiActorSpawner.cpp
|
||||
src/dusk/imgui/ImGuiBloomWindow.cpp
|
||||
src/dusk/imgui/ImGuiBloomWindow.hpp
|
||||
@@ -1472,6 +1473,9 @@ set(DUSK_FILES
|
||||
src/dusk/mods/loader/native_module.hpp
|
||||
src/dusk/mods/loader/prepatch.cpp
|
||||
src/dusk/mods/loader/prepatch.hpp
|
||||
src/dusk/mods/item.hpp
|
||||
src/dusk/mods/item_checks.cpp
|
||||
src/dusk/mods/item_gives.cpp
|
||||
src/dusk/mods/log_buffer.cpp
|
||||
src/dusk/mods/log_buffer.hpp
|
||||
src/dusk/mods/manifest.cpp
|
||||
@@ -1483,6 +1487,8 @@ set(DUSK_FILES
|
||||
src/dusk/mods/svc/gfx.cpp
|
||||
src/dusk/mods/svc/hook.cpp
|
||||
src/dusk/mods/svc/host.cpp
|
||||
src/dusk/mods/svc/item.cpp
|
||||
src/dusk/mods/svc/item.hpp
|
||||
src/dusk/mods/svc/log.cpp
|
||||
src/dusk/mods/svc/overlay.cpp
|
||||
src/dusk/mods/svc/registry.cpp
|
||||
@@ -1581,14 +1587,4 @@ set(DUSK_FILES
|
||||
src/helpers/endian.cpp
|
||||
src/helpers/offset_ptr.cpp
|
||||
src/helpers/string.cpp
|
||||
src/dusk/tphd/TphdPack.hpp
|
||||
src/dusk/tphd/TphdPack.cpp
|
||||
src/dusk/tphd/GtxParser.hpp
|
||||
src/dusk/tphd/GtxParser.cpp
|
||||
src/dusk/tphd/AddrLib.hpp
|
||||
src/dusk/tphd/AddrLib.cpp
|
||||
src/dusk/tphd/HdAssetLayer.hpp
|
||||
src/dusk/tphd/HdAssetLayer.cpp
|
||||
src/dusk/tphd/LosTable.hpp
|
||||
src/dusk/tphd/LosTable.cpp
|
||||
)
|
||||
|
||||
@@ -158,10 +158,6 @@ enum Z2Scene {
|
||||
/* 0x4E */ Z2SCENE_GROTTO_ROCK_2,
|
||||
/* 0x4F */ Z2SCENE_GROTTO_POND,
|
||||
/* 0x50 */ Z2SCENE_FARON_WOODS_CAVE,
|
||||
|
||||
#if TARGET_PC
|
||||
/* 0x51 */ Z2SCENE_CAVE_OF_SHADOWS,
|
||||
#endif
|
||||
};
|
||||
|
||||
#endif /* Z2SCENEMGR_H */
|
||||
|
||||
@@ -4560,8 +4560,6 @@ public:
|
||||
|
||||
void onIronBallChainInterpCallback();
|
||||
|
||||
f32 mLosStickValue;
|
||||
|
||||
static const int IRON_BALL_CHAIN_COUNT = 102;
|
||||
cXyz mIBChainInterpPrevPos[IRON_BALL_CHAIN_COUNT];
|
||||
cXyz mIBChainInterpCurrPos[IRON_BALL_CHAIN_COUNT];
|
||||
|
||||
@@ -96,6 +96,9 @@ public:
|
||||
/* 0xDE0 */ cXyz field_0xde0;
|
||||
/* 0xDEC */ u8 field_0xdec[0xdf9 - 0xdec];
|
||||
/* 0xDF9 */ u8 field_0xdf9;
|
||||
#if TARGET_PC
|
||||
bool mItemCheckOverridden;
|
||||
#endif
|
||||
};
|
||||
|
||||
STATIC_ASSERT(sizeof(daE_HP_c) == 0xdfc);
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -18,24 +18,16 @@ public:
|
||||
TGXTexObj& getTexObj() { return mTexObj; }
|
||||
cXyz* getQuad() { return mQuad; }
|
||||
|
||||
#if TARGET_PC
|
||||
// TP HD reflects across N floor quads (F_SP117 room 2 uses 6); GC uses 1.
|
||||
static const int MAX_QUADS = 6;
|
||||
#endif
|
||||
|
||||
/* 0x010 */ TGXTexObj mTexObj;
|
||||
/* 0x030 */ u8 mModelCount;
|
||||
/* 0x034 */ J3DModel* mModels[0x40];
|
||||
/* 0x134 */ cXyz mQuad[DUSK_IF_ELSE(MAX_QUADS*4, 4)];
|
||||
/* 0x134 */ cXyz mQuad[4];
|
||||
/* 0x164 */ cXyz mMinVal;
|
||||
/* 0x170 */ cXyz mMaxVal;
|
||||
/* 0x17C */ cXyz mViewScale;
|
||||
#if TARGET_PC
|
||||
bool mbReset = false;
|
||||
bool mbHadEntry = false;
|
||||
cXyz mQuadBoxMin[MAX_QUADS];
|
||||
cXyz mQuadBoxMax[MAX_QUADS];
|
||||
int mQuadCount = 1;
|
||||
#endif
|
||||
};
|
||||
|
||||
|
||||
@@ -88,6 +88,11 @@ private:
|
||||
/* 0x99C */ dPa_followEcallBack mEffect2;
|
||||
/* 0x9B0 */ Z2SoundObjSimple mSound;
|
||||
/* 0x9D0 */ u8 mIsHookCarry;
|
||||
#if TARGET_PC
|
||||
u8 mOriginalItemNo;
|
||||
bool mItemOverridden;
|
||||
bool mOverrideHover;
|
||||
#endif
|
||||
};
|
||||
|
||||
STATIC_ASSERT(sizeof(daObjLife_c) == 0x9d4);
|
||||
|
||||
@@ -142,12 +142,12 @@ namespace daObjSwpush {
|
||||
int Mthd_Execute();
|
||||
int Mthd_Draw();
|
||||
|
||||
static DUSK_GAME_DATA s16 const M_bmd[DUSK_IF_ELSE(4, 3)];
|
||||
static DUSK_GAME_DATA s16 const M_dzb[DUSK_IF_ELSE(4, 3)];
|
||||
static DUSK_GAME_DATA u32 const M_heap_size[DUSK_IF_ELSE(4, 3)];
|
||||
static DUSK_GAME_DATA s16 const M_bmd[3];
|
||||
static DUSK_GAME_DATA s16 const M_dzb[3];
|
||||
static DUSK_GAME_DATA u32 const M_heap_size[3];
|
||||
static DUSK_GAME_DATA Hio_c::Attr_c const M_attr[5];
|
||||
static DUSK_GAME_DATA u8 const M_op_vtx[4];
|
||||
static DUSK_GAME_DATA DUSK_CONST char* M_arcname[DUSK_IF_ELSE(4, 3)];
|
||||
static DUSK_GAME_DATA DUSK_CONST char* M_arcname[3];
|
||||
|
||||
/* 0x568 */ request_of_phase_process_class mPhase;
|
||||
/* 0x570 */ dBgWSv* mpBgW;
|
||||
|
||||
@@ -194,6 +194,9 @@ private:
|
||||
/* 0x9FC */ u8 field_0x9fc;
|
||||
/* 0x9FD */ u8 field_0x9fd;
|
||||
/* 0xA00 */ Mtx mDrawMtx;
|
||||
#if TARGET_PC
|
||||
u8 mOriginalItemNo;
|
||||
#endif
|
||||
};
|
||||
|
||||
STATIC_ASSERT(sizeof(daTbox_c) == 0xA30);
|
||||
|
||||
@@ -83,6 +83,10 @@ private:
|
||||
/* 0xAC0 */ u8 field_0xAC0[0xAC4 - 0xAC0];
|
||||
/* 0xAC4 */ int mStaffIdx;
|
||||
/* 0xAC8 */ dBgW* mBoxBgW;
|
||||
#if TARGET_PC
|
||||
bool mParamsInit;
|
||||
u8 mOriginalItemNo;
|
||||
#endif
|
||||
};
|
||||
|
||||
STATIC_ASSERT(sizeof(daTbox2_c) == 0xACC);
|
||||
|
||||
@@ -145,6 +145,10 @@ public:
|
||||
/* 0x9BC */ u8 field_0x9bc[4];
|
||||
/* 0x9C0 */ u8 field_0x9c0;
|
||||
/* 0x9C1 */ u8 field_0x9c1;
|
||||
#if TARGET_PC
|
||||
u8 mOriginalItemNo;
|
||||
bool mItemOverridden;
|
||||
#endif
|
||||
}; // Size: 0x9C4
|
||||
|
||||
#endif /* D_A_D_A_ITEM_STATIC_H */
|
||||
|
||||
@@ -50,6 +50,9 @@ public:
|
||||
csXyz* getRotateP();
|
||||
cXyz* getPosP();
|
||||
const char* getShopArcname();
|
||||
#if TARGET_PC
|
||||
const ResourceData& getResourceData() const;
|
||||
#endif
|
||||
u16 getHeapSize();
|
||||
void CreateInit();
|
||||
void set_mtx();
|
||||
@@ -110,6 +113,10 @@ private:
|
||||
/* 0x960 */ s16 mAngleX;
|
||||
/* 0x962 */ s16 mAngleY;
|
||||
/* 0x964 */ u8 mShopItemID;
|
||||
#if TARGET_PC
|
||||
ResourceData mOverrideData;
|
||||
bool mItemOverridden;
|
||||
#endif
|
||||
};
|
||||
|
||||
int CheckShopItemCreateHeap(fopAc_ac_c* i_this);
|
||||
|
||||
@@ -27,11 +27,6 @@ public:
|
||||
void setSaveDate(dSv_save_c*);
|
||||
void setPlayTime(dSv_save_c*);
|
||||
void modeWait();
|
||||
|
||||
#if TARGET_PC
|
||||
void fileSelectWide();
|
||||
#endif
|
||||
|
||||
void modeMove();
|
||||
void _draw();
|
||||
|
||||
@@ -42,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];
|
||||
|
||||
@@ -13,36 +13,8 @@ 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 {
|
||||
|
||||
+3
-5
@@ -11,7 +11,9 @@ public:
|
||||
static DUSK_GAME_DATA u8* mData;
|
||||
};
|
||||
|
||||
void execItemGet(u8 item_id);
|
||||
class fopAc_ac_c;
|
||||
void execItemGet(
|
||||
u8 item_id IF_DUSK_ARG(u32 item_give_tag = 0) IF_DUSK_ARG(fopAc_ac_c* giver = NULL));
|
||||
|
||||
void item_func_HEART();
|
||||
void item_func_GREEN_RUPEE();
|
||||
@@ -400,8 +402,4 @@ BOOL isBottleItem(u8 item_no);
|
||||
u8 check_itemno(int i_itemNo);
|
||||
BOOL isInsect(u8 i_itemNo);
|
||||
|
||||
#if TARGET_PC
|
||||
void item_func_WALLET_LV4();
|
||||
#endif
|
||||
|
||||
#endif /* D_D_ITEM_H */
|
||||
|
||||
+1
-12
@@ -58,11 +58,7 @@ struct dItem_data {
|
||||
|
||||
static s16 getTexture(u8 index) { return item_resource[index].mTexture; }
|
||||
|
||||
#if TARGET_PC
|
||||
static u8 getTexScale(u8 index);
|
||||
#else
|
||||
static u8 getTexScale(u8 index) { return item_resource[index].mTexScale; }
|
||||
#endif
|
||||
static u8 getTexScale (u8 index) { return item_resource[index].mTexScale; }
|
||||
|
||||
static const char* getFieldArc(u8 index) { return field_item_res[index].mFieldArc; }
|
||||
|
||||
@@ -354,11 +350,4 @@ enum {
|
||||
/* 0xFF */ dItemNo_NONE_e,
|
||||
};
|
||||
|
||||
#if TARGET_PC
|
||||
// HD item mappings
|
||||
enum {
|
||||
dItemNo_WALLET_LV4_e = 0xDA,
|
||||
};
|
||||
#endif
|
||||
|
||||
#endif /* D_D_ITEM_DATA_H */
|
||||
|
||||
@@ -30,7 +30,7 @@ public:
|
||||
|
||||
void drawSelf() { mpKanteraIcon->draw(); }
|
||||
|
||||
private:
|
||||
// private:
|
||||
/* 0x04 */ dDlst_KanteraIcon_c* mpKanteraIcon;
|
||||
/* 0x08 */ CPaneMgr* mpParent;
|
||||
/* 0x0C */ CPaneMgr* mpGauge;
|
||||
|
||||
@@ -57,7 +57,7 @@ public:
|
||||
return &mpTypeGroupData[i_typeGroupNo];
|
||||
}
|
||||
|
||||
/* 0x0 */ fmpTresTypeGroupDataList_c mpTypeGroupData[DUSK_IF_ELSE(35, 17)];
|
||||
/* 0x0 */ fmpTresTypeGroupDataList_c mpTypeGroupData[17];
|
||||
};
|
||||
|
||||
class dMenu_Fmap_data_c {
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -43,7 +43,7 @@ public:
|
||||
|
||||
u8 getStatus() { return mStatus; }
|
||||
|
||||
private:
|
||||
// private:
|
||||
/* 0x004 */ JKRExpHeap* mpHeap;
|
||||
/* 0x008 */ JKRArchive* mpArchive;
|
||||
/* 0x00C */ STControl* mpStick;
|
||||
|
||||
@@ -270,7 +270,7 @@ public:
|
||||
|
||||
static DUSK_GAME_DATA dMenu_Fmap_c* MyClass;
|
||||
|
||||
private:
|
||||
// private:
|
||||
/* 0x004 */ JKRExpHeap* mpHeap;
|
||||
/* 0x008 */ JKRExpHeap* mpTalkHeap;
|
||||
/* 0x00C */ STControl* mpStick;
|
||||
|
||||
@@ -60,7 +60,7 @@ public:
|
||||
|
||||
u8 getStatus() { return mStatus; }
|
||||
|
||||
private:
|
||||
// private:
|
||||
/* 0x04 */ JKRExpHeap* mpHeap;
|
||||
/* 0x08 */ JKRArchive* mpArchive;
|
||||
/* 0x0C */ STControl* mpStick;
|
||||
|
||||
@@ -64,7 +64,7 @@ public:
|
||||
|
||||
u8 getStatus() { return mStatus; }
|
||||
|
||||
private:
|
||||
// private:
|
||||
/* 0x004 */ JKRExpHeap* mpHeap;
|
||||
/* 0x008 */ JKRArchive* mpArchive;
|
||||
/* 0x00C */ STControl* mpStick;
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -58,7 +58,7 @@ public:
|
||||
|
||||
u8 getStatus() { return mStatus; }
|
||||
|
||||
private:
|
||||
// private:
|
||||
/* 0x004 */ JKRExpHeap* mpHeap;
|
||||
/* 0x008 */ JKRArchive* mpArchive;
|
||||
/* 0x00C */ STControl* mpStick;
|
||||
|
||||
@@ -154,7 +154,7 @@ public:
|
||||
}
|
||||
#endif
|
||||
|
||||
private:
|
||||
// private:
|
||||
/* 0x004 */ item_params mItemParams[4];
|
||||
/* 0x074 */ JKRExpHeap* heap;
|
||||
/* 0x078 */ J2DScreen* mpScreen;
|
||||
|
||||
+2
-11
@@ -172,15 +172,6 @@ public:
|
||||
int event041(mesg_flow_node_event*, fopAc_ac_c*);
|
||||
int event042(mesg_flow_node_event*, fopAc_ac_c*);
|
||||
|
||||
#if TARGET_PC
|
||||
// HD additions
|
||||
u16 query054(mesg_flow_node_branch*, fopAc_ac_c*, int);
|
||||
u16 query055(mesg_flow_node_branch*, fopAc_ac_c*, int);
|
||||
int event043(mesg_flow_node_event*, fopAc_ac_c*);
|
||||
int event044(mesg_flow_node_event*, fopAc_ac_c*);
|
||||
int event045(mesg_flow_node_event*, fopAc_ac_c*);
|
||||
#endif
|
||||
|
||||
void initWord(fopAc_ac_c*, const char*, u8, int, fopAc_ac_c**);
|
||||
|
||||
#if DEBUG
|
||||
@@ -194,8 +185,8 @@ public:
|
||||
void setMsg(u32 msg) { mMsg = msg; }
|
||||
bool checkEndFlow() { return (u32)field_0x26 == 1; }
|
||||
|
||||
static DUSK_GAME_DATA queryFunc mQueryList[DUSK_IF_ELSE(55, 53)];
|
||||
static DUSK_GAME_DATA eventFunc mEventList[DUSK_IF_ELSE(46, 43)];
|
||||
static DUSK_GAME_DATA queryFunc mQueryList[53];
|
||||
static DUSK_GAME_DATA eventFunc mEventList[43];
|
||||
|
||||
private:
|
||||
/* 0x04 */ u8* mFlow_p;
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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();
|
||||
|
||||
@@ -1416,11 +1416,6 @@ dStage_KeepDoorInfo* dStage_GetKeepDoorInfo();
|
||||
dStage_KeepDoorInfo* dStage_GetRoomKeepDoorInfo();
|
||||
void dStage_dt_c_fieldMapLoader(void* i_data, dStage_dt_c* i_stage);
|
||||
|
||||
#if TARGET_PC
|
||||
// TP HD Cave of Shadows (D_SB11): reveal the los next-floor when a descent gate opens.
|
||||
void dStage_showLOSNextFloor(int fromRoom);
|
||||
#endif
|
||||
|
||||
#if DEBUG
|
||||
void dStage_DebugDisp();
|
||||
#endif
|
||||
|
||||
@@ -318,6 +318,11 @@ public:
|
||||
/* 0x566 */ s8 field_0x566;
|
||||
/* 0x567 */ s8 field_0x567;
|
||||
|
||||
#if TARGET_PC
|
||||
u32 mItemGiveTag;
|
||||
u8 mItemGiveOriginalNo;
|
||||
#endif
|
||||
|
||||
#if !__MWERKS__
|
||||
s8 actor_last_base_field;
|
||||
#endif
|
||||
|
||||
@@ -79,6 +79,10 @@ struct fopAcM_prm_class {
|
||||
/* 0x1C */ fpc_ProcID parent_id;
|
||||
/* 0x20 */ s8 argument;
|
||||
/* 0x21 */ s8 room_no;
|
||||
#if TARGET_PC
|
||||
u32 mItemGiveTag;
|
||||
u8 mItemGiveOriginalNo;
|
||||
#endif
|
||||
};
|
||||
|
||||
struct fopAcM_search4ev_prm {
|
||||
@@ -516,8 +520,9 @@ s32 fopAcM_SearchByName(s16 i_procName, fopAc_ac_c** i_outActor);
|
||||
fopAcM_prm_class* fopAcM_CreateAppend();
|
||||
|
||||
fopAcM_prm_class* createAppend(u16 i_setId, u32 i_parameters, const cXyz* i_pos, int i_roomNo,
|
||||
const csXyz* i_angle, const cXyz* i_scale, s8 i_argument,
|
||||
fpc_ProcID i_parentId);
|
||||
const csXyz* i_angle, const cXyz* i_scale, s8 i_argument,
|
||||
fpc_ProcID i_parentId IF_DUSK_ARG(u32 i_itemGiveTag = 0)
|
||||
IF_DUSK_ARG(u8 i_itemOriginalNo = 0xFF));
|
||||
|
||||
void fopAcM_Log(fopAc_ac_c const* i_actor, char const* i_message);
|
||||
|
||||
@@ -526,19 +531,20 @@ s32 fopAcM_delete(fopAc_ac_c* i_actor);
|
||||
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);
|
||||
int i_roomNo, const csXyz* i_angle, const cXyz* i_scale, s8 i_argument,
|
||||
createFunc i_createFunc IF_DUSK_ARG(u32 i_itemGiveTag = 0));
|
||||
|
||||
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);
|
||||
const csXyz* i_angle, const cXyz* i_scale, s8 i_argument IF_DUSK_ARG(u32 i_itemGiveTag = 0));
|
||||
|
||||
inline fpc_ProcID fopAcM_Create(s16 i_procName, createFunc i_createFunc, void* params) {
|
||||
return fpcM_Create(i_procName, i_createFunc,params);
|
||||
}
|
||||
|
||||
fopAc_ac_c* fopAcM_fastCreate(s16 i_procName, u32 i_parameters, const cXyz* i_pos, int i_roomNo,
|
||||
const csXyz* i_angle, const cXyz* i_scale, s8 i_argument,
|
||||
createFunc i_createFunc, void* i_createFuncData);
|
||||
const csXyz* i_angle, const cXyz* i_scale, s8 i_argument, createFunc i_createFunc,
|
||||
void* i_createFuncData IF_DUSK_ARG(u32 i_itemGiveTag = 0)
|
||||
IF_DUSK_ARG(u8 i_itemOriginalNo = 0xFF));
|
||||
|
||||
fopAc_ac_c* fopAcM_fastCreate(const char* i_actorname, u32 i_parameters, const cXyz* i_pos,
|
||||
int i_roomNo, const csXyz* i_angle, const cXyz* i_scale,
|
||||
@@ -623,11 +629,11 @@ fopAc_ac_c* fopAcM_getItemEventPartner(const fopAc_ac_c*);
|
||||
fopAc_ac_c* fopAcM_getEventPartner(const fopAc_ac_c*);
|
||||
|
||||
fpc_ProcID fopAcM_createItemForPresentDemo(cXyz const* i_pos, int i_itemNo, u8 param_2,
|
||||
int i_itemBitNo, int i_roomNo, csXyz const* i_angle,
|
||||
cXyz const* i_scale);
|
||||
int i_itemBitNo, int i_roomNo, csXyz const* i_angle,
|
||||
cXyz const* i_scale IF_DUSK_ARG(u32 i_itemGiveTag = 0));
|
||||
|
||||
fpc_ProcID fopAcM_createItemForTrBoxDemo(cXyz const* i_pos, int i_itemNo, int i_itemBitNo,
|
||||
int i_roomNo, csXyz const* i_angle, cXyz const* i_scale);
|
||||
int i_roomNo, csXyz const* i_angle, cXyz const* i_scale IF_DUSK_ARG(u32 i_itemGiveTag = 0));
|
||||
|
||||
u8 fopAcM_getItemNoFromTableNo(u8 i_tableNo);
|
||||
|
||||
@@ -641,11 +647,12 @@ fpc_ProcID fopAcM_createItemFromTable(cXyz const* i_pos, int i_tableNo, int i_it
|
||||
bool i_createDirect);
|
||||
|
||||
fpc_ProcID fopAcM_createDemoItem(const cXyz* i_pos, int i_itemNo, int i_itemBitNo,
|
||||
const csXyz* i_angle, int i_roomNo, const cXyz* scale, u8 param_7);
|
||||
const csXyz* i_angle, int i_roomNo, const cXyz* scale,
|
||||
u8 param_7 IF_DUSK_ARG(u32 i_itemGiveTag = 0));
|
||||
|
||||
fpc_ProcID fopAcM_createItemForBoss(const cXyz* i_pos, int i_itemNo, int i_roomNo,
|
||||
const csXyz* i_angle, const cXyz* i_scale, f32 i_speedF,
|
||||
f32 i_speedY, int param_8);
|
||||
const csXyz* i_angle, const cXyz* i_scale, f32 i_speedF, f32 i_speedY,
|
||||
int param_8 IF_DUSK_ARG(const char* i_itemCheckName = NULL));
|
||||
|
||||
fpc_ProcID fopAcM_createItemForMidBoss(const cXyz* i_pos, int i_itemNo, int i_roomNo,
|
||||
const csXyz* i_angle, const cXyz* i_scale, int param_6,
|
||||
|
||||
@@ -256,4 +256,17 @@ using std::isnan;
|
||||
#define DUSK_CONST IF_DUSK(const)
|
||||
#define DUSK_CONSTEXPR IF_DUSK(constexpr)
|
||||
|
||||
#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)
|
||||
#define DUSK_ITEM_CHECK_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_GIVE_TAG(name)
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -1761,16 +1761,6 @@ public:
|
||||
virtual ~J3DIndBlockNull() {}
|
||||
};
|
||||
|
||||
#ifdef DUSK_TPHD
|
||||
struct PolygonOffset {
|
||||
BE(f32) mFrontOffset;
|
||||
BE(f32) mFrontScale;
|
||||
BE(f32) mBackOffset;
|
||||
BE(f32) mBackScale;
|
||||
BE(f32) mClamp;
|
||||
};
|
||||
#endif
|
||||
|
||||
/**
|
||||
* @ingroup jsystem-j3d
|
||||
*
|
||||
@@ -1803,10 +1793,6 @@ public:
|
||||
virtual void setDither(u8 const*) {}
|
||||
virtual void setDither(u8) {}
|
||||
virtual u8 getDither() const { return 0; }
|
||||
#ifdef DUSK_TPHD
|
||||
virtual void setPolygonOffset(const PolygonOffset&) {}
|
||||
virtual PolygonOffset* getPolygonOffset() { return NULL; }
|
||||
#endif
|
||||
virtual u32 getFogOffset() const { return 0; }
|
||||
virtual void setFogOffset(u32) {}
|
||||
virtual ~J3DPEBlock() {}
|
||||
@@ -1970,25 +1956,12 @@ public:
|
||||
virtual void setFogOffset(u32 fogOffset) { mFogOffset = fogOffset; }
|
||||
virtual ~J3DPEBlockFull() {}
|
||||
|
||||
#ifdef DUSK_TPHD
|
||||
virtual void setPolygonOffset(const PolygonOffset& offset) {
|
||||
mPolygonOffset = offset;
|
||||
}
|
||||
|
||||
virtual PolygonOffset* getPolygonOffset() {
|
||||
return &mPolygonOffset;
|
||||
}
|
||||
#endif
|
||||
|
||||
/* 0x04 */ J3DFog mFog;
|
||||
/* 0x30 */ J3DAlphaComp mAlphaComp;
|
||||
/* 0x34 */ J3DBlend mBlend;
|
||||
/* 0x38 */ J3DZMode mZMode;
|
||||
/* 0x3A */ u8 mZCompLoc;
|
||||
/* 0x3B */ u8 mDither;
|
||||
#ifdef DUSK_TPHD
|
||||
PolygonOffset mPolygonOffset;
|
||||
#endif
|
||||
/* 0x3C */ u32 mFogOffset;
|
||||
}; // Size: 0x40
|
||||
|
||||
|
||||
@@ -46,13 +46,6 @@ struct J3DMaterialInitData {
|
||||
/* 0x14A */ BE(u16) mNBTScaleIdx;
|
||||
}; // size 0x14C
|
||||
|
||||
|
||||
#ifdef DUSK_TPHD
|
||||
struct J3DMaterialInitData_MAT4 : public J3DMaterialInitData {
|
||||
/* 0x14C */ BE(u16) mPolygonOffsetIdx;
|
||||
}; // size 0x14E
|
||||
#endif
|
||||
|
||||
/**
|
||||
* @ingroup jsystem-j3d
|
||||
*
|
||||
@@ -150,29 +143,10 @@ public:
|
||||
J3DNBTScale newNBTScale(int) const;
|
||||
|
||||
u16 getMaterialID(int idx) const { return mpMaterialID[idx]; }
|
||||
#ifdef DUSK_TPHD
|
||||
u8 getMaterialMode(int idx) const { return getMatInitData(idx)->mMaterialMode; }
|
||||
#else
|
||||
u8 getMaterialMode(int idx) const { return mpMaterialInitData[mpMaterialID[idx]].mMaterialMode; }
|
||||
#endif
|
||||
|
||||
#if DUSK_TPHD
|
||||
const PolygonOffset newPolygonOffset(int) const;
|
||||
|
||||
J3DMaterialInitData* getMatInitData(int idx) const {
|
||||
static const u32 sInitDataSizes[] = {0, 0, 0x138, 0x14C, 0x14E};
|
||||
|
||||
return (J3DMaterialInitData*)((u8*)mpMaterialInitData + sInitDataSizes[mBlockType] * getMaterialID(idx));
|
||||
}
|
||||
|
||||
u16 mBlockType;
|
||||
#endif
|
||||
/* 0x00 */ u16 mMaterialNum;
|
||||
#if DUSK_TPHD
|
||||
/* 0x04 */ void* mpMaterialInitData;
|
||||
#else
|
||||
/* 0x04 */ J3DMaterialInitData* mpMaterialInitData;
|
||||
#endif
|
||||
/* 0x08 */ BE(u16)* mpMaterialID;
|
||||
/* 0x0C */ J3DIndInitData* mpIndInitData;
|
||||
/* 0x10 */ GXColor* mpMatColor;
|
||||
@@ -201,9 +175,6 @@ public:
|
||||
/* 0x6C */ u8* mpZCompLoc;
|
||||
/* 0x70 */ u8* mpDither;
|
||||
/* 0x74 */ J3DNBTScaleInfo* mpNBTScaleInfo;
|
||||
#ifdef DUSK_TPHD
|
||||
PolygonOffset* mpPolygonOffsets;
|
||||
#endif
|
||||
/* 0x78 */ J3DDisplayListInit* mpDisplayListInit;
|
||||
/* 0x7C */ J3DPatchingInfo* mpPatchingInfo;
|
||||
/* 0x80 */ J3DCurrentMtxInfo* mpCurrentMtxInfo;
|
||||
|
||||
@@ -169,12 +169,6 @@ struct J3DMaterialBlock_v21 : public J3DModelBlock {
|
||||
/* 0x74 */ OFFSET_PTR_V0 mpNBTScaleInfo;
|
||||
};
|
||||
|
||||
#ifdef DUSK_TPHD
|
||||
struct J3DMaterialBlock_MAT4 : public J3DMaterialBlock {
|
||||
/* 0x84 */ OFFSET_PTR_V0 mpPolygonOffsets;
|
||||
};
|
||||
#endif
|
||||
|
||||
/**
|
||||
* @ingroup jsystem-j3d
|
||||
*
|
||||
|
||||
@@ -7,9 +7,6 @@
|
||||
#include "JSystem/J3DGraphBase/J3DMaterial.h"
|
||||
#include "JSystem/JMath/JMath.h"
|
||||
#include "m_Do/m_Do_mtx.h"
|
||||
#if TARGET_PC
|
||||
#include "dusk/settings.h"
|
||||
#endif
|
||||
|
||||
void J3DMtxCalcJ3DSysInitBasic::init(Vec const& scale, Mtx const& mtx) {
|
||||
J3DSys::mCurrentS = scale;
|
||||
@@ -181,23 +178,7 @@ void J3DJoint::entryIn() {
|
||||
matPacket->setMaterialAnmID(mesh->getMaterialAnm());
|
||||
matPacket->setShapePacket(shapePacket);
|
||||
bool isDrawModeOpaTexEdge = mesh->isDrawModeOpaTexEdge() == FALSE;
|
||||
#if TARGET_PC
|
||||
// TP HD J3DJoint::entryIn (FUN_02b57690):
|
||||
J3DDrawBuffer* drawBuffer = j3dSys.getDrawBuffer(isDrawModeOpaTexEdge);
|
||||
u8 r24;
|
||||
if (dusk::tphd_active() && (mesh->mMaterialID & 0x80000000) != 0 &&
|
||||
(mesh->getMaterialMode() & 0x20) != 0 &&
|
||||
drawBuffer->getSortMode() == J3DDrawBufSortMode_Mat)
|
||||
{
|
||||
matPacket->drawClear();
|
||||
shapePacket->drawClear();
|
||||
r24 = drawBuffer->entryImm(matPacket, 1);
|
||||
} else {
|
||||
r24 = matPacket->entry(drawBuffer);
|
||||
}
|
||||
#else
|
||||
u8 r24 = matPacket->entry(j3dSys.getDrawBuffer(isDrawModeOpaTexEdge));
|
||||
#endif
|
||||
if (r24) {
|
||||
j3dSys.setMatPacket(matPacket);
|
||||
J3DDrawBuffer::entryNum++;
|
||||
|
||||
@@ -230,13 +230,6 @@ void J3DMatPacket::draw() {
|
||||
#endif
|
||||
packet->getShape()->loadPreDrawSetting();
|
||||
|
||||
#if DUSK_TPHD
|
||||
{
|
||||
const auto* offs = mpMaterial->getPEBlock()->getPolygonOffset();
|
||||
GX2SetPolygonOffset(offs->mFrontOffset, offs->mFrontScale, offs->mBackOffset, offs->mBackScale, offs->mClamp);
|
||||
}
|
||||
#endif
|
||||
|
||||
while (packet != NULL) {
|
||||
if (packet->getDisplayListObj() != NULL) {
|
||||
packet->getDisplayListObj()->callDL();
|
||||
|
||||
@@ -12,9 +12,6 @@
|
||||
#include "dusk/logging.h"
|
||||
|
||||
J3DMaterialFactory::J3DMaterialFactory(J3DMaterialBlock const& i_block) {
|
||||
#ifdef DUSK_TPHD
|
||||
mBlockType = (i_block.mBlockType & 0xFF) - 0x30; // get number at last byte of block name
|
||||
#endif
|
||||
mMaterialNum = i_block.mMaterialNum;
|
||||
mpMaterialInitData = JSUConvertOffsetToPtr<J3DMaterialInitData>(&i_block, i_block.mpMaterialInitData);
|
||||
mpMaterialID = JSUConvertOffsetToPtr<BE(u16)>(&i_block, i_block.mpMaterialID);
|
||||
@@ -49,11 +46,6 @@ J3DMaterialFactory::J3DMaterialFactory(J3DMaterialBlock const& i_block) {
|
||||
mpZCompLoc = JSUConvertOffsetToPtr<u8>(&i_block, i_block.mpZCompLoc);
|
||||
mpDither = JSUConvertOffsetToPtr<u8>(&i_block, i_block.mpDither);
|
||||
mpNBTScaleInfo = JSUConvertOffsetToPtr<J3DNBTScaleInfo>(&i_block, i_block.mpNBTScaleInfo);
|
||||
#ifdef DUSK_TPHD
|
||||
if(mBlockType >= 4) {
|
||||
mpPolygonOffsets = JSUConvertOffsetToPtr<PolygonOffset>(&i_block, reinterpret_cast<const J3DMaterialBlock_MAT4&>(i_block).mpPolygonOffsets);
|
||||
}
|
||||
#endif
|
||||
mpDisplayListInit = NULL;
|
||||
mpPatchingInfo = NULL;
|
||||
mpCurrentMtxInfo = NULL;
|
||||
@@ -82,11 +74,7 @@ u16 J3DMaterialFactory::countUniqueMaterials() {
|
||||
}
|
||||
|
||||
u32 J3DMaterialFactory::countTexGens(int i_idx) const {
|
||||
#ifdef DUSK_TPHD
|
||||
J3DMaterialInitData* mtl_init_data = getMatInitData(i_idx);
|
||||
#else
|
||||
J3DMaterialInitData* mtl_init_data = &mpMaterialInitData[mpMaterialID[i_idx]];
|
||||
#endif
|
||||
if (mtl_init_data->mTexGenNumIdx != 0xff) {
|
||||
return mpTexGenNum[mtl_init_data->mTexGenNumIdx];
|
||||
}
|
||||
@@ -94,11 +82,7 @@ u32 J3DMaterialFactory::countTexGens(int i_idx) const {
|
||||
}
|
||||
|
||||
u32 J3DMaterialFactory::countStages(int i_idx) const {
|
||||
#ifdef DUSK_TPHD
|
||||
J3DMaterialInitData* mtl_init_data = getMatInitData(i_idx);
|
||||
#else
|
||||
J3DMaterialInitData* mtl_init_data = &mpMaterialInitData[mpMaterialID[i_idx]];
|
||||
#endif
|
||||
u32 count1 = 0;
|
||||
u32 count2 = 0;
|
||||
if (mtl_init_data->mTevStageNumIdx != 0xff) {
|
||||
@@ -173,9 +157,6 @@ J3DMaterial* J3DMaterialFactory::createNormalMaterial(J3DMaterial* i_material, i
|
||||
i_material->mPEBlock->setZMode(newZMode(i_idx));
|
||||
i_material->mPEBlock->setZCompLoc(newZCompLoc(i_idx));
|
||||
i_material->mPEBlock->setDither(newDither(i_idx));
|
||||
#ifdef DUSK_TPHD
|
||||
i_material->mPEBlock->setPolygonOffset(newPolygonOffset(i_idx));
|
||||
#endif
|
||||
i_material->mTevBlock->setTevStageNum(newTevStageNum(i_idx));
|
||||
for (u8 i = 0; i < tex_num; i++) {
|
||||
i_material->mTevBlock->setTexNo(i, newTexNo(i_idx, i));
|
||||
@@ -184,11 +165,7 @@ J3DMaterial* J3DMaterialFactory::createNormalMaterial(J3DMaterial* i_material, i
|
||||
i_material->mTevBlock->setTevOrder(i, newTevOrder(i_idx, i));
|
||||
}
|
||||
for (u8 i = 0; i < tev_stage_num_max; i++) {
|
||||
#ifdef DUSK_TPHD
|
||||
J3DMaterialInitData* material_init_data = getMatInitData(i_idx);
|
||||
#else
|
||||
J3DMaterialInitData* material_init_data = &mpMaterialInitData[mpMaterialID[i_idx]];
|
||||
#endif
|
||||
i_material->mTevBlock->setTevStage(i, newTevStage(i_idx, i));
|
||||
if (material_init_data->mTevSwapModeIdx[i] != 0xffff) {
|
||||
i_material->mTevBlock->getTevStage(i)->setTexSel(
|
||||
@@ -223,11 +200,7 @@ J3DMaterial* J3DMaterialFactory::createNormalMaterial(J3DMaterial* i_material, i
|
||||
for (u8 i = 0; i < 8; i++) {
|
||||
i_material->mTexGenBlock->setTexMtx(i, newTexMtx(i_idx, i));
|
||||
}
|
||||
#ifdef DUSK_TPHD
|
||||
J3DMaterialInitData* material_init_data = getMatInitData(i_idx);
|
||||
#else
|
||||
J3DMaterialInitData* material_init_data = &mpMaterialInitData[mpMaterialID[i_idx]];
|
||||
#endif
|
||||
J3DMaterialInitData* material_init_data = &mpMaterialInitData[mpMaterialID[i_idx]];
|
||||
for (u8 i = 0; i < tev_stage_num_max; i++) {
|
||||
if (material_init_data->mTevKColorSel[i] != 0xff) {
|
||||
i_material->mTevBlock->setTevKColorSel(i, material_init_data->mTevKColorSel[i]);
|
||||
@@ -300,11 +273,7 @@ J3DMaterial* J3DMaterialFactory::createPatchedMaterial(J3DMaterial* i_material,
|
||||
i_material->mTevBlock->setTevColor(i, newTevColor(i_idx, i));
|
||||
}
|
||||
for (u8 i = 0; i < tev_stage_num; i++) {
|
||||
#ifdef DUSK_TPHD
|
||||
J3DMaterialInitData* material_init_data = getMatInitData(i_idx);
|
||||
#else
|
||||
J3DMaterialInitData* material_init_data = &mpMaterialInitData[mpMaterialID[i_idx]];
|
||||
#endif
|
||||
i_material->mTevBlock->setTevStage(i, newTevStage(i_idx, i));
|
||||
if (material_init_data->mTevSwapModeIdx[i] != 0xffff) {
|
||||
i_material->mTevBlock->getTevStage(i)->setTexSel(
|
||||
@@ -313,11 +282,7 @@ J3DMaterial* J3DMaterialFactory::createPatchedMaterial(J3DMaterial* i_material,
|
||||
mpTevSwapModeInfo[material_init_data->mTevSwapModeIdx[i]].mRasSel);
|
||||
}
|
||||
}
|
||||
#ifdef DUSK_TPHD
|
||||
J3DMaterialInitData* init_data = getMatInitData(i_idx);
|
||||
#else
|
||||
J3DMaterialInitData* init_data = &mpMaterialInitData[mpMaterialID[i_idx]];
|
||||
#endif
|
||||
J3DMaterialInitData* init_data = &mpMaterialInitData[mpMaterialID[i_idx]];
|
||||
for (u8 i = 0; i < tev_stage_num; i++) {
|
||||
if (init_data->mTevKColorSel[i] != 0xff) {
|
||||
i_material->mTevBlock->setTevKColorSel(i, init_data->mTevKColorSel[i]);
|
||||
@@ -458,11 +423,7 @@ u32 J3DMaterialFactory::calcSizeNormalMaterial(J3DMaterial* i_material, int i_id
|
||||
size += J3DMaterial::calcSizeTevBlock((u16)tev_stage_num_max);
|
||||
size += J3DMaterial::calcSizeIndBlock(ind_flag);
|
||||
size += J3DMaterial::calcSizePEBlock(pe_flag, getMaterialMode(i_idx));
|
||||
#ifdef DUSK_TPHD
|
||||
J3DMaterialInitData* init_data = getMatInitData(i_idx);
|
||||
#else
|
||||
J3DMaterialInitData* init_data = &mpMaterialInitData[mpMaterialID[i_idx]];
|
||||
#endif
|
||||
for (u32 i = 0; i < 8; i++) {
|
||||
if (init_data->mTexMtxIdx[i] != 0xffff) {
|
||||
size += sizeof(J3DTexMtx);
|
||||
@@ -483,11 +444,7 @@ u32 J3DMaterialFactory::calcSizePatchedMaterial(J3DMaterial* i_material, int i_i
|
||||
size += sizeof(J3DTevBlockPatched);
|
||||
size += J3DMaterial::calcSizeIndBlock(ind_flag);
|
||||
size += J3DMaterial::calcSizePEBlock(0x10000000, getMaterialMode(i_idx));
|
||||
#ifdef DUSK_TPHD
|
||||
J3DMaterialInitData* init_data = getMatInitData(i_idx);
|
||||
#else
|
||||
J3DMaterialInitData* init_data = &mpMaterialInitData[mpMaterialID[i_idx]];
|
||||
#endif
|
||||
for (u32 i = 0; i < 8; i++) {
|
||||
if (init_data->mTexMtxIdx[i] != 0xffff) {
|
||||
size += sizeof(J3DTexMtx);
|
||||
@@ -517,11 +474,7 @@ J3DGXColor J3DMaterialFactory::newMatColor(int i_idx, int i_no) const {
|
||||
#else
|
||||
J3DGXColor dflt = GXColor{0xff, 0xff, 0xff, 0xff};
|
||||
#endif
|
||||
#ifdef DUSK_TPHD
|
||||
J3DMaterialInitData* mtl_init_data = getMatInitData(i_idx);
|
||||
#else
|
||||
J3DMaterialInitData* mtl_init_data = &mpMaterialInitData[mpMaterialID[i_idx]];
|
||||
#endif
|
||||
if (mtl_init_data->mMatColorIdx[i_no] != 0xffff) {
|
||||
return (GXColor) mpMatColor[mtl_init_data->mMatColorIdx[i_no]];
|
||||
} else {
|
||||
@@ -530,11 +483,7 @@ J3DGXColor J3DMaterialFactory::newMatColor(int i_idx, int i_no) const {
|
||||
}
|
||||
|
||||
const u8 J3DMaterialFactory::newColorChanNum(int i_idx) const {
|
||||
#ifdef DUSK_TPHD
|
||||
J3DMaterialInitData* mtl_init_data = getMatInitData(i_idx);
|
||||
#else
|
||||
J3DMaterialInitData* mtl_init_data = &mpMaterialInitData[mpMaterialID[i_idx]];
|
||||
#endif
|
||||
if (mtl_init_data->mColorChanNumIdx != 0xff) {
|
||||
return mpColorChanNum[mtl_init_data->mColorChanNumIdx];
|
||||
} else {
|
||||
@@ -544,11 +493,7 @@ const u8 J3DMaterialFactory::newColorChanNum(int i_idx) const {
|
||||
|
||||
J3DColorChan J3DMaterialFactory::newColorChan(int i_idx, int i_no) const {
|
||||
u32 r29 = 0;
|
||||
#ifdef DUSK_TPHD
|
||||
J3DMaterialInitData* init_data = getMatInitData(i_idx);
|
||||
#else
|
||||
J3DMaterialInitData* init_data = &mpMaterialInitData[mpMaterialID[i_idx]];
|
||||
#endif
|
||||
if (init_data->mColorChanIdx[i_no] != 0xffff) {
|
||||
return J3DColorChan(mpColorChanInfo[init_data->mColorChanIdx[i_no]]);
|
||||
} else {
|
||||
@@ -562,11 +507,7 @@ J3DGXColor J3DMaterialFactory::newAmbColor(int i_idx, int i_no) const {
|
||||
#else
|
||||
J3DGXColor dflt = GXColor{0x32, 0x32, 0x32, 0x32};
|
||||
#endif
|
||||
#ifdef DUSK_TPHD
|
||||
J3DMaterialInitData* mtl_init_data = getMatInitData(i_idx);
|
||||
#else
|
||||
J3DMaterialInitData* mtl_init_data = &mpMaterialInitData[mpMaterialID[i_idx]];
|
||||
#endif
|
||||
if (mtl_init_data->mAmbColorIdx[i_no] != 0xffff) {
|
||||
return (GXColor) mpAmbColor[mtl_init_data->mAmbColorIdx[i_no]];
|
||||
} else {
|
||||
@@ -576,11 +517,7 @@ J3DGXColor J3DMaterialFactory::newAmbColor(int i_idx, int i_no) const {
|
||||
|
||||
u32 J3DMaterialFactory::newTexGenNum(int i_idx) const {
|
||||
u32 r30 = 0;
|
||||
#ifdef DUSK_TPHD
|
||||
J3DMaterialInitData* mtl_init_data = getMatInitData(i_idx);
|
||||
#else
|
||||
J3DMaterialInitData* mtl_init_data = &mpMaterialInitData[mpMaterialID[i_idx]];
|
||||
#endif
|
||||
if (mtl_init_data->mTexGenNumIdx != 0xff) {
|
||||
return mpTexGenNum[mtl_init_data->mTexGenNumIdx];
|
||||
} else {
|
||||
@@ -589,11 +526,7 @@ u32 J3DMaterialFactory::newTexGenNum(int i_idx) const {
|
||||
}
|
||||
|
||||
J3DTexCoord J3DMaterialFactory::newTexCoord(int i_idx, int i_no) const {
|
||||
#ifdef DUSK_TPHD
|
||||
J3DMaterialInitData* mtl_init_data = getMatInitData(i_idx);
|
||||
#else
|
||||
J3DMaterialInitData* mtl_init_data = &mpMaterialInitData[mpMaterialID[i_idx]];
|
||||
#endif
|
||||
if (mtl_init_data->mTexCoordIdx[i_no] != 0xffff) {
|
||||
return J3DTexCoord(mpTexCoordInfo[mtl_init_data->mTexCoordIdx[i_no]]);
|
||||
} else {
|
||||
@@ -603,11 +536,7 @@ J3DTexCoord J3DMaterialFactory::newTexCoord(int i_idx, int i_no) const {
|
||||
|
||||
J3DTexMtx* J3DMaterialFactory::newTexMtx(int i_idx, int i_no) const {
|
||||
J3DTexMtx* tex_mtx = NULL;
|
||||
#ifdef DUSK_TPHD
|
||||
J3DMaterialInitData* mtl_init_data = getMatInitData(i_idx);
|
||||
#else
|
||||
J3DMaterialInitData* mtl_init_data = &mpMaterialInitData[mpMaterialID[i_idx]];
|
||||
#endif
|
||||
if (mtl_init_data->mTexMtxIdx[i_no] != 0xffff) {
|
||||
#if TARGET_LITTLE_ENDIAN
|
||||
auto tex_mtx_info = mpTexMtxInfo[mtl_init_data->mTexMtxIdx[i_no]];
|
||||
@@ -629,11 +558,7 @@ J3DTexMtx* J3DMaterialFactory::newTexMtx(int i_idx, int i_no) const {
|
||||
|
||||
u8 J3DMaterialFactory::newCullMode(int i_idx) const {
|
||||
u32 r30 = 0;
|
||||
#ifdef DUSK_TPHD
|
||||
J3DMaterialInitData* mtl_init_data = getMatInitData(i_idx);
|
||||
#else
|
||||
J3DMaterialInitData* mtl_init_data = &mpMaterialInitData[mpMaterialID[i_idx]];
|
||||
#endif
|
||||
if (mtl_init_data->mCullModeIdx != 0xff) {
|
||||
return mpCullMode[mtl_init_data->mCullModeIdx];
|
||||
} else {
|
||||
@@ -642,11 +567,7 @@ u8 J3DMaterialFactory::newCullMode(int i_idx) const {
|
||||
}
|
||||
|
||||
u16 J3DMaterialFactory::newTexNo(int i_idx, int i_no) const {
|
||||
#ifdef DUSK_TPHD
|
||||
J3DMaterialInitData* mtl_init_data = getMatInitData(i_idx);
|
||||
#else
|
||||
J3DMaterialInitData* mtl_init_data = &mpMaterialInitData[mpMaterialID[i_idx]];
|
||||
#endif
|
||||
if (mtl_init_data->mTexNoIdx[i_no] != 0xffff) {
|
||||
return mpTexNo[mtl_init_data->mTexNoIdx[i_no]];
|
||||
} else {
|
||||
@@ -655,11 +576,7 @@ u16 J3DMaterialFactory::newTexNo(int i_idx, int i_no) const {
|
||||
}
|
||||
|
||||
J3DTevOrder J3DMaterialFactory::newTevOrder(int i_idx, int i_no) const {
|
||||
#ifdef DUSK_TPHD
|
||||
J3DMaterialInitData* mtl_init_data = getMatInitData(i_idx);
|
||||
#else
|
||||
J3DMaterialInitData* mtl_init_data = &mpMaterialInitData[mpMaterialID[i_idx]];
|
||||
#endif
|
||||
if (mtl_init_data->mTevOrderIdx[i_no] != 0xffff) {
|
||||
return J3DTevOrder(mpTevOrderInfo[mtl_init_data->mTevOrderIdx[i_no]]);
|
||||
} else {
|
||||
@@ -670,11 +587,7 @@ J3DTevOrder J3DMaterialFactory::newTevOrder(int i_idx, int i_no) const {
|
||||
J3DGXColorS10 J3DMaterialFactory::newTevColor(int i_idx, int i_no) const {
|
||||
GXColorS10 _dflt = {0, 0, 0, 0};
|
||||
J3DGXColorS10 dflt = _dflt;
|
||||
#ifdef DUSK_TPHD
|
||||
J3DMaterialInitData* mtl_init_data = getMatInitData(i_idx);
|
||||
#else
|
||||
J3DMaterialInitData* mtl_init_data = &mpMaterialInitData[mpMaterialID[i_idx]];
|
||||
#endif
|
||||
if (mtl_init_data->mTevColorIdx[i_no] != 0xffff) {
|
||||
return (GXColorS10) mpTevColor[mtl_init_data->mTevColorIdx[i_no]];
|
||||
} else {
|
||||
@@ -688,11 +601,7 @@ J3DGXColor J3DMaterialFactory::newTevKColor(int i_idx, int i_no) const {
|
||||
#else
|
||||
J3DGXColor dflt = GXColor{0xff, 0xff, 0xff, 0xff};
|
||||
#endif
|
||||
#ifdef DUSK_TPHD
|
||||
J3DMaterialInitData* mtl_init_data = getMatInitData(i_idx);
|
||||
#else
|
||||
J3DMaterialInitData* mtl_init_data = &mpMaterialInitData[mpMaterialID[i_idx]];
|
||||
#endif
|
||||
if (mtl_init_data->mTevKColorIdx[i_no] != 0xffff) {
|
||||
return (GXColor) mpTevKColor[mtl_init_data->mTevKColorIdx[i_no]];
|
||||
} else {
|
||||
@@ -701,11 +610,7 @@ J3DGXColor J3DMaterialFactory::newTevKColor(int i_idx, int i_no) const {
|
||||
}
|
||||
|
||||
const u8 J3DMaterialFactory::newTevStageNum(int i_idx) const {
|
||||
#ifdef DUSK_TPHD
|
||||
J3DMaterialInitData* mtl_init_data = getMatInitData(i_idx);
|
||||
#else
|
||||
J3DMaterialInitData* mtl_init_data = &mpMaterialInitData[mpMaterialID[i_idx]];
|
||||
#endif
|
||||
if (mtl_init_data->mTevStageNumIdx != 0xff) {
|
||||
return mpTevStageNum[mtl_init_data->mTevStageNumIdx];
|
||||
} else {
|
||||
@@ -714,11 +619,7 @@ const u8 J3DMaterialFactory::newTevStageNum(int i_idx) const {
|
||||
}
|
||||
|
||||
J3DTevStage J3DMaterialFactory::newTevStage(int i_idx, int i_no) const {
|
||||
#ifdef DUSK_TPHD
|
||||
J3DMaterialInitData* mtl_init_data = getMatInitData(i_idx);
|
||||
#else
|
||||
J3DMaterialInitData* mtl_init_data = &mpMaterialInitData[mpMaterialID[i_idx]];
|
||||
#endif
|
||||
if (mtl_init_data->mTevStageIdx[i_no] != 0xffff) {
|
||||
return J3DTevStage(mpTevStageInfo[mtl_init_data->mTevStageIdx[i_no]]);
|
||||
} else {
|
||||
@@ -727,11 +628,7 @@ J3DTevStage J3DMaterialFactory::newTevStage(int i_idx, int i_no) const {
|
||||
}
|
||||
|
||||
J3DTevSwapModeTable J3DMaterialFactory::newTevSwapModeTable(int i_idx, int i_no) const {
|
||||
#ifdef DUSK_TPHD
|
||||
J3DMaterialInitData* mtl_init_data = getMatInitData(i_idx);
|
||||
#else
|
||||
J3DMaterialInitData* mtl_init_data = &mpMaterialInitData[mpMaterialID[i_idx]];
|
||||
#endif
|
||||
if (mtl_init_data->mTevSwapModeTableIdx[i_no] != 0xffff) {
|
||||
return J3DTevSwapModeTable(mpTevSwapModeTableInfo[mtl_init_data->mTevSwapModeTableIdx[i_no]]);
|
||||
} else {
|
||||
@@ -792,11 +689,7 @@ J3DIndTexCoordScale J3DMaterialFactory::newIndTexCoordScale(int i_idx, int i_no)
|
||||
|
||||
J3DFog J3DMaterialFactory::newFog(int i_idx) const {
|
||||
J3DFog fog;
|
||||
#ifdef DUSK_TPHD
|
||||
J3DMaterialInitData* mtl_init_data = getMatInitData(i_idx);
|
||||
#else
|
||||
J3DMaterialInitData* mtl_init_data = &mpMaterialInitData[mpMaterialID[i_idx]];
|
||||
#endif
|
||||
if (mtl_init_data->mFogIdx != 0xffff) {
|
||||
#if TARGET_LITTLE_ENDIAN
|
||||
J3DFogInfo fogInfo = mpFogInfo[mtl_init_data->mFogIdx];
|
||||
@@ -816,11 +709,7 @@ J3DFog J3DMaterialFactory::newFog(int i_idx) const {
|
||||
}
|
||||
|
||||
J3DAlphaComp J3DMaterialFactory::newAlphaComp(int i_idx) const {
|
||||
#ifdef DUSK_TPHD
|
||||
J3DMaterialInitData* mtl_init_data = getMatInitData(i_idx);
|
||||
#else
|
||||
J3DMaterialInitData* mtl_init_data = &mpMaterialInitData[mpMaterialID[i_idx]];
|
||||
#endif
|
||||
if (mtl_init_data->mAlphaCompIdx != 0xffff) {
|
||||
return J3DAlphaComp(mpAlphaCompInfo[mtl_init_data->mAlphaCompIdx]);
|
||||
} else {
|
||||
@@ -829,11 +718,7 @@ J3DAlphaComp J3DMaterialFactory::newAlphaComp(int i_idx) const {
|
||||
}
|
||||
|
||||
J3DBlend J3DMaterialFactory::newBlend(int i_idx) const {
|
||||
#ifdef DUSK_TPHD
|
||||
J3DMaterialInitData* mtl_init_data = getMatInitData(i_idx);
|
||||
#else
|
||||
J3DMaterialInitData* mtl_init_data = &mpMaterialInitData[mpMaterialID[i_idx]];
|
||||
#endif
|
||||
if (mtl_init_data->mBlendIdx != 0xffff) {
|
||||
return J3DBlend(mpBlendInfo[mtl_init_data->mBlendIdx]);
|
||||
} else {
|
||||
@@ -843,11 +728,7 @@ J3DBlend J3DMaterialFactory::newBlend(int i_idx) const {
|
||||
|
||||
J3DZMode J3DMaterialFactory::newZMode(int i_idx) const {
|
||||
u32 r29 = 0;
|
||||
#ifdef DUSK_TPHD
|
||||
J3DMaterialInitData* mtl_init_data = getMatInitData(i_idx);
|
||||
#else
|
||||
J3DMaterialInitData* mtl_init_data = &mpMaterialInitData[mpMaterialID[i_idx]];
|
||||
#endif
|
||||
if (mtl_init_data->mZModeIdx != 0xff) {
|
||||
return J3DZMode(mpZModeInfo[mtl_init_data->mZModeIdx]);
|
||||
} else {
|
||||
@@ -856,11 +737,7 @@ J3DZMode J3DMaterialFactory::newZMode(int i_idx) const {
|
||||
}
|
||||
|
||||
const u8 J3DMaterialFactory::newZCompLoc(int i_idx) const {
|
||||
#ifdef DUSK_TPHD
|
||||
J3DMaterialInitData* mtl_init_data = getMatInitData(i_idx);
|
||||
#else
|
||||
J3DMaterialInitData* mtl_init_data = &mpMaterialInitData[mpMaterialID[i_idx]];
|
||||
#endif
|
||||
if (mtl_init_data->mZCompLocIdx != 0xff){
|
||||
return mpZCompLoc[mtl_init_data->mZCompLocIdx];
|
||||
} else {
|
||||
@@ -869,11 +746,7 @@ const u8 J3DMaterialFactory::newZCompLoc(int i_idx) const {
|
||||
}
|
||||
|
||||
const u8 J3DMaterialFactory::newDither(int i_idx) const {
|
||||
#ifdef DUSK_TPHD
|
||||
J3DMaterialInitData* mtl_init_data = getMatInitData(i_idx);
|
||||
#else
|
||||
J3DMaterialInitData* mtl_init_data = &mpMaterialInitData[mpMaterialID[i_idx]];
|
||||
#endif
|
||||
if (mtl_init_data->mDitherIdx != 0xff){
|
||||
return mpDither[mtl_init_data->mDitherIdx];
|
||||
} else {
|
||||
@@ -881,24 +754,9 @@ const u8 J3DMaterialFactory::newDither(int i_idx) const {
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef DUSK_TPHD
|
||||
const PolygonOffset J3DMaterialFactory::newPolygonOffset(int i_idx) const {
|
||||
J3DMaterialInitData_MAT4* mtl_init_data = (J3DMaterialInitData_MAT4*)getMatInitData(i_idx);
|
||||
if (mBlockType >= 4 && mtl_init_data->mPolygonOffsetIdx != 0xffff){
|
||||
return mpPolygonOffsets[mtl_init_data->mPolygonOffsetIdx];
|
||||
} else {
|
||||
return PolygonOffset{0.0f, 0.0f, 0.0f, 0.0f, 0.0f};
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
J3DNBTScale J3DMaterialFactory::newNBTScale(int i_idx) const {
|
||||
J3DNBTScale dflt(j3dDefaultNBTScaleInfo);
|
||||
#ifdef DUSK_TPHD
|
||||
J3DMaterialInitData* mtl_init_data = getMatInitData(i_idx);
|
||||
#else
|
||||
J3DMaterialInitData* mtl_init_data = &mpMaterialInitData[mpMaterialID[i_idx]];
|
||||
#endif
|
||||
if (mtl_init_data->mNBTScaleIdx != 0xffff) {
|
||||
return J3DNBTScale(mpNBTScaleInfo[mtl_init_data->mNBTScaleIdx]);
|
||||
} else {
|
||||
|
||||
@@ -103,9 +103,6 @@ J3DModelData* J3DModelLoader::load(void const* i_data, u32 i_flags) {
|
||||
readJoint((J3DJointBlock*)block);
|
||||
break;
|
||||
case 'MAT3':
|
||||
#if DUSK_TPHD
|
||||
case 'MAT4':
|
||||
#endif
|
||||
readMaterial((J3DMaterialBlock*)block, (s32)i_flags);
|
||||
break;
|
||||
case 'MAT2':
|
||||
@@ -150,9 +147,6 @@ J3DMaterialTable* J3DModelLoader::loadMaterialTable(void const* i_data) {
|
||||
for (u32 block_no = 0; block_no < data->mBlockNum; block_no++) {
|
||||
switch (block->mBlockType) {
|
||||
case 'MAT3':
|
||||
#if DUSK_TPHD
|
||||
case 'MAT4':
|
||||
#endif
|
||||
readMaterialTable((J3DMaterialBlock*)block, flags);
|
||||
break;
|
||||
case 'MAT2':
|
||||
@@ -218,9 +212,6 @@ J3DModelData* J3DModelLoader::loadBinaryDisplayList(void const* i_data, u32 i_fl
|
||||
modifyMaterial(i_flags);
|
||||
break;
|
||||
case 'MAT3':
|
||||
#if DUSK_TPHD
|
||||
case 'MAT4':
|
||||
#endif
|
||||
flags = 0x50100000;
|
||||
flags |= (i_flags & 0x3000000);
|
||||
mpMaterialBlock = (J3DMaterialBlock*)block;
|
||||
@@ -317,22 +308,8 @@ static GXVtxAttrFmtList getFmt(GXVtxAttrFmtList* i_fmtList, GXAttr i_attr) {
|
||||
return *i_fmtList;
|
||||
}
|
||||
}
|
||||
#if DUSK_TPHD
|
||||
// HD BMDs occasionally have vertex arrays without a format entry. Mirror
|
||||
// the GC runtime: fall back to J3DSys::initGX defaults.
|
||||
GXVtxAttrFmtList def{};
|
||||
def.attr = i_attr;
|
||||
def.frac = 0;
|
||||
if (i_attr == GX_VA_POS) { def.cnt = GX_POS_XYZ; def.type = GX_F32; }
|
||||
else if (i_attr == GX_VA_NRM) { def.cnt = GX_NRM_XYZ; def.type = GX_F32; }
|
||||
else if (i_attr == GX_VA_NBT) { def.cnt = GX_NRM_NBT; def.type = GX_F32; }
|
||||
else if (i_attr >= GX_VA_CLR0 &&
|
||||
i_attr <= GX_VA_CLR1) { def.cnt = GX_CLR_RGBA; def.type = GX_RGBA8; }
|
||||
else { def.cnt = GX_TEX_ST; def.type = GX_F32; }
|
||||
return def;
|
||||
#else
|
||||
|
||||
OSPanic(__FILE__, __LINE__, "Unable to find vertex attribute format!");
|
||||
#endif
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
@@ -16,7 +16,7 @@ u16 J3DModelLoader::countMaterialNum(const void* stream) {
|
||||
const J3DModelBlock* block = header->mBlocks;
|
||||
for (int i = 0; i < header->mBlockNum; i++)
|
||||
{
|
||||
if (block->mBlockType == 'MAT3' || block->mBlockType == 'MAT4') {
|
||||
if (block->mBlockType == 'MAT3') {
|
||||
const J3DMaterialBlock* materialBlock = (const J3DMaterialBlock*)block;
|
||||
return materialBlock->mMaterialNum;
|
||||
}
|
||||
@@ -45,7 +45,6 @@ u32 J3DModelLoader::calcLoadSize(void const* stream, u32 flags_) {
|
||||
size += calcSizeJoint((const J3DJointBlock*)nextBlock);
|
||||
break;
|
||||
case 'MAT3':
|
||||
case 'MAT4':
|
||||
size += calcSizeMaterial((const J3DMaterialBlock*)nextBlock, flags);
|
||||
break;
|
||||
case 'SHP1':
|
||||
@@ -87,7 +86,6 @@ u32 J3DModelLoader::calcLoadMaterialTableSize(const void* stream) {
|
||||
for (u32 i = 0; i < header->mBlockNum; i++) {
|
||||
switch (nextBlock->mBlockType) {
|
||||
case 'MAT3':
|
||||
case 'MAT4':
|
||||
size += calcSizeMaterialTable((const J3DMaterialBlock*)nextBlock, flags);
|
||||
break;
|
||||
case 'TEX1':
|
||||
@@ -137,8 +135,7 @@ u32 J3DModelLoader::calcLoadBinaryDisplayListSize(const void* stream, u32 flags)
|
||||
case 'MDL3':
|
||||
size += calcSizeMaterialDL((const J3DMaterialDLBlock*)nextBlock, flags);
|
||||
break;
|
||||
case 'MAT3':
|
||||
case 'MAT4': {
|
||||
case 'MAT3': {
|
||||
u32 flags2 = (J3DMLF_21 | J3DMLF_Material_PE_Full | J3DMLF_Material_Color_LightOn);
|
||||
flags2 |= (u32)flags & (J3DMLF_Material_UseIndirect | J3DMLF_26);
|
||||
mpMaterialBlock = (const J3DMaterialBlock*)nextBlock;
|
||||
|
||||
@@ -38,7 +38,7 @@ void JFWDisplay::ctor_subroutine(bool enableAlpha) {
|
||||
mTickRate = 0;
|
||||
mCombinationRatio = 0.0f;
|
||||
field_0x30 = 0;
|
||||
field_0x2c = OSGetTick();
|
||||
field_0x2c = DUSK_IF_ELSE(static_cast<OSTick>(OSGetNativeTime()), OSGetTick());
|
||||
field_0x34 = 0;
|
||||
field_0x48 = 0;
|
||||
field_0x4a = 0;
|
||||
@@ -258,7 +258,7 @@ void JFWDisplay::beginRender() {
|
||||
waitForTick(mTickRate, mFrameRate);
|
||||
JUTVideo::getManager()->waitRetraceIfNeed();
|
||||
|
||||
OSTick tick = OSGetTick();
|
||||
OSTick tick = DUSK_IF_ELSE(static_cast<OSTick>(OSGetNativeTime()), OSGetTick());
|
||||
field_0x30 = tick - field_0x2c;
|
||||
field_0x2c = tick;
|
||||
field_0x34 = field_0x2c - JUTVideo::getVideoLastTick();
|
||||
@@ -371,7 +371,7 @@ constexpr auto FRAME_PERIOD = std::chrono::duration_cast<std::chrono::nanosecond
|
||||
constexpr auto RETRACE_PERIOD = FRAME_PERIOD / 2;
|
||||
|
||||
static void waitPrecise(Limiter& limiter, Limiter::duration_t targetNs) {
|
||||
const auto sleepTime = limiter.Sleep(targetNs);
|
||||
const auto sleepTime = limiter.Sleep(targetNs);
|
||||
dusk::frameUsagePct =
|
||||
100.0f * (1.0f - static_cast<float>(sleepTime) / static_cast<float>(targetNs));
|
||||
}
|
||||
@@ -381,15 +381,12 @@ static void waitForTick(u32 p1, u16 p2) {
|
||||
#if TARGET_PC
|
||||
static Limiter limiter;
|
||||
|
||||
if (dusk::frame_interp::is_enabled() && !dusk::getTransientSettings().skipFrameRateLimit) {
|
||||
dusk::frameUsagePct = 0.f;
|
||||
return;
|
||||
if (dusk::frame_interp::is_enabled() || dusk::getTransientSettings().turboMode) {
|
||||
limiter.Reset();
|
||||
dusk::frameUsagePct = 0.f;
|
||||
return;
|
||||
}
|
||||
|
||||
if (dusk::getTransientSettings().skipFrameRateLimit) {
|
||||
p1 = OS_TIMER_CLOCK / 120;
|
||||
}
|
||||
|
||||
if (fopOvlpM_IsPeek() && dusk::getTransientSettings().stateShareLoadActive) {
|
||||
return;
|
||||
}
|
||||
@@ -399,7 +396,6 @@ static void waitForTick(u32 p1, u16 p2) {
|
||||
|
||||
if (p1 != 0) {
|
||||
#if TARGET_PC
|
||||
static Limiter limiter;
|
||||
waitPrecise(limiter, static_cast<Uint64>(OSTicksToMicroseconds(p1)) * 1000ULL);
|
||||
#else
|
||||
static OSTime nextTick = OSGetTime();
|
||||
@@ -413,7 +409,6 @@ static void waitForTick(u32 p1, u16 p2) {
|
||||
} else {
|
||||
u32 uVar1 = (p2 == 0) ? 1 : p2;
|
||||
#if TARGET_PC
|
||||
static Limiter limiter;
|
||||
waitPrecise(limiter, static_cast<Uint64>((RETRACE_PERIOD * uVar1).count()));
|
||||
#else
|
||||
static u32 nextCount = VIGetRetraceCount();
|
||||
|
||||
@@ -11,11 +11,6 @@
|
||||
#include <cstring>
|
||||
#include "os_report.h"
|
||||
|
||||
#if DUSK_TPHD
|
||||
#include "dusk/settings.h"
|
||||
#include "dusk/tphd/HdAssetLayer.hpp"
|
||||
#endif
|
||||
|
||||
JKRAramArchive::JKRAramArchive() {}
|
||||
|
||||
JKRAramArchive::JKRAramArchive(s32 entryNumber, JKRArchive::EMountDirection mountDirection)
|
||||
@@ -222,13 +217,6 @@ void* JKRAramArchive::fetchResource(SDIFileEntry* pEntry, u32* pOutSize) {
|
||||
if (compression == COMPRESSION_YAZ0) {
|
||||
this->setExpandSize(pEntry, *pOutSize);
|
||||
}
|
||||
#if DUSK_TPHD
|
||||
// ARAM mounts bypass register_mounted_hd_archive; hook the fresh per-file buffer here.
|
||||
if (dusk::tphd_active() && mStringTable != NULL) {
|
||||
dusk::tphd::register_copied_hd_resource(
|
||||
mEntryNum, mStringTable + pEntry->getNameOffset(), outBuf, *pOutSize);
|
||||
}
|
||||
#endif
|
||||
} else {
|
||||
if (compression == COMPRESSION_YAZ0) {
|
||||
*pOutSize = this->getExpandSize(pEntry);
|
||||
|
||||
@@ -9,24 +9,6 @@
|
||||
#include "JSystem/JKernel/JKRMemArchive.h"
|
||||
#include "JSystem/JUtility/JUTAssert.h"
|
||||
|
||||
#if DUSK_TPHD
|
||||
#include "dusk/tphd/HdAssetLayer.hpp"
|
||||
|
||||
namespace {
|
||||
void register_copied_hd_resource(
|
||||
JKRArchive* archive, JKRArchive::SDIFileEntry* fileEntry, void* buffer, u32 resourceSize) {
|
||||
if (archive == NULL || fileEntry == NULL || buffer == NULL || resourceSize == 0 ||
|
||||
archive->mStringTable == NULL)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
dusk::tphd::register_copied_hd_resource(archive->mEntryNum,
|
||||
archive->mStringTable + fileEntry->getNameOffset(), buffer, resourceSize);
|
||||
}
|
||||
} // namespace
|
||||
#endif
|
||||
|
||||
JKRArchive* JKRArchive::check_mount_already(s32 entryNum, JKRHeap* heap) {
|
||||
if (heap == NULL) {
|
||||
heap = JKRGetCurrentHeap();
|
||||
@@ -214,9 +196,6 @@ u32 JKRArchive::readResource(void* buffer, u32 bufferSize, u32 type, const char*
|
||||
if (fileEntry) {
|
||||
u32 resourceSize;
|
||||
fetchResource(buffer, bufferSize, fileEntry, &resourceSize);
|
||||
#if DUSK_TPHD
|
||||
register_copied_hd_resource(this, fileEntry, buffer, resourceSize);
|
||||
#endif
|
||||
return resourceSize;
|
||||
}
|
||||
|
||||
@@ -235,9 +214,6 @@ u32 JKRArchive::readResource(void* buffer, u32 bufferSize, const char* path) {
|
||||
if (fileEntry) {
|
||||
u32 resourceSize;
|
||||
fetchResource(buffer, bufferSize, fileEntry, &resourceSize);
|
||||
#if DUSK_TPHD
|
||||
register_copied_hd_resource(this, fileEntry, buffer, resourceSize);
|
||||
#endif
|
||||
return resourceSize;
|
||||
}
|
||||
|
||||
@@ -250,9 +226,6 @@ u32 JKRArchive::readIdxResource(void* buffer, u32 bufferSize, u32 index) {
|
||||
if (fileEntry) {
|
||||
u32 resourceSize;
|
||||
fetchResource(buffer, bufferSize, fileEntry, &resourceSize);
|
||||
#if DUSK_TPHD
|
||||
register_copied_hd_resource(this, fileEntry, buffer, resourceSize);
|
||||
#endif
|
||||
return resourceSize;
|
||||
}
|
||||
|
||||
@@ -265,9 +238,6 @@ u32 JKRArchive::readResource(void* buffer, u32 bufferSize, u16 id) {
|
||||
if (fileEntry) {
|
||||
u32 resourceSize;
|
||||
fetchResource(buffer, bufferSize, fileEntry, &resourceSize);
|
||||
#if DUSK_TPHD
|
||||
register_copied_hd_resource(this, fileEntry, buffer, resourceSize);
|
||||
#endif
|
||||
return resourceSize;
|
||||
}
|
||||
|
||||
|
||||
@@ -10,10 +10,6 @@
|
||||
#include <stdint.h>
|
||||
#include "os_report.h"
|
||||
|
||||
#if DUSK_TPHD
|
||||
#include "dusk/tphd/HdAssetLayer.hpp"
|
||||
#endif
|
||||
|
||||
JKRMemArchive::JKRMemArchive(s32 entryNum, JKRArchive::EMountDirection mountDirection)
|
||||
: JKRArchive(entryNum, MOUNT_MEM) {
|
||||
mIsMounted = false;
|
||||
@@ -71,13 +67,8 @@ bool JKRMemArchive::open(s32 entryNum, JKRArchive::EMountDirection mountDirectio
|
||||
mIsOpen = false;
|
||||
mMountDirection = mountDirection;
|
||||
|
||||
#ifdef TARGET_PC
|
||||
u32 loadedSize = 0;
|
||||
#endif
|
||||
if (mMountDirection == JKRArchive::MOUNT_DIRECTION_HEAD) {
|
||||
#ifndef TARGET_PC
|
||||
u32 loadedSize;
|
||||
#endif
|
||||
mArcHeader = (SArcHeader *)JKRDvdToMainRam(
|
||||
entryNum, NULL, EXPAND_SWITCH_UNKNOWN1, 0, mHeap, JKRDvdRipper::ALLOC_DIRECTION_FORWARD,
|
||||
0, (int *)&mCompression, &loadedSize);
|
||||
@@ -86,9 +77,7 @@ bool JKRMemArchive::open(s32 entryNum, JKRArchive::EMountDirection mountDirectio
|
||||
}
|
||||
}
|
||||
else {
|
||||
#ifndef TARGET_PC
|
||||
u32 loadedSize;
|
||||
#endif
|
||||
mArcHeader = (SArcHeader *)JKRDvdToMainRam(
|
||||
entryNum, NULL, EXPAND_SWITCH_UNKNOWN1, 0, mHeap,
|
||||
JKRDvdRipper::ALLOC_DIRECTION_BACKWARD, 0, (int *)&mCompression, &loadedSize);
|
||||
@@ -101,9 +90,6 @@ bool JKRMemArchive::open(s32 entryNum, JKRArchive::EMountDirection mountDirectio
|
||||
mMountMode = UNKNOWN_MOUNT_MODE;
|
||||
}
|
||||
else {
|
||||
#if DUSK_TPHD
|
||||
dusk::tphd::register_mounted_hd_archive(entryNum, mArcHeader, loadedSize);
|
||||
#endif
|
||||
JUT_ASSERT(438, mArcHeader->signature == 'RARC');
|
||||
mArcInfoBlock = (SArcDataInfo *)((u8 *)mArcHeader + mArcHeader->header_length);
|
||||
mNodes = (SDIDirEntry *)((u8 *)&mArcInfoBlock->num_nodes + mArcInfoBlock->node_offset);
|
||||
|
||||
@@ -42,7 +42,7 @@ JUTVideo::JUTVideo(GXRenderModeObj const* param_0) {
|
||||
mRetraceCount = VIGetRetraceCount();
|
||||
field_0x10 = 1;
|
||||
field_0x18 = 0;
|
||||
sVideoLastTick = OSGetTick();
|
||||
sVideoLastTick = DUSK_IF_ELSE(static_cast<OSTick>(OSGetNativeTime()), OSGetTick());
|
||||
sVideoInterval = 670000;
|
||||
mPreRetraceCallback = VISetPreRetraceCallback(preRetraceProc);
|
||||
mPostRetraceCallback = VISetPostRetraceCallback(postRetraceProc);
|
||||
@@ -68,7 +68,7 @@ void JUTVideo::preRetraceProc(u32 retrace_count) {
|
||||
(*sManager->mPreCallback)(retrace_count);
|
||||
}
|
||||
|
||||
OSTick tick = OSGetTick();
|
||||
OSTick tick = DUSK_IF_ELSE(static_cast<OSTick>(OSGetNativeTime()), OSGetTick());
|
||||
sVideoInterval = tick - sVideoLastTick;
|
||||
sVideoLastTick = tick;
|
||||
|
||||
|
||||
@@ -0,0 +1,34 @@
|
||||
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
|
||||
)
|
||||
|
||||
target_link_libraries(basic_cosmetics_mod PRIVATE xxHash::xxhash)
|
||||
@@ -0,0 +1,7 @@
|
||||
{
|
||||
"id": "dev.twilitrealm.basic_cosmetics",
|
||||
"name": "Basic Cosmetics",
|
||||
"version": "1.0.0",
|
||||
"author": "Twilit Realm",
|
||||
"description": "Change Basic Cosmetic Colors"
|
||||
}
|
||||
@@ -0,0 +1,94 @@
|
||||
#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<uint8_t>((2 * base * blend) / 255);
|
||||
}
|
||||
|
||||
return static_cast<uint8_t>(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;
|
||||
}
|
||||
}
|
||||
@@ -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 <gx.h>
|
||||
|
||||
#include <cstdint>
|
||||
#include <string>
|
||||
|
||||
// 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);
|
||||
@@ -0,0 +1,686 @@
|
||||
#include "hooks.hpp"
|
||||
|
||||
#include "mod.hpp"
|
||||
#include "color_utils.hpp"
|
||||
#include "midna_hair_color.hpp"
|
||||
#include "types.h"
|
||||
|
||||
#include "mods/svc/hook.hpp"
|
||||
#include "mods/svc/log.hpp"
|
||||
|
||||
#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_meter_button.h"
|
||||
#include "d/d_meter_hakusha.h"
|
||||
#include "d/d_meter2.h"
|
||||
#include "d/d_meter2_draw.h"
|
||||
#include "d/d_meter2_info.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"
|
||||
#include "SSystem/SComponent/c_phase.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<CPaneMgr*>(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<JUtility::TColor>(args, 1);
|
||||
auto& white = mods::arg_ref<JUtility::TColor>(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<dKantera_icon_c*>(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<daAlink_c*>(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<J2DPicture*>(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<dMeter2Draw_c*>(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<J2DPicture*>(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<dFile_info_c*>(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<J2DPicture*>(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<dMeterButton_c*>(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<dMenu_save_c*>(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<dFile_select_c*>(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<dBrightCheck_c*>(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<dMenu_Ring_c*>(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<dMenu_Collect2D_c*>(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<dMenu_Fishing_c*>(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<dMenu_Insect_c*>(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<dMenu_Letter_c*>(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<dMenu_Option_c*>(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<dMenu_Skill_c*>(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<dMenu_Fmap_c*>(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<dMsgObject_c*>(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<dMeterHakusha_c*>(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<COutFont_c*>(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<COutFontSet_c*>(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<daItemBase_c*>(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<u8**>(&itemBase->mpBrkAnm->getBrkAnm()->mAnmCRegDataR);
|
||||
u8** kRegTable = reinterpret_cast<u8**>(&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<int*>(retval);
|
||||
// Don't set colors if midna isn't done loading
|
||||
if (*step != cPhs_COMPLEATE_e) {
|
||||
return;
|
||||
}
|
||||
|
||||
auto midna = mods::arg<daMidna_c*>(args, 0);
|
||||
midna->field_0x6e0 = *get_midna_hair_normalColor();
|
||||
if (dKy_darkworld_check()) {
|
||||
midna->field_0x6e8 = *get_midna_hair_normalKColor();
|
||||
midna->field_0x6ec = *get_midna_hair_normalKColor2();
|
||||
} else {
|
||||
midna->field_0x6e8 = *get_midna_hair_lNormalKColor();
|
||||
midna->field_0x6ec = *get_midna_hair_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<daMidna_c*>(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<daMidna_c*>(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 = *get_midna_hair_bigKColor();
|
||||
if (dKy_darkworld_check()) {
|
||||
color = *get_midna_hair_bigColor();
|
||||
kcolor2 = *get_midna_hair_normalKColor2();
|
||||
} else {
|
||||
color = *get_midna_hair_lBigColor();
|
||||
kcolor2 = *get_midna_hair_lBigKColor2();
|
||||
}
|
||||
} else {
|
||||
color = *get_midna_hair_normalColor();
|
||||
if (dKy_darkworld_check()) {
|
||||
kcolor1 = *get_midna_hair_normalKColor();
|
||||
kcolor2 = *get_midna_hair_normalKColor2();
|
||||
} else {
|
||||
kcolor1 = *get_midna_hair_lNormalKColor();
|
||||
kcolor2 = *get_midna_hair_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<u8**>(&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<defined_hook>(function); \
|
||||
if (result != MOD_OK) { \
|
||||
mods::log::debug("failed to add post hook to" #original ", Result {}", static_cast<int>(result)); \
|
||||
return result; \
|
||||
}
|
||||
|
||||
#define ADD_PRE_HOOK(defined_hook, function, original) \
|
||||
result = mods::hook::add_pre<defined_hook>(function); \
|
||||
if (result != MOD_OK) { \
|
||||
mods::log::debug("failed to add pre hook to" #original ", Result {}", static_cast<int>(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<defined_hook>(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;
|
||||
}
|
||||
@@ -0,0 +1,7 @@
|
||||
#pragma once
|
||||
|
||||
#include "mods/service.hpp"
|
||||
|
||||
ModResult add_all_hooks();
|
||||
|
||||
ModResult remove_all_hooks();
|
||||
@@ -0,0 +1,141 @@
|
||||
#include "midna_hair_color.hpp"
|
||||
#include "mod.hpp"
|
||||
|
||||
#include "mods/svc/log.hpp"
|
||||
|
||||
#include <array>
|
||||
|
||||
static constexpr std::array<std::array<GXColor, 9>, 10> midnaHairColors = {{
|
||||
// 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}
|
||||
}}
|
||||
}};
|
||||
|
||||
static struct {
|
||||
GXColorS10 l_normalColor = { 0x50, 0x00, 0x00, 0x00 };
|
||||
GXColor l_normalKColor = { 0xB4, 0x87, 0x00, 0x00 };
|
||||
GXColor l_normalKColor2 = { 0x00, 0xC3, 0xC3, 0x00 };
|
||||
GXColorS10 l_bigColor = { 0xFF, 0x64, 0x78, 0x00 };
|
||||
GXColor l_bigKColor = { 0x1E, 0x00, 0x00, 0x00 };
|
||||
GXColor l_lNormalKColor = { 0xFF, 0xDC, 0x00, 0x00 };
|
||||
GXColor l_lNormalKColor2 = { 0x00, 0xC3, 0xEB, 0x00 };
|
||||
GXColorS10 l_lBigColor = { 0xFF, 0x78, 0x00, 0x00 };
|
||||
GXColor l_lBigKColor2 = { 0xAA, 0xFF, 0xC3, 0x00 };
|
||||
} currentMidnaHairColors;
|
||||
|
||||
void set_all_midna_hair_colors() {
|
||||
auto& g_cvars = get_cvars();
|
||||
auto hairBaseColor = get_int_option(g_cvars.midnaHairBaseColor, 0);
|
||||
auto hairTipsColor = get_int_option(g_cvars.midnaHairTipsColor, 0);
|
||||
|
||||
// Colors we have to convert to GXColorS10
|
||||
auto& normalColor = midnaHairColors.at(hairBaseColor)[2];
|
||||
auto& bigColor = midnaHairColors.at(hairBaseColor)[5];
|
||||
auto& lBigColor = midnaHairColors.at(hairBaseColor)[4];
|
||||
|
||||
currentMidnaHairColors.l_normalColor = GXColorS10{normalColor.r, normalColor.g, normalColor.b};
|
||||
currentMidnaHairColors.l_normalKColor = midnaHairColors.at(hairBaseColor)[1];
|
||||
currentMidnaHairColors.l_normalKColor2 = midnaHairColors.at(hairTipsColor)[7];
|
||||
currentMidnaHairColors.l_bigColor = GXColorS10{bigColor.r, bigColor.g, bigColor.b};
|
||||
currentMidnaHairColors.l_bigKColor = midnaHairColors.at(hairBaseColor)[3];
|
||||
currentMidnaHairColors.l_lNormalKColor = midnaHairColors.at(hairBaseColor)[0];
|
||||
currentMidnaHairColors.l_lNormalKColor2 = midnaHairColors.at(hairTipsColor)[6];
|
||||
currentMidnaHairColors.l_lBigColor = GXColorS10{lBigColor.r, lBigColor.g, lBigColor.b};
|
||||
currentMidnaHairColors.l_lBigKColor2 = midnaHairColors.at(hairTipsColor)[8];
|
||||
}
|
||||
|
||||
const GXColorS10* get_midna_hair_normalColor() {
|
||||
return ¤tMidnaHairColors.l_normalColor;
|
||||
}
|
||||
|
||||
const GXColor* get_midna_hair_normalKColor() {
|
||||
return ¤tMidnaHairColors.l_normalKColor;
|
||||
}
|
||||
|
||||
const GXColor* get_midna_hair_normalKColor2() {
|
||||
return ¤tMidnaHairColors.l_normalKColor2;
|
||||
}
|
||||
|
||||
const GXColorS10* get_midna_hair_bigColor() {
|
||||
return ¤tMidnaHairColors.l_bigColor;
|
||||
}
|
||||
|
||||
const GXColor* get_midna_hair_bigKColor() {
|
||||
return ¤tMidnaHairColors.l_bigKColor;
|
||||
}
|
||||
|
||||
const GXColor* get_midna_hair_lNormalKColor() {
|
||||
return ¤tMidnaHairColors.l_lNormalKColor;
|
||||
}
|
||||
|
||||
const GXColor* get_midna_hair_lNormalKColor2() {
|
||||
return ¤tMidnaHairColors.l_lNormalKColor2;
|
||||
}
|
||||
|
||||
const GXColorS10* get_midna_hair_lBigColor() {
|
||||
return ¤tMidnaHairColors.l_lBigColor;
|
||||
}
|
||||
|
||||
const GXColor* get_midna_hair_lBigKColor2() {
|
||||
return ¤tMidnaHairColors.l_lBigKColor2;
|
||||
}
|
||||
@@ -0,0 +1,15 @@
|
||||
#pragma once
|
||||
|
||||
#include <gx.h>
|
||||
|
||||
void set_all_midna_hair_colors();
|
||||
|
||||
const GXColorS10* get_midna_hair_normalColor();
|
||||
const GXColor* get_midna_hair_normalKColor();
|
||||
const GXColor* get_midna_hair_normalKColor2();
|
||||
const GXColorS10* get_midna_hair_bigColor();
|
||||
const GXColor* get_midna_hair_bigKColor();
|
||||
const GXColor* get_midna_hair_lNormalKColor();
|
||||
const GXColor* get_midna_hair_lNormalKColor2();
|
||||
const GXColorS10* get_midna_hair_lBigColor();
|
||||
const GXColor* get_midna_hair_lBigKColor2();
|
||||
@@ -0,0 +1,460 @@
|
||||
#include "mod.hpp"
|
||||
#include "color_utils.hpp"
|
||||
#include "hooks.hpp"
|
||||
#include "midna_hair_color.hpp"
|
||||
#include "option_descriptions.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 <xxhash.h>
|
||||
|
||||
#include <optional>
|
||||
#include <ranges>
|
||||
#include <string>
|
||||
|
||||
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<GXColor> get_config_var_color(ConfigVarHandle handle, bool allowRainbow /*= false*/) {
|
||||
auto colorStr = get_str_option(handle, "");
|
||||
|
||||
// Convert to lowercase
|
||||
for (auto& c : colorStr) {
|
||||
c = static_cast<char>(std::tolower(static_cast<unsigned char>(c)));
|
||||
}
|
||||
|
||||
if (is_valid_hex_color_str(colorStr) || (colorStr == "rainbow" && allowRainbow)) {
|
||||
if (is_valid_hex_color_str(colorStr)) {
|
||||
return hex_color_str_to_gx_color(colorStr);
|
||||
}
|
||||
|
||||
if (allowRainbow) {
|
||||
// Assume rainbow if not a valid hex str
|
||||
auto color = get_rainbow_rgb(127.5f);
|
||||
color.r /= 2;
|
||||
color.g /= 2;
|
||||
color.b /= 2;
|
||||
return color;
|
||||
}
|
||||
}
|
||||
|
||||
return std::nullopt;
|
||||
}
|
||||
|
||||
namespace {
|
||||
UiWindowHandle g_cosmeticsWindow = 0;
|
||||
bool g_loadedAllBaseTextures = false;
|
||||
|
||||
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<int>(result));
|
||||
}
|
||||
}
|
||||
|
||||
void add_cosmetic_option(UiElementHandle left, ConfigVarHandle cvar, const char* name, const char* helpRml) {
|
||||
UiControlDesc control = UI_CONTROL_DESC_INIT;
|
||||
control.kind = UI_CONTROL_STRING;
|
||||
control.label = name;
|
||||
control.help_rml = helpRml;
|
||||
control.binding = UI_BINDING_CONFIG_VAR;
|
||||
control.config_var = cvar;
|
||||
control.max_length = 6;
|
||||
add_control(left, control);
|
||||
}
|
||||
|
||||
void add_cosmetic_option_with_rainbow(UiElementHandle left, ConfigVarHandle cvar, const char* name, const char* helpRml) {
|
||||
UiControlDesc control = UI_CONTROL_DESC_INIT;
|
||||
control.kind = UI_CONTROL_STRING;
|
||||
control.label = name;
|
||||
control.help_rml = helpRml;
|
||||
control.binding = UI_BINDING_CONFIG_VAR;
|
||||
control.config_var = cvar;
|
||||
control.max_length = 7;
|
||||
add_control(left, 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);
|
||||
}
|
||||
|
||||
ModResult build_equipment_colors_tab(
|
||||
ModContext*, UiWindowHandle, UiElementHandle left, UiElementHandle right, void*, ModError*) {
|
||||
(void)right;
|
||||
|
||||
add_cosmetic_option(left, g_cvars.herosTunicCapColor, "Hero's Tunic Cap Color", kLinksCapColorsExplanation);
|
||||
add_cosmetic_option(left, g_cvars.herosTunicTorsoColor, "Hero's Tunic Body Color", kLinksShirtColorsExplanation);
|
||||
add_cosmetic_option(left, g_cvars.herosTunicSkirtColor, "Hero's Tunic Skirt Color", kLinksSkirtColorsExplanation);
|
||||
add_cosmetic_option(left, g_cvars.zoraArmorCapColor, "Zora Armor Cap Color", kZoraCapColorsExplanation);
|
||||
add_cosmetic_option(left, g_cvars.zoraArmorHelmetColor, "Zora Armor Helmet Color", kZoraHelmetColorsExplanation);
|
||||
add_cosmetic_option(left, g_cvars.zoraArmorTorsoColor, "Zora Armor Torso Color", kZoraTorsoColorsExplanation);
|
||||
add_cosmetic_option(left, g_cvars.zoraArmorScalesColor, "Zora Armor Scales Color", kZoraScalesColorsExplanation);
|
||||
add_cosmetic_option(left, g_cvars.zoraArmorFlippersColor, "Zora Armor Flippers Color", kZoraFlippersColorsExplanation);
|
||||
add_cosmetic_option_with_rainbow(left, g_cvars.lanternGlowColor, "Lantern Glow Color", kLanternGlowColorsExplanation);
|
||||
add_cosmetic_option(left, g_cvars.woodenSwordColor, "Wooden Sword Color", kWoodenSwordColorsExplanation);
|
||||
add_cosmetic_option(left, g_cvars.ordonSwordBladeColor, "Ordon Sword Blade Color", kOrdonBladeColorsExplanation);
|
||||
add_cosmetic_option(left, g_cvars.ordonSwordHandleColor, "Ordon Sword Handle Color", kOrdonHandleColorsExplanation);
|
||||
add_cosmetic_option(left, g_cvars.msBladeColor, "Master Sword Blade Color", kMSBladeColorsExplanation);
|
||||
add_cosmetic_option(left, g_cvars.msHandleColor, "Master Sword Handle Color", kMSHandleColorsExplanation);
|
||||
add_cosmetic_option_with_rainbow(left, g_cvars.lightSwordGlowColor, "Light Sword Glow Color", kSwordGlowColorsExplanation);
|
||||
add_cosmetic_option(left, g_cvars.boomerangColor, "Boomerang Color", kBoomerangColorsExplanation);
|
||||
add_cosmetic_option(left, g_cvars.ironBootsColor, "Iron Boots Color", kIronBootsColorsExplanation);
|
||||
add_cosmetic_option(left, g_cvars.spinnerColor, "Spinner Color", kSpinnerColorsExplanation);
|
||||
|
||||
return MOD_OK;
|
||||
}
|
||||
|
||||
ModResult build_ui_colors_tab(
|
||||
ModContext*, UiWindowHandle, UiElementHandle left, UiElementHandle right, void*, ModError*) {
|
||||
(void)right;
|
||||
|
||||
add_cosmetic_option(left, g_cvars.aButtonColor, "A Button Color", kAButtonColorsExplanation);
|
||||
add_cosmetic_option(left, g_cvars.bButtonColor, "B Button Color", kBButtonColorsExplanation);
|
||||
add_cosmetic_option(left, g_cvars.xButtonColor, "X Button Color", kXButtonColorsExplanation);
|
||||
add_cosmetic_option(left, g_cvars.yButtonColor, "Y Button Color", kYButtonColorsExplanation);
|
||||
add_cosmetic_option(left, g_cvars.zButtonColor, "Z Button Color", kZButtonColorsExplanation);
|
||||
add_cosmetic_option(left, g_cvars.heartColor, "Heart Color", kHeartColorsExplanation);
|
||||
|
||||
return MOD_OK;
|
||||
}
|
||||
|
||||
ModResult build_misc_colors_tab(
|
||||
ModContext*, UiWindowHandle, UiElementHandle left, UiElementHandle right, void*, ModError*) {
|
||||
(void)right;
|
||||
|
||||
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");
|
||||
add_cosmetic_option(left, g_cvars.midnaChargeRingColor, "Midna Charge Ring Color", kChargeRingColorsExplanation);
|
||||
add_cosmetic_option(left, g_cvars.linkHairColor, "Link's Hair Color", kLinksHairColorsExplanation);
|
||||
add_cosmetic_option(left, g_cvars.wolfLinkColor, "Wolf Link Color", kWolfLinkColorsExplanation);
|
||||
add_cosmetic_option(left, g_cvars.eponaColor, "Epona Color", kEponaColorsExplanation);
|
||||
|
||||
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 Colors";
|
||||
tabs[0].build = build_equipment_colors_tab;
|
||||
tabs[1].title = "UI Colors";
|
||||
tabs[1].build = build_ui_colors_tab;
|
||||
tabs[2].title = "Misc Colors";
|
||||
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_BUTTON;
|
||||
control.label = "Open Cosmetics Menu";
|
||||
control.on_pressed = on_open_cosmetics_menu;
|
||||
add_control(panel, control);
|
||||
return MOD_OK;
|
||||
}
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
// Try to get the model this texture is part of. If we can't get it, try again later
|
||||
auto model = static_cast<J3DModelData*>(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
|
||||
auto size = get_image_data_size(imageHeader->format, imageHeader->width,
|
||||
imageHeader->height, imageHeader->mipmapEnabled ? imageHeader->mipmapCount : 1);
|
||||
replacement.baseTextureData.resize(size);
|
||||
std::memcpy(replacement.baseTextureData.data(), tex->getImgDataPtr(i), size);
|
||||
|
||||
// Calculate the texture hash
|
||||
auto textureHash = XXH64(replacement.baseTextureData.data(), size, 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 = imageHeader->mipmapCount;
|
||||
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;
|
||||
}
|
||||
|
||||
// If we don't have a valid color, don't continue either
|
||||
auto maybeColor = get_config_var_color(configVar);
|
||||
if (!maybeColor.has_value()) {
|
||||
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);
|
||||
|
||||
replacement.data.data = newTexture.data();
|
||||
replacement.data.size = newTexture.size();
|
||||
|
||||
// Register the new data
|
||||
auto result = svc_texture->register_data(mod_ctx, &replacement.key, &replacement.data, &replacement.handle);
|
||||
if (result != MOD_OK) {
|
||||
mods::log::debug("Could not register_data for {}. Result: {}", replacement.textureName, static_cast<int>(result));
|
||||
} else {
|
||||
mods::log::debug("Registered replacement for {}.", replacement.textureName, static_cast<int>(result));
|
||||
}
|
||||
|
||||
curColor = color;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
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);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#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;
|
||||
return MOD_OK;
|
||||
}
|
||||
|
||||
MOD_EXPORT ModResult mod_update(ModError*) {
|
||||
update_rainbow_rgb(1.0f);
|
||||
set_all_midna_hair_colors();
|
||||
|
||||
if (!g_loadedAllBaseTextures) {
|
||||
load_base_texture_data();
|
||||
}
|
||||
|
||||
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();
|
||||
return MOD_OK;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,65 @@
|
||||
#pragma once
|
||||
|
||||
#include "mods/svc/config.h"
|
||||
#include "mods/svc/texture.h"
|
||||
|
||||
#include <gx.h>
|
||||
|
||||
#include <optional>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
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<u8> baseTextureData{};
|
||||
bool loadedTextureData = false;
|
||||
std::optional<GXColor> 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<GXColor> get_config_var_color(ConfigVarHandle handle, bool allowRainbow = false);
|
||||
@@ -0,0 +1,353 @@
|
||||
#pragma once
|
||||
|
||||
constexpr const char* kLinksCapColorsExplanation =
|
||||
"Set the color of the Hero's Tunic cap with any 6 digit hex code.<br/>"
|
||||
"Common colors:<br/>"
|
||||
"- Red: ab706e<br/>"
|
||||
"- Blue: 6382a0<br/>"
|
||||
"- Purple: 94749a<br/>"
|
||||
"- Orange: ec8644<br/>"
|
||||
"- Yellow: b9ab00<br/>"
|
||||
"- Pink: ec9fc8<br/>"
|
||||
"- Black: 505154<br/>"
|
||||
"- White: f8f7f4<br/>"
|
||||
"- Brown: 91723e<br/>";
|
||||
|
||||
constexpr const char* kLinksShirtColorsExplanation =
|
||||
"Set the color of the Hero's Tunic shirt with any 6 digit hex code.<br/>"
|
||||
"Common colors:<br/>"
|
||||
"- Red: ab706e<br/>"
|
||||
"- Blue: 6382a0<br/>"
|
||||
"- Purple: 94749a<br/>"
|
||||
"- Orange: ec8644<br/>"
|
||||
"- Yellow: b9ab00<br/>"
|
||||
"- Pink: ec9fc8<br/>"
|
||||
"- Black: 505154<br/>"
|
||||
"- White: f8f7f4<br/>"
|
||||
"- Brown: 91723e<br/>";
|
||||
|
||||
constexpr const char* kLinksSkirtColorsExplanation =
|
||||
"Set the color of the Hero's Tunic skirt with any 6 digit hex code.<br/>"
|
||||
"Common colors:<br/>"
|
||||
"- Red: ab706e<br/>"
|
||||
"- Blue: 6382a0<br/>"
|
||||
"- Purple: 94749a<br/>"
|
||||
"- Orange: ec8644<br/>"
|
||||
"- Yellow: b9ab00<br/>"
|
||||
"- Pink: ec9fc8<br/>"
|
||||
"- Black: 505154<br/>"
|
||||
"- White: f8f7f4<br/>"
|
||||
"- Brown: 91723e<br/>";
|
||||
|
||||
constexpr const char* kZoraCapColorsExplanation =
|
||||
"Set the color of the Zora Armor cap with any 6 digit hex code.<br/>"
|
||||
"Common colors:<br/>"
|
||||
"- Red: ab706e<br/>"
|
||||
"- Blue: 6382a0<br/>"
|
||||
"- Purple: 94749a<br/>"
|
||||
"- Orange: ec8644<br/>"
|
||||
"- Yellow: b9ab00<br/>"
|
||||
"- Pink: ec9fc8<br/>"
|
||||
"- Black: 505154<br/>"
|
||||
"- White: f8f7f4<br/>"
|
||||
"- Brown: 91723e<br/>";
|
||||
|
||||
constexpr const char* kZoraHelmetColorsExplanation =
|
||||
"Set the color of the Zora Armor helmet with any 6 digit hex code.<br/>"
|
||||
"Common colors:<br/>"
|
||||
"- Red: ab706e<br/>"
|
||||
"- Blue: 6382a0<br/>"
|
||||
"- Purple: 94749a<br/>"
|
||||
"- Orange: ec8644<br/>"
|
||||
"- Yellow: b9ab00<br/>"
|
||||
"- Pink: ec9fc8<br/>"
|
||||
"- Black: 505154<br/>"
|
||||
"- White: f8f7f4<br/>"
|
||||
"- Brown: 91723e<br/>";
|
||||
|
||||
constexpr const char* kZoraTorsoColorsExplanation =
|
||||
"Set the color of the Zora Armor torso with any 6 digit hex code.<br/>"
|
||||
"Common colors:<br/>"
|
||||
"- Red: ab706e<br/>"
|
||||
"- Blue: 6382a0<br/>"
|
||||
"- Purple: 94749a<br/>"
|
||||
"- Orange: ec8644<br/>"
|
||||
"- Yellow: b9ab00<br/>"
|
||||
"- Pink: ec9fc8<br/>"
|
||||
"- Black: 505154<br/>"
|
||||
"- White: f8f7f4<br/>"
|
||||
"- Brown: 91723e<br/>";
|
||||
|
||||
constexpr const char* kZoraScalesColorsExplanation =
|
||||
"Set the color of the Zora Armor scales with any 6 digit hex code.<br/>"
|
||||
"Common colors:<br/>"
|
||||
"- Red: ab706e<br/>"
|
||||
"- Blue: 6382a0<br/>"
|
||||
"- Purple: 94749a<br/>"
|
||||
"- Orange: ec8644<br/>"
|
||||
"- Yellow: b9ab00<br/>"
|
||||
"- Pink: ec9fc8<br/>"
|
||||
"- Black: 505154<br/>"
|
||||
"- White: f8f7f4<br/>"
|
||||
"- Brown: 91723e<br/>";
|
||||
|
||||
constexpr const char* kZoraFlippersColorsExplanation =
|
||||
"Set the color of the Zora Armor flippers with any 6 digit hex code.<br/>"
|
||||
"Common colors:<br/>"
|
||||
"- Red: ab706e<br/>"
|
||||
"- Blue: 6382a0<br/>"
|
||||
"- Purple: 94749a<br/>"
|
||||
"- Orange: ec8644<br/>"
|
||||
"- Yellow: b9ab00<br/>"
|
||||
"- Pink: ec9fc8<br/>"
|
||||
"- Black: 505154<br/>"
|
||||
"- White: f8f7f4<br/>"
|
||||
"- Brown: 91723e<br/>";
|
||||
|
||||
constexpr const char* kWoodenSwordColorsExplanation =
|
||||
"Set the color of the wooden sword with any 6 digit hex code.<br/>"
|
||||
"Common colors:<br/>"
|
||||
"- Red: ab706e<br/>"
|
||||
"- Blue: 6382a0<br/>"
|
||||
"- Purple: 94749a<br/>"
|
||||
"- Orange: ec8644<br/>"
|
||||
"- Yellow: b9ab00<br/>"
|
||||
"- Pink: ec9fc8<br/>"
|
||||
"- Black: 505154<br/>"
|
||||
"- White: f8f7f4<br/>"
|
||||
"- Brown: 91723e<br/>";
|
||||
|
||||
constexpr const char* kLanternGlowColorsExplanation =
|
||||
"Set the color of the lantern light with any 6 digit hex code, or with \"rainbow\" for a rainbow effect.<br/>"
|
||||
"Common colors:<br/>"
|
||||
"- Red: ff0000<br/>"
|
||||
"- Orange: f68821<br/>"
|
||||
"- Yellow: f6f321<br/>"
|
||||
"- Green: 00ff00<br/>"
|
||||
"- Blue: 0000ff<br/>"
|
||||
"- Purple: 8000ff<br/>"
|
||||
"- White: a0a0a0<br/>";
|
||||
|
||||
constexpr const char* kOrdonBladeColorsExplanation =
|
||||
"Set the color of the Ordon Sword's blade with any 6 digit hex code.<br/>"
|
||||
"Common colors:<br/>"
|
||||
"- Red: ff0000<br/>"
|
||||
"- Orange: f68821<br/>"
|
||||
"- Yellow: f6f321<br/>"
|
||||
"- Green: 00ff00<br/>"
|
||||
"- Blue: 0000ff<br/>"
|
||||
"- Purple: 8000ff<br/>"
|
||||
"- White: a0a0a0<br/>"
|
||||
"- Cyan: 30d0d0<br/>";
|
||||
|
||||
constexpr const char* kOrdonHandleColorsExplanation =
|
||||
"Set the color of the Ordon Sword's handle with any 6 digit hex code.<br/>"
|
||||
"Common colors:<br/>"
|
||||
"- Red: ff0000<br/>"
|
||||
"- Orange: f68821<br/>"
|
||||
"- Yellow: f6f321<br/>"
|
||||
"- Green: 00ff00<br/>"
|
||||
"- Blue: 0000ff<br/>"
|
||||
"- Purple: 8000ff<br/>"
|
||||
"- White: a0a0a0<br/>"
|
||||
"- Cyan: 30d0d0<br/>";
|
||||
|
||||
constexpr const char* kMSBladeColorsExplanation =
|
||||
"Set the color of the Master Sword's blade with any 6 digit hex code.<br/>"
|
||||
"Common colors:<br/>"
|
||||
"- Red: ff0000<br/>"
|
||||
"- Orange: f68821<br/>"
|
||||
"- Yellow: f6f321<br/>"
|
||||
"- Green: 00ff00<br/>"
|
||||
"- Blue: 0000ff<br/>"
|
||||
"- Purple: 8000ff<br/>"
|
||||
"- White: a0a0a0<br/>"
|
||||
"- Cyan: 30d0d0<br/>";
|
||||
|
||||
constexpr const char* kMSHandleColorsExplanation =
|
||||
"Set the color of the Master Sword's handle with any 6 digit hex code.<br/>"
|
||||
"Common colors:<br/>"
|
||||
"- Red: ff0000<br/>"
|
||||
"- Orange: f68821<br/>"
|
||||
"- Yellow: f6f321<br/>"
|
||||
"- Green: 00ff00<br/>"
|
||||
"- Blue: 0000ff<br/>"
|
||||
"- Purple: 8000ff<br/>"
|
||||
"- White: a0a0a0<br/>"
|
||||
"- Cyan: 30d0d0<br/>";
|
||||
|
||||
constexpr const char* kSwordGlowColorsExplanation =
|
||||
"Set the color of the light sword glow with any 6 digit hex code, or with \"rainbow\" for a rainbow effect.<br/>"
|
||||
"Common colors:<br/>"
|
||||
"- Red: ff0000<br/>"
|
||||
"- Orange: f68821<br/>"
|
||||
"- Yellow: f6f321<br/>"
|
||||
"- Green: 00ff00<br/>"
|
||||
"- Blue: 0000ff<br/>"
|
||||
"- Purple: 8000ff<br/>"
|
||||
"- White: a0a0a0<br/>";
|
||||
|
||||
constexpr const char* kBoomerangColorsExplanation =
|
||||
"Set the color of the Gale Boomerang with any 6 digit hex code.<br/>"
|
||||
"Common colors:<br/>"
|
||||
"- Red: ab706e<br/>"
|
||||
"- Blue: 6382a0<br/>"
|
||||
"- Purple: 94749a<br/>"
|
||||
"- Orange: ec8644<br/>"
|
||||
"- Yellow: b9ab00<br/>"
|
||||
"- Pink: ec9fc8<br/>"
|
||||
"- Black: 505154<br/>"
|
||||
"- White: f8f7f4<br/>"
|
||||
"- Brown: 91723e<br/>";
|
||||
|
||||
constexpr const char* kIronBootsColorsExplanation =
|
||||
"Set the color of the Iron Boots with any 6 digit hex code.<br/>"
|
||||
"Common colors:<br/>"
|
||||
"- Red: ab706e<br/>"
|
||||
"- Blue: 6382a0<br/>"
|
||||
"- Purple: 94749a<br/>"
|
||||
"- Orange: ec8644<br/>"
|
||||
"- Yellow: b9ab00<br/>"
|
||||
"- Pink: ec9fc8<br/>"
|
||||
"- Black: 505154<br/>"
|
||||
"- White: f8f7f4<br/>"
|
||||
"- Brown: 91723e<br/>";
|
||||
|
||||
constexpr const char* kSpinnerColorsExplanation =
|
||||
"Set the color of the Spinner with any 6 digit hex code.<br/>"
|
||||
"Common colors:<br/>"
|
||||
"- Red: ab706e<br/>"
|
||||
"- Blue: 6382a0<br/>"
|
||||
"- Purple: 94749a<br/>"
|
||||
"- Orange: ec8644<br/>"
|
||||
"- Yellow: b9ab00<br/>"
|
||||
"- Pink: ec9fc8<br/>"
|
||||
"- Black: 505154<br/>"
|
||||
"- White: f8f7f4<br/>"
|
||||
"- Brown: 91723e<br/>";
|
||||
|
||||
constexpr const char* kAButtonColorsExplanation =
|
||||
"Set the color of the A button with any 6 digit hex code. A reload may be necessary to see changes.<br/>"
|
||||
"Common colors:<br/>"
|
||||
"- Red: ff0000<br/>"
|
||||
"- Orange: ff5000<br/>"
|
||||
"- Yellow: ffaf00<br/>"
|
||||
"- Dark Green: 0080ff<br/>"
|
||||
"- Blue: 0000ff<br/>"
|
||||
"- Purple: 8000ff<br/>"
|
||||
"- Grey: 5555ff<br/>"
|
||||
"- Pink: ff20ff<br/>";
|
||||
|
||||
constexpr const char* kBButtonColorsExplanation =
|
||||
"Set the color of the B button with any 6 digit hex code. A reload may be necessary to see changes.<br/>"
|
||||
"Common colors:<br/>"
|
||||
"- Orange: ffff40<br/>"
|
||||
"- Pink: ffa0ff<br/>"
|
||||
"- Green: 00e87b<br/>"
|
||||
"- Blue: 00aaff<br/>"
|
||||
"- Purple: 6078ff<br/>"
|
||||
"- Black: 000000<br/>"
|
||||
"- Teal: 00f3ff<br/>";
|
||||
|
||||
constexpr const char* kXButtonColorsExplanation =
|
||||
"Set the color of the X button with any 6 digit hex code. A reload may be necessary to see changes.<br/>"
|
||||
"Common colors:<br/>"
|
||||
"- Red: ff0000<br/>"
|
||||
"- Orange: ff8200<br/>"
|
||||
"- Yellow: f7df00<br/>"
|
||||
"- Lime Green: 70ff00<br/>"
|
||||
"- Dark Green: 00bd11<br/>"
|
||||
"- Blue: 0000ff<br/>"
|
||||
"- Purple: 800088<br/>"
|
||||
"- Black: 000000<br/>"
|
||||
"- Pink: ff00aa<br/>"
|
||||
"- Cyan: 00ffff<br/>";
|
||||
|
||||
constexpr const char* kYButtonColorsExplanation =
|
||||
"Set the color of the Y button with any 6 digit hex code. A reload may be necessary to see changes.<br/>"
|
||||
"Common colors:<br/>"
|
||||
"- Red: ff0000<br/>"
|
||||
"- Orange: ff8200<br/>"
|
||||
"- Yellow: f7df00<br/>"
|
||||
"- Lime Green: 70ff00<br/>"
|
||||
"- Dark Green: 00bd11<br/>"
|
||||
"- Blue: 0000ff<br/>"
|
||||
"- Purple: 800088<br/>"
|
||||
"- Black: 000000<br/>"
|
||||
"- Pink: ff00aa<br/>"
|
||||
"- Cyan: 00ffff<br/>";
|
||||
|
||||
constexpr const char* kZButtonColorsExplanation =
|
||||
"Set the Z button color with any 6 digit hex code. A reload may be necessary to see changes.<br/>"
|
||||
"Common colors:<br/>"
|
||||
"- Red: ff0000<br/>"
|
||||
"- Orange: ff8200<br/>"
|
||||
"- Yellow: f7df00<br/>"
|
||||
"- Lime Green: 70ff00<br/>"
|
||||
"- Dark Green: 00bd11<br/>"
|
||||
"- Purple: 800088<br/>"
|
||||
"- Black: 000000<br/>"
|
||||
"- Light Blue: 00ffff<br/>";
|
||||
|
||||
constexpr const char* kHeartColorsExplanation =
|
||||
"Set the heart color with any 6 digit hex code. This will also change the color of heart drops. A reload may be necessary to see changes.<br/>"
|
||||
"Common colors:<br/>"
|
||||
"- Orange: ffff40<br/>"
|
||||
"- Pink: ffa0ff<br/>"
|
||||
"- Green: 00e87b<br/>"
|
||||
"- Blue: 00aaff<br/>"
|
||||
"- Purple: 6078ff<br/>"
|
||||
"- Black: 000000<br/>"
|
||||
"- Teal: 00f3ff<br/>";
|
||||
|
||||
constexpr const char* kChargeRingColorsExplanation =
|
||||
"Set the color of Midna's charge ring with any 6 digit hex code.<br/>"
|
||||
"Common colors:<br/>"
|
||||
"- Pink: ff9f9f<br/>"
|
||||
"- Red: ff0000<br/>"
|
||||
"- Yellow: ffff00<br/>"
|
||||
"- Green: 00ff00<br/>"
|
||||
"- Blue: 0000ff<br/>"
|
||||
"- Purple: ff00ff<br/>"
|
||||
"- Brown: 331900<br/>"
|
||||
"- White: feffff<br/>"
|
||||
"- Black: 000000<br/>";
|
||||
|
||||
constexpr const char* kLinksHairColorsExplanation =
|
||||
"Set the color of Link's hair with any 6 digit hex code.<br/>"
|
||||
"Common colors:<br/>"
|
||||
"- Red: ab706e<br/>"
|
||||
"- Blue: 6382a0<br/>"
|
||||
"- Purple: 94749a<br/>"
|
||||
"- Orange: ec8644<br/>"
|
||||
"- Yellow: b9ab00<br/>"
|
||||
"- Pink: ec9fc8<br/>"
|
||||
"- Black: 505154<br/>"
|
||||
"- White: f8f7f4<br/>"
|
||||
"- Brown: 91723e<br/>";
|
||||
|
||||
constexpr const char* kWolfLinkColorsExplanation =
|
||||
"Set the color of Wolf Link with any 6 digit hex code.<br/>"
|
||||
"Common colors:<br/>"
|
||||
"- Red: ab706e<br/>"
|
||||
"- Blue: 6382a0<br/>"
|
||||
"- Purple: 94749a<br/>"
|
||||
"- Orange: ec8644<br/>"
|
||||
"- Yellow: b9ab00<br/>"
|
||||
"- Pink: ec9fc8<br/>"
|
||||
"- Black: 505154<br/>"
|
||||
"- White: f8f7f4<br/>"
|
||||
"- Brown: 91723e<br/>";
|
||||
|
||||
constexpr const char* kEponaColorsExplanation =
|
||||
"Set the color of Epona with any 6 digit hex code.<br/>"
|
||||
"Common colors:<br/>"
|
||||
"- Red: ab706e<br/>"
|
||||
"- Blue: 6382a0<br/>"
|
||||
"- Purple: 94749a<br/>"
|
||||
"- Orange: ec8644<br/>"
|
||||
"- Yellow: b9ab00<br/>"
|
||||
"- Pink: ec9fc8<br/>"
|
||||
"- Black: 505154<br/>"
|
||||
"- White: f8f7f4<br/>"
|
||||
"- Brown: 91723e<br/>";
|
||||
@@ -0,0 +1,672 @@
|
||||
#include "texture_utils.hpp"
|
||||
#include "color_utils.hpp"
|
||||
#include "mod.hpp"
|
||||
|
||||
#include "mods/svc/config.h"
|
||||
#include "mods/svc/log.hpp"
|
||||
|
||||
// Forward declaration needed for J3DModelLoader to be happy
|
||||
class J3DVertexData;
|
||||
#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<u8>& 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<BE<uint16_t>*>(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<BE<uint32_t>*>(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<u8>& 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);
|
||||
}
|
||||
|
||||
constexpr int32_t blockWidth = 4;
|
||||
constexpr int32_t blockHeight = 4;
|
||||
|
||||
const int32_t roundedWidth = replacementData.key.width + ((blockWidth - (replacementData.key.width % blockWidth)) % blockWidth);
|
||||
const int32_t roundedHeight = replacementData.key.height + ((blockHeight - (replacementData.key.height % blockHeight)) % blockHeight);
|
||||
|
||||
const int32_t totalPixels = roundedWidth * roundedHeight;
|
||||
|
||||
auto* pixelPtr = newTextureDataOut.data();
|
||||
|
||||
for (int32_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<uint8_t>((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<uint8_t>((r8 * 77 + g8 * 150 + b8 * 29) >> 8);
|
||||
|
||||
// Combine original alpha with recolored RGB444
|
||||
pixelPtr[i] = alpha3 | recolors_rgb444[grayVal];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// 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<uint16_t>((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<uint8_t>(c0_565 >> 8);
|
||||
dst[1] = static_cast<uint8_t>(c0_565 & 0xFF);
|
||||
dst[2] = static_cast<uint8_t>(c1_565 >> 8);
|
||||
dst[3] = static_cast<uint8_t>(c1_565 & 0xFF);
|
||||
dst[4] = static_cast<uint8_t>(indices >> 24);
|
||||
dst[5] = static_cast<uint8_t>((indices >> 16) & 0xFF);
|
||||
dst[6] = static_cast<uint8_t>((indices >> 8) & 0xFF);
|
||||
dst[7] = static_cast<uint8_t>(indices & 0xFF);
|
||||
}
|
||||
|
||||
bool convert_i8_to_cmpr(TextureReplacementData& replacementData, std::vector<u8>& cmprOut) {
|
||||
if (cmprOut.empty() || replacementData.key.width % 8 != 0 || replacementData.key.height % 8 != 0) {
|
||||
return false;
|
||||
}
|
||||
|
||||
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;
|
||||
|
||||
const uint8_t* readPtr = cmprOut.data();
|
||||
uint8_t* writePtr = cmprOut.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) {
|
||||
const uint32_t topTileIdx = (2 * by) * tilesX_I8 + bx;
|
||||
const uint32_t bottomTileIdx = (2 * by + 1) * tilesX_I8 + bx;
|
||||
|
||||
const uint8_t* topTileData = readPtr + (topTileIdx * 32);
|
||||
const uint8_t* bottomTileData = readPtr + (bottomTileIdx * 32);
|
||||
|
||||
uint8_t subBlockPixels[4][16];
|
||||
|
||||
for (int row = 0; row < 4; ++row) {
|
||||
for (int col = 0; col < 4; ++col) {
|
||||
subBlockPixels[0][row * 4 + col] = topTileData[row * 8 + col];
|
||||
subBlockPixels[1][row * 4 + col] = topTileData[row * 8 + col + 4];
|
||||
}
|
||||
}
|
||||
|
||||
for (int row = 0; row < 4; ++row) {
|
||||
for (int col = 0; col < 4; ++col) {
|
||||
subBlockPixels[2][row * 4 + col] = bottomTileData[row * 8 + col];
|
||||
subBlockPixels[3][row * 4 + col] = bottomTileData[row * 8 + col + 4];
|
||||
}
|
||||
}
|
||||
|
||||
// Write 32 bytes of CMPR output into the same buffer
|
||||
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);
|
||||
}
|
||||
|
||||
// Resize for new CMPR image
|
||||
const size_t finalSize = writePtr - cmprOut.data();
|
||||
cmprOut.resize(finalSize);
|
||||
|
||||
// Update format
|
||||
replacementData.data.gx_format = GX_TF_CMPR;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void recolor_texture(TextureReplacementData& replacementData, GXColor color, std::vector<u8>& 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<ConfigVarHandle, std::list<TextureReplacementData>>& get_texture_replacements() {
|
||||
static std::unordered_map<ConfigVarHandle, std::list<TextureReplacementData>> 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;
|
||||
}
|
||||
@@ -0,0 +1,19 @@
|
||||
#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 <gx.h>
|
||||
|
||||
#include <list>
|
||||
#include <unordered_map>
|
||||
|
||||
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<u8>& newTextureDataOut);
|
||||
|
||||
std::unordered_map<ConfigVarHandle, std::list<TextureReplacementData>>& get_texture_replacements();
|
||||
@@ -16,7 +16,7 @@
|
||||
* of letting them corrupt memory.
|
||||
*/
|
||||
#define GAME_SERVICE_ID "dev.twilitrealm.dusklight.game"
|
||||
#define GAME_SERVICE_MAJOR 1u
|
||||
#define GAME_SERVICE_MAJOR 2u
|
||||
#define GAME_SERVICE_MINOR 0u
|
||||
|
||||
typedef struct GameService {
|
||||
|
||||
@@ -0,0 +1,94 @@
|
||||
#pragma once
|
||||
|
||||
#include <mods/api.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
#include <mods/service.hpp>
|
||||
#endif
|
||||
|
||||
#define ITEM_SERVICE_ID "dev.twilitrealm.dusklight.item"
|
||||
#define ITEM_SERVICE_MAJOR 2u
|
||||
#define ITEM_SERVICE_MINOR 0u
|
||||
|
||||
/* 0 is never a valid handle. */
|
||||
typedef uint64_t ItemCheckHandle;
|
||||
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.
|
||||
*/
|
||||
|
||||
/* Host-owned callback data, valid only for the duration of the callback. */
|
||||
typedef struct ItemCheckInfo {
|
||||
const char* name;
|
||||
const void* giver_actor; /* fopAc_ac_c*, or NULL when unavailable */
|
||||
uint8_t vanilla_item;
|
||||
uint8_t current_item;
|
||||
} ItemCheckInfo;
|
||||
|
||||
/* Return true and write out_item to replace current_item, or false to leave it unchanged. */
|
||||
typedef bool (*ItemCheckResolveFn)(
|
||||
ModContext* ctx, const ItemCheckInfo* info, uint8_t* out_item, void* user_data);
|
||||
|
||||
typedef enum ItemGiveOrigin {
|
||||
ITEM_GIVE_ORIGIN_GAME = 0,
|
||||
ITEM_GIVE_ORIGIN_QUEUE = 1,
|
||||
ITEM_GIVE_ORIGIN_QUEUE_SILENT = 2,
|
||||
} ItemGiveOrigin;
|
||||
|
||||
/* Host-owned callback data, valid only for the duration of the callback. */
|
||||
typedef struct ItemGiveInfo {
|
||||
const char* check_name; /* NULL when the grant is not attributed to a check */
|
||||
const void* giver_actor; /* fopAc_ac_c*, or NULL when unavailable */
|
||||
uint8_t item;
|
||||
uint8_t origin; /* ItemGiveOrigin */
|
||||
} ItemGiveInfo;
|
||||
|
||||
typedef void (*ItemGiveObserveFn)(ModContext* ctx, const ItemGiveInfo* info, void* user_data);
|
||||
|
||||
enum {
|
||||
/* Apply the inventory change without a get-item demo. */
|
||||
ITEM_GIVE_SILENT = 1u << 0,
|
||||
/* Resolve item_no as the named check's vanilla item when the queue entry is dispatched. */
|
||||
ITEM_GIVE_RESOLVE = 1u << 1,
|
||||
};
|
||||
|
||||
typedef struct ItemService {
|
||||
ServiceHeader header;
|
||||
|
||||
/* Set or replace the calling mod's fixed override for name. */
|
||||
ModResult (*set_check_override)(ModContext* ctx, const char* name, uint8_t item_no);
|
||||
|
||||
ModResult (*clear_check_override)(ModContext* ctx, const char* name);
|
||||
|
||||
/* Register for name, or for every check when name is NULL. out_handle may be NULL. */
|
||||
ModResult (*set_check_resolver)(ModContext* ctx, const char* name, ItemCheckResolveFn fn,
|
||||
void* user_data, ItemCheckHandle* out_handle);
|
||||
|
||||
ModResult (*clear_check_resolver)(ModContext* ctx, ItemCheckHandle handle);
|
||||
|
||||
/* Resolve 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.
|
||||
*/
|
||||
ModResult (*give_item)(
|
||||
ModContext* ctx, const char* check_name, uint8_t item_no, uint32_t flags);
|
||||
|
||||
/* Observe inventory grants. out_handle may be NULL. */
|
||||
ModResult (*observe_gives)(
|
||||
ModContext* ctx, ItemGiveObserveFn fn, void* user_data, ItemGiveHandle* out_handle);
|
||||
|
||||
ModResult (*unobserve_gives)(ModContext* ctx, ItemGiveHandle handle);
|
||||
} ItemService;
|
||||
|
||||
MOD_DECLARE_SERVICE(ItemService, svc_item, ITEM_SERVICE_ID, ITEM_SERVICE_MAJOR, ITEM_SERVICE_MINOR);
|
||||
@@ -15,9 +15,6 @@ static const char* sSpotName[] = {
|
||||
"D_MN08A", "D_MN08D", "D_MN09", "D_MN09A", "D_MN09B", "D_MN09C", "D_SB00", "D_SB01",
|
||||
"D_SB02", "D_SB03", "D_SB04", "D_SB05", "D_SB06", "D_SB07", "D_SB08", "D_SB09",
|
||||
"D_SB10",
|
||||
#if TARGET_PC
|
||||
"D_SB11",
|
||||
#endif
|
||||
};
|
||||
|
||||
#endif /* SPOTNAME_H */
|
||||
|
||||
@@ -1603,35 +1603,13 @@ void Z2SceneMgr::setSceneName(char* spot, s32 room, s32 layer) {
|
||||
bgm_wave1 = 0x45;
|
||||
}
|
||||
break;
|
||||
#if TARGET_PC
|
||||
case Z2SCENE_CAVE_OF_SHADOWS:
|
||||
if (room == 29) {
|
||||
se_wave2 = 0x16;
|
||||
} else if (room == 40) {
|
||||
se_wave2 = 0x12;
|
||||
} else {
|
||||
se_wave2 = 0x36;
|
||||
}
|
||||
|
||||
bgm_wave1 = 0x45;
|
||||
se_wave1 = 0x51;
|
||||
mDoAud_zelAudio_c::onBgmSet();
|
||||
bgm_id = Z2BGM_SUB_DUNGEON;
|
||||
|
||||
if (BGM_ID == Z2BGM_SUB_DUNGEON) {
|
||||
if (sceneNum == Z2SCENE_CAVE_OF_ORDEALS) {
|
||||
BGM_ID = -1;
|
||||
}
|
||||
}
|
||||
break;
|
||||
#endif
|
||||
}
|
||||
|
||||
/*dSv_event_flag_c::M_071 - Cutscene - [cutscene: 20] Zant appears (during Midna's desperate hour) */
|
||||
if (dComIfGs_isEventBit(dSv_event_flag_c::saveBitLabels[104])
|
||||
/* dSv_event_flag_c::F_0250 - Cutscene - [cutscene: 21] reunion with Zelda / Midna revived (Hyrule Castle barrier appears) */
|
||||
&& !dComIfGs_isEventBit(dSv_event_flag_c::saveBitLabels[250])
|
||||
&& demo_wave == 0 && spotNo != Z2SCENE_ELDIN_BRIDGE_BATTLE IF_DUSK(&& spotNo != Z2SCENE_CAVE_OF_SHADOWS))
|
||||
&& demo_wave == 0 && spotNo != Z2SCENE_ELDIN_BRIDGE_BATTLE)
|
||||
{
|
||||
bgm_wave1 = 0x36;
|
||||
if (spotNo == Z2SCENE_CASTLE_TOWN_SHOPS && room == 5) {
|
||||
|
||||
@@ -583,12 +583,6 @@ void Z2SeqMgr::bgmStreamPlay() {
|
||||
}
|
||||
}
|
||||
|
||||
#if TARGET_PC
|
||||
if (dusk::tphd_active()) {
|
||||
return;
|
||||
}
|
||||
#endif
|
||||
|
||||
#if !PLATFORM_SHIELD
|
||||
else if (getStreamBgmID() == 0x2000000) {
|
||||
if (mStreamBgmHandle) {
|
||||
|
||||
+27
-29
@@ -5,53 +5,51 @@
|
||||
|
||||
#include "d/dolzel.h" // IWYU pragma: keep
|
||||
|
||||
#include "d/actor/d_a_alink.h"
|
||||
#include "JSystem/J2DGraph/J2DAnmLoader.h"
|
||||
#include "JSystem/J3DGraphBase/J3DDrawBuffer.h"
|
||||
#include "JSystem/J3DGraphBase/J3DMaterial.h"
|
||||
#include "JSystem/J3DGraphLoader/J3DAnmLoader.h"
|
||||
#include "JSystem/J3DGraphBase/J3DDrawBuffer.h"
|
||||
#include "JSystem/JHostIO/JORServer.h"
|
||||
#include "JSystem/JKernel/JKRExpHeap.h"
|
||||
#include "SSystem/SComponent/c_math.h"
|
||||
#include "d/actor/d_a_alink.h"
|
||||
#include "d/actor/d_a_b_mgn.h"
|
||||
#include "d/actor/d_a_canoe.h"
|
||||
#include "d/actor/d_a_cow.h"
|
||||
#include "d/d_item.h"
|
||||
#include "d/d_meter2_draw.h"
|
||||
#include "d/d_pane_class.h"
|
||||
#include "d/d_demo.h"
|
||||
#include "d/actor/d_a_crod.h"
|
||||
#include "d/actor/d_a_horse.h"
|
||||
#include "d/actor/d_a_kytag05.h"
|
||||
#include "d/actor/d_a_mg_rod.h"
|
||||
#include "d/actor/d_a_midna.h"
|
||||
#include "d/actor/d_a_mirror.h"
|
||||
#include "d/actor/d_a_ni.h"
|
||||
#include "d/actor/d_a_npc_bou.h"
|
||||
#include "d/actor/d_a_npc_kolin.h"
|
||||
#include "d/actor/d_a_spinner.h"
|
||||
#include "d/actor/d_a_tbox.h"
|
||||
#include "d/actor/d_a_tag_Lv6Gate.h"
|
||||
#include "d/actor/d_a_tag_kmsg.h"
|
||||
#include "d/actor/d_a_tag_magne.h"
|
||||
#include "d/actor/d_a_tag_wljump.h"
|
||||
#include "d/actor/d_a_npc_tk.h"
|
||||
#include "d/actor/d_a_cow.h"
|
||||
#include "d/actor/d_a_obj_crope.h"
|
||||
#include "d/actor/d_a_obj_wchain.h"
|
||||
#include "d/actor/d_a_scene_exit.h"
|
||||
#include "d/actor/d_a_spinner.h"
|
||||
#include "d/actor/d_a_tag_Lv6Gate.h"
|
||||
#include "d/actor/d_a_tag_hstop.h"
|
||||
#include "d/actor/d_a_tag_kmsg.h"
|
||||
#include "d/actor/d_a_tag_lantern.h"
|
||||
#include "d/actor/d_a_tag_magne.h"
|
||||
#include "d/actor/d_a_scene_exit.h"
|
||||
#include "d/actor/d_a_tag_mhint.h"
|
||||
#include "d/actor/d_a_tag_mmsg.h"
|
||||
#include "d/actor/d_a_tag_lantern.h"
|
||||
#include "d/actor/d_a_horse.h"
|
||||
#include "m_Do/m_Do_controller_pad.h"
|
||||
#include "d/d_bomb.h"
|
||||
#include "d/d_meter2_info.h"
|
||||
#include "d/actor/d_a_kytag05.h"
|
||||
#include "d/actor/d_a_b_mgn.h"
|
||||
#include "d/actor/d_a_npc_bou.h"
|
||||
#include "d/actor/d_a_npc_kolin.h"
|
||||
#include "f_op/f_op_kankyo_mng.h"
|
||||
#include "d/actor/d_a_tag_mstop.h"
|
||||
#include "d/actor/d_a_tag_mwait.h"
|
||||
#include "d/actor/d_a_tag_wljump.h"
|
||||
#include "d/actor/d_a_tbox.h"
|
||||
#include "d/d_bomb.h"
|
||||
#include "d/d_demo.h"
|
||||
#include "d/d_item.h"
|
||||
#include "d/d_meter2_draw.h"
|
||||
#include "d/d_meter2_info.h"
|
||||
#include "d/d_pane_class.h"
|
||||
#include "d/actor/d_a_canoe.h"
|
||||
#include "d/actor/d_a_ni.h"
|
||||
#include "d/d_s_play.h"
|
||||
#include "dusk/tphd/LosTable.hpp"
|
||||
#include "dusk/tphd/TphdPack.hpp"
|
||||
#include "f_op/f_op_kankyo_mng.h"
|
||||
#include "m_Do/m_Do_controller_pad.h"
|
||||
|
||||
#if TARGET_PC
|
||||
#include "dusk/action_bindings.h"
|
||||
@@ -17454,7 +17452,7 @@ int daAlink_c::procCoMetamorphoseInit() {
|
||||
mProcVar2.field_0x300c = shape_angle.x;
|
||||
|
||||
daMidna_c* midna = (daMidna_c*)getMidnaActor();
|
||||
if (checkMidnaRide() && (daMidna_c::checkMidnaRealBody() IF_DUSK(|| dusk::tphd::is_los_active())) && midna->checkDemoTypeNone())
|
||||
if (checkMidnaRide() && daMidna_c::checkMidnaRealBody() && midna->checkDemoTypeNone())
|
||||
{
|
||||
midna->changeOriginalDemo();
|
||||
midna->changeDemoMode(daPy_demo_c::DEMO_UNK_15_e);
|
||||
|
||||
@@ -738,12 +738,6 @@ void daAlink_c::setDemoData() {
|
||||
} else {
|
||||
mDemo.setStick(1.0f);
|
||||
}
|
||||
|
||||
#if TARGET_PC
|
||||
if (dusk::tphd::is_los_active() && mLosStickValue > 0.0f) {
|
||||
mDemo.setStick(mLosStickValue);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
if ((demo_mode == daPy_demo_c::DEMO_UNK_2_e || demo_mode == daPy_demo_c::DEMO_UNK_3_e) && prm1_p != NULL && *prm1_p == 1) {
|
||||
@@ -2266,6 +2260,12 @@ int daAlink_c::procCoGetItemInit() {
|
||||
s16 var_r22 = 0;
|
||||
BOOL var_r31 = FALSE;
|
||||
BOOL var_r30 = FALSE;
|
||||
#if TARGET_PC
|
||||
// Queued grants have no event partner, so create the demo item from the event's GtItm.
|
||||
if (dusk::mods::item_give_queue_dispatching()) {
|
||||
mDemo.setParam0(0x100);
|
||||
}
|
||||
#endif
|
||||
if (mProcID == PROC_GET_ITEM || mProcID == PROC_INSECT_CATCH ||
|
||||
(mProcID == PROC_PREACTION_UNEQUIP && !checkNoUpperAnime()))
|
||||
{
|
||||
@@ -2305,7 +2305,7 @@ int daAlink_c::procCoGetItemInit() {
|
||||
}
|
||||
|
||||
fpc_ProcID item_partner_id = fopAcM_createItemForPresentDemo(¤t.pos, item_no, 0, -1,
|
||||
fopAcM_GetRoomNo(this), NULL, NULL);
|
||||
fopAcM_GetRoomNo(this), NULL, NULL IF_DUSK_ARG(dusk::mods::item_give_queue_take_tag()));
|
||||
if (item_partner_id != fpcM_ERROR_PROCESS_ID_e) {
|
||||
dComIfGp_event_setItemPartnerId(item_partner_id);
|
||||
}
|
||||
|
||||
@@ -3,7 +3,6 @@
|
||||
#include "d/d_meter2.h"
|
||||
#include "d/d_meter2_draw.h"
|
||||
#include "d/d_meter2_info.h"
|
||||
#include "dusk/tphd/LosTable.hpp"
|
||||
|
||||
void daAlink_c::handleWolfHowl() {
|
||||
if (checkWolf()) {
|
||||
@@ -72,11 +71,6 @@ void daAlink_c::handleQuickTransform() {
|
||||
return;
|
||||
}
|
||||
|
||||
if (dusk::tphd::is_los_active() && !dusk::getSettings().game.canTransformAnywhere) {
|
||||
Z2GetAudioMgr()->seStart(Z2SE_SYS_ERROR, NULL, 0, 0, 1.0f, 1.0f, -1.0f, -1.0f, 0);
|
||||
return;
|
||||
}
|
||||
|
||||
// Check to see if Link has the ability to transform.
|
||||
if (!dComIfGs_isEventBit(dSv_event_flag_c::M_077)) {
|
||||
return;
|
||||
|
||||
@@ -445,8 +445,4 @@ daAlink_c::daAlink_c()
|
||||
mFaceBtkHeap(0x400),
|
||||
mFaceBckHeap(0xC00),
|
||||
mAnmHeap9(0x800)
|
||||
{
|
||||
#if TARGET_PC
|
||||
mLosStickValue = -1.0f;
|
||||
#endif
|
||||
}
|
||||
{}
|
||||
|
||||
@@ -85,17 +85,6 @@ int daAlink_c::loadModelDVD() {
|
||||
}
|
||||
cPhs_Reset(&mPhaseReq);
|
||||
mpArcHeap->freeAll();
|
||||
#if TARGET_PC
|
||||
field_0x06d0 = NULL;
|
||||
field_0x06d4 = NULL;
|
||||
field_0x06d8 = NULL;
|
||||
field_0x06dc = NULL;
|
||||
field_0x06e0 = NULL;
|
||||
field_0x06e4 = NULL;
|
||||
field_0x06e8 = NULL;
|
||||
field_0x06ec = NULL;
|
||||
field_0x06f0 = NULL;
|
||||
#endif
|
||||
|
||||
if (mProcID == PROC_METAMORPHOSE || mProcID == PROC_METAMORPHOSE_ONLY) {
|
||||
setArcName(!checkWolf());
|
||||
|
||||
@@ -4084,6 +4084,10 @@ void daB_DS_c::executeBattle2Dead() {
|
||||
camera->mCamera.SetTrimSize(0);
|
||||
dComIfGp_event_reset();
|
||||
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);
|
||||
#endif
|
||||
/* dSv_event_flag_c::F_0265 - Arbiter's Grounds - Arbiter's Grounds clear */
|
||||
dComIfGs_onEventBit(0x2010);
|
||||
fopAcM_delete(this);
|
||||
|
||||
+2
-62
@@ -13,7 +13,6 @@
|
||||
#include "d/d_bg_parts.h"
|
||||
#include "m_Do/m_Do_lib.h"
|
||||
#include "d/d_demo.h"
|
||||
#include "dusk/tphd/LosTable.hpp"
|
||||
#include "JSystem/JKernel/JKRExpHeap.h"
|
||||
#include "JSystem/JKernel/JKRSolidHeap.h"
|
||||
#include "JSystem/J3DGraphAnimator/J3DMaterialAnm.h"
|
||||
@@ -298,25 +297,6 @@ int daBg_c::draw() {
|
||||
dComIfGd_setListBG();
|
||||
mDoLib_clipper::changeFar(1000000.0f);
|
||||
|
||||
#if TARGET_PC
|
||||
bool losClip = false;
|
||||
Mtx losBgMtx;
|
||||
if (dusk::tphd_active()) {
|
||||
// TPHD Cave of Shadows rooms have a base matrix far from identity; it gets the room translation from 'los.bin'
|
||||
// HD daBg::draw clips the shape bbox in world space, so recompute the room base matrix to transform it.
|
||||
if (strcmp(dComIfGp_getStartStageName(), "D_SB11") == 0) {
|
||||
f32 hx, hy, hz;
|
||||
s16 ha;
|
||||
if (dusk::tphd::los_get_room_trans(roomNo, &hx, &hy, &hz, &ha)) {
|
||||
mDoMtx_stack_c::transS(hx, hy, hz);
|
||||
mDoMtx_stack_c::YrotM(ha);
|
||||
mDoMtx_copy(mDoMtx_stack_c::get(), losBgMtx);
|
||||
losClip = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
J3DModelData* modelData;
|
||||
for (int i = 0; i < 6; i++) {
|
||||
sp8 = 0;
|
||||
@@ -345,22 +325,8 @@ int daBg_c::draw() {
|
||||
for (u16 j = 0; j < modelData->getShapeNum(); j++) {
|
||||
J3DShape* shape = modelData->getShapeNodePointer(j);
|
||||
|
||||
Vec* clipMin = (Vec*)shape->getMin();
|
||||
Vec* clipMax = (Vec*)shape->getMax();
|
||||
#if TARGET_PC
|
||||
if (dusk::tphd_active()) {
|
||||
Vec losClipMin, losClipMax;
|
||||
if (losClip) {
|
||||
// HD transforms the bbox min/max by the room base matrix; clip rebuilds
|
||||
// the 8 corners (exact for the room angles, which are multiples of 90).
|
||||
mDoMtx_multVec(losBgMtx, clipMin, &losClipMin);
|
||||
mDoMtx_multVec(losBgMtx, clipMax, &losClipMax);
|
||||
clipMin = &losClipMin;
|
||||
clipMax = &losClipMax;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
if (mDoLib_clipper::clip(j3dSys.getViewMtx(), clipMin, clipMax)) {
|
||||
if (mDoLib_clipper::clip(j3dSys.getViewMtx(), (Vec*)shape->getMin(),
|
||||
(Vec*)shape->getMax())) {
|
||||
shape->hide();
|
||||
} else {
|
||||
shape->show();
|
||||
@@ -599,43 +565,17 @@ int daBg_c::create() {
|
||||
}
|
||||
|
||||
J3DModelData* modelData;
|
||||
#if TARGET_PC
|
||||
f32 transX = 0.0f;
|
||||
f32 transY = 0.0f;
|
||||
f32 transVert = 0.0f;
|
||||
s16 angle = 0;
|
||||
bool foundMapTrans = false;
|
||||
|
||||
if (dusk::tphd_active()) {
|
||||
// TPHD positions Cave of Shadows rooms via los.bin (per-room world X/Y/Z +
|
||||
// Y-rotation, incl. the vertical Y that GC's MULT lacks). Retail gates
|
||||
// this on g_dComIfG_gameInfo.field_0x1e448; los.bin only carries
|
||||
// D_SB11's room data, so restrict it to that stage and fall back to MULT.
|
||||
if (strcmp(dComIfGp_getStartStageName(), "D_SB11") == 0) {
|
||||
foundMapTrans = dusk::tphd::los_get_room_trans(roomNo, &transX, &transVert, &transY, &angle);
|
||||
}
|
||||
}
|
||||
|
||||
if (!foundMapTrans)
|
||||
foundMapTrans = dComIfGp_getMapTrans(roomNo, &transX, &transY, &angle);
|
||||
if (foundMapTrans) {
|
||||
#else
|
||||
f32 transX;
|
||||
f32 transY;
|
||||
s16 angle;
|
||||
if (dComIfGp_getMapTrans(roomNo, &transX, &transY, &angle)) {
|
||||
#endif
|
||||
daBg_Part* bgPart = mBgParts;
|
||||
J3DModel* model;
|
||||
for (int i = 0; i < 6; i++) {
|
||||
model = bgPart->model;
|
||||
|
||||
if (model != NULL) {
|
||||
#if TARGET_PC
|
||||
mDoMtx_stack_c::transS(transX, transVert, transY);
|
||||
#else
|
||||
mDoMtx_stack_c::transS(transX, 0.0f, transY);
|
||||
#endif
|
||||
mDoMtx_stack_c::YrotM(angle);
|
||||
model->setBaseTRMtx(mDoMtx_stack_c::get());
|
||||
|
||||
|
||||
@@ -144,11 +144,7 @@ bool daBgObj_c::spec_data_c::Set(void* i_ptr) {
|
||||
default:
|
||||
// Invalid data block type
|
||||
OS_REPORT_ERROR("データブロックタイプが不正です<%d>\n", block_type);
|
||||
#if DUSK_TPHD
|
||||
return 0; // HD-port: skip actor instead of asserting.
|
||||
#else
|
||||
JUT_ASSERT(527, FALSE);
|
||||
#endif
|
||||
}
|
||||
|
||||
if (block_type == 0) {
|
||||
@@ -189,11 +185,7 @@ bool daBgObj_c::spec_data_c::Set(void* i_ptr) {
|
||||
default:
|
||||
// Invalid data block type
|
||||
OS_REPORT_ERROR("データブロックタイプが不正です<%d>\n", block_type);
|
||||
#if DUSK_TPHD
|
||||
return 0;
|
||||
#else
|
||||
JUT_ASSERT(570, FALSE);
|
||||
#endif
|
||||
}
|
||||
|
||||
if (block_type == 0) {
|
||||
@@ -234,12 +226,8 @@ bool daBgObj_c::spec_data_c::Set(void* i_ptr) {
|
||||
default:
|
||||
// "Data Block type invalid<%d>\n"
|
||||
OSReport_Error("データブロックタイプが不正です<%d>\n", block_type);
|
||||
#if DUSK_TPHD
|
||||
return 0;
|
||||
#else
|
||||
JUT_ASSERT(619, FALSE);
|
||||
break;
|
||||
#endif
|
||||
}
|
||||
|
||||
if (block_type == 0) {
|
||||
|
||||
@@ -170,7 +170,7 @@ void daDitem_c::actionEvent() {
|
||||
|
||||
if (chkDead()) {
|
||||
if (!chkArgFlag(0x1)) {
|
||||
execItemGet(m_itemNo);
|
||||
execItemGet(m_itemNo IF_DUSK_ARG(mItemGiveTag) IF_DUSK_ARG(this));
|
||||
}
|
||||
|
||||
if (m_itemNo == dItemNo_KAKERA_HEART_e) {
|
||||
|
||||
@@ -403,10 +403,7 @@ void e_ai_class::e_ai_damage() {
|
||||
if (m_timers[1] == 0) {
|
||||
m_sound.startCreatureSound(Z2SE_EN_AI_FLASH, 0, -1);
|
||||
mpEmitter = dComIfGp_particle_set(0x81ED, ¤t.pos, &tevStr, &shape_angle, NULL);
|
||||
if (mpEmitter != NULL) {
|
||||
mpEmitter->becomeImmortalEmitter();
|
||||
}
|
||||
|
||||
mpEmitter->becomeImmortalEmitter();
|
||||
m_timers[1] = 1000;
|
||||
m_timers[2] = 56;
|
||||
}
|
||||
|
||||
@@ -726,11 +726,18 @@ void daE_HP_c::executeDead() {
|
||||
fopAcM_onSwitch(this, bitSw);
|
||||
}
|
||||
|
||||
dComIfGs_addPohSpiritNum();
|
||||
#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
|
||||
#endif
|
||||
dComIfGs_addPohSpiritNum();
|
||||
|
||||
field_0x784 = -1;
|
||||
|
||||
if (dComIfGs_getPohSpiritNum() == 20) {
|
||||
if (dComIfGs_getPohSpiritNum() == 20 IF_DUSK(&&!mItemCheckOverridden)) {
|
||||
dComIfGs_onEventBit(dSv_event_flag_c::saveBitLabels[0x1c9]);
|
||||
}
|
||||
|
||||
@@ -752,13 +759,13 @@ void daE_HP_c::executeDead() {
|
||||
field_0x788 = 1;
|
||||
}
|
||||
}
|
||||
} else if (field_0x788 != 0) {
|
||||
} else if (field_0x788 != 0 IF_DUSK(|| mItemCheckOverridden)) {
|
||||
fopAcM_createDisappear(this, ¤t.pos, 8, 3, 0xff);
|
||||
fopAcM_delete(this);
|
||||
} else {
|
||||
if (field_0x784 == -1) {
|
||||
field_0x784 = fopAcM_createItemForPresentDemo(¤t.pos, dItemNo_POU_SPIRIT_e, 0, -1,
|
||||
-1, 0, 0);
|
||||
field_0x784 = fopAcM_createItemForPresentDemo(¤t.pos, dItemNo_POU_SPIRIT_e, 0,
|
||||
-1, -1, 0, 0 IF_DUSK_ARG(dusk::mods::item_give_tag_poe(bitSw)));
|
||||
}
|
||||
|
||||
if (fopAcM_IsExecuting(field_0x784) != FALSE) {
|
||||
|
||||
@@ -1132,12 +1132,20 @@ static void e_po_dead(e_po_class* i_this) {
|
||||
camera_player->mCamera.Start();
|
||||
camera_player->mCamera.SetTrimSize(0);
|
||||
dComIfGp_event_reset();
|
||||
dComIfGs_addPohSpiritNum();
|
||||
#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 !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) {
|
||||
@@ -1265,8 +1273,15 @@ 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));
|
||||
#else
|
||||
i_this->field_0x75C = fopAcM_createItemForPresentDemo(&a_this->current.pos, 0xE0, 0,
|
||||
-1, -1, NULL, NULL);
|
||||
#endif
|
||||
}
|
||||
if (fopAcM_IsExecuting(i_this->field_0x75C)) {
|
||||
i_this->field_0x762 =
|
||||
|
||||
@@ -1250,7 +1250,9 @@ static void demo_camera(e_rdb_class* i_this) {
|
||||
}
|
||||
|
||||
if (iVar1 != 0) {
|
||||
daPy_getPlayerActorClass()->changeDemoMode(11, 32, 0, 0);
|
||||
daPy_getPlayerActorClass()->changeDemoMode(11,
|
||||
DUSK_ITEM_CHECK_EXPR("bulblin_key:D_MN09", dItemNo_SMALL_KEY_e, &i_this->enemy), 0,
|
||||
0);
|
||||
i_this->mDemoMode = 12;
|
||||
i_this->field_0x10aa = 0;
|
||||
i_this->field_0xfe5 = 1;
|
||||
|
||||
@@ -931,7 +931,9 @@ static void get_demo(e_th_ball_class* i_this) {
|
||||
case 0:
|
||||
break;
|
||||
case 1:
|
||||
demo_id = fopAcM_createItemForTrBoxDemo(&i_this->current.pos, dItemNo_IRONBALL_e, -1, fopAcM_GetRoomNo(i_this), NULL, NULL);
|
||||
demo_id = fopAcM_createItemForTrBoxDemo(&i_this->current.pos,
|
||||
DUSK_ITEM_CHECK_EXPR("ball_and_chain:D_MN11", dItemNo_IRONBALL_e, i_this), -1,
|
||||
fopAcM_GetRoomNo(i_this), NULL, NULL DUSK_GIVE_TAG("ball_and_chain:D_MN11"));
|
||||
JUT_ASSERT(1670, demo_id != fpcM_ERROR_PROCESS_ID_e);
|
||||
i_this->mDemoMode = 2;
|
||||
break;
|
||||
|
||||
@@ -13,9 +13,6 @@
|
||||
#include "Z2AudioLib/Z2Instances.h"
|
||||
#include <cstring>
|
||||
|
||||
#include "dusk/tphd/LosTable.hpp"
|
||||
#include "dusk/tphd/TphdPack.hpp"
|
||||
|
||||
enum E_ww_RES_File_ID {
|
||||
/* BCK */
|
||||
/* 0x04 */ BCK_WW_APPEAR = 0x4,
|
||||
@@ -469,7 +466,7 @@ f32 daE_WW_c::checkCreateBg(cXyz i_vector) {
|
||||
return -G_CM3D_F_INF;
|
||||
}
|
||||
|
||||
if (dComIfG_Bgsp().GetSpecialCode(gnd_chk) == 5 || dComIfG_Bgsp().GetPolyAtt0(gnd_chk) == 0xD IF_DUSK(|| dusk::tphd::is_los_active())) {
|
||||
if (dComIfG_Bgsp().GetSpecialCode(gnd_chk) == 5 || dComIfG_Bgsp().GetPolyAtt0(gnd_chk) == 0xD) {
|
||||
cXyz temp_r1 = daPy_getPlayerActorClass()->current.pos;
|
||||
temp_r1.y += 100.0f;
|
||||
sp14 = i_vector;
|
||||
@@ -669,14 +666,8 @@ void daE_WW_c::executeMaster() {
|
||||
sp30.set(0.0f, 0.0f, 3000.0f);
|
||||
}
|
||||
|
||||
#if TARGET_PC
|
||||
if (dusk::tphd::is_los_active()) {
|
||||
sp30.z = 600.0f;
|
||||
}
|
||||
#endif
|
||||
|
||||
cLib_offsetPos(&sp3C, &sp48, fopCamM_GetAngleY(camera), &sp30);
|
||||
if ((current.pos.abs(sp3C) < field_0x6a8) IF_DUSK(|| (dusk::tphd::is_los_active() && current.pos.y - sp48.y < field_0x6a8))) {
|
||||
if (current.pos.abs(sp3C) < field_0x6a8) {
|
||||
f32 temp_f31 = checkCreateBg(sp3C);
|
||||
if (-G_CM3D_F_INF != temp_f31) {
|
||||
sp3C.y = temp_f31;
|
||||
|
||||
@@ -10,7 +10,6 @@
|
||||
#include "d/actor/d_a_player.h"
|
||||
#include "d/d_com_inf_game.h"
|
||||
#include <cstring>
|
||||
#include <dusk/ui/settings.hpp>
|
||||
|
||||
static int daKytag04_Draw(kytag04_class* i_this) {
|
||||
dScnKy_env_light_c* kankyo = dKy_getEnvlight();
|
||||
@@ -261,25 +260,12 @@ static int daKytag04_Create(fopAc_ac_c* i_this) {
|
||||
|
||||
a_this->mNeedDropNum = i_this->current.angle.z & 0xFF;
|
||||
|
||||
#if TARGET_PC
|
||||
if (dusk::tphd_active()) {
|
||||
a_this->mNeedDropNum = 12;
|
||||
}
|
||||
#endif
|
||||
|
||||
int phase_state = dComIfG_resLoad(&a_this->mPhase, "Kytag04");
|
||||
if (phase_state == cPhs_COMPLEATE_e) {
|
||||
a_this->field_0x5b4 = (fopAcM_GetParam(i_this) >> 8) & 7;
|
||||
a_this->mStageNo = (i_this->current.angle.z >> 8) & 0xFF;
|
||||
a_this->mExitID = fopAcM_GetParam(i_this) & 0xFF;
|
||||
a_this->mNeedDropNum = i_this->current.angle.z & 0xFF;
|
||||
|
||||
#if TARGET_PC
|
||||
if (dusk::tphd_active()) {
|
||||
a_this->mNeedDropNum = 12;
|
||||
}
|
||||
#endif
|
||||
|
||||
a_this->field_0x5b5 = fopAcM_GetParam(i_this) >> 0x10;
|
||||
a_this->field_0x5b6 = fopAcM_GetParam(i_this) >> 0x18;
|
||||
|
||||
|
||||
@@ -64,7 +64,6 @@ static dPath* get_Extent_pos_end_get(kytag10_class* i_this, dPath* i_path, cXyz*
|
||||
}
|
||||
|
||||
static void sparks_move(kytag10_class* i_this) {
|
||||
|
||||
camera_process_class* camera_p = dComIfGp_getCamera(0);
|
||||
|
||||
cXyz ratio_pos_1;
|
||||
|
||||
@@ -5,17 +5,16 @@
|
||||
|
||||
#include "d/dolzel_rel.h" // IWYU pragma: keep
|
||||
|
||||
#include "d/actor/d_a_midna.h"
|
||||
#include "JSystem/J3DGraphLoader/J3DAnmLoader.h"
|
||||
#include "d/d_meter2_info.h"
|
||||
#include "d/actor/d_a_alink.h"
|
||||
#include "d/actor/d_a_kago.h"
|
||||
#include "d/actor/d_a_midna.h"
|
||||
#include "d/d_debug_viewer.h"
|
||||
#include "d/d_demo.h"
|
||||
#include "d/d_meter2_info.h"
|
||||
#include "d/d_msg_object.h"
|
||||
#include "d/d_s_play.h"
|
||||
#include "d/d_debug_viewer.h"
|
||||
#include "dusk/frame_interpolation.h"
|
||||
#include "dusk/tphd/LosTable.hpp"
|
||||
|
||||
static f32 dummy_lit_3777(int idx, u8 foo) {
|
||||
Vec dummy_vec = {0.0f, 0.0f, 0.0f};
|
||||
@@ -3309,14 +3308,7 @@ int daMidna_c::execute() {
|
||||
}
|
||||
}
|
||||
onStateFlg0(FLG0_UNK_8000);
|
||||
#if TARGET_PC
|
||||
if (dusk::tphd::is_los_active() && !dusk::getSettings().game.canTransformAnywhere) {
|
||||
mMsgFlow.init(this, 0x457, 0, NULL);
|
||||
} else
|
||||
#endif
|
||||
{
|
||||
mMsgFlow.init(this, 0xbb9, 0, NULL);
|
||||
}
|
||||
mMsgFlow.init(this, 0xbb9, 0, NULL);
|
||||
} else if (mMsgFlow.doFlow(this, NULL, 0)) {
|
||||
int item_id;
|
||||
u16 event_id = mMsgFlow.getEventId(&item_id);
|
||||
|
||||
@@ -15,8 +15,6 @@
|
||||
#include "m_Do/m_Do_lib.h"
|
||||
#if TARGET_PC
|
||||
#include "dusk/frame_interpolation.h"
|
||||
#include "dusk/settings.h"
|
||||
#include <cstring>
|
||||
#endif
|
||||
|
||||
#ifndef __MWERKS__
|
||||
@@ -52,32 +50,6 @@ void dMirror_packet_c::calcMinMax() {
|
||||
mMinVal.set(FLT_MAX, FLT_MAX, FLT_MAX);
|
||||
mMaxVal.set(-FLT_MAX, -FLT_MAX, -FLT_MAX);
|
||||
|
||||
#if TARGET_PC
|
||||
// HD: per-quad cull box + global bbox over all mQuadCount quads.
|
||||
for (int q = 0; q < mQuadCount; q++) {
|
||||
cXyz& bmin = mQuadBoxMin[q];
|
||||
cXyz& bmax = mQuadBoxMax[q];
|
||||
bmin.set(FLT_MAX, FLT_MAX, FLT_MAX);
|
||||
bmax.set(-FLT_MAX, -FLT_MAX, -FLT_MAX);
|
||||
|
||||
cXyz* quad = &mQuad[q * 4];
|
||||
for (int i = 0; i < 4; i++, quad++) {
|
||||
if (quad->x < bmin.x) bmin.x = quad->x;
|
||||
if (quad->x > bmax.x) bmax.x = quad->x;
|
||||
if (quad->y < bmin.y) bmin.y = quad->y;
|
||||
if (quad->y > bmax.y) bmax.y = quad->y;
|
||||
if (quad->z < bmin.z) bmin.z = quad->z;
|
||||
if (quad->z > bmax.z) bmax.z = quad->z;
|
||||
}
|
||||
|
||||
if (bmin.x < mMinVal.x) mMinVal.x = bmin.x;
|
||||
if (bmax.x > mMaxVal.x) mMaxVal.x = bmax.x;
|
||||
if (bmin.y < mMinVal.y) mMinVal.y = bmin.y;
|
||||
if (bmax.y > mMaxVal.y) mMaxVal.y = bmax.y;
|
||||
if (bmin.z < mMinVal.z) mMinVal.z = bmin.z;
|
||||
if (bmax.z > mMaxVal.z) mMaxVal.z = bmax.z;
|
||||
}
|
||||
#else
|
||||
cXyz* quad = mQuad;
|
||||
for (int i = 0; i < 4; i++, quad++) {
|
||||
f32 val = quad->x;
|
||||
@@ -110,7 +82,6 @@ void dMirror_packet_c::calcMinMax() {
|
||||
mMaxVal.z = val;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
int dMirror_packet_c::entryModel(J3DModel* i_model) {
|
||||
@@ -132,10 +103,6 @@ int dMirror_packet_c::entryModel(J3DModel* i_model) {
|
||||
return 1;
|
||||
}
|
||||
|
||||
#if TARGET_PC
|
||||
static f32 dMirror_quadDist(const cXyz& p, const cXyz& bmin, const cXyz& bmax);
|
||||
#endif
|
||||
|
||||
void dMirror_packet_c::mirrorZdraw(f32* param_0, f32* param_1, f32 param_2, f32 param_3,
|
||||
f32 param_4, f32 param_5, f32 param_6, f32 param_7) {
|
||||
ZoneScoped;
|
||||
@@ -164,82 +131,11 @@ void dMirror_packet_c::mirrorZdraw(f32* param_0, f32* param_1, f32 param_2, f32
|
||||
GXLoadPosMtxImm(j3dSys.getViewMtx(), 0);
|
||||
GXSetCurrentMtx(0);
|
||||
|
||||
#if TARGET_PC
|
||||
// HD FUN_0247d9fc: with count>=2, tint only the same-height quad group nearest the camera
|
||||
u32 groupMask = 1;
|
||||
int groupCount = 1;
|
||||
if (mQuadCount >= 2) {
|
||||
const cXyz& eye = dComIfGd_getView()->lookat.eye;
|
||||
int nearest = 0;
|
||||
f32 best = FLT_MAX;
|
||||
for (int q = 0; q < mQuadCount; q++) {
|
||||
f32 dist = dMirror_quadDist(eye, mQuadBoxMin[q], mQuadBoxMax[q]);
|
||||
if (dist < best) {
|
||||
best = dist;
|
||||
nearest = q;
|
||||
}
|
||||
}
|
||||
groupMask = 0;
|
||||
groupCount = 0;
|
||||
for (int q = 0; q < mQuadCount; q++) {
|
||||
if (fabsf(mQuadBoxMin[q].y - mQuadBoxMin[nearest].y) < 0.0001f) {
|
||||
groupMask |= 1u << q;
|
||||
groupCount++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
GXBegin(GX_QUADS, GX_VTXFMT0, groupCount * 4);
|
||||
for (int q = 0; q < mQuadCount; q++) {
|
||||
if (groupMask & (1u << q)) {
|
||||
for (int i = 0; i < 4; i++) {
|
||||
GXPosition3f32(mQuad[q * 4 + i].x, mQuad[q * 4 + i].y, mQuad[q * 4 + i].z);
|
||||
}
|
||||
}
|
||||
}
|
||||
GXEnd();
|
||||
|
||||
if (mQuadCount >= 2 && GX2SupportsStencil()) {
|
||||
GXSetColorUpdate(GX_DISABLE);
|
||||
GXSetAlphaUpdate(GX_DISABLE);
|
||||
GXSetBlendMode(GX_BM_NONE, GX_BL_SRCALPHA, GX_BL_INVSRCALPHA, GX_LO_CLEAR);
|
||||
GXSetAlphaCompare(GX_ALWAYS, 0, GX_AOP_OR, GX_ALWAYS, 0);
|
||||
GX2SetStencilMask(0xff, 0xff, 0, 0xff, 0xff, 0);
|
||||
GX2SetDepthStencilControl(0, 0, 7, 1, 0, 7, 3, 3, 0, 0, 0, 0, 0);
|
||||
GXBegin(GX_QUADS, GX_VTXFMT0, groupCount * 4);
|
||||
for (int q = 0; q < mQuadCount; q++) {
|
||||
if (groupMask & (1u << q)) {
|
||||
for (int i = 0; i < 4; i++) {
|
||||
GXPosition3f32(mQuad[q * 4 + i].x, mQuad[q * 4 + i].y, mQuad[q * 4 + i].z);
|
||||
}
|
||||
}
|
||||
}
|
||||
GXEnd();
|
||||
|
||||
GX2SetDepthStencilControl(1, 1, 7, 1, 0, 2, 1, 1, 1, 0, 0, 0, 0);
|
||||
Mtx44 proj;
|
||||
C_MTXOrtho(proj, param_1[1], param_1[1] + param_1[3], param_1[0],
|
||||
param_1[0] + param_1[2], 0, 100.0f);
|
||||
GXSetProjection(proj, GX_ORTHOGRAPHIC);
|
||||
GXLoadPosMtxImm(mDoMtx_getIdentity(), 0);
|
||||
GXBegin(GX_QUADS, GX_VTXFMT0, 4);
|
||||
GXPosition3f32(param_1[0], param_1[1], -100.0f);
|
||||
GXPosition3f32(param_1[0] + param_1[2], param_1[1], -100.0f);
|
||||
GXPosition3f32(param_1[0] + param_1[2], param_1[1] + param_1[3], -100.0f);
|
||||
GXPosition3f32(param_1[0], param_1[1] + param_1[3], -100.0f);
|
||||
GXEnd();
|
||||
GXSetProjectionv(param_0);
|
||||
GXSetColorUpdate(GX_ENABLE);
|
||||
GXSetAlphaUpdate(GX_DISABLE); // no stencil-off: the next material's zmode write disables it
|
||||
return;
|
||||
}
|
||||
#else
|
||||
GXBegin(GX_QUADS, GX_VTXFMT0, 4);
|
||||
for (int i = 0; i < 4; i++) {
|
||||
GXPosition3f32(mQuad[i].x, mQuad[i].y, mQuad[i].z);
|
||||
}
|
||||
GXEnd();
|
||||
#endif
|
||||
|
||||
if (mViewScale.y > 0.0f) {
|
||||
GXSetZMode(GX_ENABLE, GX_ALWAYS, GX_ENABLE);
|
||||
@@ -369,223 +265,10 @@ void dMirror_packet_c::modelDraw(J3DModel* i_model, Mtx param_1) {
|
||||
}
|
||||
}
|
||||
|
||||
#if TARGET_PC
|
||||
// FUN_0247c89c: HD multi-quad floor reflection helpers (F_SP117 room 2):
|
||||
static f32 dMirror_quadDist(const cXyz& p, const cXyz& bmin, const cXyz& bmax) {
|
||||
f32 ox = bmin.x - p.x;
|
||||
if (ox < 0.0f) ox = 0.0f;
|
||||
f32 oz = bmin.z - p.z;
|
||||
if (oz < 0.0f) oz = 0.0f;
|
||||
f32 px = p.x - bmax.x;
|
||||
if (px < 0.0f) px = 0.0f;
|
||||
f32 pz = p.z - bmax.z;
|
||||
if (pz < 0.0f) pz = 0.0f;
|
||||
return fabsf(p.y - bmin.y) + ox + oz + px + pz;
|
||||
}
|
||||
|
||||
static void dMirror_accumQuadBBox(view_class* view, view_port_class* view_port, const u32 scissor[4],
|
||||
cXyz* quad, f32& minX, f32& maxX, f32& minY, f32& maxY, f32& maxZ) {
|
||||
cXyz sp19C[5];
|
||||
int prjPosNum = 4;
|
||||
f32 nearZ = -view->near_;
|
||||
|
||||
int behind = 0;
|
||||
int lastFront = 0;
|
||||
for (int i = 0; i < 4; i++) {
|
||||
cMtx_multVec(view->viewMtx, &quad[i], &sp19C[i]);
|
||||
if (sp19C[i].z >= nearZ) {
|
||||
behind++;
|
||||
} else {
|
||||
lastFront = i;
|
||||
}
|
||||
}
|
||||
if (behind >= 4) {
|
||||
return;
|
||||
}
|
||||
|
||||
int var_r28 = lastFront;
|
||||
if (behind != 0) {
|
||||
int var_r27 = -1;
|
||||
for (int i = 0; i < 4; i++) {
|
||||
int temp_r5 = (var_r28 + 1) % 4;
|
||||
if (var_r27 < 0) {
|
||||
if (sp19C[temp_r5].z >= nearZ) {
|
||||
var_r27 = temp_r5;
|
||||
}
|
||||
} else if (sp19C[temp_r5].z < nearZ) {
|
||||
int temp_r29 = (var_r27 + 3) % 4;
|
||||
cXyz d0 = sp19C[var_r27] - sp19C[temp_r29];
|
||||
d0 *= (nearZ - sp19C[temp_r29].z) / d0.z;
|
||||
sp19C[4] = sp19C[temp_r29] + d0;
|
||||
prjPosNum++;
|
||||
|
||||
cXyz d1 = sp19C[var_r28] - sp19C[temp_r5];
|
||||
d1 *= (nearZ - sp19C[temp_r5].z) / d1.z;
|
||||
sp19C[var_r28] = sp19C[temp_r5] + d1;
|
||||
|
||||
for (int j = var_r27; j != var_r28; j = (j + 1) % 4) {
|
||||
sp19C[j] = sp19C[var_r28];
|
||||
}
|
||||
break;
|
||||
}
|
||||
var_r28 = temp_r5;
|
||||
}
|
||||
}
|
||||
|
||||
f32 aspect = view->aspect;
|
||||
f32 tanHalf = tanf(MTXDegToRad(view->fovy * 0.5f));
|
||||
f32 vx, vy, vw, vh;
|
||||
if (view_port->x_orig != 0.0f) {
|
||||
vx = (((view_port->x_orig * 2.0f) + view_port->width) * 0.5f) - (FB_WIDTH / 2);
|
||||
vw = FB_WIDTH;
|
||||
} else {
|
||||
vx = view_port->x_orig;
|
||||
vw = view_port->width;
|
||||
}
|
||||
if (view_port->y_orig != 0.0f) {
|
||||
vy = (((view_port->y_orig * 2.0f) + view_port->height) * 0.5f) - (FB_HEIGHT / 2);
|
||||
vh = FB_HEIGHT;
|
||||
} else {
|
||||
vy = view_port->y_orig;
|
||||
vh = view_port->height;
|
||||
}
|
||||
|
||||
f32 sxMin = scissor[0];
|
||||
f32 sxMax = sxMin + scissor[2];
|
||||
f32 syMin = scissor[1];
|
||||
f32 syMax = syMin + scissor[3];
|
||||
|
||||
Vec* p = sp19C;
|
||||
for (int i = 0; i < prjPosNum; i++, p++) {
|
||||
p->y = p->y / (p->z * tanHalf);
|
||||
p->x = p->x / (aspect * (-p->z * tanHalf));
|
||||
p->x = vx + ((1.0f + p->x) * (vw * 0.5f));
|
||||
p->y = vy + ((1.0f + p->y) * (vh * 0.5f));
|
||||
p->x = cLib_minMaxLimit<f32>(p->x, sxMin, sxMax);
|
||||
p->y = cLib_minMaxLimit<f32>(p->y, syMin, syMax);
|
||||
if (p->x < minX) minX = p->x;
|
||||
if (p->x > maxX) maxX = p->x;
|
||||
if (p->y < minY) minY = p->y;
|
||||
if (p->y > maxY) maxY = p->y;
|
||||
if (p->z > maxZ) maxZ = p->z;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
void dMirror_packet_c::mainDraw() {
|
||||
ZoneScoped;
|
||||
j3dSys.reinitGX();
|
||||
|
||||
#if TARGET_PC
|
||||
f32 sp150[7];
|
||||
GXGetProjectionv(sp150);
|
||||
|
||||
f32 sp138[6];
|
||||
GXGetViewportv(sp138);
|
||||
|
||||
u32 scissor[4];
|
||||
GXGetScissor(&scissor[0], &scissor[1], &scissor[2], &scissor[3]);
|
||||
|
||||
view_class* view = dComIfGd_getView();
|
||||
view_port_class* view_port = dComIfGd_getViewport();
|
||||
|
||||
// HD mainDraw (FUN_0247e6e8):
|
||||
f32 minX = FLT_MAX, minY = FLT_MAX;
|
||||
f32 maxX = -FLT_MAX, maxY = -FLT_MAX, maxZ = -FLT_MAX;
|
||||
for (int q = 0; q < mQuadCount; q++) {
|
||||
dMirror_accumQuadBBox(view, view_port, scissor, &mQuad[q * 4], minX, maxX, minY, maxY, maxZ);
|
||||
}
|
||||
|
||||
if (maxX <= minX || maxY <= minY) {
|
||||
return;
|
||||
}
|
||||
if (fabsf(maxX - minX) < 8.0f || fabsf(maxY - minY) < 8.0f) {
|
||||
return;
|
||||
}
|
||||
|
||||
GXSetScissor((u32)minX, (u32)minY, (u32)(maxX - minX), (u32)(maxY - minY));
|
||||
|
||||
Mtx reflMtx[MAX_QUADS];
|
||||
for (int q = 0; q < mQuadCount; q++) {
|
||||
cXyz* quad = &mQuad[q * 4];
|
||||
cXyz e0 = quad[1] - quad[0];
|
||||
cXyz e1 = quad[2] - quad[1];
|
||||
cXyz n = e0.outprod(e1);
|
||||
n.normalizeZP();
|
||||
|
||||
f32 planeD = (n.x * quad[0].x) + (n.y * quad[0].y) + (n.z * quad[0].z);
|
||||
f32 dCenter = ((n.x * view->lookat.center.x) + (n.y * view->lookat.center.y) +
|
||||
(n.z * view->lookat.center.z)) -
|
||||
planeD;
|
||||
cXyz reflEye =
|
||||
view->lookat.eye -
|
||||
(n * (2.0f * (((n.x * view->lookat.eye.x) + (n.y * view->lookat.eye.y) +
|
||||
(n.z * view->lookat.eye.z)) -
|
||||
planeD)));
|
||||
cXyz reflCenter = view->lookat.center - (n * (2.0f * dCenter));
|
||||
|
||||
cXyz up(0.0f, 1.0f, 0.0f);
|
||||
if (mViewScale.y > 0.0f) {
|
||||
cXyz a = reflEye - view->lookat.eye;
|
||||
cXyz b = a.outprod(view->lookat.up);
|
||||
up = a.outprod(b);
|
||||
up.normalizeZP();
|
||||
up *= cXyz(-1.0f, -1.0f, -1.0f);
|
||||
}
|
||||
|
||||
Mtx look;
|
||||
mDoMtx_lookAt(look, &reflEye, &reflCenter, &up, view->bank);
|
||||
mDoMtx_stack_c::scaleS(mViewScale);
|
||||
mDoMtx_stack_c::concat(look);
|
||||
|
||||
f32 (*cur)[4] = mDoMtx_stack_c::get();
|
||||
for (int r = 0; r < 3; r++) {
|
||||
for (int c = 0; c < 4; c++) {
|
||||
reflMtx[q][r][c] = cur[r][c];
|
||||
}
|
||||
}
|
||||
}
|
||||
J3DShape::resetVcdVatCache();
|
||||
|
||||
bool wallQuad = !dusk::tphd_active() ||
|
||||
(mQuadCount <= 1 && mQuadBoxMax[0].y - mQuadBoxMin[0].y > 0.1f);
|
||||
for (int i = 0; i < mModelCount; i++) {
|
||||
Mtx& bm = mModels[i]->getBaseTRMtx();
|
||||
cXyz pos(bm[0][3], bm[1][3], bm[2][3]);
|
||||
int best = 0;
|
||||
if (!wallQuad) {
|
||||
const cXyz& eye = view->lookat.eye;
|
||||
best = -1;
|
||||
f32 bestDist = FLT_MAX;
|
||||
for (int q = 0; q < mQuadCount; q++) {
|
||||
if ((mQuadBoxMin[q].x <= pos.x || mQuadBoxMin[q].x <= eye.x) &&
|
||||
(mQuadBoxMin[q].z <= pos.z || mQuadBoxMin[q].z <= eye.z) &&
|
||||
(pos.x <= mQuadBoxMax[q].x || eye.x <= mQuadBoxMax[q].x) &&
|
||||
(pos.z <= mQuadBoxMax[q].z || eye.z <= mQuadBoxMax[q].z))
|
||||
{
|
||||
f32 dist = dMirror_quadDist(pos, mQuadBoxMin[q], mQuadBoxMax[q]);
|
||||
if (dist < bestDist) {
|
||||
bestDist = dist;
|
||||
best = q;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (best < 0) {
|
||||
continue;
|
||||
}
|
||||
}
|
||||
modelDraw(mModels[i], reflMtx[best]);
|
||||
}
|
||||
|
||||
j3dSys.reinitGX();
|
||||
if (dusk::tphd_active()) {
|
||||
mirrorZdraw(sp150, sp138, view->far_, minX, minY, maxX, maxY, maxZ);
|
||||
GXSetScissor(scissor[0], scissor[1], scissor[2], scissor[3]);
|
||||
} else {
|
||||
GXSetScissor(scissor[0], scissor[1], scissor[2], scissor[3]);
|
||||
mirrorZdraw(sp150, sp138, view->far_, minX, minY, maxX, maxY, maxZ);
|
||||
}
|
||||
#else
|
||||
cXyz sp19C[5];
|
||||
|
||||
Mtx sp16C;
|
||||
@@ -773,7 +456,6 @@ void dMirror_packet_c::mainDraw() {
|
||||
GXSetScissor(scissor[0], scissor[1], scissor[2], scissor[3]);
|
||||
mirrorZdraw(sp150, sp138, view->far_, var_f31, var_f30, var_f29, var_f28, var_f27);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
void dMirror_packet_c::draw() {
|
||||
@@ -854,36 +536,6 @@ int daMirror_c::create() {
|
||||
mPacket.getViewScale().set(-1.0f, 1.0f, 1.0f);
|
||||
} else {
|
||||
if (type == 1) {
|
||||
#if TARGET_PC
|
||||
if (dusk::tphd_active() && strcmp(dComIfGp_getStartStageName(), "F_SP117") == 0 &&
|
||||
dComIfGp_getStartStageRoomNo() == 2)
|
||||
{
|
||||
// HD const DAT_1002f070 (world-space floor rects)
|
||||
static const struct {
|
||||
f32 xMin, xMax, y, zMin, zMax;
|
||||
} l_tot_quads[dMirror_packet_c::MAX_QUADS] = {
|
||||
{-1800.0f, 1800.0f, 999.0f, 747.0f, 5600.0f},
|
||||
{-670.0f, 670.0f, 999.0f, 5600.0f, 6400.0f},
|
||||
{-3530.0f, 3530.0f, 1526.0f, -8151.0f, -2014.0f},
|
||||
{-3530.0f, -1040.0f, 1526.0f, -2014.0f, -1089.0f},
|
||||
{1040.0f, 3530.0f, 1526.0f, -2014.0f, -1089.0f},
|
||||
{-700.0f, 700.0f, 2887.0f, -10700.0f, -8300.0f},
|
||||
};
|
||||
cXyz* q = mPacket.getQuad();
|
||||
for (int i = 0; i < dMirror_packet_c::MAX_QUADS; i++) {
|
||||
q[i * 4 + 0].set(l_tot_quads[i].xMin, l_tot_quads[i].y, l_tot_quads[i].zMin);
|
||||
q[i * 4 + 1].set(l_tot_quads[i].xMax, l_tot_quads[i].y, l_tot_quads[i].zMin);
|
||||
q[i * 4 + 2].set(l_tot_quads[i].xMax, l_tot_quads[i].y, l_tot_quads[i].zMax);
|
||||
q[i * 4 + 3].set(l_tot_quads[i].xMin, l_tot_quads[i].y, l_tot_quads[i].zMax);
|
||||
}
|
||||
mPacket.mQuadCount = dMirror_packet_c::MAX_QUADS;
|
||||
mPacket.getViewScale().set(1.0f, -1.0f, 1.0f);
|
||||
m_myObj = this;
|
||||
mPacket.calcMinMax();
|
||||
eyePos.set(current.pos.x, current.pos.y, current.pos.z);
|
||||
return cPhs_COMPLEATE_e;
|
||||
}
|
||||
#endif
|
||||
scale *= 10.0f;
|
||||
mPacket.getViewScale().set(1.0, -1.0, 1.0);
|
||||
} else {
|
||||
|
||||
@@ -1744,7 +1744,9 @@ int daNpc_Aru_c::cutSpeakTo(int i_staffID) {
|
||||
switch (eventId) {
|
||||
case 1:
|
||||
if (mItemPartnerId == fpcM_ERROR_PROCESS_ID_e) {
|
||||
mItemPartnerId = fopAcM_createItemForPresentDemo(¤t.pos, itemNo, 0, -1, -1, NULL, NULL);
|
||||
DUSK_ITEM_CHECK("goats_reward", itemNo, this);
|
||||
mItemPartnerId = fopAcM_createItemForPresentDemo(¤t.pos, itemNo,
|
||||
0, -1, -1, NULL, NULL DUSK_GIVE_TAG("goats_reward"));
|
||||
}
|
||||
|
||||
if (fopAcM_IsExecuting(mItemPartnerId)) {
|
||||
|
||||
@@ -1001,8 +1001,9 @@ BOOL daNpcAshB_c::EvCut_Appear(int i_staffID) {
|
||||
case '0008':
|
||||
local_30[0] = 0;
|
||||
if (mFlow.getEventId(local_30) == 1) {
|
||||
mItemPartnerId =
|
||||
fopAcM_createItemForPresentDemo(¤t.pos, local_30[0], 0, -1, -1, 0, 0);
|
||||
DUSK_ITEM_CHECK("ashei_sketch", local_30[0], this);
|
||||
mItemPartnerId = fopAcM_createItemForPresentDemo(
|
||||
¤t.pos, local_30[0], 0, -1, -1, 0, 0 DUSK_GIVE_TAG("ashei_sketch"));
|
||||
dComIfGp_event_setItemPartnerId(mItemPartnerId);
|
||||
mItemPartnerId = -1;
|
||||
}
|
||||
|
||||
@@ -1804,8 +1804,19 @@ int daNpcChin_c::_Evt_GameSucceed_CutMain(const int& param_0) {
|
||||
itemId1 = 0;
|
||||
}
|
||||
|
||||
#if TARGET_PC
|
||||
const char* itemCheckName = nullptr;
|
||||
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);
|
||||
}
|
||||
#endif
|
||||
fpc_ProcID itemId2 = fopAcM_createItemForPresentDemo(¤t.pos, itemId1, 0, -1, -1,
|
||||
0, 0);
|
||||
0, 0 IF_DUSK_ARG(dusk::mods::item_give_tag(itemCheckName)));
|
||||
if (itemId2 != -1) {
|
||||
dComIfGp_event_setItemPartnerId(itemId2);
|
||||
}
|
||||
|
||||
@@ -1333,7 +1333,9 @@ void daNpc_Fairy_c::PresentDemoCall() {
|
||||
item_no = 0;
|
||||
}
|
||||
|
||||
fpc_ProcID id = fopAcM_createItemForPresentDemo(¤t.pos, item_no, 0, -1, -1, NULL, NULL);
|
||||
DUSK_ITEM_CHECK("fairy_reward:D_SB01", item_no, this);
|
||||
fpc_ProcID id = fopAcM_createItemForPresentDemo(¤t.pos, item_no, 0, -1, -1, NULL,
|
||||
NULL DUSK_GIVE_TAG("fairy_reward:D_SB01"));
|
||||
if (id != fpcM_ERROR_PROCESS_ID_e) {
|
||||
dComIfGp_event_setItemPartnerId(id);
|
||||
}
|
||||
|
||||
@@ -10,11 +10,8 @@
|
||||
#include <cstring>
|
||||
|
||||
|
||||
static DUSK_CONSTEXPR daNpcT_evtData_c l_evtList[DUSK_IF_ELSE(2, 1)] = {
|
||||
static DUSK_CONSTEXPR daNpcT_evtData_c l_evtList[1] = {
|
||||
{"", 0},
|
||||
#if TARGET_PC
|
||||
{"DEFAULT_GETITEM", 0},
|
||||
#endif
|
||||
};
|
||||
|
||||
static DUSK_CONST char* l_resNameList[2] = {
|
||||
@@ -148,7 +145,7 @@ int daNpc_FairySeirei_c::Draw() {
|
||||
|
||||
int daNpc_FairySeirei_c::isDelete() {
|
||||
int ret = 0;
|
||||
if (IF_DUSK(mType != 4 &&) daNpcT_chkEvtBit(0x1F9) == false) {
|
||||
if (daNpcT_chkEvtBit(0x1F9) == false) {
|
||||
ret = 1;
|
||||
}
|
||||
return ret;
|
||||
@@ -362,15 +359,6 @@ int daNpc_FairySeirei_c::talk(int param_0) {
|
||||
}
|
||||
if (fopAcM_IsExecuting(mItemPartnerId)) {
|
||||
mTalking = TRUE;
|
||||
|
||||
#if TARGET_PC
|
||||
if (dusk::tphd_active() && getType() == 4) {
|
||||
mEvtNo = 1;
|
||||
field_0xe33 = true;
|
||||
mSpeakEvent = true;
|
||||
}
|
||||
#endif
|
||||
|
||||
evtChange();
|
||||
}
|
||||
} else {
|
||||
|
||||
@@ -4018,8 +4018,15 @@ BOOL daNpc_grA_c::talk(void*) {
|
||||
}
|
||||
if (r26 && talkProc(NULL, TRUE, NULL)) {
|
||||
if (mFlow.getEventId(&sp8) == 1) {
|
||||
field_0x1480 =
|
||||
fopAcM_createItemForPresentDemo(¤t.pos, sp8, 0, -1, -1, NULL, NULL);
|
||||
#if TARGET_PC
|
||||
const char* itemCheckName = nullptr;
|
||||
if (sp8 == dItemNo_BOMB_IN_BAG_e) {
|
||||
itemCheckName = "goron_reward:F_SP113";
|
||||
sp8 = dusk::mods::item_check(itemCheckName, sp8, this);
|
||||
}
|
||||
#endif
|
||||
field_0x1480 = fopAcM_createItemForPresentDemo(¤t.pos, sp8, 0, -1, -1, NULL,
|
||||
NULL IF_DUSK_ARG(dusk::mods::item_give_tag(itemCheckName)));
|
||||
if (field_0x1480 != fpcM_ERROR_PROCESS_ID_e) {
|
||||
s16 r25 = dComIfGp_getEventManager().getEventIdx(this, "DEFAULT_GETITEM", 0xff);
|
||||
dComIfGp_getEvent()->reset(this);
|
||||
|
||||
@@ -1681,7 +1681,9 @@ int daNpc_grO_c::talk(void* param_1) {
|
||||
if (facePlayerFlag && talkProc(NULL, TRUE, NULL)) {
|
||||
if (mType == TYPE_MINES) {
|
||||
if (mFlow.getEventId(&itemId) == 1) {
|
||||
mItemID = fopAcM_createItemForPresentDemo(¤t.pos, itemId, 0, -1, -1, NULL, NULL);
|
||||
DUSK_ITEM_CHECK("key_shard_2:D_MN04", itemId, this);
|
||||
mItemID = fopAcM_createItemForPresentDemo(¤t.pos, itemId, 0, -1, -1,
|
||||
NULL, NULL DUSK_GIVE_TAG("key_shard_2:D_MN04"));
|
||||
if (mItemID != fpcM_ERROR_PROCESS_ID_e) {
|
||||
s16 eventIdx = dComIfGp_getEventManager().getEventIdx(this, "DEFAULT_GETITEM", 0xFF);
|
||||
dComIfGp_getEvent()->reset(this);
|
||||
|
||||
@@ -1338,7 +1338,9 @@ int daNpc_grR_c::talk(void* param_1) {
|
||||
if (bVar1 && talkProc(NULL, TRUE, NULL)) {
|
||||
if (mType == TYPE_0) {
|
||||
if (mFlow.getEventId(&i_itemNo) == 1) {
|
||||
mItemID = fopAcM_createItemForPresentDemo(¤t.pos, i_itemNo, 0, -1, -1, NULL, NULL);
|
||||
DUSK_ITEM_CHECK("key_shard_3:D_MN04", i_itemNo, this);
|
||||
mItemID = fopAcM_createItemForPresentDemo(¤t.pos, i_itemNo, 0, -1, -1,
|
||||
NULL, NULL DUSK_GIVE_TAG("key_shard_3:D_MN04"));
|
||||
|
||||
if (mItemID != fpcM_ERROR_PROCESS_ID_e) {
|
||||
s16 i_eventID = dComIfGp_getEventManager().getEventIdx(this, "DEFAULT_GETITEM", 0xFF);
|
||||
|
||||
@@ -1190,8 +1190,9 @@ int daNpc_grS_c::talk(void* param_0) {
|
||||
if (unkFlag1 && talkProc(NULL, 1, NULL)) {
|
||||
if (mType == 0) {
|
||||
if (mFlow.getEventId(&unkInt2) == 1) {
|
||||
mPresentItemId =
|
||||
fopAcM_createItemForPresentDemo(¤t.pos, unkInt2, 0, -1, -1, 0, 0);
|
||||
DUSK_ITEM_CHECK("key_shard_1:D_MN04", unkInt2, this);
|
||||
mPresentItemId = fopAcM_createItemForPresentDemo(¤t.pos, unkInt2, 0, -1,
|
||||
-1, 0, 0 DUSK_GIVE_TAG("key_shard_1:D_MN04"));
|
||||
|
||||
if (mPresentItemId != fpcM_ERROR_PROCESS_ID_e) {
|
||||
s16 eventIdx =
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user