Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
107 changes: 54 additions & 53 deletions config/SOUE01/rels/d_a_obj_mushroomNP/symbols.txt
Original file line number Diff line number Diff line change
Expand Up @@ -3,63 +3,63 @@ _epilog = .text:0x00000030; // type:function size:0x2C scope:global
_unresolved = .text:0x00000060; // type:function size:0x4 scope:global
__register_global_object = .text:0x00000070; // type:function size:0x1C scope:global
__destroy_global_chain = .text:0x00000090; // type:function size:0x54 scope:global
fn_328_F0 = .text:0x000000F0; // type:function size:0x40
__dt__7mVec3_cFv = .text:0x000000F0; // type:function size:0x40
dAcOMushRoom_c_classInit__Fv = .text:0x00000130; // type:function size:0x1C0
fn_328_2F0 = .text:0x000002F0; // type:function size:0x18
fn_328_310 = .text:0x00000310; // type:function size:0x80
fn_328_390 = .text:0x00000390; // type:function size:0x78
fn_328_410 = .text:0x00000410; // type:function size:0x58
__ct__Q26dLOD_c5mdl_cFv = .text:0x000002F0; // type:function size:0x18
__dt__Q26dLOD_c5mdl_cFv = .text:0x00000310; // type:function size:0x80
__dt__9dMdlLOD_cFv = .text:0x00000390; // type:function size:0x78
__dt__15dShadowCircle_cFv = .text:0x00000410; // type:function size:0x58
__dt__27sFState_c<14dAcOMushRoom_c>Fv = .text:0x00000470; // type:function size:0x58
__dt__30sFStateFct_c<14dAcOMushRoom_c>Fv = .text:0x000004D0; // type:function size:0x6C
__dt__83sStateMgr_c<14dAcOMushRoom_c,20sStateMethodUsr_FI_c,12sFStateFct_c,13sStateIDChk_c>Fv = .text:0x00000540; // type:function size:0xA0
__dt__53sFStateMgr_c<14dAcOMushRoom_c,20sStateMethodUsr_FI_c>Fv = .text:0x000005E0; // type:function size:0xA4
fn_328_690 = .text:0x00000690; // type:function size:0x4
fn_328_6A0 = .text:0x000006A0; // type:function size:0x5C
fn_328_700 = .text:0x00000700; // type:function size:0x7C
fn_328_780 = .text:0x00000780; // type:function size:0x64
fn_328_7F0 = .text:0x000007F0; // type:function size:0x40
fn_328_830 = .text:0x00000830; // type:function size:0x1C4
AcOMushRoom__initModels = .text:0x00000A00; // type:function size:0x194
AcOMushRoom__init = .text:0x00000BA0; // type:function size:0x424
__ct__7mVec3_cFv = .text:0x00000690; // type:function size:0x4
__ct__Q214dAcOMushRoom_c6proc_cFv = .text:0x000006A0; // type:function size:0x5C
__dt__Q214dAcOMushRoom_c6proc_cFv = .text:0x00000700; // type:function size:0x7C
__dt__Q214dAcOMushRoom_c8camera_cFv = .text:0x00000780; // type:function size:0x64
__dt__Q23EGG11OrthoCameraFv = .text:0x000007F0; // type:function size:0x40
fn_328_830__FScSc = .text:0x00000830; // type:function size:0x1C4
createHeap__14dAcOMushRoom_cFv = .text:0x00000A00; // type:function size:0x194
create__14dAcOMushRoom_cFv = .text:0x00000BA0; // type:function size:0x424
changeState__83sStateMgr_c<14dAcOMushRoom_c,20sStateMethodUsr_FI_c,12sFStateFct_c,13sStateIDChk_c>FRC12sStateIDIf_c = .text:0x00000FD0; // type:function size:0x10
fn_328_FE0 = .text:0x00000FE0; // type:function size:0xFC
AcOMushRoom__update = .text:0x000010E0; // type:function size:0x1CC
doDelete__14dAcOMushRoom_cFv = .text:0x00000FE0; // type:function size:0xFC
actorExecute__14dAcOMushRoom_cFv = .text:0x000010E0; // type:function size:0x1CC
executeState__83sStateMgr_c<14dAcOMushRoom_c,20sStateMethodUsr_FI_c,12sFStateFct_c,13sStateIDChk_c>Fv = .text:0x000012B0; // type:function size:0x10
AcOMushRoom__draw = .text:0x000012C0; // type:function size:0x2C0
draw__14dAcOMushRoom_cFv = .text:0x000012C0; // type:function size:0x2C0
initializeState_Wait__14dAcOMushRoom_cFv = .text:0x00001580; // type:function size:0x50
executeState_Wait__14dAcOMushRoom_cFv = .text:0x000015D0; // type:function size:0xD68
fn_328_2340 = .text:0x00002340; // type:function size:0x1C
calcTimer<Ul>__4sLibFPUl_Ul = .text:0x00002340; // type:function size:0x1C
finalizeState_Wait__14dAcOMushRoom_cFv = .text:0x00002360; // type:function size:0x4
initializeState_Init__14dAcOMushRoom_cFv = .text:0x00002370; // type:function size:0x4
executeState_Init__14dAcOMushRoom_cFv = .text:0x00002380; // type:function size:0x18
finalizeState_Init__14dAcOMushRoom_cFv = .text:0x000023A0; // type:function size:0x4
fn_328_23B0 = .text:0x000023B0; // type:function size:0xB8
fn_328_2470 = .text:0x00002470; // type:function size:0xBC
fn_328_2530 = .text:0x00002530; // type:function size:0x34
fn_328_2570 = .text:0x00002570; // type:function size:0x34
fn_328_25B0 = .text:0x000025B0; // type:function size:0xC4
AcOMushRoom__getArcName = .text:0x00002680; // type:function size:0xB0
AcOMushRoom__getArcName2 = .text:0x00002730; // type:function size:0x4
AcOMushRoom__getBtiName = .text:0x00002740; // type:function size:0xF8
fn_328_2840 = .text:0x00002840; // type:function size:0x208
fn_328_2A50 = .text:0x00002A50; // type:function size:0x224
fn_328_2C80 = .text:0x00002C80; // type:function size:0x76C
fn_328_33F0 = .text:0x000033F0; // type:function size:0x88
fn_328_3480 = .text:0x00003480; // type:function size:0x30C
fn_328_3790 = .text:0x00003790; // type:function size:0x230
fn_328_39C0 = .text:0x000039C0; // type:function size:0x72C
fn_328_40F0 = .text:0x000040F0; // type:function size:0xE8
fn_328_41E0 = .text:0x000041E0; // type:function size:0x38
fn_328_4220 = .text:0x00004220; // type:function size:0xC
fn_328_4230 = .text:0x00004230; // type:function size:0x4EC
fn_328_4720 = .text:0x00004720; // type:function size:0xB0
fn_328_47D0 = .text:0x000047D0; // type:function size:0x350
fn_328_4B20 = .text:0x00004B20; // type:function size:0x108
fn_328_4C30 = .text:0x00004C30; // type:function size:0x19C
fn_328_4DD0 = .text:0x00004DD0; // type:function size:0xCC
fn_328_4EA0 = .text:0x00004EA0; // type:function size:0x4C
fn_328_4EF0 = .text:0x00004EF0; // type:function size:0xC0
fn_328_4FB0 = .text:0x00004FB0; // type:function size:0x84
getUnscaledRadiusX__14dAcOMushRoom_cFv = .text:0x000023B0; // type:function size:0xB8
getUnscaledRadiusY__14dAcOMushRoom_cFv = .text:0x00002470; // type:function size:0xBC
getRadiusX__14dAcOMushRoom_cFv = .text:0x00002530; // type:function size:0x34
getShadowOffsetY__14dAcOMushRoom_cFv = .text:0x00002570; // type:function size:0x34
getRadiusZ__14dAcOMushRoom_cFv = .text:0x000025B0; // type:function size:0xC4
getResFileName__14dAcOMushRoom_cFv = .text:0x00002680; // type:function size:0xB0
getResMdlName__14dAcOMushRoom_cFv = .text:0x00002730; // type:function size:0x4
getDataBinName__14dAcOMushRoom_cFv = .text:0x00002740; // type:function size:0xF8
initCc__14dAcOMushRoom_cFv = .text:0x00002840; // type:function size:0x208
setCc__14dAcOMushRoom_cFv = .text:0x00002A50; // type:function size:0x224
startCloudEmitter__14dAcOMushRoom_cFv = .text:0x00002C80; // type:function size:0x76C
rndRange<i>__2cMFii_i = .text:0x000033F0; // type:function size:0x88
startGlitterEmitter__14dAcOMushRoom_cFv = .text:0x00003480; // type:function size:0x30C
fn_328_3970__14dAcOMushRoom_cFv = .text:0x00003790; // type:function size:0x230
fn_328_39C0__14dAcOMushRoom_cFv = .text:0x000039C0; // type:function size:0x72C
create__Q214dAcOMushRoom_c6proc_cFPQ23EGG7ResTIMGUlP12mAllocator_clP7mVec3_cP7mVec3_cPUsPUs = .text:0x000040F0; // type:function size:0xE8
entryIdx__Q214dAcOMushRoom_c6proc_cFUs = .text:0x000041E0; // type:function size:0x38
clearIdx__Q214dAcOMushRoom_c6proc_cFv = .text:0x00004220; // type:function size:0xC
drawOpa__Q214dAcOMushRoom_c6proc_cFv = .text:0x00004230; // type:function size:0x4EC
draw__Q214dAcOMushRoom_c6proc_cFv = .text:0x00004720; // type:function size:0xB0
updateCameras__14dAcOMushRoom_cFv = .text:0x000047D0; // type:function size:0x350
fn_328_4B20__14dAcOMushRoom_cFRC6mMtx_cRC7mVec3_cff = .text:0x00004B20; // type:function size:0x108
fn_328_4C30__14dAcOMushRoom_cFRCfRCsP8cCcD_ObjRCfRCf = .text:0x00004C30; // type:function size:0x19C
setLighting__14dAcOMushRoom_cFv = .text:0x00004DD0; // type:function size:0xCC
cutLighting__14dAcOMushRoom_cFv = .text:0x00004EA0; // type:function size:0x4C
fn_328_4EF0__14dAcOMushRoom_cFv = .text:0x00004EF0; // type:function size:0xC0
checkUnderWater__14dAcOMushRoom_cFv = .text:0x00004FB0; // type:function size:0x84
__dt__14dAcOMushRoom_cFv = .text:0x00005040; // type:function size:0x198
getStateID__83sStateMgr_c<14dAcOMushRoom_c,20sStateMethodUsr_FI_c,12sFStateFct_c,13sStateIDChk_c>CFv = .text:0x000051E0; // type:function size:0x10
build__30sFStateFct_c<14dAcOMushRoom_c>FRC12sStateIDIf_c = .text:0x000051F0; // type:function size:0x60
Expand All @@ -78,7 +78,7 @@ executeState__29sFStateID_c<14dAcOMushRoom_c>CFR14dAcOMushRoom_c = .text:0x00005
initializeState__29sFStateID_c<14dAcOMushRoom_c>CFR14dAcOMushRoom_c = .text:0x00005380; // type:function size:0x30
__sinit_\d_a_obj_mushroom_cpp = .text:0x000053B0; // type:function size:0x26C scope:local
__dt__29sFStateID_c<14dAcOMushRoom_c>Fv = .text:0x00005620; // type:function size:0x58
fn_328_5680 = .text:0x00005680; // type:function size:0x68
__ct__Q214dAcOMushRoom_c8camera_cFv = .text:0x00005680; // type:function size:0x68
isSameName__29sFStateID_c<14dAcOMushRoom_c>CFPCc = .text:0x000056F0; // type:function size:0x88
_ctors = .ctors:0x00000000; // type:label scope:global
_dtors = .dtors:0x00000000; // type:label scope:global
Expand All @@ -102,14 +102,15 @@ lbl_328_data_40 = .data:0x00000040; // type:object size:0x30
lbl_328_data_70 = .data:0x00000070; // type:object size:0x58
lbl_328_data_C8 = .data:0x000000C8; // type:object size:0x98
lbl_328_data_160 = .data:0x00000160; // type:object size:0xA data:string
lbl_328_data_170 = .data:0x00000170; // type:object size:0x80
lbl_328_data_1F0 = .data:0x000001F0; // type:object size:0x30
lbl_328_data_220 = .data:0x00000220; // type:object size:0x30
lbl_328_data_250 = .data:0x00000250; // type:object size:0x18
lbl_328_data_268 = .data:0x00000268; // type:object size:0x18
lbl_328_data_280 = .data:0x00000280; // type:object size:0x2C data:4byte
lbl_328_data_2AC = .data:0x000002AC; // type:object size:0x2C
lbl_328_data_2D8 = .data:0x000002D8; // type:object size:0x94
__vt__14dAcOMushRoom_c = .data:0x00000170; // type:object size:0x7C
__vt__53sFStateMgr_c<14dAcOMushRoom_c,20sStateMethodUsr_FI_c> = .data:0x000001F0; // type:object size:0x30
__vt__83sStateMgr_c<14dAcOMushRoom_c,20sStateMethodUsr_FI_c,12sFStateFct_c,13sStateIDChk_c> = .data:0x00000220; // type:object size:0x30
__vt__30sFStateFct_c<14dAcOMushRoom_c> = .data:0x00000250; // type:object size:0x18
__vt__27sFState_c<14dAcOMushRoom_c> = .data:0x00000268; // type:object size:0x18
__vt__Q214dAcOMushRoom_c6proc_c = .data:0x00000280; // type:object size:0x2C data:4byte
__vt__9dMdlLOD_c = .data:0x000002AC; // type:object size:0x2C
__vt__15dShadowCircle_c = .data:0x000002D8; // type:object size:0xC
lbl_328_data_2E4 = .data:0x000002E4; // type:object size:0x88
lbl_328_data_36C = .data:0x0000036C; // type:object size:0x34
__global_destructor_chain = .bss:0x00000000; // type:object size:0x4 scope:global
lbl_328_bss_8 = .bss:0x00000008; // type:object size:0x70 data:4byte
Expand Down
6 changes: 3 additions & 3 deletions config/SOUE01/symbols.txt
Original file line number Diff line number Diff line change
Expand Up @@ -724,11 +724,11 @@ ExecCallback_CALC_MAT__Q34nw4r3g3d15IScnObjCallbackFQ44nw4r3g3d6ScnObj6TimingPQ3
fn_8001F700 = .text:0x8001F700; // type:function size:0xA8
fn_8001F7B0 = .text:0x8001F7B0; // type:function size:0x64
sprintf__15SizedString<32>FPCce = .text:0x8001F820; // type:function size:0xD0
fn_8001F8F0 = .text:0x8001F8F0; // type:function size:0x14
fn_8001F910 = .text:0x8001F910; // type:function size:0xD4
setLODDistance__6dLOD_cFlf = .text:0x8001F8F0; // type:function size:0x14
getMdl__6dLOD_cFRQ23m3d6smdl_c = .text:0x8001F910; // type:function size:0xD4
fn_8001F9F0 = .text:0x8001F9F0; // type:function size:0xB4
fn_8001FAB0 = .text:0x8001FAB0; // type:function size:0x140
fn_8001FBF0 = .text:0x8001FBF0; // type:function size:0xA4
create__9dMdlLOD_cFPvPCcP16mHeapAllocator_cUl = .text:0x8001FBF0; // type:function size:0xA4
fn_8001FCA0 = .text:0x8001FCA0; // type:function size:0x60
fn_8001FD00 = .text:0x8001FD00; // type:function size:0x64
fn_8001FD70 = .text:0x8001FD70; // type:function size:0xA8
Expand Down
222 changes: 220 additions & 2 deletions include/d/a/obj/d_a_obj_mushroom.h
Original file line number Diff line number Diff line change
@@ -1,19 +1,237 @@
#ifndef D_A_OBJ_MUSHROOM_H
#define D_A_OBJ_MUSHROOM_H

