NZ0 Elevators (#468)

These functions correspond to the two elevators in the Alchemy Lab, it's
been some time since i happen to get a match in this overlay so i think
this is good progress!

Despite the appearance, these functions were really hard to tackle,
there's some kind of variable reuse that i had to fake to get a match,
i'm leaving the scratches in case somebody wants to mess with them and
find a real match.

https://decomp.me/scratch/bnY5N
https://decomp.me/scratch/Hpxl5
This commit is contained in:
Alejandro Asenjo Nitti 2023-08-13 11:42:37 -03:00 committed by GitHub
parent ebe5b67cb3
commit 6e2ff6ea64
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
7 changed files with 269 additions and 21 deletions

View File

@ -80,7 +80,8 @@ segments:
- [0x305E8, .rodata, 33FCC] # EntityBossRoomBlock
- [0x305FC, .rodata, 33FCC] # EntitySlogra
- [0x30618, rodata] # EntityGaibon .rodata, 33FCC
- [0x3063C, rodata]
- [0x3063C, .rodata, 36DE4] # func_801B7034
- [0x3064C, rodata]
- [0x30790, .rodata, 3E30C]
- [0x307B0, .rodata, 3E30C]
- [0x307C8, rodata]

View File

@ -4,7 +4,10 @@ g_Cluts = 0x80180160;
g_TileLayers = 0x80180394;
g_EntityGfxs = 0x80180888;
PfnEntityUpdates = 0x80180A94;
g_CallElevator = 0x80180EEC;
g_BossFlag = 0x80181010;
g_ElevatorTarget = 0x801813A4;
g_ElevatorTargetPos = 0x801813A8;
UNK_Invincibility0 = 0x80181574;
c_GoldPrizes = 0x80181D14;
c_HeartPrizes = 0x80181DA4;
@ -54,6 +57,7 @@ EntityCannonLever = 0x801B23B4;
EntityCannon = 0x801B25C4;
EntityCannonShot = 0x801B2874;
EntityCannonWall = 0x801B2978;
EntityElevator2 = 0x801B2D08;
EntityFloorSpikes = 0x801B3294;
EntityTableWithGlobe = 0x801B3534;
EntityCloseBossRoom = 0x801B3FCC;
@ -65,6 +69,7 @@ EntitySlograSpearProjectile = 0x801B5654;
EntityGaibon = 0x801B5778;
EntitySmallGaibonProjectile = 0x801B6AAC;
EntityLargeGaibonProjectile = 0x801B6BBC;
EntityElevator = 0x801B7034;
EntityMariaCutscene = 0x801B7D58;
Random = 0x801B94D4;
Update = 0x801B9504;

View File

@ -294,6 +294,12 @@ typedef struct {
/* 0x84 */ s16 timer;
} ET_ShuttingWindow;
typedef struct {
/* 0x7C */ struct Primitive* prim;
/* 0x80 */ char pad_80[0x4];
/* 0x84 */ s32 elevatorTarget;
} ET_Elevator;
typedef union {
/* 0x7C */ struct Primitive* prim;
/* 0x7C */ ET_Generic generic;
@ -314,5 +320,6 @@ typedef union {
/* 0x7C */ ET_801BCC4C et_801BCC4C;
/* 0x7C */ ET_ShuttingWindow shuttingWindow;
/* 0x7C */ ET_801B2F30 et_801B2F30;
/* 0x7C */ ET_Elevator elevator;
/* 0x7C */ char stub[0x40];
} Ext;

View File

@ -1402,6 +1402,11 @@ extern s32 D_80097448; // underwater physics
extern s32 D_8009744C;
extern s32 D_80097450;
extern u16 D_8009748A[];
/*
* Elevator moving, "underflowed" to 0xFF
* when going up, 0x1 when going up
*/
extern u16 D_8009748E[];
extern Pad g_pads[PAD_COUNT];
extern Stages g_StageId;

View File

@ -891,8 +891,8 @@ void EntityCannonWall(Entity* self) {
}
void func_801B2AD8(Entity* self) {
s16 primIndex;
POLY_GT4* poly;
s16 primIndex;
s32 var_v0;
s32 var_a0;
s32 temp;
@ -901,7 +901,7 @@ void func_801B2AD8(Entity* self) {
case 0:
InitializeEntity(D_80180BF8);
self->hitboxHeight = 8;
self->hitboxOffY = -0x16;
self->hitboxOffY = -22;
self->hitboxWidth = 6;
self->hitboxState = 1;
CreateEntityFromEntity(0x26, self, &self[-1]);
@ -940,14 +940,14 @@ void func_801B2AD8(Entity* self) {
if (temp > 376) {
self->posY.i.hi = 376 - g_Camera.posY.i.hi;
}
D_80180EEC = 1;
g_CallElevator = true;
} else {
self->posY.val += 0xFFFF0000;
temp = g_Camera.posY.i.hi + self->posY.i.hi;
if (temp < 372) {
self->posY.i.hi = 372 - g_Camera.posY.i.hi;
}
D_80180EEC = 0;
g_CallElevator = false;
}
default:
@ -957,8 +957,90 @@ void func_801B2AD8(Entity* self) {
}
}
// DECOMP_ME_WIP func_801B2D08 https://decomp.me/scratch/ixW6j 93.06%
INCLUDE_ASM("asm/us/st/nz0/nonmatchings/30958", func_801B2D08);
void EntityElevator2(Entity* self) {
s32 temp = func_801BD9A0(self, 16, 5, 4);
volatile int pad[3];
Primitive* prim;
s16 primIndex;
s32 player;
s32 camY;
s32 i;
switch (self->step) {
case 0:
InitializeEntity(D_80180BF8);
self->hitboxOffX = 0;
self->hitboxOffY = 68;
g_CallElevator = false;
primIndex = g_api.AllocPrimitives(PRIM_GT4, 3);
if (primIndex == -1) {
DestroyEntity(self);
return;
}
prim = &g_PrimBuf[primIndex];
self->primIndex = primIndex;
self->ext.prim = prim;
self->flags |= FLAG_HAS_PRIMS;
prim->type = PRIM_SPRT;
prim->tpage = 0xF;
prim->clut = 9;
prim->u0 = 8;
prim->v0 = 0x80;
prim->u1 = 0x20;
prim->v1 = 0x48;
prim->priority = 0x72;
prim->blendMode = 2;
prim = prim->next;
for (i = 0; i < 2; i++) {
prim->type = PRIM_SPRT;
prim->tpage = 0xF;
prim->clut = 9;
prim->u0 = 0;
prim->v0 = 0x80;
prim->u1 = 8;
prim->v1 = 0x40;
prim->priority = 0x5F;
prim->blendMode = 2;
prim = prim->next;
}
case 1:
//! FAKE:
player = PLAYER_CHARACTER;
if (g_CallElevator) {
self->posY.i.hi--;
camY = g_Camera.posY.i.hi;
if ((self->posY.i.hi + camY) < 96) {
self->posY.i.hi = 96 - camY;
} else if (temp != 0) {
g_Entities[player].posY.i.hi--;
D_8009748E[0]--;
}
} else {
self->posY.i.hi++;
camY = g_Camera.posY.i.hi;
if ((self->posY.i.hi + camY) > 216) {
self->posY.i.hi = 216 - camY;
} else if (temp != 0) {
g_Entities[player].posY.i.hi++;
D_8009748E[0]++;
}
}
}
prim = self->ext.prim;
prim->x0 = self->posX.i.hi - 16;
prim->y0 = self->posY.i.hi;
prim = prim->next;
prim->x0 = self->posX.i.hi - 3;
prim->y0 = self->posY.i.hi - 56;
prim = prim->next;
prim->x0 = self->posX.i.hi - 3;
prim->y0 = self->posY.i.hi - 120;
}
void func_801B2FD8(Entity* self) {
s32 temp = func_801BD9A0(self, 8, 8, 4);
@ -981,7 +1063,7 @@ void func_801B2FD8(Entity* self) {
self->primIndex = primIndex;
self->ext.prim = prim;
self->flags |= FLAG_HAS_PRIMS;
prim->type = 6;
prim->type = PRIM_SPRT;
prim->tpage = 0xF;
prim->clut = 9;
prim->u0 = 0x48;
@ -1076,7 +1158,7 @@ void EntityFloorSpikes(Entity* self) {
self->primIndex = primIndex;
*((s32*)(&self->ext.generic.unk7C)) = prim;
self->flags |= FLAG_HAS_PRIMS;
prim->type = 6;
prim->type = PRIM_SPRT;
prim->tpage = 0xF;
prim->clut = 9;
prim->u0 = 0x28;

View File

@ -4,14 +4,14 @@ void func_801B6DE4(Entity* self) {
s32 temp_s1 = self->hitFlags;
s16 primIndex;
POLY_GT4* poly;
s32 temp;
s32 y;
switch (self->step) {
case 0:
InitializeEntity(D_80180BF8);
self->ext.generic.unk80.modeS32 = self->posY.i.hi + g_Camera.posY.i.hi;
self->hitboxHeight = 8;
self->hitboxOffY = -0x16;
self->hitboxOffY = -22;
self->hitboxWidth = 6;
self->hitboxState = 1;
@ -22,7 +22,7 @@ void func_801B6DE4(Entity* self) {
}
poly = &g_PrimBuf[primIndex];
self->primIndex = primIndex;
*((s32*)(&self->ext.generic.unk7C)) = poly;
self->ext.prim = poly;
self->flags |= FLAG_HAS_PRIMS;
poly->tpage = 0xF;
@ -38,13 +38,13 @@ void func_801B6DE4(Entity* self) {
case 1:
if (temp_s1 != 0) {
self->posY.val += FIX(1.0);
temp = g_Camera.posY.i.hi + self->posY.i.hi;
if ((self->ext.generic.unk80.modeS32 + 4) < temp) {
y = g_Camera.posY.i.hi + self->posY.i.hi;
if ((self->ext.generic.unk80.modeS32 + 4) < y) {
self->posY.i.hi = (u16)(self->ext.generic.unk80.modeS16.unk0 -
(g_Camera.posY.i.hi - 4));
self->step++;
func_801C29B0(NA_SE_EV_SWITCH_CLICK);
D_801813A4 = self->params;
g_ElevatorTarget = self->params;
}
}
break;
@ -52,8 +52,8 @@ void func_801B6DE4(Entity* self) {
case 2:
if (temp_s1 == 0) {
self->posY.val += 0xFFFF0000;
temp = g_Camera.posY.i.hi + self->posY.i.hi;
if (temp < self->ext.generic.unk80.modeS32) {
y = g_Camera.posY.i.hi + self->posY.i.hi;
if (y < self->ext.generic.unk80.modeS32) {
self->posY.i.hi = (u16)(self->ext.generic.unk80.modeS16.unk0) -
g_Camera.posY.i.hi;
self->step = 1;
@ -68,7 +68,154 @@ void func_801B6DE4(Entity* self) {
poly->y0 = poly->y0 - 8;
}
INCLUDE_ASM("asm/us/st/nz0/nonmatchings/36DE4", func_801B7034);
typedef enum ElevatorSubSteps {
/* 0 */ ELEVATOR_INIT,
/* 1 */ ELEVATOR_IDLE,
/* 2 */ ELEVATOR_ASCEND,
/* 3 */ ELEVATOR_DESCEND,
} ElevatorSubSteps;
void EntityElevator(Entity* self) {
Primitive* prim;
s16 primIndex;
s32 player;
s32 x, y;
s32 temp;
FntPrint("elevator:%x\n", g_ElevatorTarget);
if (g_Player.unk0C & 3) {
temp = 0;
} else {
temp = func_801BD9A0(self, 16, 5, 4);
}
//! FAKE:
player = PLAYER_CHARACTER;
switch (self->step) {
case ELEVATOR_INIT:
InitializeEntity(D_80180BF8);
self->hitboxOffX = 0;
self->hitboxOffY = 68;
self->hitboxWidth = 16;
self->hitboxHeight = 5;
self->hitboxState = 1;
if (g_ElevatorTarget != 0) {
y = g_ElevatorTargetPos[g_ElevatorTarget];
self->posY.i.hi = y - g_Camera.posY.i.hi;
} else {
g_ElevatorTarget = self->params;
}
primIndex = g_api.AllocPrimitives(PRIM_GT4, 32);
if (primIndex == -1) {
DestroyEntity(self);
return;
}
prim = &g_PrimBuf[primIndex];
self->primIndex = primIndex;
self->ext.elevator.prim = prim;
self->flags |= FLAG_HAS_PRIMS;
prim->type = PRIM_SPRT;
prim->tpage = 0xF;
prim->clut = 9;
prim->u0 = 8;
prim->v0 = 0x80;
prim->u1 = 0x20;
prim->v1 = 0x48;
prim->priority = 0x72;
prim->blendMode = 2;
prim = prim->next;
while (prim != NULL) {
prim->type = PRIM_SPRT;
prim->tpage = 0xF;
prim->clut = 9;
prim->u0 = 0;
prim->v0 = 0x80;
prim->u1 = 8;
prim->v1 = 0x40;
prim->priority = 0x5F;
prim->blendMode = 2;
prim = prim->next;
}
self->ext.elevator.elevatorTarget = g_ElevatorTarget;
case ELEVATOR_IDLE:
if (temp != 0) {
if (g_pads[0].pressed & PAD_UP) {
if (--g_ElevatorTarget < 1) {
g_ElevatorTarget = 1;
}
}
if (g_pads[0].pressed & PAD_DOWN) {
if (++g_ElevatorTarget > 3) {
g_ElevatorTarget = 3;
}
}
}
if (g_ElevatorTarget != self->ext.elevator.elevatorTarget) {
y = g_ElevatorTargetPos[g_ElevatorTarget];
y -= g_Camera.posY.i.hi;
if (y >= self->posY.i.hi) {
self->step = ELEVATOR_DESCEND;
} else {
self->step = ELEVATOR_ASCEND;
}
func_801C29B0(0x6E6);
}
self->ext.elevator.elevatorTarget = g_ElevatorTarget;
break;
case ELEVATOR_ASCEND:
self->posY.i.hi--;
y = g_ElevatorTargetPos[self->ext.elevator.elevatorTarget] -
g_Camera.posY.i.hi;
if (self->posY.i.hi >= y) {
if (temp != 0) {
g_api.func_8010DFF0(0, 1);
g_Entities[player].posY.i.hi--;
D_8009748E[0]--;
}
} else {
self->posY.i.hi = y;
self->step = ELEVATOR_IDLE;
}
break;
case ELEVATOR_DESCEND:
self->posY.i.hi++;
y = g_ElevatorTargetPos[self->ext.elevator.elevatorTarget] -
g_Camera.posY.i.hi;
if (y < self->posY.i.hi) {
self->posY.i.hi = y;
self->step = ELEVATOR_IDLE;
break;
}
if (temp != 0) {
g_api.func_8010DFF0(0, 1);
g_Entities[player].posY.i.hi++;
D_8009748E[0]++;
}
break;
}
prim = self->ext.prim;
prim->x0 = self->posX.i.hi - 16;
prim->y0 = self->posY.i.hi;
prim = prim->next;
x = self->posX.i.hi;
y = self->posY.i.hi - 56;
x -= 3;
while (prim != NULL) {
prim->x0 = x;
prim->y0 = y;
prim = prim->next;
y -= 0x40;
}
}
void func_801B74CC(void) {
D_801CB694 = 2;

View File

@ -47,7 +47,7 @@ LayoutEntity* D_801809C0[];
extern PfnEntityUpdate PfnEntityUpdates[];
extern const u16 D_80180BE0[];
extern u16 D_80180BEC[];
extern u16 D_80180BF8[];
extern u16 D_80180BF8[]; // Init Elevator2
extern u16 D_80180C1C[];
extern u16 D_80180C34[];
@ -153,7 +153,7 @@ extern u16* D_80180E94;
extern s32 D_80180EB4;
extern u16 D_80180ED4[];
extern u16 D_80180EE0[];
extern s32 D_80180EEC;
extern bool g_CallElevator;
extern const u8 D_80180EF0[];
extern const u8 D_80180EF8[];
extern u16 D_80180F10[];
@ -176,7 +176,8 @@ extern u8 D_80181218[];
extern const u8 D_8018136C[];
extern const u8 D_80181378[];
extern const u8 D_80181388[];
extern s32 D_801813A4;
extern s32 g_ElevatorTarget;
extern s16 g_ElevatorTargetPos[];
extern u16 D_801813B0[];
extern u16 UNK_Invincibility0[];
extern s16 D_80181978[];