document mp_finish

This commit is contained in:
Oliver Bell committed 2026-05-14 19:11:49 +01:00
1 parent 4577c2e5c3
commit bde11f1f03
9 files changed
+73 -89

No files matched your search

+2
View File
@@ -680,6 +680,8 @@ sa1:
sa2: sa2:
@$(MAKE) GAME_NAME=sa2 @$(MAKE) GAME_NAME=sa2
trilogy: sa1 sa2
$(TOOLDIRS): tool_libs $(TOOLDIRS): tool_libs
@$(MAKE) -C $@ @$(MAKE) -C $@
@@ -359,7 +359,7 @@ _080181DA:
ldr r1, [sp, #8] ldr r1, [sp, #8]
cmp r1, #0 cmp r1, #0
bne _080181E4 bne _080181E4
bl CreateMultiplayerFinishHandler bl CreateMultiplayerFinishTransition
_080181E4: _080181E4:
add sp, #0x14 add sp, #0x14
pop {r3, r4, r5} pop {r3, r4, r5}
+1 -1
View File
@@ -4,6 +4,6 @@
#include "global.h" #include "global.h"
void CreateMultiplayerFinishResult(u8 sioId, u8 count); void CreateMultiplayerFinishResult(u8 sioId, u8 count);
void CreateMultiplayerFinishHandler(void); void CreateMultiplayerFinishTransition(void);
#endif // GUARD_MULTIPLAYER_FINISH_H #endif // GUARD_MULTIPLAYER_FINISH_H
@@ -551,7 +551,7 @@ void Task_StageGoal4(void)
goal->unk3C = 0; goal->unk3C = 0;
gCurTask->main = Task_StageGoal6; gCurTask->main = Task_StageGoal6;
CreateMultiplayerFinishHandler(); CreateMultiplayerFinishTransition();
} else { } else {
gCurTask->main = Task_StageGoal5; gCurTask->main = Task_StageGoal5;
} }
@@ -282,7 +282,7 @@ static void StageGoalToggle_PlayerReachedGoal(void)
} }
} }
CreateMultiplayerFinishHandler(); CreateMultiplayerFinishTransition();
TaskDestroy(gCurTask); TaskDestroy(gCurTask);
} }
} }
@@ -152,7 +152,6 @@ static void Task_AmyAttackHeartEffect(void)
#if (GAME == GAME_SA1) #if (GAME == GAME_SA1)
if (hearts->initialCharState != gPlayer.charState) if (hearts->initialCharState != gPlayer.charState)
#else #else
// TODO: Fix horrible cast!
if ((!PLAYER_IS_ALIVE) if ((!PLAYER_IS_ALIVE)
|| ((hearts->initialPlayerAnim != gPlayer.anim || hearts->initialPlayerVarient != gPlayer.variant) || ((hearts->initialPlayerAnim != gPlayer.anim || hearts->initialPlayerVarient != gPlayer.variant)
&& (gPlayer.anim != SA2_ANIM_CHAR(SA2_CHAR_ANIM_51, CHARACTER_AMY) || gPlayer.variant != 1))) && (gPlayer.anim != SA2_ANIM_CHAR(SA2_CHAR_ANIM_51, CHARACTER_AMY) || gPlayer.variant != 1)))
+1 -1
View File
@@ -375,7 +375,7 @@ void ReceiveRoomEvent_ReachedStageGoal(union MultiSioData *recv, u8 i)
} }
if (!somebool) { if (!somebool) {
CreateMultiplayerFinishHandler(); CreateMultiplayerFinishTransition();
} }
} }
} }
+64 -81
View File
@@ -28,36 +28,21 @@
#include "constants/sa2/text.h" #include "constants/sa2/text.h"
#endif #endif
#if (GAME == GAME_SA1) && !(defined NON_MATCHING)
// Once CreateMultiplayerFinishHandler matches in SA1,
// this can go away.
asm(".section .rodata");
asm(".align 2, 0");
asm(".global gUnknown_080BB490");
asm("gUnknown_080BB490:");
// NOTE:
// As long as gUnknown_080BB490 is above data with this layout, this works out:
// asm(".byte 0, 1, 2, 3:");
// But once CreateMultiplayerFinishHandler matches,
// the label won't be necessary. It's only here because
// the asm file out of asm/non_matching/ references it.
#endif
typedef struct { typedef struct {
Sprite s; Sprite s;
u8 unk30; u8 sioId;
u8 unk31; u8 rank;
} MpFinish1; /* size: 0x34 */ } FinishResult; /* size: 0x34 */
typedef struct { typedef struct {
u16 unk0; u16 frame;
} Finish2; /* size: 4 */ } FinishTransition; /* size: 4 */
void SA2_LABEL(Task_801A04C)(void); static void Task_TransitionWaitForResults(void);
void Task_TransitionToResultsScreen(void); static void Task_TransitionToResultsScreen(void);
void SA2_LABEL(Task_8019E70)(void); static void Task_DisplayResult(void);
void SA2_LABEL(TaskDestructor_8019EF4)(struct Task *); static void TaskDestructor_MultiplayerFinishResult(struct Task *);
#ifndef COLLECT_RINGS_ROM #ifndef COLLECT_RINGS_ROM
@@ -100,7 +85,7 @@ const TileInfo sMPFinishTileInfo[2][7] = { {
}) })
#endif #endif
void CreateMultiplayerFinishResult(u8 sioId, u8 count) void CreateMultiplayerFinishResult(u8 sioId, u8 rank)
{ {
u32 i = 0; u32 i = 0;
@@ -108,8 +93,8 @@ void CreateMultiplayerFinishResult(u8 sioId, u8 count)
if (gMultiplayerRanks[sioId] == -1) if (gMultiplayerRanks[sioId] == -1)
#endif #endif
{ {
struct Task *t = TaskCreate(SA2_LABEL(Task_8019E70), sizeof(MpFinish1), 0x2010, 0, SA2_LABEL(TaskDestructor_8019EF4)); struct Task *t = TaskCreate(Task_DisplayResult, sizeof(FinishResult), 0x2010, 0, TaskDestructor_MultiplayerFinishResult);
MpFinish1 *finish = TASK_DATA(t); FinishResult *finish = TASK_DATA(t);
struct Task **mpt = &gMultiplayerPlayerTasks[0]; struct Task **mpt = &gMultiplayerPlayerTasks[0];
Sprite *s; Sprite *s;
@@ -120,15 +105,15 @@ void CreateMultiplayerFinishResult(u8 sioId, u8 count)
mpt++; mpt++;
} }
if (count < 6) { if (rank < 6) {
gMultiplayerRanks[sioId] = count; gMultiplayerRanks[sioId] = rank;
} else { } else {
// BUG(?): Value underflows if i is 0 // BUG(?): Value underflows if i is 0
gMultiplayerRanks[sioId] = i - 1; gMultiplayerRanks[sioId] = i - 1;
} }
finish->unk30 = sioId; finish->sioId = sioId;
finish->unk31 = count; finish->rank = rank;
s = &finish->s; s = &finish->s;
s->graphics.size = 0; s->graphics.size = 0;
@@ -136,34 +121,34 @@ void CreateMultiplayerFinishResult(u8 sioId, u8 count)
#if (GAME == GAME_SA1) #if (GAME == GAME_SA1)
s->graphics.anim = 904; s->graphics.anim = 904;
if (count == 5) { if (rank == 5) {
s->variant = 1; s->variant = 1;
s->graphics.dest = VramMalloc(12); s->graphics.dest = VramMalloc(12);
} else if (count == 4) { } else if (rank == 4) {
s->variant = 2; s->variant = 2;
s->graphics.dest = VramMalloc(12); s->graphics.dest = VramMalloc(12);
} else if ((i == 2) || (gGameMode == GAME_MODE_CHAO_HUNT) || (gGameMode == GAME_MODE_MULTI_PLAYER) } else if ((i == 2) || (gGameMode == GAME_MODE_CHAO_HUNT) || (gGameMode == GAME_MODE_MULTI_PLAYER)
|| (gGameMode == GAME_MODE_TEAM_PLAY)) { || (gGameMode == GAME_MODE_TEAM_PLAY)) {
s->variant = count; s->variant = rank;
s->graphics.dest = VramMalloc(12); s->graphics.dest = VramMalloc(12);
} else { } else {
s->variant = count + 3; s->variant = rank + 3;
s->graphics.dest = VramMalloc(8); s->graphics.dest = VramMalloc(8);
} }
#elif (GAME == GAME_SA2) #elif (GAME == GAME_SA2)
s->graphics.dest = VramMalloc(12); s->graphics.dest = VramMalloc(12);
if (count == 5) { if (rank == 5) {
s->graphics.anim = GET_MP_FINISH_RESULT_TILE_INFO(1)->anim; s->graphics.anim = GET_MP_FINISH_RESULT_TILE_INFO(1)->anim;
s->variant = GET_MP_FINISH_RESULT_TILE_INFO(1)->variant; s->variant = GET_MP_FINISH_RESULT_TILE_INFO(1)->variant;
} else if (count == 4) { } else if (rank == 4) {
s->graphics.anim = GET_MP_FINISH_RESULT_TILE_INFO(2)->anim; s->graphics.anim = GET_MP_FINISH_RESULT_TILE_INFO(2)->anim;
s->variant = GET_MP_FINISH_RESULT_TILE_INFO(2)->variant; s->variant = GET_MP_FINISH_RESULT_TILE_INFO(2)->variant;
} else if ((i == 2) || gGameMode == GAME_MODE_TEAM_PLAY) { } else if ((i == 2) || gGameMode == GAME_MODE_TEAM_PLAY) {
s->graphics.anim = GET_MP_FINISH_RESULT_TILE_INFO(0)->anim; s->graphics.anim = GET_MP_FINISH_RESULT_TILE_INFO(0)->anim;
s->variant = count + GET_MP_FINISH_RESULT_TILE_INFO(0)->variant; s->variant = rank + GET_MP_FINISH_RESULT_TILE_INFO(0)->variant;
} else { } else {
s->graphics.anim = GET_MP_FINISH_RESULT_TILE_INFO(3)->anim; s->graphics.anim = GET_MP_FINISH_RESULT_TILE_INFO(3)->anim;
s->variant = count + GET_MP_FINISH_RESULT_TILE_INFO(3)->variant; s->variant = rank + GET_MP_FINISH_RESULT_TILE_INFO(3)->variant;
} }
#endif #endif
@@ -177,11 +162,11 @@ void CreateMultiplayerFinishResult(u8 sioId, u8 count)
} }
} }
void SA2_LABEL(Task_8019E70)(void) void Task_DisplayResult(void)
{ {
MpFinish1 *finish = TASK_DATA(gCurTask); FinishResult *finish = TASK_DATA(gCurTask);
Sprite *s = &finish->s; Sprite *s = &finish->s;
MultiplayerPlayer *mpp = TASK_DATA(gMultiplayerPlayerTasks[finish->unk30]); MultiplayerPlayer *mpp = TASK_DATA(gMultiplayerPlayerTasks[finish->sioId]);
s->x = mpp->pos.x - gCamera.x; s->x = mpp->pos.x - gCamera.x;
@@ -194,14 +179,14 @@ void SA2_LABEL(Task_8019E70)(void)
DisplaySprite(s); DisplaySprite(s);
} }
void SA2_LABEL(TaskDestructor_8019EF4)(struct Task *t) void TaskDestructor_MultiplayerFinishResult(struct Task *t)
{ {
MpFinish1 *finish = TASK_DATA(t); FinishResult *finish = TASK_DATA(t);
Sprite *s = &finish->s; Sprite *s = &finish->s;
VramFree(s->graphics.dest); VramFree(s->graphics.dest);
} }
void CreateMultiplayerFinishHandler(void) void CreateMultiplayerFinishTransition(void)
{ {
u32 i; u32 i;
u32 r2; u32 r2;
@@ -213,10 +198,10 @@ void CreateMultiplayerFinishHandler(void)
#endif #endif
{ {
struct Task *mpt; struct Task *mpt;
struct Task *t = TaskCreate(SA2_LABEL(Task_801A04C), sizeof(Finish2), 0x2000, 0, NULL); struct Task *t = TaskCreate(Task_TransitionWaitForResults, sizeof(FinishTransition), 0x2000, 0, NULL);
Finish2 *f2 = TASK_DATA(t); FinishTransition *finishTransition = TASK_DATA(t);
f2->unk0 = 0; finishTransition->frame = 0;
if (gGameMode != GAME_MODE_MULTI_PLAYER_COLLECT_RINGS) { if (gGameMode != GAME_MODE_MULTI_PLAYER_COLLECT_RINGS) {
#if (GAME == GAME_SA1) #if (GAME == GAME_SA1)
@@ -396,17 +381,17 @@ void CreateMultiplayerFinishHandler(void)
#endif // COLLECT_RINGS_ROM #endif // COLLECT_RINGS_ROM
void SA2_LABEL(Task_801A04C)(void) static void Task_TransitionWaitForResults(void)
{ {
u32 x = 0; u32 x = 0;
Finish2 *f2 = TASK_DATA(gCurTask); FinishTransition *finishTransition = TASK_DATA(gCurTask);
if (gGameMode != GAME_MODE_MULTI_PLAYER_COLLECT_RINGS) { if (gGameMode != GAME_MODE_MULTI_PLAYER_COLLECT_RINGS) {
x = DISPLAY_WIDTH; x = DISPLAY_WIDTH;
} }
if (gRoomEventQueueWritePos == gRoomEventQueueSendPos) { if (gRoomEventQueueWritePos == gRoomEventQueueSendPos) {
if (f2->unk0++ > x) { if (finishTransition->frame++ > x) {
gBldRegs.bldCnt = (BLDCNT_EFFECT_LIGHTEN | BLDCNT_TGT1_ALL); gBldRegs.bldCnt = (BLDCNT_EFFECT_LIGHTEN | BLDCNT_TGT1_ALL);
gBldRegs.bldY = 0; gBldRegs.bldY = 0;
@@ -415,43 +400,42 @@ void SA2_LABEL(Task_801A04C)(void)
m4aMPlayFadeOut(&gMPlayInfo_SE2, 4); m4aMPlayFadeOut(&gMPlayInfo_SE2, 4);
m4aMPlayFadeOut(&gMPlayInfo_SE3, 4); m4aMPlayFadeOut(&gMPlayInfo_SE3, 4);
f2->unk0 = 0; finishTransition->frame = 0;
gCurTask->main = Task_TransitionToResultsScreen; gCurTask->main = Task_TransitionToResultsScreen;
} }
} }
} }
#if 01 static void Task_TransitionToResultsScreen(void)
void Task_TransitionToResultsScreen(void)
{ {
u32 i; // r7 u32 i; // r7
Finish2 *f2 = TASK_DATA(gCurTask); FinishTransition *finishTransition = TASK_DATA(gCurTask);
f2->unk0 += Q(0.25); finishTransition->frame += Q(0.25);
gBldRegs.bldY = I(f2->unk0); gBldRegs.bldY = I(finishTransition->frame);
if (f2->unk0 >= 0x1000) { if (finishTransition->frame >= 0x1000) {
// _0801A110 // _0801A110
gBldRegs.bldCnt = (BLDCNT_EFFECT_LIGHTEN | BLDCNT_TGT1_ALL); gBldRegs.bldCnt = (BLDCNT_EFFECT_LIGHTEN | BLDCNT_TGT1_ALL);
gBldRegs.bldY = 0; gBldRegs.bldY = 0;
if (gGameMode == GAME_MODE_MULTI_PLAYER_COLLECT_RINGS) { if (gGameMode == GAME_MODE_MULTI_PLAYER_COLLECT_RINGS) {
u8 sp00[4] = { 0, 1, 2, 3 }; u8 rankToPid[4] = { 0, 1, 2, 3 };
u8 sp04[4] = { 0 }; u8 charRings[4] = { 0 };
#if (GAME == GAME_SA2) #if (GAME == GAME_SA2)
m4aMPlayAllStop(); m4aMPlayAllStop();
#endif #endif
*((u32 *)sp04) = *((u32 *)gMultiplayerCharRings); *((u32 *)charRings) = *((u32 *)gMultiplayerCharRings);
for (i = 0; i < MULTI_SIO_PLAYERS_MAX; i++) { for (i = 0; i < MULTI_SIO_PLAYERS_MAX; i++) {
s32 m; s32 m;
for (m = 0; m < (3 - i); m++) { for (m = 0; m < (3 - i); m++) {
if (sp04[m] < sp04[m + 1]) { if (charRings[m] < charRings[m + 1]) {
XOR_SWAP(sp04[m], sp04[m + 1]); XOR_SWAP(charRings[m], charRings[m + 1]);
XOR_SWAP(sp00[m], sp00[m + 1]); XOR_SWAP(rankToPid[m], rankToPid[m + 1]);
} }
} }
} }
@@ -459,30 +443,30 @@ void Task_TransitionToResultsScreen(void)
for (i = 0; i < MULTI_SIO_PLAYERS_MAX; i++) { for (i = 0; i < MULTI_SIO_PLAYERS_MAX; i++) {
if (i != 0) { if (i != 0) {
if (sp04[i] != sp04[0]) { if (charRings[i] != charRings[0]) {
gMultiplayerRanks[sp00[i]] = i; gMultiplayerRanks[rankToPid[i]] = i;
gMultiplayerCharacters[sp00[i]] = 1; gMultiplayerCharacters[rankToPid[i]] = 1;
} else { } else {
#ifndef NON_MATCHING #ifndef NON_MATCHING
// TODO: Match without goto // TODO: Match without goto
goto else_block; goto else_block;
#else #else
gMultiplayerRanks[sp00[i]] = i; gMultiplayerRanks[rankToPid[i]] = i;
gMultiplayerCharacters[sp00[i]] = 2; gMultiplayerCharacters[rankToPid[i]] = 2;
#endif #endif
} }
} else { } else {
// _0801A1F4 // _0801A1F4
if (sp04[0] == sp04[1]) { if (charRings[0] == charRings[1]) {
#ifndef NON_MATCHING #ifndef NON_MATCHING
else_block: else_block:
#endif #endif
gMultiplayerRanks[sp00[i]] = i; gMultiplayerRanks[rankToPid[i]] = i;
gMultiplayerCharacters[sp00[i]] = 2; gMultiplayerCharacters[rankToPid[i]] = 2;
} else { } else {
gMultiplayerRanks[sp00[0]] = i; gMultiplayerRanks[rankToPid[0]] = i;
gMPRingCollectWins[sp00[0]]++; gMPRingCollectWins[rankToPid[0]]++;
gMultiplayerCharacters[sp00[0]] = i; gMultiplayerCharacters[rankToPid[0]] = i;
} }
} }
} }
@@ -523,7 +507,7 @@ void Task_TransitionToResultsScreen(void)
s16 ownResult = 0; s16 ownResult = 0;
for (pid = 0; pid < MULTI_SIO_PLAYERS_MAX; pid++) { for (pid = 0; pid < MULTI_SIO_PLAYERS_MAX; pid++) {
if (!((gMultiplayerConnections >> pid) & 0x1)) if (!CONNECTION_REGISTERED(pid))
continue; continue;
if (pid == SIO_MULTI_CNT->id) if (pid == SIO_MULTI_CNT->id)
@@ -576,17 +560,16 @@ void Task_TransitionToResultsScreen(void)
return; return;
} }
} }
#endif
#if COLLECT_RINGS_ROM #if COLLECT_RINGS_ROM
void CreateMultiplayerFinishHandler(void) void CreateMultiplayerFinishTransition(void)
{ {
u32 i; u32 i;
u32 r2; u32 r2;
u8 r6; u8 r6;
struct Task *mpt; struct Task *mpt;
struct Task *t = TaskCreate(SA2_LABEL(Task_801A04C), sizeof(Finish2), 0x2000, 0, NULL); struct Task *t = TaskCreate(Task_TransitionWaitForResults, sizeof(FinishTransition), 0x2000, 0, NULL);
Finish2 *f2 = TASK_DATA(t); FinishTransition *finishTransition = TASK_DATA(t);
f2->unk0 = 0; finishTransition->frame = 0;
} }
#endif #endif
+2 -2
View File
@@ -620,7 +620,7 @@ void Task_GameStage(void)
#endif #endif
else { else {
gStageFlags |= STAGE_FLAG__ACT_START; gStageFlags |= STAGE_FLAG__ACT_START;
CreateMultiplayerFinishHandler(); CreateMultiplayerFinishTransition();
} }
} }
#ifndef COLLECT_RINGS_ROM #ifndef COLLECT_RINGS_ROM
@@ -648,7 +648,7 @@ void Task_GameStage(void)
m4aSongNumStart(SE_TIME_UP); m4aSongNumStart(SE_TIME_UP);
} else { } else {
gStageFlags |= STAGE_FLAG__ACT_START; gStageFlags |= STAGE_FLAG__ACT_START;
CreateMultiplayerFinishHandler(); CreateMultiplayerFinishTransition();
} }
} }
#endif #endif