Merge pull request #1376 from PikalaxALT/battle_multi_buffer

Resolve link comm buffers in gBattleStruct
This commit is contained in:
GriffinR 2021-03-15 21:35:16 -04:00 committed by GitHub
commit 9242ec30de
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
5 changed files with 82 additions and 66 deletions

View File

@ -344,6 +344,15 @@ struct BattleTvMovePoints
s16 points[2][PARTY_SIZE * 4]; s16 points[2][PARTY_SIZE * 4];
}; };
struct LinkBattlerHeader
{
u8 versionSignatureLo;
u8 versionSignatureHi;
u8 vsScreenHealthFlagsLo;
u8 vsScreenHealthFlagsHi;
struct BattleEnigmaBerry battleEnigmaBerry;
};
struct BattleStruct struct BattleStruct
{ {
u8 turnEffectsTracker; u8 turnEffectsTracker;
@ -419,11 +428,10 @@ struct BattleStruct
u8 givenExpMons; // Bits for enemy party's pokemon that gave exp to player's party. u8 givenExpMons; // Bits for enemy party's pokemon that gave exp to player's party.
u8 lastTakenMoveFrom[MAX_BATTLERS_COUNT * MAX_BATTLERS_COUNT * 2]; // a 3-D array [target][attacker][byte] u8 lastTakenMoveFrom[MAX_BATTLERS_COUNT * MAX_BATTLERS_COUNT * 2]; // a 3-D array [target][attacker][byte]
u16 castformPalette[MAX_BATTLERS_COUNT][16]; u16 castformPalette[MAX_BATTLERS_COUNT][16];
u8 field_180; // weird field, used in battle_main.c, once accessed as an array of u32 overwriting the field below union {
u8 field_181; struct LinkBattlerHeader linkBattlerHeader;
u8 vsScreenHealthFlagsLo; u32 battleVideo[2];
u8 vsScreenHealthFlagsHi; // Last bit is 'has frontier pass' } multiBuffer;
struct BattleEnigmaBerry battleEnigmaBerry;
u8 wishPerishSongState; u8 wishPerishSongState;
u8 wishPerishSongBattlerId; u8 wishPerishSongBattlerId;
bool8 overworldWeatherDone; bool8 overworldWeatherDone;

View File

@ -37,7 +37,7 @@ struct Main
/*0x439*/ u8 oamLoadDisabled:1; /*0x439*/ u8 oamLoadDisabled:1;
/*0x439*/ u8 inBattle:1; /*0x439*/ u8 inBattle:1;
/*0x439*/ u8 field_439_x4:1; /*0x439*/ u8 anyLinkBattlerHasFrontierPass:1;
}; };
extern const u8 gGameVersion; extern const u8 gGameVersion;

View File

@ -22,9 +22,9 @@ u8 GetRecordedBattleFrontierFacility(void);
u8 GetRecordedBattleFronterBrainSymbol(void); u8 GetRecordedBattleFronterBrainSymbol(void);
void RecordedBattle_SaveParties(void); void RecordedBattle_SaveParties(void);
u8 GetActiveBattlerLinkPlayerGender(void); u8 GetActiveBattlerLinkPlayerGender(void);
void sub_8185F84(void); void RecordedBattle_ClearFrontierPassFlag(void);
void sub_8185F90(u16 arg0); void RecordedBattle_SetFrontierPassFlagFromHword(u16 arg0);
u8 sub_8185FAC(void); u8 RecordedBattle_GetFrontierPassFlag(void);
u8 GetBattleSceneInRecordedBattle(void); u8 GetBattleSceneInRecordedBattle(void);
u8 GetTextSpeedInRecordedBattle(void); u8 GetTextSpeedInRecordedBattle(void);
void RecordedBattle_CopyBattlerMoves(void); void RecordedBattle_CopyBattlerMoves(void);

View File

