From 64cc277d055439456e926e294fc131d91685b6ff Mon Sep 17 00:00:00 2001 From: Mike Lester Date: Thu, 31 Oct 2024 14:58:37 -0600 Subject: [PATCH] d_wood (bushes) matching (#682) * d_wood (bushes) 73% matching * d_wood::Unit_c::set_ground 100% match Jasper pointed me to the fact that the complicated inv_sqrt function I wrote was indeed just std::sqrtf(), which unlocked the rest of the match * Replace some bitshifts with multiplies based on PR feedback * Remove all instances of "this->" from d_wood * Add missing struct offset comment for mTevStr * Cleaned up d_tree externs * Use MTXIdentity instead of PSMTXIdentity * Remove incorrect TODO rearding cCcD_ObjAtType enum * Use the mDoAud_seStart inline function * Remove unnecessary parenthesis * Fix incorrect branching logic in d_wood::cc_hit_before_cut() * d_wood data sections fixup * Re-add "Nonmatching" comments to all nonmatching functions * Formatting: reformat from 2 to 4 space indentation This was a local system problem which slipped by me in a previous commit * 100% match for d_wood::Anm_c::mode_norm() Thanks Chippy! https://discord.com/channels/727908905392275526/873250400483024976/1298360716964790294 * Use cLib_*Bit() functions for flag checking and setting Based on the inline functions from the .map * d_wood: Use AnmID_e according to the .map file * d_wood: add a couple AnmID_e related inlines from the .map * d_wood: Name remaining unknowns related to animation * d_wood: Match cc_hit_before_cut() * d_wood: Match calc_cc() by using the dComIfGp_roomControl_getStayNo() inline * d_wood: Match string table and search_anm() by using a constant in assert string * d_wood: Match mode_to_norm() Switching normAnim to a const* did most of the work * d_wood: 100% match for L_attr and the .rodata section * d_wood: Fill in .data section. Still some extra data from vtables * d_wood: Match .sbss section * d_wood: Match .sdata section * d_wood: 98% match for Packet_c::draw() The only error is that g_dTree_shadowTexCoord is still using a 32-bit load instead of 16. the only way I know of to fix that is to define the data in this compilation unit. But that can't be right * d_wood: Various small formatting changes - No one line function implementations - Replaced instances of (SomeType*)0x0 (copy/pasted from Ghidra) with NULL - Replaced a few instances of 0.0 with 0.0f - Replaced one instance where a number was used instead of an enum value * d_wood: More formatting fixes - Removed unused variables from functions - Removed unnecessary iVar1 loop variables (leftover Ghidra detritus) - Fixed dtk function comments being wrapped by autoformatter. They now always appear on one line * d_tree: 100% match of data which is used by d_wood This moves g_dTree_shadowTexCoord into .sdata which allows d_wood::Packet_c::draw() to load its address with a single instruction. This makes a 100% match for draw() * d_wood: Removed unnecessary comment now that draw() matches g_dTree_shadowTexCoord now lives in the d_tree .sdata section, so its instruction can be loaded with a single instruction. This makes a 100% match with draw(). * d_wood: 100% match for mode_cut() * d_wood: Match mode_push_into() Also renamed mWindDir to mForceDir as it represents both wind and an actor pushing from a vector * d_wood: Match mode_push_back * d_wood: Match __sinit_d_wood_cpp The l_matDL display list is dynamically patched to reference the l_Txa_swood_bTEX texture at static initialization time. Is there a better way to represent this? * d_wood: Fix incorrect constant in set_ground() * d_wood: Simplify dummy data at the top of .data section * d_wood: Mark as matching in configure.py Had to move Packet_c destructor to get the functions in the right order. See discussion: https://discord.com/channels/727908905392275526/873250400483024976/1300680009458913280 * d_wood: Add `d/d_cc_d.h` include as some enums have moved * d_wood: Clean up some types at the top * Mark d_wood as non-matching for the Japanese version --- configure.py | 2 +- include/d/d_cc_mass_s.h | 4 +- include/d/d_com_inf_game.h | 4 + include/d/d_particle_name.h | 1 + include/d/d_tree.h | 7 + include/d/d_wood.h | 107 +++- src/d/d_tree.cpp | 8 + src/d/d_wood.cpp | 959 +++++++++++++++++++++++++++++++++--- 8 files changed, 993 insertions(+), 99 deletions(-) diff --git a/configure.py b/configure.py index 849ef94c0..45f7605b7 100644 --- a/configure.py +++ b/configure.py @@ -496,7 +496,7 @@ def MatchingFor(*versions): Object(NonMatching, "d/d_cam_style.cpp"), Object(NonMatching, "d/d_cam_type2.cpp"), Object(NonMatching, "d/d_ev_camera.cpp"), - Object(NonMatching, "d/d_wood.cpp"), + Object(MatchingFor("GZLE01", "GZLP01"), "d/d_wood.cpp", extra_cflags=["-sym off"]), Object(NonMatching, "d/d_flower.cpp"), Object(Matching, "d/d_item_data.cpp"), Object(Matching, "d/d_seafightgame.cpp"), diff --git a/include/d/d_cc_mass_s.h b/include/d/d_cc_mass_s.h index 98e8670f3..c0209c365 100644 --- a/include/d/d_cc_mass_s.h +++ b/include/d/d_cc_mass_s.h @@ -52,6 +52,8 @@ class dCcMassS_HitInf { void SetAtHitObj(cCcD_Obj* obj) { mpAtObj = obj; } void SetCoHitLen(f32 len) { mCoHitLen = len; } cCcD_Obj* GetAtHitObj() const { return mpAtObj; } + cCcD_Obj* GetCoHitObj() const { return mpCoObj; } + f32 GetCoHitLen() const { return mCoHitLen; } void ClearPointer() { mpArea = NULL; @@ -59,8 +61,6 @@ class dCcMassS_HitInf { mpCoObj = NULL; mCoHitLen = 0.0f; } - void GetCoHitLen() const {} - void GetCoHitObj() const {} }; class dCcMassS_Mng { diff --git a/include/d/d_com_inf_game.h b/include/d/d_com_inf_game.h index 3d395df6e..332bb6a40 100644 --- a/include/d/d_com_inf_game.h +++ b/include/d/d_com_inf_game.h @@ -3012,6 +3012,10 @@ inline void dComIfGd_setList() { g_dComIfG_gameInfo.drawlist.setXluList(); } +inline void dComIfGd_setXluList() { + g_dComIfG_gameInfo.drawlist.setXluList(); +} + inline void dComIfGd_setListInvisisble() { g_dComIfG_gameInfo.drawlist.setOpaListInvisible(); g_dComIfG_gameInfo.drawlist.setXluListInvisible(); diff --git a/include/d/d_particle_name.h b/include/d/d_particle_name.h index 0091f7c7b..9e239b77a 100644 --- a/include/d/d_particle_name.h +++ b/include/d/d_particle_name.h @@ -16,6 +16,7 @@ namespace dPa_name { ID_COMMON_LIGHT_EXPLOSION = 0x272, ID_COMMON_STARS_SPIN = 0x27A, ID_COMMON_STARS_BLOW = 0x27B, + ID_CUT_L_TREE_DOWN = 0x3E0, ID_PEDESTAL_OCTAGON_GLOW = 0x826D, ID_WARPFOUT_WARP4 = 0x830e, }; diff --git a/include/d/d_tree.h b/include/d/d_tree.h index 42469687a..285e69714 100644 --- a/include/d/d_tree.h +++ b/include/d/d_tree.h @@ -9,6 +9,13 @@ class cCcD_Obj; class dCcMassS_HitInf; class fopAc_ac_c; +extern const u32 g_dTree_shadowMatDL_SIZE; +extern const u32 g_dTree_Oba_kage_32DL_SIZE; +extern u8 g_dTree_shadowMatDL[]; +extern u8 g_dTree_Oba_kage_32DL[]; +extern u8 g_dTree_shadowPos[12]; +extern u8 g_dTree_shadowTexCoord[8]; + class dTree_data_c { public: ~dTree_data_c(); diff --git a/include/d/d_wood.h b/include/d/d_wood.h index cf20017e2..b859a7aff 100644 --- a/include/d/d_wood.h +++ b/include/d/d_wood.h @@ -2,23 +2,44 @@ #define D_WOOD_H #include "JSystem/J3DGraphBase/J3DPacket.h" +#include "JSystem/J3DGraphBase/J3DStruct.h" #include "SSystem/SComponent/c_xyz.h" #include "dolphin/mtx/mtx.h" +#include "d/d_kankyo.h" class dCcMassS_HitInf; class cCcD_Obj; class fopAc_ac_c; namespace dWood { -enum AnmID_e {}; + +enum AnmID_e { + AnmID_Norm0, + AnmID_Norm1, + AnmID_Norm2, + AnmID_Norm3, + AnmID_Norm4, + AnmID_Norm5, + AnmID_Norm6, + AnmID_Norm7, + + AnmID_Norm_Max = 8, + AnmID_Norm_Invalid = -1 +}; + class Anm_c; class Packet_c; class Unit_c { public: Unit_c(); - ~Unit_c(); - void set_ground(); + enum State_e { + STATE_ACTIVE = 1 << 0, + STATE_FRUSTUM_CULLED = 1 << 1, + STATE_CUT = 1 << 2, + }; + + bool set_ground(); void set_mtx(Anm_c*); void clear(); void cc_hit_before_cut(Packet_c*); @@ -26,26 +47,44 @@ class Unit_c { void proc(Packet_c*); /* 0x000 */ cXyz mPos; - /* 0x00C */ u8 field_0x00C[0x010 - 0x00C]; - /* 0x010 */ u32 mFlags; - /* 0x014 */ int mAnmIdx; - /* 0x018 */ Mtx field_0x018; - /* 0x048 */ Mtx field_0x048; - /* 0x078 */ Mtx field_0x078; - /* 0x0A8 */ Mtx field_0x0a8; + /* 0x00C */ s16 mAnimCooldown; // In frames. Animations will not change unless this is 0. + /* 0x00E */ u8 field_0x00C[0x010 - 0x00E]; + /* 0x010 */ State_e mFlags; + /* 0x014 */ AnmID_e mAnmIdx; + /* 0x018 */ Mtx mModelViewMtx; + /* 0x048 */ Mtx mTrunkModelViewMtx; + /* 0x078 */ Mtx mShadowModelMtx; + /* 0x0A8 */ Mtx mShadowModelViewMtx; /* 0x0D8 */ Unit_c* mpNext; - /* 0x0DC */ u8 field_0xdc[0x18C - 0xDC]; + + /* 0x0DC */ dKy_tevstr_c mTevStr; }; STATIC_ASSERT(sizeof(Unit_c) == 0x18C); - class Anm_c { public: - enum Mode_e {}; + enum Mode_e { + Mode_Cut = 0, // Chopping down + Mode_PushInto = 1, // Attacked or collided with, but not chopped + Mode_PushBack = 2, // Second half of PushInto, returning to normal + Mode_Fan = 3, // When hit with fan (does nothing) + Mode_Norm = 4, // Idle animation + Mode_ToNorm = 5, // Transition to idle from any other animation + + Mode_Max + }; Anm_c(); void play(Packet_c*); + + // Copies the "angle" and "amplitude" from another animation void copy_angamp(const Anm_c*); + + // Animations are assigned from the Packet to specific Wood instances (Bushes) when a new animation starts + // Each animation mode has an mode_*_init() function which is called when the animation is started + // The mode_*() function is called to update the animation each frame, until finished + // Their are 8 pre-allocated "normal" animations. When not animating, each unit is assigned one of the 8. + void mode_cut_init(const Anm_c*, short); void mode_cut(Packet_c*); void mode_push_into_init(const Anm_c*, short); @@ -59,11 +98,33 @@ class Anm_c { void mode_to_norm_init(AnmID_e); void mode_to_norm(Packet_c*); - /* 0x00 */ u8 field_0x00[0x60 - 0x00]; - /* 0x60 */ int field_0x60; - /* 0x64 */ s16 field_0x64; - /* 0x66 */ u8 field_0x66[0x8A - 0x66]; - /* 0x8A */ u8 field_0x8a; + inline AnmID_e mode_to_norm_get_AnmID() { return (AnmID_e)mNormAnimIdx; } + inline void mode_to_norm_set_AnmID(AnmID_e anmID) { mNormAnimIdx = anmID; } + + Mode_e get_mode() { return mMode; } + + /* 0x00 */ Mtx mModelMtx; + /* 0x30 */ Mtx mTrunkModelMtx; + + /* 0x60 */ Mode_e mMode; + + /* 0x64 */ s16 mCountdown; + /* 0x66 */ s16 mForceDir; // The direction from the wind or actor who instigated this animation + /* 0x68 */ float mWindPow; // 0.0 - 1.0 + /* 0x6c */ float mPosOffsetY; + /* 0x70 */ float mPosOffsetZ; + /* 0x74 */ float mVelY; + + /* 0x78 */ s16 mPhaseY[2]; + /* 0x7c */ s16 mPhaseX[2]; + /* 0x80 */ s16 mAmpY[2]; + /* 0x84 */ s16 mAmpX[2]; + + /* 0x88 */ s16 mNormAnimIdx; + + /* 0x8A */ u8 mAlphaScale; + + static s32 M_init_num; }; STATIC_ASSERT(sizeof(Anm_c) == 0x8C); @@ -81,13 +142,15 @@ class Packet_c : public J3DPacket { public: Packet_c(); - void delete_room(int); - void put_unit(const cXyz&, int); + void delete_room(int room_no); + s32 put_unit(const cXyz& pos, int room_no); void calc_cc(); void calc(); void update(); - void search_empty_UnitID() const; - void search_anm(Anm_c::Mode_e); + s32 search_empty_UnitID() const; + AnmID_e search_anm(Anm_c::Mode_e mode); + + inline Anm_c* get_anm_p(AnmID_e idx) { return &mAnm[idx]; } virtual void draw(); virtual ~Packet_c(); diff --git a/src/d/d_tree.cpp b/src/d/d_tree.cpp index f0f1a3c6d..8a41532f5 100644 --- a/src/d/d_tree.cpp +++ b/src/d/d_tree.cpp @@ -5,6 +5,14 @@ #include "d/d_tree.h" #include "dolphin/types.h" +#include "dolphin/mtx/mtx.h" + +u8 g_dTree_shadowPos[12] = { 0xb5, 0x00, 0x4b, 0x4b, 0x00, 0x4b, 0xb5, 0x00, 0xb5, 0x4b, 0x00, 0xb5 }; +u8 g_dTree_shadowTexCoord[8] = { 0x00, 0x00, 0x01, 0x00, 0x01, 0x01, 0x00, 0x01 }; +const u32 g_dTree_Oba_kage_32DL_SIZE = 0x2b; +const u32 g_dTree_shadowMatDL_SIZE = 0x90; +u8 g_dTree_Oba_kage_32DL[g_dTree_Oba_kage_32DL_SIZE] = { 0x98, 0x00, 0x04, 0x01, 0x02, 0x00, 0x03, 0x03, 0x01, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }; +u8 g_dTree_shadowMatDL[g_dTree_shadowMatDL_SIZE] = { 0x61, 0x80, 0x00, 0x01, 0x35, 0x61, 0x84, 0x00, 0x00, 0x00, 0x61, 0x88, 0x00, 0x7c, 0x1f, 0x61, 0x94, 0x00, 0x00, 0x00, 0x61, 0x30, 0x00, 0x00, 0x20, 0x61, 0x31, 0x00, 0x00, 0x20, 0x10, 0x00, 0x00, 0x10, 0x40, 0xff, 0xff, 0x42, 0x80, 0x08, 0x30, 0x3c, 0xf3, 0xcf, 0x00, 0x10, 0x00, 0x00, 0x10, 0x18, 0x3c, 0xf3, 0xcf, 0x00, 0x61, 0x28, 0x38, 0x03, 0xc0, 0x61, 0xc0, 0x08, 0xff, 0xff, 0x61, 0xc1, 0x08, 0xe6, 0x70, 0x61, 0x43, 0x00, 0x00, 0x01, 0x61, 0x40, 0x00, 0x00, 0x07, 0x61, 0x41, 0x00, 0x04, 0xad, 0x61, 0xf3, 0x64, 0x00, 0x00, 0x10, 0x00, 0x00, 0x10, 0x3f, 0x00, 0x00, 0x00, 0x01, 0x10, 0x00, 0x00, 0x10, 0x09, 0x00, 0x00, 0x00, 0x00, 0x61, 0x00, 0x00, 0x40, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }; /* 800787BC-80078960 .text WorkCo__12dTree_data_cFP10fopAc_ac_cUli */ void dTree_data_c::WorkCo(fopAc_ac_c*, u32, int) { diff --git a/src/d/d_wood.cpp b/src/d/d_wood.cpp index e5fca8060..a77322209 100644 --- a/src/d/d_wood.cpp +++ b/src/d/d_wood.cpp @@ -4,184 +4,995 @@ // #include "d/d_wood.h" +#include "JAZelAudio/JAIZelBasic.h" +#include "JSystem/J3DGraphBase/J3DShape.h" +#include "JSystem/J3DU/J3DUClipper.h" +#include "JSystem/JMath/JMath.h" +#include "JSystem/JUtility/JUTAssert.h" +#include "SSystem/SComponent/c_bg_s_gnd_chk.h" +#include "SSystem/SComponent/c_lib.h" +#include "d/d_bg_s_gnd_chk.h" +#include "d/d_bg_s_spl_grp_chk.h" +#include "d/d_com_inf_game.h" +#include "d/d_drawlist.h" +#include "d/d_kankyo_wether.h" +#include "d/d_procname.h" +#include "d/d_tree.h" +#include "d/d_cc_d.h" +#include "dolphin/gf/GFGeometry.h" +#include "dolphin/gf/GFTev.h" +#include "dolphin/gf/GFTransform.h" +#include "dolphin/gx/GXAttr.h" +#include "dolphin/gx/GXDisplayList.h" #include "dolphin/types.h" +#include "m_Do/m_Do_lib.h" +#include "m_Do/m_Do_mtx.h" + +//----------------------------------------- +// Types +//----------------------------------------- +enum AttrSway_e { + SWAY_LIGHT, + SWAY_MEDIUM, + SWAY_STRONG, + SWAY_PUSH, +}; + +struct AttrSway_c { + /* 0x0 */ s16 phaseVelY; + /* 0x2 */ s16 ampY; + /* 0x4 */ s16 phaseVelX; + /* 0x6 */ s16 ampX; + /* 0x8 */ float phaseBiasX; +}; +struct Attr_c { + /* 0x0 */ AttrSway_c kSways[4][2]; + /* 0x60 */ u8 kCutCooldown; // = 20 + /* 0x61 */ u8 kCutFadeStart; // = 20 (Countdown time at which bush starts to fade out) + /* 0x62 */ u8 kCutAlphaFadeSpeed; // = 14 + /* 0x64 */ float kCutInitVelY; // = 18.0f + /* 0x68 */ float kCutYAccel; // = -3.0f (Units per frame per frame) + /* 0x6C */ float kCutZVel; // = 2.5f (Units per frame) + /* 0x70 */ s16 kCutPitchVel; // = 200 (shortRad per frame) + /* 0x74 */ float kUncutShadowScale; // = 1.5f + /* 0x78 */ float kCutShadowScale; // = 0.3f + /* 0x7c */ float kCollisionRad; // = 80.0f; + /* 0x80 */ float kCollisionRadCut; // = 15.0f; + /* 0x84 */ float kCollisionHeight; // = 80.0f; + /* 0x88 */ float kCollisionHeightCut; // = 15.0f; + /* 0x8c */ float kClipRadius; // = 100.0f; + /* 0x90 */ float kClipCenterYOffset; // = 40.0f; + /* 0x94 */ u8 kPushBackCountdown; // = 23 + /* 0x95 */ const u8 L_Alpha_Cutoff; // = 0x80; +}; + +typedef void (dWood::Anm_c::*modeProcFunc)(dWood::Packet_c *); + +//----------------------------------------- +// Data +//----------------------------------------- +static Vec dummy1 = { 1.0f, 1.0f, 1.0f }; +static Vec dummy2 = { 1.0f, 1.0f, 1.0f }; + +namespace dWood { +namespace { +// .data +u8 l_Txa_swood_bTEX[0x800] ALIGN_DECL(32) = { 0x34, 0x66, 0x3c, 0xe7, 0xff, 0xff, 0x55, 0x80, 0x3c, 0x86, 0x3c, 0xe7, 0xff, 0xff, 0x5b, 0x95, 0x2c, 0x05, 0x2b, 0xc4, 0x2d, 0xa0, 0xa0, 0x00, 0x3c, 0xc7, 0x2c, 0x05, 0x78, 0x57, 0x55, 0x55, 0x00, 0x00, 0x3c, 0xe7, 0xff, 0xff, 0xff, 0x7f, 0x3c, 0xa7, 0x3d, 0x07, 0xff, 0xff, 0xfa, 0x81, 0x2c, 0x25, 0x3c, 0xc7, 0x5d, 0x55, 0x95, 0x24, 0x3c, 0xe7, 0x2b, 0xe5, 0x0a, 0x37, 0xd5, 0x75, 0x3c, 0xc7, 0x3c, 0xe7, 0xff, 0xff, 0x3f, 0x4f, 0x00, 0x00, 0x3c, 0xc7, 0xff, 0xff, 0xff, 0xfd, 0x3c, 0xa7, 0x3c, 0xe7, 0xaf, 0x5d, 0x55, 0x14, 0x3c, 0xc7, 0x2c, 0x05, 0x00, 0x00, 0x0b, 0xd5, 0x00, 0x00, 0x3c, 0xe7, 0xff, 0xff, 0xff, 0x57, 0x3c, 0xe7, 0x3c, 0xe7, 0xff, 0xff, 0xff, 0xff, 0x34, 0x46, 0x3c, 0xe7, 0x57, 0x57, 0x17, 0x17, 0x3c, 0xc7, 0x3c, 0xc7, 0xff, 0xff, 0xff, 0xff, 0x3c, 0xe7, 0x3c, 0xe7, 0xff, 0xff, 0xff, 0xff, 0x3c, 0xe7, 0x3c, 0xe7, 0xff, 0xff, 0xff, 0xff, 0x3c, 0xc7, 0x3c, 0xc7, 0xff, 0xff, 0xff, 0xff, 0x3c, 0xe7, 0x3c, 0xe7, 0xff, 0xff, 0xff, 0xff, 0x3c, 0xe7, 0x3c, 0xe7, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x3c, 0xe7, 0xff, 0xfd, 0xf5, 0xf5, 0x3c, 0xc7, 0x3c, 0xe7, 0xff, 0xff, 0xff, 0x95, 0x34, 0x25, 0x3c, 0xe7, 0xf5, 0xd5, 0xd6, 0xd4, 0x3c, 0xc7, 0x3c, 0xe7, 0xff, 0x7f, 0x87, 0x55, 0x3c, 0xe7, 0x3c, 0xe7, 0xff, 0xff, 0xff, 0xff, 0x3c, 0xc7, 0x2b, 0xe5, 0xe0, 0x5c, 0x56, 0x5f, 0x3c, 0xa7, 0x3c, 0xe7, 0x7f, 0x7f, 0x5d, 0x95, 0x3c, 0xe7, 0x3c, 0xe7, 0xff, 0xff, 0xff, 0xff, 0x3c, 0xe7, 0x3c, 0xe7, 0xff, 0xff, 0xff, 0xff, 0x2c, 0x25, 0x3c, 0xc7, 0xf5, 0x55, 0x56, 0x40, 0x3c, 0xc7, 0x2b, 0xc5, 0x00, 0x00, 0xff, 0x5d, 0x2c, 0x25, 0x2b, 0xe5, 0xae, 0x38, 0x03, 0x3e, 0x2c, 0x25, 0x2b, 0xc5, 0x80, 0xa0, 0x72, 0xae, 0x2c, 0x25, 0x2b, 0xc5, 0x2a, 0xe2, 0xe0, 0x62, 0x2c, 0x05, 0x23, 0x84, 0x05, 0xa5, 0x25, 0x85, 0x2c, 0x25, 0x2b, 0xe5, 0xe1, 0x9a, 0xfc, 0x3a, 0x2c, 0x05, 0x2b, 0xe5, 0x82, 0xc3, 0x00, 0xc2, 0x2c, 0x05, 0x23, 0x84, 0x80, 0x60, 0x58, 0x56, 0x2c, 0x05, 0x2b, 0xc5, 0x80, 0x03, 0xf0, 0x0e, 0x3c, 0xe7, 0x2c, 0x05, 0x81, 0x85, 0xf7, 0x55, 0x34, 0x46, 0x2b, 0xe5, 0xfb, 0xe9, 0xfa, 0xb4, 0x2c, 0x05, 0x23, 0x84, 0x00, 0x28, 0xd0, 0x58, 0x3c, 0xe7, 0x2b, 0xe5, 0x54, 0x5c, 0x77, 0x5d, 0x34, 0x86, 0x3c, 0xe7, 0x17, 0x17, 0x9f, 0x5f, 0x3c, 0xe7, 0x3c, 0xe7, 0xff, 0xff, 0xff, 0xff, 0x2c, 0x05, 0x3c, 0xc7, 0x5f, 0x55, 0x95, 0x01, 0x00, 0x00, 0x3c, 0xe7, 0xfd, 0x5d, 0x5f, 0x5f, 0x3c, 0xc7, 0x3c, 0xe7, 0xff, 0xff, 0xf9, 0x55, 0x3c, 0xc7, 0x3c, 0xe7, 0xfd, 0xfd, 0x59, 0x41, 0x3c, 0xe7, 0x2b, 0xc5, 0x00, 0x0f, 0x0d, 0x01, 0x3c, 0xa7, 0x23, 0x84, 0x00, 0xfa, 0xef, 0xf7, 0x3c, 0xe7, 0x2c, 0x05, 0x00, 0x26, 0x25, 0x25, 0x3c, 0xe7, 0x2c, 0x05, 0x01, 0x0d, 0xf5, 0x55, 0x3d, 0x07, 0x2c, 0x05, 0x25, 0xf5, 0x55, 0x55, 0x2c, 0x05, 0x23, 0x84, 0x00, 0x20, 0x00, 0x60, 0x2c, 0x05, 0x2b, 0xc5, 0x08, 0x00, 0x60, 0x82, 0x3c, 0xc7, 0x2b, 0xe5, 0xc2, 0x6d, 0x55, 0xf5, 0x2c, 0x05, 0x2b, 0xc5, 0x30, 0x02, 0x02, 0x00, 0x2c, 0x05, 0x23, 0x84, 0x0a, 0x0d, 0x0d, 0x15, 0x2c, 0x25, 0x2b, 0xe5, 0x98, 0x5b, 0xa3, 0x89, 0x2c, 0x05, 0x2b, 0xc5, 0x20, 0x00, 0x02, 0x0c, 0x2c, 0x05, 0x23, 0x64, 0xa8, 0x78, 0x58, 0xfc, 0x2c, 0x05, 0x2b, 0xe5, 0x20, 0x90, 0x09, 0x02, 0x2c, 0x25, 0x2b, 0xc5, 0xa2, 0xb8, 0x98, 0x02, 0x2c, 0x25, 0x23, 0x84, 0x85, 0x2d, 0x3d, 0x89, 0x2c, 0x25, 0x2b, 0xe5, 0x26, 0x76, 0x7a, 0x82, 0x2c, 0x05, 0x2b, 0xa4, 0x01, 0x02, 0x02, 0x02, 0x2b, 0x84, 0x23, 0x64, 0x08, 0x00, 0x20, 0x00, 0x2c, 0x05, 0x23, 0x84, 0x03, 0x81, 0x49, 0x6d, 0x23, 0x84, 0x23, 0x64, 0x00, 0x00, 0x02, 0x22, 0x23, 0x84, 0x23, 0x64, 0x02, 0x00, 0x00, 0x00, 0x2c, 0x25, 0x23, 0x84, 0x58, 0x7a, 0x7a, 0x70, 0x2c, 0x05, 0x2b, 0xe5, 0xa0, 0x80, 0x00, 0x23, 0x2c, 0x25, 0x23, 0x84, 0x78, 0x68, 0x60, 0xef, 0x2c, 0x05, 0x2b, 0xc5, 0x02, 0x98, 0x20, 0x55, 0x3c, 0xc7, 0x2c, 0x05, 0x5c, 0x50, 0x70, 0x40, 0x3c, 0xc7, 0x3c, 0xe7, 0x7f, 0xbf, 0xff, 0x5f, 0x3c, 0xc7, 0x2c, 0x05, 0x78, 0x55, 0x55, 0x55, 0x3c, 0xe7, 0x2b, 0xc5, 0x00, 0xe0, 0x58, 0xe0, 0x34, 0x46, 0x3c, 0xe7, 0xd4, 0xf5, 0xfd, 0xfd, 0x3c, 0xe7, 0x2c, 0x05, 0x55, 0xd5, 0x0b, 0x03, 0x2b, 0xe5, 0x3c, 0xe7, 0xd5, 0x58, 0x58, 0x56, 0x34, 0x46, 0x2b, 0xe5, 0x03, 0x5f, 0x7d, 0x7d, 0x2c, 0x05, 0x2b, 0xc5, 0x03, 0x08, 0x00, 0x82, 0x2c, 0x05, 0x23, 0x84, 0x5c, 0x56, 0xd5, 0xd5, 0x2c, 0x05, 0x2b, 0xe5, 0x02, 0x08, 0x88, 0x00, 0x2c, 0x25, 0x23, 0x84, 0x95, 0x35, 0x25, 0x2d, 0x2c, 0x05, 0x23, 0x84, 0x08, 0x02, 0x03, 0x4d, 0x2b, 0xc5, 0x23, 0x84, 0x17, 0xff, 0xff, 0x75, 0x2b, 0xc5, 0x23, 0x64, 0x8b, 0xff, 0xff, 0xad, 0x23, 0x84, 0x23, 0x64, 0x00, 0x00, 0x08, 0x08, 0x2c, 0x05, 0x23, 0x84, 0x5c, 0x5c, 0x58, 0x70, 0x2c, 0x05, 0x2b, 0xc5, 0xe0, 0x08, 0x00, 0x08, 0x2c, 0x05, 0x23, 0x84, 0x60, 0xc2, 0xc0, 0x80, 0x2c, 0x25, 0x2b, 0xc5, 0x0a, 0x0a, 0xca, 0x88, 0x2c, 0x05, 0x2b, 0xc5, 0x02, 0xa0, 0x00, 0x62, 0x2c, 0x05, 0x2b, 0xe5, 0x02, 0x00, 0xf0, 0x51, 0x2c, 0x25, 0x2b, 0xc5, 0x60, 0x0b, 0x28, 0xf0, 0x2c, 0x25, 0x2b, 0xc5, 0x8b, 0x7e, 0xaa, 0x82, 0x2c, 0x05, 0x23, 0x84, 0xd5, 0x35, 0x25, 0x09, 0x23, 0x84, 0x23, 0x64, 0x80, 0x00, 0x00, 0x00, 0x2c, 0x05, 0x23, 0x84, 0x01, 0x02, 0x00, 0x03, 0x2b, 0xe5, 0x23, 0x84, 0x55, 0x57, 0xd5, 0x15, 0x23, 0x84, 0x23, 0x64, 0x02, 0x00, 0x00, 0x80, 0x2c, 0x05, 0x23, 0x84, 0x55, 0x56, 0x50, 0x80, 0x2c, 0x05, 0x23, 0x84, 0x78, 0x70, 0x50, 0x58, 0x2c, 0x05, 0x2b, 0xc5, 0x0e, 0x00, 0x00, 0x02, 0x34, 0x86, 0x2b, 0xe5, 0x5e, 0xdc, 0x7d, 0x5f, 0x2c, 0x25, 0x3d, 0x07, 0x97, 0x7f, 0x9f, 0x27, 0x34, 0x46, 0x2b, 0xc5, 0xa7, 0xfa, 0xdb, 0xe2, 0x3c, 0xe7, 0x2c, 0x05, 0x70, 0x58, 0x5c, 0x5c, 0x3c, 0xc7, 0x3c, 0xe7, 0xd5, 0xfd, 0xff, 0xff, 0x2c, 0x05, 0x3c, 0xe7, 0x80, 0x58, 0xd4, 0x50, 0x3c, 0xc7, 0x3c, 0xe7, 0xff, 0x7e, 0x7d, 0x3d, 0x3c, 0xe7, 0x2c, 0x05, 0x25, 0x25, 0x3d, 0x00, 0x2c, 0x05, 0x23, 0x84, 0x00, 0x00, 0x0b, 0x35, 0x2c, 0x05, 0x23, 0x84, 0x09, 0xb5, 0x55, 0x55, 0x3c, 0x86, 0x23, 0x84, 0x95, 0xef, 0xee, 0x00, 0x2c, 0x05, 0x23, 0x84, 0x75, 0x05, 0x0d, 0x05, 0x23, 0x84, 0x23, 0x64, 0x00, 0x80, 0x80, 0x02, 0x2b, 0xe5, 0x23, 0x84, 0x57, 0x54, 0xdc, 0x50, 0x23, 0x84, 0x23, 0x64, 0x02, 0x00, 0x80, 0x02, 0x2c, 0x05, 0x23, 0x64, 0xf0, 0x60, 0x40, 0xc0, 0x2c, 0x25, 0x2b, 0xe5, 0x0a, 0xba, 0xab, 0xb8, 0x8b, 0x28, 0x2c, 0x05, 0x55, 0x57, 0x58, 0xe0, 0x83, 0x28, 0x2c, 0x05, 0x57, 0x5c, 0x60, 0x80, 0x8b, 0x28, 0x83, 0x48, 0x4f, 0xbf, 0xff, 0xff, 0x2c, 0x25, 0x2b, 0xa4, 0xe0, 0x2a, 0xaa, 0xa2, 0x2c, 0x25, 0x2b, 0xe5, 0x3c, 0x3e, 0x16, 0x3b, 0x2c, 0x05, 0x2b, 0xa4, 0x08, 0x24, 0x08, 0x00, 0x2c, 0x05, 0x2b, 0xc5, 0x03, 0x00, 0x00, 0x28, 0x2c, 0x05, 0x2b, 0xc5, 0x07, 0x00, 0x00, 0x02, 0x2c, 0x05, 0x23, 0x84, 0x35, 0x25, 0x0d, 0x09, 0x2c, 0x25, 0x2b, 0xe5, 0x82, 0x82, 0xeb, 0xa2, 0x2c, 0x05, 0x23, 0x84, 0x81, 0x02, 0x08, 0x00, 0x2c, 0x25, 0x23, 0x84, 0x5c, 0x5c, 0x54, 0x56, 0x2c, 0x05, 0x2b, 0xc5, 0x32, 0x02, 0x0e, 0x80, 0x2b, 0xe5, 0x23, 0x84, 0x57, 0x54, 0x94, 0x3c, 0x3c, 0xa7, 0x2b, 0xe5, 0x75, 0xd6, 0x58, 0xe0, 0x2c, 0x05, 0x3c, 0xe7, 0x25, 0x25, 0x17, 0x17, 0x3c, 0xc7, 0x3c, 0xe7, 0x85, 0x55, 0xff, 0xff, 0x3c, 0xc7, 0x3c, 0xe7, 0x1f, 0x5f, 0xbf, 0x5f, 0x3c, 0xe7, 0x3d, 0x07, 0xff, 0xff, 0xfc, 0xfd, 0x3c, 0xc7, 0x3c, 0xe7, 0x3f, 0x7f, 0xff, 0xff, 0x3c, 0xc7, 0x3c, 0xe7, 0x55, 0xff, 0xff, 0xff, 0x2b, 0xe5, 0x3c, 0xc7, 0xff, 0x57, 0x55, 0x49, 0x00, 0x00, 0x3c, 0xe7, 0xff, 0xff, 0xff, 0x7f, 0x3c, 0xa7, 0x3c, 0xe7, 0x5d, 0xfe, 0xf4, 0xf6, 0x2c, 0x25, 0x23, 0x84, 0x25, 0x25, 0x25, 0x25, 0x3c, 0x86, 0x3c, 0xe7, 0xf4, 0xf6, 0xfe, 0x55, 0x3c, 0xc7, 0x23, 0x84, 0xf5, 0xfd, 0xbd, 0x2f, 0x2c, 0x05, 0x23, 0x84, 0x55, 0x56, 0x5c, 0x58, 0x8b, 0x28, 0x33, 0xe5, 0x56, 0x58, 0x60, 0x80, 0x83, 0x28, 0x2b, 0xa4, 0x56, 0x58, 0x60, 0xc0, 0xa4, 0x2c, 0x83, 0x28, 0x55, 0x55, 0x55, 0x54, 0x8b, 0x49, 0x83, 0x08, 0x80, 0x00, 0x02, 0x0c, 0xa4, 0x2c, 0x83, 0x28, 0x55, 0x55, 0x55, 0x25, 0xee, 0x73, 0x83, 0x28, 0x56, 0x70, 0xc0, 0x00, 0xee, 0x73, 0x8b, 0x48, 0x0d, 0x01, 0x01, 0x01, 0x2c, 0x05, 0x2b, 0xc5, 0x07, 0x28, 0x80, 0x00, 0x2c, 0x25, 0x2b, 0xe5, 0x28, 0x28, 0xd6, 0x6a, 0x2c, 0x25, 0x2b, 0xe5, 0x8a, 0xea, 0xe8, 0xe0, 0x2c, 0x05, 0x2b, 0xe5, 0x00, 0x80, 0xa2, 0xb0, 0x2c, 0x05, 0x2b, 0xe5, 0x02, 0x20, 0x08, 0x01, 0x2c, 0x25, 0x2b, 0xc5, 0x2a, 0xa5, 0x8a, 0x68, 0x2c, 0x05, 0x2b, 0xe5, 0x20, 0x02, 0x03, 0x20, 0x2c, 0x05, 0x2b, 0xc5, 0x08, 0x02, 0x20, 0xe0, 0x2c, 0x05, 0x2b, 0xc5, 0x00, 0x00, 0x09, 0x02, 0x34, 0x25, 0x2b, 0xe5, 0x00, 0x28, 0xe4, 0x8f, 0x2c, 0x05, 0x2b, 0xe5, 0x0a, 0xc1, 0x88, 0x20, 0x2c, 0x05, 0x2b, 0xa5, 0x02, 0xc0, 0x0a, 0x0d, 0x3c, 0xe7, 0x2c, 0x05, 0x80, 0x70, 0x56, 0x75, 0x2c, 0x05, 0x3c, 0xe7, 0xf5, 0x76, 0x54, 0x58, 0x2c, 0x05, 0x2b, 0xe5, 0x82, 0x22, 0x00, 0x00, 0x3c, 0xa7, 0x2c, 0x05, 0x85, 0x55, 0x5d, 0x55, 0x34, 0x86, 0x2b, 0xe5, 0xf4, 0x5c, 0xde, 0xdf, 0x34, 0x46, 0x3c, 0xe7, 0x7d, 0x55, 0x55, 0x54, 0x2c, 0x05, 0x2b, 0xe5, 0x0a, 0xe0, 0x0e, 0x08, 0x45, 0x07, 0x2c, 0x05, 0x8d, 0xe5, 0x55, 0x55, 0x3c, 0xe7, 0x2c, 0x05, 0x02, 0x2d, 0xd7, 0x55, 0x83, 0x28, 0x2c, 0x25, 0x57, 0x5c, 0x70, 0x40, 0x8b, 0x28, 0x2b, 0xe5, 0x55, 0x56, 0x5c, 0x58, 0x83, 0x28, 0x6b, 0x67, 0x40, 0x00, 0x00, 0x00, 0x93, 0x89, 0x83, 0x07, 0xff, 0xff, 0xfd, 0xfc, 0xee, 0x73, 0x83, 0x08, 0x5c, 0x70, 0xc0, 0x00, 0xbc, 0xce, 0x83, 0x28, 0x54, 0x54, 0x57, 0x55, 0xee, 0x74, 0x83, 0x28, 0x00, 0x00, 0x80, 0x5f, 0xee, 0x94, 0xe6, 0x52, 0x1e, 0x60, 0x80, 0x02, 0xee, 0x93, 0x83, 0x08, 0x09, 0x09, 0x09, 0x09, 0xee, 0x74, 0xac, 0x8d, 0x00, 0x00, 0x00, 0x55, 0xee, 0x74, 0x83, 0x08, 0x0d, 0x0d, 0x25, 0xd5, 0x2c, 0x25, 0x2b, 0xc5, 0x0b, 0xab, 0x98, 0x08, 0x2c, 0x25, 0x2b, 0xe5, 0xaf, 0xa8, 0x22, 0xac, 0x2c, 0x25, 0x2b, 0xe5, 0xee, 0x7b, 0xda, 0xac, 0x2c, 0x05, 0x2b, 0xc5, 0x1c, 0x22, 0x0c, 0x0a, 0x2c, 0x05, 0x2b, 0xe5, 0x01, 0x50, 0xe2, 0x80, 0x2c, 0x05, 0x2b, 0xe5, 0x80, 0x20, 0xe2, 0x8b, 0x2c, 0x25, 0x2b, 0xe5, 0x6e, 0xa6, 0xb8, 0x8a, 0x2c, 0x25, 0x2b, 0xc5, 0x3a, 0x3e, 0x0a, 0x00, 0x2c, 0x05, 0x2b, 0xa4, 0x20, 0x00, 0x20, 0x24, 0x2c, 0x05, 0x23, 0x84, 0x01, 0x23, 0x03, 0x08, 0x2c, 0x25, 0x2b, 0xe5, 0x96, 0xf0, 0xa0, 0x8f, 0x2c, 0x05, 0x2b, 0xc5, 0x40, 0x80, 0x02, 0x02, 0x2b, 0xe5, 0x23, 0x84, 0xc0, 0x70, 0x5c, 0xf6, 0x2c, 0x25, 0x2b, 0xe5, 0x28, 0xbe, 0xb8, 0xad, 0x2b, 0xe5, 0x23, 0x84, 0x9d, 0x35, 0x25, 0x07, 0x2c, 0x05, 0x23, 0x84, 0x80, 0x40, 0x70, 0x70, 0x2c, 0x05, 0x2b, 0xc5, 0x00, 0x92, 0x30, 0x00, 0x2c, 0x05, 0x23, 0x64, 0x02, 0x8b, 0x2d, 0xd5, 0x2c, 0x05, 0x2b, 0x84, 0x00, 0x03, 0x09, 0x0d, 0x2c, 0x25, 0x23, 0x84, 0x57, 0x57, 0x56, 0x5c, 0x5b, 0x87, 0x2b, 0xe5, 0x5c, 0xd5, 0x55, 0x55, 0x8b, 0x48, 0x2c, 0x05, 0x80, 0x58, 0x5c, 0x5c, 0x2c, 0x05, 0x2b, 0xc5, 0x00, 0x87, 0x00, 0x20, 0xa3, 0xa8, 0x2c, 0x05, 0x58, 0x55, 0x55, 0x5c, 0xa3, 0xc8, 0x83, 0x28, 0x55, 0x55, 0xff, 0x00, 0xa3, 0xc8, 0x83, 0x28, 0x55, 0x55, 0xff, 0x00, 0xa3, 0xc8, 0x7a, 0xe7, 0xaa, 0x55, 0xff, 0x00, 0xa3, 0xc8, 0x7a, 0xe7, 0xaa, 0x55, 0xff, 0x00, 0xa3, 0xc8, 0x83, 0x28, 0x55, 0x55, 0xff, 0x00, 0xa3, 0xc8, 0x83, 0x28, 0x55, 0x55, 0xff, 0x00, 0xa3, 0xc8, 0x7a, 0xe7, 0xaa, 0x55, 0xff, 0x00, 0xa3, 0xa8, 0x7a, 0xe7, 0xaa, 0x55, 0xff, 0x00, 0x2c, 0x25, 0x2b, 0xe5, 0xaa, 0x51, 0xa1, 0xe1, 0x2c, 0x25, 0x2b, 0xe5, 0x52, 0xa0, 0xc2, 0x40, 0x2c, 0x25, 0x2b, 0x84, 0x82, 0x02, 0xa0, 0x70, 0x2c, 0x25, 0x2b, 0xe5, 0x82, 0xe3, 0xaa, 0x08, 0x2c, 0x25, 0x2b, 0xc5, 0x2b, 0xbe, 0xaa, 0x08, 0x2c, 0x05, 0x2b, 0xc5, 0x0a, 0xc3, 0x88, 0x08, 0x2c, 0x05, 0x2b, 0xe5, 0x80, 0x4f, 0x8a, 0x01, 0x2c, 0x25, 0x2b, 0xe5, 0x06, 0x0a, 0xcf, 0xcd, 0x2c, 0x25, 0x2b, 0xe5, 0xa6, 0xca, 0x82, 0x2a, 0x2c, 0x05, 0x2b, 0xc5, 0x20, 0x00, 0x0a, 0x04, 0x2c, 0x25, 0x2b, 0xe5, 0xba, 0xb0, 0x8a, 0x8f, 0x2c, 0x05, 0x2b, 0xe5, 0x00, 0x38, 0x14, 0x02, 0x2c, 0x25, 0x23, 0x84, 0x05, 0x8d, 0x89, 0x01, 0x2c, 0x05, 0x23, 0x84, 0x5c, 0x54, 0xd6, 0x55, 0x2c, 0x05, 0x2b, 0xe5, 0x21, 0x00, 0x80, 0x42, 0x2c, 0x05, 0x23, 0x84, 0x55, 0x95, 0x35, 0x25, 0x2b, 0xe5, 0x23, 0x84, 0x05, 0x35, 0x1d, 0xd5, 0x2c, 0x25, 0x23, 0x84, 0x58, 0x70, 0x60, 0xc0, 0x2c, 0x05, 0x23, 0x84, 0x57, 0x5c, 0x58, 0x70, 0x2c, 0x25, 0x2b, 0xe5, 0xeb, 0x26, 0x0a, 0x01, 0x2c, 0x25, 0x2b, 0xc5, 0xba, 0x22, 0x2a, 0xa8, 0xab, 0xa8, 0x2c, 0x05, 0x5c, 0x55, 0x55, 0x5c, 0x2c, 0x05, 0x2b, 0xc5, 0x88, 0x08, 0x38, 0x2c, 0xa3, 0xa8, 0x2c, 0x05, 0x58, 0x55, 0x55, 0x55, 0xa3, 0xc8, 0x7a, 0xe7, 0xaa, 0x55, 0xff, 0x00, 0xa3, 0xc8, 0x7a, 0xe7, 0xaa, 0x55, 0xff, 0x00, 0x93, 0x47, 0x73, 0x07, 0x00, 0x7f, 0xaa, 0xaa, 0x93, 0x47, 0x7a, 0xe7, 0x00, 0x55, 0xaa, 0xaa, 0xa3, 0xc8, 0x7a, 0xe7, 0xaa, 0x55, 0xff, 0x00, 0xa3, 0xc8, 0x7a, 0xe7, 0xaa, 0x55, 0xff, 0x00, 0x93, 0x47, 0x7a, 0xe7, 0x00, 0x55, 0xaa, 0xaa, 0x93, 0x47, 0x7a, 0xe7, 0x00, 0x55, 0xaa, 0xaa }; +u8 l_pos[0x2e8] = { 0x37, 0xb8, 0x8c, 0xa4, 0x41, 0x6e, 0xc3, 0xf7, 0xc2, 0xb3, 0xf6, 0xf9, 0xc2, 0x9b, 0xda, 0xa2, 0x41, 0x6e, 0xc3, 0xf7, 0xc2, 0x33, 0xf6, 0xfe, 0xc2, 0x9b, 0xda, 0xa3, 0x41, 0x6e, 0xc3, 0xf7, 0x42, 0x33, 0xf6, 0xf6, 0xb7, 0x06, 0x37, 0xbd, 0x41, 0x6e, 0xc3, 0xf7, 0x42, 0xb3, 0xf6, 0xf7, 0x42, 0x9b, 0xda, 0xa1, 0x41, 0x6e, 0xc3, 0xf7, 0x42, 0x33, 0xf6, 0xf8, 0x42, 0x9b, 0xda, 0xa1, 0x41, 0x6e, 0xc3, 0xf7, 0xc2, 0x33, 0xf6, 0xf8, 0x00, 0x00, 0x00, 0x00, 0x42, 0xac, 0x37, 0x3b, 0x00, 0x00, 0x00, 0x00, 0x42, 0x40, 0x4b, 0x91, 0x42, 0x03, 0x2c, 0x64, 0xc2, 0xa6, 0x88, 0x4d, 0xc2, 0x40, 0x4b, 0x86, 0x42, 0x03, 0x2c, 0x64, 0xc2, 0xa6, 0x88, 0x4f, 0xc2, 0xc0, 0x4b, 0x8a, 0x42, 0x03, 0x2c, 0x64, 0xb7, 0x7b, 0xa8, 0x82, 0xc2, 0x40, 0x4b, 0x8b, 0x42, 0x03, 0x2c, 0x64, 0x42, 0xa6, 0x88, 0x4d, 0x42, 0x40, 0x4b, 0x87, 0x42, 0x03, 0x2c, 0x64, 0x42, 0xa6, 0x88, 0x4d, 0x42, 0xc0, 0x4b, 0x89, 0x42, 0x03, 0x2c, 0x64, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x42, 0xbd, 0x95, 0x4a, 0x00, 0x00, 0x00, 0x00, 0x42, 0x3b, 0x22, 0xd7, 0x42, 0x87, 0x96, 0x71, 0xc2, 0xa2, 0x10, 0x84, 0xc2, 0x3b, 0x22, 0xcc, 0x42, 0x87, 0x96, 0x71, 0xc2, 0xa2, 0x10, 0x86, 0xc2, 0xbb, 0x22, 0xd1, 0x42, 0x87, 0x96, 0x71, 0xb7, 0x7b, 0xa8, 0x82, 0xc2, 0x3b, 0x22, 0xd2, 0x42, 0x87, 0x96, 0x71, 0x42, 0xa2, 0x10, 0x84, 0x42, 0x3b, 0x22, 0xcf, 0x42, 0x87, 0x96, 0x71, 0x42, 0xa2, 0x10, 0x84, 0x42, 0xbb, 0x22, 0xd0, 0x42, 0x87, 0x96, 0x71, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x42, 0xd2, 0xc8, 0x80, 0x00, 0x00, 0x00, 0x00, 0x41, 0xe7, 0x0f, 0x01, 0x42, 0xc5, 0x3b, 0x61, 0xc2, 0x48, 0x1a, 0x3c, 0xc1, 0xe7, 0x0e, 0xf5, 0x42, 0xc5, 0x3b, 0x61, 0xc2, 0x48, 0x1a, 0x42, 0xc2, 0x67, 0x0e, 0xf9, 0x42, 0xc5, 0x3b, 0x61, 0xb7, 0x16, 0xfe, 0xb5, 0xc1, 0xe7, 0x0e, 0xfb, 0x42, 0xc5, 0x3b, 0x61, 0x42, 0x48, 0x1a, 0x3c, 0x41, 0xe7, 0x0e, 0xf6, 0x42, 0xc5, 0x3b, 0x61, 0x42, 0x48, 0x1a, 0x3c, 0x42, 0x67, 0x0e, 0xf7, 0x42, 0xc5, 0x3b, 0x61, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x42, 0xda, 0x1f, 0x3f, 0x00, 0x00, 0x00, 0x00, 0x42, 0x24, 0xf5, 0x0b, 0x3f, 0x96, 0x3e, 0xc9, 0xc2, 0x8e, 0xdb, 0x67, 0xc2, 0x24, 0xf5, 0x01, 0x3f, 0x96, 0x3e, 0xc9, 0xc2, 0x8e, 0xdb, 0x69, 0xc2, 0xa4, 0xf5, 0x05, 0x3f, 0x96, 0x3e, 0xc9, 0xb7, 0x5a, 0x1a, 0x93, 0xc2, 0x24, 0xf5, 0x06, 0x3f, 0x96, 0x3e, 0xc9, 0x42, 0x8e, 0xdb, 0x67, 0x42, 0x24, 0xf5, 0x02, 0x3f, 0x96, 0x3e, 0xc9, 0x42, 0x8e, 0xdb, 0x67, 0x42, 0xa4, 0xf5, 0x03, 0x3f, 0x96, 0x3e, 0xc9, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x42, 0x8c, 0x89, 0x4e, 0x00, 0x00, 0x00, 0x00, 0x37, 0xd1, 0xb7, 0x17, 0x42, 0x4b, 0x3d, 0xf5, 0xc2, 0xc3, 0x63, 0xe0, 0xc2, 0xa9, 0x36, 0x7a, 0x42, 0x4b, 0x3d, 0xf5, 0xc2, 0x43, 0x63, 0xe4, 0xc2, 0xa9, 0x36, 0x7d, 0x42, 0x4b, 0x3d, 0xf5, 0x42, 0x43, 0x63, 0xdc, 0xb7, 0x27, 0xc5, 0xac, 0x42, 0x4b, 0x3d, 0xf5, 0x42, 0xc3, 0x63, 0xde, 0x42, 0xa9, 0x36, 0x7a, 0x42, 0x4b, 0x3d, 0xf5, 0x42, 0x43, 0x63, 0xdf, 0x42, 0xa9, 0x36, 0x7a, 0x42, 0x4b, 0x3d, 0xf5, 0xc2, 0x43, 0x63, 0xde, 0x00, 0x00, 0x00, 0x00, 0x42, 0xcc, 0x24, 0x67, 0x00, 0x00, 0x00, 0x00, 0x37, 0xb0, 0x29, 0x28, 0x42, 0xa4, 0x8f, 0x40, 0xc2, 0xa0, 0x12, 0x3e, 0xc2, 0x8a, 0xa0, 0x33, 0x42, 0xa4, 0x8f, 0x40, 0xc2, 0x20, 0x12, 0x43, 0xc2, 0x8a, 0xa0, 0x35, 0x42, 0xa4, 0x8f, 0x40, 0x42, 0x20, 0x12, 0x3d, 0xb7, 0x06, 0x37, 0xbd, 0x42, 0xa4, 0x8f, 0x40, 0x42, 0xa0, 0x12, 0x3f, 0x42, 0x8a, 0xa0, 0x33, 0x42, 0xa4, 0x8f, 0x40, 0x42, 0x20, 0x12, 0x3f, 0x42, 0x8a, 0xa0, 0x33, 0x42, 0xa4, 0x8f, 0x40, 0xc2, 0x20, 0x12, 0x3e, 0x00, 0x00, 0x00, 0x00, 0x42, 0xda, 0x0b, 0x81, 0x00, 0x00, 0x00, 0x00, 0x40, 0x50, 0x61, 0xdd, 0x00, 0x00, 0x00, 0x00, 0xc0, 0xbd, 0x7d, 0x44, 0x40, 0x50, 0x61, 0xdd, 0x00, 0x00, 0x00, 0x00, 0x40, 0xbd, 0x7d, 0x44, 0xc0, 0xa5, 0x2c, 0x52, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3d, 0xea, 0x44, 0xc8, 0x41, 0x3c, 0x67, 0x6f, 0xbe, 0x7f, 0x13, 0x8c, 0xbf, 0x5c, 0xeb, 0xbc, 0x41, 0x9e, 0x08, 0x97, 0x41, 0x09, 0x94, 0x81, 0xc1, 0x15, 0xb8, 0x96, 0x41, 0x9c, 0xac, 0xef, 0x41, 0x34, 0x4a, 0xd4, 0xc1, 0x01, 0x4e, 0x1d, 0x41, 0x9e, 0x11, 0x4d, 0x40, 0x44, 0x75, 0x2e, 0xc0, 0x0e, 0x33, 0x37, 0x41, 0x98, 0x13, 0x05, 0xc1, 0x01, 0x2a, 0x2c, 0xc1, 0x18, 0x08, 0xee, 0x41, 0x98, 0x13, 0x05, 0xc0, 0x80, 0xc7, 0x39, 0xc1, 0x06, 0xa2, 0x25, 0x41, 0x98, 0x13, 0x05, 0xc1, 0x40, 0x57, 0xb5, 0x41, 0x57, 0x63, 0xee, 0x41, 0xb0, 0x33, 0x7c, 0x3f, 0xc9, 0xad, 0xb0, 0x40, 0xb1, 0xf3, 0x9f, 0x41, 0xb0, 0x33, 0x7c, 0x40, 0x87, 0x54, 0x2a, 0x40, 0xb5, 0x00, 0x0f, 0x41, 0xb0, 0x33, 0x7c, 0xc0, 0x6f, 0xf7, 0xe4 }; +u8 l_color[0x50] = { 0x7f, 0x7f, 0x7f, 0xff, 0x98, 0x98, 0x99, 0xff, 0x99, 0x99, 0x99, 0xff, 0xcc, 0xcc, 0xcc, 0xff, 0xff, 0xff, 0xff, 0xff, 0x66, 0x66, 0x66, 0xff, 0xb2, 0xb2, 0xb2, 0xff, 0xe5, 0xe5, 0xe5, 0xff, 0xf4, 0xf4, 0xf4, 0xff, 0xab, 0xab, 0xab, 0xff, 0xfc, 0xfc, 0xfc, 0xff, 0xf7, 0xf7, 0xf7, 0xff, 0xf8, 0xf8, 0xf8, 0xff, 0xc3, 0xc3, 0xc3, 0xff, 0xa1, 0xa1, 0xa1, 0xff, 0xf5, 0xf5, 0xf5, 0xff, 0xfb, 0xfb, 0xfb, 0xff, 0x73, 0x73, 0x73, 0xff, 0x43, 0x43, 0x43, 0xff, 0x9a, 0x9a, 0x9a, 0xff }; +u8 l_texCoord[0x50] = { 0x3f, 0x00, 0x00, 0x00, 0x3f, 0x80, 0x00, 0x00, 0x3f, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3f, 0x80, 0x00, 0x00, 0x3e, 0xe9, 0x5d, 0xb3, 0x3f, 0x80, 0x00, 0x00, 0x3f, 0x40, 0x00, 0x00, 0x3f, 0x34, 0xae, 0xda, 0x3f, 0x40, 0x00, 0x00, 0x3f, 0x75, 0x5e, 0x6c, 0x3f, 0x80, 0x00, 0x00, 0x3f, 0x4a, 0xf9, 0x55, 0x3f, 0x40, 0x00, 0x00, 0x3f, 0x75, 0x5e, 0x6c, 0x3f, 0x40, 0x00, 0x00, 0x3f, 0x4a, 0xf9, 0x55, 0x3f, 0x80, 0x00, 0x00 }; +u8 l_Oba_swood_bDL[0x11c] ALIGN_DECL(32) = { 0x98, 0x00, 0x05, 0x2a, 0x07, 0x02, 0x2f, 0x07, 0x01, 0x30, 0x07, 0x00, 0x2e, 0x07, 0x02, 0x2d, 0x07, 0x01, 0x98, 0x00, 0x05, 0x2d, 0x07, 0x01, 0x2c, 0x07, 0x02, 0x30, 0x07, 0x00, 0x2b, 0x07, 0x01, 0x2a, 0x07, 0x02, 0x98, 0x00, 0x05, 0x23, 0x06, 0x02, 0x28, 0x06, 0x01, 0x29, 0x06, 0x00, 0x27, 0x06, 0x02, 0x26, 0x06, 0x01, 0x98, 0x00, 0x05, 0x26, 0x06, 0x01, 0x25, 0x06, 0x02, 0x29, 0x06, 0x00, 0x24, 0x06, 0x01, 0x23, 0x06, 0x02, 0x98, 0x00, 0x05, 0x1c, 0x05, 0x02, 0x21, 0x05, 0x01, 0x22, 0x05, 0x00, 0x20, 0x05, 0x02, 0x1f, 0x05, 0x01, 0x98, 0x00, 0x05, 0x1f, 0x05, 0x01, 0x1e, 0x05, 0x02, 0x22, 0x05, 0x00, 0x1d, 0x05, 0x01, 0x1c, 0x05, 0x02, 0x98, 0x00, 0x05, 0x15, 0x04, 0x02, 0x1a, 0x04, 0x01, 0x1b, 0x04, 0x00, 0x19, 0x04, 0x02, 0x18, 0x04, 0x01, 0x98, 0x00, 0x05, 0x18, 0x04, 0x01, 0x17, 0x04, 0x02, 0x1b, 0x04, 0x00, 0x16, 0x04, 0x01, 0x15, 0x04, 0x02, 0x98, 0x00, 0x05, 0x0e, 0x03, 0x02, 0x13, 0x03, 0x01, 0x14, 0x03, 0x00, 0x12, 0x03, 0x02, 0x11, 0x03, 0x01, 0x98, 0x00, 0x05, 0x11, 0x03, 0x01, 0x10, 0x03, 0x02, 0x14, 0x03, 0x00, 0x0f, 0x03, 0x01, 0x0e, 0x03, 0x02, 0x98, 0x00, 0x05, 0x07, 0x02, 0x02, 0x0c, 0x02, 0x01, 0x0d, 0x01, 0x00, 0x0b, 0x02, 0x02, 0x0a, 0x02, 0x01, 0x98, 0x00, 0x05, 0x0a, 0x02, 0x01, 0x09, 0x02, 0x02, 0x0d, 0x01, 0x00, 0x08, 0x02, 0x01, 0x07, 0x02, 0x02, 0x98, 0x00, 0x05, 0x00, 0x00, 0x02, 0x05, 0x00, 0x01, 0x06, 0x00, 0x00, 0x04, 0x00, 0x02, 0x03, 0x00, 0x01, 0x98, 0x00, 0x05, 0x03, 0x00, 0x01, 0x02, 0x00, 0x02, 0x06, 0x00, 0x00, 0x01, 0x00, 0x01, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }; +u8 l_Oba_swood_b_cutDL[0xcb] ALIGN_DECL(32) = { 0x98, 0x00, 0x04, 0x31, 0x13, 0x06, 0x32, 0x11, 0x09, 0x3b, 0x0d, 0x08, 0x3c, 0x0b, 0x07, 0x98, 0x00, 0x04, 0x3b, 0x0d, 0x07, 0x3d, 0x0c, 0x08, 0x31, 0x13, 0x09, 0x34, 0x00, 0x06, 0x98, 0x00, 0x04, 0x31, 0x13, 0x06, 0x34, 0x00, 0x09, 0x38, 0x0a, 0x08, 0x39, 0x08, 0x07, 0x98, 0x00, 0x04, 0x33, 0x12, 0x06, 0x31, 0x13, 0x09, 0x3a, 0x09, 0x08, 0x38, 0x0a, 0x07, 0x98, 0x00, 0x04, 0x3a, 0x09, 0x07, 0x39, 0x08, 0x08, 0x33, 0x12, 0x09, 0x34, 0x00, 0x06, 0x98, 0x00, 0x04, 0x36, 0x0e, 0x08, 0x33, 0x12, 0x06, 0x37, 0x0f, 0x07, 0x34, 0x00, 0x09, 0x98, 0x00, 0x04, 0x33, 0x12, 0x09, 0x36, 0x0e, 0x07, 0x32, 0x11, 0x06, 0x35, 0x10, 0x08, 0x98, 0x00, 0x04, 0x32, 0x11, 0x06, 0x34, 0x00, 0x09, 0x3c, 0x0b, 0x08, 0x3d, 0x0c, 0x07, 0x98, 0x00, 0x04, 0x32, 0x11, 0x09, 0x35, 0x10, 0x07, 0x34, 0x00, 0x06, 0x37, 0x0f, 0x08, 0x98, 0x00, 0x03, 0x36, 0x0e, 0x03, 0x37, 0x0f, 0x04, 0x35, 0x10, 0x05, 0x98, 0x00, 0x03, 0x3c, 0x0b, 0x03, 0x3d, 0x0c, 0x04, 0x3b, 0x0d, 0x05, 0x98, 0x00, 0x03, 0x39, 0x08, 0x03, 0x3a, 0x09, 0x04, 0x38, 0x0a, 0x05, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }; +u8 l_matDL[0xa3] ALIGN_DECL(32) = { 0x61, 0x80, 0x00, 0x01, 0x3a, 0x61, 0x84, 0x00, 0x00, 0x00, 0x61, 0x88, 0xe0, 0xfc, 0x3f, 0x61, 0x94, ((int)l_Txa_swood_bTEX >> 21) & 0xFF, ((int)l_Txa_swood_bTEX >> 13) & 0xFF, ((int)l_Txa_swood_bTEX >> 5) & 0xFF, 0x61, 0x30, 0x00, 0x00, 0x40, 0x61, 0x31, 0x00, 0x00, 0x40, 0x10, 0x00, 0x00, 0x10, 0x40, 0xff, 0xff, 0x42, 0x80, 0x08, 0x30, 0x3c, 0xf3, 0xcf, 0x00, 0x10, 0x00, 0x00, 0x10, 0x18, 0x3c, 0xf3, 0xcf, 0x00, 0x10, 0x00, 0x00, 0x10, 0x0e, 0x00, 0x00, 0x05, 0x43, 0x61, 0x28, 0x3c, 0x00, 0x00, 0x61, 0xc0, 0x08, 0x24, 0xaf, 0x61, 0xc1, 0x08, 0xff, 0xf0, 0x61, 0x28, 0x3c, 0x00, 0x00, 0x61, 0xc2, 0x08, 0xf0, 0x8f, 0x61, 0xc3, 0x08, 0xee, 0x70, 0x61, 0x40, 0x00, 0x00, 0x17, 0x61, 0xf3, 0x64, 0x00, 0x00, 0x61, 0xf3, 0x64, 0xfe, 0xfe, 0x10, 0x00, 0x00, 0x10, 0x3f, 0x00, 0x00, 0x00, 0x01, 0x10, 0x00, 0x00, 0x10, 0x09, 0x00, 0x00, 0x00, 0x01, 0x61, 0x00, 0x00, 0x04, 0x11, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }; + +// .rodata +const Attr_c L_attr = { + {{{ + 0x00C8, + 0x50, + 0x5DC, + 0x32, + 0.6 + }, { + 0x00B4, + 0x1E, + 0xC80, + 0xA, + 0.2, + }}, {{ + 0x01f4, + 0x96, + 0x4B0, + 0x96, + 0.6, + }, { + 0x02BC, + 0x32, + 0x898, + 0x1E, + 0.2, + }}, {{ + 0x0258, + 0xC8, + 0x898, + 0x12C, + 0.6, + }, { + 0x01BC, + 0x1E, + 0xFA0, + 0x32, + 0.2, + }}, {{ + 0x0258, + 0xC8, + 0x1838, + 0x1F4, + 0.6, + }, { + 0x01BC, + 0x1E, + 0x3E8, + 0x32, + 0.2, + }} + }, 0x14, 0x14, 0x0e, 18.0f, -3.0f, 2.5f, 200, 1.5f, 0.3f, 80.0f, 15.0f, 80.0f, 15.0f, 100.0f, 40.0f, 0x23, 0x80 +}; +} // namespace +} // namespace dWood + +//----------------------------------------- +// Constants +//----------------------------------------- +const s32 L_Room_Max = 64; +const float l_Ground_check_y_offset = 100.0f; +const double l_Ground_check_unk1 = 0.5; +const double l_Ground_check_unk2 = 3.0; +const float kGroundHeightBias = 1.0f; + +const u32 l_Oba_swood_bDL_SIZE = 0x100; +const u32 l_Oba_swood_b_cutDL_SIZE = 0xc0; + +s32 dWood::Anm_c::M_init_num = 0; + +//----------------------------------------- +// Helpers +//----------------------------------------- +namespace { +inline const Attr_c &attr() { return dWood::L_attr; } + +inline const AttrSway_c &attr_sway(AttrSway_e swayID, int idx) { + return attr().kSways[swayID][idx]; +} +} // namespace + +//----------------------------------------- +// Classes +//----------------------------------------- /* 800BD678-800BD710 .text __ct__Q25dWood5Anm_cFv */ dWood::Anm_c::Anm_c() { - /* Nonmatching */ + MTXIdentity(mModelMtx); + MTXIdentity(mTrunkModelMtx); + mMode = Mode_Max; + mCountdown = 0; + mForceDir = 0; + mWindPow = 0.0f; + mPosOffsetY = 0.0f; + mPosOffsetZ = 0.0f; + mVelY = 0.0f; + + for (u32 i = 0; i < 2; i++) { + mPhaseY[i] = 0; + mPhaseX[i] = 0; + mAmpY[i] = 0; + mAmpX[i] = 0; + } + + mNormAnimIdx = AnmID_Norm0; + mAlphaScale = 0xff; + return; } /* 800BD710-800BD800 .text play__Q25dWood5Anm_cFPQ25dWood8Packet_c */ -void dWood::Anm_c::play(dWood::Packet_c*) { - /* Nonmatching */ +void dWood::Anm_c::play(dWood::Packet_c *i_packet) { + if (mMode != Mode_Max) { + static modeProcFunc mode_proc[] = { + &dWood::Anm_c::mode_cut, &dWood::Anm_c::mode_push_into, + &dWood::Anm_c::mode_push_back, &dWood::Anm_c::mode_fan, + &dWood::Anm_c::mode_norm, &dWood::Anm_c::mode_to_norm, + }; + (this->*mode_proc[mMode])(i_packet); + } + return; } /* 800BD800-800BD848 .text copy_angamp__Q25dWood5Anm_cFPCQ25dWood5Anm_c */ -void dWood::Anm_c::copy_angamp(const dWood::Anm_c*) { - /* Nonmatching */ -} - -/* 800BD848-800BD8BC .text mode_cut_init__Q25dWood5Anm_cFPCQ25dWood5Anm_cs */ -void dWood::Anm_c::mode_cut_init(const dWood::Anm_c*, short) { - /* Nonmatching */ +void dWood::Anm_c::copy_angamp(const dWood::Anm_c *other) { + if (this == other) { + return; + } + + for (u32 i = 0; i < 2; i++) { + mPhaseY[i] = other->mPhaseY[i]; + mPhaseX[i] = other->mPhaseX[i]; + mAmpY[i] = other->mAmpY[i]; + mAmpX[i] = other->mAmpX[i]; + } +} + +/* 800BD848-800BD8BC .text mode_cut_init__Q25dWood5Anm_cFPCQ25dWood5Anm_cs + */ +void dWood::Anm_c::mode_cut_init(const dWood::Anm_c *, short targetAngle) { + for (u32 i = 0; i < 2; i++) { + mPhaseY[i] = 0; + mPhaseX[i] = 0; + mAmpY[i] = 0; + mAmpX[i] = 0; + } + + mForceDir = targetAngle; + mVelY = L_attr.kCutInitVelY; + mPosOffsetY = 0.0f; + mPosOffsetZ = 0.0f; + mAlphaScale = 0xff; + mCountdown = L_attr.kCutCooldown; + mMode = Anm_c::Mode_Cut; } /* 800BD8BC-800BD9E4 .text mode_cut__Q25dWood5Anm_cFPQ25dWood8Packet_c */ -void dWood::Anm_c::mode_cut(dWood::Packet_c*) { - /* Nonmatching */ +void dWood::Anm_c::mode_cut(dWood::Packet_c *) { + mVelY = mVelY + L_attr.kCutYAccel; + if (mVelY < -40.0f) { + mVelY = -40.0f; + } + + mPosOffsetY = mPosOffsetY + mVelY; + mPosOffsetZ = mPosOffsetZ + L_attr.kCutZVel; + mPhaseX[0] = mPhaseX[0] - L_attr.kCutPitchVel; + + mDoMtx_YrotS(mDoMtx_stack_c::now, (int)mForceDir); + mDoMtx_stack_c::transM(0.0f, mPosOffsetY, mPosOffsetZ); + mDoMtx_XrotM(mDoMtx_stack_c::now, mPhaseX[0]); + mDoMtx_YrotM(mDoMtx_stack_c::now, -mForceDir); + mDoMtx_copy(mDoMtx_stack_c::now, mModelMtx); + + // Fade out the bush as it falls + if (mCountdown < attr().kCutFadeStart) { + int alphaScale = mAlphaScale; + alphaScale -= attr().kCutAlphaFadeSpeed; + if (alphaScale < 0) { + alphaScale = 0; + } + mAlphaScale = (u8)alphaScale; + } + + if ((s32)mCountdown > 0) { + mCountdown = mCountdown + -1; + } } /* 800BD9E4-800BDA38 .text mode_push_into_init__Q25dWood5Anm_cFPCQ25dWood5Anm_cs */ -void dWood::Anm_c::mode_push_into_init(const dWood::Anm_c*, short) { - /* Nonmatching */ +void dWood::Anm_c::mode_push_into_init(const dWood::Anm_c *anm, + short targetAngle) { + copy_angamp(anm); + mForceDir = targetAngle; + mAlphaScale = 0xff; + mCountdown = 2; + mMode = Mode_PushInto; } /* 800BDA38-800BDC24 .text mode_push_into__Q25dWood5Anm_cFPQ25dWood8Packet_c */ -void dWood::Anm_c::mode_push_into(dWood::Packet_c*) { - /* Nonmatching */ +void dWood::Anm_c::mode_push_into(dWood::Packet_c *packet) { + if (--mCountdown <= 0) { + mode_push_back_init(); + } + else { + float rotY = 0.0f; + float rotX = rotY; + for (s32 i = 0; i < 2; i++) { + const AttrSway_c* sway = &attr().kSways[SWAY_PUSH][i]; + s32 phaseVelX = sway->phaseVelX; + s32 ampY = sway->ampY; + s32 ampX = sway->ampX; + float phaseBiasX = sway->phaseBiasX; + + mPhaseY[i] += sway->phaseVelY; + cLib_chaseAngleS(&mPhaseX[i], 0, phaseVelX); + cLib_chaseS(&mAmpY[i], ampY/4, 0x14); + cLib_addCalcAngleS(&mAmpX[i], ampX, 8, 0x14, 5); + + rotY += mAmpY[i] * JMASCos(mPhaseY[i]); + rotX += mAmpX[i] * (phaseBiasX + JMASCos(mPhaseX[i])); + } + + mDoMtx_YrotS(mModelMtx, (s16)rotY + mForceDir); + mDoMtx_XrotM(mModelMtx, (s32)rotX); + mDoMtx_YrotM(mModelMtx, -mForceDir); + } } /* 800BDC24-800BDC48 .text mode_push_back_init__Q25dWood5Anm_cFv */ void dWood::Anm_c::mode_push_back_init() { - /* Nonmatching */ + mCountdown = L_attr.kPushBackCountdown; + mAlphaScale = 0xff; + mMode = Mode_PushBack; } /* 800BDC48-800BDECC .text mode_push_back__Q25dWood5Anm_cFPQ25dWood8Packet_c */ -void dWood::Anm_c::mode_push_back(dWood::Packet_c*) { - /* Nonmatching */ +void dWood::Anm_c::mode_push_back(dWood::Packet_c *packet) { + if (--mCountdown <= 0) { + AnmID_e animIdx = packet->search_anm(Anm_c::Mode_Norm); + mode_to_norm_init(animIdx); + } + else { + float t = mCountdown * (1.0f / L_attr.kPushBackCountdown); + + float rotY = 0.0; + float rotX = rotY; + for (s32 i = 0; i < 2; i++) { + const AttrSway_c* sway = &attr().kSways[SWAY_PUSH][i]; + s32 phaseVelX = sway->phaseVelX; + s16 ampY = t * sway->ampY; + s16 ampX = t * sway->ampX; + float phaseBiasX = sway->phaseBiasX; + + mPhaseY[i] += sway->phaseVelY; + mPhaseX[i] += phaseVelX; + cLib_chaseS(&mAmpY[i], (s32)ampY, 0x14); + cLib_chaseS(&mAmpX[i], (s32)ampX, 0x14); + + rotY += mAmpY[i] * JMASCos(mPhaseY[i]); + rotX += mAmpX[i] * (phaseBiasX + JMASCos(mPhaseX[i])); + } + + mDoMtx_YrotS(mModelMtx, (s16)rotY + mForceDir); + mDoMtx_XrotM(mModelMtx, (s32)rotX); + mDoMtx_YrotM(mModelMtx, -mForceDir); + } } /* 800BDECC-800BDED0 .text mode_fan__Q25dWood5Anm_cFPQ25dWood8Packet_c */ -void dWood::Anm_c::mode_fan(dWood::Packet_c*) { - /* Nonmatching */ -} +void dWood::Anm_c::mode_fan(dWood::Packet_c *) {} /* 800BDED0-800BDF5C .text mode_norm_init__Q25dWood5Anm_cFv */ void dWood::Anm_c::mode_norm_init() { - /* Nonmatching */ + mMode = Mode_Norm; + + for (u32 i = 0; i < 2; i++) { + mPhaseY[i] = M_init_num * 0x2000; + mPhaseX[i] = M_init_num * 0x2000; + mAmpY[i] = attr_sway(SWAY_LIGHT, i).ampY; + mAmpX[i] = attr_sway(SWAY_LIGHT, i).ampX; + } + + mAlphaScale = 0xff; + + M_init_num++; + M_init_num = M_init_num % 8; } /* 800BDF5C-800BE148 .text mode_norm__Q25dWood5Anm_cFPQ25dWood8Packet_c */ -void dWood::Anm_c::mode_norm(dWood::Packet_c*) { - /* Nonmatching */ +void dWood::Anm_c::mode_norm(dWood::Packet_c *packet) { + AttrSway_e swayID; + if (mWindPow < 0.33f) { + swayID = SWAY_LIGHT; + } else { + if (mWindPow < 0.66f) { + swayID = SWAY_MEDIUM; + } else { + swayID = SWAY_STRONG; + } + } + + float rotY = 0.0f; + float rotX = rotY; + for (s32 i = 0; i < 2; i++) { + const AttrSway_c *sway = &attr_sway(swayID, i); + s32 phaseVelX = sway->phaseVelX; + s16 ampY = sway->ampY; + s16 ampX = sway->ampX; + float phaseBiasX = sway->phaseBiasX; + + mPhaseY[i] += sway->phaseVelY; + mPhaseX[i] += phaseVelX; + cLib_chaseS(&mAmpY[i], ampY, 2); + cLib_chaseS(&mAmpX[i], ampX, 2); + + rotY += mAmpY[i] * JMASCos(mPhaseY[i]); + rotX += mAmpX[i] * (phaseBiasX + JMASCos(mPhaseX[i])); + } + + mDoMtx_YrotS(mModelMtx, (s16)rotY + mForceDir); // Y Rotation (Yaw) + mDoMtx_XrotM(mModelMtx, rotX); // X Rotation + mDoMtx_YrotM(mModelMtx, -mForceDir); // Y Rotation } /* 800BE148-800BE154 .text mode_norm_set_wind__Q25dWood5Anm_cFfs */ -void dWood::Anm_c::mode_norm_set_wind(float, short) { - /* Nonmatching */ +void dWood::Anm_c::mode_norm_set_wind(float windPow, short windDir) { + mWindPow = windPow; + mForceDir = windDir; } - /* 800BE154-800BE1F0 .text mode_to_norm_init__Q25dWood5Anm_cFQ25dWood7AnmID_e */ -void dWood::Anm_c::mode_to_norm_init(dWood::AnmID_e) { - /* Nonmatching */ +void dWood::Anm_c::mode_to_norm_init(dWood::AnmID_e anm_id_norm) { + JUT_ASSERT(0x4d7, (anm_id_norm >= 0) && (anm_id_norm < AnmID_Norm_Max)); + + mode_to_norm_set_AnmID(anm_id_norm); + mAlphaScale = 0xff; + mCountdown = 0x14; + mMode = Anm_c::Mode_ToNorm; } /* 800BE1F0-800BE428 .text mode_to_norm__Q25dWood5Anm_cFPQ25dWood8Packet_c */ -void dWood::Anm_c::mode_to_norm(dWood::Packet_c*) { - /* Nonmatching */ +void dWood::Anm_c::mode_to_norm(dWood::Packet_c *packet) { + const Anm_c *normAnim = packet->get_anm_p(mode_to_norm_get_AnmID()); + + AttrSway_e swayID; + if (normAnim->mWindPow < 0.33f) { + swayID = SWAY_LIGHT; + } else { + if (normAnim->mWindPow < 0.66f) { + swayID = SWAY_MEDIUM; + } else { + swayID = SWAY_STRONG; + } + } + + cLib_chaseAngleS(&mForceDir, normAnim->mForceDir, 3000); + + float rotY = 0.0f; + float rotX = rotY; + for (s32 i = 0; i < 2; i++) { + const AttrSway_c *sway = &attr_sway(swayID, i); + float phaseBiasX = sway->phaseBiasX; + s32 phaseVelX = sway->phaseVelX; + s16 rotXStep = phaseVelX + 3000; + + cLib_chaseS(&mPhaseY[i], normAnim->mPhaseY[i], sway->phaseVelY + 3000); + cLib_chaseS(&mPhaseX[i], normAnim->mPhaseX[i], rotXStep); + cLib_chaseS(&mAmpY[i], normAnim->mAmpY[i], 0xf); + cLib_chaseS(&mAmpX[i], normAnim->mAmpX[i], 0xf); + + rotY += mAmpY[i] * JMASCos(mPhaseY[i]); + rotX += mAmpX[i] * (phaseBiasX + JMASCos(mPhaseX[i])); + } + + mDoMtx_YrotS(mModelMtx, (s16)rotY + mForceDir); + mDoMtx_XrotM(mModelMtx, rotX); + mDoMtx_YrotM(mModelMtx, -mForceDir); + + if (mCountdown > 0) { + mCountdown -= 1; + } } /* 800BE428-800BE4DC .text __ct__Q25dWood6Unit_cFv */ dWood::Unit_c::Unit_c() { - /* Nonmatching */ + clear(); } /* 800BE4DC-800BE93C .text set_ground__Q25dWood6Unit_cFv */ -void dWood::Unit_c::set_ground() { - /* Nonmatching */ +bool dWood::Unit_c::set_ground() { + cXyz pos(mPos.x, mPos.y + l_Ground_check_y_offset, mPos.z); + + // Cast the current position to the ground + dBgS_ObjGndChk gndChk; + gndChk.SetPos(&pos); + f32 gndHeight = dComIfG_Bgsp()->GroundCross(&gndChk); + + if (gndHeight > -1000000000.0f) { + mPos.y = gndHeight; + cM3dGPla *triPla = dComIfG_Bgsp()->GetTriPla(gndChk); + + cXyz gndNorm = *triPla->GetNP(); + float unkFloat = std::sqrtf(1.0f - gndNorm.x * gndNorm.x); + + float scaledNormY; + float scaledNormZ; + if (unkFloat != 0.0f) { + scaledNormY = gndNorm.y * unkFloat; + scaledNormZ = -gndNorm.z * unkFloat; + } else { + scaledNormY = 0.0f; + scaledNormZ = 0.0f; + } + + MtxP mtx = mDoMtx_stack_c::get(); + + mtx[0][0] = unkFloat; + mtx[0][1] = gndNorm.x; + mtx[0][2] = 0.0f; + mtx[0][3] = mPos.x; + + mtx[1][0] = -gndNorm.x * scaledNormY; + mtx[1][1] = gndNorm.y; + mtx[1][2] = scaledNormZ; + mtx[1][3] = kGroundHeightBias + gndHeight; + + mtx[2][0] = gndNorm.x * scaledNormZ; + mtx[2][1] = gndNorm.z; + mtx[2][2] = scaledNormY; + mtx[2][3] = mPos.z; + mDoMtx_stack_c::scaleM(L_attr.kUncutShadowScale, kGroundHeightBias, + L_attr.kUncutShadowScale); + mDoMtx_copy(mDoMtx_stack_c::now, mShadowModelMtx); + return true; + } else { + return false; + } } /* 800BE93C-800BEA28 .text set_mtx__Q25dWood6Unit_cFPQ25dWood5Anm_c */ -void dWood::Unit_c::set_mtx(dWood::Anm_c*) { - /* Nonmatching */ +void dWood::Unit_c::set_mtx(dWood::Anm_c *anim) { + int anmIdx = mAnmIdx; + + mDoMtx_copy(anim[anmIdx].mModelMtx, mDoMtx_stack_c::get()); + mDoMtx_stack_c::now[0][3] = mDoMtx_stack_c::now[0][3] + mPos.x; + mDoMtx_stack_c::now[1][3] = mDoMtx_stack_c::now[1][3] + mPos.y; + mDoMtx_stack_c::now[2][3] = mDoMtx_stack_c::now[2][3] + mPos.z; + mDoMtx_concat(j3dSys.getViewMtx(), mDoMtx_stack_c::now, mModelViewMtx); + + mDoMtx_copy(anim[anmIdx].mTrunkModelMtx, mDoMtx_stack_c::get()); + mDoMtx_stack_c::now[0][3] = mPos.x; + mDoMtx_stack_c::now[1][3] = mPos.y; + mDoMtx_stack_c::now[2][3] = mPos.z; + mDoMtx_concat(j3dSys.getViewMtx(), mDoMtx_stack_c::get(), + mTrunkModelViewMtx); + + mDoMtx_concat(j3dSys.getViewMtx(), mShadowModelMtx, mShadowModelViewMtx); } /* 800BEA28-800BEA50 .text clear__Q25dWood6Unit_cFv */ -void dWood::Unit_c::clear() { - /* Nonmatching */ +void dWood::Unit_c::clear() { + cLib_memSet(this, 0, 0x18c); } /* 800BEA50-800BEE9C .text cc_hit_before_cut__Q25dWood6Unit_cFPQ25dWood8Packet_c */ -void dWood::Unit_c::cc_hit_before_cut(dWood::Packet_c*) { - /* Nonmatching */ +void dWood::Unit_c::cc_hit_before_cut(dWood::Packet_c *packet) { + AnmID_e animIdx; + AnmID_e oldAnimIdx; + s16 targetAngle; + + dCcMassS_HitInf inf; + fopAc_ac_c *actor; + u32 ret = dComIfG_Ccsp()->ChkMass(&mPos, &actor, &inf); + + if (mAnimCooldown > 0) { + mAnimCooldown -= 1; + } + + // Evaluate for attacks that will not cut us down + if (cLib_checkBit(ret, 0x01UL)) { + cCcD_Obj *atHitObj = inf.GetAtHitObj(); + if (atHitObj != NULL && (atHitObj->ChkAtType(AT_TYPE_WIND) || + atHitObj->ChkAtType(AT_TYPE_BOMB) || + atHitObj->ChkAtType(AT_TYPE_FIRE) || + atHitObj->ChkAtType(AT_TYPE_NORMAL_ARROW) || + atHitObj->ChkAtType(AT_TYPE_FIRE_ARROW) || + atHitObj->ChkAtType(AT_TYPE_ICE_ARROW) || + atHitObj->ChkAtType(AT_TYPE_LIGHT_ARROW) || + atHitObj->ChkAtType(AT_TYPE_HOOKSHOT))) { + + // Clear the hit bit so that we don't get cut down + ret &= ~0x01; + + if (actor != NULL && mAnimCooldown == 0) { + animIdx = packet->search_anm(Anm_c::Mode_PushInto); + mAnimCooldown = 20; + + // Play the cut sound + mDoAud_seStart(JA_SE_OBJ_TREE_SWING, &mPos, 0, 0); + + // If we are currently performing a basic animation, assign a + // new animation + oldAnimIdx = mAnmIdx; + if ((oldAnimIdx < 8) && (animIdx != AnmID_Norm_Invalid)) { + mAnmIdx = animIdx; + } + + // If we were able to allocate an animation (or we already have + // one), start the "PushInto" (shrinking) animation + if ((mAnmIdx >= 8) && packet->get_anm_p(mAnmIdx)->get_mode() >= + Anm_c::Mode_PushInto) { + targetAngle = cLib_targetAngleY(&actor->current.pos, &mPos); + packet->get_anm_p(mAnmIdx)->mode_push_into_init( + packet->mAnm + oldAnimIdx, (s32)targetAngle); + } + } + } + } + + // Check for collisions that are not attacks + if (cLib_checkBit(ret, 0x02UL) && actor && inf.GetCoHitObj() && + inf.GetCoHitObj()->GetStts()) { + animIdx = packet->search_anm(Anm_c::Mode_PushInto); + + if (fopAcM_GetProfName(actor) == PROC_PLAYER && + inf.GetCoHitLen() >= 2.0f && mAnimCooldown == 0) { + + mAnimCooldown = 20; + mDoAud_seStart(JA_SE_OBJ_TREE_SWING, &mPos, 0, 0); + + // If we are currently performing a basic animation, assign a new + // animation + oldAnimIdx = mAnmIdx; + if ((oldAnimIdx < 8) && (animIdx != AnmID_Norm_Invalid)) { + mAnmIdx = animIdx; + } + + // If we were able to allocate an animation (or we already have + // one), start the "PushInto" (shrinking) animation + if ((mAnmIdx >= 8) && (packet->get_anm_p(mAnmIdx)->get_mode() >= + Anm_c::Mode_PushInto)) { + targetAngle = cLib_targetAngleY(&actor->current.pos, &mPos); + packet->get_anm_p(mAnmIdx)->mode_push_into_init( + packet->mAnm + oldAnimIdx, (s32)targetAngle); + } + } + } + + // Check for attacks that WILL cut us down + if (cLib_checkBit(ret, 0x01UL)) { + AnmID_e oldAnimIdx = mAnmIdx; + + if ((mAnmIdx < 8)) { + animIdx = packet->search_anm(Anm_c::Mode_Cut); + if (animIdx != AnmID_Norm_Invalid) { + mAnmIdx = animIdx; + } + } + + if ((mAnmIdx >= 8)) { + if (packet->get_anm_p(mAnmIdx)->get_mode() > Anm_c::Mode_Cut) { + targetAngle = cLib_targetAngleY(&actor->current.pos, &mPos); + packet->get_anm_p(mAnmIdx)->mode_cut_init( + packet->get_anm_p(oldAnimIdx), (s32)targetAngle); + + // Compute the color settings for particels + g_env_light.settingTevStruct(TEV_TYPE_BG0, &mPos, &mTevStr); + + // Spawn cut down particles (a bunch of leaves) + dComIfGp_particle_set(dPa_name::ID_CUT_L_TREE_DOWN, &mPos, NULL, + NULL, 0xff, NULL, -1, &mTevStr.mColorK0, + NULL, NULL); + + mDoAud_seStart(JA_SE_OBJ_CUT_L_TREE_DOWN, &mPos, 0, 0); + + float newShadowScale = + L_attr.kCutShadowScale / L_attr.kUncutShadowScale; + + mDoMtx_copy(mShadowModelMtx, mDoMtx_stack_c::get()); + mDoMtx_stack_c::scaleM(newShadowScale, 1.0f, newShadowScale); + mDoMtx_copy(mDoMtx_stack_c::get(), mShadowModelMtx); + } + } + } } /* 800BEE9C-800BEEA0 .text cc_hit_after_cut__Q25dWood6Unit_cFPQ25dWood8Packet_c */ -void dWood::Unit_c::cc_hit_after_cut(dWood::Packet_c*) { - /* Nonmatching */ -} +void dWood::Unit_c::cc_hit_after_cut(dWood::Packet_c *) {} /* 800BEEA0-800BEF78 .text proc__Q25dWood6Unit_cFPQ25dWood8Packet_c */ -void dWood::Unit_c::proc(dWood::Packet_c*) { - /* Nonmatching */ +void dWood::Unit_c::proc(dWood::Packet_c *packet) { + // If this unit is active, and performing a non-normal animation... + if (cLib_checkBit(mFlags, STATE_ACTIVE)) { + AnmID_e animIdx = mAnmIdx; + + if (animIdx >= 8) { + Anm_c *anim = packet->get_anm_p(animIdx); + Anm_c::Mode_e mode = anim->mMode; + if (mode == Anm_c::Mode_ToNorm) { + if (anim->mCountdown <= 0) { + mAnmIdx = anim->mode_to_norm_get_AnmID(); + anim->mMode = Anm_c::Mode_Max; + } + } else if (mode == Anm_c::Mode_Cut) { + if (anim->mCountdown <= 0) { + AnmID_e newAnimIdx = packet->search_anm(Anm_c::Mode_Norm); + mAnmIdx = newAnimIdx; + anim->mMode = Anm_c::Mode_Max; + cLib_onBit(mFlags, STATE_CUT); + } + } else if (mode == Anm_c::Mode_Max) { + animIdx = packet->search_anm(Anm_c::Mode_Norm); + mAnmIdx = animIdx; + } + } + } } /* 800BEF78-800BEF84 .text __ct__Q25dWood6Room_cFv */ -dWood::Room_c::Room_c() { - /* Nonmatching */ +dWood::Room_c::Room_c() { + mpUnit = NULL; } -/* 800BEF84-800BEF94 .text entry_unit__Q25dWood6Room_cFPQ25dWood6Unit_c */ -void dWood::Room_c::entry_unit(dWood::Unit_c*) { - /* Nonmatching */ +/* 800BEF84-800BEF94 .text entry_unit__Q25dWood6Room_cFPQ25dWood6Unit_c + */ +void dWood::Room_c::entry_unit(dWood::Unit_c *unit) { + unit->mpNext = mpUnit; + mpUnit = unit; + return; } /* 800BEF94-800BEFF0 .text delete_all_unit__Q25dWood6Room_cFv */ void dWood::Room_c::delete_all_unit() { - /* Nonmatching */ + Unit_c *unit; + while (unit = mpUnit, unit != NULL) { + mpUnit = unit->mpNext; + mDoAud_zelAudio_c::getInterface()->seDeleteObject((Vec *)unit); + unit->clear(); + } } /* 800BEFF0-800BF0D4 .text __ct__Q25dWood8Packet_cFv */ dWood::Packet_c::Packet_c() { - /* Nonmatching */ + for (s32 i = 0; i < 8; i++) { + mAnm[i].mode_norm_init(); + } } -/* 800BF0D4-800BF110 .text __dt__Q25dWood6Unit_cFv */ -dWood::Unit_c::~Unit_c() { - /* Nonmatching */ -} - -/* 800BF110-800BF194 .text __dt__Q25dWood8Packet_cFv */ -dWood::Packet_c::~Packet_c() { - /* Nonmatching */ -} +dWood::Packet_c::~Packet_c() {}; /* 800BF194-800BF1C8 .text delete_room__Q25dWood8Packet_cFi */ -void dWood::Packet_c::delete_room(int) { - /* Nonmatching */ +void dWood::Packet_c::delete_room(int room_no) { + mRoom[room_no].delete_all_unit(); } /* 800BF1C8-800BF2D4 .text put_unit__Q25dWood8Packet_cFRC4cXyzi */ -void dWood::Packet_c::put_unit(const cXyz&, int) { - /* Nonmatching */ +s32 dWood::Packet_c::put_unit(const cXyz &pos, int room_no) { + JUT_ASSERT(0x6e0, (room_no >= 0) && (room_no < L_Room_Max)); + + const s32 unitCount = ARRAY_SIZE(mUnit); + s32 unitIdx = search_empty_UnitID(); + if (unitIdx != unitCount) { + Unit_c *unit = &mUnit[unitIdx]; + cLib_setBit(unit->mFlags, Unit_c::STATE_ACTIVE); + unit->mPos.x = pos.x; + unit->mPos.y = pos.y; + unit->mPos.z = pos.z; + unit->mAnmIdx = search_anm(Anm_c::Mode_Norm); + s8 valid = unit->set_ground(); + if (valid & 0xff) { + mRoom[room_no].entry_unit(unit); + } else { + unit->clear(); + } + } + return unitIdx; } /* 800BF2D4-800BF404 .text calc_cc__Q25dWood8Packet_cFv */ +// Collision Calculations void dWood::Packet_c::calc_cc() { - /* Nonmatching */ + int roomIdx = dComIfGp_roomControl_getStayNo(); + + if ((roomIdx >= 0) && (roomIdx < (s32)ARRAY_SIZE(mRoom))) { + dComIfG_Ccsp()->SetMassAttr(L_attr.kCollisionRad, + L_attr.kCollisionHeight, (u8)0x13, 1); + + Room_c *room = &mRoom[roomIdx]; + for (Unit_c *unit = room->mpUnit; unit != NULL; unit = unit->mpNext) { + if (!cLib_checkBit(unit->mFlags, Unit_c::STATE_CUT)) { + unit->cc_hit_before_cut(this); + } + } + + dComIfG_Ccsp()->SetMassAttr(L_attr.kCollisionRadCut, + L_attr.kCollisionHeightCut, (u8)0x12, 1); + for (Unit_c *unit = room->mpUnit; unit != NULL; unit = unit->mpNext) { + if (cLib_checkBit(unit->mFlags, Unit_c::STATE_CUT)) { + unit->cc_hit_after_cut(this); + } + } + } } /* 800BF404-800BF4EC .text calc__Q25dWood8Packet_cFv */ void dWood::Packet_c::calc() { - /* Nonmatching */ + calc_cc(); + + cXyz *windDir = dKyw_get_wind_vec(); + float windVel = dKyw_get_wind_pow(); + s16 windAngle = cM_atan2s(windDir->x, windDir->z); + + for (s32 i = 0; i < (s32)8; i++) { + mAnm[i].mode_norm_set_wind(windVel, (s32)windAngle); + } + + for (s32 i = 0; i < (s32)ARRAY_SIZE(mAnm); i++) { + mAnm[i].play(this); + } + + for (s32 i = 0; i < (s32)ARRAY_SIZE(mUnit); i++) { + mUnit[i].proc(this); + } } /* 800BF4EC-800BF614 .text update__Q25dWood8Packet_cFv */ void dWood::Packet_c::update() { - /* Nonmatching */ + s32 i = 0; + for (Unit_c *unit = mUnit; i < (s32)ARRAY_SIZE(mUnit); i++, unit++) { + if (cLib_checkBit(unit->mFlags, Unit_c::STATE_ACTIVE)) { + cXyz clipPos(unit->mPos.x, unit->mPos.y + L_attr.kClipCenterYOffset, + unit->mPos.z); + s32 res = mDoLib_clipper::clip(j3dSys.getViewMtx(), clipPos, + L_attr.kClipRadius); + + if (res != 0) { + cLib_onBit(unit->mFlags, Unit_c::STATE_FRUSTUM_CULLED); + } else { + cLib_offBit(unit->mFlags, Unit_c::STATE_FRUSTUM_CULLED); + unit->set_mtx(mAnm); + } + } + } + + dComIfGd_setXluListBG(); + j3dSys.getDrawBuffer(0)->entryImm(this, 0); + dComIfGd_setXluList(); } /* 800BF614-800BF900 .text draw__Q25dWood8Packet_cFv */ void dWood::Packet_c::draw() { - /* Nonmatching */ + u8 bVar1; + int iVar2; + int iVar3; + uint uVar4; + int iVar6; + int iVar7; + GXColor local_48; + GXColor local_44; + GXColor local_40; + GXColor local_38; + GXColorS10 local_30; + + static GXVtxDescList l_shadowVtxDescList[] = { + {GX_VA_POS, GX_INDEX8}, + {GX_VA_TEX0, GX_INDEX8}, + {GX_VA_NULL, GX_NONE}, + }; + static GXVtxAttrFmtList l_shadowVtxAttrFmtList[] = { + {GX_VA_POS, GX_CLR_RGBA, GX_RGB8}, + {GX_VA_TEX0, GX_CLR_RGBA, GX_RGB8}, + {GX_VA_NULL, GX_CLR_RGBA, GX_RGB8}, + }; + static GXVtxDescList l_vtxDescList[] = { + {GX_VA_POS, GX_INDEX8}, + {GX_VA_CLR0, GX_INDEX8}, + {GX_VA_TEX0, GX_INDEX8}, + {GX_VA_NULL, GX_NONE}, + }; + static GXVtxAttrFmtList l_vtxAttrFmtList[] = { + {GX_VA_POS, GX_CLR_RGBA, GX_F32}, + {GX_VA_CLR0, GX_CLR_RGBA, GX_RGBA8}, + {GX_VA_TEX0, GX_CLR_RGBA, GX_F32}, + {GX_VA_NULL, GX_CLR_RGBA, GX_RGB8}, + }; + static GXColor l_shadowColor = {0x00, 0x00, 0x00, 0x64}; + + // Assign the shadow material and draw state + GFSetVtxDescv(l_shadowVtxDescList); + GFSetVtxAttrFmtv(GX_VTXFMT0, l_shadowVtxAttrFmtList); + GFSetArray(GX_VA_POS, g_dTree_shadowPos, 3); + GFSetArray(GX_VA_TEX0, g_dTree_shadowTexCoord, 2); + dKy_GxFog_set(); + GXCallDisplayList(g_dTree_shadowMatDL, g_dTree_shadowMatDL_SIZE & ~0b11111); + GFSetTevColor(GX_TEVREG0, l_shadowColor); + + // Draw the drop shadows for each active unit + Room_c* room; + int i; + + for (i = 0, room = mRoom; i < (s32)ARRAY_SIZE(mRoom); room++, i++) { + for (Unit_c *data = room->mpUnit; data != NULL; data = data->mpNext) { + if (!cLib_checkBit(data->mFlags, Unit_c::STATE_FRUSTUM_CULLED)) { + GFLoadPosMtxImm(data->mShadowModelViewMtx, 0); + GXCallDisplayList(g_dTree_Oba_kage_32DL, g_dTree_Oba_kage_32DL_SIZE & ~0b11111); // This is probably an inline + } + } + } + + // Assign the body and trunk material and draw state + GXColor alphaColor = {0xff, 0xff, 0xff, 0xff}; + GFSetVtxDescv(l_vtxDescList); + GFSetVtxAttrFmtv(GX_VTXFMT0, l_vtxAttrFmtList); + GFSetArray(GX_VA_POS, l_pos, 0xc); + GFSetArray(GX_VA_CLR0, l_color, 4); + GFSetArray(GX_VA_TEX0, l_texCoord, 8); + GXCallDisplayList(l_matDL, 0xa0); + GFSetAlphaCompare(GX_GREATER, L_attr.L_Alpha_Cutoff, GX_AOP_OR, GX_GREATER, + L_attr.L_Alpha_Cutoff); + GFSetTevColor(GX_TEVREG2, alphaColor); + + // Draw the trunk and body for each active unit + for (i = 0, room = mRoom; i < (s32)ARRAY_SIZE(mRoom); i++, room++) { + dKy_tevstr_c *tevStr = dComIfGp_roomControl_getTevStr(i); + GFSetTevColorS10(GX_TEVREG0, tevStr->mColorC0); + GFSetTevColor(GX_TEVREG1, tevStr->mColorK0); + + dKy_GfFog_tevstr_set(tevStr); + + for (Unit_c *data = room->mpUnit; data != NULL; data = data->mpNext) { + if (!cLib_checkBit(data->mFlags, Unit_c::STATE_FRUSTUM_CULLED)) { + if (!cLib_checkBit(data->mFlags, Unit_c::STATE_CUT)) { + u32 alphaScale = mAnm[data->mAnmIdx].mAlphaScale; + alphaColor.a = alphaScale; + bool fading = alphaColor.a != 0xff; + + if (fading) { + GFSetAlphaCompare(GX_GREATER, 0, GX_AOP_OR, GX_GREATER, + 0); // Disable Alpha Test + } + GFSetTevColor(GX_TEVREG2, alphaColor); + GFLoadPosMtxImm(data->mModelViewMtx, 0); + GXCallDisplayList(l_Oba_swood_bDL, l_Oba_swood_bDL_SIZE); + + if (fading) { + GFSetAlphaCompare( + GX_GREATER, L_attr.L_Alpha_Cutoff, GX_AOP_OR, + GX_GREATER, + L_attr.L_Alpha_Cutoff); // Alpha Test < 50% + } + alphaColor.a = 0xff; + GFSetTevColor(GX_TEVREG2, alphaColor); + } + GFLoadPosMtxImm(data->mTrunkModelViewMtx, 0); + GXCallDisplayList(l_Oba_swood_b_cutDL, l_Oba_swood_b_cutDL_SIZE); + } + } + } + J3DShape::sOldVcdVatCmd = 0; } /* 800BF900-800BF938 .text search_empty_UnitID__Q25dWood8Packet_cCFv */ -void dWood::Packet_c::search_empty_UnitID() const { - /* Nonmatching */ +s32 dWood::Packet_c::search_empty_UnitID() const { + const Unit_c *unit; + int idx = 0; + unit = mUnit; + + for (s32 i = 0; i < ARRAY_SIZE(mUnit); i++) { + if ((s32)unit->mFlags == 0) { + return idx; + } + idx += 1; + unit = unit + 1; + } + + return ARRAY_SIZE(mUnit); } /* 800BF938-800BFA70 .text search_anm__Q25dWood8Packet_cFQ35dWood5Anm_c6Mode_e */ -void dWood::Packet_c::search_anm(dWood::Anm_c::Mode_e) { - /* Nonmatching */ +dWood::AnmID_e dWood::Packet_c::search_anm(dWood::Anm_c::Mode_e i_mode) { + u32 animIdx; + + JUT_ASSERT(0x80d, (i_mode >= 0) && (i_mode < Anm_c::Mode_Max)); + + if (i_mode == Anm_c::Mode_Norm) { + static s32 anm_norm_num = 0; + animIdx = anm_norm_num++; + anm_norm_num = anm_norm_num % 8; + } else { + // Return the first anim slot which has an unset mode + animIdx = 8; + for (s32 i = 0; i < 64; i++) { + if (mAnm[animIdx].mMode == Anm_c::Mode_Max) { + return (AnmID_e)animIdx; + } + animIdx++; + } + + // If none are available, return the first one which has a higher mode + animIdx = 8; + for (s32 i = 0; i < 64; i++) { + if (i_mode < mAnm[animIdx].mMode) { + return (AnmID_e)animIdx; + } + animIdx++; + } + + // If no available anim slot is found, return -1 + animIdx = AnmID_Norm_Invalid; + } + + return (AnmID_e)animIdx; }