diff --git a/PKHeX.Core/Saves/SAV8BS.cs b/PKHeX.Core/Saves/SAV8BS.cs
index 2e7871bcf..43e53c96a 100644
--- a/PKHeX.Core/Saves/SAV8BS.cs
+++ b/PKHeX.Core/Saves/SAV8BS.cs
@@ -33,7 +33,7 @@ namespace PKHeX.Core
Contest = new Contest8b(this, 0x79C08); // size: 0x720
Zukan = new Zukan8b(this, 0x7A328); // size: 0x30B8
- // 0x7D3E0 - Trainer Battle Data (bool,bool)[707]
+ BattleTrainer = new BattleTrainerStatus8b(this, 0x7D3E0); // size: 0x1618
// 0x7E9F8 - Menu selections (TopMenuItemTypeInt32, bool IsNew)[8], TopMenuItemTypeInt32 LastSelected
// 0x7EA3C - _FIELDOBJ_SAVE Objects[1000] (sizeof (0x44, 17 int fields), total size 0x109A0
Records = new Record8b(this, 0x8F3DC); // size: 0x78
@@ -53,8 +53,8 @@ namespace PKHeX.Core
// BoukenNote
// TV_DATA
// UgSaveData
- // GMS_DATA
- // PLAYER_NETWORK_DATA
+ // 0x9D03C - GMS_DATA // size: 0x31304
+ // 0xCE340 - PLAYER_NETWORK_DATA
// UnionSaveData
// CON_PHOTO_LANG_DATA -- contest photo language data
// ZUKAN_PERSONAL_RND_DATA
@@ -188,6 +188,7 @@ namespace PKHeX.Core
public Contest8b Contest { get; }
// public Misc8 Misc { get; }
public Zukan8b Zukan { get; }
+ public BattleTrainerStatus8b BattleTrainer { get; }
public Record8b Records { get; }
public BerryTreeGrowSave8b BerryTrees { get; }
public PoffinSaveData8b Poffins { get; }
diff --git a/PKHeX.Core/Saves/Substructures/Gen8/BS/BattleTrainerStatus8b.cs b/PKHeX.Core/Saves/Substructures/Gen8/BS/BattleTrainerStatus8b.cs
new file mode 100644
index 000000000..59f06d9b7
--- /dev/null
+++ b/PKHeX.Core/Saves/Substructures/Gen8/BS/BattleTrainerStatus8b.cs
@@ -0,0 +1,54 @@
+using System;
+
+namespace PKHeX.Core
+{
+ ///
+ /// Defeated Status for all trainers (Dpr.Trainer.TrainerID)
+ ///
+ /// size: 0x1618
+ public sealed class BattleTrainerStatus8b : SaveBlock
+ {
+ public BattleTrainerStatus8b(SAV8BS sav, int offset) : base(sav) => Offset = offset;
+
+ // Structure:
+ // (bool IsWin, bool IsBattleSearcher)[707];
+ private const int COUNT_TRAINER = 707;
+ private const int SIZE_TRAINER = 8; // bool,bool
+
+ ///
+ /// Don't use this unless you've finished the post-game.
+ ///
+ public void DefeatAll()
+ {
+ for (int i = 0; i < COUNT_TRAINER; i++)
+ {
+ SetIsWin(i, true);
+ SetIsBattleSearcher(i, false);
+ }
+ }
+
+ ///
+ /// Don't use this unless you've finished the post-game.
+ ///
+ public void RebattleAll()
+ {
+ for (int i = 0; i < COUNT_TRAINER; i++)
+ {
+ SetIsWin(i, true);
+ SetIsBattleSearcher(i, true);
+ }
+ }
+
+ private int GetTrainerOffset(int trainer)
+ {
+ if ((uint)trainer >= COUNT_TRAINER)
+ throw new ArgumentOutOfRangeException(nameof(trainer));
+ return Offset + (trainer * SIZE_TRAINER);
+ }
+
+ public bool GetIsWin(int trainer) => BitConverter.ToUInt32(Data, GetTrainerOffset(trainer)) == 1;
+ public bool GetIsBattleSearcher(int trainer) => BitConverter.ToUInt32(Data, GetTrainerOffset(trainer) + 4) == 1;
+ public void SetIsWin(int trainer, bool value) => BitConverter.GetBytes(value ? 1u : 0u).CopyTo(Data, GetTrainerOffset(trainer));
+ public void SetIsBattleSearcher(int trainer, bool value) => BitConverter.GetBytes(value ? 1u : 0u).CopyTo(Data, GetTrainerOffset(trainer) + 4);
+ }
+}