Match Remaining Obj_Lightswitch Functions (Obj_Lightswitch OK) (#207)

* Obj_Lightswitch OK

* Minor improvement

* PR Cleanup
This commit is contained in:
engineer124 2021-07-14 12:12:32 +10:00 committed by GitHub
parent 12217a2081
commit afad253fa8
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
4 changed files with 80 additions and 151 deletions

View File

@ -2565,7 +2565,7 @@ SECTIONS
build/src/overlays/actors/ovl_Obj_Lightswitch/z_obj_lightswitch.o(.text)
build/src/overlays/actors/ovl_Obj_Lightswitch/z_obj_lightswitch.o(.data)
build/src/overlays/actors/ovl_Obj_Lightswitch/z_obj_lightswitch.o(.rodata)
build/asm/overlays/ovl_Obj_Lightswitch_rodata.o(.rodata)
build/src/overlays/actors/ovl_Obj_Lightswitch/z_obj_lightswitch_overlay.o(.ovl)
}
SegmentEnd = .;
SegmentSize = SegmentEnd - SegmentStart;

View File

@ -549,9 +549,12 @@ D_06001180 = 0x06001180;
D_06001A70 = 0x06001A70;
/* z_obj_lightswitch */
D_06000C20 = 0x6000C20;
D_06000420 = 0x6000420;
D_06001420 = 0x6001420;
D_06000260 = 0x06000260;
D_06000398 = 0x06000398;
D_06000408 = 0x06000408;
D_06000420 = 0x06000420;
D_06000C20 = 0x06000C20;
D_06001420 = 0x06001420;
/* z_obj_milk_bin */
D_060004B0 = 0x060004B0;

View File