@ -576,7 +576,7 @@ void CB2_InitBattle(void)
AllocateBattleResources(); AllocateBattleResources();
AllocateBattleSpritesData(); AllocateBattleSpritesData();
AllocateMonSpritesGfx(); AllocateMonSpritesGfx();
sub_8185F84(); RecordedBattle_ClearFrontierPassFlag();
if (gBattleTypeFlags & BATTLE_TYPE_MULTI) if (gBattleTypeFlags & BATTLE_TYPE_MULTI)
{ {
@ -733,16 +733,16 @@ static void BufferPartyVsScreenHealth_AtStart(void)
s32 i; s32 i;
BUFFER_PARTY_VS_SCREEN_STATUS(gPlayerParty, flags, i); BUFFER_PARTY_VS_SCREEN_STATUS(gPlayerParty, flags, i);
gBattleStruct->vsScreenHealthFlagsLo = flags; gBattleStruct->multiBuffer.linkBattlerHeader.vsScreenHealthFlagsLo = flags;
*(&gBattleStruct->vsScreenHealthFlagsHi) = flags >> 8; *(&gBattleStruct->multiBuffer.linkBattlerHeader.vsScreenHealthFlagsHi) = flags >> 8;
gBattleStruct->vsScreenHealthFlagsHi |= FlagGet(FLAG_SYS_FRONTIER_PASS) << 7; gBattleStruct->multiBuffer.linkBattlerHeader.vsScreenHealthFlagsHi |= FlagGet(FLAG_SYS_FRONTIER_PASS) << 7;
} }
static void SetPlayerBerryDataInBattleStruct(void) static void SetPlayerBerryDataInBattleStruct(void)
{ {
s32 i; s32 i;
struct BattleStruct *battleStruct = gBattleStruct; struct BattleStruct *battleStruct = gBattleStruct;
struct BattleEnigmaBerry *battleBerry = &battleStruct->battleEnigmaBerry; struct BattleEnigmaBerry *battleBerry = &battleStruct->multiBuffer.linkBattlerHeader.battleEnigmaBerry;
if (IsEnigmaBerryValid() == TRUE) if (IsEnigmaBerryValid() == TRUE)
{ {
@ -882,52 +882,56 @@ static void SetAllPlayersBerryData(void)
} }
} }
static void sub_8036EB8(u8 arg0, u8 arg1) // This was inlined in Ruby/Sapphire
static void FindLinkBattleMaster(u8 numPlayers, u8 multiPlayerId)
{ {
u8 var = 0; u8 found = 0;
if (gBlockRecvBuffer[0][0] == 256) // If player 1 is playing the minimum version, player 1 is master.
if (gBlockRecvBuffer[0][0] == 0x100)
{ {
if (arg1 == 0) if (multiPlayerId == 0)
gBattleTypeFlags |= BATTLE_TYPE_IS_MASTER | BATTLE_TYPE_TRAINER; gBattleTypeFlags |= BATTLE_TYPE_IS_MASTER | BATTLE_TYPE_TRAINER;
else else
gBattleTypeFlags |= BATTLE_TYPE_TRAINER; gBattleTypeFlags |= BATTLE_TYPE_TRAINER;
var++; found++;
} }
if (var == 0) if (found == 0)
{ {
// If multiple different versions are being used, player 1 is master.
s32 i; s32 i;
for (i = 0; i < arg0; i++) for (i = 0; i < numPlayers; i++)
{ {
if (gBlockRecvBuffer[0][0] != gBlockRecvBuffer[i][0]) if (gBlockRecvBuffer[0][0] != gBlockRecvBuffer[i][0])
break; break;
} }
if (i == arg0) if (i == numPlayers)
{ {
if (arg1 == 0) if (multiPlayerId == 0)
gBattleTypeFlags |= BATTLE_TYPE_IS_MASTER | BATTLE_TYPE_TRAINER; gBattleTypeFlags |= BATTLE_TYPE_IS_MASTER | BATTLE_TYPE_TRAINER;
else else
gBattleTypeFlags |= BATTLE_TYPE_TRAINER; gBattleTypeFlags |= BATTLE_TYPE_TRAINER;
var++; found++;
} }
if (var == 0) if (found == 0)
{ {
for (i = 0; i < arg0; i++) // Lowest index player with the highest game version is master.
for (i = 0; i < numPlayers; i++)
{ {
if (gBlockRecvBuffer[i][0] == 0x300) if (gBlockRecvBuffer[i][0] == 0x300 && i != multiPlayerId)
{ {
if (i != arg1 && i < arg1) if (i < multiPlayerId)
break; break;
} }
if (gBlockRecvBuffer[i][0] > 0x300 && i != arg1) if (gBlockRecvBuffer[i][0] > 0x300 && i != multiPlayerId)
break; break;
} }
if (i == arg0) if (i == numPlayers)
gBattleTypeFlags |= BATTLE_TYPE_IS_MASTER | BATTLE_TYPE_TRAINER; gBattleTypeFlags |= BATTLE_TYPE_IS_MASTER | BATTLE_TYPE_TRAINER;
else else
gBattleTypeFlags |= BATTLE_TYPE_TRAINER; gBattleTypeFlags |= BATTLE_TYPE_TRAINER;
@ -970,8 +974,9 @@ static void CB2_HandleStartBattle(void)
{ {
if (IsLinkTaskFinished()) if (IsLinkTaskFinished())
{ {
*(&gBattleStruct->field_180) = 0; // 0x300
*(&gBattleStruct->field_181) = 3; *(&gBattleStruct->multiBuffer.linkBattlerHeader.versionSignatureLo) = 0;
*(&gBattleStruct->multiBuffer.linkBattlerHeader.versionSignatureHi) = 3;
BufferPartyVsScreenHealth_AtStart(); BufferPartyVsScreenHealth_AtStart();
SetPlayerBerryDataInBattleStruct(); SetPlayerBerryDataInBattleStruct();
@ -981,7 +986,7 @@ static void CB2_HandleStartBattle(void)
gLinkPlayers[1].id = 1; gLinkPlayers[1].id = 1;
} }
SendBlock(bitmask_all_link_players_but_self(), &gBattleStruct->field_180, 32); SendBlock(bitmask_all_link_players_but_self(), &gBattleStruct->multiBuffer.linkBattlerHeader, sizeof(gBattleStruct->multiBuffer.linkBattlerHeader));
gBattleCommunication[MULTIUSE_STATE] = 2; gBattleCommunication[MULTIUSE_STATE] = 2;
} }
if (gWirelessCommType) if (gWirelessCommType)
@ -1002,16 +1007,16 @@ static void CB2_HandleStartBattle(void)
u8 taskId; u8 taskId;
ResetBlockReceivedFlags(); ResetBlockReceivedFlags();
sub_8036EB8(2, playerMultiplayerId); FindLinkBattleMaster(2, playerMultiplayerId);
SetAllPlayersBerryData(); SetAllPlayersBerryData();
taskId = CreateTask(InitLinkBattleVsScreen, 0); taskId = CreateTask(InitLinkBattleVsScreen, 0);
gTasks[taskId].data[1] = 0x10E; gTasks[taskId].data[1] = 0x10E;
gTasks[taskId].data[2] = 0x5A; gTasks[taskId].data[2] = 0x5A;
gTasks[taskId].data[5] = 0; gTasks[taskId].data[5] = 0;
gTasks[taskId].data[3] = gBattleStruct->vsScreenHealthFlagsLo | (gBattleStruct->vsScreenHealthFlagsHi << 8); gTasks[taskId].data[3] = gBattleStruct->multiBuffer.linkBattlerHeader.vsScreenHealthFlagsLo | (gBattleStruct->multiBuffer.linkBattlerHeader.vsScreenHealthFlagsHi << 8);
gTasks[taskId].data[4] = gBlockRecvBuffer[enemyMultiplayerId][1]; gTasks[taskId].data[4] = gBlockRecvBuffer[enemyMultiplayerId][1];
sub_8185F90(gBlockRecvBuffer[playerMultiplayerId][1]); RecordedBattle_SetFrontierPassFlagFromHword(gBlockRecvBuffer[playerMultiplayerId][1]);
sub_8185F90(gBlockRecvBuffer[enemyMultiplayerId][1]); RecordedBattle_SetFrontierPassFlagFromHword(gBlockRecvBuffer[enemyMultiplayerId][1]);
SetDeoxysStats(); SetDeoxysStats();
gBattleCommunication[MULTIUSE_STATE]++; gBattleCommunication[MULTIUSE_STATE]++;
} }
@ -1178,11 +1183,12 @@ static void CB2_HandleStartMultiPartnerBattle(void)
if (IsLinkTaskFinished()) if (IsLinkTaskFinished())
{ {
*(&gBattleStruct->field_180) = 0; // 0x300
*(&gBattleStruct->field_181) = 3; *(&gBattleStruct->multiBuffer.linkBattlerHeader.versionSignatureLo) = 0;
*(&gBattleStruct->multiBuffer.linkBattlerHeader.versionSignatureHi) = 3;
BufferPartyVsScreenHealth_AtStart(); BufferPartyVsScreenHealth_AtStart();
SetPlayerBerryDataInBattleStruct(); SetPlayerBerryDataInBattleStruct();
SendBlock(bitmask_all_link_players_but_self(), &gBattleStruct->field_180, 32); SendBlock(bitmask_all_link_players_but_self(), &gBattleStruct->multiBuffer.linkBattlerHeader, sizeof(gBattleStruct->multiBuffer.linkBattlerHeader));
gBattleCommunication[MULTIUSE_STATE] = 2; gBattleCommunication[MULTIUSE_STATE] = 2;
} }
@ -1204,7 +1210,7 @@ static void CB2_HandleStartMultiPartnerBattle(void)
u8 taskId; u8 taskId;
ResetBlockReceivedFlags(); ResetBlockReceivedFlags();
sub_8036EB8(2, playerMultiplayerId); FindLinkBattleMaster(2, playerMultiplayerId);
SetAllPlayersBerryData(); SetAllPlayersBerryData();
taskId = CreateTask(InitLinkBattleVsScreen, 0); taskId = CreateTask(InitLinkBattleVsScreen, 0);
gTasks[taskId].data[1] = 0x10E; gTasks[taskId].data[1] = 0x10E;
@ -1565,12 +1571,13 @@ static void CB2_HandleStartMultiBattle(void)
{ {
if (IsLinkTaskFinished()) if (IsLinkTaskFinished())
{ {
*(&gBattleStruct->field_180) = 0; // 0x300
*(&gBattleStruct->field_181) = 3; *(&gBattleStruct->multiBuffer.linkBattlerHeader.versionSignatureLo) = 0;
*(&gBattleStruct->multiBuffer.linkBattlerHeader.versionSignatureHi) = 3;
BufferPartyVsScreenHealth_AtStart(); BufferPartyVsScreenHealth_AtStart();
SetPlayerBerryDataInBattleStruct(); SetPlayerBerryDataInBattleStruct();
SendBlock(bitmask_all_link_players_but_self(), &gBattleStruct->field_180, 32); SendBlock(bitmask_all_link_players_but_self(), &gBattleStruct->multiBuffer.linkBattlerHeader, sizeof(gBattleStruct->multiBuffer.linkBattlerHeader));
gBattleCommunication[MULTIUSE_STATE]++; gBattleCommunication[MULTIUSE_STATE]++;
} }
if (gWirelessCommType) if (gWirelessCommType)
@ -1589,7 +1596,7 @@ static void CB2_HandleStartMultiBattle(void)
if ((GetBlockReceivedStatus() & 0xF) == 0xF) if ((GetBlockReceivedStatus() & 0xF) == 0xF)
{ {
ResetBlockReceivedFlags(); ResetBlockReceivedFlags();
sub_8036EB8(4, playerMultiplayerId); FindLinkBattleMaster(4, playerMultiplayerId);
SetAllPlayersBerryData(); SetAllPlayersBerryData();
SetDeoxysStats(); SetDeoxysStats();
var = CreateTask(InitLinkBattleVsScreen, 0); var = CreateTask(InitLinkBattleVsScreen, 0);
@ -1601,7 +1608,7 @@ static void CB2_HandleStartMultiBattle(void)
for (id = 0; id < MAX_LINK_PLAYERS; id++) for (id = 0; id < MAX_LINK_PLAYERS; id++)
{ {
sub_8185F90(gBlockRecvBuffer[id][1]); RecordedBattle_SetFrontierPassFlagFromHword(gBlockRecvBuffer[id][1]);
switch (gLinkPlayers[id].id) switch (gLinkPlayers[id].id)
{ {
case 0: case 0:
@ -1786,10 +1793,10 @@ static void CB2_HandleStartMultiBattle(void)
case 8: case 8:
if (IsLinkTaskFinished()) if (IsLinkTaskFinished())
{ {
u32* ptr = (u32*)(&gBattleStruct->field_180); u32* ptr = gBattleStruct->multiBuffer.battleVideo;
ptr[0] = gBattleTypeFlags; ptr[0] = gBattleTypeFlags;
ptr[1] = gRecordedBattleRngSeed; // UB: overwrites berry data ptr[1] = gRecordedBattleRngSeed; // UB: overwrites berry data
SendBlock(bitmask_all_link_players_but_self(), ptr, 8); SendBlock(bitmask_all_link_players_but_self(), ptr, sizeof(gBattleStruct->multiBuffer.battleVideo));
gBattleCommunication[MULTIUSE_STATE]++; gBattleCommunication[MULTIUSE_STATE]++;
} }
break; break;
@ -2248,7 +2255,7 @@ static void EndLinkBattleInSteps(void)
{ {
u8 monsCount; u8 monsCount;
gMain.field_439_x4 = sub_8185FAC(); gMain.anyLinkBattlerHasFrontierPass = RecordedBattle_GetFrontierPassFlag();
if (gBattleTypeFlags & BATTLE_TYPE_MULTI) if (gBattleTypeFlags & BATTLE_TYPE_MULTI)
monsCount = 4; monsCount = 4;
@ -2264,7 +2271,7 @@ static void EndLinkBattleInSteps(void)
FreeAllWindowBuffers(); FreeAllWindowBuffers();
SetMainCallback2(sub_80392A8); SetMainCallback2(sub_80392A8);
} }
else if (!gMain.field_439_x4) else if (!gMain.anyLinkBattlerHasFrontierPass)
{ {
SetMainCallback2(gMain.savedCallback); SetMainCallback2(gMain.savedCallback);
FreeBattleResources(); FreeBattleResources();
@ -2328,9 +2335,9 @@ static void EndLinkBattleInSteps(void)
gBattleCommunication[MULTIUSE_STATE]++; gBattleCommunication[MULTIUSE_STATE]++;
break; break;
case 9: case 9:
if (!gMain.field_439_x4 || gWirelessCommType || gReceivedRemoteLinkPlayers != 1) if (!gMain.anyLinkBattlerHasFrontierPass || gWirelessCommType || gReceivedRemoteLinkPlayers != 1)
{ {
gMain.field_439_x4 = 0; gMain.anyLinkBattlerHasFrontierPass = 0;
SetMainCallback2(gMain.savedCallback); SetMainCallback2(gMain.savedCallback);
FreeBattleResources(); FreeBattleResources();
FreeBattleSpritesData(); FreeBattleSpritesData();
@ -2426,7 +2433,7 @@ static void sub_803939C(void)
gBattleCommunication[MULTIUSE_STATE]++; gBattleCommunication[MULTIUSE_STATE]++;
break; break;
case 1: case 1:
if (gMain.field_439_x4 && gReceivedRemoteLinkPlayers == 0) if (gMain.anyLinkBattlerHasFrontierPass && gReceivedRemoteLinkPlayers == 0)
CreateTask(Task_ReconnectWithLinkPlayers, 5); CreateTask(Task_ReconnectWithLinkPlayers, 5);
gBattleCommunication[MULTIUSE_STATE]++; gBattleCommunication[MULTIUSE_STATE]++;
break; break;
@ -2496,7 +2503,7 @@ static void sub_803939C(void)
if (IsLinkTaskFinished() == TRUE) if (IsLinkTaskFinished() == TRUE)
{ {
HandleBattleWindow(0x18, 8, 0x1D, 0xD, WINDOW_CLEAR); HandleBattleWindow(0x18, 8, 0x1D, 0xD, WINDOW_CLEAR);
if (gMain.field_439_x4) if (gMain.anyLinkBattlerHasFrontierPass)
{ {
SetLinkStandbyCallback(); SetLinkStandbyCallback();
BattlePutTextOnWindow(gText_LinkStandby3, 0); BattlePutTextOnWindow(gText_LinkStandby3, 0);
@ -2507,15 +2514,15 @@ static void sub_803939C(void)
case 8: case 8:
if (--gBattleCommunication[1] == 0) if (--gBattleCommunication[1] == 0)
{ {
if (gMain.field_439_x4 && !gWirelessCommType) if (gMain.anyLinkBattlerHasFrontierPass && !gWirelessCommType)
SetCloseLinkCallback(); SetCloseLinkCallback();
gBattleCommunication[MULTIUSE_STATE]++; gBattleCommunication[MULTIUSE_STATE]++;
} }
break; break;
case 9: case 9:
if (!gMain.field_439_x4 || gWirelessCommType || gReceivedRemoteLinkPlayers != 1) if (!gMain.anyLinkBattlerHasFrontierPass || gWirelessCommType || gReceivedRemoteLinkPlayers != 1)
{ {
gMain.field_439_x4 = 0; gMain.anyLinkBattlerHasFrontierPass = 0;
if (!gPaletteFade.active) if (!gPaletteFade.active)
{ {
SetMainCallback2(gMain.savedCallback); SetMainCallback2(gMain.savedCallback);
@ -2545,7 +2552,7 @@ static void sub_803939C(void)
case 11: case 11:
if (IsLinkTaskFinished() == TRUE && !IsTextPrinterActive(0) && --gBattleCommunication[1] == 0) if (IsLinkTaskFinished() == TRUE && !IsTextPrinterActive(0) && --gBattleCommunication[1] == 0)
{ {
if (gMain.field_439_x4) if (gMain.anyLinkBattlerHasFrontierPass)
{ {
SetLinkStandbyCallback(); SetLinkStandbyCallback();
BattlePutTextOnWindow(gText_LinkStandby3, 0); BattlePutTextOnWindow(gText_LinkStandby3, 0);
@ -2557,7 +2564,7 @@ static void sub_803939C(void)
case 7: case 7:
if (!IsTextPrinterActive(0)) if (!IsTextPrinterActive(0))
{ {
if (gMain.field_439_x4) if (gMain.anyLinkBattlerHasFrontierPass)
{ {
if (IsLinkTaskFinished() == TRUE) if (IsLinkTaskFinished() == TRUE)
{ {

View File

@ -84,7 +84,7 @@ EWRAM_DATA static u8 sFrontierFacility = 0;
EWRAM_DATA static u8 sFrontierBrainSymbol = 0; EWRAM_DATA static u8 sFrontierBrainSymbol = 0;
EWRAM_DATA static MainCallback sCallback2_AfterRecordedBattle = NULL; EWRAM_DATA static MainCallback sCallback2_AfterRecordedBattle = NULL;
EWRAM_DATA u8 gRecordedBattleMultiplayerId = 0; EWRAM_DATA u8 gRecordedBattleMultiplayerId = 0;
EWRAM_DATA static u8 sUnknown_0203C7B5 = 0; EWRAM_DATA static u8 sFrontierPassFlag = 0;
EWRAM_DATA static u8 sBattleScene = 0; EWRAM_DATA static u8 sBattleScene = 0;
EWRAM_DATA static u8 sTextSpeed = 0; EWRAM_DATA static u8 sTextSpeed = 0;
EWRAM_DATA static u32 sBattleFlags = 0; EWRAM_DATA static u32 sBattleFlags = 0;
@ -687,19 +687,20 @@ u8 GetActiveBattlerLinkPlayerGender(void)
return 0; return 0;
} }
void sub_8185F84(void) void RecordedBattle_ClearFrontierPassFlag(void)
{ {
sUnknown_0203C7B5 = 0; sFrontierPassFlag = 0;
} }
void sub_8185F90(u16 arg0) // Set sFrontierPassFlag to received state of FLAG_SYS_FRONTIER_PASS
void RecordedBattle_SetFrontierPassFlagFromHword(u16 arg0)
{ {
sUnknown_0203C7B5 |= (arg0 & 0x8000) >> 0xF; sFrontierPassFlag |= (arg0 & 0x8000) >> 15;
} }
u8 sub_8185FAC(void) u8 RecordedBattle_GetFrontierPassFlag(void)
{ {
return sUnknown_0203C7B5; return sFrontierPassFlag;
} }
u8 GetBattleSceneInRecordedBattle(void) u8 GetBattleSceneInRecordedBattle(void)