Decompile NO3 EntityDeathCutscene (#1309)

As far as the duplicate-finder can tell, this is the last of the
cutscenes, but who knows - we may find more. Luckily, the pattern is
pretty recognizable.

Named it due to what we see at the very end in `case 7`, with the
TimeAttackController getting triggered.
This commit is contained in:
bismurphy 2024-06-12 13:09:19 -04:00 committed by GitHub
parent 350559c0b8
commit 4ae980706e
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
6 changed files with 756 additions and 279 deletions

View File

@ -60,9 +60,9 @@ segments:
- [0x373E8, .rodata, 377D4] # EntityCastleDoor - [0x373E8, .rodata, 377D4] # EntityCastleDoor
- [0x37400, .rodata, 377D4] # EntityStairwayPiece - [0x37400, .rodata, 377D4] # EntityStairwayPiece
- [0x37414, .rodata, 3C4EC] - [0x37414, .rodata, 3C4EC]
- [0x3742C, .rodata, 3E134] - [0x3742C, .rodata, 3E134] #EntityFlyingOwlAndLeaves
- [0x37440, rodata] - [0x37440, rodata]
- [0x37458, rodata] - [0x37458, .rodata, deathcutscene] # EntityDeathCutscene
- [0x374DC, .rodata, 3FF00] # EntityRoomTransition2 - [0x374DC, .rodata, 3FF00] # EntityRoomTransition2
- [0x374F4, .rodata, 3FF00] # EntityDeathStolenItems - [0x374F4, .rodata, 3FF00] # EntityDeathStolenItems
- [0x37514, .rodata, 3FF00] # EntityDeath - [0x37514, .rodata, 3FF00] # EntityDeath
@ -82,6 +82,7 @@ segments:
- [0x377D4, c] - [0x377D4, c]
- [0x3C4EC, c] - [0x3C4EC, c]
- [0x3E134, c] - [0x3E134, c]
- [0x3E544, c, deathcutscene]
- [0x3FF00, c] - [0x3FF00, c]
- [0x4184C, c, random] - [0x4184C, c, random]
- [0x4187C, c, update] - [0x4187C, c, update]

View File

@ -74,7 +74,7 @@ EntityBackgroundTrees = 0x801BDEB0;
EntityBackgroundCastleWall = 0x801BE080; EntityBackgroundCastleWall = 0x801BE080;
EntityFlyingOwlAndLeaves = 0x801BE134; EntityFlyingOwlAndLeaves = 0x801BE134;
EntityFallingLeaf = 0x801BE444; EntityFallingLeaf = 0x801BE444;
EntityRoomTransition1 = 0x801BEEB0; EntityDeathCutscene = 0x801BEEB0;
EntityRoomTransition2 = 0x801BFF00; EntityRoomTransition2 = 0x801BFF00;
EntityDeathStolenItem = 0x801C033C; EntityDeathStolenItem = 0x801C033C;
EntityDeath = 0x801C083C; EntityDeath = 0x801C083C;

View File

@ -129,269 +129,3 @@ void EntityFallingLeaf(Entity* entity) {
break; break;
} }
} }
void func_801BE544(void) {
D_801D7D30 = 0x182;
D_801D7D2E = 0x182;
D_801D7D32 = 0;
D_801D7D36 = 0;
D_801D7D3A = 0;
D_801D7D3B = 8;
D_801D7D2A = D_801D7D2C + 0x14;
}
s32 func_801BE598(s32 textDialogue) {
Primitive* prim;
s16 firstPrimIndex;
firstPrimIndex = g_api.AllocPrimitives(PRIM_SPRT, 7);
g_Dialogue.primIndex[2] = firstPrimIndex;
if (firstPrimIndex == -1) {
g_Dialogue.primIndex[2] = 0;
return 0;
}
g_Dialogue.nextCharDialogue = textDialogue;
g_Dialogue.unk3C = 0;
g_Dialogue.primIndex[1] = -1;
g_Dialogue.primIndex[0] = -1;
func_801BE544();
//! FAKE:
if (prim && prim) {
}
prim = g_Dialogue.prim[0] = &g_PrimBuf[g_Dialogue.primIndex[2]];
prim->drawMode = DRAW_HIDE;
prim = g_Dialogue.prim[1] = prim->next;
prim->drawMode = DRAW_HIDE;
prim = g_Dialogue.prim[2] = prim->next;
prim->drawMode = DRAW_HIDE;
prim = g_Dialogue.prim[3] = prim->next;
prim->drawMode = DRAW_HIDE;
prim = g_Dialogue.prim[4] = prim->next;
prim->drawMode = DRAW_HIDE;
prim = g_Dialogue.prim[5] = prim->next;
prim->type = 4;
prim->drawMode = DRAW_HIDE;
prim = prim->next;
prim->type = 3;
prim->r0 = prim->r1 = prim->r2 = prim->r3 = 0xFF;
prim->g0 = prim->g1 = prim->g2 = prim->g3 = 0;
prim->b0 = prim->b1 = prim->b2 = prim->b3 = 0;
prim->x0 = prim->x2 = 4;
prim->x1 = prim->x3 = 0xF8;
prim->priority = 0x1FD;
prim->drawMode = DRAW_HIDE;
prim = prim->next;
prim->type = 1;
prim->x0 = 3;
prim->y0 = 0x2F;
prim->v0 = 0x4A;
prim->r0 = prim->g0 = prim->b0 = 0xFF;
prim->priority = 0x1FC;
prim->drawMode = DRAW_HIDE;
return 1;
}
void func_801BE75C(s16 yOffset) {
RECT rect;
rect.x = 384;
rect.y = (yOffset * 12) + 256;
rect.w = 64;
rect.h = 12;
ClearImage(&rect, 0, 0, 0);
}
void func_801BE7BC(void) {
Primitive* prim;
func_801BE75C(g_Dialogue.nextCharY);
prim = g_Dialogue.prim[g_Dialogue.nextCharY];
prim->tpage = 0x16;
prim->clut = g_Dialogue.clutIndex;
prim->y0 = g_Dialogue.nextLineY;
prim->u0 = 0;
prim->x0 = g_Dialogue.startX;
prim->x0 = prim->x0 + 4;
prim->v0 = g_Dialogue.nextCharY * 0xC;
prim->u1 = 0xC0;
prim->v1 = 0xC;
prim->priority = 0x1FF;
prim->drawMode = DRAW_DEFAULT;
}
// Creates primitives for the actor name at the head of the dialogue
void func_801BE870(u16 actorIndex, Entity* self) {
Primitive* prim;
s16 primIndex;
s32 x;
u16 chCount;
const char* actorName;
char ch;
actorName = D_80181ACC[actorIndex];
chCount = 0;
while (true) {
ch = *actorName++;
if (ch == DIAG_EOL) {
ch = *actorName++;
if (ch == DIAG_EOS) {
break;
}
}
if (ch == MENUCHAR(' ')) {
continue;
}
chCount++;
}
// Create chCount amount of sprites based on the actor name's letter count
primIndex = g_api.AllocPrimitives(PRIM_SPRT, chCount);
if (primIndex == -1) {
DestroyEntity(self);
return;
}
// Fill prims to render the actor name on screen
prim = &g_PrimBuf[primIndex];
g_Dialogue.primIndex[1] = primIndex;
actorName = D_80181ACC[actorIndex];
x = 0x38;
while (prim != NULL) {
ch = *actorName++;
if (ch == MENUCHAR(' ')) {
x += FONT_SPACE;
} else {
prim->type = PRIM_SPRT;
prim->tpage = 0x1E;
prim->clut = 0x196;
prim->u0 = (ch & 0x0F) * FONT_W;
prim->v0 = (ch & 0xF0) / (FONT_H / 4);
prim->v1 = FONT_H;
prim->u1 = FONT_W;
prim->priority = 0x1FF;
prim->drawMode = DRAW_HIDE;
prim->x0 = x;
prim->y0 = g_Dialogue.startY + 6;
prim = prim->next;
x += FONT_GAP;
}
}
}
void func_801BE9F4(s32 arg0) {
g_Dialogue.unk40 = arg0 + 0x100000;
g_Dialogue.timer = 0;
g_Dialogue.unk3C = 1;
}
void func_801BEA20(void) {
Entity* entity;
u16 startTimer;
u8 entityIndex;
g_Dialogue.timer++;
// protect from overflows
if (g_Dialogue.timer > 0xFFFE) {
g_Dialogue.unk3C = 0;
return;
}
while (true) {
// Start the dialogue script only if the start timer has passed
startTimer = (*g_Dialogue.unk40++ << 8) | *g_Dialogue.unk40++;
if (g_Dialogue.timer < startTimer) {
// Re-evaluate the condition at the next frame
g_Dialogue.unk40 -= 2;
return;
}
switch (*g_Dialogue.unk40++) {
case 0:
entityIndex = *g_Dialogue.unk40++;
entity = &g_Entities[STAGE_ENTITY_START + entityIndex];
DestroyEntity(entity);
entity->entityId = *g_Dialogue.unk40++;
entity->pfnUpdate = PfnEntityUpdates[entity->entityId - 1];
entity->posX.i.hi = *g_Dialogue.unk40++ * 0x10;
entity->posX.i.hi = *g_Dialogue.unk40++ | entity->posX.i.hi;
entity->posY.i.hi = *g_Dialogue.unk40++ * 0x10;
entity->posY.i.hi = *g_Dialogue.unk40++ | entity->posY.i.hi;
break;
case 1:
entityIndex = *g_Dialogue.unk40++;
entity = &g_Entities[STAGE_ENTITY_START + entityIndex];
DestroyEntity(entity);
break;
case 2:
if (!((D_801D7DD0 >> *g_Dialogue.unk40) & 1)) {
g_Dialogue.unk40--;
return;
}
D_801D7DD0 &= ~(1 << *g_Dialogue.unk40++);
break;
case 3:
D_801D7DD0 |= 1 << *g_Dialogue.unk40++;
break;
}
}
}
void func_801BECCC(Entity* self) {
if (g_pads[0].tapped == PAD_START) {
D_801D7D20 = 1;
g_api.FreePrimitives(self->primIndex);
self->flags ^= FLAG_HAS_PRIMS;
if (g_Dialogue.primIndex[1] != -1) {
g_api.FreePrimitives(g_Dialogue.primIndex[1]);
}
if (g_Dialogue.primIndex[0] != -1) {
g_api.FreePrimitives(g_Dialogue.primIndex[0]);
}
g_api.PlaySfx(SET_STOP_MUSIC);
self->step = 1;
self->step_s = 0;
}
}
// Animates the portrait size of the actor by enlarging or shrinking it
void func_801BEDAC(u8 ySteps) {
Primitive* prim;
s32 primIndex;
s32 i;
primIndex = g_Dialogue.nextCharY + 1;
while (primIndex >= 5) {
primIndex -= 5;
}
if (g_CurrentEntity->step_s == 0) {
prim = g_Dialogue.prim[primIndex];
prim->v1 -= ySteps;
prim->v0 += ySteps;
if (prim->v1 == 0) {
g_CurrentEntity->step_s++;
prim->drawMode = DRAW_HIDE;
}
}
for (i = 0; i < 5; i++) {
if (i != primIndex) {
prim = g_Dialogue.prim[i];
prim->y0 -= ySteps;
}
}
g_Dialogue.portraitAnimTimer++;
}
// seems to cause a room transition
INCLUDE_ASM("st/no3/nonmatchings/3E134", EntityRoomTransition1);