@ -20,6 +20,10 @@ void ObjLightSwitch_SetupDisabled(ObjLightswitch* this);
void ObjLightSwitch_Disabled(ObjLightswitch* this, GlobalContext* globalCtx);
void ObjLightswitch_Idle(ObjLightswitch* this, GlobalContext* globalCtx);
extern Gfx D_06000260[];
extern Gfx D_06000398[];
extern Gfx D_06000408[];
const ActorInit Obj_Lightswitch_InitVars = {
ACTOR_OBJ_LIGHTSWITCH,
ACTORCAT_SWITCH,
@ -60,24 +64,15 @@ static ColliderJntSphInit sJntSphInit = {
};
// different face addresses for (sleep -> waking -> awake) of light switch face
Gfx* lightswitchFaceGfx[] = {
static Gfx* sLightswitchFaceGfx[] = {
D_06000C20,
D_06000420,
D_06001420,
};
Color_RGBA8 lightswitchEffectPrimColor = {
0xFF,
0xFF,
0xA0,
0xA0,
};
Color_RGBA8 lightswitchEffectEnvColor = {
0xFF,
0x0,
0x0,
0x0,
};
static Color_RGBA8 sLightswitchEffectPrimColor = { 255, 255, 160, 160 };
static Color_RGBA8 sLightswitchEffectEnvColor = { 255, 0, 0, 0 };
static InitChainEntry sInitChain[] = {
ICHAIN_VEC3F_DIV1000(scale, 100, ICHAIN_CONTINUE),
@ -91,7 +86,7 @@ void ObjLightswitch_InitCollider(ObjLightswitch* this, GlobalContext* globalCtx)
Collider_InitJntSph(globalCtx, &this->collider);
Collider_SetJntSph(globalCtx, &this->collider, &this->actor, &sJntSphInit, &this->elements);
this->actor.colChkInfo.mass = 0xFF;
this->actor.colChkInfo.mass = MASS_IMMOVABLE;
SysMatrix_SetStateRotationAndTranslation(
this->actor.world.pos.x, this->actor.world.pos.y + (this->actor.shape.yOffset * this->actor.scale.y),
this->actor.world.pos.z, &this->actor.shape.rot);
@ -109,89 +104,58 @@ void ObjLightswitch_UpdateSwitchFlags(ObjLightswitch* this, GlobalContext* globa
}
}
#if NON_EQUIVELENT
// issues: a lot of ordering issues leading up to the big effect spawn function call
// there are a lot of temps, some might have been removed that were required by accident
// however, constantly on the edge of stack oversize, so something has to go
void ObjLightswitch_SpawnEffects(ObjLightswitch* this, GlobalContext* globalCtx) {
Vec3f effectPos;
f32 sinResult;
f32 cosResult;
f32 tempResult;
f32 tempResult2; // must exist because of condition assignemt?
f32 tempResult_shorter; // tempResult - 30
f32 randomOutput;
f32 tempResult5;
f32 tempResultDiff;
f32 rand;
s32 alpha;
sinResult = Math_SinS(this->actor.shape.rot.y);
cosResult = Math_CosS(this->actor.shape.rot.y);
if (this->colorAlpha >= 0x1900) {
// late rodata: 6.127451e-05f = 1 / 16320 ?
tempResult = (1.0f - (this->colorAlpha * 6.127451e-05f)) * 400.0f;
alpha = this->colorAlpha;
if (tempResult > 60.0f) {
tempResult2 = 60.0f;
} else {
tempResult2 = tempResult;
}
tempResult = Rand_ZeroOne() * ((tempResult2 - 30.0f) + 30.0f);
tempResult_shorter = tempResult - 30.0f;
if (alpha >= (100 << 6)) {
tempResult = (1.0f - (alpha * (1.0f / (255 << 6)))) * 400.0f;
tempResult = ((CLAMP_MAX(tempResult, 60.0f) - 30.0f) + 30.0f) * Rand_ZeroOne();
tempResultDiff = tempResult - 30.0f;
if (tempResult > 30.0f) {
tempResult = 30.0f;
} else {
tempResult = 900.0f - SQ(tempResult_shorter);
if (tempResult < 100.0f) {
tempResult = 100.0f;
}
tempResult = SQ(30.0f) - SQ(tempResultDiff);
tempResult = CLAMP_MIN(tempResult, SQ(10.0f));
tempResult = sqrtf(tempResult);
}
tempResult5 = 2.0f * ((Rand_ZeroOne() - 0.5f) * tempResult);
tempResult = 2.0f * ((Rand_ZeroOne() - 0.5f) * tempResult);
rand = ((30.0f - fabsf(tempResult)) * 0.5f) + (Rand_ZeroOne() * 10.0f);
// permuter seems to think something could be added to fix ordering here, but doesn't fix enough
// goto dummy_label_809848; dummy_label_809848: ; // minor regalloc fix
// if (cosResult){} // minor regalloc fix, but breaks some code
effectPos.x = this->actor.world.pos.x + ((rand * sinResult) + (tempResult * cosResult));
effectPos.y = this->actor.world.pos.y + tempResultDiff + 10.0f;
effectPos.z = this->actor.world.pos.z + ((rand * cosResult) - (tempResult * sinResult));
// saving fabsf result as a temp might help, but need to reduce temps
// fabsResult = fabsf(tempResult5);
// randomOutput = (Rand_ZeroOne() * 10.0f) + ((30.0f - fabsResult) * 0.5f);
// randomOutput = fabsf(tempResult5);
// randomOutput = (Rand_ZeroOne() * 10.0f) + ((30.0f - randomOutput) * 0.5f);
randomOutput = (Rand_ZeroOne() * 10.0f) + ((30.0f - fabsf(tempResult5)) * 0.5f);
effectPos.x = this->actor.world.pos.x + ((randomOutput * sinResult) + (tempResult5 * cosResult));
effectPos.y = this->actor.world.pos.y + tempResult_shorter + 10.0f;
effectPos.z = this->actor.world.pos.z + ((randomOutput * cosResult) - (tempResult5 * sinResult));
// weirdly, using a temp here make a big difference, but.. is that right? just one temp? prob ordering issue
// above
// tempResult = this->actor.world.pos.z + ((randomOutput * cosResult) - (tempResult5 * sinResult));
// effectPos.z = tempResult;
EffectSsDeadDb_Spawn(globalCtx, &effectPos, &D_801D15B0, &D_801D15B0, &lightswitchEffectPrimColor,
&lightswitchEffectEnvColor, 100, 0, 9);
EffectSsDeadDb_Spawn(globalCtx, &effectPos, &D_801D15B0, &D_801D15B0, &sLightswitchEffectPrimColor,
&sLightswitchEffectEnvColor, 100, 0, 9);
}
}
#else
void ObjLightswitch_SpawnEffects(ObjLightswitch* this, GlobalContext* globalCtx);
#pragma GLOBAL_ASM("./asm/non_matchings/overlays/ovl_Obj_Lightswitch_0x8095FBF0/ObjLightswitch_SpawnEffects.asm")
#endif
void ObjLightswitch_Init(Actor* thisx, GlobalContext* globalCtx) {
ObjLightswitch* this = THIS;
s32 pad;
u32 switchFlagResult;
u32 isSwitchActivated;
s32 isTriggered;
switchFlagResult = Flags_GetSwitch(globalCtx, GET_LIGHTSWITCH_SWITCHFLAG(this));
isTriggered = 0;
isSwitchActivated = Flags_GetSwitch(globalCtx, GET_LIGHTSWITCH_SWITCHFLAG(this));
isTriggered = false;
Actor_ProcessInitChain(&this->actor, sInitChain);
Actor_SetHeight(&this->actor, 0.0f);
if (switchFlagResult != 0) {
if (isSwitchActivated) {
if (GET_LIGHTSWITCH_TYPE(this) == LIGHTSWITCH_TYPE_FAKE) {
isTriggered = 1;
isTriggered = true;
} else {
ObjLightSwitch_SetupEnabled(this);
}
@ -235,10 +199,10 @@ void ObjLightswitch_PlayCinema(ObjLightswitch* this, GlobalContext* globalCtx) {
void ObjLightswitch_SetupIdle(ObjLightswitch* this) {
this->faceState = LIGHTSWITCH_FACE_ASLEEP;
this->colorR = 0x26C0;
this->colorG = 0x1F40;
this->colorB = 0x3FC0;
this->colorAlpha = 0x3FC0;
this->colorR = 155 << 6;
this->colorG = 125 << 6;
this->colorB = 255 << 6;
this->colorAlpha = 255 << 6;
this->actionFunc = ObjLightswitch_Idle;
}
@ -271,8 +235,8 @@ void ObjLightSwitch_Asleep(ObjLightswitch* this, GlobalContext* globalCtx) {
Math_StepToS(&this->edgeRotSpeed, -0xAA, 0xA);
this->edgeRot += this->edgeRotSpeed;
this->colorR = (this->colorShiftTimer * 0x140) + 0x26C0;
this->colorG = (this->colorShiftTimer * 0x1A0) + 0x1F40;
this->colorR = (this->colorShiftTimer * (5 << 6)) + (155 << 6);
this->colorG = (this->colorShiftTimer * ((6 << 6) + 32)) + (125 << 6);
if (this->colorShiftTimer >= 20) {
ObjLightSwitch_SetupEnabled(this);
@ -284,10 +248,10 @@ void ObjLightSwitch_Asleep(ObjLightswitch* this, GlobalContext* globalCtx) {
void ObjLightSwitch_SetupEnabled(ObjLightswitch* this) {
this->faceState = LIGHTSWITCH_FACE_FULLAWAKE;
this->colorR = 0x3FC0;
this->colorG = 0x3FC0;
this->colorB = 0x3FC0;
this->colorAlpha = 0x3FC0;
this->colorR = 255 << 6;
this->colorG = 255 << 6;
this->colorB = 255 << 6;
this->colorAlpha = 255 << 6;
this->edgeRotSpeed = -0xAA;
this->colorShiftTimer = 0;
this->actionFunc = ObjLightSwitch_Enabled;
@ -298,7 +262,7 @@ void ObjLightSwitch_Enabled(ObjLightswitch* this, GlobalContext* globalCtx) {
if (actorType == LIGHTSWITCH_TYPE_REGULAR) {
// switch can be disabled outside of this actor by flag
if (Flags_GetSwitch(globalCtx, GET_LIGHTSWITCH_SWITCHFLAG(this)) == 0) {
if (!Flags_GetSwitch(globalCtx, GET_LIGHTSWITCH_SWITCHFLAG(this))) {
ObjLightSwitch_SetupDisabled(this);
}
} else if (actorType == LIGHTSWITCH_TYPE_FLIP) {
@ -311,7 +275,7 @@ void ObjLightSwitch_Enabled(ObjLightswitch* this, GlobalContext* globalCtx) {
ObjLightswitch_UpdateSwitchFlags(this, globalCtx, 0);
ObjLightSwitch_SetupDisabled(this);
} else {
this->colorShiftTimer += 1;
this->colorShiftTimer++;
}
} else {
this->colorShiftTimer = 0;
@ -329,8 +293,8 @@ void ObjLightSwitch_Disabled(ObjLightswitch* this, GlobalContext* globalCtx) {
this->colorShiftTimer--;
Math_StepToS(&this->edgeRotSpeed, 0, 0xA);
this->edgeRot += this->edgeRotSpeed;
this->colorR = (this->colorShiftTimer * 0x140) + 0x26C0;
this->colorG = (this->colorShiftTimer * 0x1A0) + 0x1F40;
this->colorR = (this->colorShiftTimer * (5 << 6)) + (155 << 6);
this->colorG = (this->colorShiftTimer * ((6 << 6) + 32)) + (125 << 6);
if (this->colorShiftTimer <= 0) {
ObjLightswitch_SetupIdle(this);
@ -341,12 +305,12 @@ void ObjLightSwitch_Disabled(ObjLightswitch* this, GlobalContext* globalCtx) {
}
void ObjLightSwitch_SetupFade(ObjLightswitch* this) {
this->colorAlpha = 0x3FC0;
this->colorAlpha = 255 << 6;
this->actionFunc = ObjLightSwitch_Fade;
}
void ObjLightSwitch_Fade(ObjLightswitch* this, GlobalContext* globalCtx) {
this->colorAlpha -= 0xC8;
this->colorAlpha -= 200;
ObjLightswitch_SpawnEffects(this, globalCtx); // spawn burning fire effect
if (this->colorAlpha < 0) {
Actor_MarkForDeath(&this->actor);
@ -389,126 +353,88 @@ void ObjLightswitch_Update(Actor* thisx, GlobalContext* globalCtx) {
}
this->actionFunc(this, globalCtx);
if (this->actor.update != 0) {
if (this->actor.update != NULL) {
this->previousACFlags = this->collider.base.acFlags;
CollisionCheck_SetOC(globalCtx, &globalCtx->colChkCtx, &this->collider.base);
CollisionCheck_SetAC(globalCtx, &globalCtx->colChkCtx, &this->collider.base);
}
}
#if NON_EQUIVELENT
// gDPSetEnvColor parameter load order is different than the order in which the value is built
// also massive regalloc probably caused by the above
void ObjLightSwitch_DrawOpa(ObjLightswitch* this, GlobalContext* globalCtx) {
s32 pad;
Vec3f tempPos;
Vec3s tempRot;
OPEN_DISPS(globalCtx->state.gfxCtx);
func_8012C28C(globalCtx->state.gfxCtx);
// temp_v0->words.w1 = ((((s32) this->colorB >> 6) & 0xFF) << 8)
//| (((s32) this->colorR >> 6) << 0x18)
//| ((((s32) this->colorG >> 6) & 0xFF) << 0x10)
//| (((s32) this->colorAlpha >> 6) & 0xFF);
// load order issues with loading this in the right order for the function
gDPSetEnvColor(POLY_OPA_DISP++, this->colorR >> 6, this->colorG >> 6, this->colorB >> 6, this->colorAlpha >> 6);
gSPSegment(POLY_OPA_DISP++, 0x09, D_801AEFA0);
gDPSetEnvColor(POLY_OPA_DISP++, (u8)(this->colorR >> 6), (u8)(this->colorG >> 6), (0, (u8)(this->colorB >> 6)), (u8)(this->colorAlpha >> 6));
gSPSegment(POLY_OPA_DISP++, 0x09, &D_801AEFA0);
tempPos.x = this->actor.world.pos.x;
tempPos.y = this->actor.world.pos.y + (this->actor.shape.yOffset * this->actor.scale.y);
tempPos.z = this->actor.world.pos.z;
gSPMatrix(POLY_OPA_DISP++, Matrix_NewMtx(globalCtx->state.gfxCtx), G_MTX_NOPUSH | G_MTX_LOAD | G_MTX_MODELVIEW);
gSPSegment(POLY_OPA_DISP++, 0x08, Lib_SegmentedToVirtual(D_80960BC4[this->faceState]));
gSPDisplayList(POLY_OPA_DISP++, 0x6000260);
gSPSegment(POLY_OPA_DISP++, 0x08, Lib_SegmentedToVirtual(sLightswitchFaceGfx[this->faceState]));
gSPDisplayList(POLY_OPA_DISP++, D_06000260);
tempRot.x = this->actor.shape.rot.x;
tempRot.y = this->actor.shape.rot.y;
tempRot.z = this->actor.shape.rot.z + this->edgeRot;
SysMatrix_SetStateRotationAndTranslation(tempPos.z, tempPos.y, tempPos.x, &tempRot);
Matrix_Scale(this->actor.scale.x, this->actor.scale.y, this->actor.scale.z, 1);
SysMatrix_SetStateRotationAndTranslation(tempPos.x, tempPos.y, tempPos.z, &tempRot);
Matrix_Scale(this->actor.scale.x, this->actor.scale.y, this->actor.scale.z, MTXMODE_APPLY);
gSPMatrix(POLY_OPA_DISP++, Matrix_NewMtx(globalCtx->state.gfxCtx), G_MTX_NOPUSH | G_MTX_LOAD | G_MTX_MODELVIEW);
gSPDisplayList(POLY_OPA_DISP++, 0x6000398);
gSPDisplayList(POLY_OPA_DISP++, D_06000398);
tempRot.z = this->actor.shape.rot.z - this->edgeRot;
SysMatrix_SetStateRotationAndTranslation(tempPos.z, tempPos.y, tempPos.x, &tempRot);
Matrix_Scale(this->actor.scale.x, this->actor.scale.y, this->actor.scale.z, 1);
SysMatrix_SetStateRotationAndTranslation(tempPos.x, tempPos.y, tempPos.z, &tempRot);
Matrix_Scale(this->actor.scale.x, this->actor.scale.y, this->actor.scale.z, MTXMODE_APPLY);
gSPMatrix(POLY_OPA_DISP++, Matrix_NewMtx(globalCtx->state.gfxCtx), G_MTX_NOPUSH | G_MTX_LOAD | G_MTX_MODELVIEW);
gSPDisplayList(POLY_OPA_DISP++, 0x6000408);
gSPDisplayList(POLY_OPA_DISP++, D_06000408);
CLOSE_DISPS(globalCtx->state.gfxCtx);
}
#else
void ObjLightSwitch_DrawOpa(ObjLightswitch* this, GlobalContext* globalCtx);
#pragma GLOBAL_ASM("./asm/non_matchings/overlays/ovl_Obj_Lightswitch_0x8095FBF0/ObjLightSwitch_DrawOpa.asm")
#endif
#if NON_EQUIVELENT
// same issue as above
void ObjLightSwitch_DrawXlu(ObjLightswitch* this, GlobalContext* globalCtx) {
s32 pad;
Vec3f tempPos;
Vec3s tempRot;
OPEN_DISPS(globalCtx->state.gfxCtx);
func_8012C2DC(globalCtx->state.gfxCtx);
// temp_v0->words.w1 = ((((s32) this->colorB >> 6) & 0xFF) << 8)
//| (((s32) this->colorR >> 6) << 0x18)
//| ((((s32) this->colorG >> 6) & 0xFF) << 0x10)
//| (((s32) this->colorAlpha >> 6) & 0xFF);
gDPSetEnvColor(POLY_XLU_DISP++, this->colorR >> 6, this->colorG >> 6, this->colorB >> 6, this->colorAlpha >> 6);
gSPSegment(POLY_XLU_DISP++, 0x09, D_801AEF88);
gDPSetEnvColor(POLY_XLU_DISP++, (u8)(this->colorR >> 6), (u8)(this->colorG >> 6), (0, (u8)(this->colorB >> 6)), (u8)(this->colorAlpha >> 6));
gSPSegment(POLY_XLU_DISP++, 0x09, &D_801AEF88);
tempPos.x = this->actor.world.pos.x;
tempPos.y = this->actor.world.pos.y + (this->actor.shape.yOffset * this->actor.scale.y);
tempPos.z = this->actor.world.pos.z;
gSPMatrix(POLY_XLU_DISP++, Matrix_NewMtx(globalCtx->state.gfxCtx), G_MTX_NOPUSH | G_MTX_LOAD | G_MTX_MODELVIEW);
gSPSegment(POLY_XLU_DISP++, 0x08, Lib_SegmentedToVirtual(D_80960BC4[this->faceState]));
gSPDisplayList(POLY_XLU_DISP++, 0x6000260);
gSPSegment(POLY_XLU_DISP++, 0x08, Lib_SegmentedToVirtual(sLightswitchFaceGfx[this->faceState]));
gSPDisplayList(POLY_XLU_DISP++, D_06000260);
tempRot.x = this->actor.shape.rot.x;
tempRot.y = this->actor.shape.rot.y;
tempRot.z = this->actor.shape.rot.z + this->edgeRot;
SysMatrix_SetStateRotationAndTranslation(tempPos.x, tempPos.y, tempPos.z, &tempRot);
Matrix_Scale(this->actor.scale.x, this->actor.scale.y, this->actor.scale.z, 1);
Matrix_Scale(this->actor.scale.x, this->actor.scale.y, this->actor.scale.z, MTXMODE_APPLY);
gSPMatrix(POLY_XLU_DISP++, Matrix_NewMtx(globalCtx->state.gfxCtx), G_MTX_NOPUSH | G_MTX_LOAD | G_MTX_MODELVIEW);
gSPDisplayList(POLY_XLU_DISP++, 0x6000398);
gSPDisplayList(POLY_XLU_DISP++, D_06000398);
tempRot.z = this->actor.shape.rot.z - this->edgeRot;
SysMatrix_SetStateRotationAndTranslation(tempPos.x, tempPos.y, tempPos.z, &tempRot);
Matrix_Scale(this->actor.scale.x, this->actor.scale.y, this->actor.scale.z, 1);
Matrix_Scale(this->actor.scale.x, this->actor.scale.y, this->actor.scale.z, MTXMODE_APPLY);
gSPMatrix(POLY_XLU_DISP++, Matrix_NewMtx(globalCtx->state.gfxCtx), G_MTX_NOPUSH | G_MTX_LOAD | G_MTX_MODELVIEW);
gSPDisplayList(POLY_XLU_DISP++, 0x6000408);
gSPDisplayList(POLY_XLU_DISP++, D_06000408);
CLOSE_DISPS(globalCtx->state.gfxCtx);
}
#else
void ObjLightSwitch_DrawXlu(ObjLightswitch* this, GlobalContext* globalCtx);
#pragma GLOBAL_ASM("./asm/non_matchings/overlays/ovl_Obj_Lightswitch_0x8095FBF0/ObjLightSwitch_DrawXlu.asm")
#endif
void ObjLightswitch_Draw(Actor* thisx, GlobalContext* globalCtx) {
ObjLightswitch* this = THIS;
s32 alpha = (this->colorAlpha >> 6) & 0xFF;
s32 alpha = (u8)(this->colorAlpha >> 6);
if ((GET_LIGHTSWITCH_TYPE(this) == LIGHTSWITCH_TYPE_FAKE) && (alpha > 0) && (alpha < 0xFF)) {
if ((GET_LIGHTSWITCH_TYPE(this) == LIGHTSWITCH_TYPE_FAKE) && (alpha > 0) && (alpha < 255)) {
ObjLightSwitch_DrawXlu(this, globalCtx);
} else {
ObjLightSwitch_DrawOpa(this, globalCtx);

View File

@ -9396,9 +9396,9 @@
0x80960B70:("Obj_Lightswitch_InitVars","UNK_TYPE1","",0x1),
0x80960B90:("D_80960B90","UNK_TYPE1","",0x1),
0x80960BB4:("D_80960BB4","UNK_TYPE1","",0x1),
0x80960BC4:("lightswitchFaceGfx","UNK_TYPE1","",0x1),
0x80960BD0:("lightswitchEffectPrimColor","UNK_TYPE1","",0x1),
0x80960BD4:("lightswitchEffectEnvColor","UNK_TYPE1","",0x1),
0x80960BC4:("sLightswitchFaceGfx","UNK_TYPE1","",0x1),
0x80960BD0:("sLightswitchEffectPrimColor","UNK_TYPE1","",0x1),
0x80960BD4:("sLightswitchEffectEnvColor","UNK_TYPE1","",0x1),
0x80960BD8:("D_80960BD8","UNK_TYPE1","",0x1),
0x80960BF0:("D_80960BF0","f32","",0x4),
0x80960C00:("objLightswitchOverlayInfo","OverlayRelocationSection","",0x14),