diff --git a/config/SOUE01/splits.txt b/config/SOUE01/splits.txt index 68ce0d6f..75a194e2 100644 --- a/config/SOUE01/splits.txt +++ b/config/SOUE01/splits.txt @@ -454,6 +454,9 @@ toBeSorted/special_item_drop_mgr.cpp: toBeSorted/d_particle.cpp: .text start:0x800C82B0 end:0x800C8948 align:16 + .data start:0x80511C60 end:0x80511C80 + .sdata start:0x80572310 end:0x80572318 + .sbss start:0x80575440 end:0x80575448 d/lyt/meter/d_lyt_meter.cpp: .text start:0x800C8950 end:0x800DF8A8 align:16 diff --git a/config/SOUE01/symbols.txt b/config/SOUE01/symbols.txt index 2890520f..d60aa2a7 100644 --- a/config/SOUE01/symbols.txt +++ b/config/SOUE01/symbols.txt @@ -4423,24 +4423,24 @@ giveSpecialDropItem__18SpecialItemDropMgrFiiP7mVec3_ci4mAngl = .text:0x800C7D40; spawnSpecialDropItem__18SpecialItemDropMgrFiiP7mVec3_ci4mAng = .text:0x800C7EF0; // type:function size:0x2D8 rndRange<4mAng>__2cMF4mAng4mAng_4mAng = .text:0x800C81D0; // type:function size:0x98 __dt__18SpecialItemDropMgrFv = .text:0x800C8270; // type:function size:0x40 -isShortNegative = .text:0x800C82B0; // type:function size:0x18 -0x3FFFMask = .text:0x800C82D0; // type:function size:0x18 -Particle__init = .text:0x800C82F0; // type:function size:0xB0 -fn_800C83A0 = .text:0x800C83A0; // type:function size:0x68 -fn_800C8410 = .text:0x800C8410; // type:function size:0xE4 -fn_800C8500 = .text:0x800C8500; // type:function size:0xCC -fn_800C85D0 = .text:0x800C85D0; // type:function size:0x6C -fn_800C8640 = .text:0x800C8640; // type:function size:0x50 -dParticle__GetResUserWork = .text:0x800C8690; // type:function size:0x74 -fn_800C8710 = .text:0x800C8710; // type:function size:0x78 -fn_800C8790 = .text:0x800C8790; // type:function size:0x8 -fn_800C87A0 = .text:0x800C87A0; // type:function size:0x8 -fn_800C87B0 = .text:0x800C87B0; // type:function size:0x8 -fn_800C87C0 = .text:0x800C87C0; // type:function size:0xE0 -fn_800C88A0 = .text:0x800C88A0; // type:function size:0x8 -fn_800C88B0 = .text:0x800C88B0; // type:function size:0x8 -fn_800C88C0 = .text:0x800C88C0; // type:function size:0x10 -fn_800C88D0 = .text:0x800C88D0; // type:function size:0x78 +extractResMgrIdx__FUs = .text:0x800C82B0; // type:function size:0x18 +extractResUserIdx__FUs = .text:0x800C82D0; // type:function size:0x18 +init__Q29dParticle5res_cFPCvPCvPQ23EGG4Heap = .text:0x800C82F0; // type:function size:0xB0 +dispose__Q29dParticle5res_cFv = .text:0x800C83A0; // type:function size:0x68 +set__Q29dParticle5tex_cFPQ23EGG10CpuTexture = .text:0x800C8410; // type:function size:0xE4 +__ct__Q29dParticle5mgr_cFPQ23EGG4HeapUlUlUc = .text:0x800C8500; // type:function size:0xCC +createResource__Q29dParticle5mgr_cFPQ23EGG4HeaplPvPv = .text:0x800C85D0; // type:function size:0x6C +disposeResource__Q29dParticle5mgr_cFl = .text:0x800C8640; // type:function size:0x50 +getResUserWork__Q29dParticle5mgr_cCFUs = .text:0x800C8690; // type:function size:0x74 +getJpnData__Q29dParticle5mgr_cCFUs = .text:0x800C8710; // type:function size:0x78 +doCustomSkywardSwordThing__Q29dParticle5mgr_cFUcff = .text:0x800C8790; // type:function size:0x8 +calc__Q29dParticle5mgr_cFUc = .text:0x800C87A0; // type:function size:0x8 +draw__Q29dParticle5mgr_cFPC11JPADrawInfoUc = .text:0x800C87B0; // type:function size:0x8 +createEmitter__Q29dParticle5mgr_cFUsUcRC7mVec3_cPC7mAng3_cPC7mVec3_c = .text:0x800C87C0; // type:function size:0xE0 +forceDeleteAllEmitter__Q29dParticle5mgr_cFv = .text:0x800C88A0; // type:function size:0x8 +forceDeleteEmitter__Q29dParticle5mgr_cFP14JPABaseEmitter = .text:0x800C88B0; // type:function size:0x8 +getResourceManager__Q29dParticle5mgr_cFl = .text:0x800C88C0; // type:function size:0x10 +create__Q29dParticle5mgr_cFPQ23EGG4HeapUlUlUc = .text:0x800C88D0; // type:function size:0x78 initializeState_Wait__18dLytMeter1Button_cFv = .text:0x800C8950; // type:function size:0x4 executeState_Wait__18dLytMeter1Button_cFv = .text:0x800C8960; // type:function size:0x34 changeState__87sStateMgr_c<18dLytMeter1Button_c,20sStateMethodUsr_FI_c,12sFStateFct_c,13sStateIDChk_c>FRC12sStateIDIf_c = .text:0x800C89A0; // type:function size:0x10 @@ -31054,8 +31054,8 @@ lbl_80511C10 = .data:0x80511C10; // type:object size:0x10 lbl_80511C20 = .data:0x80511C20; // type:object size:0x10 Timekeeper__vtable = .data:0x80511C30; // type:object size:0x20 __vt__18SpecialItemDropMgr = .data:0x80511C50; // type:object size:0xC -lbl_80511C60 = .data:0x80511C60; // type:object size:0x14 -lbl_80511C74 = .data:0x80511C74; // type:object size:0xC +lbl_80511C60 = .data:0x80511C60; // type:object size:0x11 data:string +__vt__Q29dParticle5tex_c = .data:0x80511C74; // type:object size:0xC lbl_80511C80 = .data:0x80511C80; // type:object size:0x1A data:string lbl_80511C9C = .data:0x80511C9C; // type:object size:0xB data:string lbl_80511CA8 = .data:0x80511CA8; // type:object size:0x19 data:string @@ -38110,7 +38110,7 @@ lbl_805722F4 = .sdata:0x805722F4; // type:object size:0x4 data:4byte lbl_805722F8 = .sdata:0x805722F8; // type:object size:0x8 lbl_80572300 = .sdata:0x80572300; // type:object size:0x8 data:4byte lbl_80572308 = .sdata:0x80572308; // type:object size:0x8 data:4byte -lbl_80572310 = .sdata:0x80572310; // type:object size:0x8 +lbl_80572310 = .sdata:0x80572310; // type:object size:0x6 data:string lbl_80572318 = .sdata:0x80572318; // type:object size:0x4 data:4byte lbl_8057231C = .sdata:0x8057231C; // type:object size:0x4 data:4byte lbl_80572320 = .sdata:0x80572320; // type:object size:0x4 data:4byte @@ -40092,7 +40092,7 @@ lbl_80575420 = .sbss:0x80575420; // type:object size:0x8 data:byte lbl_80575428 = .sbss:0x80575428; // type:object size:0x8 data:byte lbl_80575430 = .sbss:0x80575430; // type:object size:0x8 data:4byte sInstance__18SpecialItemDropMgr = .sbss:0x80575438; // type:object size:0x4 data:4byte -FOR_LOADED_PARTICLES = .sbss:0x80575440; // type:object size:0x8 data:4byte +sInstance__Q29dParticle5mgr_c = .sbss:0x80575440; // type:object size:0x4 data:4byte sInstance__11dLytMeter_c = .sbss:0x80575448; // type:object size:0x8 data:4byte sInstance__24dLytMeterConfiguration_c = .sbss:0x80575450; // type:object size:0x8 data:4byte sInstance__20LytMeterTimerPart1_c = .sbss:0x80575458; // type:object size:0x4 data:4byte @@ -43742,7 +43742,8 @@ lbl_8057A398 = .sdata2:0x8057A398; // type:object size:0x4 data:float lbl_8057A39C = .sdata2:0x8057A39C; // type:object size:0x4 data:float lbl_8057A3A0 = .sdata2:0x8057A3A0; // type:object size:0x4 data:float lbl_8057A3A4 = .sdata2:0x8057A3A4; // type:object size:0x4 data:float -lbl_8057A3A8 = .sdata2:0x8057A3A8; // type:object size:0xA +lbl_8057A3A8 = .sdata2:0x8057A3A8; // type:object size:0x8 data:float +PARTICLE_RESOURCE_ID_MAPPING_0_ = .sdata2:0x8057A3B0; // type:object size:0x2 data:2byte PARTICLE_RESOURCE_ID_MAPPING_1_ = .sdata2:0x8057A3B2; // type:object size:0x2 data:2byte PARTICLE_RESOURCE_ID_MAPPING_2_ = .sdata2:0x8057A3B4; // type:object size:0x2 data:2byte PARTICLE_RESOURCE_ID_MAPPING_3_ = .sdata2:0x8057A3B6; // type:object size:0x2 data:2byte diff --git a/configure.py b/configure.py index 5c2384a2..5db0be0c 100644 --- a/configure.py +++ b/configure.py @@ -468,7 +468,7 @@ config.libs = [ Object(NonMatching, "toBeSorted/unk_bird_stuff.cpp"), Object(NonMatching, "toBeSorted/timekeeper.cpp"), Object(NonMatching, "toBeSorted/special_item_drop_mgr.cpp"), - Object(NonMatching, "toBeSorted/d_particle.cpp"), + Object(Matching, "toBeSorted/d_particle.cpp"), Object(Matching, "d/lyt/meter/d_lyt_meter.cpp"), Object(NonMatching, "d/lyt/meter/d_lyt_meter_unk.cpp"), Object(Matching, "d/lyt/meter/d_lyt_meter_a_btn.cpp"), diff --git a/include/JSystem/JParticle/JPADynamicsBlock.h b/include/JSystem/JParticle/JPADynamicsBlock.h index f1811246..73a7a6f6 100644 --- a/include/JSystem/JParticle/JPADynamicsBlock.h +++ b/include/JSystem/JParticle/JPADynamicsBlock.h @@ -3,8 +3,8 @@ #include "common.h" -#include "JSystem/JGeometry.h" #include "egg/math/eggVector.h" +#include "m/m_angle.h" class JPAEmitterWorkData; @@ -36,7 +36,7 @@ struct JPADynamicsBlockData { /* 0x5C */ f32 mVolumeMinRad; /* 0x60 */ f32 mAirResist; /* 0x64 */ f32 mMoment; - /* 0x68 */ JGeometry::TVec3 mEmitterRot; + /* 0x68 */ mAng3_c mEmitterRot; /* 0x6E */ s16 mMaxFrame; /* 0x70 */ s16 mStartFrame; /* 0x72 */ s16 mLifeTime; @@ -83,7 +83,7 @@ public: void getEmitterDir(EGG::Vector3f* vec) const { vec->set(mpData->mEmitterDir.x, mpData->mEmitterDir.y, mpData->mEmitterDir.z); } - void getEmitterRot(JGeometry::TVec3* vec) const { + void getEmitterRot(mAng3_c* vec) const { vec->set(mpData->mEmitterRot.x, mpData->mEmitterRot.y, mpData->mEmitterRot.z); } s16 getMaxFrame() { return mpData->mMaxFrame; } diff --git a/include/JSystem/JParticle/JPAEmitter.h b/include/JSystem/JParticle/JPAEmitter.h index d8900bff..6e49752f 100644 --- a/include/JSystem/JParticle/JPAEmitter.h +++ b/include/JSystem/JParticle/JPAEmitter.h @@ -9,6 +9,8 @@ #include "JSystem/JParticle/JPAMath.h" #include "JSystem/JParticle/JPADynamicsBlock.h" #include "JSystem/JSupport/JSUList.h" +#include "egg/math/eggVector.h" +#include "m/m_angle.h" class JPAResourceManager; class JPABaseEmitter; @@ -47,8 +49,8 @@ struct JPAEmitterWorkData { /* 0x120 */ EGG::Vector3f mGlobalEmtrDir; /* 0x12C */ EGG::Vector3f mPublicScale; /* 0x138 */ EGG::Vector3f mGlobalPos; - /* 0x144 */ JGeometry::TVec2 mGlobalPtclScl; - /* 0x14C */ JGeometry::TVec2 mPivot; + /* 0x144 */ EGG::Vector2f mGlobalPtclScl; + /* 0x14C */ EGG::Vector2f mPivot; /* 0x154 */ Mtx mYBBCamMtx; /* 0x184 */ Mtx mPosCamMtx; /* 0x1B4 */ Mtx mPrjMtx; @@ -136,7 +138,7 @@ public: void setGlobalTranslation(f32 x, f32 y, f32 z) { mGlobalTrs.set(x, y, z); } void setGlobalTranslation(const EGG::Vector3f& trs) { mGlobalTrs.set(trs); } void getLocalTranslation(EGG::Vector3f& vec) { vec.set(mLocalTrs); } - void setGlobalRotation(const JGeometry::TVec3& rot) { + void setGlobalRotation(const mAng3_c& rot) { JPAGetXYZRotateMtx(rot.x, rot.y, rot.z, mGlobalRot); } void getGlobalTranslation(EGG::Vector3f* out) const { out->set(mGlobalTrs); } @@ -152,7 +154,7 @@ public: void setAwayFromAxisSpeed(f32 i_speed) { mAwayFromAxisSpeed = i_speed; } void setSpread(f32 i_spread) { mSpread = i_spread; } void setLocalTranslation(const EGG::Vector3f& i_trans) { mLocalTrs.set(i_trans); } - void setLocalRotation(const JGeometry::TVec3& i_rot) { mLocalRot.set(i_rot.x * 0.005493248f, i_rot.y * 0.005493248f, i_rot.z * 0.005493248f); } + void setLocalRotation(const mAng3_c& i_rot) { mLocalRot.set(i_rot.x * 0.005493248f, i_rot.y * 0.005493248f, i_rot.z * 0.005493248f); } void setRateStep(u8 i_step) { mRateStep = i_step; } void setGlobalParticleHeightScale(f32 height) { @@ -232,7 +234,7 @@ public: /* 0x40 */ f32 mSpread; /* 0x44 */ f32 mRndmDirSpeed; /* 0x48 */ f32 mAirResist; - /* 0x4C */ JGeometry::TVec3 mLocalRot; + /* 0x4C */ mAng3_c mLocalRot; /* 0x52 */ s16 mLifeTime; /* 0x54 */ u16 mVolumeSize; /* 0x56 */ u8 mRateStep; @@ -240,7 +242,7 @@ public: /* 0x68 */ Mtx mGlobalRot; /* 0x98 */ EGG::Vector3f mGlobalScl; /* 0xA4 */ EGG::Vector3f mGlobalTrs; - /* 0xB0 */ JGeometry::TVec2 mGlobalPScl; + /* 0xB0 */ EGG::Vector2f mGlobalPScl; /* 0xB8 */ GXColor mGlobalPrmClr; /* 0xBC */ GXColor mGlobalEnvClr; /* 0xC0 */ s32 mpUserWork; diff --git a/include/d/d_stage_mgr.h b/include/d/d_stage_mgr.h index cc7d16a3..c239a98d 100644 --- a/include/d/d_stage_mgr.h +++ b/include/d/d_stage_mgr.h @@ -18,6 +18,7 @@ #include "toBeSorted/arc_managers/oarc_manager.h" #include "toBeSorted/attention.h" #include "toBeSorted/d_d3d.h" +#include "toBeSorted/d_particle.h" #include "toBeSorted/time_area_mgr.h" class RelObjCtrl { @@ -161,9 +162,11 @@ private: /* 0x0580 */ LayoutArcControl mLayoutArcCtrl2; /* 0x058C */ dBgS mBg; // ... - u8 _0x00001[0x7D0]; + u8 _0x00001[0x778]; /* 0x3E40 */ dCcS mCc; // ... + /* 0x7814 */ dParticle::tex_c mParticleTex[2]; + // ... /* 0x7930 */ dFader_c mFader; /* 0x7954 */ u16 mPcamCount; diff --git a/include/egg/gfx/eggCpuTexture.h b/include/egg/gfx/eggCpuTexture.h index a3e4db22..d5300b41 100644 --- a/include/egg/gfx/eggCpuTexture.h +++ b/include/egg/gfx/eggCpuTexture.h @@ -90,6 +90,13 @@ public: mWrapT = wrap; } + GXTexWrapMode getWrapS() const { + return (GXTexWrapMode)mWrapS; + } + GXTexWrapMode getWrapT() const { + return (GXTexWrapMode)mWrapT; + } + void setWrap(GXTexWrapMode wrapS, GXTexWrapMode wrapT) { mWrapS = wrapS; mWrapT = wrapT; @@ -107,6 +114,13 @@ public: mMagFilt = filt; } + GXTexFilter getMinFilt() const { + return (GXTexFilter)mMinFilt; + } + GXTexFilter getMagFilt() const { + return (GXTexFilter)mMagFilt; + } + ResTIMG *getHeader() const { return (ResTIMG *)((u8 *)dataPtr - sizeof(ResTIMG)); } diff --git a/include/toBeSorted/d_particle.h b/include/toBeSorted/d_particle.h new file mode 100644 index 00000000..ef81921b --- /dev/null +++ b/include/toBeSorted/d_particle.h @@ -0,0 +1,96 @@ +#ifndef D_PARTICLE_H +#define D_PARTICLE_H + +#include "JSystem/JParticle/JPADrawInfo.h" +#include "JSystem/JParticle/JPAEmitter.h" +#include "JSystem/JParticle/JPAResourceManager.h" +#include "common.h" +#include "m/m_angle.h" +#include "m/m_vec.h" + +#define D_PARTICLE_RES_COMMON 0 +#define D_PARTICLE_RES_PARTICLE 1 + +#define D_PARTICLE_NUM_RES 2 + +namespace dParticle { + +struct JPN { + u16 numJpn; + u16 mData[1]; +}; + +class res_c { +public: + res_c() { + mpHeap = nullptr; + mpResourceManager = nullptr; + mpJpnData = nullptr; + } + + JPAResourceManager *init(const void *jpc, const void *jpn, EGG::Heap *heap); + void dispose(); + + JPAResourceManager *getResourceManager() { + return mpResourceManager; + } + + const JPN *getJpn() const { + return mpJpnData; + } + +private: + /* 0x00 */ EGG::FrmHeap *mpHeap; + /* 0x04 */ JPAResourceManager *mpResourceManager; + /* 0x08 */ const JPN *mpJpnData; +}; + +// Made up name +class tex_c { +public: + tex_c() { + field_0x04 = 0; + field_0x08 = 0; + } + virtual void set(EGG::CpuTexture *tex); + +private: + /* 0x04 */ UNKWORD field_0x04; + /* 0x08 */ UNKWORD field_0x08; + /* 0x0C */ EGG::ResTIMG mImg; +}; + +// Made up name +class mgr_c { +public: + mgr_c(EGG::Heap *heap, u32 ptclMax, u32 emtrMax, u8 grpMax); + + static mgr_c *GetInstance() { + return sInstance; + } + + static mgr_c *create(EGG::Heap *heap, u32 ptclMax, u32 emtrMax, u8 grpMax); + + void createResource(EGG::Heap *heap, s32 mgrIndex, void *jpc, void *jpn); + void disposeResource(s32 mgrIndex); + s32 getResUserWork(u16 handle) const; + u16 getJpnData(u16 handle) const; + // Invokes the JParticle 11 extension + void doCustomSkywardSwordThing(u8 groupId, f32 x, f32 y); + void calc(u8 groupId); + void draw(const JPADrawInfo *drawInfo, u8 groupId); + JPABaseEmitter * + createEmitter(u16 particleResId, u8 groupId, const mVec3_c &pos, const mAng3_c *rot, const mVec3_c *scale); + void forceDeleteAllEmitter(); + void forceDeleteEmitter(JPABaseEmitter *emitter); + JPAResourceManager *getResourceManager(s32 idx); + +private: + static mgr_c *sInstance; + /* 0x00 */ JPAEmitterManager *mpEmitterMgr; + /* 0x04 */ res_c mRes[D_PARTICLE_NUM_RES]; +}; + +} // namespace dParticle + +#endif diff --git a/src/toBeSorted/d_particle.cpp b/src/toBeSorted/d_particle.cpp new file mode 100644 index 00000000..e05695af --- /dev/null +++ b/src/toBeSorted/d_particle.cpp @@ -0,0 +1,169 @@ +#include "toBeSorted/d_particle.h" + +#include "JSystem/JParticle/JPAEmitter.h" +#include "JSystem/JParticle/JPAEmitterManager.h" +#include "JSystem/JParticle/JPAResourceManager.h" +#include "common.h" +#include "egg/core/eggHeap.h" +#include "egg/egg_types.h" +#include "egg/gfx/eggCpuTexture.h" +#include "egg/gfx/eggTexture.h" +#include "m/m_angle.h" +#include "m/m_heap.h" +#include "m/m_vec.h" + +extern "C" const u16 lbl_8057AB72; +extern "C" const u16 lbl_8057AB74; + +static u32 extractResMgrIdx(u16 particleResId) { + return (particleResId & lbl_8057AB72) != 0 ? 1 : 0; +} + +static u16 extractResUserIdx(u16 particleResId) { + return (particleResId & ~(lbl_8057AB72 | lbl_8057AB74)); +} + +namespace dParticle { + +JPAResourceManager *res_c::init(const void *jpc, const void *jpn, EGG::Heap *heap) { + mpHeap = mHeap::createFrmHeap(-1, heap, "dParticle::res_c", 0x20, 0); + if (mpHeap == nullptr) { + return nullptr; + } + mpResourceManager = new (mpHeap, 4) JPAResourceManager(jpc, mpHeap); + if (mpResourceManager != nullptr) { + mpJpnData = static_cast(jpn); + } + mHeap::adjustFrmHeap(mpHeap); + return mpResourceManager; +} + +void res_c::dispose() { + if (mpHeap != nullptr) { + if (mpResourceManager != nullptr) { + mpResourceManager = nullptr; + mpJpnData = nullptr; + } + mpHeap->destroy(); + mpHeap = nullptr; + } +} + +void tex_c::set(EGG::CpuTexture *tex) { + mImg.format = tex->getFormat(); + mImg.alphaEnabled = true; + mImg.width = tex->getWidth(); + mImg.height = tex->getHeight(); + mImg.wrapS = tex->getWrapS(); + mImg.wrapT = tex->getWrapT(); + mImg.indexTexture = 0; + mImg.colorFormat = GX_TL_IA8; + mImg.numColors = 0; + mImg.paletteOffset = 0; + mImg.mipmapEnabled = 0; + mImg.doEdgeLOD = 0; + mImg.biasClamp = 0; + mImg.maxAnisotropy = 0; + mImg.minFilter = tex->getMinFilt(); + mImg.magFilter = tex->getMagFilt(); + mImg.minLOD = 0; + mImg.maxLOD = 0; + mImg.mipmapCount = 1; + mImg.LODBias = 0; + mImg.imageOffset = (u32)tex->getBuffer() - (u32)&mImg; + + for (int i = 0; i < D_PARTICLE_NUM_RES; i++) { + JPAResourceManager *mgr = dParticle::mgr_c::GetInstance()->getResourceManager(i); + if (mgr != nullptr) { + mgr->swapTexture(&mImg, "dummy"); + } + } +} + +mgr_c *mgr_c::sInstance; + +mgr_c::mgr_c(EGG::Heap *heap, u32 ptclMax, u32 emtrMax, u8 grpMax) : mpEmitterMgr(nullptr) { + sInstance = this; + mpEmitterMgr = new (heap, 4) JPAEmitterManager(ptclMax, emtrMax, heap, grpMax, D_PARTICLE_NUM_RES); +} + +void mgr_c::createResource(EGG::Heap *heap, s32 mgrIndex, void *jpc, void *jpn) { + JPAResourceManager *mgr = mRes[mgrIndex].init(jpc, jpn, heap); + if (mgr != nullptr) { + mpEmitterMgr->entryResourceManager(mgr, mgrIndex); + } +} + +void mgr_c::disposeResource(s32 mgrIndex) { + res_c &res = mRes[mgrIndex]; + if (res.getResourceManager() != nullptr) { + mpEmitterMgr->clearResourceManager(mgrIndex); + } + res.dispose(); +} + +s32 mgr_c::getResUserWork(u16 particleResId) const { + u8 idx = extractResMgrIdx(particleResId); + JPAResourceManager *mgr = mpEmitterMgr->getResourceManager(idx); + if (mgr == nullptr) { + return -1; + } + return mgr->getResUserWork(extractResUserIdx(particleResId)); +} + +u16 mgr_c::getJpnData(u16 particleResId) const { + const JPN *jpn = mRes[extractResMgrIdx(particleResId)].getJpn(); + u16 idx = extractResUserIdx(particleResId); + if (idx >= jpn->numJpn) { + return 0xFFFF; + } else { + return jpn->mData[idx]; + } +} + +void mgr_c::doCustomSkywardSwordThing(u8 groupId, f32 x, f32 y) { + mpEmitterMgr->fn_80320E20(groupId, x, y); +} + +void mgr_c::calc(u8 groupId) { + mpEmitterMgr->calc(groupId); +} + +void mgr_c::draw(const JPADrawInfo *drawInfo, u8 groupId) { + mpEmitterMgr->draw(drawInfo, groupId); +} + +JPABaseEmitter * +mgr_c::createEmitter(u16 particleResId, u8 groupId, const mVec3_c &pos, const mAng3_c *rot, const mVec3_c *scale) { + u32 resMgrId = extractResMgrIdx(particleResId); + u16 resId = extractResUserIdx(particleResId); + JPABaseEmitter *emitter = mpEmitterMgr->createSimpleEmitterID(pos, resId, groupId, resMgrId, nullptr, nullptr); + if (emitter == nullptr) { + return nullptr; + } + if (rot != nullptr) { + emitter->setGlobalRotation(*rot); + } + if (scale != nullptr) { + emitter->setGlobalScale(*scale); + } + return emitter; +} + +void mgr_c::forceDeleteAllEmitter() { + mpEmitterMgr->forceDeleteAllEmitter(); +} + +void mgr_c::forceDeleteEmitter(JPABaseEmitter *emitter) { + mpEmitterMgr->forceDeleteEmitter(emitter); +} + +JPAResourceManager *mgr_c::getResourceManager(s32 idx) { + return mRes[idx].getResourceManager(); +} + +mgr_c *mgr_c::create(EGG::Heap *heap, u32 ptclMax, u32 emtrMax, u8 grpMax) { + return new (heap, 4) mgr_c(heap, ptclMax, emtrMax, grpMax); +} + +} // namespace dParticle