View File

@ -102,7 +102,7 @@ void EntityRoomTransition2(Entity* self) {
tilemap->y = 0; tilemap->y = 0;
D_8003C8B8 = 1; D_8003C8B8 = 1;
DestroyEntity(gents); DestroyEntity(gents);
CreateEntityFromCurrentEntity(E_ID_17, gents); CreateEntityFromCurrentEntity(E_BG_LIGHTNING, gents);
} }
g_Player.padSim = 0; g_Player.padSim = 0;
g_Player.D_80072EFC = 1; g_Player.D_80072EFC = 1;

735
src/st/no3/deathcutscene.c Normal file
View File

@ -0,0 +1,735 @@
#include "no3.h"
void func_801BE544(void) {
g_Dialogue.nextLineX = 0x182; // Note that these two lines are "= 2"
g_Dialogue.nextCharX = 0x182; // for all other cutscenes (so far)!
g_Dialogue.nextCharY = 0;
g_Dialogue.unk12 = 0;
g_Dialogue.nextCharTimer = 0;
g_Dialogue.unk17 = 8;
g_Dialogue.nextLineY = g_Dialogue.startY + 0x14;
}
s32 func_801BE598(s32 textDialogue) {
Primitive* prim;
s16 firstPrimIndex;
firstPrimIndex = g_api.AllocPrimitives(PRIM_SPRT, 7);
g_Dialogue.primIndex[2] = firstPrimIndex;
if (firstPrimIndex == -1) {
g_Dialogue.primIndex[2] = 0;
return 0;
}
g_Dialogue.nextCharDialogue = textDialogue;
g_Dialogue.unk3C = 0;
g_Dialogue.primIndex[1] = -1;
g_Dialogue.primIndex[0] = -1;
func_801BE544();
//! FAKE:
if (prim && prim) {
}
prim = g_Dialogue.prim[0] = &g_PrimBuf[g_Dialogue.primIndex[2]];
prim->drawMode = DRAW_HIDE;
prim = g_Dialogue.prim[1] = prim->next;
prim->drawMode = DRAW_HIDE;
prim = g_Dialogue.prim[2] = prim->next;
prim->drawMode = DRAW_HIDE;
prim = g_Dialogue.prim[3] = prim->next;
prim->drawMode = DRAW_HIDE;
prim = g_Dialogue.prim[4] = prim->next;
prim->drawMode = DRAW_HIDE;
prim = g_Dialogue.prim[5] = prim->next;
prim->type = 4;
prim->drawMode = DRAW_HIDE;
prim = prim->next;
prim->type = 3;
prim->r0 = prim->r1 = prim->r2 = prim->r3 = 0xFF;
prim->g0 = prim->g1 = prim->g2 = prim->g3 = 0;
prim->b0 = prim->b1 = prim->b2 = prim->b3 = 0;
prim->x0 = prim->x2 = 4;
prim->x1 = prim->x3 = 0xF8;
prim->priority = 0x1FD;
prim->drawMode = DRAW_HIDE;
prim = prim->next;
prim->type = 1;
prim->x0 = 3;
prim->y0 = 0x2F;
prim->v0 = 0x4A;
prim->r0 = prim->g0 = prim->b0 = 0xFF;
prim->priority = 0x1FC;
prim->drawMode = DRAW_HIDE;
return 1;
}
void func_801BE75C(s16 yOffset) {
RECT rect;
rect.x = 384;
rect.y = (yOffset * 12) + 256;
rect.w = 64;
rect.h = 12;
ClearImage(&rect, 0, 0, 0);
}
void func_801BE7BC(void) {
Primitive* prim;
func_801BE75C(g_Dialogue.nextCharY);
prim = g_Dialogue.prim[g_Dialogue.nextCharY];
prim->tpage = 0x16;
prim->clut = g_Dialogue.clutIndex;
prim->y0 = g_Dialogue.nextLineY;
prim->u0 = 0;
prim->x0 = g_Dialogue.startX;
prim->x0 = prim->x0 + 4;
prim->v0 = g_Dialogue.nextCharY * 0xC;
prim->u1 = 0xC0;
prim->v1 = 0xC;
prim->priority = 0x1FF;
prim->drawMode = DRAW_DEFAULT;
}
// Creates primitives for the actor name at the head of the dialogue
void func_801BE870(u16 actorIndex, Entity* self) {
Primitive* prim;
s16 primIndex;
s32 x;
u16 chCount;
const char* actorName;
char ch;
actorName = D_80181ACC[actorIndex];
chCount = 0;
while (true) {
ch = *actorName++;
if (ch == DIAG_EOL) {
ch = *actorName++;
if (ch == DIAG_EOS) {
break;
}
}
if (ch == MENUCHAR(' ')) {
continue;
}
chCount++;
}
// Create chCount amount of sprites based on the actor name's letter count
primIndex = g_api.AllocPrimitives(PRIM_SPRT, chCount);
if (primIndex == -1) {
DestroyEntity(self);
return;
}
// Fill prims to render the actor name on screen
prim = &g_PrimBuf[primIndex];
g_Dialogue.primIndex[1] = primIndex;
actorName = D_80181ACC[actorIndex];
x = 0x38;
while (prim != NULL) {
ch = *actorName++;
if (ch == MENUCHAR(' ')) {
x += FONT_SPACE;
} else {
prim->type = PRIM_SPRT;
prim->tpage = 0x1E;
prim->clut = 0x196;
prim->u0 = (ch & 0x0F) * FONT_W;
prim->v0 = (ch & 0xF0) / (FONT_H / 4);
prim->v1 = FONT_H;
prim->u1 = FONT_W;
prim->priority = 0x1FF;
prim->drawMode = DRAW_HIDE;
prim->x0 = x;
prim->y0 = g_Dialogue.startY + 6;
prim = prim->next;
x += FONT_GAP;
}
}
}
void func_801BE9F4(s32 arg0) {
g_Dialogue.unk40 = arg0 + 0x100000;
g_Dialogue.timer = 0;
g_Dialogue.unk3C = 1;
}
void func_801BEA20(void) {
Entity* entity;
u16 startTimer;
u8 entityIndex;
g_Dialogue.timer++;
// protect from overflows
if (g_Dialogue.timer > 0xFFFE) {
g_Dialogue.unk3C = 0;
return;
}
while (true) {
// Start the dialogue script only if the start timer has passed
startTimer = (*g_Dialogue.unk40++ << 8) | *g_Dialogue.unk40++;
if (g_Dialogue.timer < startTimer) {
// Re-evaluate the condition at the next frame
g_Dialogue.unk40 -= 2;
return;
}
switch (*g_Dialogue.unk40++) {
case 0:
entityIndex = *g_Dialogue.unk40++;
entity = &g_Entities[STAGE_ENTITY_START + entityIndex];
DestroyEntity(entity);
entity->entityId = *g_Dialogue.unk40++;
entity->pfnUpdate = PfnEntityUpdates[entity->entityId - 1];
entity->posX.i.hi = *g_Dialogue.unk40++ * 0x10;
entity->posX.i.hi = *g_Dialogue.unk40++ | entity->posX.i.hi;
entity->posY.i.hi = *g_Dialogue.unk40++ * 0x10;
entity->posY.i.hi = *g_Dialogue.unk40++ | entity->posY.i.hi;
break;
case 1:
entityIndex = *g_Dialogue.unk40++;
entity = &g_Entities[STAGE_ENTITY_START + entityIndex];
DestroyEntity(entity);
break;
case 2:
if (!((D_801D7DD0 >> *g_Dialogue.unk40) & 1)) {
g_Dialogue.unk40--;
return;
}
D_801D7DD0 &= ~(1 << *g_Dialogue.unk40++);
break;
case 3:
D_801D7DD0 |= 1 << *g_Dialogue.unk40++;
break;
}
}
}
void func_801BECCC(Entity* self) {
if (g_pads[0].tapped == PAD_START) {
D_801D7D20 = 1;
g_api.FreePrimitives(self->primIndex);
self->flags ^= FLAG_HAS_PRIMS;
if (g_Dialogue.primIndex[1] != -1) {
g_api.FreePrimitives(g_Dialogue.primIndex[1]);
}
if (g_Dialogue.primIndex[0] != -1) {
g_api.FreePrimitives(g_Dialogue.primIndex[0]);
}
g_api.PlaySfx(SET_STOP_MUSIC);
self->step = 1;
self->step_s = 0;
}
}
// Animates the portrait size of the actor by enlarging or shrinking it
void func_801BEDAC(u8 ySteps) {
Primitive* prim;
s32 primIndex;
s32 i;
primIndex = g_Dialogue.nextCharY + 1;
while (primIndex >= 5) {
primIndex -= 5;
}
if (g_CurrentEntity->step_s == 0) {
prim = g_Dialogue.prim[primIndex];
prim->v1 -= ySteps;
prim->v0 += ySteps;
if (prim->v1 == 0) {
g_CurrentEntity->step_s++;
prim->drawMode = DRAW_HIDE;
}
}
for (i = 0; i < 5; i++) {
if (i != primIndex) {
prim = g_Dialogue.prim[i];
prim->y0 -= ySteps;
}
}
g_Dialogue.portraitAnimTimer++;
}
void EntityDeathCutscene(Entity* self) {
RECT rect;
Primitive* prim;
s32 primIndex;
s32 i;
s16 j;
s16 uCoord;
s16 vCoord;
u16 nextChar;
s32 nextChar2;
s32 bit_shifty;
if (self->step != 0) {
if ((D_801D7DD4 != 0) && (D_801D7D20 == 0) &&
((g_IsTimeAttackUnlocked) || (g_Settings.D_8003CB04 & 4))) {
func_801BECCC(self);
}
if ((self->step != 0) && (D_801D7D60 != 0)) {
func_801BEA20();
}
}
switch (self->step) {
case 0:
CreateEntityFromCurrentEntity(E_BG_LIGHTNING, &g_Entities[192]);
if ((g_CastleFlags[53]) || (g_PlayableCharacter != PLAYER_ALUCARD)) {
DestroyEntity(self);
g_Entities[192].params = 0;
return;
}
g_Entities[192].params = 0x100;
if (func_801BE598(D_80184CE0) & 0xFF) {
self->flags |= FLAG_HAS_PRIMS | FLAG_UNK_2000;
D_801D7DD0 = 0;
D_801D7DD4 = 0;
D_801D7D20 = 0;
D_8003C704 = 1;
self->primIndex = g_Dialogue.primIndex[2];
self->step++;
}
break;
case 1:
// this is a huge While-loop! Don't miss it!
while (1) {
if ((g_Dialogue.nextCharTimer != 0) && (D_801D7D20 == 0)) {
g_Dialogue.nextCharTimer--;
return;
}
nextChar = *g_Dialogue.nextCharDialogue++;
switch (nextChar) {
case 0:
self->step = 7;
return;
case 1:
if (D_801D7D20 != 0) {
continue;
}
g_Dialogue.nextCharX = g_Dialogue.nextLineX;
if (!(g_Dialogue.unk12 & 1)) {
g_Dialogue.nextLineY += 12;
}
g_Dialogue.nextCharY++;
if (g_Dialogue.nextCharY >= 5) {
g_Dialogue.nextCharY = 0;
}
func_801BE7BC();
if (!(g_Dialogue.unk12 & 1)) {
if (g_Dialogue.nextCharY >= 4) {
g_Dialogue.unk12 |= 1;
g_Dialogue.portraitAnimTimer = 0;
self->step_s = 0;
self->step++;
return;
}
continue;
}
g_Dialogue.portraitAnimTimer = 0;
self->step_s = 0;
self->step++;
return;
case 2:
g_Dialogue.unk17 = *g_Dialogue.nextCharDialogue++;
continue;
case 3:
g_Dialogue.nextCharTimer = *g_Dialogue.nextCharDialogue++;
if (D_801D7D20 != 0) {
continue;
}
return;
case 4:
if (D_801D7D20 != 0) {
continue;
}
prim = g_Dialogue.prim[0];
for (i = 0; i < 5; i++) {
prim->drawMode = DRAW_HIDE;
prim = prim->next;
}
return;
case 5:
if (D_801D7D20 != 0) {
g_Dialogue.nextCharDialogue += 2;
continue;
}
// fake reuse of i?
i = *g_Dialogue.nextCharDialogue++;
nextChar2 = *g_Dialogue.nextCharDialogue++;
prim = g_Dialogue.prim[5];
uCoord = D_80181A28[nextChar2 & 1];
vCoord = D_80181A2C[nextChar2 & 1];
prim->clut = D_80181A30[i];
prim->tpage = 0x94; // Weird, this is 0x90 in other cutscenes
if (nextChar2 & 0x80) {
prim->u0 = prim->u2 = uCoord + 0x2F;
prim->u1 = prim->u3 = uCoord;
} else {
prim->u0 = prim->u2 = uCoord;
prim->u1 = prim->u3 = uCoord + 0x2F;
}
prim->v0 = prim->v1 = vCoord;
prim->v2 = prim->v3 = vCoord + 0x48;
prim->x0 = prim->x1 = prim->x2 = prim->x3 =
g_Dialogue.startX - 0x1E;
prim->y0 = prim->y1 = prim->y2 = prim->y3 =
g_Dialogue.startY + 0x24;
g_Dialogue.clutIndex = D_80181A38[i];
func_801BE544();
func_801BE7BC();
prim->priority = 0x1FE;
prim->drawMode = 0;
func_801BE870(i, self);
g_Dialogue.portraitAnimTimer = 6;
self->step = 3;
return;
case 6:
if (D_801D7D20 != 0) {
continue;
}
for (prim = g_Dialogue.prim[0], i = 0; i < 5; i++) {
prim->drawMode = DRAW_HIDE;
prim = prim->next;
}
g_api.FreePrimitives(g_Dialogue.primIndex[1]);
g_Dialogue.primIndex[1] = -1;
g_Dialogue.portraitAnimTimer = 6;
self->step = 4;
return;
case 7:
if (D_801D7D20 != 0) {
g_Dialogue.nextCharDialogue++;
g_Dialogue.nextCharDialogue++;
continue;
}
g_Dialogue.startX = *g_Dialogue.nextCharDialogue++;
g_Dialogue.startY = *g_Dialogue.nextCharDialogue++;
prim = g_Dialogue.prim[5];
prim = prim->next;
prim->y0 = prim->y1 = g_Dialogue.startY;
prim->y2 = prim->y3 = g_Dialogue.startY + 0x48;
prim = prim->next;
prim->y0 = g_Dialogue.startY - 1;
prim->u0 = 0xF6;
g_Dialogue.portraitAnimTimer = 0x18;
self->step = 5;
self->step_s = 0;
return;
case 8:
if (D_801D7D20 != 0) {
continue;
}
g_Dialogue.portraitAnimTimer = 0x18;
self->step = 6;
return;
case 9:
if (D_801D7D20 != 0) {
g_Dialogue.nextCharDialogue++;
g_Dialogue.nextCharDialogue++;
continue;
}
nextChar = *g_Dialogue.nextCharDialogue++;
nextChar <<= 4;
nextChar |= *g_Dialogue.nextCharDialogue++;
g_api.PlaySfx(nextChar);
continue;
case 10:
if (D_801D7D20 != 0) {
continue;
}
if (g_api.func_80131F68() != false) {
continue;
}
*g_Dialogue.nextCharDialogue--;
return;
case 11:
if (D_801D7D20 != 0) {
continue;
}
if (g_api.func_80131F68() != true) {
continue;
}
*g_Dialogue.nextCharDialogue--;
return;
case 12:
bit_shifty = (s32)*g_Dialogue.nextCharDialogue++;
bit_shifty <<= 4;
bit_shifty |= (s32)*g_Dialogue.nextCharDialogue++;
bit_shifty <<= 4;
bit_shifty |= (s32)*g_Dialogue.nextCharDialogue++;
bit_shifty <<= 4;
bit_shifty |= (s32)*g_Dialogue.nextCharDialogue++;
func_801BE9F4((u8*)bit_shifty);
continue;
case 13:
continue;
case 14:
bit_shifty = (s32)*g_Dialogue.nextCharDialogue++;
bit_shifty <<= 4;
bit_shifty |= (s32)*g_Dialogue.nextCharDialogue++;
bit_shifty <<= 4;
bit_shifty |= (s32)*g_Dialogue.nextCharDialogue++;
bit_shifty <<= 4;
bit_shifty |= (s32)*g_Dialogue.nextCharDialogue++;
bit_shifty += (u16)0x100000;
g_Dialogue.nextCharDialogue += *(u16*)bit_shifty << 2;
bit_shifty = (s32)*g_Dialogue.nextCharDialogue++;
bit_shifty <<= 4;
bit_shifty |= (s32)*g_Dialogue.nextCharDialogue++;
bit_shifty <<= 4;
bit_shifty |= (s32)*g_Dialogue.nextCharDialogue++;
bit_shifty <<= 4;
bit_shifty |= (s32)*g_Dialogue.nextCharDialogue;
g_Dialogue.nextCharDialogue = (u8*)bit_shifty + 0x100000;
continue;
case 15:
bit_shifty = (s32)*g_Dialogue.nextCharDialogue++;
bit_shifty <<= 4;
bit_shifty |= (s32)*g_Dialogue.nextCharDialogue++;
bit_shifty <<= 4;
bit_shifty |= (s32)*g_Dialogue.nextCharDialogue++;
bit_shifty <<= 4;
bit_shifty |= (s32)*g_Dialogue.nextCharDialogue;
g_Dialogue.nextCharDialogue = (u8*)bit_shifty + 0x100000;
continue;
case 16:
if (!((D_801D7DD0 >> *g_Dialogue.nextCharDialogue) & 1)) {
g_Dialogue.nextCharDialogue--;
return;
}
D_801D7DD0 &= ~(1 << *g_Dialogue.nextCharDialogue);
*g_Dialogue.nextCharDialogue++;
continue;
case 17:
D_801D7DD0 |= 1 << *g_Dialogue.nextCharDialogue++;
continue;
case 18:
g_Dialogue.unk3C = 0;
continue;
case 19:
if (D_801D7D20 != 0) {
g_Dialogue.nextCharDialogue += 5;
} else {
bit_shifty = (s32)*g_Dialogue.nextCharDialogue++;
bit_shifty <<= 4;
bit_shifty |= (s32)*g_Dialogue.nextCharDialogue++;
bit_shifty <<= 4;
bit_shifty |= (s32)*g_Dialogue.nextCharDialogue++;
bit_shifty <<= 4;
bit_shifty |= (s32)*g_Dialogue.nextCharDialogue++;
bit_shifty += 0x100000;
nextChar2 = g_Dialogue.nextCharDialogue++[0];
LoadTPage((u32*)bit_shifty, 1, 0, D_80181A34[nextChar2],
0x100, 0x30, 0x48);
}
continue;
case 20:
nextChar = *g_Dialogue.nextCharDialogue++;
nextChar <<= 4;
nextChar |= *g_Dialogue.nextCharDialogue++;
g_api.PlaySfx(nextChar);
continue;
case 21:
D_801D7DD0 = 0;
D_801D7D20 = 0;
D_801D7DD4 = 0;
continue;
case 22:
D_801D7DD0 &= ~(1 << *g_Dialogue.nextCharDialogue++);
continue;
case 23:
return;
case 24:
if (!((D_801D7DD0 >> *g_Dialogue.nextCharDialogue) & 1)) {
*g_Dialogue.nextCharDialogue--;
return;
}
*g_Dialogue.nextCharDialogue++;
continue;
default:
if (D_801D7D20 != 0) {
continue;
}
g_Dialogue.nextCharTimer = g_Dialogue.unk17;
}
break; // This breaks the big while-loop!
}
if (nextChar == 0x20) {
g_Dialogue.nextCharX += 2;
return;
}
rect.x = ((nextChar & 0xF) * 2) + 0x380;
rect.y = ((u32)(nextChar & 0xF0) >> 1) + 0xF0;
rect.w = 2;
rect.h = 8;
// Other cutscenes have + 0x180 here
vCoord = (g_Dialogue.nextCharY * 0xC) + 0x100;
MoveImage(&rect, g_Dialogue.nextCharX, vCoord);
g_Dialogue.nextCharX += 2;
break;
case 2:
func_801BEDAC(2U);
if (g_Dialogue.portraitAnimTimer >= 6) {
self->step -= 1;
return;
}
break;
case 3:
prim = g_Dialogue.prim[5];
prim->x0 = prim->x2 -= 4;
prim->x1 = prim->x3 += 4;
prim->y0 = prim->y1 -= 6;
prim->y2 = prim->y3 += 6;
g_Dialogue.portraitAnimTimer--;
if (!g_Dialogue.portraitAnimTimer) {
self->step = 1;
for (prim = &g_PrimBuf[g_Dialogue.primIndex[1]]; prim != NULL;
prim = prim->next) {
prim->drawMode = 0;
}
}
break;
case 4:
prim = g_Dialogue.prim[5];
prim->x0 = prim->x2 += 4;
prim->x1 = prim->x3 -= 4;
prim->y0 = prim->y1 += 6;
prim->y2 = prim->y3 -= 6;
if (prim->x1 >= (g_Dialogue.startX - 2)) {
prim->x1 = prim->x3 = g_Dialogue.startX - 3;
}
g_Dialogue.portraitAnimTimer--;
if (!g_Dialogue.portraitAnimTimer) {
self->step = 1;
return;
}
break;
case 5:
switch (self->step_s) {
case 0:
D_801D7DD4 = 1;
primIndex = g_api.AllocPrimitives(PRIM_LINE_G2, 0x48);
if (primIndex == -1) {
DestroyEntity(self);
return;
}
g_Dialogue.primIndex[0] = primIndex;
for (prim = &g_PrimBuf[primIndex], j = 0; prim != NULL;
prim = prim->next) {
prim->r0 = prim->r1 = 0x7F;
prim->b0 = prim->b1 = prim->g0 = prim->g1 = 0;
prim->x0 = prim->x1 = 0xF7;
prim->y0 = prim->y1 = g_Dialogue.startY + j;
prim->priority = 0x1FE;
prim->drawMode = 0;
prim->x2 = D_80181A3C[j];
prim->x3 = 0xF70;
j++;
}
self->step_s++;
return;
case 1:
for (j = 0, prim = &g_PrimBuf[g_Dialogue.primIndex[0]];
prim != NULL; prim = prim->next) {
prim->x3 -= prim->x2;
prim->x2 += 2;
prim->x0 = prim->x3 / 16;
if (prim->x0 < 5) {
prim->x0 = 4;
} else {
j = 1;
}
}
if (j == 0) {
g_api.FreePrimitives(g_Dialogue.primIndex[0]);
g_Dialogue.primIndex[0] = -1;
prim = g_Dialogue.prim[5];
prim = prim->next;
prim->blendMode = 0x11;
prim = prim->next;
prim->blendMode = 0x51;
self->step_s++;
return;
}
break;
case 2:
j = 0;
prim = g_Dialogue.prim[5];
prim = prim->next;
if (prim->r0 < 0x10) {
prim->r0 = prim->r1 = prim->r2 = prim->r3 = 0;
} else {
prim->r0 = prim->r1 = prim->r2 = prim->r3 -= 0x10;
j = 1;
}
if (prim->b0 >= 0x7F) {
prim->b0 = prim->b1 = 0x7F;
} else {
prim->b0 = prim->b1 += 8;
j = 1;
}
prim = prim->next;
if (prim->r0 < 0x10) {
prim->r0 = prim->g0 = prim->b0 = 0x10;
} else {
prim->r0 = prim->g0 = prim->b0 -= 0xF;
j = 1;
}
if (j == 0) {
self->step = 1;
}
}
break;
case 6:
prim = g_Dialogue.prim[5];
prim = prim->next;
g_Dialogue.portraitAnimTimer--;
if (g_Dialogue.portraitAnimTimer >= 0xC) {
prim = prim->next;
prim->u0 -= 20;
if (g_Dialogue.portraitAnimTimer & 1) {
prim->u0--;
return;
}
} else {
if (!g_Dialogue.portraitAnimTimer) {
self->step = 1;
prim->drawMode = DRAW_HIDE;
} else {
prim->y2 = (prim->y3 -= 6);
}
prim = prim->next;
prim->drawMode = DRAW_HIDE;
return;
}
break;
case 7:
g_CastleFlags[53] = 1;
g_api.TimeAttackController(
TIMEATTACK_EVENT_MEET_DEATH, TIMEATTACK_SET_RECORD);
D_8003C704 = 0;
g_Settings.D_8003CB04 |= 4;
DestroyEntity(self);
break;
}
}

