diff --git a/PKHeX.Avalonia/ViewModels/Subforms/CGearImage5ViewModel.cs b/PKHeX.Avalonia/ViewModels/Subforms/CGearImage5ViewModel.cs
new file mode 100644
index 000000000..68c9e958f
--- /dev/null
+++ b/PKHeX.Avalonia/ViewModels/Subforms/CGearImage5ViewModel.cs
@@ -0,0 +1,29 @@
+using CommunityToolkit.Mvvm.ComponentModel;
+using PKHeX.Core;
+
+namespace PKHeX.Avalonia.ViewModels.Subforms;
+
+///
+/// ViewModel for the C-Gear skin image display (Gen 5).
+/// Shows the current C-Gear background skin dimensions and status.
+///
+public partial class CGearImage5ViewModel : SaveEditorViewModelBase
+{
+ [ObservableProperty] private bool _hasSkin;
+ [ObservableProperty] private string _skinStatus = "No C-Gear skin loaded";
+ [ObservableProperty] private int _width;
+ [ObservableProperty] private int _height;
+
+ public CGearImage5ViewModel(SAV5 sav) : base(sav)
+ {
+ var data = sav.CGearSkinData;
+ CGearBackground bg = sav is SAV5BW ? new CGearBackgroundBW(data) : new CGearBackgroundB2W2(data);
+
+ _width = CGearBackground.Width;
+ _height = CGearBackground.Height;
+ _hasSkin = !bg.IsUninitialized;
+ _skinStatus = _hasSkin
+ ? $"C-Gear skin loaded ({_width}x{_height})"
+ : "No C-Gear skin loaded";
+ }
+}
diff --git a/PKHeX.Avalonia/ViewModels/Subforms/DLC5ViewModel.cs b/PKHeX.Avalonia/ViewModels/Subforms/DLC5ViewModel.cs
new file mode 100644
index 000000000..07a3469a8
--- /dev/null
+++ b/PKHeX.Avalonia/ViewModels/Subforms/DLC5ViewModel.cs
@@ -0,0 +1,164 @@
+using System;
+using System.Collections.ObjectModel;
+using CommunityToolkit.Mvvm.ComponentModel;
+using CommunityToolkit.Mvvm.Input;
+using PKHeX.Core;
+
+namespace PKHeX.Avalonia.ViewModels.Subforms;
+
+///
+/// Model for a Battle Video entry.
+///
+public class BattleVideo5Entry
+{
+ public int Index { get; }
+ public string Label { get; }
+
+ public BattleVideo5Entry(int index, string label)
+ {
+ Index = index;
+ Label = label;
+ }
+}
+
+///
+/// Model for a PWT entry.
+///
+public class PWT5Entry
+{
+ public int Index { get; }
+ public string Label { get; }
+
+ public PWT5Entry(int index, string label)
+ {
+ Index = index;
+ Label = label;
+ }
+}
+
+///
+/// Model for a Pokestar movie entry.
+///
+public class Pokestar5Entry
+{
+ public int Index { get; }
+ public string Label { get; }
+
+ public Pokestar5Entry(int index, string label)
+ {
+ Index = index;
+ Label = label;
+ }
+}
+
+///
+/// ViewModel for the Gen 5 DLC content editor.
+/// Manages C-Gear skins, Battle Videos, PWT, Pokestar Movies, Musical Shows, Memory Links, and Pokedex Skins.
+///
+public partial class DLC5ViewModel : SaveEditorViewModelBase
+{
+ private readonly SAV5 SAV5;
+
+ // C-Gear
+ [ObservableProperty] private bool _hasCGear;
+ [ObservableProperty] private string _cGearStatus = "Not loaded";
+
+ // Battle Videos
+ public ObservableCollection BattleVideos { get; } = [];
+
+ [ObservableProperty]
+ private int _selectedBattleVideoIndex;
+
+ // PWT (B2W2 only)
+ public bool ShowPWT { get; }
+ public ObservableCollection PWTEntries { get; } = [];
+
+ [ObservableProperty]
+ private int _selectedPWTIndex;
+
+ // Pokestar (B2W2 only)
+ public bool ShowPokestar { get; }
+ public ObservableCollection PokestarMovies { get; } = [];
+
+ [ObservableProperty]
+ private int _selectedPokestarIndex;
+
+ // Musical
+ [ObservableProperty] private string _musicalName = string.Empty;
+
+ // Memory Link
+ [ObservableProperty] private string _link1Status = "Link 1";
+ [ObservableProperty] private string _link2Status = "Link 2";
+
+ public DLC5ViewModel(SAV5 sav) : base(sav)
+ {
+ SAV5 = sav;
+ ShowPWT = sav is SAV5B2W2;
+ ShowPokestar = sav is SAV5B2W2;
+
+ LoadCGear();
+ LoadBattleVideos();
+ LoadPWT();
+ LoadPokestar();
+ LoadMusical();
+ }
+
+ private void LoadCGear()
+ {
+ var data = SAV5.CGearSkinData;
+ var bg = SAV5 is SAV5BW ? (CGearBackground)new CGearBackgroundBW(data) : new CGearBackgroundB2W2(data);
+ _hasCGear = !bg.IsUninitialized;
+ _cGearStatus = _hasCGear ? "C-Gear skin loaded" : "No C-Gear skin";
+ }
+
+ private void LoadBattleVideos()
+ {
+ for (int i = 0; i < 4; i++)
+ {
+ var data = SAV5.GetBattleVideo(i);
+ var bvid = new BattleVideo5(data);
+ var name = bvid.IsUninitialized ? "Empty" : bvid.GetTrainerNames();
+ BattleVideos.Add(new BattleVideo5Entry(i, $"{i:00} - {name}"));
+ }
+ }
+
+ private void LoadPWT()
+ {
+ if (SAV5 is not SAV5B2W2 b2w2)
+ return;
+ for (int i = 0; i < SAV5B2W2.PWTCount; i++)
+ {
+ var data = b2w2.GetPWT(i);
+ var pwt = new WorldTournament5(data);
+ var name = pwt.Name;
+ if (string.IsNullOrWhiteSpace(name))
+ name = "Empty";
+ PWTEntries.Add(new PWT5Entry(i, $"{i + 1:00} - {name}"));
+ }
+ }
+
+ private void LoadPokestar()
+ {
+ if (SAV5 is not SAV5B2W2 b2w2)
+ return;
+ for (int i = 0; i < SAV5B2W2.PokestarCount; i++)
+ {
+ var data = b2w2.GetPokestarMovie(i);
+ var movie = new PokestarMovie5(data);
+ PokestarMovies.Add(new Pokestar5Entry(i, $"{i + 1:00} - {movie.Name}"));
+ }
+ }
+
+ private void LoadMusical()
+ {
+ _musicalName = SAV5.Musical.MusicalName;
+ }
+
+ [RelayCommand]
+ private void Save()
+ {
+ SAV5.Musical.MusicalName = MusicalName;
+ SAV.State.Edited = true;
+ Modified = true;
+ }
+}
diff --git a/PKHeX.Avalonia/ViewModels/Subforms/Misc5ViewModel.cs b/PKHeX.Avalonia/ViewModels/Subforms/Misc5ViewModel.cs
new file mode 100644
index 000000000..6a8a48ba3
--- /dev/null
+++ b/PKHeX.Avalonia/ViewModels/Subforms/Misc5ViewModel.cs
@@ -0,0 +1,425 @@
+using System;
+using System.Collections.ObjectModel;
+using CommunityToolkit.Mvvm.ComponentModel;
+using CommunityToolkit.Mvvm.Input;
+using PKHeX.Core;
+using static System.Buffers.Binary.BinaryPrimitives;
+
+namespace PKHeX.Avalonia.ViewModels.Subforms;
+
+///
+/// Model for a fly destination entry (Gen 5).
+///
+public partial class FlyDest5Model : ObservableObject
+{
+ public int FlagBit { get; }
+ public string Name { get; }
+
+ [ObservableProperty]
+ private bool _unlocked;
+
+ public FlyDest5Model(int flagBit, string name, bool unlocked)
+ {
+ FlagBit = flagBit;
+ Name = name;
+ _unlocked = unlocked;
+ }
+}
+
+///
+/// Model for a Key System entry (B2W2).
+///
+public partial class KeyEntry5Model : ObservableObject
+{
+ public int Index { get; }
+ public string Label { get; }
+ public bool IsObtain { get; }
+
+ [ObservableProperty]
+ private bool _enabled;
+
+ public KeyEntry5Model(int index, string label, bool isObtain, bool enabled)
+ {
+ Index = index;
+ Label = label;
+ IsObtain = isObtain;
+ _enabled = enabled;
+ }
+}
+
+///
+/// Model for a Musical prop entry.
+///
+public partial class PropModel : ObservableObject
+{
+ public int Index { get; }
+ public string Name { get; }
+
+ [ObservableProperty]
+ private bool _obtained;
+
+ public PropModel(int index, string name, bool obtained)
+ {
+ Index = index;
+ Name = name;
+ _obtained = obtained;
+ }
+}
+
+///
+/// ViewModel for the Gen 5 Misc editor.
+/// Covers Fly Destinations, Roamer (BW), Key System (B2W2), Musical Props, Records, and Battle Subway.
+///
+public partial class Misc5ViewModel : SaveEditorViewModelBase
+{
+ private readonly SAV5 SAV5;
+ private readonly BattleSubway5 Subway;
+ private readonly BattleSubwayPlay5 SubwayPlay;
+ private readonly Record5 Record;
+
+ // Fly
+ public ObservableCollection FlyDestinations { get; } = [];
+ private int _flyOffset;
+ private int[] _flyDestC = [];
+
+ // Roamer (BW only)
+ public bool ShowRoamer { get; }
+
+ [ObservableProperty] private int _roamer641State;
+ [ObservableProperty] private int _roamer642State;
+ [ObservableProperty] private int _roamStatus;
+ [ObservableProperty] private bool _libertyPass;
+
+ public string[] RoamerStates { get; } = ["Not roamed", "Roaming", "Defeated", "Captured"];
+ public string[] RoamStatusStates { get; } = ["Not happened", "Go to route 7", "Unknown (2)", "Event finished"];
+
+ // Key System (B2W2 only)
+ public bool ShowKeySystem { get; }
+ public ObservableCollection KeyEntries { get; } = [];
+
+ // Musical Props
+ public ObservableCollection Props { get; } = [];
+
+ // Battle Subway
+ [ObservableProperty] private int _subwayCurrentType;
+ [ObservableProperty] private int _subwayCurrentBattle;
+
+ // Subway flags
+ [ObservableProperty] private bool _subwayFlag0;
+ [ObservableProperty] private bool _subwayFlag1;
+ [ObservableProperty] private bool _subwayFlag2;
+ [ObservableProperty] private bool _subwayFlag3;
+ [ObservableProperty] private bool _superSingle;
+ [ObservableProperty] private bool _superDouble;
+ [ObservableProperty] private bool _superMulti;
+ [ObservableProperty] private bool _subwayFlag7;
+ [ObservableProperty] private bool _npcMet;
+
+ // Subway records
+ [ObservableProperty] private int _singlePast;
+ [ObservableProperty] private int _singleRecord;
+ [ObservableProperty] private int _doublePast;
+ [ObservableProperty] private int _doubleRecord;
+ [ObservableProperty] private int _multiNpcPast;
+ [ObservableProperty] private int _multiNpcRecord;
+ [ObservableProperty] private int _multiFriendsPast;
+ [ObservableProperty] private int _multiFriendsRecord;
+ [ObservableProperty] private int _superSinglePast;
+ [ObservableProperty] private int _superSingleRecord;
+ [ObservableProperty] private int _superDoublePast;
+ [ObservableProperty] private int _superDoubleRecord;
+ [ObservableProperty] private int _superMultiNpcPast;
+ [ObservableProperty] private int _superMultiNpcRecord;
+ [ObservableProperty] private int _superMultiFriendsPast;
+ [ObservableProperty] private int _superMultiFriendsRecord;
+
+ // Records
+ [ObservableProperty] private int _record16Index;
+ [ObservableProperty] private int _record16Value;
+ [ObservableProperty] private int _record32Index;
+ [ObservableProperty] private uint _record32Value;
+
+ public Misc5ViewModel(SAV5 sav) : base(sav)
+ {
+ SAV5 = sav;
+ Subway = sav.BattleSubway;
+ SubwayPlay = sav.BattleSubwayPlay;
+ Record = sav.Records;
+
+ ReadFly();
+ ReadRoamer();
+ ReadKeySystem();
+ ReadMusical();
+ ReadSubway();
+ ReadRecords();
+
+ ShowRoamer = sav is SAV5BW;
+ ShowKeySystem = sav is SAV5B2W2;
+ }
+
+ private void ReadFly()
+ {
+ string[] flyNames;
+ switch (SAV5.Version)
+ {
+ case GameVersion.B or GameVersion.W or GameVersion.BW:
+ _flyOffset = 0x204B2;
+ flyNames = [
+ "Nuvema Town", "Accumula Town", "Striaton City", "Nacrene City",
+ "Castelia City", "Nimbasa City", "Driftveil City", "Mistralton City",
+ "Icirrus City", "Opelucid City", "Victory Road", "Pokemon League",
+ "Lacunosa Town", "Undella Town", "Black City/White Forest", "(Unity Tower)",
+ ];
+ _flyDestC = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 15, 11, 10, 13, 12, 14];
+ break;
+ case GameVersion.B2 or GameVersion.W2 or GameVersion.B2W2:
+ _flyOffset = 0x20392;
+ flyNames = [
+ "Aspertia City", "Floccesy Town", "Virbank City",
+ "Nuvema Town", "Accumula Town", "Striaton City", "Nacrene City",
+ "Castelia City", "Nimbasa City", "Driftveil City", "Mistralton City",
+ "Icirrus City", "Opelucid City",
+ "Lacunosa Town", "Undella Town", "Black City/White Forest",
+ "Lentimas Town", "Humilau City", "Victory Road", "Pokemon League",
+ "Pokestar Studios", "Join Avenue", "PWT", "(Unity Tower)",
+ ];
+ _flyDestC = [24, 27, 25, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 21, 20, 28, 26, 66, 19, 5, 6, 7, 22];
+ break;
+ default:
+ flyNames = [];
+ break;
+ }
+
+ uint valFly = ReadUInt32LittleEndian(SAV5.Data[_flyOffset..]);
+ for (int i = 0; i < flyNames.Length; i++)
+ {
+ bool isSet;
+ if (_flyDestC[i] < 32)
+ isSet = (valFly & (1u << _flyDestC[i])) != 0;
+ else
+ isSet = (SAV5.Data[_flyOffset + (_flyDestC[i] >> 3)] & (1 << (_flyDestC[i] & 7))) != 0;
+ FlyDestinations.Add(new FlyDest5Model(_flyDestC[i], flyNames[i], isSet));
+ }
+ }
+
+ private void ReadRoamer()
+ {
+ if (SAV5 is SAV5BW bw)
+ {
+ var encount = bw.Encount;
+ _roamer641State = Math.Clamp((int)encount.GetRoamerState(1), (int)0, (int)3);
+ _roamer642State = Math.Clamp((int)encount.GetRoamerState(0), (int)0, (int)3);
+ _roamStatus = Math.Clamp((int)bw.EventWork.GetWorkRoamer(), (int)0, (int)3);
+ _libertyPass = bw.Misc.IsLibertyTicketActivated;
+ }
+ }
+
+ private void ReadKeySystem()
+ {
+ if (SAV5 is SAV5B2W2 b2w2)
+ {
+ var keys = b2w2.Keys;
+ string[] keyNames = ["EasyKey", "ChallengeKey", "CityKey", "IronKey", "IcebergKey"];
+ for (int i = 0; i < 5; i++)
+ {
+ KeyEntries.Add(new KeyEntry5Model(i, $"Obtain {keyNames[i]}", true, keys.GetIsKeyObtained((KeyType5)i)));
+ KeyEntries.Add(new KeyEntry5Model(i, $"Unlock {keyNames[i]}", false, keys.GetIsKeyUnlocked((KeyType5)i)));
+ }
+ }
+ }
+
+ private void ReadMusical()
+ {
+ var musical = SAV5.Musical;
+ // Musical has 100 props
+ for (int i = 0; i < 100; i++)
+ {
+ var name = $"Prop {i:000}";
+ Props.Add(new PropModel(i, name, musical.GetHasProp(i)));
+ }
+ }
+
+ private void ReadSubway()
+ {
+ _subwayCurrentType = SubwayPlay.CurrentType;
+ _subwayCurrentBattle = SubwayPlay.CurrentBattle;
+
+ _subwayFlag0 = Subway.Flag0;
+ _subwayFlag1 = Subway.Flag1;
+ _subwayFlag2 = Subway.Flag2;
+ _subwayFlag3 = Subway.Flag3;
+ _superSingle = Subway.SuperSingle;
+ _superDouble = Subway.SuperDouble;
+ _superMulti = Subway.SuperMulti;
+ _subwayFlag7 = Subway.Flag7;
+ _npcMet = Subway.NPCMet;
+
+ _singlePast = Subway.SinglePast;
+ _singleRecord = Subway.SingleRecord;
+ _doublePast = Subway.DoublePast;
+ _doubleRecord = Subway.DoubleRecord;
+ _multiNpcPast = Subway.MultiNPCPast;
+ _multiNpcRecord = Subway.MultiNPCRecord;
+ _multiFriendsPast = Subway.MultiFriendsPast;
+ _multiFriendsRecord = Subway.MultiFriendsRecord;
+ _superSinglePast = Subway.SuperSinglePast;
+ _superSingleRecord = Subway.SuperSingleRecord;
+ _superDoublePast = Subway.SuperDoublePast;
+ _superDoubleRecord = Subway.SuperDoubleRecord;
+ _superMultiNpcPast = Subway.SuperMultiNPCPast;
+ _superMultiNpcRecord = Subway.SuperMultiNPCRecord;
+ _superMultiFriendsPast = Subway.SuperMultiFriendsPast;
+ _superMultiFriendsRecord = Subway.SuperMultiFriendsRecord;
+ }
+
+ private void ReadRecords()
+ {
+ _record16Value = Record.GetRecord16(0);
+ _record32Value = Record.GetRecord32(0);
+ }
+
+ partial void OnRecord16IndexChanged(int value)
+ {
+ if (value >= 0 && value < Record5.Record16)
+ Record16Value = Record.GetRecord16(value);
+ }
+
+ partial void OnRecord32IndexChanged(int value)
+ {
+ if (value >= 0 && value < Record5.Record32)
+ Record32Value = Record.GetRecord32(value);
+ }
+
+ [RelayCommand]
+ private void UnlockAllFlyDest()
+ {
+ foreach (var dest in FlyDestinations)
+ dest.Unlocked = true;
+ }
+
+ [RelayCommand]
+ private void UnlockAllKeys()
+ {
+ foreach (var entry in KeyEntries)
+ entry.Enabled = true;
+ }
+
+ [RelayCommand]
+ private void UnlockAllProps()
+ {
+ foreach (var prop in Props)
+ prop.Obtained = true;
+ }
+
+ [RelayCommand]
+ private void Save()
+ {
+ SaveFly();
+ SaveRoamer();
+ SaveKeySystem();
+ SaveMusical();
+ SaveSubway();
+ SaveRecords();
+
+ SAV.State.Edited = true;
+ Modified = true;
+ }
+
+ private void SaveFly()
+ {
+ uint valFly = ReadUInt32LittleEndian(SAV5.Data[_flyOffset..]);
+ for (int i = 0; i < FlyDestinations.Count; i++)
+ {
+ var dest = FlyDestinations[i];
+ if (_flyDestC[i] < 32)
+ {
+ if (dest.Unlocked)
+ valFly |= 1u << _flyDestC[i];
+ else
+ valFly &= ~(1u << _flyDestC[i]);
+ }
+ else
+ {
+ var ofs = _flyOffset + (_flyDestC[i] >> 3);
+ SAV5.Data[ofs] = (byte)((SAV5.Data[ofs] & ~(1 << (_flyDestC[i] & 7))) | ((dest.Unlocked ? 1 : 0) << (_flyDestC[i] & 7)));
+ }
+ }
+ WriteUInt32LittleEndian(SAV5.Data[_flyOffset..], valFly);
+ }
+
+ private void SaveRoamer()
+ {
+ if (SAV5 is SAV5BW bw)
+ {
+ var encount = bw.Encount;
+ encount.SetRoamerState(1, (byte)Roamer641State);
+ encount.SetRoamerState(0, (byte)Roamer642State);
+ bw.EventWork.SetWorkRoamer((ushort)RoamStatus);
+
+ if (LibertyPass != bw.Misc.IsLibertyTicketActivated)
+ bw.Misc.IsLibertyTicketActivated = LibertyPass;
+ }
+ }
+
+ private void SaveKeySystem()
+ {
+ if (SAV5 is SAV5B2W2 b2w2)
+ {
+ var keys = b2w2.Keys;
+ for (int i = 0; i < 5; i++)
+ {
+ var obtainIndex = i * 2;
+ var unlockIndex = obtainIndex + 1;
+ keys.SetIsKeyObtained((KeyType5)i, KeyEntries[obtainIndex].Enabled);
+ keys.SetIsKeyUnlocked((KeyType5)i, KeyEntries[unlockIndex].Enabled);
+ }
+ }
+ }
+
+ private void SaveMusical()
+ {
+ var musical = SAV5.Musical;
+ foreach (var prop in Props)
+ musical.SetHasProp(prop.Index, prop.Obtained);
+ }
+
+ private void SaveSubway()
+ {
+ SubwayPlay.CurrentType = SubwayCurrentType;
+ SubwayPlay.CurrentBattle = SubwayCurrentBattle;
+
+ Subway.Flag0 = SubwayFlag0;
+ Subway.Flag1 = SubwayFlag1;
+ Subway.Flag2 = SubwayFlag2;
+ Subway.Flag3 = SubwayFlag3;
+ Subway.SuperSingle = SuperSingle;
+ Subway.SuperDouble = SuperDouble;
+ Subway.SuperMulti = SuperMulti;
+ Subway.Flag7 = SubwayFlag7;
+ Subway.NPCMet = NpcMet;
+
+ Subway.SinglePast = SinglePast;
+ Subway.SingleRecord = SingleRecord;
+ Subway.DoublePast = DoublePast;
+ Subway.DoubleRecord = DoubleRecord;
+ Subway.MultiNPCPast = MultiNpcPast;
+ Subway.MultiNPCRecord = MultiNpcRecord;
+ Subway.MultiFriendsPast = MultiFriendsPast;
+ Subway.MultiFriendsRecord = MultiFriendsRecord;
+ Subway.SuperSinglePast = SuperSinglePast;
+ Subway.SuperSingleRecord = SuperSingleRecord;
+ Subway.SuperDoublePast = SuperDoublePast;
+ Subway.SuperDoubleRecord = SuperDoubleRecord;
+ Subway.SuperMultiNPCPast = SuperMultiNpcPast;
+ Subway.SuperMultiNPCRecord = SuperMultiNpcRecord;
+ Subway.SuperMultiFriendsPast = SuperMultiFriendsPast;
+ Subway.SuperMultiFriendsRecord = SuperMultiFriendsRecord;
+ }
+
+ private void SaveRecords()
+ {
+ Record.SetRecord16(Record16Index, (ushort)Record16Value);
+ Record.SetRecord32(Record32Index, Record32Value);
+ Record.EndAccess();
+ }
+}
diff --git a/PKHeX.Avalonia/ViewModels/Subforms/Pokedex5ViewModel.cs b/PKHeX.Avalonia/ViewModels/Subforms/Pokedex5ViewModel.cs
new file mode 100644
index 000000000..e2d966955
--- /dev/null
+++ b/PKHeX.Avalonia/ViewModels/Subforms/Pokedex5ViewModel.cs
@@ -0,0 +1,208 @@
+using System;
+using System.Collections.ObjectModel;
+using System.Linq;
+using CommunityToolkit.Mvvm.ComponentModel;
+using CommunityToolkit.Mvvm.Input;
+using PKHeX.Core;
+
+namespace PKHeX.Avalonia.ViewModels.Subforms;
+
+///
+/// Model for a single Gen 5 Pokedex species entry.
+///
+public partial class Pokedex5EntryModel : ObservableObject
+{
+ public ushort Species { get; }
+ public string Label { get; }
+
+ // Caught
+ [ObservableProperty] private bool _caught;
+
+ // Seen: Male, Female, Male Shiny, Female Shiny
+ [ObservableProperty] private bool _seenMale;
+ [ObservableProperty] private bool _seenFemale;
+ [ObservableProperty] private bool _seenMaleShiny;
+ [ObservableProperty] private bool _seenFemaleShiny;
+
+ // Displayed: Male, Female, Male Shiny, Female Shiny
+ [ObservableProperty] private bool _dispMale;
+ [ObservableProperty] private bool _dispFemale;
+ [ObservableProperty] private bool _dispMaleShiny;
+ [ObservableProperty] private bool _dispFemaleShiny;
+
+ // Language flags (7 languages: JPN, ENG, FRE, ITA, GER, SPA, KOR)
+ [ObservableProperty] private bool[] _languages;
+
+ public bool HasLanguages { get; }
+
+ public Pokedex5EntryModel(ushort species, string label, bool hasLanguages)
+ {
+ Species = species;
+ Label = label;
+ HasLanguages = hasLanguages;
+ _languages = new bool[7];
+ }
+}
+
+///
+/// ViewModel for the Gen 5 Pokedex editor.
+/// Edits seen/caught/language/form status per species.
+///
+public partial class Pokedex5ViewModel : SaveEditorViewModelBase
+{
+ private readonly SAV5 SAV5;
+ private readonly Zukan5 Dex;
+ private const int LangCount = 7;
+
+ [ObservableProperty] private string _searchText = string.Empty;
+ [ObservableProperty] private bool _nationalDexUnlocked;
+ [ObservableProperty] private bool _nationalDexActive;
+ [ObservableProperty] private string _spindaPid = "00000000";
+
+ public ObservableCollection AllEntries { get; } = [];
+
+ [ObservableProperty]
+ private ObservableCollection _filteredEntries = [];
+
+ public Pokedex5ViewModel(SAV5 sav) : base(sav)
+ {
+ SAV5 = sav;
+ Dex = sav.Zukan;
+
+ _nationalDexUnlocked = Dex.IsNationalDexUnlocked;
+ _nationalDexActive = Dex.IsNationalDexMode;
+ _spindaPid = Dex.Spinda.ToString("X8");
+
+ var speciesNames = GameInfo.Strings.specieslist;
+ for (ushort i = 1; i <= sav.MaxSpeciesID; i++)
+ {
+ var name = i < speciesNames.Length ? speciesNames[i] : $"Species {i}";
+ var label = $"{i:000} - {name}";
+ bool hasLangs = i <= 493; // Language flags only for Gen 1-4 species
+
+ var entry = new Pokedex5EntryModel(i, label, hasLangs)
+ {
+ Caught = Dex.GetCaught(i),
+ SeenMale = Dex.GetSeen(i, 0),
+ SeenFemale = Dex.GetSeen(i, 1),
+ SeenMaleShiny = Dex.GetSeen(i, 2),
+ SeenFemaleShiny = Dex.GetSeen(i, 3),
+ DispMale = Dex.GetDisplayed(i, 0),
+ DispFemale = Dex.GetDisplayed(i, 1),
+ DispMaleShiny = Dex.GetDisplayed(i, 2),
+ DispFemaleShiny = Dex.GetDisplayed(i, 3),
+ };
+
+ if (hasLangs)
+ {
+ var langs = new bool[LangCount];
+ for (int l = 0; l < LangCount; l++)
+ langs[l] = Dex.GetLanguageFlag(i, l);
+ entry.Languages = langs;
+ }
+
+ AllEntries.Add(entry);
+ }
+
+ FilteredEntries = new ObservableCollection(AllEntries);
+ }
+
+ partial void OnSearchTextChanged(string value) => ApplyFilter();
+
+ private void ApplyFilter()
+ {
+ if (string.IsNullOrWhiteSpace(SearchText))
+ {
+ FilteredEntries = new ObservableCollection(AllEntries);
+ return;
+ }
+ FilteredEntries = new ObservableCollection(
+ AllEntries.Where(e => e.Label.Contains(SearchText, StringComparison.OrdinalIgnoreCase)));
+ }
+
+ [RelayCommand]
+ private void SeenAll()
+ {
+ foreach (var entry in AllEntries)
+ {
+ entry.SeenMale = true;
+ entry.SeenFemale = true;
+ if (!entry.DispMale && !entry.DispFemale && !entry.DispMaleShiny && !entry.DispFemaleShiny)
+ entry.DispMale = true;
+ }
+ }
+
+ [RelayCommand]
+ private void CaughtAll()
+ {
+ foreach (var entry in AllEntries)
+ {
+ entry.Caught = true;
+ if (entry.HasLanguages)
+ {
+ var langs = new bool[LangCount];
+ for (int i = 0; i < LangCount; i++)
+ langs[i] = true;
+ entry.Languages = langs;
+ }
+ }
+ }
+
+ [RelayCommand]
+ private void ClearAll()
+ {
+ foreach (var entry in AllEntries)
+ {
+ entry.Caught = false;
+ entry.SeenMale = false;
+ entry.SeenFemale = false;
+ entry.SeenMaleShiny = false;
+ entry.SeenFemaleShiny = false;
+ entry.DispMale = false;
+ entry.DispFemale = false;
+ entry.DispMaleShiny = false;
+ entry.DispFemaleShiny = false;
+ if (entry.HasLanguages)
+ entry.Languages = new bool[LangCount];
+ }
+ }
+
+ [RelayCommand]
+ private void CompleteAll()
+ {
+ SeenAll();
+ CaughtAll();
+ }
+
+ [RelayCommand]
+ private void Save()
+ {
+ foreach (var entry in AllEntries)
+ {
+ var species = entry.Species;
+ Dex.SetCaught(species, entry.Caught);
+ Dex.SetSeen(species, 0, entry.SeenMale);
+ Dex.SetSeen(species, 1, entry.SeenFemale);
+ Dex.SetSeen(species, 2, entry.SeenMaleShiny);
+ Dex.SetSeen(species, 3, entry.SeenFemaleShiny);
+ Dex.SetDisplayed(species, 0, entry.DispMale);
+ Dex.SetDisplayed(species, 1, entry.DispFemale);
+ Dex.SetDisplayed(species, 2, entry.DispMaleShiny);
+ Dex.SetDisplayed(species, 3, entry.DispFemaleShiny);
+
+ if (entry.HasLanguages)
+ {
+ for (int l = 0; l < LangCount; l++)
+ Dex.SetLanguageFlag(species, l, entry.Languages[l]);
+ }
+ }
+
+ Dex.IsNationalDexUnlocked = NationalDexUnlocked;
+ Dex.IsNationalDexMode = NationalDexActive;
+ if (uint.TryParse(SpindaPid, System.Globalization.NumberStyles.HexNumber, null, out var spinda))
+ Dex.Spinda = spinda;
+
+ SAV.State.Edited = true;
+ Modified = true;
+ }
+}
diff --git a/PKHeX.Avalonia/ViewModels/Subforms/SAVBerryFieldXYViewModel.cs b/PKHeX.Avalonia/ViewModels/Subforms/SAVBerryFieldXYViewModel.cs
new file mode 100644
index 000000000..7f6ccaf57
--- /dev/null
+++ b/PKHeX.Avalonia/ViewModels/Subforms/SAVBerryFieldXYViewModel.cs
@@ -0,0 +1,97 @@
+using System;
+using System.Collections.ObjectModel;
+using CommunityToolkit.Mvvm.ComponentModel;
+using CommunityToolkit.Mvvm.Input;
+using PKHeX.Core;
+using static System.Buffers.Binary.BinaryPrimitives;
+
+namespace PKHeX.Avalonia.ViewModels.Subforms;
+
+///
+/// Model for a single berry plot entry.
+///
+public partial class BerryPlotModel : ObservableObject
+{
+ public int Index { get; }
+
+ [ObservableProperty]
+ private int _berry;
+
+ [ObservableProperty]
+ private int _u1;
+
+ [ObservableProperty]
+ private int _u2;
+
+ [ObservableProperty]
+ private int _u3;
+
+ [ObservableProperty]
+ private int _u4;
+
+ [ObservableProperty]
+ private int _u5;
+
+ [ObservableProperty]
+ private int _u6;
+
+ [ObservableProperty]
+ private int _u7;
+
+ public string DisplayName => $"Plot {Index + 1}";
+
+ public BerryPlotModel(int index) => Index = index;
+}
+
+///
+/// ViewModel for the Gen 6 XY Berry Field viewer.
+/// Read-only display of berry plots (no save, just viewing).
+///
+public partial class SAVBerryFieldXYViewModel : SaveEditorViewModelBase
+{
+ private readonly SAV6XY _sav;
+
+ public ObservableCollection Plots { get; } = [];
+
+ [ObservableProperty]
+ private BerryPlotModel? _selectedPlot;
+
+ [ObservableProperty]
+ private int _selectedPlotIndex = -1;
+
+ public SAVBerryFieldXYViewModel(SAV6XY sav) : base(sav)
+ {
+ _sav = sav;
+
+ for (int i = 0; i < BerryField6XY.Count; i++)
+ {
+ var model = new BerryPlotModel(i);
+ Plots.Add(model);
+ }
+
+ if (Plots.Count > 0)
+ SelectedPlotIndex = 0;
+ }
+
+ partial void OnSelectedPlotIndexChanged(int value)
+ {
+ if (value < 0 || value >= Plots.Count)
+ return;
+ LoadPlot(value);
+ SelectedPlot = Plots[value];
+ }
+
+ private void LoadPlot(int index)
+ {
+ var span = _sav.BerryField.GetPlot(index);
+ var model = Plots[index];
+ model.Berry = ReadUInt16LittleEndian(span);
+ model.U1 = ReadUInt16LittleEndian(span[(2 * 1)..]);
+ model.U2 = ReadUInt16LittleEndian(span[(2 * 2)..]);
+ model.U3 = ReadUInt16LittleEndian(span[(2 * 3)..]);
+ model.U4 = ReadUInt16LittleEndian(span[(2 * 4)..]);
+ model.U5 = ReadUInt16LittleEndian(span[(2 * 5)..]);
+ model.U6 = ReadUInt16LittleEndian(span[(2 * 6)..]);
+ model.U7 = ReadUInt16LittleEndian(span[(2 * 7)..]);
+ }
+}
diff --git a/PKHeX.Avalonia/ViewModels/Subforms/SAVHallOfFame6ViewModel.cs b/PKHeX.Avalonia/ViewModels/Subforms/SAVHallOfFame6ViewModel.cs
new file mode 100644
index 000000000..a04247cb3
--- /dev/null
+++ b/PKHeX.Avalonia/ViewModels/Subforms/SAVHallOfFame6ViewModel.cs
@@ -0,0 +1,229 @@
+using System;
+using System.Collections.Generic;
+using System.Collections.ObjectModel;
+using System.Linq;
+using System.Text;
+using CommunityToolkit.Mvvm.ComponentModel;
+using CommunityToolkit.Mvvm.Input;
+using PKHeX.Core;
+
+namespace PKHeX.Avalonia.ViewModels.Subforms;
+
+///
+/// ViewModel for the Gen 6 Hall of Fame viewer/editor.
+/// Shows 16 entries with 6 team members each.
+///
+public partial class SAVHallOfFame6ViewModel : SaveEditorViewModelBase
+{
+ private readonly SAV6 _origin;
+ private readonly SAV6 _sav;
+ private readonly HallOfFame6 _fame;
+ private bool _loading;
+
+ public List EntryNames { get; } = [];
+ public List SpeciesList { get; }
+ public List ItemsList { get; }
+ public List MovesList { get; }
+
+ [ObservableProperty]
+ private int _selectedEntryIndex = -1;
+
+ [ObservableProperty]
+ private int _memberIndex = 1;
+
+ [ObservableProperty]
+ private int _maxMembers = 6;
+
+ [ObservableProperty]
+ private int _selectedSpecies;
+
+ [ObservableProperty]
+ private int _selectedItem;
+
+ [ObservableProperty]
+ private int _move1;
+
+ [ObservableProperty]
+ private int _move2;
+
+ [ObservableProperty]
+ private int _move3;
+
+ [ObservableProperty]
+ private int _move4;
+
+ [ObservableProperty]
+ private string _ec = "00000000";
+
+ [ObservableProperty]
+ private string _tid = "00000";
+
+ [ObservableProperty]
+ private string _sid = "00000";
+
+ [ObservableProperty]
+ private string _nickname = string.Empty;
+
+ [ObservableProperty]
+ private string _otName = string.Empty;
+
+ [ObservableProperty]
+ private bool _isShiny;
+
+ [ObservableProperty]
+ private bool _isNicknamed;
+
+ [ObservableProperty]
+ private int _level;
+
+ [ObservableProperty]
+ private string _entryText = string.Empty;
+
+ [ObservableProperty]
+ private string _clearIndex = "000";
+
+ public SAVHallOfFame6ViewModel(SAV6 sav) : base(sav)
+ {
+ _sav = (SAV6)(_origin = sav).Clone();
+ _fame = ((ISaveBlock6Main)_sav).HallOfFame;
+
+ var filtered = GameInfo.FilteredSources;
+ SpeciesList = filtered.Species.ToList();
+ ItemsList = filtered.Items.ToList();
+ MovesList = filtered.Moves.ToList();
+
+ for (int i = 0; i < HallOfFame6.Entries; i++)
+ EntryNames.Add($"Entry {i}");
+
+ SelectedEntryIndex = 0;
+ }
+
+ partial void OnSelectedEntryIndexChanged(int value)
+ {
+ if (value < 0)
+ return;
+ LoadEntry(value);
+ }
+
+ partial void OnMemberIndexChanged(int value)
+ {
+ if (_loading || value < 1 || SelectedEntryIndex < 0)
+ return;
+ LoadMember(SelectedEntryIndex, value - 1);
+ }
+
+ private void LoadEntry(int index)
+ {
+ _loading = true;
+ var span = _fame.GetEntry(index);
+ var vnd = new HallFame6Index(span[^4..]);
+ ClearIndex = vnd.ClearIndex.ToString("000");
+
+ var sb = new StringBuilder();
+ sb.AppendLine($"Entry #{vnd.ClearIndex}");
+
+ if (!vnd.HasData)
+ {
+ sb.AppendLine("No records in this slot.");
+ EntryText = sb.ToString();
+ MemberIndex = 1;
+ MaxMembers = 1;
+ _loading = false;
+ return;
+ }
+
+ var year = vnd.Year + 2000;
+ var month = vnd.Month;
+ var day = vnd.Day;
+ sb.AppendLine($"Date: {year}/{month:00}/{day:00}");
+
+ int monCount = 0;
+ for (int i = 0; i < 6; i++)
+ {
+ var slice = span[(i * HallFame6Entity.SIZE)..];
+ var entity = new HallFame6Entity(slice, _sav.Language);
+ if (entity.Species == 0)
+ continue;
+ monCount++;
+ var str = GameInfo.Strings;
+ sb.AppendLine($" {str.Species[entity.Species]} Lv.{entity.Level} - {str.Item[entity.HeldItem]}");
+ }
+
+ EntryText = sb.ToString();
+ MaxMembers = monCount == 0 ? 1 : monCount;
+ MemberIndex = 1;
+ LoadMember(index, 0);
+ _loading = false;
+ }
+
+ private void LoadMember(int entryIndex, int memberIdx)
+ {
+ _loading = true;
+ var slice = _fame.GetEntity(entryIndex, memberIdx);
+ var entity = new HallFame6Entity(slice, _sav.Language);
+
+ SelectedSpecies = entity.Species;
+ SelectedItem = entity.HeldItem;
+ Move1 = entity.Move1;
+ Move2 = entity.Move2;
+ Move3 = entity.Move3;
+ Move4 = entity.Move4;
+ Ec = entity.EncryptionConstant.ToString("X8");
+ Tid = entity.TID16.ToString("00000");
+ Sid = entity.SID16.ToString("00000");
+ Nickname = entity.Nickname;
+ OtName = entity.OriginalTrainerName;
+ IsShiny = entity.IsShiny;
+ IsNicknamed = entity.IsNicknamed;
+ Level = (int)entity.Level;
+ _loading = false;
+ }
+
+ private void SaveMember()
+ {
+ if (SelectedEntryIndex < 0 || MemberIndex < 1)
+ return;
+ var slice = _fame.GetEntity(SelectedEntryIndex, MemberIndex - 1);
+ var entity = new HallFame6Entity(slice, _sav.Language)
+ {
+ Species = (ushort)SelectedSpecies,
+ HeldItem = (ushort)SelectedItem,
+ Move1 = (ushort)Move1,
+ Move2 = (ushort)Move2,
+ Move3 = (ushort)Move3,
+ Move4 = (ushort)Move4,
+ EncryptionConstant = Convert.ToUInt32(Ec, 16),
+ TID16 = ushort.TryParse(Tid, out var tid) ? tid : (ushort)0,
+ SID16 = ushort.TryParse(Sid, out var sid) ? sid : (ushort)0,
+ Nickname = Nickname,
+ OriginalTrainerName = OtName,
+ IsShiny = IsShiny,
+ IsNicknamed = IsNicknamed,
+ Level = (uint)Math.Clamp(Level, 0, 100),
+ };
+
+ var span = _fame.GetEntry(SelectedEntryIndex);
+ _ = new HallFame6Index(span[^4..])
+ {
+ ClearIndex = ushort.TryParse(ClearIndex, out var ci) ? ci : (ushort)0,
+ HasData = true,
+ };
+ }
+
+ [RelayCommand]
+ private void DeleteEntry()
+ {
+ if (SelectedEntryIndex < 1)
+ return;
+ _fame.ClearEntry(SelectedEntryIndex);
+ LoadEntry(SelectedEntryIndex);
+ }
+
+ [RelayCommand]
+ private void Save()
+ {
+ SaveMember();
+ _origin.CopyChangesFrom(_sav);
+ Modified = true;
+ }
+}
diff --git a/PKHeX.Avalonia/ViewModels/Subforms/SAVLink6ViewModel.cs b/PKHeX.Avalonia/ViewModels/Subforms/SAVLink6ViewModel.cs
new file mode 100644
index 000000000..0f53c965c
--- /dev/null
+++ b/PKHeX.Avalonia/ViewModels/Subforms/SAVLink6ViewModel.cs
@@ -0,0 +1,163 @@
+using System.Collections.Generic;
+using System.Linq;
+using CommunityToolkit.Mvvm.ComponentModel;
+using CommunityToolkit.Mvvm.Input;
+using PKHeX.Core;
+
+namespace PKHeX.Avalonia.ViewModels.Subforms;
+
+///
+/// ViewModel for the Gen 6 Link event editor.
+/// Edits link data including items, quantities, battle points, and pokemiles.
+///
+public partial class SAVLink6ViewModel : SaveEditorViewModelBase
+{
+ private readonly SaveFile _origin;
+ private readonly ISaveBlock6Main _clone;
+ private readonly PL6 _gifts;
+
+ public List ItemsList { get; }
+
+ [ObservableProperty]
+ private string _linkSource = string.Empty;
+
+ [ObservableProperty]
+ private bool _linkAvailable;
+
+ [ObservableProperty]
+ private int _battlePoints;
+
+ [ObservableProperty]
+ private int _pokemiles;
+
+ [ObservableProperty]
+ private int _item1;
+
+ [ObservableProperty]
+ private int _item2;
+
+ [ObservableProperty]
+ private int _item3;
+
+ [ObservableProperty]
+ private int _item4;
+
+ [ObservableProperty]
+ private int _item5;
+
+ [ObservableProperty]
+ private int _item6;
+
+ [ObservableProperty]
+ private int _quantity1;
+
+ [ObservableProperty]
+ private int _quantity2;
+
+ [ObservableProperty]
+ private int _quantity3;
+
+ [ObservableProperty]
+ private int _quantity4;
+
+ [ObservableProperty]
+ private int _quantity5;
+
+ [ObservableProperty]
+ private int _quantity6;
+
+ [ObservableProperty]
+ private string _pkm1 = string.Empty;
+
+ [ObservableProperty]
+ private string _pkm2 = string.Empty;
+
+ [ObservableProperty]
+ private string _pkm3 = string.Empty;
+
+ [ObservableProperty]
+ private string _pkm4 = string.Empty;
+
+ [ObservableProperty]
+ private string _pkm5 = string.Empty;
+
+ [ObservableProperty]
+ private string _pkm6 = string.Empty;
+
+ public SAVLink6ViewModel(SaveFile sav) : base(sav)
+ {
+ _origin = sav;
+ var clone = sav.Clone();
+ _clone = (ISaveBlock6Main)clone;
+ _gifts = _clone.Link.Gifts;
+
+ ItemsList = GameInfo.FilteredSources.Items.ToList();
+
+ LoadLinkData();
+ }
+
+ private void LoadLinkData()
+ {
+ LinkSource = _gifts.Origin;
+ LinkAvailable = _gifts.Enabled;
+
+ BattlePoints = _gifts.BattlePoints;
+ Pokemiles = _gifts.Pokemiles;
+
+ Item1 = _gifts.Item1;
+ Item2 = _gifts.Item2;
+ Item3 = _gifts.Item3;
+ Item4 = _gifts.Item4;
+ Item5 = _gifts.Item5;
+ Item6 = _gifts.Item6;
+
+ Quantity1 = _gifts.Quantity1;
+ Quantity2 = _gifts.Quantity2;
+ Quantity3 = _gifts.Quantity3;
+ Quantity4 = _gifts.Quantity4;
+ Quantity5 = _gifts.Quantity5;
+ Quantity6 = _gifts.Quantity6;
+
+ Pkm1 = GetSpecies(_gifts.Entity1.Species);
+ Pkm2 = GetSpecies(_gifts.Entity2.Species);
+ Pkm3 = GetSpecies(_gifts.Entity3.Species);
+ Pkm4 = GetSpecies(_gifts.Entity4.Species);
+ Pkm5 = GetSpecies(_gifts.Entity5.Species);
+ Pkm6 = GetSpecies(_gifts.Entity6.Species);
+ }
+
+ private static string GetSpecies(ushort species)
+ {
+ var arr = GameInfo.Strings.Species;
+ if (species < arr.Count)
+ return arr[species];
+ return species.ToString();
+ }
+
+ [RelayCommand]
+ private void Save()
+ {
+ _gifts.Origin = LinkSource;
+ _gifts.Enabled = LinkAvailable;
+ _gifts.BattlePoints = (ushort)BattlePoints;
+ _gifts.Pokemiles = (ushort)Pokemiles;
+
+ _gifts.Item1 = (ushort)Item1;
+ _gifts.Item2 = (ushort)Item2;
+ _gifts.Item3 = (ushort)Item3;
+ _gifts.Item4 = (ushort)Item4;
+ _gifts.Item5 = (ushort)Item5;
+ _gifts.Item6 = (ushort)Item6;
+
+ _gifts.Quantity1 = (ushort)Quantity1;
+ _gifts.Quantity2 = (ushort)Quantity2;
+ _gifts.Quantity3 = (ushort)Quantity3;
+ _gifts.Quantity4 = (ushort)Quantity4;
+ _gifts.Quantity5 = (ushort)Quantity5;
+ _gifts.Quantity6 = (ushort)Quantity6;
+
+ _clone.Link.RefreshChecksum();
+ _origin.CopyChangesFrom((SaveFile)_clone);
+ Modified = true;
+ }
+}
diff --git a/PKHeX.Avalonia/ViewModels/Subforms/SAVOPower6ViewModel.cs b/PKHeX.Avalonia/ViewModels/Subforms/SAVOPower6ViewModel.cs
new file mode 100644
index 000000000..19c9338c4
--- /dev/null
+++ b/PKHeX.Avalonia/ViewModels/Subforms/SAVOPower6ViewModel.cs
@@ -0,0 +1,151 @@
+using System;
+using System.Collections.ObjectModel;
+using CommunityToolkit.Mvvm.ComponentModel;
+using CommunityToolkit.Mvvm.Input;
+using PKHeX.Core;
+
+namespace PKHeX.Avalonia.ViewModels.Subforms;
+
+///
+/// Model for an unlock flag item.
+///
+public partial class OPowerUnlockModel : ObservableObject
+{
+ public string Name { get; }
+ public int Index { get; }
+
+ [ObservableProperty]
+ private bool _isUnlocked;
+
+ public OPowerUnlockModel(string name, int index, bool unlocked)
+ {
+ Name = name;
+ Index = index;
+ _isUnlocked = unlocked;
+ }
+}
+
+///
+/// Model for a field/battle level row.
+///
+public partial class OPowerLevelModel : ObservableObject
+{
+ public string Name { get; }
+ public int Index { get; }
+
+ [ObservableProperty]
+ private byte _level1;
+
+ [ObservableProperty]
+ private byte _level2;
+
+ public OPowerLevelModel(string name, int index, byte level1, byte level2)
+ {
+ Name = name;
+ Index = index;
+ _level1 = level1;
+ _level2 = level2;
+ }
+}
+
+///
+/// ViewModel for the Gen 6 O-Power editor.
+/// Edits unlock states, field/battle levels, and points.
+///
+public partial class SAVOPower6ViewModel : SaveEditorViewModelBase
+{
+ private readonly SaveFile _origin;
+ private readonly SaveFile _clone;
+ private readonly OPower6 _block;
+
+ public ObservableCollection UnlockFlags { get; } = [];
+ public ObservableCollection FieldLevels { get; } = [];
+ public ObservableCollection BattleLevels { get; } = [];
+
+ [ObservableProperty]
+ private byte _points;
+
+ public SAVOPower6ViewModel(ISaveBlock6Main sav) : base((SaveFile)sav)
+ {
+ _origin = (SaveFile)sav;
+ _clone = _origin.Clone();
+ _block = ((ISaveBlock6Main)_clone).OPower;
+
+ LoadData();
+ }
+
+ private void LoadData()
+ {
+ UnlockFlags.Clear();
+ FieldLevels.Clear();
+ BattleLevels.Clear();
+
+ // Unlock flags - use enum names
+ var indexNames = Enum.GetNames();
+ int indexCount = (int)OPower6Index.Count;
+ for (int i = 0; i < indexCount; i++)
+ {
+ var name = i < indexNames.Length ? indexNames[i] : $"Index {i}";
+ bool unlocked = _block.GetState((OPower6Index)i) == OPowerFlagState.Unlocked;
+ UnlockFlags.Add(new OPowerUnlockModel(name, i, unlocked));
+ }
+
+ // Field levels
+ var fieldNames = Enum.GetNames();
+ int fieldCount = (int)OPower6FieldType.Count;
+ for (int i = 0; i < fieldCount; i++)
+ {
+ var name = i < fieldNames.Length ? fieldNames[i] : $"Field {i}";
+ FieldLevels.Add(new OPowerLevelModel(name, i,
+ _block.GetLevel1((OPower6FieldType)i),
+ _block.GetLevel2((OPower6FieldType)i)));
+ }
+
+ // Battle levels
+ var battleNames = Enum.GetNames();
+ int battleCount = (int)OPower6BattleType.Count;
+ for (int i = 0; i < battleCount; i++)
+ {
+ var name = i < battleNames.Length ? battleNames[i] : $"Battle {i}";
+ BattleLevels.Add(new OPowerLevelModel(name, i,
+ _block.GetLevel1((OPower6BattleType)i),
+ _block.GetLevel2((OPower6BattleType)i)));
+ }
+
+ Points = _block.Points;
+ }
+
+ [RelayCommand]
+ private void GiveAll()
+ {
+ _block.UnlockAll();
+ LoadData();
+ }
+
+ [RelayCommand]
+ private void ClearAll()
+ {
+ _block.ClearAll();
+ LoadData();
+ }
+
+ [RelayCommand]
+ private void Save()
+ {
+ foreach (var flag in UnlockFlags)
+ _block.SetState((OPower6Index)flag.Index, flag.IsUnlocked ? OPowerFlagState.Unlocked : OPowerFlagState.Locked);
+ foreach (var field in FieldLevels)
+ {
+ _block.SetLevel1((OPower6FieldType)field.Index, field.Level1);
+ _block.SetLevel2((OPower6FieldType)field.Index, field.Level2);
+ }
+ foreach (var battle in BattleLevels)
+ {
+ _block.SetLevel1((OPower6BattleType)battle.Index, battle.Level1);
+ _block.SetLevel2((OPower6BattleType)battle.Index, battle.Level2);
+ }
+ _block.Points = Points;
+ _origin.CopyChangesFrom(_clone);
+ Modified = true;
+ }
+}
diff --git a/PKHeX.Avalonia/ViewModels/Subforms/SAVPokeBlockORASViewModel.cs b/PKHeX.Avalonia/ViewModels/Subforms/SAVPokeBlockORASViewModel.cs
new file mode 100644
index 000000000..2e57f0a78
--- /dev/null
+++ b/PKHeX.Avalonia/ViewModels/Subforms/SAVPokeBlockORASViewModel.cs
@@ -0,0 +1,74 @@
+using System.Collections.ObjectModel;
+using CommunityToolkit.Mvvm.ComponentModel;
+using CommunityToolkit.Mvvm.Input;
+using PKHeX.Core;
+
+namespace PKHeX.Avalonia.ViewModels.Subforms;
+
+///
+/// Model for a single PokeBlock entry in ORAS.
+///
+public partial class PokeBlock6Model : ObservableObject
+{
+ public int Index { get; }
+ public string Label { get; }
+
+ [ObservableProperty]
+ private uint _count;
+
+ public PokeBlock6Model(int index, string label, uint count)
+ {
+ Index = index;
+ Label = label;
+ _count = count;
+ }
+}
+
+///
+/// ViewModel for the Gen 6 ORAS PokeBlock editor.
+/// Edits the 12 pokeblock counts.
+///
+public partial class SAVPokeBlockORASViewModel : SaveEditorViewModelBase
+{
+ private readonly SAV6AO _origin;
+ private readonly SAV6AO _sav;
+
+ public ObservableCollection Blocks { get; } = [];
+
+ public SAVPokeBlockORASViewModel(SAV6AO sav) : base(sav)
+ {
+ _sav = (SAV6AO)(_origin = sav).Clone();
+
+ var contest = _sav.Contest;
+ var blockNames = GameInfo.Strings.pokeblocks;
+ for (int i = 0; i < Contest6.CountBlock; i++)
+ {
+ var label = (94 + i < blockNames.Length) ? blockNames[94 + i] : $"Block {i}";
+ Blocks.Add(new PokeBlock6Model(i, label, contest.GetBlockCount(i)));
+ }
+ }
+
+ [RelayCommand]
+ private void GiveAll()
+ {
+ foreach (var block in Blocks)
+ block.Count = 999;
+ }
+
+ [RelayCommand]
+ private void ClearAll()
+ {
+ foreach (var block in Blocks)
+ block.Count = 0;
+ }
+
+ [RelayCommand]
+ private void Save()
+ {
+ var contest = _sav.Contest;
+ foreach (var block in Blocks)
+ contest.SetBlockCount(block.Index, block.Count);
+ _origin.CopyChangesFrom(_sav);
+ Modified = true;
+ }
+}
diff --git a/PKHeX.Avalonia/ViewModels/Subforms/SAVPokedexORASViewModel.cs b/PKHeX.Avalonia/ViewModels/Subforms/SAVPokedexORASViewModel.cs
new file mode 100644
index 000000000..3a5ddc5ca
--- /dev/null
+++ b/PKHeX.Avalonia/ViewModels/Subforms/SAVPokedexORASViewModel.cs
@@ -0,0 +1,233 @@
+using System;
+using System.Collections.ObjectModel;
+using CommunityToolkit.Mvvm.ComponentModel;
+using CommunityToolkit.Mvvm.Input;
+using PKHeX.Core;
+
+namespace PKHeX.Avalonia.ViewModels.Subforms;
+
+///
+/// ViewModel for the Gen 6 ORAS Pokedex editor.
+/// Edits seen/caught/language flags and DexNav counts per species.
+///
+public partial class SAVPokedexORASViewModel : SaveEditorViewModelBase
+{
+ private readonly SaveFile _origin;
+ private readonly SAV6AO _sav;
+ private readonly Zukan6AO _zukan;
+ private bool _editing;
+ private ushort _species = ushort.MaxValue;
+
+ public ObservableCollection SpeciesNames { get; } = [];
+
+ [ObservableProperty]
+ private int _selectedSpeciesIndex = -1;
+
+ [ObservableProperty]
+ private bool _caught;
+
+ [ObservableProperty]
+ private bool _seenMale;
+
+ [ObservableProperty]
+ private bool _seenFemale;
+
+ [ObservableProperty]
+ private bool _seenMaleShiny;
+
+ [ObservableProperty]
+ private bool _seenFemaleShiny;
+
+ [ObservableProperty]
+ private bool _displayedMale;
+
+ [ObservableProperty]
+ private bool _displayedFemale;
+
+ [ObservableProperty]
+ private bool _displayedMaleShiny;
+
+ [ObservableProperty]
+ private bool _displayedFemaleShiny;
+
+ [ObservableProperty]
+ private bool _langJPN;
+
+ [ObservableProperty]
+ private bool _langENG;
+
+ [ObservableProperty]
+ private bool _langFRE;
+
+ [ObservableProperty]
+ private bool _langITA;
+
+ [ObservableProperty]
+ private bool _langGER;
+
+ [ObservableProperty]
+ private bool _langSPA;
+
+ [ObservableProperty]
+ private bool _langKOR;
+
+ [ObservableProperty]
+ private bool _nationalDexUnlocked;
+
+ [ObservableProperty]
+ private bool _nationalDexActive;
+
+ [ObservableProperty]
+ private string _spindaPid = "00000000";
+
+ [ObservableProperty]
+ private int _countSeen;
+
+ [ObservableProperty]
+ private int _countObtained;
+
+ public SAVPokedexORASViewModel(SAV6AO sav) : base(sav)
+ {
+ _sav = (SAV6AO)(_origin = sav).Clone();
+ _zukan = _sav.Zukan;
+
+ for (int i = 1; i <= _sav.MaxSpeciesID; i++)
+ SpeciesNames.Add($"{i:000} - {GameInfo.Strings.specieslist[i]}");
+
+ NationalDexUnlocked = _zukan.IsNationalDexUnlocked;
+ NationalDexActive = _zukan.IsNationalDexMode;
+ SpindaPid = _zukan.Spinda.ToString("X8");
+
+ SelectedSpeciesIndex = 0;
+ }
+
+ partial void OnSelectedSpeciesIndexChanged(int value)
+ {
+ if (value < 0 || _editing)
+ return;
+ SaveEntry();
+ _editing = true;
+ _species = (ushort)(value + 1);
+ LoadEntry();
+ _editing = false;
+ }
+
+ private void LoadEntry()
+ {
+ Caught = _zukan.GetCaught(_species);
+ SeenMale = _zukan.GetSeen(_species, 0);
+ SeenFemale = _zukan.GetSeen(_species, 1);
+ SeenMaleShiny = _zukan.GetSeen(_species, 2);
+ SeenFemaleShiny = _zukan.GetSeen(_species, 3);
+ DisplayedMale = _zukan.GetDisplayed(_species, 0);
+ DisplayedFemale = _zukan.GetDisplayed(_species, 1);
+ DisplayedMaleShiny = _zukan.GetDisplayed(_species, 2);
+ DisplayedFemaleShiny = _zukan.GetDisplayed(_species, 3);
+ LangJPN = _zukan.GetLanguageFlag(_species, 0);
+ LangENG = _zukan.GetLanguageFlag(_species, 1);
+ LangFRE = _zukan.GetLanguageFlag(_species, 2);
+ LangITA = _zukan.GetLanguageFlag(_species, 3);
+ LangGER = _zukan.GetLanguageFlag(_species, 4);
+ LangSPA = _zukan.GetLanguageFlag(_species, 5);
+ LangKOR = _zukan.GetLanguageFlag(_species, 6);
+ CountSeen = _zukan.GetCountSeen(_species);
+ CountObtained = _zukan.GetCountObtained(_species);
+ }
+
+ private void SaveEntry()
+ {
+ if (_species is 0 or > 721)
+ return;
+
+ _zukan.SetCaught(_species, Caught);
+ _zukan.SetSeen(_species, 0, SeenMale);
+ _zukan.SetSeen(_species, 1, SeenFemale);
+ _zukan.SetSeen(_species, 2, SeenMaleShiny);
+ _zukan.SetSeen(_species, 3, SeenFemaleShiny);
+ _zukan.SetDisplayed(_species, 0, DisplayedMale);
+ _zukan.SetDisplayed(_species, 1, DisplayedFemale);
+ _zukan.SetDisplayed(_species, 2, DisplayedMaleShiny);
+ _zukan.SetDisplayed(_species, 3, DisplayedFemaleShiny);
+ _zukan.SetLanguageFlag(_species, 0, LangJPN);
+ _zukan.SetLanguageFlag(_species, 1, LangENG);
+ _zukan.SetLanguageFlag(_species, 2, LangFRE);
+ _zukan.SetLanguageFlag(_species, 3, LangITA);
+ _zukan.SetLanguageFlag(_species, 4, LangGER);
+ _zukan.SetLanguageFlag(_species, 5, LangSPA);
+ _zukan.SetLanguageFlag(_species, 6, LangKOR);
+ _zukan.SetCountSeen(_species, (ushort)Math.Clamp(CountSeen, 0, ushort.MaxValue));
+ _zukan.SetCountObtained(_species, (ushort)Math.Clamp(CountObtained, 0, ushort.MaxValue));
+ }
+
+ [RelayCommand]
+ private void SeenAll()
+ {
+ SaveEntry();
+ _zukan.SeenAll(shinyToo: false);
+ LoadEntry();
+ }
+
+ [RelayCommand]
+ private void SeenNone()
+ {
+ SaveEntry();
+ _zukan.SeenNone();
+ LoadEntry();
+ }
+
+ [RelayCommand]
+ private void CaughtAll()
+ {
+ SaveEntry();
+ var language = (LanguageID)_sav.Language;
+ _zukan.CaughtAll(language, allLanguages: false);
+ LoadEntry();
+ }
+
+ [RelayCommand]
+ private void CaughtNone()
+ {
+ SaveEntry();
+ _zukan.CaughtNone();
+ LoadEntry();
+ }
+
+ [RelayCommand]
+ private void Complete()
+ {
+ SaveEntry();
+ var language = (LanguageID)_sav.Language;
+ _zukan.SeenAll(shinyToo: false);
+ _zukan.CaughtAll(language, allLanguages: false);
+ LoadEntry();
+ }
+
+ [RelayCommand]
+ private void MaxDexNav()
+ {
+ for (ushort i = 0; i < _sav.MaxSpeciesID; i++)
+ _zukan.SetCountSeen(i, 999);
+ LoadEntry();
+ }
+
+ [RelayCommand]
+ private void ResetDexNav()
+ {
+ for (ushort i = 0; i < _sav.MaxSpeciesID; i++)
+ _zukan.SetCountSeen(i, 0);
+ LoadEntry();
+ }
+
+ [RelayCommand]
+ private void Save()
+ {
+ SaveEntry();
+ _zukan.IsNationalDexUnlocked = NationalDexUnlocked;
+ _zukan.IsNationalDexMode = NationalDexActive;
+ _zukan.Spinda = Convert.ToUInt32(SpindaPid, 16);
+ if (_species is not 0)
+ _zukan.InitialSpecies = _species;
+ _origin.CopyChangesFrom(_sav);
+ Modified = true;
+ }
+}
diff --git a/PKHeX.Avalonia/ViewModels/Subforms/SAVPokedexXYViewModel.cs b/PKHeX.Avalonia/ViewModels/Subforms/SAVPokedexXYViewModel.cs
new file mode 100644
index 000000000..1aae6bde5
--- /dev/null
+++ b/PKHeX.Avalonia/ViewModels/Subforms/SAVPokedexXYViewModel.cs
@@ -0,0 +1,213 @@
+using System;
+using System.Collections.Generic;
+using System.Collections.ObjectModel;
+using System.Linq;
+using CommunityToolkit.Mvvm.ComponentModel;
+using CommunityToolkit.Mvvm.Input;
+using PKHeX.Core;
+
+namespace PKHeX.Avalonia.ViewModels.Subforms;
+
+///
+/// ViewModel for the Gen 6 XY Pokedex editor.
+/// Edits seen/caught/language flags per species.
+///
+public partial class SAVPokedexXYViewModel : SaveEditorViewModelBase
+{
+ private readonly SaveFile _origin;
+ private readonly SAV6XY _sav;
+ private readonly Zukan6XY _zukan;
+ private bool _editing;
+ private ushort _species = ushort.MaxValue;
+
+ public ObservableCollection SpeciesNames { get; } = [];
+
+ [ObservableProperty]
+ private int _selectedSpeciesIndex = -1;
+
+ // Caught
+ [ObservableProperty]
+ private bool _caught;
+
+ // Seen M/F/MS/FS
+ [ObservableProperty]
+ private bool _seenMale;
+
+ [ObservableProperty]
+ private bool _seenFemale;
+
+ [ObservableProperty]
+ private bool _seenMaleShiny;
+
+ [ObservableProperty]
+ private bool _seenFemaleShiny;
+
+ // Displayed M/F/MS/FS
+ [ObservableProperty]
+ private bool _displayedMale;
+
+ [ObservableProperty]
+ private bool _displayedFemale;
+
+ [ObservableProperty]
+ private bool _displayedMaleShiny;
+
+ [ObservableProperty]
+ private bool _displayedFemaleShiny;
+
+ // Language flags
+ [ObservableProperty]
+ private bool _langJPN;
+
+ [ObservableProperty]
+ private bool _langENG;
+
+ [ObservableProperty]
+ private bool _langFRE;
+
+ [ObservableProperty]
+ private bool _langITA;
+
+ [ObservableProperty]
+ private bool _langGER;
+
+ [ObservableProperty]
+ private bool _langSPA;
+
+ [ObservableProperty]
+ private bool _langKOR;
+
+ [ObservableProperty]
+ private bool _nationalDexUnlocked;
+
+ [ObservableProperty]
+ private bool _nationalDexActive;
+
+ [ObservableProperty]
+ private string _spindaPid = "00000000";
+
+ public SAVPokedexXYViewModel(SAV6XY sav) : base(sav)
+ {
+ _sav = (SAV6XY)(_origin = sav).Clone();
+ _zukan = _sav.Zukan;
+
+ for (int i = 1; i <= _sav.MaxSpeciesID; i++)
+ SpeciesNames.Add($"{i:000} - {GameInfo.Strings.specieslist[i]}");
+
+ NationalDexUnlocked = _zukan.IsNationalDexUnlocked;
+ NationalDexActive = _zukan.IsNationalDexMode;
+ SpindaPid = _zukan.Spinda.ToString("X8");
+
+ SelectedSpeciesIndex = 0;
+ }
+
+ partial void OnSelectedSpeciesIndexChanged(int value)
+ {
+ if (value < 0 || _editing)
+ return;
+ SaveEntry();
+ _editing = true;
+ _species = (ushort)(value + 1);
+ LoadEntry();
+ _editing = false;
+ }
+
+ private void LoadEntry()
+ {
+ Caught = _zukan.GetCaught(_species);
+ SeenMale = _zukan.GetSeen(_species, 0);
+ SeenFemale = _zukan.GetSeen(_species, 1);
+ SeenMaleShiny = _zukan.GetSeen(_species, 2);
+ SeenFemaleShiny = _zukan.GetSeen(_species, 3);
+ DisplayedMale = _zukan.GetDisplayed(_species, 0);
+ DisplayedFemale = _zukan.GetDisplayed(_species, 1);
+ DisplayedMaleShiny = _zukan.GetDisplayed(_species, 2);
+ DisplayedFemaleShiny = _zukan.GetDisplayed(_species, 3);
+ LangJPN = _zukan.GetLanguageFlag(_species, 0);
+ LangENG = _zukan.GetLanguageFlag(_species, 1);
+ LangFRE = _zukan.GetLanguageFlag(_species, 2);
+ LangITA = _zukan.GetLanguageFlag(_species, 3);
+ LangGER = _zukan.GetLanguageFlag(_species, 4);
+ LangSPA = _zukan.GetLanguageFlag(_species, 5);
+ LangKOR = _zukan.GetLanguageFlag(_species, 6);
+ }
+
+ private void SaveEntry()
+ {
+ if (_species is 0 or > 721)
+ return;
+
+ _zukan.SetCaught(_species, Caught);
+ _zukan.SetSeen(_species, 0, SeenMale);
+ _zukan.SetSeen(_species, 1, SeenFemale);
+ _zukan.SetSeen(_species, 2, SeenMaleShiny);
+ _zukan.SetSeen(_species, 3, SeenFemaleShiny);
+ _zukan.SetDisplayed(_species, 0, DisplayedMale);
+ _zukan.SetDisplayed(_species, 1, DisplayedFemale);
+ _zukan.SetDisplayed(_species, 2, DisplayedMaleShiny);
+ _zukan.SetDisplayed(_species, 3, DisplayedFemaleShiny);
+ _zukan.SetLanguageFlag(_species, 0, LangJPN);
+ _zukan.SetLanguageFlag(_species, 1, LangENG);
+ _zukan.SetLanguageFlag(_species, 2, LangFRE);
+ _zukan.SetLanguageFlag(_species, 3, LangITA);
+ _zukan.SetLanguageFlag(_species, 4, LangGER);
+ _zukan.SetLanguageFlag(_species, 5, LangSPA);
+ _zukan.SetLanguageFlag(_species, 6, LangKOR);
+ }
+
+ [RelayCommand]
+ private void SeenAll()
+ {
+ SaveEntry();
+ _zukan.SeenAll(shinyToo: false);
+ LoadEntry();
+ }
+
+ [RelayCommand]
+ private void SeenNone()
+ {
+ SaveEntry();
+ _zukan.SeenNone();
+ LoadEntry();
+ }
+
+ [RelayCommand]
+ private void CaughtAll()
+ {
+ SaveEntry();
+ var language = (LanguageID)_sav.Language;
+ _zukan.CaughtAll(language, allLanguages: false);
+ LoadEntry();
+ }
+
+ [RelayCommand]
+ private void CaughtNone()
+ {
+ SaveEntry();
+ _zukan.CaughtNone();
+ LoadEntry();
+ }
+
+ [RelayCommand]
+ private void Complete()
+ {
+ SaveEntry();
+ var language = (LanguageID)_sav.Language;
+ _zukan.SeenAll(shinyToo: false);
+ _zukan.CaughtAll(language, allLanguages: false);
+ LoadEntry();
+ }
+
+ [RelayCommand]
+ private void Save()
+ {
+ SaveEntry();
+ _zukan.IsNationalDexUnlocked = NationalDexUnlocked;
+ _zukan.IsNationalDexMode = NationalDexActive;
+ _zukan.Spinda = Convert.ToUInt32(SpindaPid, 16);
+ if (_species is not 0)
+ _zukan.InitialSpecies = _species;
+ _origin.CopyChangesFrom(_sav);
+ Modified = true;
+ }
+}
diff --git a/PKHeX.Avalonia/ViewModels/Subforms/SAVPokepuff6ViewModel.cs b/PKHeX.Avalonia/ViewModels/Subforms/SAVPokepuff6ViewModel.cs
new file mode 100644
index 000000000..f39d3b186
--- /dev/null
+++ b/PKHeX.Avalonia/ViewModels/Subforms/SAVPokepuff6ViewModel.cs
@@ -0,0 +1,113 @@
+using System;
+using System.Collections.Generic;
+using System.Collections.ObjectModel;
+using System.Linq;
+using CommunityToolkit.Mvvm.ComponentModel;
+using CommunityToolkit.Mvvm.Input;
+using PKHeX.Core;
+
+namespace PKHeX.Avalonia.ViewModels.Subforms;
+
+///
+/// Model for a single Pokepuff slot.
+///
+public partial class PokepuffSlotModel : ObservableObject
+{
+ public int Index { get; }
+
+ [ObservableProperty]
+ private int _selectedPuffIndex;
+
+ public string DisplayName => $"Slot {Index + 1}";
+
+ public PokepuffSlotModel(int index, int puffIndex)
+ {
+ Index = index;
+ _selectedPuffIndex = puffIndex;
+ }
+}
+
+///
+/// ViewModel for the Gen 6 Pokepuff collection editor.
+///
+public partial class SAVPokepuff6ViewModel : SaveEditorViewModelBase
+{
+ private readonly ISaveBlock6Main _sav;
+
+ public ObservableCollection Slots { get; } = [];
+ public List PuffNames { get; }
+
+ public SAVPokepuff6ViewModel(ISaveBlock6Main sav) : base((SaveFile)sav)
+ {
+ _sav = sav;
+ PuffNames = [.. GameInfo.Strings.puffs];
+
+ LoadPuffs();
+ }
+
+ private void LoadPuffs()
+ {
+ Slots.Clear();
+ var puffs = _sav.Puff.GetPuffs();
+ for (int i = 0; i < puffs.Length; i++)
+ {
+ int puffVal = puffs[i];
+ if (puffVal >= PuffNames.Count)
+ puffVal = 0;
+ Slots.Add(new PokepuffSlotModel(i, puffVal));
+ }
+ }
+
+ [RelayCommand]
+ private void GiveAll()
+ {
+ _sav.Puff.MaxCheat(false);
+ LoadPuffs();
+ }
+
+ [RelayCommand]
+ private void GiveBest()
+ {
+ _sav.Puff.MaxCheat(true);
+ LoadPuffs();
+ }
+
+ [RelayCommand]
+ private void ClearAll()
+ {
+ _sav.Puff.Reset();
+ LoadPuffs();
+ }
+
+ [RelayCommand]
+ private void Sort()
+ {
+ SavePuffs();
+ _sav.Puff.Sort(false);
+ LoadPuffs();
+ }
+
+ [RelayCommand]
+ private void SortReverse()
+ {
+ SavePuffs();
+ _sav.Puff.Sort(true);
+ LoadPuffs();
+ }
+
+ private void SavePuffs()
+ {
+ var puffs = new byte[Slots.Count];
+ for (int i = 0; i < Slots.Count; i++)
+ puffs[i] = (byte)Slots[i].SelectedPuffIndex;
+ _sav.Puff.SetPuffs(puffs);
+ _sav.Puff.PuffCount = puffs.Length;
+ }
+
+ [RelayCommand]
+ private void Save()
+ {
+ SavePuffs();
+ Modified = true;
+ }
+}
diff --git a/PKHeX.Avalonia/ViewModels/Subforms/SAVRoamer6ViewModel.cs b/PKHeX.Avalonia/ViewModels/Subforms/SAVRoamer6ViewModel.cs
new file mode 100644
index 000000000..90c0da771
--- /dev/null
+++ b/PKHeX.Avalonia/ViewModels/Subforms/SAVRoamer6ViewModel.cs
@@ -0,0 +1,68 @@
+using System.Collections.Generic;
+using System.Linq;
+using CommunityToolkit.Mvvm.ComponentModel;
+using CommunityToolkit.Mvvm.Input;
+using PKHeX.Core;
+
+namespace PKHeX.Avalonia.ViewModels.Subforms;
+
+///
+/// ViewModel for the Gen 6 Roaming Pokemon editor.
+/// Edits species, roam state, and times encountered.
+///
+public partial class SAVRoamer6ViewModel : SaveEditorViewModelBase
+{
+ private readonly SAV6XY _origin;
+ private readonly SAV6XY _sav;
+ private readonly Roamer6 _roamer;
+
+ public List SpeciesChoices { get; }
+ public List RoamStateChoices { get; } = ["Inactive", "Roaming", "Stationary", "Defeated", "Captured"];
+
+ [ObservableProperty]
+ private int _selectedSpeciesIndex;
+
+ [ObservableProperty]
+ private int _selectedRoamStateIndex;
+
+ [ObservableProperty]
+ private uint _timesEncountered;
+
+ public SAVRoamer6ViewModel(SAV6XY sav) : base(sav)
+ {
+ _sav = (SAV6XY)(_origin = sav).Clone();
+ _roamer = _sav.Encount.Roamer;
+
+ var species = GameInfo.Strings.specieslist;
+ SpeciesChoices =
+ [
+ species[(int)Species.Articuno],
+ species[(int)Species.Zapdos],
+ species[(int)Species.Moltres],
+ ];
+
+ SelectedSpeciesIndex = GetInitialIndex();
+ TimesEncountered = _roamer.TimesEncountered;
+ SelectedRoamStateIndex = (int)_roamer.RoamStatus;
+ }
+
+ private int GetInitialIndex()
+ {
+ const int speciesOffset = 144;
+ const int starterChoiceIndex = 48;
+ if (_roamer.Species != 0)
+ return _roamer.Species - speciesOffset;
+ return _sav.EventWork.GetWork(starterChoiceIndex);
+ }
+
+ [RelayCommand]
+ private void Save()
+ {
+ const int speciesOffset = 144;
+ _roamer.Species = (ushort)(speciesOffset + SelectedSpeciesIndex);
+ _roamer.TimesEncountered = TimesEncountered;
+ _roamer.RoamStatus = (Roamer6State)SelectedRoamStateIndex;
+ _origin.CopyChangesFrom(_sav);
+ Modified = true;
+ }
+}
diff --git a/PKHeX.Avalonia/ViewModels/Subforms/SAVSecretBase6ViewModel.cs b/PKHeX.Avalonia/ViewModels/Subforms/SAVSecretBase6ViewModel.cs
new file mode 100644
index 000000000..5a14b13fb
--- /dev/null
+++ b/PKHeX.Avalonia/ViewModels/Subforms/SAVSecretBase6ViewModel.cs
@@ -0,0 +1,182 @@
+using System.Collections.ObjectModel;
+using CommunityToolkit.Mvvm.ComponentModel;
+using CommunityToolkit.Mvvm.Input;
+using PKHeX.Core;
+
+namespace PKHeX.Avalonia.ViewModels.Subforms;
+
+///
+/// ViewModel for the Gen 6 ORAS Secret Base editor.
+/// Edits base list, decorations, trainer info.
+///
+public partial class SAVSecretBase6ViewModel : SaveEditorViewModelBase
+{
+ private readonly SaveFile _origin;
+ private readonly SAV6AO _sav;
+ private bool _loading;
+
+ public ObservableCollection BaseNames { get; } = [];
+
+ [ObservableProperty]
+ private int _selectedBaseIndex = -1;
+
+ // Base properties (displayed via PropertyGrid-like fields)
+ [ObservableProperty]
+ private string _trainerName = string.Empty;
+
+ [ObservableProperty]
+ private int _baseLocation;
+
+ [ObservableProperty]
+ private string _teamName = string.Empty;
+
+ [ObservableProperty]
+ private string _teamSlogan = string.Empty;
+
+ // Decoration placement
+ [ObservableProperty]
+ private int _placementIndex;
+
+ [ObservableProperty]
+ private int _placementGood;
+
+ [ObservableProperty]
+ private int _placementX;
+
+ [ObservableProperty]
+ private int _placementY;
+
+ [ObservableProperty]
+ private int _placementRotation;
+
+ [ObservableProperty]
+ private uint _capturedRecord;
+
+ private SecretBase6? _currentBase;
+ private int _currentPlacementIndex = -1;
+
+ public SAVSecretBase6ViewModel(SAV6AO sav) : base(sav)
+ {
+ _sav = (SAV6AO)(_origin = sav).Clone();
+
+ CapturedRecord = (uint)_sav.Records.GetRecord(080);
+ ReloadBaseList();
+
+ if (BaseNames.Count > 0)
+ SelectedBaseIndex = 0;
+ }
+
+ private void ReloadBaseList()
+ {
+ _loading = true;
+ BaseNames.Clear();
+ var block = _sav.SecretBase;
+ var self = block.GetSecretBaseSelf();
+ BaseNames.Add($"* {self.TrainerName}");
+ for (int i = 0; i < SecretBase6Block.OtherSecretBaseCount; i++)
+ {
+ var other = block.GetSecretBaseOther(i);
+ string name = other.TrainerName;
+ if (string.IsNullOrWhiteSpace(name))
+ name = "Empty";
+ BaseNames.Add($"{i + 1:00} {name}");
+ }
+ _loading = false;
+ }
+
+ partial void OnSelectedBaseIndexChanged(int value)
+ {
+ if (value < 0 || _loading)
+ return;
+ SaveCurrentBase();
+ LoadBase(value);
+ }
+
+ partial void OnPlacementIndexChanged(int value)
+ {
+ if (_currentBase == null || _loading)
+ return;
+ SavePlacement();
+ LoadPlacement(value);
+ }
+
+ private void LoadBase(int index)
+ {
+ _loading = true;
+ _currentPlacementIndex = -1;
+ _currentBase = index == 0
+ ? _sav.SecretBase.GetSecretBaseSelf()
+ : _sav.SecretBase.GetSecretBaseOther(index - 1);
+
+ TrainerName = _currentBase.TrainerName;
+ BaseLocation = _currentBase.BaseLocation;
+ TeamName = _currentBase.TeamName;
+ TeamSlogan = _currentBase.TeamSlogan;
+
+ PlacementIndex = 0;
+ LoadPlacement(0);
+ _loading = false;
+ }
+
+ private void LoadPlacement(int index)
+ {
+ if (_currentBase == null || index < 0 || index >= SecretBase6.COUNT_GOODS)
+ return;
+ _currentPlacementIndex = index;
+ var p = _currentBase.GetPlacement(index);
+ PlacementGood = p.Good;
+ PlacementX = p.X;
+ PlacementY = p.Y;
+ PlacementRotation = p.Rotation;
+ }
+
+ private void SavePlacement()
+ {
+ if (_currentBase == null || _currentPlacementIndex < 0)
+ return;
+ var p = _currentBase.GetPlacement(_currentPlacementIndex);
+ p.Good = (ushort)PlacementGood;
+ p.X = (ushort)PlacementX;
+ p.Y = (ushort)PlacementY;
+ p.Rotation = (byte)PlacementRotation;
+ }
+
+ private void SaveCurrentBase()
+ {
+ if (_currentBase == null)
+ return;
+ SavePlacement();
+ _currentBase.TrainerName = TrainerName;
+ _currentBase.BaseLocation = BaseLocation;
+ _currentBase.TeamName = TeamName;
+ _currentBase.TeamSlogan = TeamSlogan;
+ }
+
+ [RelayCommand]
+ private void GiveAllDecor()
+ {
+ _sav.SecretBase.GiveAllGoods();
+ }
+
+ [RelayCommand]
+ private void DeleteBase()
+ {
+ if (SelectedBaseIndex < 1)
+ return;
+ int index = SelectedBaseIndex - 1;
+ _sav.SecretBase.DeleteOther(index);
+ _currentBase = null;
+ _currentPlacementIndex = -1;
+ ReloadBaseList();
+ SelectedBaseIndex = index + 1;
+ }
+
+ [RelayCommand]
+ private void Save()
+ {
+ SaveCurrentBase();
+ _sav.Records.SetRecord(080, (int)CapturedRecord);
+ _origin.CopyChangesFrom(_sav);
+ Modified = true;
+ }
+}
diff --git a/PKHeX.Avalonia/ViewModels/Subforms/SAVSuperTrain6ViewModel.cs b/PKHeX.Avalonia/ViewModels/Subforms/SAVSuperTrain6ViewModel.cs
new file mode 100644
index 000000000..b3b422c89
--- /dev/null
+++ b/PKHeX.Avalonia/ViewModels/Subforms/SAVSuperTrain6ViewModel.cs
@@ -0,0 +1,162 @@
+using System;
+using System.Collections.Generic;
+using System.Collections.ObjectModel;
+using System.Globalization;
+using System.Linq;
+using CommunityToolkit.Mvvm.ComponentModel;
+using CommunityToolkit.Mvvm.Input;
+using PKHeX.Core;
+
+namespace PKHeX.Avalonia.ViewModels.Subforms;
+
+///
+/// Model for a training bag slot.
+///
+public partial class TrainingBagSlotModel : ObservableObject
+{
+ public int Index { get; }
+
+ [ObservableProperty]
+ private int _selectedBagIndex;
+
+ public string DisplayName => $"Slot {Index + 1}";
+
+ public TrainingBagSlotModel(int index, int bagIndex)
+ {
+ Index = index;
+ _selectedBagIndex = bagIndex;
+ }
+}
+
+///
+/// ViewModel for the Gen 6 Super Training editor.
+/// Edits training bags and regimen records.
+///
+public partial class SAVSuperTrain6ViewModel : SaveEditorViewModelBase
+{
+ private readonly SaveFile _origin;
+ private readonly SAV6 _sav;
+ private readonly SuperTrainBlock _stb;
+ private bool _loading;
+
+ public List StageNames { get; } = [];
+ public List BagNames { get; }
+ public List SpeciesList { get; }
+ public ObservableCollection BagSlots { get; } = [];
+
+ [ObservableProperty]
+ private int _selectedStageIndex = -1;
+
+ // Record holder 1
+ [ObservableProperty]
+ private int _species1;
+
+ [ObservableProperty]
+ private string _gender1 = "0";
+
+ [ObservableProperty]
+ private string _form1 = "0";
+
+ [ObservableProperty]
+ private string _time1 = "0";
+
+ // Record holder 2
+ [ObservableProperty]
+ private int _species2;
+
+ [ObservableProperty]
+ private string _gender2 = "0";
+
+ [ObservableProperty]
+ private string _form2 = "0";
+
+ [ObservableProperty]
+ private string _time2 = "0";
+
+ public SAVSuperTrain6ViewModel(SAV6 sav) : base(sav)
+ {
+ _sav = (SAV6)(_origin = sav).Clone();
+ _stb = ((ISaveBlock6Main)_sav).SuperTrain;
+
+ var bagNames = GameInfo.Strings.trainingbags.ToList();
+ if (bagNames.Count > 0)
+ bagNames[0] = "---";
+ BagNames = bagNames;
+
+ SpeciesList = GameInfo.FilteredSources.Species.ToList();
+
+ var stages = GameInfo.Strings.trainingstage;
+ for (int i = 0; i < 32; i++)
+ StageNames.Add($"{i + 1:00} - {stages[i]}");
+
+ // Load bags
+ for (int i = 0; i < 12; i++)
+ {
+ int bagId = _stb.GetBag(i);
+ BagSlots.Add(new TrainingBagSlotModel(i, bagId));
+ }
+
+ SelectedStageIndex = 0;
+ }
+
+ partial void OnSelectedStageIndexChanged(int value)
+ {
+ if (value < 0)
+ return;
+ LoadStageRecord(value);
+ }
+
+ private void LoadStageRecord(int index)
+ {
+ _loading = true;
+ var h1 = _stb.GetHolder1(index);
+ var h2 = _stb.GetHolder2(index);
+ Species1 = h1.Species;
+ Gender1 = h1.Gender.ToString();
+ Form1 = h1.Form.ToString();
+ Species2 = h2.Species;
+ Gender2 = h2.Gender.ToString();
+ Form2 = h2.Form.ToString();
+ Time1 = _stb.GetTime1(index).ToString(CultureInfo.InvariantCulture);
+ Time2 = _stb.GetTime2(index).ToString(CultureInfo.InvariantCulture);
+ _loading = false;
+ }
+
+ private void SaveStageRecord(int index)
+ {
+ if (index < 0)
+ return;
+ var h1 = _stb.GetHolder1(index);
+ h1.Species = (ushort)Species1;
+ if (byte.TryParse(Gender1, out var g1)) h1.Gender = g1;
+ if (byte.TryParse(Form1, out var f1)) h1.Form = f1;
+ var h2 = _stb.GetHolder2(index);
+ h2.Species = (ushort)Species2;
+ if (byte.TryParse(Gender2, out var g2)) h2.Gender = g2;
+ if (byte.TryParse(Form2, out var f2)) h2.Form = f2;
+ if (float.TryParse(Time1, out var t1)) _stb.SetTime1(index, t1);
+ if (float.TryParse(Time2, out var t2)) _stb.SetTime2(index, t2);
+ }
+
+ [RelayCommand]
+ private void Save()
+ {
+ SaveStageRecord(SelectedStageIndex);
+
+ // Save bags
+ int emptySlots = 0;
+ for (int i = 0; i < 12; i++)
+ {
+ int bagIndex = BagSlots[i].SelectedBagIndex;
+ if (bagIndex <= 0)
+ {
+ emptySlots++;
+ continue;
+ }
+ _stb.SetBag(i - emptySlots, (byte)bagIndex);
+ }
+
+ _origin.CopyChangesFrom(_sav);
+ Modified = true;
+ }
+}
diff --git a/PKHeX.Avalonia/ViewModels/Subforms/SAVTrainer6ViewModel.cs b/PKHeX.Avalonia/ViewModels/Subforms/SAVTrainer6ViewModel.cs
new file mode 100644
index 000000000..8f1cdbede
--- /dev/null
+++ b/PKHeX.Avalonia/ViewModels/Subforms/SAVTrainer6ViewModel.cs
@@ -0,0 +1,208 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using CommunityToolkit.Mvvm.ComponentModel;
+using CommunityToolkit.Mvvm.Input;
+using PKHeX.Core;
+
+namespace PKHeX.Avalonia.ViewModels.Subforms;
+
+///
+/// ViewModel for the Gen 6 trainer editor.
+/// Edits OT name, TID/SID, money, play time, badges, BP, pokemiles, maison records, etc.
+///
+public partial class SAVTrainer6ViewModel : SaveEditorViewModelBase
+{
+ private readonly SaveFile _origin;
+ private readonly SAV6 _sav;
+
+ public string[] GenderChoices { get; } = ["Male", "Female"];
+
+ [ObservableProperty]
+ private string _otName = string.Empty;
+
+ [ObservableProperty]
+ private string _tid = "00000";
+
+ [ObservableProperty]
+ private string _sid = "00000";
+
+ [ObservableProperty]
+ private string _money = "0";
+
+ [ObservableProperty]
+ private int _gender;
+
+ [ObservableProperty]
+ private int _playedHours;
+
+ [ObservableProperty]
+ private int _playedMinutes;
+
+ [ObservableProperty]
+ private int _playedSeconds;
+
+ [ObservableProperty]
+ private string _bp = "0";
+
+ [ObservableProperty]
+ private string _pokemiles = "0";
+
+ [ObservableProperty]
+ private string _style = "0";
+
+ [ObservableProperty]
+ private bool _megaUnlocked;
+
+ [ObservableProperty]
+ private bool _megaRayquazaUnlocked;
+
+ [ObservableProperty]
+ private bool _showStyle;
+
+ [ObservableProperty]
+ private bool _showMegaRayquaza;
+
+ // Badges
+ [ObservableProperty]
+ private bool _badge1;
+
+ [ObservableProperty]
+ private bool _badge2;
+
+ [ObservableProperty]
+ private bool _badge3;
+
+ [ObservableProperty]
+ private bool _badge4;
+
+ [ObservableProperty]
+ private bool _badge5;
+
+ [ObservableProperty]
+ private bool _badge6;
+
+ [ObservableProperty]
+ private bool _badge7;
+
+ [ObservableProperty]
+ private bool _badge8;
+
+ // Sayings
+ [ObservableProperty]
+ private string _saying1 = string.Empty;
+
+ [ObservableProperty]
+ private string _saying2 = string.Empty;
+
+ [ObservableProperty]
+ private string _saying3 = string.Empty;
+
+ [ObservableProperty]
+ private string _saying4 = string.Empty;
+
+ [ObservableProperty]
+ private string _saying5 = string.Empty;
+
+ public SAVTrainer6ViewModel(SAV6 sav) : base(sav)
+ {
+ _sav = (SAV6)(_origin = sav).Clone();
+
+ ShowStyle = _sav is SAV6XY;
+ ShowMegaRayquaza = _sav is SAV6AO;
+
+ LoadData();
+ }
+
+ private void LoadData()
+ {
+ OtName = _sav.OT;
+ Tid = _sav.TID16.ToString("00000");
+ Sid = _sav.SID16.ToString("00000");
+ Money = _sav.Money.ToString();
+ Gender = _sav.Gender;
+
+ PlayedHours = _sav.PlayedHours;
+ PlayedMinutes = _sav.PlayedMinutes;
+ PlayedSeconds = _sav.PlayedSeconds;
+
+ Bp = _sav.BP.ToString();
+ Pokemiles = _sav.GetRecord(63).ToString();
+
+ var sit = _sav.Situation;
+ Style = sit.Style.ToString();
+
+ int badgeval = _sav.Badges;
+ Badge1 = (badgeval & (1 << 0)) != 0;
+ Badge2 = (badgeval & (1 << 1)) != 0;
+ Badge3 = (badgeval & (1 << 2)) != 0;
+ Badge4 = (badgeval & (1 << 3)) != 0;
+ Badge5 = (badgeval & (1 << 4)) != 0;
+ Badge6 = (badgeval & (1 << 5)) != 0;
+ Badge7 = (badgeval & (1 << 6)) != 0;
+ Badge8 = (badgeval & (1 << 7)) != 0;
+
+ var status = _sav.Status;
+ Saying1 = status.Saying1;
+ Saying2 = status.Saying2;
+ Saying3 = status.Saying3;
+ Saying4 = status.Saying4;
+ Saying5 = status.Saying5;
+
+ MegaUnlocked = status.IsMegaEvolutionUnlocked;
+ MegaRayquazaUnlocked = status.IsMegaRayquazaUnlocked;
+ }
+
+ [RelayCommand]
+ private void MaxCash()
+ {
+ Money = "9999999";
+ }
+
+ [RelayCommand]
+ private void Save()
+ {
+ _sav.OT = OtName;
+ _sav.TID16 = (ushort)(uint.TryParse(Tid, out var tid) ? tid : 0u);
+ _sav.SID16 = (ushort)(uint.TryParse(Sid, out var sid) ? sid : 0u);
+ _sav.Money = uint.TryParse(Money, out var money) ? money : 0u;
+ _sav.Gender = (byte)Gender;
+ _sav.Overworld.ResetPlayerModel();
+
+ _sav.PlayedHours = (ushort)PlayedHours;
+ _sav.PlayedMinutes = (ushort)(PlayedMinutes % 60);
+ _sav.PlayedSeconds = (ushort)(PlayedSeconds % 60);
+
+ _sav.BP = ushort.TryParse(Bp, out var bp) ? bp : (ushort)0;
+ _sav.SetRecord(63, int.TryParse(Pokemiles, out var pm1) ? pm1 : 0);
+ _sav.SetRecord(64, int.TryParse(Pokemiles, out var pm2) ? pm2 : 0);
+
+ var sit = _sav.Situation;
+ if (byte.TryParse(Style, out var style))
+ sit.Style = style;
+
+ int badgeval = 0;
+ if (Badge1) badgeval |= 1 << 0;
+ if (Badge2) badgeval |= 1 << 1;
+ if (Badge3) badgeval |= 1 << 2;
+ if (Badge4) badgeval |= 1 << 3;
+ if (Badge5) badgeval |= 1 << 4;
+ if (Badge6) badgeval |= 1 << 5;
+ if (Badge7) badgeval |= 1 << 6;
+ if (Badge8) badgeval |= 1 << 7;
+ _sav.Badges = badgeval;
+
+ var status = _sav.Status;
+ status.Saying1 = Saying1;
+ status.Saying2 = Saying2;
+ status.Saying3 = Saying3;
+ status.Saying4 = Saying4;
+ status.Saying5 = Saying5;
+
+ status.IsMegaEvolutionUnlocked = MegaUnlocked;
+ status.IsMegaRayquazaUnlocked = MegaRayquazaUnlocked;
+
+ _origin.CopyChangesFrom(_sav);
+ Modified = true;
+ }
+}
diff --git a/PKHeX.Avalonia/ViewModels/Subforms/UnityTower5ViewModel.cs b/PKHeX.Avalonia/ViewModels/Subforms/UnityTower5ViewModel.cs
new file mode 100644
index 000000000..d27d92302
--- /dev/null
+++ b/PKHeX.Avalonia/ViewModels/Subforms/UnityTower5ViewModel.cs
@@ -0,0 +1,166 @@
+using System.Collections.ObjectModel;
+using CommunityToolkit.Mvvm.ComponentModel;
+using CommunityToolkit.Mvvm.Input;
+using PKHeX.Core;
+
+namespace PKHeX.Avalonia.ViewModels.Subforms;
+
+///
+/// Model for a Geonet location row (Gen 5).
+///
+public partial class GeonetEntry5Model : ObservableObject
+{
+ public int Country { get; }
+ public string CountryName { get; }
+ public int Subregion { get; }
+ public string SubregionName { get; }
+
+ [ObservableProperty]
+ private int _point;
+
+ public GeonetEntry5Model(int country, string countryName, int subregion, string subregionName, int point)
+ {
+ Country = country;
+ CountryName = countryName;
+ Subregion = subregion;
+ SubregionName = subregionName;
+ _point = point;
+ }
+}
+
+///
+/// Model for a Unity Tower floor entry.
+///
+public partial class UnityTowerFloorModel : ObservableObject
+{
+ public int Country { get; }
+ public string CountryName { get; }
+
+ [ObservableProperty]
+ private bool _unlocked;
+
+ public UnityTowerFloorModel(int country, string countryName, bool unlocked)
+ {
+ Country = country;
+ CountryName = countryName;
+ _unlocked = unlocked;
+ }
+}
+
+///
+/// ViewModel for the Unity Tower / Geonet editor (Gen 5).
+/// Edits Geonet globe data and Unity Tower floor unlock status.
+///
+public partial class UnityTower5ViewModel : SaveEditorViewModelBase
+{
+ private readonly SAV5 SAV5;
+ private readonly UnityTower5 Tower;
+
+ [ObservableProperty] private bool _globalFlag;
+ [ObservableProperty] private bool _unityTowerFlag;
+
+ public ObservableCollection GeonetEntries { get; } = [];
+ public ObservableCollection FloorEntries { get; } = [];
+
+ public string[] PointNames { get; } = ["None", "Blue", "Yellow", "Red"];
+
+ public UnityTower5ViewModel(SAV5 sav) : base(sav)
+ {
+ SAV5 = sav;
+ Tower = sav.UnityTower;
+
+ _globalFlag = Tower.GlobalFlag;
+ _unityTowerFlag = Tower.UnityTowerFlag;
+
+ LoadGeonet();
+ LoadFloors();
+ }
+
+ private void LoadGeonet()
+ {
+ GeonetEntries.Clear();
+ for (int i = 1; i <= UnityTower5.CountryCount; i++)
+ {
+ var country = i;
+ var countryName = $"Country {country}";
+ var subregionCount = UnityTower5.GetSubregionCount((byte)country);
+
+ if (subregionCount == 0)
+ {
+ var point = (int)Tower.GetCountrySubregion((byte)country, 0);
+ GeonetEntries.Add(new GeonetEntry5Model(country, countryName, 0, "Default", point));
+ }
+ else
+ {
+ for (int j = 1; j <= subregionCount; j++)
+ {
+ var point = (int)Tower.GetCountrySubregion((byte)country, (byte)j);
+ GeonetEntries.Add(new GeonetEntry5Model(country, countryName, j, $"Region {j}", point));
+ }
+ }
+ }
+ }
+
+ private void LoadFloors()
+ {
+ FloorEntries.Clear();
+ for (int i = 1; i <= UnityTower5.CountryCount; i++)
+ {
+ var countryName = $"Country {i}";
+ var unlocked = Tower.GetUnityTowerFloor((byte)i);
+ FloorEntries.Add(new UnityTowerFloorModel(i, countryName, unlocked));
+ }
+ }
+
+ [RelayCommand]
+ private void SetAllLocations()
+ {
+ Tower.SetAll();
+ GlobalFlag = Tower.GlobalFlag;
+ UnityTowerFlag = Tower.UnityTowerFlag;
+ LoadGeonet();
+ LoadFloors();
+ }
+
+ [RelayCommand]
+ private void SetAllLegalLocations()
+ {
+ Tower.SetAllLegal();
+ GlobalFlag = Tower.GlobalFlag;
+ UnityTowerFlag = Tower.UnityTowerFlag;
+ LoadGeonet();
+ LoadFloors();
+ }
+
+ [RelayCommand]
+ private void ClearLocations()
+ {
+ Tower.ClearAll();
+ GlobalFlag = Tower.GlobalFlag;
+ UnityTowerFlag = Tower.UnityTowerFlag;
+ LoadGeonet();
+ LoadFloors();
+ }
+
+ [RelayCommand]
+ private void Save()
+ {
+ Tower.ClearAll();
+
+ foreach (var entry in GeonetEntries)
+ {
+ if (entry.Country > 0)
+ Tower.SetCountrySubregion((byte)entry.Country, (byte)entry.Subregion, (GeonetPoint)entry.Point);
+ }
+
+ foreach (var floor in FloorEntries)
+ Tower.SetUnityTowerFloor((byte)floor.Country, floor.Unlocked);
+
+ Tower.SetSAVCountry();
+ Tower.GlobalFlag = GlobalFlag;
+ Tower.UnityTowerFlag = UnityTowerFlag;
+
+ SAV.State.Edited = true;
+ Modified = true;
+ }
+}
diff --git a/PKHeX.Avalonia/Views/Subforms/CGearImage5View.axaml b/PKHeX.Avalonia/Views/Subforms/CGearImage5View.axaml
new file mode 100644
index 000000000..7677c0cd2
--- /dev/null
+++ b/PKHeX.Avalonia/Views/Subforms/CGearImage5View.axaml
@@ -0,0 +1,34 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/PKHeX.Avalonia/Views/Subforms/CGearImage5View.axaml.cs b/PKHeX.Avalonia/Views/Subforms/CGearImage5View.axaml.cs
new file mode 100644
index 000000000..16c7408f5
--- /dev/null
+++ b/PKHeX.Avalonia/Views/Subforms/CGearImage5View.axaml.cs
@@ -0,0 +1,16 @@
+using Avalonia.Interactivity;
+
+namespace PKHeX.Avalonia.Views.Subforms;
+
+public partial class CGearImage5View : SubformWindow
+{
+ public CGearImage5View()
+ {
+ InitializeComponent();
+ }
+
+ private void OnCloseClick(object? sender, RoutedEventArgs e)
+ {
+ CloseWithResult(false);
+ }
+}
diff --git a/PKHeX.Avalonia/Views/Subforms/DLC5View.axaml b/PKHeX.Avalonia/Views/Subforms/DLC5View.axaml
new file mode 100644
index 000000000..7d04e506a
--- /dev/null
+++ b/PKHeX.Avalonia/Views/Subforms/DLC5View.axaml
@@ -0,0 +1,94 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/PKHeX.Avalonia/Views/Subforms/DLC5View.axaml.cs b/PKHeX.Avalonia/Views/Subforms/DLC5View.axaml.cs
new file mode 100644
index 000000000..ff1899e34
--- /dev/null
+++ b/PKHeX.Avalonia/Views/Subforms/DLC5View.axaml.cs
@@ -0,0 +1,24 @@
+using Avalonia.Interactivity;
+using PKHeX.Avalonia.ViewModels.Subforms;
+
+namespace PKHeX.Avalonia.Views.Subforms;
+
+public partial class DLC5View : SubformWindow
+{
+ public DLC5View()
+ {
+ InitializeComponent();
+ }
+
+ private void OnOkClick(object? sender, RoutedEventArgs e)
+ {
+ if (DataContext is DLC5ViewModel vm)
+ vm.SaveCommand.Execute(null);
+ CloseWithResult(true);
+ }
+
+ private void OnCancelClick(object? sender, RoutedEventArgs e)
+ {
+ CloseWithResult(false);
+ }
+}
diff --git a/PKHeX.Avalonia/Views/Subforms/Misc5View.axaml b/PKHeX.Avalonia/Views/Subforms/Misc5View.axaml
new file mode 100644
index 000000000..067ab5122
--- /dev/null
+++ b/PKHeX.Avalonia/Views/Subforms/Misc5View.axaml
@@ -0,0 +1,181 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/PKHeX.Avalonia/Views/Subforms/Misc5View.axaml.cs b/PKHeX.Avalonia/Views/Subforms/Misc5View.axaml.cs
new file mode 100644
index 000000000..28a431b2d
--- /dev/null
+++ b/PKHeX.Avalonia/Views/Subforms/Misc5View.axaml.cs
@@ -0,0 +1,24 @@
+using Avalonia.Interactivity;
+using PKHeX.Avalonia.ViewModels.Subforms;
+
+namespace PKHeX.Avalonia.Views.Subforms;
+
+public partial class Misc5View : SubformWindow
+{
+ public Misc5View()
+ {
+ InitializeComponent();
+ }
+
+ private void OnOkClick(object? sender, RoutedEventArgs e)
+ {
+ if (DataContext is Misc5ViewModel vm)
+ vm.SaveCommand.Execute(null);
+ CloseWithResult(true);
+ }
+
+ private void OnCancelClick(object? sender, RoutedEventArgs e)
+ {
+ CloseWithResult(false);
+ }
+}
diff --git a/PKHeX.Avalonia/Views/Subforms/Pokedex5View.axaml b/PKHeX.Avalonia/Views/Subforms/Pokedex5View.axaml
new file mode 100644
index 000000000..2230ae096
--- /dev/null
+++ b/PKHeX.Avalonia/Views/Subforms/Pokedex5View.axaml
@@ -0,0 +1,60 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/PKHeX.Avalonia/Views/Subforms/Pokedex5View.axaml.cs b/PKHeX.Avalonia/Views/Subforms/Pokedex5View.axaml.cs
new file mode 100644
index 000000000..4fe68a8be
--- /dev/null
+++ b/PKHeX.Avalonia/Views/Subforms/Pokedex5View.axaml.cs
@@ -0,0 +1,24 @@
+using Avalonia.Interactivity;
+using PKHeX.Avalonia.ViewModels.Subforms;
+
+namespace PKHeX.Avalonia.Views.Subforms;
+
+public partial class Pokedex5View : SubformWindow
+{
+ public Pokedex5View()
+ {
+ InitializeComponent();
+ }
+
+ private void OnOkClick(object? sender, RoutedEventArgs e)
+ {
+ if (DataContext is Pokedex5ViewModel vm)
+ vm.SaveCommand.Execute(null);
+ CloseWithResult(true);
+ }
+
+ private void OnCancelClick(object? sender, RoutedEventArgs e)
+ {
+ CloseWithResult(false);
+ }
+}
diff --git a/PKHeX.Avalonia/Views/Subforms/SAVBerryFieldXYView.axaml b/PKHeX.Avalonia/Views/Subforms/SAVBerryFieldXYView.axaml
new file mode 100644
index 000000000..e502dd947
--- /dev/null
+++ b/PKHeX.Avalonia/Views/Subforms/SAVBerryFieldXYView.axaml
@@ -0,0 +1,77 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/PKHeX.Avalonia/Views/Subforms/SAVBerryFieldXYView.axaml.cs b/PKHeX.Avalonia/Views/Subforms/SAVBerryFieldXYView.axaml.cs
new file mode 100644
index 000000000..9dbd09070
--- /dev/null
+++ b/PKHeX.Avalonia/Views/Subforms/SAVBerryFieldXYView.axaml.cs
@@ -0,0 +1,16 @@
+using Avalonia.Interactivity;
+
+namespace PKHeX.Avalonia.Views.Subforms;
+
+public partial class SAVBerryFieldXYView : SubformWindow
+{
+ public SAVBerryFieldXYView()
+ {
+ InitializeComponent();
+ }
+
+ private void OnCancelClick(object? sender, RoutedEventArgs e)
+ {
+ CloseWithResult(false);
+ }
+}
diff --git a/PKHeX.Avalonia/Views/Subforms/SAVHallOfFame6View.axaml b/PKHeX.Avalonia/Views/Subforms/SAVHallOfFame6View.axaml
new file mode 100644
index 000000000..d7fbde284
--- /dev/null
+++ b/PKHeX.Avalonia/Views/Subforms/SAVHallOfFame6View.axaml
@@ -0,0 +1,128 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/PKHeX.Avalonia/Views/Subforms/SAVHallOfFame6View.axaml.cs b/PKHeX.Avalonia/Views/Subforms/SAVHallOfFame6View.axaml.cs
new file mode 100644
index 000000000..f5cbc6a7f
--- /dev/null
+++ b/PKHeX.Avalonia/Views/Subforms/SAVHallOfFame6View.axaml.cs
@@ -0,0 +1,24 @@
+using Avalonia.Interactivity;
+using PKHeX.Avalonia.ViewModels.Subforms;
+
+namespace PKHeX.Avalonia.Views.Subforms;
+
+public partial class SAVHallOfFame6View : SubformWindow
+{
+ public SAVHallOfFame6View()
+ {
+ InitializeComponent();
+ }
+
+ private void OnOkClick(object? sender, RoutedEventArgs e)
+ {
+ if (DataContext is SAVHallOfFame6ViewModel vm)
+ vm.SaveCommand.Execute(null);
+ CloseWithResult(true);
+ }
+
+ private void OnCancelClick(object? sender, RoutedEventArgs e)
+ {
+ CloseWithResult(false);
+ }
+}
diff --git a/PKHeX.Avalonia/Views/Subforms/SAVLink6View.axaml b/PKHeX.Avalonia/Views/Subforms/SAVLink6View.axaml
new file mode 100644
index 000000000..3d2837f08
--- /dev/null
+++ b/PKHeX.Avalonia/Views/Subforms/SAVLink6View.axaml
@@ -0,0 +1,74 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/PKHeX.Avalonia/Views/Subforms/SAVLink6View.axaml.cs b/PKHeX.Avalonia/Views/Subforms/SAVLink6View.axaml.cs
new file mode 100644
index 000000000..19f3b4231
--- /dev/null
+++ b/PKHeX.Avalonia/Views/Subforms/SAVLink6View.axaml.cs
@@ -0,0 +1,24 @@
+using Avalonia.Interactivity;
+using PKHeX.Avalonia.ViewModels.Subforms;
+
+namespace PKHeX.Avalonia.Views.Subforms;
+
+public partial class SAVLink6View : SubformWindow
+{
+ public SAVLink6View()
+ {
+ InitializeComponent();
+ }
+
+ private void OnOkClick(object? sender, RoutedEventArgs e)
+ {
+ if (DataContext is SAVLink6ViewModel vm)
+ vm.SaveCommand.Execute(null);
+ CloseWithResult(true);
+ }
+
+ private void OnCancelClick(object? sender, RoutedEventArgs e)
+ {
+ CloseWithResult(false);
+ }
+}
diff --git a/PKHeX.Avalonia/Views/Subforms/SAVOPower6View.axaml b/PKHeX.Avalonia/Views/Subforms/SAVOPower6View.axaml
new file mode 100644
index 000000000..92c4a4243
--- /dev/null
+++ b/PKHeX.Avalonia/Views/Subforms/SAVOPower6View.axaml
@@ -0,0 +1,79 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/PKHeX.Avalonia/Views/Subforms/SAVOPower6View.axaml.cs b/PKHeX.Avalonia/Views/Subforms/SAVOPower6View.axaml.cs
new file mode 100644
index 000000000..0cf2c599a
--- /dev/null
+++ b/PKHeX.Avalonia/Views/Subforms/SAVOPower6View.axaml.cs
@@ -0,0 +1,24 @@
+using Avalonia.Interactivity;
+using PKHeX.Avalonia.ViewModels.Subforms;
+
+namespace PKHeX.Avalonia.Views.Subforms;
+
+public partial class SAVOPower6View : SubformWindow
+{
+ public SAVOPower6View()
+ {
+ InitializeComponent();
+ }
+
+ private void OnOkClick(object? sender, RoutedEventArgs e)
+ {
+ if (DataContext is SAVOPower6ViewModel vm)
+ vm.SaveCommand.Execute(null);
+ CloseWithResult(true);
+ }
+
+ private void OnCancelClick(object? sender, RoutedEventArgs e)
+ {
+ CloseWithResult(false);
+ }
+}
diff --git a/PKHeX.Avalonia/Views/Subforms/SAVPokeBlockORASView.axaml b/PKHeX.Avalonia/Views/Subforms/SAVPokeBlockORASView.axaml
new file mode 100644
index 000000000..9f905e069
--- /dev/null
+++ b/PKHeX.Avalonia/Views/Subforms/SAVPokeBlockORASView.axaml
@@ -0,0 +1,39 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/PKHeX.Avalonia/Views/Subforms/SAVPokeBlockORASView.axaml.cs b/PKHeX.Avalonia/Views/Subforms/SAVPokeBlockORASView.axaml.cs
new file mode 100644
index 000000000..902973c97
--- /dev/null
+++ b/PKHeX.Avalonia/Views/Subforms/SAVPokeBlockORASView.axaml.cs
@@ -0,0 +1,24 @@
+using Avalonia.Interactivity;
+using PKHeX.Avalonia.ViewModels.Subforms;
+
+namespace PKHeX.Avalonia.Views.Subforms;
+
+public partial class SAVPokeBlockORASView : SubformWindow
+{
+ public SAVPokeBlockORASView()
+ {
+ InitializeComponent();
+ }
+
+ private void OnOkClick(object? sender, RoutedEventArgs e)
+ {
+ if (DataContext is SAVPokeBlockORASViewModel vm)
+ vm.SaveCommand.Execute(null);
+ CloseWithResult(true);
+ }
+
+ private void OnCancelClick(object? sender, RoutedEventArgs e)
+ {
+ CloseWithResult(false);
+ }
+}
diff --git a/PKHeX.Avalonia/Views/Subforms/SAVPokedexORASView.axaml b/PKHeX.Avalonia/Views/Subforms/SAVPokedexORASView.axaml
new file mode 100644
index 000000000..03bc3c13c
--- /dev/null
+++ b/PKHeX.Avalonia/Views/Subforms/SAVPokedexORASView.axaml
@@ -0,0 +1,93 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/PKHeX.Avalonia/Views/Subforms/SAVPokedexORASView.axaml.cs b/PKHeX.Avalonia/Views/Subforms/SAVPokedexORASView.axaml.cs
new file mode 100644
index 000000000..521111e38
--- /dev/null
+++ b/PKHeX.Avalonia/Views/Subforms/SAVPokedexORASView.axaml.cs
@@ -0,0 +1,24 @@
+using Avalonia.Interactivity;
+using PKHeX.Avalonia.ViewModels.Subforms;
+
+namespace PKHeX.Avalonia.Views.Subforms;
+
+public partial class SAVPokedexORASView : SubformWindow
+{
+ public SAVPokedexORASView()
+ {
+ InitializeComponent();
+ }
+
+ private void OnOkClick(object? sender, RoutedEventArgs e)
+ {
+ if (DataContext is SAVPokedexORASViewModel vm)
+ vm.SaveCommand.Execute(null);
+ CloseWithResult(true);
+ }
+
+ private void OnCancelClick(object? sender, RoutedEventArgs e)
+ {
+ CloseWithResult(false);
+ }
+}
diff --git a/PKHeX.Avalonia/Views/Subforms/SAVPokedexXYView.axaml b/PKHeX.Avalonia/Views/Subforms/SAVPokedexXYView.axaml
new file mode 100644
index 000000000..4fbbc6807
--- /dev/null
+++ b/PKHeX.Avalonia/Views/Subforms/SAVPokedexXYView.axaml
@@ -0,0 +1,75 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/PKHeX.Avalonia/Views/Subforms/SAVPokedexXYView.axaml.cs b/PKHeX.Avalonia/Views/Subforms/SAVPokedexXYView.axaml.cs
new file mode 100644
index 000000000..efa0f91b5
--- /dev/null
+++ b/PKHeX.Avalonia/Views/Subforms/SAVPokedexXYView.axaml.cs
@@ -0,0 +1,24 @@
+using Avalonia.Interactivity;
+using PKHeX.Avalonia.ViewModels.Subforms;
+
+namespace PKHeX.Avalonia.Views.Subforms;
+
+public partial class SAVPokedexXYView : SubformWindow
+{
+ public SAVPokedexXYView()
+ {
+ InitializeComponent();
+ }
+
+ private void OnOkClick(object? sender, RoutedEventArgs e)
+ {
+ if (DataContext is SAVPokedexXYViewModel vm)
+ vm.SaveCommand.Execute(null);
+ CloseWithResult(true);
+ }
+
+ private void OnCancelClick(object? sender, RoutedEventArgs e)
+ {
+ CloseWithResult(false);
+ }
+}
diff --git a/PKHeX.Avalonia/Views/Subforms/SAVPokepuff6View.axaml b/PKHeX.Avalonia/Views/Subforms/SAVPokepuff6View.axaml
new file mode 100644
index 000000000..03f240318
--- /dev/null
+++ b/PKHeX.Avalonia/Views/Subforms/SAVPokepuff6View.axaml
@@ -0,0 +1,43 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/PKHeX.Avalonia/Views/Subforms/SAVPokepuff6View.axaml.cs b/PKHeX.Avalonia/Views/Subforms/SAVPokepuff6View.axaml.cs
new file mode 100644
index 000000000..a8f1db9d8
--- /dev/null
+++ b/PKHeX.Avalonia/Views/Subforms/SAVPokepuff6View.axaml.cs
@@ -0,0 +1,24 @@
+using Avalonia.Interactivity;
+using PKHeX.Avalonia.ViewModels.Subforms;
+
+namespace PKHeX.Avalonia.Views.Subforms;
+
+public partial class SAVPokepuff6View : SubformWindow
+{
+ public SAVPokepuff6View()
+ {
+ InitializeComponent();
+ }
+
+ private void OnOkClick(object? sender, RoutedEventArgs e)
+ {
+ if (DataContext is SAVPokepuff6ViewModel vm)
+ vm.SaveCommand.Execute(null);
+ CloseWithResult(true);
+ }
+
+ private void OnCancelClick(object? sender, RoutedEventArgs e)
+ {
+ CloseWithResult(false);
+ }
+}
diff --git a/PKHeX.Avalonia/Views/Subforms/SAVRoamer6View.axaml b/PKHeX.Avalonia/Views/Subforms/SAVRoamer6View.axaml
new file mode 100644
index 000000000..238e7920a
--- /dev/null
+++ b/PKHeX.Avalonia/Views/Subforms/SAVRoamer6View.axaml
@@ -0,0 +1,41 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/PKHeX.Avalonia/Views/Subforms/SAVRoamer6View.axaml.cs b/PKHeX.Avalonia/Views/Subforms/SAVRoamer6View.axaml.cs
new file mode 100644
index 000000000..b5a6412a8
--- /dev/null
+++ b/PKHeX.Avalonia/Views/Subforms/SAVRoamer6View.axaml.cs
@@ -0,0 +1,24 @@
+using Avalonia.Interactivity;
+using PKHeX.Avalonia.ViewModels.Subforms;
+
+namespace PKHeX.Avalonia.Views.Subforms;
+
+public partial class SAVRoamer6View : SubformWindow
+{
+ public SAVRoamer6View()
+ {
+ InitializeComponent();
+ }
+
+ private void OnOkClick(object? sender, RoutedEventArgs e)
+ {
+ if (DataContext is SAVRoamer6ViewModel vm)
+ vm.SaveCommand.Execute(null);
+ CloseWithResult(true);
+ }
+
+ private void OnCancelClick(object? sender, RoutedEventArgs e)
+ {
+ CloseWithResult(false);
+ }
+}
diff --git a/PKHeX.Avalonia/Views/Subforms/SAVSecretBase6View.axaml b/PKHeX.Avalonia/Views/Subforms/SAVSecretBase6View.axaml
new file mode 100644
index 000000000..b22a59ded
--- /dev/null
+++ b/PKHeX.Avalonia/Views/Subforms/SAVSecretBase6View.axaml
@@ -0,0 +1,87 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/PKHeX.Avalonia/Views/Subforms/SAVSecretBase6View.axaml.cs b/PKHeX.Avalonia/Views/Subforms/SAVSecretBase6View.axaml.cs
new file mode 100644
index 000000000..ea43b6105
--- /dev/null
+++ b/PKHeX.Avalonia/Views/Subforms/SAVSecretBase6View.axaml.cs
@@ -0,0 +1,24 @@
+using Avalonia.Interactivity;
+using PKHeX.Avalonia.ViewModels.Subforms;
+
+namespace PKHeX.Avalonia.Views.Subforms;
+
+public partial class SAVSecretBase6View : SubformWindow
+{
+ public SAVSecretBase6View()
+ {
+ InitializeComponent();
+ }
+
+ private void OnOkClick(object? sender, RoutedEventArgs e)
+ {
+ if (DataContext is SAVSecretBase6ViewModel vm)
+ vm.SaveCommand.Execute(null);
+ CloseWithResult(true);
+ }
+
+ private void OnCancelClick(object? sender, RoutedEventArgs e)
+ {
+ CloseWithResult(false);
+ }
+}
diff --git a/PKHeX.Avalonia/Views/Subforms/SAVSuperTrain6View.axaml b/PKHeX.Avalonia/Views/Subforms/SAVSuperTrain6View.axaml
new file mode 100644
index 000000000..d648704d0
--- /dev/null
+++ b/PKHeX.Avalonia/Views/Subforms/SAVSuperTrain6View.axaml
@@ -0,0 +1,95 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/PKHeX.Avalonia/Views/Subforms/SAVSuperTrain6View.axaml.cs b/PKHeX.Avalonia/Views/Subforms/SAVSuperTrain6View.axaml.cs
new file mode 100644
index 000000000..186b6cc86
--- /dev/null
+++ b/PKHeX.Avalonia/Views/Subforms/SAVSuperTrain6View.axaml.cs
@@ -0,0 +1,24 @@
+using Avalonia.Interactivity;
+using PKHeX.Avalonia.ViewModels.Subforms;
+
+namespace PKHeX.Avalonia.Views.Subforms;
+
+public partial class SAVSuperTrain6View : SubformWindow
+{
+ public SAVSuperTrain6View()
+ {
+ InitializeComponent();
+ }
+
+ private void OnOkClick(object? sender, RoutedEventArgs e)
+ {
+ if (DataContext is SAVSuperTrain6ViewModel vm)
+ vm.SaveCommand.Execute(null);
+ CloseWithResult(true);
+ }
+
+ private void OnCancelClick(object? sender, RoutedEventArgs e)
+ {
+ CloseWithResult(false);
+ }
+}
diff --git a/PKHeX.Avalonia/Views/Subforms/SAVTrainer6View.axaml b/PKHeX.Avalonia/Views/Subforms/SAVTrainer6View.axaml
new file mode 100644
index 000000000..d28a689fb
--- /dev/null
+++ b/PKHeX.Avalonia/Views/Subforms/SAVTrainer6View.axaml
@@ -0,0 +1,123 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/PKHeX.Avalonia/Views/Subforms/SAVTrainer6View.axaml.cs b/PKHeX.Avalonia/Views/Subforms/SAVTrainer6View.axaml.cs
new file mode 100644
index 000000000..850a8ac7c
--- /dev/null
+++ b/PKHeX.Avalonia/Views/Subforms/SAVTrainer6View.axaml.cs
@@ -0,0 +1,24 @@
+using Avalonia.Interactivity;
+using PKHeX.Avalonia.ViewModels.Subforms;
+
+namespace PKHeX.Avalonia.Views.Subforms;
+
+public partial class SAVTrainer6View : SubformWindow
+{
+ public SAVTrainer6View()
+ {
+ InitializeComponent();
+ }
+
+ private void OnOkClick(object? sender, RoutedEventArgs e)
+ {
+ if (DataContext is SAVTrainer6ViewModel vm)
+ vm.SaveCommand.Execute(null);
+ CloseWithResult(true);
+ }
+
+ private void OnCancelClick(object? sender, RoutedEventArgs e)
+ {
+ CloseWithResult(false);
+ }
+}
diff --git a/PKHeX.Avalonia/Views/Subforms/UnityTower5View.axaml b/PKHeX.Avalonia/Views/Subforms/UnityTower5View.axaml
new file mode 100644
index 000000000..83b339828
--- /dev/null
+++ b/PKHeX.Avalonia/Views/Subforms/UnityTower5View.axaml
@@ -0,0 +1,68 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/PKHeX.Avalonia/Views/Subforms/UnityTower5View.axaml.cs b/PKHeX.Avalonia/Views/Subforms/UnityTower5View.axaml.cs
new file mode 100644
index 000000000..cf730ab8a
--- /dev/null
+++ b/PKHeX.Avalonia/Views/Subforms/UnityTower5View.axaml.cs
@@ -0,0 +1,24 @@
+using Avalonia.Interactivity;
+using PKHeX.Avalonia.ViewModels.Subforms;
+
+namespace PKHeX.Avalonia.Views.Subforms;
+
+public partial class UnityTower5View : SubformWindow
+{
+ public UnityTower5View()
+ {
+ InitializeComponent();
+ }
+
+ private void OnOkClick(object? sender, RoutedEventArgs e)
+ {
+ if (DataContext is UnityTower5ViewModel vm)
+ vm.SaveCommand.Execute(null);
+ CloseWithResult(true);
+ }
+
+ private void OnCancelClick(object? sender, RoutedEventArgs e)
+ {
+ CloseWithResult(false);
+ }
+}