mirror of
https://github.com/kwsch/PKHeX
synced 2024-09-20 14:21:59 +00:00
Decouple event flag/work from SaveFile
This commit is contained in:
parent
a601180821
commit
a5ee845c3b
45 changed files with 1523 additions and 579 deletions
|
@ -1,50 +1,56 @@
|
|||
using System;
|
||||
using static PKHeX.Core.GameVersion;
|
||||
|
||||
namespace PKHeX.Core
|
||||
namespace PKHeX.Core;
|
||||
|
||||
public sealed class EventWorkspace<TSave, TWork> where TSave : IEventFlagArray, IEventWorkArray<TWork> where TWork : unmanaged
|
||||
{
|
||||
public sealed class EventWorkspace
|
||||
private readonly TSave SAV;
|
||||
public readonly bool[] Flags;
|
||||
public readonly TWork[] Values;
|
||||
public readonly EventLabelCollection Labels;
|
||||
|
||||
public EventWorkspace(TSave sav)
|
||||
{
|
||||
private readonly SaveFile SAV;
|
||||
public readonly bool[] Flags;
|
||||
public readonly ushort[] Values;
|
||||
public readonly EventLabelCollection Labels;
|
||||
SAV = sav;
|
||||
Flags = sav.GetEventFlags();
|
||||
Values = sav.GetAllEventWork();
|
||||
|
||||
public EventWorkspace(SaveFile sav)
|
||||
{
|
||||
SAV = sav;
|
||||
Flags = sav.GetEventFlags();
|
||||
Values = sav.GetEventConsts();
|
||||
var game = GetResourceSuffix(sav);
|
||||
Labels = new EventLabelCollection(game, Flags.Length, Values.Length);
|
||||
}
|
||||
|
||||
var game = GetResourceSuffix(sav.Version);
|
||||
Labels = new EventLabelCollection(game, Flags.Length, Values.Length);
|
||||
}
|
||||
public void Save()
|
||||
{
|
||||
SAV.SetEventFlags(Flags);
|
||||
SAV.SetAllEventWork(Values);
|
||||
if (SAV is SAV7SM s7) // Ensure Magearna event flag has magic constant
|
||||
s7.UpdateMagearnaConstant();
|
||||
}
|
||||
|
||||
public void Save()
|
||||
{
|
||||
SAV.SetEventFlags(Flags);
|
||||
SAV.SetEventConsts(Values);
|
||||
if (SAV is SAV7SM s7) // Ensure Magearna event flag has magic constant
|
||||
s7.UpdateMagearnaConstant();
|
||||
}
|
||||
private static string GetResourceSuffix(TSave ver) => GetVersion(ver) switch
|
||||
{
|
||||
X or Y or XY => "xy",
|
||||
OR or AS or ORAS => "oras",
|
||||
SN or MN or SM => "sm",
|
||||
US or UM or USUM => "usum",
|
||||
D or P or DP => "dp",
|
||||
Pt or DPPt => "pt",
|
||||
HG or SS or HGSS => "hgss",
|
||||
B or W or BW => "bw",
|
||||
B2 or W2 or B2W2 => "b2w2",
|
||||
R or S or RS => "rs",
|
||||
E => "e",
|
||||
FR or LG or FRLG => "frlg",
|
||||
C => "c",
|
||||
GD or SI or GS => "gs",
|
||||
_ => throw new ArgumentOutOfRangeException(nameof(GameVersion)),
|
||||
};
|
||||
|
||||
private static string GetResourceSuffix(GameVersion ver) => ver switch
|
||||
{
|
||||
X or Y or XY => "xy",
|
||||
OR or AS or ORAS => "oras",
|
||||
SN or MN or SM => "sm",
|
||||
US or UM or USUM => "usum",
|
||||
D or P or DP => "dp",
|
||||
Pt or DPPt => "pt",
|
||||
HG or SS or HGSS => "hgss",
|
||||
B or W or BW => "bw",
|
||||
B2 or W2 or B2W2 => "b2w2",
|
||||
R or S or RS => "rs",
|
||||
E => "e",
|
||||
FR or LG or FRLG => "frlg",
|
||||
C => "c",
|
||||
GD or SI or GS => "gs",
|
||||
_ => throw new ArgumentOutOfRangeException(nameof(GameVersion)),
|
||||
};
|
||||
private static GameVersion GetVersion(TSave ver)
|
||||
{
|
||||
if (ver is IVersion v)
|
||||
return v.Version;
|
||||
return Invalid;
|
||||
}
|
||||
}
|
||||
|
|
102
PKHeX.Core/Editing/Saves/Editors/EventWork/Diff/EventWorkDiff.cs
Normal file
102
PKHeX.Core/Editing/Saves/Editors/EventWork/Diff/EventWorkDiff.cs
Normal file
|
@ -0,0 +1,102 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using static PKHeX.Core.EventWorkDiffCompatibility;
|
||||
using static PKHeX.Core.EventWorkDiffCompatibilityExtensions;
|
||||
|
||||
namespace PKHeX.Core;
|
||||
|
||||
/// <summary>
|
||||
/// Calculates differences in the Event Blocks between two <see cref="SaveFile"/>.
|
||||
/// </summary>
|
||||
public class EventBlockDiff<T, T2> : IEventWorkDiff where T : IEventFlagArray, IEventWorkArray<T2> where T2 : unmanaged, IEquatable<T2>
|
||||
{
|
||||
public List<int> SetFlags { get; } = new();
|
||||
public List<int> ClearedFlags { get; } = new();
|
||||
public List<int> WorkChanged { get; } = new();
|
||||
public List<string> WorkDiff { get; } = new();
|
||||
public EventWorkDiffCompatibility Message { get; private set; }
|
||||
|
||||
private const int MAX_SAVEFILE_SIZE = 0x10_0000; // 1 MB
|
||||
|
||||
public EventBlockDiff(T s1, T s2) => Diff(s1, s2);
|
||||
|
||||
public EventBlockDiff(string f1, string f2)
|
||||
{
|
||||
Message = SanityCheckFiles(f1, f2, MAX_SAVEFILE_SIZE);
|
||||
if (Message != Valid)
|
||||
return;
|
||||
var s1 = SaveUtil.GetVariantSAV(f1);
|
||||
var s2 = SaveUtil.GetVariantSAV(f2);
|
||||
if (s1 == null || s2 == null || s1.GetType() != s2.GetType() || s1 is not T t1 || s2 is not T t2)
|
||||
{
|
||||
Message = DifferentGameGroup;
|
||||
return;
|
||||
}
|
||||
Diff(t1, t2);
|
||||
}
|
||||
|
||||
protected EventWorkDiffCompatibility SanityCheckSaveInfo(T s1, T s2)
|
||||
{
|
||||
if (s1.GetType() != s2.GetType())
|
||||
return DifferentGameGroup;
|
||||
|
||||
if (s1 is not IVersion i1 || s2 is not IVersion i2 || i1.Version != i2.Version)
|
||||
return DifferentVersion;
|
||||
|
||||
return Valid;
|
||||
}
|
||||
|
||||
protected void Diff(T s1, T s2)
|
||||
{
|
||||
Message = SanityCheckSaveInfo(s1, s2);
|
||||
if (Message != Valid)
|
||||
return;
|
||||
|
||||
bool[] oldBits = s1.GetEventFlags();
|
||||
bool[] newBits = s2.GetEventFlags();
|
||||
var oldConst = s1.GetAllEventWork();
|
||||
var newConst = s2.GetAllEventWork();
|
||||
|
||||
for (int i = 0; i < newBits.Length; i++)
|
||||
{
|
||||
if (oldBits[i] != newBits[i])
|
||||
(newBits[i] ? SetFlags : ClearedFlags).Add(i);
|
||||
}
|
||||
for (int i = 0; i < newConst.Length; i++)
|
||||
{
|
||||
if (oldConst[i].Equals(newConst[i]))
|
||||
continue;
|
||||
WorkChanged.Add(i);
|
||||
WorkDiff.Add($"{i}: {oldConst[i]} => {newConst[i]}");
|
||||
}
|
||||
}
|
||||
|
||||
public IReadOnlyList<string> Summarize()
|
||||
{
|
||||
var fOn = SetFlags.Select(z => z.ToString());
|
||||
var fOff = ClearedFlags.Select(z => z.ToString());
|
||||
var wt = WorkChanged.Select((z, _) => z.ToString());
|
||||
|
||||
var list = new List<string> { "Flags: ON", "=========" };
|
||||
list.AddRange(fOn);
|
||||
if (SetFlags.Count == 0)
|
||||
list.Add("None.");
|
||||
|
||||
list.Add("");
|
||||
list.Add("Flags: OFF");
|
||||
list.Add("==========");
|
||||
list.AddRange(fOff);
|
||||
if (ClearedFlags.Count == 0)
|
||||
list.Add("None.");
|
||||
|
||||
list.Add("");
|
||||
list.Add("Work:");
|
||||
list.Add("=====");
|
||||
if (WorkChanged.Count == 0)
|
||||
list.Add("None.");
|
||||
list.AddRange(wt);
|
||||
|
||||
return list;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,106 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using static PKHeX.Core.EventWorkUtil;
|
||||
using static PKHeX.Core.EventWorkDiffCompatibility;
|
||||
using static PKHeX.Core.EventWorkDiffCompatibilityExtensions;
|
||||
|
||||
namespace PKHeX.Core;
|
||||
|
||||
public sealed class EventWorkDiff7b : IEventWorkDiff
|
||||
{
|
||||
private SAV7b? S1;
|
||||
public List<int> SetFlags { get; } = new();
|
||||
public List<int> ClearedFlags { get; } = new();
|
||||
public List<int> WorkChanged { get; } = new();
|
||||
public List<string> WorkDiff { get; } = new();
|
||||
public EventWorkDiffCompatibility Message { get; private set; }
|
||||
|
||||
private const int MAX_SAVEFILE_SIZE = 0x10_0000; // 1 MB
|
||||
|
||||
public EventWorkDiff7b(SAV7b s1, SAV7b s2) => Diff(s1, s2);
|
||||
|
||||
public EventWorkDiff7b(string f1, string f2)
|
||||
{
|
||||
Message = SanityCheckFiles(f1, f2, MAX_SAVEFILE_SIZE);
|
||||
if (Message != Valid)
|
||||
return;
|
||||
|
||||
var s1 = SaveUtil.GetVariantSAV(f1);
|
||||
var s2 = SaveUtil.GetVariantSAV(f2);
|
||||
if (s1 is not SAV7b b1 || s2 is not SAV7b b2)
|
||||
{
|
||||
Message = DifferentVersion;
|
||||
return;
|
||||
}
|
||||
|
||||
Diff(b1, b2);
|
||||
}
|
||||
|
||||
private void Diff(SAV7b s1, SAV7b s2)
|
||||
{
|
||||
S1 = s1;
|
||||
if (s1.Version != s2.Version)
|
||||
{
|
||||
Message = DifferentVersion;
|
||||
return;
|
||||
}
|
||||
|
||||
DiffSavesFlag(s1.Blocks.EventWork, s2.Blocks.EventWork, SetFlags, ClearedFlags);
|
||||
DiffSavesWork(s1.Blocks.EventWork, s2.Blocks.EventWork, WorkChanged, WorkDiff);
|
||||
}
|
||||
|
||||
public IReadOnlyList<string> Summarize()
|
||||
{
|
||||
if (S1 == null)
|
||||
return Array.Empty<string>();
|
||||
var ew = S1.Blocks.EventWork;
|
||||
|
||||
var fOn = SetFlags.Select(z => FlagSummary.Get(z, ew).ToString());
|
||||
var fOff = ClearedFlags.Select(z => FlagSummary.Get(z, ew).ToString());
|
||||
var wt = WorkChanged.Select((z, i) => WorkSummary.Get(z, ew, WorkDiff[i]).ToString());
|
||||
|
||||
var list = new List<string> { "Flags: ON", "=========" };
|
||||
list.AddRange(fOn);
|
||||
if (SetFlags.Count == 0)
|
||||
list.Add("None.");
|
||||
|
||||
list.Add("");
|
||||
list.Add("Flags: OFF");
|
||||
list.Add("==========");
|
||||
list.AddRange(fOff);
|
||||
if (ClearedFlags.Count == 0)
|
||||
list.Add("None.");
|
||||
|
||||
list.Add("");
|
||||
list.Add("Work:");
|
||||
list.Add("=====");
|
||||
if (WorkChanged.Count == 0)
|
||||
list.Add("None.");
|
||||
list.AddRange(wt);
|
||||
|
||||
return list;
|
||||
}
|
||||
|
||||
private readonly record struct FlagSummary(EventVarType Type, int Index, int Raw)
|
||||
{
|
||||
public override string ToString() => $"{Raw:0000}\t{false}\t{Index:0000}\t{Type}";
|
||||
|
||||
public static FlagSummary Get(int rawIndex, EventWork7b ew)
|
||||
{
|
||||
var type = ew.GetFlagType(rawIndex, out var subIndex);
|
||||
return new FlagSummary(type, subIndex, rawIndex);
|
||||
}
|
||||
}
|
||||
|
||||
private readonly record struct WorkSummary(EventVarType Type, int Index, int Raw, string Text)
|
||||
{
|
||||
public override string ToString() => $"{Raw:000}\t{Text}\t{Index:000}\t{Type}";
|
||||
|
||||
public static WorkSummary Get(int rawIndex, EventWork7b ew, string text)
|
||||
{
|
||||
var type = ew.GetFlagType(rawIndex, out var subIndex);
|
||||
return new WorkSummary(type, subIndex, rawIndex, text);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,112 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using static PKHeX.Core.EventWorkUtil;
|
||||
using static PKHeX.Core.EventWorkDiffCompatibility;
|
||||
using static PKHeX.Core.EventWorkDiffCompatibilityExtensions;
|
||||
|
||||
namespace PKHeX.Core;
|
||||
|
||||
public sealed class EventWorkDiff8b : IEventWorkDiff
|
||||
{
|
||||
private SAV8BS? S1;
|
||||
public List<int> SetSystem { get; } = new();
|
||||
public List<int> SetFlags { get; } = new();
|
||||
public List<int> ClearedSystem { get; } = new();
|
||||
public List<int> ClearedFlags { get; } = new();
|
||||
public List<int> WorkChanged { get; } = new();
|
||||
public List<string> WorkDiff { get; } = new();
|
||||
public EventWorkDiffCompatibility Message { get; private set; }
|
||||
|
||||
private const int MAX_SAVEFILE_SIZE = 0x10_0000; // 1 MB
|
||||
|
||||
public EventWorkDiff8b(SAV8BS s1, SAV8BS s2) => Diff(s1, s2);
|
||||
|
||||
public EventWorkDiff8b(string f1, string f2)
|
||||
{
|
||||
Message = SanityCheckFiles(f1, f2, MAX_SAVEFILE_SIZE);
|
||||
if (Message != Valid)
|
||||
return;
|
||||
var s1 = SaveUtil.GetVariantSAV(f1);
|
||||
var s2 = SaveUtil.GetVariantSAV(f2);
|
||||
if (s1 is not SAV8BS b1 || s2 is not SAV8BS b2)
|
||||
{
|
||||
Message = DifferentGameGroup;
|
||||
return;
|
||||
}
|
||||
Diff(b1, b2);
|
||||
}
|
||||
|
||||
private void Diff(SAV8BS s1, SAV8BS s2)
|
||||
{
|
||||
S1 = s1;
|
||||
if (s1.Version != s2.Version)
|
||||
{
|
||||
Message = DifferentVersion;
|
||||
return;
|
||||
}
|
||||
|
||||
DiffSavesFlag(s1.Work, s2.Work, SetFlags, ClearedFlags);
|
||||
DiffSavesSystem(s1.Work, s2.Work, SetSystem, ClearedSystem);
|
||||
DiffSavesWork(s1.Work, s2.Work, WorkChanged, WorkDiff);
|
||||
S1 = s1;
|
||||
}
|
||||
|
||||
public IReadOnlyList<string> Summarize()
|
||||
{
|
||||
if (S1 == null)
|
||||
return Array.Empty<string>();
|
||||
|
||||
var fOn = SetFlags.Select(z => new FlagSummary(z).ToString());
|
||||
var fOff = ClearedFlags.Select(z => new FlagSummary(z).ToString());
|
||||
|
||||
var sOn = SetSystem.Select(z => new FlagSummary(z).ToString());
|
||||
var sOff = ClearedSystem.Select(z => new FlagSummary(z).ToString());
|
||||
|
||||
var wt = WorkChanged.Select((z, i) => new WorkSummary(z, WorkDiff[i]).ToString());
|
||||
|
||||
var list = new List<string> { "Flags: ON", "=========" };
|
||||
list.AddRange(fOn);
|
||||
if (SetFlags.Count == 0)
|
||||
list.Add("None.");
|
||||
|
||||
list.Add("");
|
||||
list.Add("Flags: OFF");
|
||||
list.Add("==========");
|
||||
list.AddRange(fOff);
|
||||
if (ClearedFlags.Count == 0)
|
||||
list.Add("None.");
|
||||
|
||||
list.Add("System: ON");
|
||||
list.Add("=========");
|
||||
list.AddRange(sOn);
|
||||
if (SetFlags.Count == 0)
|
||||
list.Add("None.");
|
||||
|
||||
list.Add("");
|
||||
list.Add("System: OFF");
|
||||
list.Add("==========");
|
||||
list.AddRange(sOff);
|
||||
if (ClearedSystem.Count == 0)
|
||||
list.Add("None.");
|
||||
|
||||
list.Add("");
|
||||
list.Add("Work:");
|
||||
list.Add("=====");
|
||||
if (WorkChanged.Count == 0)
|
||||
list.Add("None.");
|
||||
list.AddRange(wt);
|
||||
|
||||
return list;
|
||||
}
|
||||
|
||||
private readonly record struct FlagSummary(int Raw)
|
||||
{
|
||||
public override string ToString() => $"{Raw:0000}\t{false}";
|
||||
}
|
||||
|
||||
private readonly record struct WorkSummary(int Raw, string Text)
|
||||
{
|
||||
public override string ToString() => $"{Raw:000}\t{Text}";
|
||||
}
|
||||
}
|
|
@ -0,0 +1,48 @@
|
|||
using System;
|
||||
using System.IO;
|
||||
using static PKHeX.Core.MessageStrings;
|
||||
using static PKHeX.Core.EventWorkDiffCompatibility;
|
||||
|
||||
namespace PKHeX.Core;
|
||||
|
||||
public enum EventWorkDiffCompatibility
|
||||
{
|
||||
Valid,
|
||||
DifferentVersion,
|
||||
DifferentGameGroup,
|
||||
FileTooBig1,
|
||||
FileTooBig2,
|
||||
FileMissing1,
|
||||
FileMissing2,
|
||||
}
|
||||
|
||||
public static class EventWorkDiffCompatibilityExtensions
|
||||
{
|
||||
public static string GetMessage(this EventWorkDiffCompatibility value) => value switch
|
||||
{
|
||||
DifferentVersion => MsgSaveDifferentVersions,
|
||||
DifferentGameGroup => MsgSaveDifferentTypes,
|
||||
FileTooBig1 => string.Format(MsgSaveNumberInvalid, 1),
|
||||
FileTooBig2 => string.Format(MsgSaveNumberInvalid, 2),
|
||||
FileMissing1 => string.Format(MsgSaveNumberInvalid, 1),
|
||||
FileMissing2 => string.Format(MsgSaveNumberInvalid, 2),
|
||||
_ => throw new ArgumentOutOfRangeException(nameof(value), value, null)
|
||||
};
|
||||
|
||||
public static EventWorkDiffCompatibility SanityCheckFiles(string f1, string f2, int MAX_SAVEFILE_SIZE)
|
||||
{
|
||||
if (!File.Exists(f1))
|
||||
return FileMissing1;
|
||||
|
||||
if (!File.Exists(f2))
|
||||
return FileMissing2;
|
||||
|
||||
if (new FileInfo(f1).Length > MAX_SAVEFILE_SIZE)
|
||||
return FileTooBig1;
|
||||
|
||||
if (new FileInfo(f2).Length > MAX_SAVEFILE_SIZE)
|
||||
return FileTooBig2;
|
||||
|
||||
return Valid;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,13 @@
|
|||
using System.Collections.Generic;
|
||||
|
||||
namespace PKHeX.Core;
|
||||
|
||||
public interface IEventWorkDiff
|
||||
{
|
||||
List<int> SetFlags { get; }
|
||||
List<int> ClearedFlags { get; }
|
||||
List<int> WorkChanged { get; }
|
||||
List<string> WorkDiff { get; }
|
||||
EventWorkDiffCompatibility Message { get; }
|
||||
IReadOnlyList<string> Summarize();
|
||||
}
|
|
@ -1,267 +0,0 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using static PKHeX.Core.MessageStrings;
|
||||
|
||||
namespace PKHeX.Core
|
||||
{
|
||||
/// <summary>
|
||||
/// Calculates differences in the Event Blocks between two <see cref="SaveFile"/>.
|
||||
/// </summary>
|
||||
public class EventBlockDiff
|
||||
{
|
||||
public string Message { get; protected set; } = string.Empty;
|
||||
public readonly List<int> SetFlags = new();
|
||||
public readonly List<int> ClearedFlags = new();
|
||||
public readonly List<string> WorkDiff = new();
|
||||
|
||||
private const int MAX_SAVEFILE_SIZE = 0x10_0000; // 1 MB
|
||||
protected EventBlockDiff() { }
|
||||
|
||||
public EventBlockDiff(string f1, string f2)
|
||||
{
|
||||
if (!SanityCheckFiles(f1, f2))
|
||||
return;
|
||||
var s1 = SaveUtil.GetVariantSAV(f1);
|
||||
var s2 = SaveUtil.GetVariantSAV(f2);
|
||||
if (s1 == null || s2 == null || s1.GetType() != s2.GetType())
|
||||
{
|
||||
Message = MsgSaveDifferentTypes;
|
||||
return;
|
||||
}
|
||||
Diff(s1, s2);
|
||||
}
|
||||
|
||||
public EventBlockDiff(SaveFile s1, SaveFile s2) => Diff(s1, s2);
|
||||
|
||||
protected bool SanityCheckFiles(string f1, string f2)
|
||||
{
|
||||
if (!File.Exists(f1))
|
||||
{ Message = string.Format(MsgSaveNumberInvalid, 1); return false; }
|
||||
|
||||
if (!File.Exists(f2))
|
||||
{ Message = string.Format(MsgSaveNumberInvalid, 2); return false; }
|
||||
|
||||
if (new FileInfo(f1).Length > MAX_SAVEFILE_SIZE)
|
||||
{ Message = string.Format(MsgSaveNumberInvalid, 1); return false; }
|
||||
|
||||
if (new FileInfo(f2).Length > MAX_SAVEFILE_SIZE)
|
||||
{ Message = string.Format(MsgSaveNumberInvalid, 2); return false; }
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
protected bool SanityCheckSaveInfo(SaveFile s1, SaveFile s2)
|
||||
{
|
||||
if (s1.GetType() != s2.GetType())
|
||||
{ Message = string.Format(MsgSaveDifferentTypes, $"S1: {s1.GetType().Name}", $"S2: {s2.GetType().Name}"); return false; }
|
||||
|
||||
if (s1.Version != s2.Version)
|
||||
{ Message = string.Format(MsgSaveDifferentVersions, $"S1: {s1.Version}", $"S2: {s2.Version}"); return false; }
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
protected virtual void Diff(SaveFile s1, SaveFile s2)
|
||||
{
|
||||
if (!SanityCheckSaveInfo(s1, s2))
|
||||
return;
|
||||
|
||||
bool[] oldBits = s1.GetEventFlags();
|
||||
bool[] newBits = s2.GetEventFlags();
|
||||
var oldConst = s1.GetEventConsts();
|
||||
var newConst = s2.GetEventConsts();
|
||||
|
||||
for (int i = 0; i < newBits.Length; i++)
|
||||
{
|
||||
if (oldBits[i] != newBits[i])
|
||||
(newBits[i] ? SetFlags : ClearedFlags).Add(i);
|
||||
}
|
||||
for (int i = 0; i < newConst.Length; i++)
|
||||
{
|
||||
if (oldConst[i] != newConst[i])
|
||||
WorkDiff.Add($"{i}: {oldConst[i]}->{newConst[i]}");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public sealed class EventWorkDiff7b : EventBlockDiff
|
||||
{
|
||||
public readonly List<int> WorkChanged = new();
|
||||
private SaveFile? S1;
|
||||
|
||||
public EventWorkDiff7b(string f1, string f2)
|
||||
{
|
||||
if (!SanityCheckFiles(f1, f2))
|
||||
return;
|
||||
var s1 = SaveUtil.GetVariantSAV(f1);
|
||||
var s2 = SaveUtil.GetVariantSAV(f2);
|
||||
if (s1 == null || s2 == null || s1.GetType() != s2.GetType())
|
||||
{
|
||||
Message = MsgSaveDifferentTypes;
|
||||
return;
|
||||
}
|
||||
Diff(s1, s2);
|
||||
}
|
||||
|
||||
public EventWorkDiff7b(SaveFile s1, SaveFile s2) => Diff(s1, s2);
|
||||
|
||||
protected override void Diff(SaveFile s1, SaveFile s2)
|
||||
{
|
||||
if (!SanityCheckSaveInfo(s1, s2))
|
||||
return;
|
||||
|
||||
EventWorkUtil.DiffSavesFlag(((SAV7b)s1).Blocks.EventWork, ((SAV7b)s2).Blocks.EventWork, SetFlags, ClearedFlags);
|
||||
EventWorkUtil.DiffSavesWork(((SAV7b)s1).Blocks.EventWork, ((SAV7b)s2).Blocks.EventWork, WorkChanged, WorkDiff);
|
||||
S1 = s1;
|
||||
}
|
||||
|
||||
public IReadOnlyList<string> Summarize()
|
||||
{
|
||||
if (S1 == null)
|
||||
return Array.Empty<string>();
|
||||
var ew = ((SAV7b)S1).Blocks.EventWork;
|
||||
|
||||
var fOn = SetFlags.Select(z => FlagSummary.Get(z, ew).ToString());
|
||||
var fOff = ClearedFlags.Select(z => FlagSummary.Get(z, ew).ToString());
|
||||
var wt = WorkChanged.Select((z, i) => WorkSummary.Get(z, ew, WorkDiff[i]).ToString());
|
||||
|
||||
var list = new List<string> { "Flags: ON", "=========" };
|
||||
list.AddRange(fOn);
|
||||
if (SetFlags.Count == 0)
|
||||
list.Add("None.");
|
||||
|
||||
list.Add("");
|
||||
list.Add("Flags: OFF");
|
||||
list.Add("==========");
|
||||
list.AddRange(fOff);
|
||||
if (ClearedFlags.Count == 0)
|
||||
list.Add("None.");
|
||||
|
||||
list.Add("");
|
||||
list.Add("Work:");
|
||||
list.Add("=====");
|
||||
if (WorkChanged.Count == 0)
|
||||
list.Add("None.");
|
||||
list.AddRange(wt);
|
||||
|
||||
return list;
|
||||
}
|
||||
|
||||
private readonly record struct FlagSummary(EventVarType Type, int Index, int Raw)
|
||||
{
|
||||
public override string ToString() => $"{Raw:0000}\t{false}\t{Index:0000}\t{Type}";
|
||||
|
||||
public static FlagSummary Get(int rawIndex, EventWork7b ew)
|
||||
{
|
||||
var type = ew.GetFlagType(rawIndex, out var subIndex);
|
||||
return new FlagSummary(type, subIndex, rawIndex);
|
||||
}
|
||||
}
|
||||
|
||||
private readonly record struct WorkSummary(EventVarType Type, int Index, int Raw, string Text)
|
||||
{
|
||||
public override string ToString() => $"{Raw:000}\t{Text}\t{Index:000}\t{Type}";
|
||||
|
||||
public static WorkSummary Get(int rawIndex, EventWork7b ew, string text)
|
||||
{
|
||||
var type = ew.GetFlagType(rawIndex, out var subIndex);
|
||||
return new WorkSummary(type, subIndex, rawIndex, text);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public sealed class EventWorkDiff8b : EventBlockDiff
|
||||
{
|
||||
public readonly List<int> WorkChanged = new();
|
||||
private SaveFile? S1;
|
||||
public readonly List<int> SetSystem = new();
|
||||
public readonly List<int> ClearedSystem = new();
|
||||
|
||||
public EventWorkDiff8b(string f1, string f2)
|
||||
{
|
||||
if (!SanityCheckFiles(f1, f2))
|
||||
return;
|
||||
var s1 = SaveUtil.GetVariantSAV(f1);
|
||||
var s2 = SaveUtil.GetVariantSAV(f2);
|
||||
if (s1 == null || s2 == null || s1.GetType() != s2.GetType())
|
||||
{
|
||||
Message = MsgSaveDifferentTypes;
|
||||
return;
|
||||
}
|
||||
Diff(s1, s2);
|
||||
}
|
||||
|
||||
public EventWorkDiff8b(SaveFile s1, SaveFile s2) => Diff(s1, s2);
|
||||
|
||||
protected override void Diff(SaveFile s1, SaveFile s2)
|
||||
{
|
||||
if (!SanityCheckSaveInfo(s1, s2))
|
||||
return;
|
||||
|
||||
EventWorkUtil.DiffSavesFlag(((SAV8BS)s1).Work, ((SAV8BS)s2).Work, SetFlags, ClearedFlags);
|
||||
EventWorkUtil.DiffSavesSystem(((SAV8BS)s1).Work, ((SAV8BS)s2).Work, SetSystem, ClearedSystem);
|
||||
EventWorkUtil.DiffSavesWork(((SAV8BS)s1).Work, ((SAV8BS)s2).Work, WorkChanged, WorkDiff);
|
||||
S1 = s1;
|
||||
}
|
||||
|
||||
public IReadOnlyList<string> Summarize()
|
||||
{
|
||||
if (S1 == null)
|
||||
return Array.Empty<string>();
|
||||
|
||||
var fOn = SetFlags.Select(z => new FlagSummary(z).ToString());
|
||||
var fOff = ClearedFlags.Select(z => new FlagSummary(z).ToString());
|
||||
|
||||
var sOn = SetSystem.Select(z => new FlagSummary(z).ToString());
|
||||
var sOff = ClearedSystem.Select(z => new FlagSummary(z).ToString());
|
||||
|
||||
var wt = WorkChanged.Select((z, i) => new WorkSummary(z, WorkDiff[i]).ToString());
|
||||
|
||||
var list = new List<string> { "Flags: ON", "=========" };
|
||||
list.AddRange(fOn);
|
||||
if (SetFlags.Count == 0)
|
||||
list.Add("None.");
|
||||
|
||||
list.Add("");
|
||||
list.Add("Flags: OFF");
|
||||
list.Add("==========");
|
||||
list.AddRange(fOff);
|
||||
if (ClearedFlags.Count == 0)
|
||||
list.Add("None.");
|
||||
|
||||
list.Add("System: ON");
|
||||
list.Add("=========");
|
||||
list.AddRange(sOn);
|
||||
if (SetFlags.Count == 0)
|
||||
list.Add("None.");
|
||||
|
||||
list.Add("");
|
||||
list.Add("System: OFF");
|
||||
list.Add("==========");
|
||||
list.AddRange(sOff);
|
||||
if (ClearedSystem.Count == 0)
|
||||
list.Add("None.");
|
||||
|
||||
list.Add("");
|
||||
list.Add("Work:");
|
||||
list.Add("=====");
|
||||
if (WorkChanged.Count == 0)
|
||||
list.Add("None.");
|
||||
list.AddRange(wt);
|
||||
|
||||
return list;
|
||||
}
|
||||
|
||||
private readonly record struct FlagSummary(int Raw)
|
||||
{
|
||||
public override string ToString() => $"{Raw:0000}\t{false}";
|
||||
}
|
||||
|
||||
private readonly record struct WorkSummary(int Raw, string Text)
|
||||
{
|
||||
public override string ToString() => $"{Raw:000}\t{Text}";
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,6 +1,8 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Diagnostics;
|
||||
using System.Diagnostics.CodeAnalysis;
|
||||
using static PKHeX.Core.MessageStrings;
|
||||
|
||||
namespace PKHeX.Core
|
||||
{
|
||||
|
@ -119,19 +121,31 @@ namespace PKHeX.Core
|
|||
/// <param name="after">Data after the event was triggered</param>
|
||||
/// <param name="changed"><see cref="EventVar.RawIndex"/> values that changed</param>
|
||||
/// <param name="changes">Summary of the <see cref="EventWork{T}"/> value change</param>
|
||||
public static void DiffSavesWork<T>(IEventWork<T> before, IEventWork<T> after, List<int> changed, List<string> changes)
|
||||
public static void DiffSavesWork<T>(IEventWork<T> before, IEventWork<T> after, List<int> changed, List<string> changes) where T : unmanaged, IEquatable<T>
|
||||
{
|
||||
int max = before.CountWork;
|
||||
for (int i = 0; i < max; i++)
|
||||
{
|
||||
var b = before.GetWork(i);
|
||||
var a = after.GetWork(i);
|
||||
if (b is null || b.Equals(a))
|
||||
if (b.Equals(a))
|
||||
continue;
|
||||
|
||||
changed.Add(i);
|
||||
changes.Add($"{b} => {a}");
|
||||
}
|
||||
}
|
||||
|
||||
public static bool SanityCheckSaveInfo<T>(T s1, T s2, [NotNullWhen(false)] out string? Message) where T : SaveFile
|
||||
{
|
||||
if (s1.GetType() != s2.GetType())
|
||||
{ Message = string.Format(MsgSaveDifferentTypes, $"S1: {s1.GetType().Name}", $"S2: {s2.GetType().Name}"); return false; }
|
||||
|
||||
if (s1.Version != s2.Version)
|
||||
{ Message = string.Format(MsgSaveDifferentVersions, $"S1: {s1.Version}", $"S2: {s2.Version}"); return false; }
|
||||
|
||||
Message = null;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
61
PKHeX.Core/Saves/IEventFlagArray.cs
Normal file
61
PKHeX.Core/Saves/IEventFlagArray.cs
Normal file
|
@ -0,0 +1,61 @@
|
|||
using System;
|
||||
|
||||
namespace PKHeX.Core;
|
||||
|
||||
public interface IEventFlagArray
|
||||
{
|
||||
int EventFlagCount { get; }
|
||||
bool GetEventFlag(int flagNumber);
|
||||
void SetEventFlag(int flagNumber, bool value);
|
||||
}
|
||||
|
||||
public interface IEventFlag37 : IEventFlagArray, IEventWorkArray<ushort> { }
|
||||
|
||||
public static class EventFlagArrayExtensions
|
||||
{
|
||||
/// <summary> All Event Flag values for the savegame </summary>
|
||||
public static bool[] GetEventFlags(this IEventFlagArray source)
|
||||
{
|
||||
var result = new bool[source.EventFlagCount];
|
||||
for (int i = 0; i < result.Length; i++)
|
||||
result[i] = source.GetEventFlag(i);
|
||||
return result;
|
||||
}
|
||||
|
||||
/// <summary> All Event Flag values for the savegame </summary>
|
||||
public static void SetEventFlags(this IEventFlagArray source, ReadOnlySpan<bool> value)
|
||||
{
|
||||
if (value.Length != source.EventFlagCount)
|
||||
return;
|
||||
for (int i = 0; i < value.Length; i++)
|
||||
source.SetEventFlag(i, value[i]);
|
||||
}
|
||||
}
|
||||
|
||||
public interface IEventWorkArray<T> where T : unmanaged
|
||||
{
|
||||
public int EventWorkCount { get; }
|
||||
public T GetWork(int index);
|
||||
public void SetWork(int index, T value = default);
|
||||
}
|
||||
|
||||
public static class EventWorkArrayExtensions
|
||||
{
|
||||
/// <summary> All Event Constant values for the savegame </summary>
|
||||
public static T[] GetAllEventWork<T>(this IEventWorkArray<T> source) where T : unmanaged
|
||||
{
|
||||
var result = new T[source.EventWorkCount];
|
||||
for (int i = 0; i < result.Length; i++)
|
||||
result[i] = source.GetWork(i);
|
||||
return result;
|
||||
}
|
||||
|
||||
/// <summary> All Event Constant values for the savegame </summary>
|
||||
public static void SetAllEventWork<T>(this IEventWorkArray<T> source, ReadOnlySpan<T> value) where T : unmanaged
|
||||
{
|
||||
if (value.Length != source.EventWorkCount)
|
||||
return;
|
||||
for (int i = 0; i < value.Length; i++)
|
||||
source.SetWork(i, value[i]);
|
||||
}
|
||||
}
|
|
@ -7,7 +7,7 @@ namespace PKHeX.Core
|
|||
/// <summary>
|
||||
/// Generation 1 <see cref="SaveFile"/> object.
|
||||
/// </summary>
|
||||
public sealed class SAV1 : SaveFile, ILangDeviantSave
|
||||
public sealed class SAV1 : SaveFile, ILangDeviantSave, IEventFlagArray
|
||||
{
|
||||
protected internal override string ShortSummary => $"{OT} ({Version}) - {PlayTimeString}";
|
||||
public override string Extension => ".sav";
|
||||
|
@ -115,8 +115,6 @@ namespace PKHeX.Core
|
|||
daycareList.Write().CopyTo(Data, GetPartyOffset(7));
|
||||
DaycareOffset = GetPartyOffset(7);
|
||||
|
||||
EventFlag = Offsets.EventFlag;
|
||||
|
||||
// Enable Pokedex editing
|
||||
PokeDex = 0;
|
||||
}
|
||||
|
@ -125,8 +123,20 @@ namespace PKHeX.Core
|
|||
private readonly SAV1Offsets Offsets;
|
||||
|
||||
// Event Flags
|
||||
protected override int EventFlagMax => 0xA00; // 320 * 8
|
||||
protected override int EventConstMax => 0;
|
||||
public int EventFlagCount => 0xA00; // 320 * 8
|
||||
public bool GetEventFlag(int flagNumber)
|
||||
{
|
||||
if ((uint)flagNumber >= EventFlagCount)
|
||||
throw new ArgumentOutOfRangeException(nameof(flagNumber), $"Event Flag to get ({flagNumber}) is greater than max ({EventFlagCount}).");
|
||||
return GetFlag(Offsets.EventFlag + (flagNumber >> 3), flagNumber & 7);
|
||||
}
|
||||
|
||||
public void SetEventFlag(int flagNumber, bool value)
|
||||
{
|
||||
if ((uint)flagNumber >= EventFlagCount)
|
||||
throw new ArgumentOutOfRangeException(nameof(flagNumber), $"Event Flag to set ({flagNumber}) is greater than max ({EventFlagCount}).");
|
||||
SetFlag(Offsets.EventFlag + (flagNumber >> 3), flagNumber & 7, value);
|
||||
}
|
||||
|
||||
protected override byte[] GetFinalData()
|
||||
{
|
||||
|
|
|
@ -7,7 +7,7 @@ namespace PKHeX.Core
|
|||
/// <summary>
|
||||
/// Generation 2 <see cref="SaveFile"/> object.
|
||||
/// </summary>
|
||||
public sealed class SAV2 : SaveFile, ILangDeviantSave
|
||||
public sealed class SAV2 : SaveFile, ILangDeviantSave, IEventFlagArray, IEventWorkArray<byte>
|
||||
{
|
||||
protected internal override string ShortSummary => $"{OT} ({Version}) - {PlayTimeString}";
|
||||
public override string Extension => ".sav";
|
||||
|
@ -140,10 +140,11 @@ namespace PKHeX.Core
|
|||
|
||||
// Enable Pokedex editing
|
||||
PokeDex = 0;
|
||||
EventFlag = Offsets.EventFlag;
|
||||
EventConst = Offsets.EventConst;
|
||||
}
|
||||
|
||||
private int EventFlag => Offsets.EventFlag;
|
||||
private int EventWork => Offsets.EventWork;
|
||||
|
||||
private PK2 ReadPKMFromOffset(int offset)
|
||||
{
|
||||
var stringLength = StringLength;
|
||||
|
@ -272,8 +273,8 @@ namespace PKHeX.Core
|
|||
|
||||
public override bool IsPKMPresent(ReadOnlySpan<byte> data) => PKX.IsPKMPresentGB(data);
|
||||
|
||||
protected override int EventConstMax => 0x100;
|
||||
protected override int EventFlagMax => 2000;
|
||||
public int EventWorkCount => 0x100;
|
||||
public int EventFlagCount => 2000;
|
||||
|
||||
public override int BoxCount => Japanese ? 9 : 14;
|
||||
public override int MaxEV => 65535;
|
||||
|
@ -679,25 +680,20 @@ namespace PKHeX.Core
|
|||
SetFlag(region + ofs, bit & 7, value);
|
||||
}
|
||||
|
||||
/// <summary>All Event Constant values for the save file</summary>
|
||||
/// <remarks>These are all bytes</remarks>
|
||||
public override ushort[] GetEventConsts()
|
||||
public byte GetWork(int index) => Data[EventWork + index];
|
||||
public void SetWork(int index, byte value) => Data[EventWork + index] = value;
|
||||
public bool GetEventFlag(int flagNumber)
|
||||
{
|
||||
ushort[] Constants = new ushort[EventConstMax];
|
||||
for (int i = 0; i < Constants.Length; i++)
|
||||
Constants[i] = Data[EventConst + i];
|
||||
return Constants;
|
||||
if ((uint)flagNumber >= EventFlagCount)
|
||||
throw new ArgumentOutOfRangeException(nameof(flagNumber), $"Event Flag to get ({flagNumber}) is greater than max ({EventFlagCount}).");
|
||||
return GetFlag(EventFlag + (flagNumber >> 3), flagNumber & 7);
|
||||
}
|
||||
|
||||
/// <summary>All Event Constant values for the save file</summary>
|
||||
/// <remarks>These are all bytes</remarks>
|
||||
public override void SetEventConsts(ReadOnlySpan<ushort> value)
|
||||
public void SetEventFlag(int flagNumber, bool value)
|
||||
{
|
||||
if (value.Length != EventConstMax)
|
||||
return;
|
||||
|
||||
for (int i = 0; i < value.Length; i++)
|
||||
Data[EventConst + i] = Math.Min(byte.MaxValue, (byte)value[i]);
|
||||
if ((uint)flagNumber >= EventFlagCount)
|
||||
throw new ArgumentOutOfRangeException(nameof(flagNumber), $"Event Flag to set ({flagNumber}) is greater than max ({EventFlagCount}).");
|
||||
SetFlag(EventFlag + (flagNumber >> 3), flagNumber & 7, value);
|
||||
}
|
||||
|
||||
// Misc
|
||||
|
|
|
@ -8,7 +8,7 @@ namespace PKHeX.Core
|
|||
/// <summary>
|
||||
/// Generation 3 <see cref="SaveFile"/> object.
|
||||
/// </summary>
|
||||
public abstract class SAV3 : SaveFile, ILangDeviantSave
|
||||
public abstract class SAV3 : SaveFile, ILangDeviantSave, IEventFlag37
|
||||
{
|
||||
protected internal sealed override string ShortSummary => $"{OT} ({Version}) - {PlayTimeString}";
|
||||
public sealed override string Extension => ".sav";
|
||||
|
@ -148,6 +148,11 @@ namespace PKHeX.Core
|
|||
public sealed override int MaxBallID => Legal.MaxBallID_3;
|
||||
public sealed override int MaxGameID => Legal.MaxGameID_3;
|
||||
|
||||
public abstract int EventFlagCount { get; }
|
||||
public abstract int EventWorkCount { get; }
|
||||
protected abstract int EventFlag { get; }
|
||||
protected abstract int EventWork { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Force loads a new <see cref="SAV3"/> object to the requested <see cref="version"/>.
|
||||
/// </summary>
|
||||
|
@ -324,47 +329,28 @@ namespace PKHeX.Core
|
|||
set => Small[0x12] = (byte)value;
|
||||
}
|
||||
|
||||
public sealed override bool GetEventFlag(int flagNumber)
|
||||
#region Event Flag/Event Work
|
||||
public bool GetEventFlag(int flagNumber)
|
||||
{
|
||||
if (flagNumber >= EventFlagMax)
|
||||
throw new ArgumentOutOfRangeException(nameof(flagNumber), $"Event Flag to get ({flagNumber}) is greater than max ({EventFlagMax}).");
|
||||
|
||||
var start = EventFlag;
|
||||
return GetFlag(start + (flagNumber >> 3), flagNumber & 7);
|
||||
if ((uint)flagNumber >= EventFlagCount)
|
||||
throw new ArgumentOutOfRangeException(nameof(flagNumber), $"Event Flag to get ({flagNumber}) is greater than max ({EventFlagCount}).");
|
||||
return GetFlag(EventFlag + (flagNumber >> 3), flagNumber & 7);
|
||||
}
|
||||
|
||||
public sealed override void SetEventFlag(int flagNumber, bool value)
|
||||
public void SetEventFlag(int flagNumber, bool value)
|
||||
{
|
||||
if (flagNumber >= EventFlagMax)
|
||||
throw new ArgumentOutOfRangeException(nameof(flagNumber), $"Event Flag to set ({flagNumber}) is greater than max ({EventFlagMax}).");
|
||||
|
||||
var start = EventFlag;
|
||||
SetFlag(start + (flagNumber >> 3), flagNumber & 7, value);
|
||||
if ((uint)flagNumber >= EventFlagCount)
|
||||
throw new ArgumentOutOfRangeException(nameof(flagNumber), $"Event Flag to set ({flagNumber}) is greater than max ({EventFlagCount}).");
|
||||
SetFlag(EventFlag + (flagNumber >> 3), flagNumber & 7, value);
|
||||
}
|
||||
|
||||
public ushort GetWork(int index) => ReadUInt16LittleEndian(Large.AsSpan(EventWork + (index * 2)));
|
||||
public void SetWork(int index, ushort value) => WriteUInt16LittleEndian(Large.AsSpan(EventWork)[(index * 2)..], value);
|
||||
#endregion
|
||||
|
||||
public sealed override bool GetFlag(int offset, int bitIndex) => FlagUtil.GetFlag(Large, offset, bitIndex);
|
||||
public sealed override void SetFlag(int offset, int bitIndex, bool value) => FlagUtil.SetFlag(Large, offset, bitIndex, value);
|
||||
|
||||
public ushort GetEventConst(int index) => ReadUInt16LittleEndian(Large.AsSpan(EventConst + (index * 2)));
|
||||
public void SetEventConst(int index, ushort value) => WriteUInt16LittleEndian(Large.AsSpan(EventConst + (index * 2)), value);
|
||||
|
||||
public sealed override ushort[] GetEventConsts()
|
||||
{
|
||||
ushort[] Constants = new ushort[EventConstMax];
|
||||
for (int i = 0; i < Constants.Length; i++)
|
||||
Constants[i] = GetEventConst(i);
|
||||
return Constants;
|
||||
}
|
||||
|
||||
public sealed override void SetEventConsts(ReadOnlySpan<ushort> value)
|
||||
{
|
||||
if (value.Length != EventConstMax)
|
||||
return;
|
||||
|
||||
for (int i = 0; i < value.Length; i++)
|
||||
SetEventConst(i, value[i]);
|
||||
}
|
||||
|
||||
protected abstract int BadgeFlagStart { get; }
|
||||
public abstract uint Coin { get; set; }
|
||||
|
||||
|
|
|
@ -15,8 +15,8 @@ namespace PKHeX.Core
|
|||
public override GameVersion Version { get => GameVersion.E; protected set { } }
|
||||
public override PersonalTable Personal => PersonalTable.E;
|
||||
|
||||
protected override int EventFlagMax => 8 * 300;
|
||||
protected override int EventConstMax => 0x100;
|
||||
public override int EventFlagCount => 8 * 300;
|
||||
public override int EventWorkCount => 0x100;
|
||||
protected override int DaycareSlotSize => SIZE_STORED + 0x3C; // 0x38 mail + 4 exp
|
||||
public override int DaycareSeedSize => 8; // 32bit
|
||||
protected override int EggEventFlag => 0x86;
|
||||
|
@ -25,14 +25,15 @@ namespace PKHeX.Core
|
|||
public SAV3E(byte[] data) : base(data) => Initialize();
|
||||
public SAV3E(bool japanese = false) : base(japanese) => Initialize();
|
||||
|
||||
protected override int EventFlag => 0x1270;
|
||||
protected override int EventWork => 0x139C;
|
||||
|
||||
private void Initialize()
|
||||
{
|
||||
// small
|
||||
PokeDex = 0x18;
|
||||
|
||||
// large
|
||||
EventFlag = 0x1270;
|
||||
EventConst = 0x139C;
|
||||
DaycareOffset = 0x3030;
|
||||
|
||||
// storage
|
||||
|
@ -48,7 +49,7 @@ namespace PKHeX.Core
|
|||
PokedexMode = value ? (byte)1 : (byte)0; // mode
|
||||
PokedexNationalMagicRSE = value ? PokedexNationalUnlockRSE : (byte)0; // magic
|
||||
SetEventFlag(0x896, value);
|
||||
SetEventConst(0x46, PokedexNationalUnlockWorkRSE);
|
||||
SetWork(0x46, PokedexNationalUnlockWorkRSE);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -15,8 +15,8 @@ namespace PKHeX.Core
|
|||
private PersonalTable _personal = PersonalTable.FR;
|
||||
public override PersonalTable Personal => _personal;
|
||||
|
||||
protected override int EventFlagMax => 8 * 288;
|
||||
protected override int EventConstMax => 0x100;
|
||||
public override int EventFlagCount => 8 * 288;
|
||||
public override int EventWorkCount => 0x100;
|
||||
protected override int DaycareSlotSize => SIZE_STORED + 0x3C; // 0x38 mail + 4 exp
|
||||
public override int DaycareSeedSize => 4; // 16bit
|
||||
protected override int EggEventFlag => 0x266;
|
||||
|
@ -34,14 +34,15 @@ namespace PKHeX.Core
|
|||
WriteUInt32LittleEndian(Small.AsSpan(0xAC), 1);
|
||||
}
|
||||
|
||||
protected override int EventFlag => 0xEE0;
|
||||
protected override int EventWork => 0x1000;
|
||||
|
||||
private void Initialize()
|
||||
{
|
||||
// small
|
||||
PokeDex = 0x18;
|
||||
|
||||
// large
|
||||
EventFlag = 0xEE0;
|
||||
EventConst = 0x1000;
|
||||
DaycareOffset = 0x2F80;
|
||||
|
||||
// storage
|
||||
|
@ -65,7 +66,7 @@ namespace PKHeX.Core
|
|||
{
|
||||
PokedexNationalMagicFRLG = value ? PokedexNationalUnlockFRLG : (byte)0; // magic
|
||||
SetEventFlag(0x840, value);
|
||||
SetEventConst(0x4E, PokedexNationalUnlockWorkFRLG);
|
||||
SetWork(0x4E, PokedexNationalUnlockWorkFRLG);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -15,8 +15,8 @@ namespace PKHeX.Core
|
|||
public override GameVersion Version { get => GameVersion.RS; protected set { } }
|
||||
public override PersonalTable Personal => PersonalTable.RS;
|
||||
|
||||
protected override int EventFlagMax => 8 * 288;
|
||||
protected override int EventConstMax => 0x100;
|
||||
public override int EventFlagCount => 8 * 288;
|
||||
public override int EventWorkCount => 0x100;
|
||||
protected override int DaycareSlotSize => SIZE_STORED;
|
||||
public override int DaycareSeedSize => 4; // 16bit
|
||||
protected override int EggEventFlag => 0x86;
|
||||
|
@ -25,14 +25,15 @@ namespace PKHeX.Core
|
|||
public SAV3RS(byte[] data) : base(data) => Initialize();
|
||||
public SAV3RS(bool japanese = false) : base(japanese) => Initialize();
|
||||
|
||||
protected override int EventFlag => 0x1220;
|
||||
protected override int EventWork => 0x1340;
|
||||
|
||||
private void Initialize()
|
||||
{
|
||||
// small
|
||||
PokeDex = 0x18;
|
||||
|
||||
// large
|
||||
EventFlag = 0x1220;
|
||||
EventConst = 0x1340;
|
||||
DaycareOffset = 0x2F9C;
|
||||
|
||||
// storage
|
||||
|
@ -48,7 +49,7 @@ namespace PKHeX.Core
|
|||
PokedexMode = value ? (byte)1 : (byte)0; // mode
|
||||
PokedexNationalMagicRSE = value ? PokedexNationalUnlockRSE : (byte)0; // magic
|
||||
SetEventFlag(0x836, value);
|
||||
SetEventConst(0x46, PokedexNationalUnlockWorkRSE);
|
||||
SetWork(0x46, PokedexNationalUnlockWorkRSE);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -10,7 +10,7 @@ namespace PKHeX.Core
|
|||
/// <remarks>
|
||||
/// Storage data is stored in one contiguous block, and the remaining data is stored in another block.
|
||||
/// </remarks>
|
||||
public abstract class SAV4 : SaveFile
|
||||
public abstract class SAV4 : SaveFile, IEventFlag37
|
||||
{
|
||||
protected internal override string ShortSummary => $"{OT} ({Version}) - {PlayTimeString}";
|
||||
public sealed override string Extension => ".sav";
|
||||
|
@ -29,6 +29,8 @@ namespace PKHeX.Core
|
|||
protected abstract int StorageStart { get; }
|
||||
public abstract Zukan4 Dex { get; }
|
||||
|
||||
protected abstract int EventFlag { get; }
|
||||
protected abstract int EventWork { get; }
|
||||
public sealed override bool GetFlag(int offset, int bitIndex) => FlagUtil.GetFlag(General, offset, bitIndex);
|
||||
public sealed override void SetFlag(int offset, int bitIndex, bool value) => FlagUtil.SetFlag(General, offset, bitIndex, value);
|
||||
|
||||
|
@ -77,8 +79,8 @@ namespace PKHeX.Core
|
|||
public sealed override int BoxCount => 18;
|
||||
public sealed override int MaxEV => 255;
|
||||
public sealed override int Generation => 4;
|
||||
protected sealed override int EventFlagMax => 0xB60; // 2912
|
||||
protected sealed override int EventConstMax => (EventFlag - EventConst) >> 1;
|
||||
public int EventFlagCount => 0xB60; // 2912
|
||||
public int EventWorkCount => (EventFlag - EventWork) >> 1;
|
||||
protected sealed override int GiftCountMax => 11;
|
||||
public sealed override int OTLength => 7;
|
||||
public sealed override int NickLength => 10;
|
||||
|
@ -481,31 +483,25 @@ namespace PKHeX.Core
|
|||
return StringConverter4.SetString(destBuffer, value, maxLength, option);
|
||||
}
|
||||
|
||||
/// <summary> All Event Constant values for the savegame </summary>
|
||||
public sealed override ushort[] GetEventConsts()
|
||||
#region Event Flag/Event Work
|
||||
public bool GetEventFlag(int flagNumber)
|
||||
{
|
||||
if (EventConstMax <= 0)
|
||||
return Array.Empty<ushort>();
|
||||
|
||||
ushort[] Constants = new ushort[EventConstMax];
|
||||
for (int i = 0; i < Constants.Length; i++)
|
||||
Constants[i] = ReadUInt16LittleEndian(General.AsSpan(EventConst + (i * 2)));
|
||||
return Constants;
|
||||
if ((uint)flagNumber >= EventFlagCount)
|
||||
throw new ArgumentOutOfRangeException(nameof(flagNumber), $"Event Flag to get ({flagNumber}) is greater than max ({EventFlagCount}).");
|
||||
return GetFlag(EventFlag + (flagNumber >> 3), flagNumber & 7);
|
||||
}
|
||||
|
||||
/// <summary> All Event Constant values for the savegame </summary>
|
||||
public sealed override void SetEventConsts(ReadOnlySpan<ushort> value)
|
||||
public void SetEventFlag(int flagNumber, bool value)
|
||||
{
|
||||
if (EventConstMax <= 0)
|
||||
return;
|
||||
if (value.Length != EventConstMax)
|
||||
return;
|
||||
|
||||
var span = General.AsSpan(EventConst);
|
||||
for (int i = 0; i < value.Length; i++)
|
||||
WriteUInt16LittleEndian(span[(i * 2)..], value[i]);
|
||||
if ((uint)flagNumber >= EventFlagCount)
|
||||
throw new ArgumentOutOfRangeException(nameof(flagNumber), $"Event Flag to set ({flagNumber}) is greater than max ({EventFlagCount}).");
|
||||
SetFlag(EventFlag + (flagNumber >> 3), flagNumber & 7, value);
|
||||
}
|
||||
|
||||
public ushort GetWork(int index) => ReadUInt16LittleEndian(General.AsSpan(EventWork + (index * 2)));
|
||||
public void SetWork(int index, ushort value) => WriteUInt16LittleEndian(General.AsSpan(EventWork)[(index * 2)..], value);
|
||||
#endregion
|
||||
|
||||
// Seals
|
||||
private const byte SealMaxCount = 99;
|
||||
|
||||
|
|
|
@ -38,6 +38,9 @@ namespace PKHeX.Core
|
|||
GetSAVOffsets();
|
||||
}
|
||||
|
||||
protected override int EventWork => 0xD9C;
|
||||
protected override int EventFlag => 0xFDC;
|
||||
|
||||
private void GetSAVOffsets()
|
||||
{
|
||||
AdventureInfo = 0;
|
||||
|
@ -47,8 +50,6 @@ namespace PKHeX.Core
|
|||
WondercardFlags = 0xA6D0;
|
||||
WondercardData = 0xA7fC;
|
||||
|
||||
EventConst = 0xD9C;
|
||||
EventFlag = 0xFDC;
|
||||
DaycareOffset = 0x141C;
|
||||
OFS_HONEY = 0x72E4;
|
||||
|
||||
|
|
|
@ -40,6 +40,9 @@ namespace PKHeX.Core
|
|||
GetSAVOffsets();
|
||||
}
|
||||
|
||||
protected override int EventWork => 0xDE4;
|
||||
protected override int EventFlag => 0x10C4;
|
||||
|
||||
private void GetSAVOffsets()
|
||||
{
|
||||
AdventureInfo = 0;
|
||||
|
@ -49,8 +52,6 @@ namespace PKHeX.Core
|
|||
WondercardFlags = 0x9D3C;
|
||||
WondercardData = 0x9E3C;
|
||||
|
||||
EventConst = 0xDE4;
|
||||
EventFlag = 0x10C4;
|
||||
DaycareOffset = 0x15FC;
|
||||
Seal = 0x4E20;
|
||||
|
||||
|
|
|
@ -37,6 +37,9 @@ namespace PKHeX.Core
|
|||
GetSAVOffsets();
|
||||
}
|
||||
|
||||
protected override int EventWork => 0xDAC;
|
||||
protected override int EventFlag => 0xFEC;
|
||||
|
||||
private void GetSAVOffsets()
|
||||
{
|
||||
AdventureInfo = 0;
|
||||
|
@ -46,8 +49,6 @@ namespace PKHeX.Core
|
|||
WondercardFlags = 0xB4C0;
|
||||
WondercardData = 0xB5C0;
|
||||
|
||||
EventConst = 0xDAC;
|
||||
EventFlag = 0xFEC;
|
||||
DaycareOffset = 0x1654;
|
||||
OFS_HONEY = 0x7F38;
|
||||
|
||||
|
|
|
@ -7,7 +7,7 @@ namespace PKHeX.Core
|
|||
/// <summary>
|
||||
/// Generation 5 <see cref="SaveFile"/> object.
|
||||
/// </summary>
|
||||
public abstract class SAV5 : SaveFile, ISaveBlock5BW
|
||||
public abstract class SAV5 : SaveFile, ISaveBlock5BW, IEventFlag37
|
||||
{
|
||||
protected override PKM GetPKM(byte[] data) => new PK5(data);
|
||||
protected override byte[] DecryptPKM(byte[] data) => PokeCrypto.DecryptArray45(data);
|
||||
|
@ -27,6 +27,10 @@ namespace PKHeX.Core
|
|||
public override int OTLength => 7;
|
||||
public override int NickLength => 10;
|
||||
protected override int GiftCountMax => 12;
|
||||
public abstract int EventFlagCount { get; }
|
||||
public abstract int EventWorkCount { get; }
|
||||
protected abstract int EventFlag { get; }
|
||||
protected abstract int EventWork { get; }
|
||||
|
||||
public override int MaxMoveID => Legal.MaxMoveID_5;
|
||||
public override int MaxSpeciesID => Legal.MaxSpeciesID_5;
|
||||
|
@ -142,6 +146,23 @@ namespace PKHeX.Core
|
|||
return StringConverter5.SetString(destBuffer, value, maxLength, option);
|
||||
}
|
||||
|
||||
public bool GetEventFlag(int flagNumber)
|
||||
{
|
||||
if ((uint)flagNumber >= EventFlagCount)
|
||||
throw new ArgumentOutOfRangeException(nameof(flagNumber), $"Event Flag to get ({flagNumber}) is greater than max ({EventFlagCount}).");
|
||||
return GetFlag(EventFlag + (flagNumber >> 3), flagNumber & 7);
|
||||
}
|
||||
|
||||
public void SetEventFlag(int flagNumber, bool value)
|
||||
{
|
||||
if ((uint)flagNumber >= EventFlagCount)
|
||||
throw new ArgumentOutOfRangeException(nameof(flagNumber), $"Event Flag to set ({flagNumber}) is greater than max ({EventFlagCount}).");
|
||||
SetFlag(EventFlag + (flagNumber >> 3), flagNumber & 7, value);
|
||||
}
|
||||
|
||||
public ushort GetWork(int index) => ReadUInt16LittleEndian(Data.AsSpan(EventWork + (index * 2)));
|
||||
public void SetWork(int index, ushort value) => WriteUInt16LittleEndian(Data.AsSpan(EventWork)[(index * 2)..], value);
|
||||
|
||||
// DLC
|
||||
private int CGearSkinInfoOffset => CGearInfoOffset + (this is SAV5B2W2 ? 0x10 : 0) + 0x24;
|
||||
|
||||
|
|
|
@ -24,15 +24,15 @@ namespace PKHeX.Core
|
|||
public override PersonalTable Personal => PersonalTable.B2W2;
|
||||
public SaveBlockAccessor5B2W2 Blocks { get; }
|
||||
protected override SaveFile CloneInternal() => new SAV5B2W2((byte[]) Data.Clone());
|
||||
protected override int EventConstMax => 0x1AF; // this doesn't seem right?
|
||||
protected override int EventFlagMax => 0xBF8;
|
||||
public override int EventWorkCount => 0x1AF; // this doesn't seem right?
|
||||
public override int EventFlagCount => 0xBF8;
|
||||
protected override int EventWork => 0x1FF00;
|
||||
protected override int EventFlag => EventWork + 0x35E;
|
||||
public override int MaxItemID => Legal.MaxItemID_5_B2W2;
|
||||
|
||||
private void Initialize()
|
||||
{
|
||||
BattleBoxOffset = 0x20900;
|
||||
EventConst = 0x1FF00;
|
||||
EventFlag = EventConst + 0x35E;
|
||||
CGearInfoOffset = 0x1C000;
|
||||
CGearDataOffset = 0x52800;
|
||||
EntreeForestOffset = 0x22A00;
|
||||
|
|
|
@ -23,15 +23,15 @@ namespace PKHeX.Core
|
|||
public override PersonalTable Personal => PersonalTable.BW;
|
||||
public SaveBlockAccessor5BW Blocks { get; }
|
||||
protected override SaveFile CloneInternal() => new SAV5BW((byte[])Data.Clone());
|
||||
protected override int EventConstMax => 0x13E;
|
||||
protected override int EventFlagMax => 0xB60;
|
||||
public override int EventWorkCount => 0x13E;
|
||||
public override int EventFlagCount => 0xB60;
|
||||
protected override int EventWork => 0x20100;
|
||||
protected override int EventFlag => EventWork + 0x27C;
|
||||
public override int MaxItemID => Legal.MaxItemID_5_BW;
|
||||
|
||||
private void Initialize()
|
||||
{
|
||||
BattleBoxOffset = 0x20A00;
|
||||
EventConst = 0x20100;
|
||||
EventFlag = EventConst + 0x27C;
|
||||
CGearInfoOffset = 0x1C000;
|
||||
CGearDataOffset = 0x52000;
|
||||
EntreeForestOffset = 0x22C00;
|
||||
|
|
|
@ -1,12 +1,13 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using static System.Buffers.Binary.BinaryPrimitives;
|
||||
|
||||
namespace PKHeX.Core
|
||||
{
|
||||
/// <summary>
|
||||
/// Generation 6 <see cref="SaveFile"/> object.
|
||||
/// </summary>
|
||||
public abstract class SAV6 : SAV_BEEF, ITrainerStatRecord, ISaveBlock6Core, IRegionOrigin, IGameSync
|
||||
public abstract class SAV6 : SAV_BEEF, ITrainerStatRecord, ISaveBlock6Core, IRegionOrigin, IGameSync, IEventFlag37
|
||||
{
|
||||
// Save Data Attributes
|
||||
protected internal override string ShortSummary => $"{OT} ({Version}) - {Played.LastSavedTime}";
|
||||
|
@ -26,8 +27,10 @@ namespace PKHeX.Core
|
|||
public override int Generation => 6;
|
||||
protected override int GiftCountMax => 24;
|
||||
protected override int GiftFlagMax => 0x100 * 8;
|
||||
protected override int EventFlagMax => 8 * 0x1A0;
|
||||
protected override int EventConstMax => (EventFlag - EventConst) / sizeof(ushort);
|
||||
public int EventFlagCount => 8 * 0x1A0;
|
||||
public int EventWorkCount => (EventFlag - EventWork) / sizeof(ushort);
|
||||
protected abstract int EventFlag { get; }
|
||||
protected abstract int EventWork { get; }
|
||||
public override int OTLength => 12;
|
||||
public override int NickLength => 12;
|
||||
|
||||
|
@ -190,5 +193,22 @@ namespace PKHeX.Core
|
|||
public abstract PlayTime6 Played { get; }
|
||||
public abstract MyStatus6 Status { get; }
|
||||
public abstract RecordBlock6 Records { get; }
|
||||
|
||||
public bool GetEventFlag(int flagNumber)
|
||||
{
|
||||
if ((uint)flagNumber >= EventFlagCount)
|
||||
throw new ArgumentOutOfRangeException(nameof(flagNumber), $"Event Flag to get ({flagNumber}) is greater than max ({EventFlagCount}).");
|
||||
return GetFlag(EventFlag + (flagNumber >> 3), flagNumber & 7);
|
||||
}
|
||||
|
||||
public void SetEventFlag(int flagNumber, bool value)
|
||||
{
|
||||
if ((uint)flagNumber >= EventFlagCount)
|
||||
throw new ArgumentOutOfRangeException(nameof(flagNumber), $"Event Flag to set ({flagNumber}) is greater than max ({EventFlagCount}).");
|
||||
SetFlag(EventFlag + (flagNumber >> 3), flagNumber & 7, value);
|
||||
}
|
||||
|
||||
public ushort GetWork(int index) => ReadUInt16LittleEndian(Data.AsSpan(EventWork + (index * 2)));
|
||||
public void SetWork(int index, ushort value) => WriteUInt16LittleEndian(Data.AsSpan(EventWork)[(index * 2)..], value);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -31,13 +31,15 @@ namespace PKHeX.Core
|
|||
public override int MaxItemID => Legal.MaxItemID_6_AO;
|
||||
public override int MaxAbilityID => Legal.MaxAbilityID_6_AO;
|
||||
|
||||
protected override int EventWork => 0x14A00;
|
||||
protected override int EventFlag => EventWork + 0x2F0;
|
||||
|
||||
private void Initialize()
|
||||
{
|
||||
PCLayout = 0x04400;
|
||||
BattleBoxOffset = 0x04A00;
|
||||
PSS = 0x05000;
|
||||
Party = 0x14200;
|
||||
EventConst = 0x14A00;
|
||||
PokeDex = 0x15000;
|
||||
HoF = 0x19E00;
|
||||
DaycareOffset = 0x1BC00;
|
||||
|
@ -46,7 +48,6 @@ namespace PKHeX.Core
|
|||
Box = 0x33000;
|
||||
JPEG = 0x67C00;
|
||||
|
||||
EventFlag = EventConst + 0x2F0;
|
||||
WondercardData = WondercardFlags + 0x100;
|
||||
}
|
||||
|
||||
|
|
|
@ -26,14 +26,13 @@ namespace PKHeX.Core
|
|||
public override int MaxMoveID => Legal.MaxMoveID_6_AO;
|
||||
public override int MaxItemID => Legal.MaxItemID_6_AO;
|
||||
public override int MaxAbilityID => Legal.MaxAbilityID_6_AO;
|
||||
protected override int EventWork => 0x04600;
|
||||
protected override int EventFlag => EventWork + 0x2F0;
|
||||
public SaveBlockAccessor6AODemo Blocks { get; }
|
||||
|
||||
private void Initialize()
|
||||
{
|
||||
Party = 0x03E00;
|
||||
EventConst = 0x04600;
|
||||
|
||||
EventFlag = EventConst + 0x2F0;
|
||||
}
|
||||
|
||||
public override GameVersion Version => Game switch
|
||||
|
|
|
@ -31,6 +31,9 @@ namespace PKHeX.Core
|
|||
public override int MaxItemID => Legal.MaxItemID_6_XY;
|
||||
public override int MaxAbilityID => Legal.MaxAbilityID_6_XY;
|
||||
|
||||
protected override int EventWork => 0x14A00;
|
||||
protected override int EventFlag => EventWork + 0x2F0;
|
||||
|
||||
private void Initialize()
|
||||
{
|
||||
// Enable Features
|
||||
|
@ -38,7 +41,6 @@ namespace PKHeX.Core
|
|||
PCLayout = 0x4400;
|
||||
BattleBoxOffset = 0x04A00;
|
||||
PSS = 0x05000;
|
||||
EventConst = 0x14A00;
|
||||
PokeDex = 0x15000;
|
||||
HoF = 0x19400;
|
||||
DaycareOffset = 0x1B200;
|
||||
|
@ -47,7 +49,6 @@ namespace PKHeX.Core
|
|||
Box = 0x22600;
|
||||
JPEG = 0x57200;
|
||||
|
||||
EventFlag = EventConst + 0x2F0;
|
||||
WondercardData = WondercardFlags + 0x100;
|
||||
|
||||
// Extra Viewable Slots
|
||||
|
|
|
@ -1,13 +1,14 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Diagnostics;
|
||||
using static System.Buffers.Binary.BinaryPrimitives;
|
||||
|
||||
namespace PKHeX.Core
|
||||
{
|
||||
/// <summary>
|
||||
/// Generation 7 <see cref="SaveFile"/> object.
|
||||
/// </summary>
|
||||
public abstract class SAV7 : SAV_BEEF, ITrainerStatRecord, ISaveBlock7Main, IRegionOrigin, IGameSync
|
||||
public abstract class SAV7 : SAV_BEEF, ITrainerStatRecord, ISaveBlock7Main, IRegionOrigin, IGameSync, IEventFlag37
|
||||
{
|
||||
// Save Data Attributes
|
||||
protected internal override string ShortSummary => $"{OT} ({Version}) - {Played.LastSavedTime}";
|
||||
|
@ -74,7 +75,10 @@ namespace PKHeX.Core
|
|||
public override int Generation => 7;
|
||||
protected override int GiftCountMax => 48;
|
||||
protected override int GiftFlagMax => 0x100 * 8;
|
||||
protected override int EventConstMax => 1000;
|
||||
public abstract int EventFlagCount { get; }
|
||||
public int EventWorkCount => 1000;
|
||||
private int EventWork => AllBlocks[05].Offset;
|
||||
private int EventFlag => EventWork + (EventWorkCount * 2); // After Event Const (u16)*n
|
||||
public override int OTLength => 12;
|
||||
public override int NickLength => 12;
|
||||
|
||||
|
@ -253,5 +257,21 @@ namespace PKHeX.Core
|
|||
|
||||
protected override bool[] MysteryGiftReceivedFlags { get => MysteryGift.MysteryGiftReceivedFlags; set => MysteryGift.MysteryGiftReceivedFlags = value; }
|
||||
protected override DataMysteryGift[] MysteryGiftCards { get => MysteryGift.MysteryGiftCards; set => MysteryGift.MysteryGiftCards = value; }
|
||||
public bool GetEventFlag(int flagNumber)
|
||||
{
|
||||
if ((uint)flagNumber >= EventFlagCount)
|
||||
throw new ArgumentOutOfRangeException(nameof(flagNumber), $"Event Flag to get ({flagNumber}) is greater than max ({EventFlagCount}).");
|
||||
return GetFlag(EventFlag + (flagNumber >> 3), flagNumber & 7);
|
||||
}
|
||||
|
||||
public void SetEventFlag(int flagNumber, bool value)
|
||||
{
|
||||
if ((uint)flagNumber >= EventFlagCount)
|
||||
throw new ArgumentOutOfRangeException(nameof(flagNumber), $"Event Flag to set ({flagNumber}) is greater than max ({EventFlagCount}).");
|
||||
SetFlag(EventFlag + (flagNumber >> 3), flagNumber & 7, value);
|
||||
}
|
||||
|
||||
public ushort GetWork(int index) => ReadUInt16LittleEndian(Data.AsSpan(EventWork + (index * 2)));
|
||||
public void SetWork(int index, ushort value) => WriteUInt16LittleEndian(Data.AsSpan(EventWork)[(index * 2)..], value);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -23,9 +23,7 @@ namespace PKHeX.Core
|
|||
private void Initialize()
|
||||
{
|
||||
Party = Blocks.BlockInfo[04].Offset;
|
||||
EventConst = Blocks.BlockInfo[05].Offset;
|
||||
PokeDex = Blocks.BlockInfo[06].Offset;
|
||||
EventFlag = EventConst + (EventConstMax * 2); // After Event Const (u16)*n
|
||||
|
||||
TeamSlots = Blocks.BoxLayout.TeamSlots;
|
||||
Box = Blocks.BlockInfo[14].Offset;
|
||||
|
@ -64,7 +62,7 @@ namespace PKHeX.Core
|
|||
public override HallOfFame7 Fame => Blocks.Fame;
|
||||
#endregion
|
||||
|
||||
protected override int EventFlagMax => 4000;
|
||||
public override int EventFlagCount => 4000;
|
||||
public override int MaxMoveID => Legal.MaxMoveID_7;
|
||||
public override int MaxSpeciesID => Legal.MaxSpeciesID_7;
|
||||
public override int MaxItemID => Legal.MaxItemID_7;
|
||||
|
|
|
@ -20,9 +20,7 @@ namespace PKHeX.Core
|
|||
private void Initialize()
|
||||
{
|
||||
Party = Blocks.BlockInfo[04].Offset;
|
||||
EventConst = Blocks.BlockInfo[05].Offset;
|
||||
PokeDex = Blocks.BlockInfo[06].Offset;
|
||||
EventFlag = EventConst + (EventConstMax * 2); // After Event Const (u16)*n
|
||||
|
||||
TeamSlots = Blocks.BoxLayout.TeamSlots;
|
||||
Box = Blocks.BlockInfo[14].Offset;
|
||||
|
@ -35,7 +33,7 @@ namespace PKHeX.Core
|
|||
public override PersonalTable Personal => PersonalTable.USUM;
|
||||
public override IReadOnlyList<ushort> HeldItems => Legal.HeldItems_USUM;
|
||||
protected override SaveFile CloneInternal() => new SAV7USUM((byte[])Data.Clone());
|
||||
protected override int EventFlagMax => 4960;
|
||||
public override int EventFlagCount => 4960;
|
||||
public override int MaxMoveID => Legal.MaxMoveID_7_USUM;
|
||||
public override int MaxSpeciesID => Legal.MaxSpeciesID_7_USUM;
|
||||
public override int MaxItemID => Legal.MaxItemID_7_USUM;
|
||||
|
|
|
@ -6,7 +6,7 @@ namespace PKHeX.Core
|
|||
/// <summary>
|
||||
/// Generation 7 <see cref="SaveFile"/> object for <see cref="GameVersion.GG"/> games.
|
||||
/// </summary>
|
||||
public sealed class SAV7b : SAV_BEEF, ISaveBlock7b, IGameSync
|
||||
public sealed class SAV7b : SAV_BEEF, ISaveBlock7b, IGameSync, IEventFlagArray
|
||||
{
|
||||
protected internal override string ShortSummary => $"{OT} ({Version}) - {Blocks.Played.LastSavedTime}";
|
||||
public override string Extension => ".bin";
|
||||
|
@ -44,7 +44,6 @@ namespace PKHeX.Core
|
|||
{
|
||||
Box = Blocks.GetBlockOffset(BelugaBlockIndex.PokeListPokemon);
|
||||
Party = Blocks.GetBlockOffset(BelugaBlockIndex.PokeListPokemon);
|
||||
EventFlag = Blocks.GetBlockOffset(BelugaBlockIndex.EventWork);
|
||||
PokeDex = Blocks.GetBlockOffset(BelugaBlockIndex.Zukan);
|
||||
|
||||
WondercardData = Blocks.GiftRecords.Offset;
|
||||
|
@ -79,11 +78,9 @@ namespace PKHeX.Core
|
|||
public override int NickLength => 12;
|
||||
protected override int GiftCountMax => 48;
|
||||
protected override int GiftFlagMax => 0x100 * 8;
|
||||
protected override int EventFlagMax => 4160; // 0xDC0 (true max may be up to 0x7F less. 23A8 starts u64 hashvals)
|
||||
protected override int EventConstMax => 1000;
|
||||
public int EventFlagCount => 4160; // 0xDC0 (true max may be up to 0x7F less. 23A8 starts u64 hashvals)
|
||||
|
||||
public override bool HasParty => false; // handled via team slots
|
||||
public override bool HasEvents => true; // advanced!
|
||||
|
||||
// BoxSlotCount => 1000 -- why couldn't this be a multiple of 30...
|
||||
public override int BoxSlotCount => 25;
|
||||
|
@ -160,7 +157,7 @@ namespace PKHeX.Core
|
|||
/// </summary>
|
||||
/// <param name="flagNumber">Event Flag to check</param>
|
||||
/// <returns>Flag is Set (true) or not Set (false)</returns>
|
||||
public override bool GetEventFlag(int flagNumber) => Blocks.EventWork.GetFlag(flagNumber);
|
||||
public bool GetEventFlag(int flagNumber) => Blocks.EventWork.GetFlag(flagNumber);
|
||||
|
||||
/// <summary>
|
||||
/// Sets the <see cref="bool"/> status of a desired Event Flag
|
||||
|
@ -168,7 +165,7 @@ namespace PKHeX.Core
|
|||
/// <param name="flagNumber">Event Flag to check</param>
|
||||
/// <param name="value">Event Flag status to set</param>
|
||||
/// <remarks>Flag is Set (true) or not Set (false)</remarks>
|
||||
public override void SetEventFlag(int flagNumber, bool value) => Blocks.EventWork.SetFlag(flagNumber, value);
|
||||
public void SetEventFlag(int flagNumber, bool value) => Blocks.EventWork.SetFlag(flagNumber, value);
|
||||
|
||||
protected override bool[] MysteryGiftReceivedFlags { get => Blocks.GiftRecords.GetFlags(); set => Blocks.GiftRecords.SetFlags(value); }
|
||||
protected override DataMysteryGift[] MysteryGiftCards { get => Blocks.GiftRecords.GetRecords(); set => Blocks.GiftRecords.SetRecords((WR7[])value); }
|
||||
|
|
|
@ -8,7 +8,7 @@ namespace PKHeX.Core
|
|||
/// <summary>
|
||||
/// Generation 8 <see cref="SaveFile"/> object for <see cref="GameVersion.BDSP"/> games.
|
||||
/// </summary>
|
||||
public sealed class SAV8BS : SaveFile, ISaveFileRevision, ITrainerStatRecord
|
||||
public sealed class SAV8BS : SaveFile, ISaveFileRevision, ITrainerStatRecord, IEventFlagArray, IEventWorkArray<int>
|
||||
{
|
||||
// Save Data Attributes
|
||||
protected internal override string ShortSummary => $"{OT} ({Version}) - {System.LastSavedTime}";
|
||||
|
@ -98,8 +98,6 @@ namespace PKHeX.Core
|
|||
TeamSlots = BoxLayout.TeamSlots;
|
||||
}
|
||||
|
||||
public override bool HasEvents => true;
|
||||
|
||||
// Configuration
|
||||
protected override int SIZE_STORED => PokeCrypto.SIZE_8STORED;
|
||||
protected override int SIZE_PARTY => PokeCrypto.SIZE_8PARTY;
|
||||
|
@ -111,7 +109,6 @@ namespace PKHeX.Core
|
|||
public override int MaxEV => 252;
|
||||
|
||||
public override int Generation => 8;
|
||||
protected override int EventConstMax => 500;
|
||||
public override PersonalTable Personal => PersonalTable.BDSP;
|
||||
public override int OTLength => 12;
|
||||
public override int NickLength => 12;
|
||||
|
@ -252,8 +249,9 @@ namespace PKHeX.Core
|
|||
return StringConverter8.SetString(destBuffer, value, maxLength, option);
|
||||
}
|
||||
|
||||
public override bool GetEventFlag(int flagNumber) => Work.GetFlag(flagNumber);
|
||||
public override void SetEventFlag(int flagNumber, bool value) => Work.SetFlag(flagNumber, value);
|
||||
public int EventFlagCount => FlagWork8b.COUNT_FLAG;
|
||||
public bool GetEventFlag(int flagNumber) => Work.GetFlag(flagNumber);
|
||||
public void SetEventFlag(int flagNumber, bool value) => Work.SetFlag(flagNumber, value);
|
||||
|
||||
// Player Information
|
||||
public override int TID { get => MyStatus.TID; set => MyStatus.TID = value; }
|
||||
|
@ -367,5 +365,9 @@ namespace PKHeX.Core
|
|||
public override string GetDaycareRNGSeed(int loc) => Daycare.DaycareSeed.ToString("X16");
|
||||
public override void SetDaycareRNGSeed(int loc, string seed) => Daycare.DaycareSeed = Util.GetHexValue64(seed);
|
||||
#endregion
|
||||
|
||||
public int EventWorkCount => FlagWork8b.COUNT_WORK;
|
||||
public int GetWork(int index) => Work.GetWork(index);
|
||||
public void SetWork(int index, int value = default) => Work.SetWork(index, value);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -148,7 +148,6 @@ public sealed class SAV8SWSH : SaveFile, ISaveBlock8SWSH, ITrainerStatRecord, IS
|
|||
public override int BoxCount => BoxLayout8.BoxCount;
|
||||
public override int MaxEV => 252;
|
||||
public override int Generation => 8;
|
||||
protected override int EventConstMax => 1000;
|
||||
public override int OTLength => 12;
|
||||
public override int NickLength => 12;
|
||||
protected override PKM GetPKM(byte[] data) => new PK8(data);
|
||||
|
|
|
@ -1,14 +1,13 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using static System.Buffers.Binary.BinaryPrimitives;
|
||||
|
||||
namespace PKHeX.Core
|
||||
{
|
||||
/// <summary>
|
||||
/// Base Class for Save Files
|
||||
/// </summary>
|
||||
public abstract class SaveFile : ITrainerInfo, IGameValueLimit, IBoxDetailWallpaper, IBoxDetailName, IGeneration
|
||||
public abstract class SaveFile : ITrainerInfo, IGameValueLimit, IBoxDetailWallpaper, IBoxDetailName, IGeneration, IVersion
|
||||
{
|
||||
// General Object Properties
|
||||
public byte[] Data;
|
||||
|
@ -99,86 +98,6 @@ namespace PKHeX.Core
|
|||
public virtual int MinGameID => 0;
|
||||
#endregion
|
||||
|
||||
#region Event Work
|
||||
public virtual bool HasEvents => GetEventFlags().Length != 0;
|
||||
protected virtual int EventFlagMax { get; } = int.MinValue;
|
||||
protected virtual int EventConstMax { get; } = int.MinValue;
|
||||
protected int EventFlag { get; set; } = int.MinValue;
|
||||
protected int EventConst { get; set; } = int.MinValue;
|
||||
|
||||
/// <summary> All Event Flag values for the savegame </summary>
|
||||
public bool[] GetEventFlags()
|
||||
{
|
||||
if (EventFlagMax < 0)
|
||||
return Array.Empty<bool>();
|
||||
|
||||
bool[] result = new bool[EventFlagMax];
|
||||
for (int i = 0; i < result.Length; i++)
|
||||
result[i] = GetEventFlag(i);
|
||||
return result;
|
||||
}
|
||||
|
||||
/// <summary> All Event Flag values for the savegame </summary>
|
||||
public void SetEventFlags(bool[] value)
|
||||
{
|
||||
if (EventFlagMax < 0)
|
||||
return;
|
||||
if (value.Length != EventFlagMax)
|
||||
return;
|
||||
for (int i = 0; i < value.Length; i++)
|
||||
SetEventFlag(i, value[i]);
|
||||
}
|
||||
|
||||
/// <summary> All Event Constant values for the savegame </summary>
|
||||
public virtual ushort[] GetEventConsts()
|
||||
{
|
||||
if (EventConstMax <= 0 || Data.Length == 0)
|
||||
return Array.Empty<ushort>();
|
||||
|
||||
ushort[] Constants = new ushort[EventConstMax];
|
||||
for (int i = 0; i < Constants.Length; i++)
|
||||
Constants[i] = ReadUInt16LittleEndian(Data.AsSpan(EventConst + (i * 2)));
|
||||
return Constants;
|
||||
}
|
||||
|
||||
/// <summary> All Event Constant values for the savegame </summary>
|
||||
public virtual void SetEventConsts(ReadOnlySpan<ushort> value)
|
||||
{
|
||||
if (EventConstMax <= 0)
|
||||
return;
|
||||
if (value.Length != EventConstMax)
|
||||
return;
|
||||
|
||||
var span = Data.AsSpan(EventConst);
|
||||
for (int i = 0; i < value.Length; i++)
|
||||
WriteUInt16LittleEndian(span[(i*2)..], value[i]);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets the <see cref="bool"/> status of a desired Event Flag
|
||||
/// </summary>
|
||||
/// <param name="flagNumber">Event Flag to check</param>
|
||||
/// <returns>Flag is Set (true) or not Set (false)</returns>
|
||||
public virtual bool GetEventFlag(int flagNumber)
|
||||
{
|
||||
if ((uint)flagNumber >= EventFlagMax)
|
||||
throw new ArgumentOutOfRangeException(nameof(flagNumber), $"Event Flag to get ({flagNumber}) is greater than max ({EventFlagMax}).");
|
||||
return GetFlag(EventFlag + (flagNumber >> 3), flagNumber & 7);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Sets the <see cref="bool"/> status of a desired Event Flag
|
||||
/// </summary>
|
||||
/// <param name="flagNumber">Event Flag to check</param>
|
||||
/// <param name="value">Event Flag status to set</param>
|
||||
/// <remarks>Flag is Set (true) or not Set (false)</remarks>
|
||||
public virtual void SetEventFlag(int flagNumber, bool value)
|
||||
{
|
||||
if ((uint)flagNumber >= EventFlagMax)
|
||||
throw new ArgumentOutOfRangeException(nameof(flagNumber), $"Event Flag to set ({flagNumber}) is greater than max ({EventFlagMax}).");
|
||||
SetFlag(EventFlag + (flagNumber >> 3), flagNumber & 7, value);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets the <see cref="bool"/> status of the Flag at the specified offset and index.
|
||||
/// </summary>
|
||||
|
@ -195,7 +114,6 @@ namespace PKHeX.Core
|
|||
/// <param name="value">Flag status to set</param>
|
||||
/// <remarks>Flag is Set (true) or not Set (false)</remarks>
|
||||
public virtual void SetFlag(int offset, int bitIndex, bool value) => FlagUtil.SetFlag(Data, offset, bitIndex, value);
|
||||
#endregion
|
||||
|
||||
public virtual IReadOnlyList<InventoryPouch> Inventory { get => Array.Empty<InventoryPouch>(); set { } }
|
||||
|
||||
|
|
|
@ -16,7 +16,7 @@ namespace PKHeX.Core
|
|||
else
|
||||
LoadOffsetsInternational(sav.Version);
|
||||
Daycare = PokedexSeen + 0x1F + 28 + 1; // right after first unown seen
|
||||
EventConst = EventFlag - 0x100;
|
||||
EventWork = EventFlag - 0x100;
|
||||
}
|
||||
|
||||
public int RTCFlags { get; private set; } = -1;
|
||||
|
@ -41,7 +41,7 @@ namespace PKHeX.Core
|
|||
public int AccumulatedChecksumEnd { get; private set; } = -1;
|
||||
public int OverallChecksumPosition { get; private set; } = -1;
|
||||
public int EventFlag { get; private set; } = -1;
|
||||
public int EventConst { get; }
|
||||
public int EventWork { get; }
|
||||
public int Daycare { get; }
|
||||
|
||||
public int BlueCardPoints { get; private set; } = -1;
|
||||
|
|
|
@ -3,7 +3,7 @@ using static System.Buffers.Binary.BinaryPrimitives;
|
|||
|
||||
namespace PKHeX.Core
|
||||
{
|
||||
public sealed class FestaBlock5 : SaveBlock
|
||||
public sealed class FestaBlock5 : SaveBlock<SAV5B2W2>
|
||||
{
|
||||
public FestaBlock5(SAV5B2W2 SAV, int offset) : base(SAV) => Offset = offset;
|
||||
|
||||
|
|
|
@ -1,23 +1,38 @@
|
|||
using System.ComponentModel;
|
||||
|
||||
namespace PKHeX.Core
|
||||
namespace PKHeX.Core;
|
||||
|
||||
/// <summary>
|
||||
/// Base class for a savegame data reader.
|
||||
/// </summary>
|
||||
public abstract class SaveBlock
|
||||
{
|
||||
/// <summary>
|
||||
/// Base class for a savegame data reader.
|
||||
/// </summary>
|
||||
public abstract class SaveBlock
|
||||
[Browsable(false)]
|
||||
public int Offset { get; protected init; }
|
||||
|
||||
public readonly byte[] Data;
|
||||
protected readonly SaveFile SAV;
|
||||
protected SaveBlock(SaveFile sav) => Data = (SAV = sav).Data;
|
||||
|
||||
protected SaveBlock(SaveFile sav, byte[] data)
|
||||
{
|
||||
[Browsable(false)]
|
||||
public int Offset { get; protected init; }
|
||||
|
||||
public readonly byte[] Data;
|
||||
protected readonly SaveFile SAV;
|
||||
protected SaveBlock(SaveFile sav) => Data = (SAV = sav).Data;
|
||||
|
||||
protected SaveBlock(SaveFile sav, byte[] data)
|
||||
{
|
||||
SAV = sav;
|
||||
Data = data;
|
||||
}
|
||||
SAV = sav;
|
||||
Data = data;
|
||||
}
|
||||
}
|
||||
|
||||
public abstract class SaveBlock<T> where T : SaveFile
|
||||
{
|
||||
[Browsable(false)]
|
||||
public int Offset { get; protected init; }
|
||||
|
||||
public readonly byte[] Data;
|
||||
protected readonly T SAV;
|
||||
protected SaveBlock(T sav) => Data = (SAV = sav).Data;
|
||||
|
||||
protected SaveBlock(T sav, byte[] data)
|
||||
{
|
||||
SAV = sav;
|
||||
Data = data;
|
||||
}
|
||||
}
|
|
@ -524,7 +524,9 @@ namespace PKHeX.WinForms.Controls
|
|||
SAV1 s => (Form) new SAV_EventReset1(s),
|
||||
SAV7b s => new SAV_EventWork(s),
|
||||
SAV8BS s => new SAV_FlagWork8b(s),
|
||||
_ => new SAV_EventFlags(SAV),
|
||||
IEventFlag37 g37 => new SAV_EventFlags(g37),
|
||||
SAV2 s => new SAV_EventFlags2(s),
|
||||
_ => throw new Exception(),
|
||||
};
|
||||
form.ShowDialog();
|
||||
}
|
||||
|
@ -1093,7 +1095,7 @@ namespace PKHeX.WinForms.Controls
|
|||
B_OpenPokedex.Visible = sav.HasPokeDex;
|
||||
B_OpenBerryField.Visible = sav is SAV6XY; // oras undocumented
|
||||
B_OpenFriendSafari.Visible = sav is SAV6XY;
|
||||
B_OpenEventFlags.Visible = sav.HasEvents;
|
||||
B_OpenEventFlags.Visible = sav is IEventFlag37 or (SAV1 or SAV2 or SAV8BS or SAV7b);
|
||||
B_CGearSkin.Visible = sav.Generation == 5;
|
||||
B_OpenPokeBeans.Visible = B_CellsStickers.Visible = B_FestivalPlaza.Visible = sav is SAV7;
|
||||
|
||||
|
|
|
@ -48,7 +48,7 @@ namespace PKHeX.WinForms
|
|||
cba[i].Items.Clear();
|
||||
cba[i].InitializeBinding();
|
||||
cba[i].DataSource = new BindingSource(legal, null);
|
||||
var g3Species = SAV.GetEventConst(0x43 + i);
|
||||
var g3Species = SAV.GetWork(0x43 + i);
|
||||
var species = SpeciesConverter.GetG4Species(g3Species);
|
||||
cba[i].SelectedValue = species;
|
||||
}
|
||||
|
@ -75,7 +75,7 @@ namespace PKHeX.WinForms
|
|||
{
|
||||
var species = (ushort) WinFormsUtil.GetIndex(cba[i]);
|
||||
var g3Species = SpeciesConverter.GetG3Species(species);
|
||||
SAV.SetEventConst(0x43 + i, (ushort)g3Species);
|
||||
SAV.SetWork(0x43 + i, (ushort)g3Species);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -238,9 +238,7 @@ namespace PKHeX.WinForms
|
|||
else
|
||||
{
|
||||
CB_Stats2.Visible = true;
|
||||
foreach (var t in bft)
|
||||
CB_Stats2.Items.Add(t);
|
||||
|
||||
CB_Stats2.Items.AddRange(bft);
|
||||
CB_Stats2.SelectedIndex = 0;
|
||||
}
|
||||
|
||||
|
@ -377,8 +375,7 @@ namespace PKHeX.WinForms
|
|||
SetFrontierSymbols();
|
||||
|
||||
CB_Stats1.Items.Clear();
|
||||
foreach (string t in BFN)
|
||||
CB_Stats1.Items.Add(t);
|
||||
CB_Stats1.Items.AddRange(BFN);
|
||||
|
||||
loading = false;
|
||||
CB_Stats1.SelectedIndex = 0;
|
||||
|
|
|
@ -18,7 +18,7 @@ namespace PKHeX.WinForms
|
|||
// Constants @ 0x1C00
|
||||
// Cell Data @ 0x1D8C
|
||||
// Use constants 0x18C/2 = 198 thru +95
|
||||
ushort[] constants = SAV.GetEventConsts();
|
||||
ushort[] constants = SAV.GetAllEventWork();
|
||||
var cells = constants.AsSpan(celloffset, CellCount);
|
||||
|
||||
int cellCount = constants[cellstotal];
|
||||
|
@ -28,8 +28,7 @@ namespace PKHeX.WinForms
|
|||
NUD_Collected.Value = cellCollected;
|
||||
|
||||
var combo = (DataGridViewComboBoxColumn)dgv.Columns[2];
|
||||
foreach (string t in states)
|
||||
combo.Items.Add(t); // add only the Names
|
||||
combo.Items.AddRange(states); // add only the Names
|
||||
dgv.Columns[0].ValueType = typeof(int);
|
||||
|
||||
// Populate Grid
|
||||
|
@ -54,7 +53,7 @@ namespace PKHeX.WinForms
|
|||
|
||||
private void B_Save_Click(object sender, EventArgs e)
|
||||
{
|
||||
ushort[] constants = SAV.GetEventConsts();
|
||||
ushort[] constants = SAV.GetAllEventWork();
|
||||
for (int i = 0; i < CellCount; i++)
|
||||
{
|
||||
string str = (string)dgv.Rows[i].Cells[2].Value;
|
||||
|
@ -70,7 +69,7 @@ namespace PKHeX.WinForms
|
|||
if (SAV is SAV7USUM)
|
||||
SAV.SetRecord(72, (int)NUD_Collected.Value);
|
||||
|
||||
SAV.SetEventConsts(constants);
|
||||
SAV.SetAllEventWork(constants);
|
||||
Origin.CopyChangesFrom(SAV);
|
||||
|
||||
Close();
|
||||
|
|
|
@ -257,9 +257,9 @@ namespace PKHeX.WinForms
|
|||
private void DiffSaves()
|
||||
{
|
||||
var diff = new EventWorkDiff8b(TB_OldSAV.Text, TB_NewSAV.Text);
|
||||
if (diff.Message.Length != 0)
|
||||
if (diff.Message != EventWorkDiffCompatibility.Valid)
|
||||
{
|
||||
WinFormsUtil.Alert(diff.Message);
|
||||
WinFormsUtil.Alert(diff.Message.GetMessage());
|
||||
return;
|
||||
}
|
||||
|
||||
|
|
|
@ -10,18 +10,18 @@ namespace PKHeX.WinForms
|
|||
{
|
||||
public sealed partial class SAV_EventFlags : Form
|
||||
{
|
||||
private readonly EventWorkspace Editor;
|
||||
private readonly EventWorkspace<IEventFlag37, ushort> Editor;
|
||||
private readonly Dictionary<int, NumericUpDown> WorkDict = new();
|
||||
private readonly Dictionary<int, int> FlagDict = new();
|
||||
|
||||
private bool editing;
|
||||
|
||||
public SAV_EventFlags(SaveFile sav)
|
||||
public SAV_EventFlags(IEventFlag37 sav)
|
||||
{
|
||||
InitializeComponent();
|
||||
WinFormsUtil.TranslateInterface(this, Main.CurrentLanguage);
|
||||
|
||||
var editor = Editor = new EventWorkspace(sav);
|
||||
var editor = Editor = new EventWorkspace<IEventFlag37, ushort>(sav);
|
||||
DragEnter += Main_DragEnter;
|
||||
DragDrop += Main_DragDrop;
|
||||
|
||||
|
@ -40,7 +40,7 @@ namespace PKHeX.WinForms
|
|||
dgv.ResumeLayout();
|
||||
TLP_Const.ResumeLayout();
|
||||
|
||||
Text = $"{Text} ({sav.Version})";
|
||||
Text = $"{Text} ({((IVersion)sav).Version})";
|
||||
|
||||
if (CB_Stats.Items.Count > 0)
|
||||
{
|
||||
|
@ -285,10 +285,10 @@ namespace PKHeX.WinForms
|
|||
|
||||
private void DiffSaves()
|
||||
{
|
||||
var diff = new EventBlockDiff(TB_OldSAV.Text, TB_NewSAV.Text);
|
||||
if (!string.IsNullOrWhiteSpace(diff.Message))
|
||||
var diff = new EventBlockDiff<IEventFlag37, ushort>(TB_OldSAV.Text, TB_NewSAV.Text);
|
||||
if (diff.Message != EventWorkDiffCompatibility.Valid)
|
||||
{
|
||||
WinFormsUtil.Alert(diff.Message);
|
||||
WinFormsUtil.Alert(diff.Message.GetMessage());
|
||||
return;
|
||||
}
|
||||
|
||||
|
|
427
PKHeX.WinForms/Subforms/Save Editors/SAV_EventFlags2.Designer.cs
generated
Normal file
427
PKHeX.WinForms/Subforms/Save Editors/SAV_EventFlags2.Designer.cs
generated
Normal file
|
@ -0,0 +1,427 @@
|
|||
namespace PKHeX.WinForms
|
||||
{
|
||||
sealed partial class SAV_EventFlags2
|
||||
{
|
||||
/// <summary>
|
||||
/// Required designer variable.
|
||||
/// </summary>
|
||||
private System.ComponentModel.IContainer components = null;
|
||||
|
||||
/// <summary>
|
||||
/// Clean up any resources being used.
|
||||
/// </summary>
|
||||
/// <param name="disposing">true if managed resources should be disposed; otherwise, false.</param>
|
||||
protected override void Dispose(bool disposing)
|
||||
{
|
||||
if (disposing && (components != null))
|
||||
{
|
||||
components.Dispose();
|
||||
}
|
||||
base.Dispose(disposing);
|
||||
}
|
||||
|
||||
#region Windows Form Designer generated code
|
||||
|
||||
/// <summary>
|
||||
/// Required method for Designer support - do not modify
|
||||
/// the contents of this method with the code editor.
|
||||
/// </summary>
|
||||
private void InitializeComponent()
|
||||
{
|
||||
this.c_CustomFlag = new System.Windows.Forms.CheckBox();
|
||||
this.B_Cancel = new System.Windows.Forms.Button();
|
||||
this.GB_FlagStatus = new System.Windows.Forms.GroupBox();
|
||||
this.NUD_Flag = new System.Windows.Forms.NumericUpDown();
|
||||
this.MT_Stat = new System.Windows.Forms.MaskedTextBox();
|
||||
this.CHK_CustomFlag = new System.Windows.Forms.Label();
|
||||
this.CB_Stats = new System.Windows.Forms.ComboBox();
|
||||
this.L_Stats = new System.Windows.Forms.Label();
|
||||
this.B_Save = new System.Windows.Forms.Button();
|
||||
this.GB_Researcher = new System.Windows.Forms.GroupBox();
|
||||
this.L_UnSet = new System.Windows.Forms.Label();
|
||||
this.L_IsSet = new System.Windows.Forms.Label();
|
||||
this.TB_NewSAV = new System.Windows.Forms.TextBox();
|
||||
this.TB_OldSAV = new System.Windows.Forms.TextBox();
|
||||
this.TB_UnSet = new System.Windows.Forms.TextBox();
|
||||
this.TB_IsSet = new System.Windows.Forms.TextBox();
|
||||
this.B_LoadNew = new System.Windows.Forms.Button();
|
||||
this.B_LoadOld = new System.Windows.Forms.Button();
|
||||
this.L_EventFlagWarn = new System.Windows.Forms.Label();
|
||||
this.tabControl1 = new System.Windows.Forms.TabControl();
|
||||
this.GB_Flags = new System.Windows.Forms.TabPage();
|
||||
this.dgv = new System.Windows.Forms.DataGridView();
|
||||
this.GB_Constants = new System.Windows.Forms.TabPage();
|
||||
this.TLP_Const = new System.Windows.Forms.TableLayoutPanel();
|
||||
this.GB_Research = new System.Windows.Forms.TabPage();
|
||||
this.GB_FlagStatus.SuspendLayout();
|
||||
((System.ComponentModel.ISupportInitialize)(this.NUD_Flag)).BeginInit();
|
||||
this.GB_Researcher.SuspendLayout();
|
||||
this.tabControl1.SuspendLayout();
|
||||
this.GB_Flags.SuspendLayout();
|
||||
((System.ComponentModel.ISupportInitialize)(this.dgv)).BeginInit();
|
||||
this.GB_Constants.SuspendLayout();
|
||||
this.GB_Research.SuspendLayout();
|
||||
this.SuspendLayout();
|
||||
//
|
||||
// c_CustomFlag
|
||||
//
|
||||
this.c_CustomFlag.AutoSize = true;
|
||||
this.c_CustomFlag.CheckAlign = System.Drawing.ContentAlignment.MiddleRight;
|
||||
this.c_CustomFlag.Location = new System.Drawing.Point(138, 20);
|
||||
this.c_CustomFlag.Name = "c_CustomFlag";
|
||||
this.c_CustomFlag.Size = new System.Drawing.Size(15, 14);
|
||||
this.c_CustomFlag.TabIndex = 1;
|
||||
this.c_CustomFlag.UseVisualStyleBackColor = true;
|
||||
this.c_CustomFlag.CheckedChanged += new System.EventHandler(this.ChangeCustomBool);
|
||||
//
|
||||
// B_Cancel
|
||||
//
|
||||
this.B_Cancel.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Right)));
|
||||
this.B_Cancel.Location = new System.Drawing.Point(289, 330);
|
||||
this.B_Cancel.Name = "B_Cancel";
|
||||
this.B_Cancel.Size = new System.Drawing.Size(75, 23);
|
||||
this.B_Cancel.TabIndex = 2;
|
||||
this.B_Cancel.Text = "Cancel";
|
||||
this.B_Cancel.UseVisualStyleBackColor = true;
|
||||
this.B_Cancel.Click += new System.EventHandler(this.B_Cancel_Click);
|
||||
//
|
||||
// GB_FlagStatus
|
||||
//
|
||||
this.GB_FlagStatus.Controls.Add(this.NUD_Flag);
|
||||
this.GB_FlagStatus.Controls.Add(this.MT_Stat);
|
||||
this.GB_FlagStatus.Controls.Add(this.CHK_CustomFlag);
|
||||
this.GB_FlagStatus.Controls.Add(this.CB_Stats);
|
||||
this.GB_FlagStatus.Controls.Add(this.L_Stats);
|
||||
this.GB_FlagStatus.Controls.Add(this.c_CustomFlag);
|
||||
this.GB_FlagStatus.Location = new System.Drawing.Point(6, 5);
|
||||
this.GB_FlagStatus.Name = "GB_FlagStatus";
|
||||
this.GB_FlagStatus.Size = new System.Drawing.Size(206, 75);
|
||||
this.GB_FlagStatus.TabIndex = 3;
|
||||
this.GB_FlagStatus.TabStop = false;
|
||||
this.GB_FlagStatus.Text = "Check Status";
|
||||
//
|
||||
// NUD_Flag
|
||||
//
|
||||
this.NUD_Flag.Location = new System.Drawing.Point(87, 17);
|
||||
this.NUD_Flag.Maximum = new decimal(new int[] {
|
||||
3072,
|
||||
0,
|
||||
0,
|
||||
0});
|
||||
this.NUD_Flag.Name = "NUD_Flag";
|
||||
this.NUD_Flag.Size = new System.Drawing.Size(45, 20);
|
||||
this.NUD_Flag.TabIndex = 9;
|
||||
this.NUD_Flag.ValueChanged += new System.EventHandler(this.ChangeCustomFlag);
|
||||
this.NUD_Flag.KeyUp += new System.Windows.Forms.KeyEventHandler(this.ChangeCustomFlag);
|
||||
//
|
||||
// MT_Stat
|
||||
//
|
||||
this.MT_Stat.Font = new System.Drawing.Font("Courier New", 8.25F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(0)));
|
||||
this.MT_Stat.Location = new System.Drawing.Point(159, 44);
|
||||
this.MT_Stat.Mask = "00000";
|
||||
this.MT_Stat.Name = "MT_Stat";
|
||||
this.MT_Stat.Size = new System.Drawing.Size(34, 20);
|
||||
this.MT_Stat.TabIndex = 34;
|
||||
this.MT_Stat.TextAlign = System.Windows.Forms.HorizontalAlignment.Right;
|
||||
this.MT_Stat.TextChanged += new System.EventHandler(this.ChangeCustomConst);
|
||||
//
|
||||
// CHK_CustomFlag
|
||||
//
|
||||
this.CHK_CustomFlag.Location = new System.Drawing.Point(9, 17);
|
||||
this.CHK_CustomFlag.Name = "CHK_CustomFlag";
|
||||
this.CHK_CustomFlag.Size = new System.Drawing.Size(72, 20);
|
||||
this.CHK_CustomFlag.TabIndex = 2;
|
||||
this.CHK_CustomFlag.Text = "Flag:";
|
||||
this.CHK_CustomFlag.TextAlign = System.Drawing.ContentAlignment.MiddleRight;
|
||||
//
|
||||
// CB_Stats
|
||||
//
|
||||
this.CB_Stats.DropDownHeight = 156;
|
||||
this.CB_Stats.DropDownStyle = System.Windows.Forms.ComboBoxStyle.DropDownList;
|
||||
this.CB_Stats.DropDownWidth = 180;
|
||||
this.CB_Stats.FormattingEnabled = true;
|
||||
this.CB_Stats.IntegralHeight = false;
|
||||
this.CB_Stats.Location = new System.Drawing.Point(87, 44);
|
||||
this.CB_Stats.Name = "CB_Stats";
|
||||
this.CB_Stats.Size = new System.Drawing.Size(66, 21);
|
||||
this.CB_Stats.TabIndex = 36;
|
||||
this.CB_Stats.SelectedIndexChanged += new System.EventHandler(this.ChangeConstantIndex);
|
||||
//
|
||||
// L_Stats
|
||||
//
|
||||
this.L_Stats.Location = new System.Drawing.Point(9, 45);
|
||||
this.L_Stats.Name = "L_Stats";
|
||||
this.L_Stats.Size = new System.Drawing.Size(72, 20);
|
||||
this.L_Stats.TabIndex = 37;
|
||||
this.L_Stats.Text = "Constant:";
|
||||
this.L_Stats.TextAlign = System.Drawing.ContentAlignment.MiddleRight;
|
||||
//
|
||||
// B_Save
|
||||
//
|
||||
this.B_Save.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Right)));
|
||||
this.B_Save.Location = new System.Drawing.Point(372, 330);
|
||||
this.B_Save.Name = "B_Save";
|
||||
this.B_Save.Size = new System.Drawing.Size(75, 23);
|
||||
this.B_Save.TabIndex = 9;
|
||||
this.B_Save.Text = "Save";
|
||||
this.B_Save.UseVisualStyleBackColor = true;
|
||||
this.B_Save.Click += new System.EventHandler(this.B_Save_Click);
|
||||
//
|
||||
// GB_Researcher
|
||||
//
|
||||
this.GB_Researcher.Controls.Add(this.L_UnSet);
|
||||
this.GB_Researcher.Controls.Add(this.L_IsSet);
|
||||
this.GB_Researcher.Controls.Add(this.TB_NewSAV);
|
||||
this.GB_Researcher.Controls.Add(this.TB_OldSAV);
|
||||
this.GB_Researcher.Controls.Add(this.TB_UnSet);
|
||||
this.GB_Researcher.Controls.Add(this.TB_IsSet);
|
||||
this.GB_Researcher.Controls.Add(this.B_LoadNew);
|
||||
this.GB_Researcher.Controls.Add(this.B_LoadOld);
|
||||
this.GB_Researcher.Dock = System.Windows.Forms.DockStyle.Bottom;
|
||||
this.GB_Researcher.Location = new System.Drawing.Point(3, 160);
|
||||
this.GB_Researcher.Name = "GB_Researcher";
|
||||
this.GB_Researcher.Size = new System.Drawing.Size(416, 120);
|
||||
this.GB_Researcher.TabIndex = 13;
|
||||
this.GB_Researcher.TabStop = false;
|
||||
this.GB_Researcher.Text = "FlagDiff Researcher";
|
||||
//
|
||||
// L_UnSet
|
||||
//
|
||||
this.L_UnSet.Location = new System.Drawing.Point(3, 94);
|
||||
this.L_UnSet.Name = "L_UnSet";
|
||||
this.L_UnSet.Size = new System.Drawing.Size(51, 21);
|
||||
this.L_UnSet.TabIndex = 7;
|
||||
this.L_UnSet.Text = "UnSet:";
|
||||
this.L_UnSet.TextAlign = System.Drawing.ContentAlignment.MiddleRight;
|
||||
//
|
||||
// L_IsSet
|
||||
//
|
||||
this.L_IsSet.Location = new System.Drawing.Point(6, 73);
|
||||
this.L_IsSet.Name = "L_IsSet";
|
||||
this.L_IsSet.Size = new System.Drawing.Size(48, 20);
|
||||
this.L_IsSet.TabIndex = 6;
|
||||
this.L_IsSet.Text = "IsSet:";
|
||||
this.L_IsSet.TextAlign = System.Drawing.ContentAlignment.MiddleRight;
|
||||
//
|
||||
// TB_NewSAV
|
||||
//
|
||||
this.TB_NewSAV.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Left)
|
||||
| System.Windows.Forms.AnchorStyles.Right)));
|
||||
this.TB_NewSAV.Location = new System.Drawing.Point(93, 47);
|
||||
this.TB_NewSAV.Name = "TB_NewSAV";
|
||||
this.TB_NewSAV.ReadOnly = true;
|
||||
this.TB_NewSAV.Size = new System.Drawing.Size(317, 20);
|
||||
this.TB_NewSAV.TabIndex = 5;
|
||||
this.TB_NewSAV.TextChanged += new System.EventHandler(this.ChangeSAV);
|
||||
//
|
||||
// TB_OldSAV
|
||||
//
|
||||
this.TB_OldSAV.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Left)
|
||||
| System.Windows.Forms.AnchorStyles.Right)));
|
||||
this.TB_OldSAV.Location = new System.Drawing.Point(93, 21);
|
||||
this.TB_OldSAV.Name = "TB_OldSAV";
|
||||
this.TB_OldSAV.ReadOnly = true;
|
||||
this.TB_OldSAV.Size = new System.Drawing.Size(317, 20);
|
||||
this.TB_OldSAV.TabIndex = 4;
|
||||
this.TB_OldSAV.TextChanged += new System.EventHandler(this.ChangeSAV);
|
||||
//
|
||||
// TB_UnSet
|
||||
//
|
||||
this.TB_UnSet.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Left)
|
||||
| System.Windows.Forms.AnchorStyles.Right)));
|
||||
this.TB_UnSet.Location = new System.Drawing.Point(56, 94);
|
||||
this.TB_UnSet.Name = "TB_UnSet";
|
||||
this.TB_UnSet.ReadOnly = true;
|
||||
this.TB_UnSet.Size = new System.Drawing.Size(354, 20);
|
||||
this.TB_UnSet.TabIndex = 3;
|
||||
//
|
||||
// TB_IsSet
|
||||
//
|
||||
this.TB_IsSet.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Left)
|
||||
| System.Windows.Forms.AnchorStyles.Right)));
|
||||
this.TB_IsSet.Location = new System.Drawing.Point(56, 73);
|
||||
this.TB_IsSet.Name = "TB_IsSet";
|
||||
this.TB_IsSet.ReadOnly = true;
|
||||
this.TB_IsSet.Size = new System.Drawing.Size(354, 20);
|
||||
this.TB_IsSet.TabIndex = 2;
|
||||
//
|
||||
// B_LoadNew
|
||||
//
|
||||
this.B_LoadNew.Location = new System.Drawing.Point(12, 45);
|
||||
this.B_LoadNew.Name = "B_LoadNew";
|
||||
this.B_LoadNew.Size = new System.Drawing.Size(75, 23);
|
||||
this.B_LoadNew.TabIndex = 1;
|
||||
this.B_LoadNew.Text = "Load New";
|
||||
this.B_LoadNew.UseVisualStyleBackColor = true;
|
||||
this.B_LoadNew.Click += new System.EventHandler(this.OpenSAV);
|
||||
//
|
||||
// B_LoadOld
|
||||
//
|
||||
this.B_LoadOld.Location = new System.Drawing.Point(12, 19);
|
||||
this.B_LoadOld.Name = "B_LoadOld";
|
||||
this.B_LoadOld.Size = new System.Drawing.Size(75, 23);
|
||||
this.B_LoadOld.TabIndex = 0;
|
||||
this.B_LoadOld.Text = "Load Old";
|
||||
this.B_LoadOld.UseVisualStyleBackColor = true;
|
||||
this.B_LoadOld.Click += new System.EventHandler(this.OpenSAV);
|
||||
//
|
||||
// L_EventFlagWarn
|
||||
//
|
||||
this.L_EventFlagWarn.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Left)));
|
||||
this.L_EventFlagWarn.ForeColor = System.Drawing.Color.Red;
|
||||
this.L_EventFlagWarn.Location = new System.Drawing.Point(9, 324);
|
||||
this.L_EventFlagWarn.Name = "L_EventFlagWarn";
|
||||
this.L_EventFlagWarn.Size = new System.Drawing.Size(262, 31);
|
||||
this.L_EventFlagWarn.TabIndex = 41;
|
||||
this.L_EventFlagWarn.Text = "Altering Event Flags may impact other story events.\r\nSave file backups are recomm" +
|
||||
"ended.";
|
||||
this.L_EventFlagWarn.TextAlign = System.Drawing.ContentAlignment.MiddleLeft;
|
||||
//
|
||||
// tabControl1
|
||||
//
|
||||
this.tabControl1.Anchor = ((System.Windows.Forms.AnchorStyles)((((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Bottom)
|
||||
| System.Windows.Forms.AnchorStyles.Left)
|
||||
| System.Windows.Forms.AnchorStyles.Right)));
|
||||
this.tabControl1.Controls.Add(this.GB_Flags);
|
||||
this.tabControl1.Controls.Add(this.GB_Constants);
|
||||
this.tabControl1.Controls.Add(this.GB_Research);
|
||||
this.tabControl1.Location = new System.Drawing.Point(12, 12);
|
||||
this.tabControl1.Name = "tabControl1";
|
||||
this.tabControl1.SelectedIndex = 0;
|
||||
this.tabControl1.Size = new System.Drawing.Size(430, 309);
|
||||
this.tabControl1.TabIndex = 42;
|
||||
//
|
||||
// GB_Flags
|
||||
//
|
||||
this.GB_Flags.Controls.Add(this.dgv);
|
||||
this.GB_Flags.Location = new System.Drawing.Point(4, 22);
|
||||
this.GB_Flags.Name = "GB_Flags";
|
||||
this.GB_Flags.Size = new System.Drawing.Size(422, 283);
|
||||
this.GB_Flags.TabIndex = 0;
|
||||
this.GB_Flags.Text = "Event Flags";
|
||||
this.GB_Flags.UseVisualStyleBackColor = true;
|
||||
//
|
||||
// dgv
|
||||
//
|
||||
this.dgv.AllowUserToAddRows = false;
|
||||
this.dgv.AllowUserToDeleteRows = false;
|
||||
this.dgv.AllowUserToResizeColumns = false;
|
||||
this.dgv.AllowUserToResizeRows = false;
|
||||
this.dgv.BackgroundColor = System.Drawing.SystemColors.ControlLightLight;
|
||||
this.dgv.BorderStyle = System.Windows.Forms.BorderStyle.None;
|
||||
this.dgv.ColumnHeadersBorderStyle = System.Windows.Forms.DataGridViewHeaderBorderStyle.Single;
|
||||
this.dgv.ColumnHeadersHeightSizeMode = System.Windows.Forms.DataGridViewColumnHeadersHeightSizeMode.AutoSize;
|
||||
this.dgv.ColumnHeadersVisible = false;
|
||||
this.dgv.Dock = System.Windows.Forms.DockStyle.Fill;
|
||||
this.dgv.EditMode = System.Windows.Forms.DataGridViewEditMode.EditOnEnter;
|
||||
this.dgv.Location = new System.Drawing.Point(0, 0);
|
||||
this.dgv.Margin = new System.Windows.Forms.Padding(0);
|
||||
this.dgv.MultiSelect = false;
|
||||
this.dgv.Name = "dgv";
|
||||
this.dgv.RowHeadersVisible = false;
|
||||
this.dgv.SelectionMode = System.Windows.Forms.DataGridViewSelectionMode.CellSelect;
|
||||
this.dgv.ShowEditingIcon = false;
|
||||
this.dgv.Size = new System.Drawing.Size(422, 283);
|
||||
this.dgv.TabIndex = 12;
|
||||
//
|
||||
// GB_Constants
|
||||
//
|
||||
this.GB_Constants.Controls.Add(this.TLP_Const);
|
||||
this.GB_Constants.Location = new System.Drawing.Point(4, 22);
|
||||
this.GB_Constants.Name = "GB_Constants";
|
||||
this.GB_Constants.Padding = new System.Windows.Forms.Padding(3);
|
||||
this.GB_Constants.Size = new System.Drawing.Size(422, 283);
|
||||
this.GB_Constants.TabIndex = 1;
|
||||
this.GB_Constants.Text = "Event Constants";
|
||||
this.GB_Constants.UseVisualStyleBackColor = true;
|
||||
//
|
||||
// TLP_Const
|
||||
//
|
||||
this.TLP_Const.Anchor = ((System.Windows.Forms.AnchorStyles)((((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Bottom)
|
||||
| System.Windows.Forms.AnchorStyles.Left)
|
||||
| System.Windows.Forms.AnchorStyles.Right)));
|
||||
this.TLP_Const.AutoScroll = true;
|
||||
this.TLP_Const.ColumnCount = 3;
|
||||
this.TLP_Const.ColumnStyles.Add(new System.Windows.Forms.ColumnStyle());
|
||||
this.TLP_Const.ColumnStyles.Add(new System.Windows.Forms.ColumnStyle());
|
||||
this.TLP_Const.ColumnStyles.Add(new System.Windows.Forms.ColumnStyle(System.Windows.Forms.SizeType.Absolute, 416F));
|
||||
this.TLP_Const.Location = new System.Drawing.Point(3, 3);
|
||||
this.TLP_Const.Name = "TLP_Const";
|
||||
this.TLP_Const.RowCount = 1;
|
||||
this.TLP_Const.RowStyles.Add(new System.Windows.Forms.RowStyle());
|
||||
this.TLP_Const.RowStyles.Add(new System.Windows.Forms.RowStyle());
|
||||
this.TLP_Const.Size = new System.Drawing.Size(416, 277);
|
||||
this.TLP_Const.TabIndex = 1;
|
||||
//
|
||||
// GB_Research
|
||||
//
|
||||
this.GB_Research.Controls.Add(this.GB_FlagStatus);
|
||||
this.GB_Research.Controls.Add(this.GB_Researcher);
|
||||
this.GB_Research.Location = new System.Drawing.Point(4, 22);
|
||||
this.GB_Research.Name = "GB_Research";
|
||||
this.GB_Research.Padding = new System.Windows.Forms.Padding(3);
|
||||
this.GB_Research.Size = new System.Drawing.Size(422, 283);
|
||||
this.GB_Research.TabIndex = 2;
|
||||
this.GB_Research.Text = "Research";
|
||||
this.GB_Research.UseVisualStyleBackColor = true;
|
||||
//
|
||||
// SAV_EventFlags
|
||||
//
|
||||
this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F);
|
||||
this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
|
||||
this.ClientSize = new System.Drawing.Size(454, 361);
|
||||
this.Controls.Add(this.tabControl1);
|
||||
this.Controls.Add(this.L_EventFlagWarn);
|
||||
this.Controls.Add(this.B_Save);
|
||||
this.Controls.Add(this.B_Cancel);
|
||||
this.Icon = global::PKHeX.WinForms.Properties.Resources.Icon;
|
||||
this.MaximizeBox = false;
|
||||
this.MaximumSize = new System.Drawing.Size(670, 800);
|
||||
this.MinimizeBox = false;
|
||||
this.MinimumSize = new System.Drawing.Size(470, 400);
|
||||
this.Name = "SAV_EventFlags";
|
||||
this.StartPosition = System.Windows.Forms.FormStartPosition.CenterParent;
|
||||
this.Text = "Event Flag Editor";
|
||||
this.GB_FlagStatus.ResumeLayout(false);
|
||||
this.GB_FlagStatus.PerformLayout();
|
||||
((System.ComponentModel.ISupportInitialize)(this.NUD_Flag)).EndInit();
|
||||
this.GB_Researcher.ResumeLayout(false);
|
||||
this.GB_Researcher.PerformLayout();
|
||||
this.tabControl1.ResumeLayout(false);
|
||||
this.GB_Flags.ResumeLayout(false);
|
||||
((System.ComponentModel.ISupportInitialize)(this.dgv)).EndInit();
|
||||
this.GB_Constants.ResumeLayout(false);
|
||||
this.GB_Research.ResumeLayout(false);
|
||||
this.ResumeLayout(false);
|
||||
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
private System.Windows.Forms.CheckBox c_CustomFlag;
|
||||
private System.Windows.Forms.Button B_Cancel;
|
||||
private System.Windows.Forms.GroupBox GB_FlagStatus;
|
||||
private System.Windows.Forms.Label CHK_CustomFlag;
|
||||
private System.Windows.Forms.NumericUpDown NUD_Flag;
|
||||
private System.Windows.Forms.Button B_Save;
|
||||
private System.Windows.Forms.GroupBox GB_Researcher;
|
||||
private System.Windows.Forms.Label L_UnSet;
|
||||
private System.Windows.Forms.Label L_IsSet;
|
||||
private System.Windows.Forms.TextBox TB_NewSAV;
|
||||
private System.Windows.Forms.TextBox TB_OldSAV;
|
||||
private System.Windows.Forms.TextBox TB_UnSet;
|
||||
private System.Windows.Forms.TextBox TB_IsSet;
|
||||
private System.Windows.Forms.Button B_LoadNew;
|
||||
private System.Windows.Forms.Button B_LoadOld;
|
||||
private System.Windows.Forms.Label L_Stats;
|
||||
private System.Windows.Forms.ComboBox CB_Stats;
|
||||
private System.Windows.Forms.MaskedTextBox MT_Stat;
|
||||
private System.Windows.Forms.Label L_EventFlagWarn;
|
||||
private System.Windows.Forms.TabControl tabControl1;
|
||||
private System.Windows.Forms.TabPage GB_Flags;
|
||||
private System.Windows.Forms.TabPage GB_Constants;
|
||||
private System.Windows.Forms.TabPage GB_Research;
|
||||
private System.Windows.Forms.TableLayoutPanel TLP_Const;
|
||||
private System.Windows.Forms.DataGridView dgv;
|
||||
}
|
||||
}
|
326
PKHeX.WinForms/Subforms/Save Editors/SAV_EventFlags2.cs
Normal file
326
PKHeX.WinForms/Subforms/Save Editors/SAV_EventFlags2.cs
Normal file
|
@ -0,0 +1,326 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Drawing;
|
||||
using System.Linq;
|
||||
using System.Windows.Forms;
|
||||
using PKHeX.Core;
|
||||
using static PKHeX.Core.MessageStrings;
|
||||
|
||||
namespace PKHeX.WinForms
|
||||
{
|
||||
public sealed partial class SAV_EventFlags2 : Form
|
||||
{
|
||||
private readonly EventWorkspace<SAV2, byte> Editor;
|
||||
private readonly Dictionary<int, NumericUpDown> WorkDict = new();
|
||||
private readonly Dictionary<int, int> FlagDict = new();
|
||||
|
||||
private bool editing;
|
||||
|
||||
public SAV_EventFlags2(SAV2 sav)
|
||||
{
|
||||
InitializeComponent();
|
||||
WinFormsUtil.TranslateInterface(this, Main.CurrentLanguage);
|
||||
|
||||
var editor = Editor = new EventWorkspace<SAV2, byte>(sav);
|
||||
DragEnter += Main_DragEnter;
|
||||
DragDrop += Main_DragDrop;
|
||||
|
||||
editing = true;
|
||||
CB_Stats.Items.Clear();
|
||||
for (int i = 0; i < editor.Values.Length; i++)
|
||||
CB_Stats.Items.Add(i.ToString());
|
||||
|
||||
dgv.SuspendLayout();
|
||||
TLP_Const.SuspendLayout();
|
||||
TLP_Const.Scroll += WinFormsUtil.PanelScroll;
|
||||
TLP_Const.Controls.Clear();
|
||||
AddFlagList(editor.Labels, editor.Flags);
|
||||
AddConstList(editor.Labels, editor.Values);
|
||||
|
||||
dgv.ResumeLayout();
|
||||
TLP_Const.ResumeLayout();
|
||||
|
||||
Text = $"{Text} ({sav.Version})";
|
||||
|
||||
if (CB_Stats.Items.Count > 0)
|
||||
{
|
||||
CB_Stats.SelectedIndex = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
L_Stats.Visible = CB_Stats.Visible = MT_Stat.Visible = false;
|
||||
tabControl1.TabPages.Remove(GB_Constants);
|
||||
}
|
||||
NUD_Flag.Maximum = editor.Flags.Length - 1;
|
||||
NUD_Flag.Value = 0;
|
||||
c_CustomFlag.Checked = editor.Flags[0];
|
||||
editing = false;
|
||||
}
|
||||
|
||||
private void B_Cancel_Click(object sender, EventArgs e)
|
||||
{
|
||||
Close();
|
||||
}
|
||||
|
||||
private void B_Save_Click(object sender, EventArgs e)
|
||||
{
|
||||
Editor.Save();
|
||||
Close();
|
||||
}
|
||||
|
||||
private void AddFlagList(EventLabelCollection list, bool[] values)
|
||||
{
|
||||
var labels = list.Flag;
|
||||
if (labels.Count == 0)
|
||||
{
|
||||
dgv.Visible = false;
|
||||
var research = new Label { Text = MsgResearchRequired, Name = "TLP_Flags_Research", ForeColor = Color.Red, AutoSize = true, Location = new Point(20, 20) };
|
||||
GB_Flags.Controls.Add(research);
|
||||
return;
|
||||
}
|
||||
|
||||
var cFlag = new DataGridViewCheckBoxColumn
|
||||
{
|
||||
DisplayIndex = 0,
|
||||
Width = 20,
|
||||
SortMode = DataGridViewColumnSortMode.NotSortable,
|
||||
};
|
||||
|
||||
var cLabel = new DataGridViewTextBoxColumn
|
||||
{
|
||||
DisplayIndex = 1,
|
||||
AutoSizeMode = DataGridViewAutoSizeColumnMode.Fill,
|
||||
ReadOnly = true,
|
||||
SortMode = DataGridViewColumnSortMode.NotSortable,
|
||||
};
|
||||
|
||||
cFlag.DefaultCellStyle.Alignment = DataGridViewContentAlignment.MiddleCenter;
|
||||
cLabel.DefaultCellStyle.Alignment = DataGridViewContentAlignment.MiddleLeft;
|
||||
|
||||
dgv.Columns.Add(cFlag);
|
||||
dgv.Columns.Add(cLabel);
|
||||
|
||||
var hideBelow = Main.Settings.Advanced.HideEventTypeBelow;
|
||||
labels = labels.Where(z => z.Type >= hideBelow).OrderByDescending(z => z.Type).ToList();
|
||||
dgv.Rows.Add(labels.Count);
|
||||
|
||||
for (int i = 0; i < labels.Count; i++)
|
||||
FlagDict[labels[i].Index] = i;
|
||||
|
||||
for (int i = 0; i < labels.Count; i++)
|
||||
{
|
||||
var (name, index, _) = labels[i];
|
||||
var cells = dgv.Rows[i].Cells;
|
||||
cells[0].Value = values[index];
|
||||
cells[1].Value = name;
|
||||
}
|
||||
dgv.CellValueChanged += (s, e) =>
|
||||
{
|
||||
if (e.ColumnIndex != 0 || e.RowIndex == -1)
|
||||
return;
|
||||
|
||||
bool chk = (bool)dgv.Rows[e.RowIndex].Cells[0].Value;
|
||||
var index = labels[e.RowIndex].Index;
|
||||
values[index] = chk;
|
||||
if (NUD_Flag.Value == index)
|
||||
c_CustomFlag.Checked = chk;
|
||||
};
|
||||
dgv.CellMouseUp += (s, e) =>
|
||||
{
|
||||
if (e.RowIndex == -1)
|
||||
return;
|
||||
|
||||
if (e.ColumnIndex == 0)
|
||||
{
|
||||
dgv.EndEdit();
|
||||
return;
|
||||
}
|
||||
|
||||
if (e.ColumnIndex != 1)
|
||||
return;
|
||||
|
||||
bool chk = (bool)dgv.Rows[e.RowIndex].Cells[0].Value;
|
||||
dgv.Rows[e.RowIndex].Cells[0].Value = !chk;
|
||||
var index = labels[e.RowIndex].Index;
|
||||
values[index] = chk;
|
||||
if (NUD_Flag.Value == index)
|
||||
c_CustomFlag.Checked = !chk;
|
||||
};
|
||||
}
|
||||
|
||||
private void AddConstList(EventLabelCollection list, byte[] values)
|
||||
{
|
||||
var labels = list.Work;
|
||||
if (labels.Count == 0)
|
||||
{
|
||||
TLP_Const.Controls.Add(new Label { Text = MsgResearchRequired, Name = "TLP_Const_Research", ForeColor = Color.Red, AutoSize = true }, 0, 0);
|
||||
return;
|
||||
}
|
||||
|
||||
var hide = Main.Settings.Advanced.HideEventTypeBelow;
|
||||
labels = labels.OrderByDescending(z => z.Type).ToList();
|
||||
for (var i = 0; i < labels.Count; i++)
|
||||
{
|
||||
var entry = labels[i];
|
||||
if (entry.Type < hide)
|
||||
break;
|
||||
var lbl = new Label { Text = entry.Name, Margin = Padding.Empty, AutoSize = true };
|
||||
var mtb = new NumericUpDown
|
||||
{
|
||||
Maximum = ushort.MaxValue,
|
||||
Minimum = ushort.MinValue,
|
||||
Margin = Padding.Empty,
|
||||
Width = 50,
|
||||
};
|
||||
|
||||
var map = entry.PredefinedValues.Select(z => new ComboItem(z.Name, z.Value)).ToList();
|
||||
var cb = new ComboBox
|
||||
{
|
||||
Margin = Padding.Empty,
|
||||
Width = 150,
|
||||
DropDownStyle = ComboBoxStyle.DropDownList,
|
||||
BindingContext = BindingContext,
|
||||
DropDownWidth = Width + 100,
|
||||
};
|
||||
cb.InitializeBinding();
|
||||
cb.DataSource = map;
|
||||
|
||||
lbl.Click += (sender, e) => mtb.Value = 0;
|
||||
bool updating = false;
|
||||
mtb.ValueChanged += ChangeConstValue;
|
||||
void ChangeConstValue(object? sender, EventArgs e)
|
||||
{
|
||||
if (updating)
|
||||
return;
|
||||
|
||||
updating = true;
|
||||
var value = (byte)mtb.Value;
|
||||
var (_, valueID) = map.Find(z => z.Value == value) ?? map[0];
|
||||
if (WinFormsUtil.GetIndex(cb) != valueID)
|
||||
cb.SelectedValue = valueID;
|
||||
|
||||
Editor.Values[entry.Index] = value;
|
||||
if (CB_Stats.SelectedIndex == entry.Index)
|
||||
MT_Stat.Text = ((int)mtb.Value).ToString();
|
||||
updating = false;
|
||||
}
|
||||
cb.SelectedValueChanged += (o, args) =>
|
||||
{
|
||||
if (editing || updating)
|
||||
return;
|
||||
var value = WinFormsUtil.GetIndex(cb);
|
||||
mtb.Value = value == NamedEventConst.CustomMagicValue ? 0 : value;
|
||||
};
|
||||
|
||||
mtb.Value = values[entry.Index];
|
||||
if (mtb.Value == 0)
|
||||
ChangeConstValue(this, EventArgs.Empty);
|
||||
|
||||
TLP_Const.Controls.Add(lbl, 0, i);
|
||||
TLP_Const.Controls.Add(cb, 1, i);
|
||||
TLP_Const.Controls.Add(mtb, 2, i);
|
||||
|
||||
WorkDict.Add(entry.Index, mtb);
|
||||
}
|
||||
}
|
||||
|
||||
private void ChangeCustomBool(object sender, EventArgs e)
|
||||
{
|
||||
if (editing)
|
||||
return;
|
||||
editing = true;
|
||||
var index = (int) NUD_Flag.Value;
|
||||
Editor.Flags[index] = c_CustomFlag.Checked;
|
||||
if (FlagDict.TryGetValue(index, out var rowIndex))
|
||||
dgv.Rows[rowIndex].Cells[0].Value = c_CustomFlag.Checked;
|
||||
editing = false;
|
||||
}
|
||||
|
||||
private void ChangeCustomFlag(object sender, EventArgs e)
|
||||
{
|
||||
int flag = (int)NUD_Flag.Value;
|
||||
c_CustomFlag.Checked = Editor.Flags[flag];
|
||||
}
|
||||
|
||||
private void ChangeCustomFlag(object sender, KeyEventArgs e) => ChangeCustomFlag(sender, (EventArgs)e);
|
||||
|
||||
private void ChangeConstantIndex(object sender, EventArgs e)
|
||||
{
|
||||
var constants = Editor.Values;
|
||||
var index = CB_Stats.SelectedIndex;
|
||||
MT_Stat.Text = constants[index].ToString();
|
||||
}
|
||||
|
||||
private void ChangeCustomConst(object sender, EventArgs e)
|
||||
{
|
||||
if (editing)
|
||||
return;
|
||||
editing = true;
|
||||
var index = CB_Stats.SelectedIndex;
|
||||
var parse = byte.TryParse(MT_Stat.Text, out var value) ? value : (byte)0;
|
||||
Editor.Values[index] = parse;
|
||||
if (WorkDict.TryGetValue(index, out var mtb))
|
||||
mtb.Value = parse;
|
||||
editing = false;
|
||||
}
|
||||
|
||||
private void ChangeSAV(object sender, EventArgs e)
|
||||
{
|
||||
if (TB_NewSAV.Text.Length > 0 && TB_OldSAV.Text.Length > 0)
|
||||
DiffSaves();
|
||||
}
|
||||
|
||||
private void OpenSAV(object sender, EventArgs e)
|
||||
{
|
||||
using var ofd = new OpenFileDialog();
|
||||
if (ofd.ShowDialog() == DialogResult.OK)
|
||||
LoadSAV(sender, ofd.FileName);
|
||||
}
|
||||
|
||||
private void LoadSAV(object sender, string path)
|
||||
{
|
||||
var dest = sender == B_LoadOld ? TB_OldSAV : TB_NewSAV;
|
||||
dest.Text = path;
|
||||
}
|
||||
|
||||
private void DiffSaves()
|
||||
{
|
||||
var diff = new EventBlockDiff<SAV2, byte>(TB_OldSAV.Text, TB_NewSAV.Text);
|
||||
if (diff.Message != EventWorkDiffCompatibility.Valid)
|
||||
{
|
||||
WinFormsUtil.Alert(diff.Message.GetMessage());
|
||||
return;
|
||||
}
|
||||
|
||||
TB_IsSet.Text = string.Join(", ", diff.SetFlags.Select(z => $"{z:0000}"));
|
||||
TB_UnSet.Text = string.Join(", ", diff.ClearedFlags.Select(z => $"{z:0000}"));
|
||||
|
||||
if (diff.WorkDiff.Count == 0)
|
||||
{
|
||||
WinFormsUtil.Alert("No Event Constant diff found.");
|
||||
return;
|
||||
}
|
||||
|
||||
var promptCopy = WinFormsUtil.Prompt(MessageBoxButtons.YesNo, "Copy Event Constant diff to clipboard?");
|
||||
if (promptCopy == DialogResult.Yes)
|
||||
WinFormsUtil.SetClipboardText(string.Join(Environment.NewLine, diff.WorkDiff));
|
||||
}
|
||||
|
||||
private static void Main_DragEnter(object? sender, DragEventArgs? e)
|
||||
{
|
||||
if (e?.Data is null)
|
||||
return;
|
||||
if (e.Data.GetDataPresent(DataFormats.FileDrop))
|
||||
e.Effect = DragDropEffects.Copy;
|
||||
}
|
||||
|
||||
private void Main_DragDrop(object? sender, DragEventArgs? e)
|
||||
{
|
||||
if (e?.Data?.GetData(DataFormats.FileDrop) is not string[] { Length: not 0 } files)
|
||||
return;
|
||||
var dr = WinFormsUtil.Prompt(MessageBoxButtons.YesNo, Name, "Yes: Old Save" + Environment.NewLine + "No: New Save");
|
||||
var button = dr == DialogResult.Yes ? B_LoadOld : B_LoadNew;
|
||||
LoadSAV(button, files[0]);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -270,9 +270,9 @@ namespace PKHeX.WinForms
|
|||
private void DiffSaves()
|
||||
{
|
||||
var diff7b = new EventWorkDiff7b(TB_OldSAV.Text, TB_NewSAV.Text);
|
||||
if (diff7b.Message.Length != 0)
|
||||
if (diff7b.Message != EventWorkDiffCompatibility.Valid)
|
||||
{
|
||||
WinFormsUtil.Alert(diff7b.Message);
|
||||
WinFormsUtil.Alert(diff7b.Message.GetMessage());
|
||||
return;
|
||||
}
|
||||
|
||||
|
|
|
@ -33,6 +33,7 @@ namespace PKHeX.WinForms
|
|||
|
||||
// Translate Title
|
||||
var formName = form.Name;
|
||||
formName = GetSaneFormName(formName);
|
||||
form.Text = context.GetTranslatedText(formName, form.Text);
|
||||
|
||||
// Translate Controls
|
||||
|
@ -43,6 +44,20 @@ namespace PKHeX.WinForms
|
|||
form.ResumeLayout();
|
||||
}
|
||||
|
||||
private static string GetSaneFormName(string formName)
|
||||
{
|
||||
// Strip out generic form names
|
||||
var degen = formName.IndexOf('`');
|
||||
if (degen != -1)
|
||||
formName = formName[..degen];
|
||||
|
||||
return formName switch
|
||||
{
|
||||
nameof(SAV_EventFlags2) => nameof(SAV_EventFlags),
|
||||
_ => formName,
|
||||
};
|
||||
}
|
||||
|
||||
private static void TranslateControl(object c, TranslationContext context, string formname)
|
||||
{
|
||||
if (c is Control r)
|
||||
|
|
Loading…
Reference in a new issue