#include "common.h"
#include "d/a/obj/d_a_obj_base.h"
#include "d/col/c/c_cc_d.h"
#include "d/col/cc/d_cc_d.h"
#include "d/d_light_env.h"
#include "d/d_shadow.h"
#include "egg/egg_types.h"
#include "egg/gfx/eggCamera.h"
#include "m/m3d/m_proc.h"
#include "m/m_allocator.h"
#include "m/m_angle.h"
#include "m/m_mtx.h"
#include "m/m_vec.h"
#include "nw4r/g3d/res/g3d_resfile.h"
#include "s/s_State.hpp"
#include "toBeSorted/d_emitter.h"
#include "toBeSorted/d_unk_mdl_stuff_2.h"

class dAcOMushRoom_c : public dAcObjBase_c {
public:
dAcOMushRoom_c() : mStateMgr(*this) {}
class proc_c : public m3d::proc_c {
public:
proc_c() : mpImg(nullptr), mpIdxArr(nullptr), field_0x20(0), mIdxNum(0), mIdxMax(0) {}
virtual ~proc_c() {
remove();
}
virtual void drawOpa() override;
void draw();

bool create(
EGG::ResTIMG *pImg, u32 drawOpa, mAllocator_c *pAllocator, s32 idxNum, mVec3_c *pVtx, mVec3_c *pNrm,
u16 *pVtxIdx, u16 *pNrmIdx
);
bool entryIdx(u16 idx);
void clearIdx();

/* 0x18 */ EGG::ResTIMG *mpImg;
/* 0x1C */ u16 *mpIdxArr;
/* 0x20 */ u32 field_0x20;
/* 0x24 */ s32 mIdxNum;
/* 0x28 */ s32 mIdxMax;
/* 0x2C */ u32 mCameraIdx;
/* 0x30 */ u32 mCameraSubIdx;
/* 0x34 */ u8 mTev0Alpha;
/* 0x38 */ mVec3_c *mpVtxArr;
/* 0x3C */ mVec3_c *mpNrmArr;
/* 0x40 */ u16 *mpVtxIdxArr;
/* 0x44 */ u16 *mpNrmIdxArr;
};

class camera_c {
public:
camera_c() : field_0x1B6(0) {
for (int i = 0; i < 3; ++i) {
mAlpha[i] = 0;
field_0x1B3[i] = 0;
}
}
~camera_c();

/* 0x000 */ EGG::OrthoCamera mCam[3];
/* 0x1B0 */ u8 mAlpha[3];
/* 0x1B3 */ u8 field_0x1B3[3];
/* 0x1B6 */ u8 field_0x1B6;
};
static camera_c sCameras[8];

dAcOMushRoom_c() : mStateMgr(*this), mEmitter(this) {}
virtual ~dAcOMushRoom_c() {}

virtual int create() override;
virtual int doDelete() override;
virtual int draw() override;
virtual bool createHeap() override;
virtual int actorExecute() override;

STATE_FUNC_DECLARE(dAcOMushRoom_c, Wait);
STATE_FUNC_DECLARE(dAcOMushRoom_c, Init);

STATE_MGR_DEFINE_UTIL_ISSTATE(dAcOMushRoom_c);
STATE_MGR_DEFINE_UTIL_EXECUTESTATE(dAcOMushRoom_c);
STATE_MGR_DEFINE_UTIL_CHANGESTATE(dAcOMushRoom_c);

f32 getUnscaledRadiusX();
f32 getUnscaledRadiusY();
f32 getRadiusX();
f32 getShadowOffsetY();
f32 getRadiusZ();

void initCc();
void setCc();
void startCloudEmitter();
void startGlitterEmitter();
void fn_328_3970();
bool fn_328_39C0();
void updateCameras();
bool fn_328_4B20(const mMtx_c &m, const mVec3_c &v, f32 zHi, f32 zLo);
bool fn_328_4C30(const f32 &radius, const s16 &angle, cCcD_Obj *ccObj, const f32 &yHi, const f32 &yLo);
void setLighting();
void cutLighting();
void fn_328_4EF0();
bool checkUnderWater();

enum SpawnedActorSubtype_e {
SPAWN_Param = 0,
SPAWN_MushroomA,
SPAWN_MushroomB,
SPAWN_MushroomC,
SPAWN_MushroomD,
};
// The Actual Type
enum Type_e {
TYPE_MushroomA,
TYPE_MushroomB,
TYPE_MushroomC,
TYPE_MushroomD,
TYPE_Max
};
s32 getType() {
s32 type;
if (mActorSubtype == SPAWN_Param) { // Spawned as "Mushroom"
switch ((s32)getFromParams(0, 0xF)) {
case TYPE_MushroomA: type = TYPE_MushroomA; break;
case TYPE_MushroomB: type = TYPE_MushroomB; break;
case TYPE_MushroomC: type = TYPE_MushroomC; break;
case TYPE_MushroomD: type = TYPE_MushroomD; break;
default: type = TYPE_MushroomA; break;
}
} else { // Spawned as "MushroomA", "MushroomB", "MushroomC", "MushroomD"
switch (mActorSubtype) {
case SPAWN_MushroomA: type = TYPE_MushroomA; break;
case SPAWN_MushroomB: type = TYPE_MushroomB; break;
case SPAWN_MushroomC: type = TYPE_MushroomC; break;
case SPAWN_MushroomD: type = TYPE_MushroomD; break;
default: type = TYPE_MushroomA; break;
}
}
return type;
}

bool isNotParamBit30() {
return mActorSubtype == SPAWN_Param && (s32)getFromParams(30, 0x1) == 0;
}

bool checkGlittering() {
return getFromParams(31, 1) == 1 && field_0x892;
}

dCcD_Sph &getMainCc() {
return mSph0;
}
s32 getSporeParams1() const {
return field_0x892 != 0 ? 1 : 0;
}

int findCameraIdx() {
for (int i = 0; i < 8; ++i) {
bool found;
if (sCameras[i].field_0x1B6 == 0) {
sCameras[i].field_0x1B6 = 1;
found = true;
} else {
found = false;
}
if (found) {
return i;
}
}
return -1;
}

void clearField_0x854() {
if (mSph0.ChkTgHit() && mSph0.ChkTgAtHitType(AT_TYPE_BELLOWS)) {
return;
}

if (!mSph0.ChkTgHit()) {
return;
}
field_0x854 = 0;
}

private:
const char *getResFileName();
const char *getResMdlName();
const char *getDataBinName();

private:
/* 0x??? */ STATE_MGR_DECLARE(dAcOMushRoom_c);
/* 0x330 */ nw4r::g3d::ResFile mRes;
/* 0x334 */ dMdlLOD_c mMdl;
/* 0x360 */ dShadowCircle_c mShadow;
/* 0x368 */ dCcD_Sph mSph0;
/* 0x4B8 */ dCcD_Cyl mCyl;
/* 0x608 */ dCcD_Sph mSph1;
/* 0x758 */ STATE_MGR_DECLARE(dAcOMushRoom_c);
/* 0x794 */ mAng3_c field_0x794;
/* 0x79C */ u32 field_0x79C;
/* 0x7A0 */ u8 field_0x7A0;
/* 0x7A1 */ u8 field_0x7A1;
/* 0x7A4 */ mVec3_c field_0x7A4;
/* 0x7B0 */ mVec3_c field_0x7B0;
/* 0x7BC */ f32 field_0x7BC;
/* 0x7C0 */ s32 field_0x7C0;
/* 0x7C4 */ mVec3_c field_0x7C4[3];
/* 0x7E8 */ mVec3_c field_0x7E8[3];
/* 0x80C */ mVec3_c field_0x80C[3];
/* 0x830 */ int mProcAlpha[3];
/* 0x83C */ u8 field_0x83C[3];
/* 0x83F */ u8 field_0x83F[3];
/* 0x844 */ mVec3_c field_0x844;
/* 0x850 */ s32 mCameraIdx;
/* 0x854 */ s32 field_0x854;
/* 0x858 */ LIGHT_INFLUENCE mLightInfluence;
/* 0x874 */ SHADOW_INFLUENCE mShadowInfluence;
/* 0x888 */ s32 field_0x888;
/* 0x88C */ s32 field_0x88C;
/* 0x890 */ u8 field_0x890;
/* 0x891 */ u8 field_0x891;
/* 0x892 */ u8 field_0x892;
/* 0x894 */ dAcObjRef_c mRef;
/* 0x8A0 */ dEmitter_c mEmitter;

/* 0x8D4 */ proc_c mProc[3];

// Mushroom Bin Data info
/* 0x9AC */ s32 mData_VecNum;
/* 0x9B0 */ s32 mData_IdxMax;
/* 0x9B4 */ mVec3_c *mData_pPosArr;
/* 0x9B8 */ mVec3_c *mData_pNrmArr;
/* 0x9BC */ u16 *mData_pPosIdxArr;
/* 0x9C0 */ u16 *mData_pNrmIdxArr;
};

#endif
Loading
Loading