View File

@ -69,7 +69,7 @@ typedef enum EntityIDs {
/* 0x11 */ E_ID_11 = 0x11, /* 0x11 */ E_ID_11 = 0x11,
/* 0x14 */ E_ID_14 = 0x14, /* 0x14 */ E_ID_14 = 0x14,
/* 0x15 */ E_ID_15 = 0x15, /* 0x15 */ E_ID_15 = 0x15,
/* 0x17 */ E_ID_17 = 0x17, /* 0x17 */ E_BG_LIGHTNING = 0x17,
/* 0x27 */ E_FALLING_ROCK_2 = 0x27, /* 0x27 */ E_FALLING_ROCK_2 = 0x27,
/* 0x35 */ E_SPLASH_WATER = 0x35, /* 0x35 */ E_SPLASH_WATER = 0x35,
/* 0x36 */ E_SURFACING_WATER, /* 0x36 */ E_SURFACING_WATER,
@ -228,14 +228,6 @@ extern u8 D_80183C98[];
extern s32 D_80183CAC; extern s32 D_80183CAC;
extern s32 D_80183CBC; extern s32 D_80183CBC;
extern s32 D_801D7D20; extern s32 D_801D7D20;
extern s16 D_801D7D2A;
extern u16 D_801D7D2C;
extern s16 D_801D7D2E;
extern s16 D_801D7D30;
extern s16 D_801D7D32;
extern s16 D_801D7D36;
extern s8 D_801D7D3A;
extern s8 D_801D7D3B;
extern s32 D_801D7D54; extern s32 D_801D7D54;
extern s32 D_801D7D58; extern s32 D_801D7D58;
extern u32 D_801D7DD0; extern u32 D_801D7DD0;
@ -253,4 +245,19 @@ extern u8 g_ESoulStealOrbAnim[];
extern SVECTOR D_801B73E0; extern SVECTOR D_801B73E0;
// For EntityDeathCutscene
extern u8 D_80181A28[];
extern u8 D_80181A2C[];
extern u16 D_80181A30[];
extern u16 D_80181A34[];
extern u16 D_80181A38[];
extern s16 D_80181A3C[];
extern const char D_801813F0[];
extern s32 D_801D7D20;
extern u32 D_801D7DD0;
extern s32 D_801D7DD4;
extern u16 D_801D7D60;
extern const char D_80184CE0[];
extern s32 D_801D7D5C;
extern Dialogue g_Dialogue; extern Dialogue g_Dialogue;