mirror of
https://github.com/kwsch/PKHeX
synced 2024-11-10 06:34:19 +00:00
Misc tweaks
Add more xmldoc Move files/functions to better spot Less allocation on hover glow fix honeytree dppt group/slot/shake rand call (ty real.96)
This commit is contained in:
parent
3eb6ff2c9e
commit
10c5adadb8
47 changed files with 653 additions and 305 deletions
|
@ -128,7 +128,7 @@ public sealed class GameStrings : IBasicStrings
|
|||
|
||||
Sanitize();
|
||||
|
||||
g4items = (string[])itemlist.Clone();
|
||||
g4items = [..itemlist];
|
||||
Get("mail4").CopyTo(g4items, 137);
|
||||
}
|
||||
|
||||
|
|
|
@ -20,8 +20,8 @@ public interface ILocationSet
|
|||
string GetLocationName(int locationID);
|
||||
|
||||
/// <summary>
|
||||
/// Gets all groups -- ONLY USE FOR UNIT TESTING.
|
||||
/// Gets all groups -- not really useful besides unit testing.
|
||||
/// </summary>
|
||||
[EditorBrowsable(EditorBrowsableState.Never)]
|
||||
IEnumerable<(int Bank, string[] Names)> GetAll();
|
||||
IEnumerable<(int Bank, ReadOnlyMemory<string> Names)> GetAll();
|
||||
}
|
||||
|
|
|
@ -18,7 +18,7 @@ public sealed record LocationSet0(string[] Met0) : ILocationSet
|
|||
return Met0[locationID];
|
||||
}
|
||||
|
||||
public IEnumerable<(int Bank, string[] Names)> GetAll()
|
||||
public IEnumerable<(int Bank, ReadOnlyMemory<string> Names)> GetAll()
|
||||
{
|
||||
yield return (0, Met0);
|
||||
}
|
||||
|
|
|
@ -27,7 +27,7 @@ public sealed record LocationSet4(string[] Met0, string[] Met2, string[] Met3) :
|
|||
return names[index];
|
||||
}
|
||||
|
||||
public IEnumerable<(int Bank, string[] Names)> GetAll()
|
||||
public IEnumerable<(int Bank, ReadOnlyMemory<string> Names)> GetAll()
|
||||
{
|
||||
yield return (0, Met0);
|
||||
yield return (2, Met2);
|
||||
|
|
|
@ -29,7 +29,7 @@ public sealed record LocationSet6(string[] Met0, string[] Met3, string[] Met4, s
|
|||
return names[index];
|
||||
}
|
||||
|
||||
public IEnumerable<(int Bank, string[] Names)> GetAll()
|
||||
public IEnumerable<(int Bank, ReadOnlyMemory<string> Names)> GetAll()
|
||||
{
|
||||
yield return (0, Met0);
|
||||
yield return (3, Met3);
|
||||
|
|
|
@ -96,7 +96,7 @@ public sealed record EncounterStatic7b(GameVersion Version)
|
|||
return false;
|
||||
if (FlawlessIVCount != 0 && pk.FlawlessIVCount < FlawlessIVCount)
|
||||
return false;
|
||||
if (IVs.IsSpecified && !Legal.GetIsFixedIVSequenceValidSkipRand(IVs, pk))
|
||||
if (IVs.IsSpecified && !Legal.GetIsFixedIVSequenceValidNoRand(IVs, pk))
|
||||
return false;
|
||||
return true;
|
||||
}
|
||||
|
|
|
@ -3,6 +3,9 @@ using static PKHeX.Core.GameVersion;
|
|||
|
||||
namespace PKHeX.Core;
|
||||
|
||||
/// <summary>
|
||||
/// Hatch Location validity for <see cref="GameVersion.Gen3"/>.
|
||||
/// </summary>
|
||||
public static class EggHatchLocation3
|
||||
{
|
||||
private const byte MaskRS = 1 << 0; // 1
|
||||
|
@ -10,6 +13,9 @@ public static class EggHatchLocation3
|
|||
private const byte MaskFRLG = 1 << 2; // 4
|
||||
private const byte MaskAll = MaskRS | MaskE | MaskFRLG; // 7
|
||||
|
||||
/// <summary>
|
||||
/// Returns true if the hatch location is valid for the specified Generation 3 game.
|
||||
/// </summary>
|
||||
public static bool IsValidMet3(int location, GameVersion game) => game switch
|
||||
{
|
||||
R or S => IsValidMet3RS(location),
|
||||
|
@ -18,9 +24,24 @@ public static class EggHatchLocation3
|
|||
_ => false,
|
||||
};
|
||||
|
||||
/// <summary>
|
||||
/// Returns true if the hatch location is valid for Ruby and Sapphire.
|
||||
/// </summary>
|
||||
public static bool IsValidMet3RS(int location) => HasLocationFlag(LocationPermitted3, MaskRS, location);
|
||||
|
||||
/// <summary>
|
||||
/// Returns true if the hatch location is valid for Emerald.
|
||||
/// </summary>
|
||||
public static bool IsValidMet3E(int location) => HasLocationFlag(LocationPermitted3, MaskE, location);
|
||||
|
||||
/// <summary>
|
||||
/// Returns true if the hatch location is valid for FireRed and LeafGreen.
|
||||
/// </summary>
|
||||
public static bool IsValidMet3FRLG(int location) => HasLocationFlag(LocationPermitted3, MaskFRLG, location);
|
||||
|
||||
/// <summary>
|
||||
/// Returns true if the hatch location is valid for any Generation 3 game.
|
||||
/// </summary>
|
||||
public static bool IsValidMet3Any(int location) => HasLocationFlag(LocationPermitted3, MaskAll, location);
|
||||
|
||||
private static bool HasLocationFlag(ReadOnlySpan<byte> arr, byte mask, int location)
|
||||
|
|
|
@ -3,6 +3,9 @@ using static PKHeX.Core.GameVersion;
|
|||
|
||||
namespace PKHeX.Core;
|
||||
|
||||
/// <summary>
|
||||
/// Hatch Location validity for <see cref="GameVersion.Gen4"/>.
|
||||
/// </summary>
|
||||
public static class EggHatchLocation4
|
||||
{
|
||||
private const byte MaskDP = 1 << 0; // 1
|
||||
|
@ -10,6 +13,9 @@ public static class EggHatchLocation4
|
|||
private const byte MaskHGSS = 1 << 2; // 4
|
||||
private const byte MaskAll4 = MaskDP | MaskPt | MaskHGSS; // 7
|
||||
|
||||
/// <summary>
|
||||
/// Returns true if the hatch location is valid for the specified Generation 4 game.
|
||||
/// </summary>
|
||||
public static bool IsValidMet4(int location, GameVersion game) => game switch
|
||||
{
|
||||
D or P => IsValidMet4DP(location),
|
||||
|
@ -18,9 +24,24 @@ public static class EggHatchLocation4
|
|||
_ => false,
|
||||
};
|
||||
|
||||
/// <summary>
|
||||
/// Returns true if the hatch location is valid for Diamond and Pearl.
|
||||
/// </summary>
|
||||
public static bool IsValidMet4DP(int location) => HasLocationFlag(LocationPermitted4, MaskDP, location);
|
||||
|
||||
/// <summary>
|
||||
/// Returns true if the hatch location is valid for Platinum.
|
||||
/// </summary>
|
||||
public static bool IsValidMet4Pt(int location) => HasLocationFlag(LocationPermitted4, MaskPt, location);
|
||||
|
||||
/// <summary>
|
||||
/// Returns true if the hatch location is valid for HeartGold and SoulSilver.
|
||||
/// </summary>
|
||||
public static bool IsValidMet4HGSS(int location) => HasLocationFlag(LocationPermitted4, MaskHGSS, location);
|
||||
|
||||
/// <summary>
|
||||
/// Returns true if the hatch location is valid for any Generation 4 game.
|
||||
/// </summary>
|
||||
public static bool IsValidMet4Any(int location) => HasLocationFlag(LocationPermitted4, MaskAll4, location);
|
||||
|
||||
private static bool HasLocationFlag(ReadOnlySpan<byte> arr, byte mask, int location)
|
||||
|
|
|
@ -3,6 +3,9 @@ using static PKHeX.Core.GameVersion;
|
|||
|
||||
namespace PKHeX.Core;
|
||||
|
||||
/// <summary>
|
||||
/// Hatch Location validity for <see cref="GameVersion.Gen5"/>.
|
||||
/// </summary>
|
||||
public static class EggHatchLocation5
|
||||
{
|
||||
private const byte MaskWhite = 1 << 0; // 1
|
||||
|
@ -10,6 +13,9 @@ public static class EggHatchLocation5
|
|||
private const byte MaskWhite2 = 1 << 2; // 4
|
||||
private const byte MaskBlack2 = 1 << 3; // 8
|
||||
|
||||
/// <summary>
|
||||
/// Returns true if the location is valid for the specified Generation 5 game.
|
||||
/// </summary>
|
||||
public static bool IsValidMet5(int location, GameVersion game)
|
||||
{
|
||||
var shift = (uint)(game - W);
|
||||
|
@ -20,9 +26,24 @@ public static class EggHatchLocation5
|
|||
return HasLocationFlag(LocationPermitted5, mask, location);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Returns true if the hatch location is valid for White.
|
||||
/// </summary>
|
||||
public static bool IsValidMet5W(int location) => HasLocationFlag(LocationPermitted5, MaskWhite, location);
|
||||
|
||||
/// <summary>
|
||||
/// Returns true if the hatch location is valid for Black.
|
||||
/// </summary>
|
||||
public static bool IsValidMet5B(int location) => HasLocationFlag(LocationPermitted5, MaskBlack, location);
|
||||
|
||||
/// <summary>
|
||||
/// Returns true if the hatch location is valid for White 2.
|
||||
/// </summary>
|
||||
public static bool IsValidMet5W2(int location) => HasLocationFlag(LocationPermitted5, MaskWhite2, location);
|
||||
|
||||
/// <summary>
|
||||
/// Returns true if the hatch location is valid for Black 2.
|
||||
/// </summary>
|
||||
public static bool IsValidMet5B2(int location) => HasLocationFlag(LocationPermitted5, MaskBlack2, location);
|
||||
|
||||
private static bool HasLocationFlag(ReadOnlySpan<byte> arr, byte mask, int location)
|
||||
|
|
|
@ -1,7 +1,13 @@
|
|||
namespace PKHeX.Core;
|
||||
|
||||
/// <summary>
|
||||
/// Hatch Location validity for <see cref="GameVersion.Gen6"/>.
|
||||
/// </summary>
|
||||
public static class EggHatchLocation6
|
||||
{
|
||||
/// <summary>
|
||||
/// Returns true if the hatch location is valid for X and Y.
|
||||
/// </summary>
|
||||
public static bool IsValidMet6XY(int location)
|
||||
{
|
||||
const int min = 6;
|
||||
|
@ -15,6 +21,9 @@ public static class EggHatchLocation6
|
|||
return location != 80; // unused
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Returns true if the hatch location is valid for Omega Ruby and Alpha Sapphire.
|
||||
/// </summary>
|
||||
public static bool IsValidMet6AO(int location)
|
||||
{
|
||||
const int min = 170;
|
||||
|
|
|
@ -2,11 +2,17 @@ using System;
|
|||
|
||||
namespace PKHeX.Core;
|
||||
|
||||
/// <summary>
|
||||
/// Hatch Location validity for <see cref="GameVersion.Gen7"/>.
|
||||
/// </summary>
|
||||
public static class EggHatchLocation7
|
||||
{
|
||||
private const byte MaskSM = 1 << 0; // 1
|
||||
private const byte MaskUSUM = 1 << 1; // 2
|
||||
|
||||
/// <summary>
|
||||
/// Returns true if the hatch location is valid for Sun and Moon.
|
||||
/// </summary>
|
||||
public static bool IsValidMet7SM(int location)
|
||||
{
|
||||
if (HasLocationFlag(LocationPermitted7, MaskSM, location))
|
||||
|
@ -14,6 +20,9 @@ public static class EggHatchLocation7
|
|||
return location == Locations.Pelago7; // 30016
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Returns true if the hatch location is valid for Ultra Sun and Ultra Moon.
|
||||
/// </summary>
|
||||
public static bool IsValidMet7USUM(int location)
|
||||
{
|
||||
if (HasLocationFlag(LocationPermitted7, MaskUSUM, location))
|
||||
|
|
|
@ -2,8 +2,14 @@ using System;
|
|||
|
||||
namespace PKHeX.Core;
|
||||
|
||||
/// <summary>
|
||||
/// Hatch Location validity for <see cref="GameVersion.SWSH"/>.
|
||||
/// </summary>
|
||||
public static class EggHatchLocation8
|
||||
{
|
||||
/// <summary>
|
||||
/// Returns true if the hatch location is valid for Sword and Shield.
|
||||
/// </summary>
|
||||
public static bool IsValidMet8SWSH(int location)
|
||||
{
|
||||
if (location % 2 != 0)
|
||||
|
|
|
@ -2,12 +2,22 @@ using System;
|
|||
|
||||
namespace PKHeX.Core;
|
||||
|
||||
/// <summary>
|
||||
/// Hatch Location validity for <see cref="GameVersion.BDSP"/>.
|
||||
/// </summary>
|
||||
public static class EggHatchLocation8b
|
||||
{
|
||||
private const byte MaskBD = 1 << 0; // 1
|
||||
private const byte MaskSP = 1 << 1; // 2
|
||||
|
||||
/// <summary>
|
||||
/// Returns true if the hatch location is valid for Brilliant Diamond.
|
||||
/// </summary>
|
||||
public static bool IsValidMet8BD(int location) => HasLocationFlag(LocationPermitted8b, MaskBD, location);
|
||||
|
||||
/// <summary>
|
||||
/// Returns true if the hatch location is valid for Shining Pearl.
|
||||
/// </summary>
|
||||
public static bool IsValidMet8SP(int location) => HasLocationFlag(LocationPermitted8b, MaskSP, location);
|
||||
|
||||
private static bool HasLocationFlag(ReadOnlySpan<byte> arr, byte mask, int location)
|
||||
|
|
|
@ -2,11 +2,22 @@ using System;
|
|||
|
||||
namespace PKHeX.Core;
|
||||
|
||||
/// <summary>
|
||||
/// Hatch Location validity for <see cref="GameVersion.SV"/>.
|
||||
/// </summary>
|
||||
public static class EggHatchLocation9
|
||||
{
|
||||
private const byte MaskScarlet = 1 << 0; // 1
|
||||
private const byte MaskViolet = 1 << 1; // 2
|
||||
|
||||
/// <summary>
|
||||
/// Returns true if the hatch location is valid for Scarlet.
|
||||
/// </summary>
|
||||
public static bool IsValidMet9SL(int location) => HasLocationFlag(LocationPermitted9, MaskScarlet, location);
|
||||
|
||||
/// <summary>
|
||||
/// Returns true if the hatch location is valid for Violet.
|
||||
/// </summary>
|
||||
public static bool IsValidMet9VL(int location) => HasLocationFlag(LocationPermitted9, MaskViolet, location);
|
||||
|
||||
private static bool HasLocationFlag(ReadOnlySpan<byte> arr, byte mask, int location)
|
||||
|
|
|
@ -87,8 +87,18 @@ public static class Tera9RNG
|
|||
/// </summary>
|
||||
private static bool IsMatchType(IPersonalType pi, in byte original) => original == pi.Type1 || original == pi.Type2;
|
||||
|
||||
/// <summary>
|
||||
/// Checks if the original Tera Type matches the Personal Info type for the specified form.
|
||||
/// </summary>
|
||||
/// <param name="species">Egg Species</param>
|
||||
/// <param name="form">Egg Form</param>
|
||||
/// <param name="original">Original Tera Type from the Entity</param>
|
||||
/// <returns>True if the Tera Type matches the expected Personal Info type</returns>
|
||||
/// <remarks>
|
||||
/// Special consideration is required as some eggs can change forms that have different Personal Info types.
|
||||
/// </remarks>
|
||||
public static bool IsMatchTeraTypePersonalEgg(in ushort species, in byte form, in byte original) =>
|
||||
FormInfo.IsFormChangeEgg(species)
|
||||
FormInfo.IsFormChangeEggTypes(species)
|
||||
? IsMatchTeraTypePersonalAnyForm(species, original)
|
||||
: IsMatchTeraTypePersonal(species, form, original);
|
||||
|
||||
|
|
|
@ -113,7 +113,12 @@ public static class FormInfo
|
|||
return false;
|
||||
}
|
||||
|
||||
public static bool IsFormChangeEgg(ushort species) => FormChangeEgg.Contains(species);
|
||||
/// <summary>
|
||||
/// Checks if the form can be changed for a given (baby) species into a different-typed form.
|
||||
/// </summary>
|
||||
/// <param name="species">Baby species</param>
|
||||
/// <returns>True if the species can change form to another with a different typing, false if it cannot.</returns>
|
||||
public static bool IsFormChangeEggTypes(ushort species) => FormChangeEgg.Contains(species);
|
||||
|
||||
private static ReadOnlySpan<ushort> FormChangeEgg =>
|
||||
[
|
||||
|
@ -296,6 +301,13 @@ public static class FormInfo
|
|||
return --form;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Checks if the <see cref="form"/> for the <see cref="species"/> is a Lord Form from Legends: Arceus.
|
||||
/// </summary>
|
||||
/// <param name="species">Entity species</param>
|
||||
/// <param name="form">Entity form</param>
|
||||
/// <param name="context">Current context</param>
|
||||
/// <returns>True if the form is a Lord Form, false if it is not.</returns>
|
||||
public static bool IsLordForm(ushort species, byte form, EntityContext context)
|
||||
{
|
||||
if (context != EntityContext.Gen8a)
|
||||
|
|
|
@ -11,5 +11,9 @@ public interface IHomeTrack
|
|||
/// </summary>
|
||||
ulong Tracker { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Simple check if a <see cref="Tracker"/> is present.
|
||||
/// </summary>
|
||||
/// <remarks>Does not ensure that it is a valid tracker, just non-zero.</remarks>
|
||||
bool HasTracker => Tracker != 0;
|
||||
}
|
||||
|
|
|
@ -1,17 +1,21 @@
|
|||
namespace PKHeX.Core;
|
||||
|
||||
/// <summary>
|
||||
/// <inheritdoc cref="IObedienceLevelReadOnly"/>
|
||||
/// </summary>
|
||||
public interface IObedienceLevel : IObedienceLevelReadOnly
|
||||
{
|
||||
/// <summary>
|
||||
/// <inheritdoc cref="IObedienceLevelReadOnly.Obedience_Level"/>
|
||||
/// </summary>
|
||||
new byte Obedience_Level { get; set; }
|
||||
}
|
||||
|
||||
public interface IObedienceLevelReadOnly
|
||||
{
|
||||
byte Obedience_Level { get; } // no setter, use for Encounters
|
||||
}
|
||||
|
||||
public static class ObedienceExtensions
|
||||
{
|
||||
/// <summary>
|
||||
/// Suggests the <see cref="IObedienceLevelReadOnly.Obedience_Level"/> for the entity.
|
||||
/// </summary>
|
||||
public static byte GetSuggestedObedienceLevel(this IObedienceLevelReadOnly _, PKM entity, int originalMet)
|
||||
{
|
||||
if (entity.Species is (int)Species.Koraidon or (int)Species.Miraidon && entity is PK9 { FormArgument: not 0 })
|
||||
|
|
|
@ -0,0 +1,11 @@
|
|||
|
||||
/// <summary>
|
||||
/// Exposes information about the level the Pokémon was obtained.
|
||||
/// </summary>
|
||||
public interface IObedienceLevelReadOnly
|
||||
{
|
||||
/// <summary>
|
||||
/// Indicates the level the Pokémon was obtained by the current handler.
|
||||
/// </summary>
|
||||
byte Obedience_Level { get; } // no setter, use for Encounters
|
||||
}
|
|
@ -75,7 +75,8 @@ public static class Language
|
|||
German => "de",
|
||||
Spanish => "es",
|
||||
Korean => "ko",
|
||||
ChineseS or ChineseT => "zh",
|
||||
ChineseS => "zh",
|
||||
ChineseT => "zh2",
|
||||
_ => GameLanguage.DefaultLanguage,
|
||||
};
|
||||
|
||||
|
|
|
@ -10,12 +10,60 @@ namespace PKHeX.Core;
|
|||
/// </summary>
|
||||
public static class SCBlockUtil
|
||||
{
|
||||
/// <summary>
|
||||
/// Create a blank block array using the provided <see cref="arr"/> definition.
|
||||
/// </summary>
|
||||
/// <param name="arr">Block specification tuples (key, size)</param>
|
||||
/// <returns>List of blocks</returns>
|
||||
internal static SCBlock[] GetBlankBlockArray(ReadOnlySpan<uint> arr)
|
||||
{
|
||||
var blocks = new SCBlock[arr.Length / 2];
|
||||
for (int i = 0; i < blocks.Length; i++)
|
||||
{
|
||||
int index = i * 2;
|
||||
var key = arr[index];
|
||||
var length = (int)arr[index + 1];
|
||||
var dummy = new byte[length];
|
||||
blocks[i] = new SCBlock(key, SCTypeCode.None, dummy);
|
||||
}
|
||||
return blocks;
|
||||
}
|
||||
|
||||
#if DEBUG
|
||||
/// <summary>
|
||||
/// Exports the block keys & sizes in a human-readable format.
|
||||
/// </summary>
|
||||
public static IEnumerable<string> RipSizes(IReadOnlyCollection<SCBlock> blocks)
|
||||
{
|
||||
int ctr = 0;
|
||||
foreach (var block in blocks)
|
||||
{
|
||||
if (block.Data.Length == 0)
|
||||
continue;
|
||||
if (ctr == 4)
|
||||
{
|
||||
yield return Environment.NewLine;
|
||||
ctr = 0;
|
||||
}
|
||||
yield return $"0x{block.Key:X8}, 0x{block.Data.Length:X5}, ";
|
||||
ctr++;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
/// <summary>
|
||||
/// Concatenates all blocks into a single file with some metadata sprinkled in.
|
||||
/// </summary>
|
||||
/// <param name="blocks">Ascending-key ordered blocks</param>
|
||||
/// <param name="path">File path to write to</param>
|
||||
/// <param name="option">Export options</param>
|
||||
public static void ExportAllBlocksAsSingleFile(IReadOnlyList<SCBlock> blocks, string path, SCBlockExportOption option = SCBlockExportOption.All)
|
||||
{
|
||||
var data = ExportAllBlocks(blocks, option);
|
||||
File.WriteAllBytes(path, data);
|
||||
}
|
||||
|
||||
/// <inheritdoc cref="ExportAllBlocksAsSingleFile(IReadOnlyList{SCBlock}, string, SCBlockExportOption)"/>
|
||||
public static byte[] ExportAllBlocks(IReadOnlyList<SCBlock> blocks, SCBlockExportOption option = SCBlockExportOption.None)
|
||||
{
|
||||
if (option == SCBlockExportOption.None)
|
||||
|
@ -28,6 +76,9 @@ public static class SCBlockUtil
|
|||
return stream.ToArray();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Writes the block to the <see cref="bw"/> stream with the specified <see cref="option"/>.
|
||||
/// </summary>
|
||||
private static void ExportBlock(SCBlock block, BinaryWriter bw, int blockIndex, SCBlockExportOption option)
|
||||
{
|
||||
if (option.HasFlag(SCBlockExportOption.DataOnly) && block.Data.Length == 0)
|
||||
|
@ -48,6 +99,11 @@ public static class SCBlockUtil
|
|||
bw.Write(block.Data);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Get the suggested file name for a <see cref="block"/>, without the file extension.
|
||||
/// </summary>
|
||||
/// <param name="block"></param>
|
||||
/// <returns></returns>
|
||||
public static string GetBlockFileNameWithoutExtension(SCBlock block)
|
||||
{
|
||||
var key = block.Key;
|
||||
|
@ -57,6 +113,9 @@ public static class SCBlockUtil
|
|||
return name;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets a summary of the block similar to it being a record type.
|
||||
/// </summary>
|
||||
public static string GetBlockSummary(SCBlock b)
|
||||
{
|
||||
var sb = new StringBuilder(64);
|
||||
|
@ -73,6 +132,12 @@ public static class SCBlockUtil
|
|||
return sb.ToString();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Import blocks from a folder, using the block key as the file name.
|
||||
/// </summary>
|
||||
/// <param name="path">Folder to import from</param>
|
||||
/// <param name="sav">Save file to import into</param>
|
||||
/// <returns>List of block keys that failed to import</returns>
|
||||
public static List<string> ImportBlocksFromFolder(string path, ISCBlockArray sav)
|
||||
{
|
||||
var failed = new List<string>();
|
||||
|
|
|
@ -23,7 +23,7 @@ public sealed class SAV8LA : SaveFile, ISaveBlock8LA, ISCBlockArray, ISaveFileRe
|
|||
|
||||
public SAV8LA()
|
||||
{
|
||||
AllBlocks = Meta8.GetBlankDataLA();
|
||||
AllBlocks = BlankBlocks8a.GetBlankBlocks();
|
||||
Blocks = new SaveBlockAccessor8LA(this);
|
||||
SaveRevision = Blocks.DetectRevision();
|
||||
Initialize();
|
||||
|
|
|
@ -20,7 +20,7 @@ public sealed class SAV8SWSH : SaveFile, ISaveBlock8SWSH, ITrainerStatRecord, IS
|
|||
|
||||
public SAV8SWSH()
|
||||
{
|
||||
AllBlocks = Meta8.GetBlankDataSWSH();
|
||||
AllBlocks = BlankBlocks8.GetBlankBlocks();
|
||||
Blocks = new SaveBlockAccessor8SWSH(this);
|
||||
SaveRevision = Zukan.GetRevision();
|
||||
Initialize();
|
||||
|
|
|
@ -24,9 +24,9 @@ public sealed class SAV9SV : SaveFile, ISaveBlock9Main, ISCBlockArray, ISaveFile
|
|||
|
||||
public SAV9SV()
|
||||
{
|
||||
AllBlocks = Meta9.GetBlankDataSV();
|
||||
AllBlocks = BlankBlocks9.GetBlankBlocks();
|
||||
Blocks = new SaveBlockAccessor9SV(this);
|
||||
SaveRevision = Meta9.BlankRevision;
|
||||
SaveRevision = BlankBlocks9.BlankRevision;
|
||||
Initialize();
|
||||
ClearBoxes();
|
||||
}
|
||||
|
|
|
@ -81,7 +81,7 @@ public abstract class SAV_STADIUM : SaveFile, ILangDeviantSave
|
|||
{
|
||||
var result = base.GetFinalData();
|
||||
if (IsPairSwapped)
|
||||
ReverseEndianness(result = (byte[])result.Clone());
|
||||
ReverseEndianness(result = [..result]);
|
||||
return result;
|
||||
}
|
||||
|
||||
|
|
|
@ -57,12 +57,11 @@ public static class SlotPointerUtil
|
|||
|
||||
public static void UpdateRepointFrom(int newIndex, int oldIndex, Span<int> slotPointers)
|
||||
{
|
||||
for (int s = 0; s < slotPointers.Length; s++)
|
||||
// Don't return on first match; assume multiple pointers can point to the same slot
|
||||
foreach (ref var ptr in slotPointers)
|
||||
{
|
||||
if (slotPointers[s] != oldIndex)
|
||||
continue;
|
||||
slotPointers[s] = newIndex;
|
||||
break;
|
||||
if (ptr == oldIndex)
|
||||
ptr = newIndex;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -4,37 +4,71 @@ using static System.Buffers.Binary.BinaryPrimitives;
|
|||
|
||||
namespace PKHeX.Core;
|
||||
|
||||
/// <summary>
|
||||
/// Battle Video Request Utility for Gen 7
|
||||
/// </summary>
|
||||
public static class BVRequestUtil
|
||||
{
|
||||
public static string GetSMBattleVideoURL(string code)
|
||||
private const int Size = 16;
|
||||
|
||||
public static string GetBattleVideoURL7(ReadOnlySpan<char> code)
|
||||
{
|
||||
code = code.Replace("-", string.Empty);
|
||||
Debug.Assert(code.Length == 16);
|
||||
var video_id = StrToU64(code, out bool valid);
|
||||
var valid = TryGetBattleVideoID(code, out var result);
|
||||
if (!valid)
|
||||
return string.Empty;
|
||||
return $"https://ctr-bnda-live.s3.amazonaws.com/10.CTR_BNDA_datastore/ds/1/data/{video_id:D11}-00001"; // Sun datastore
|
||||
return GetBattleVideoURL7(result);
|
||||
}
|
||||
|
||||
public static ulong StrToU64(ReadOnlySpan<char> input, out bool valid)
|
||||
public static string GetBattleVideoURL7(ulong video_id)
|
||||
{
|
||||
// Sun datastore
|
||||
return $"https://ctr-bnda-live.s3.amazonaws.com/10.CTR_BNDA_datastore/ds/1/data/{video_id:D11}-00001";
|
||||
}
|
||||
|
||||
private static bool TryGetBattleVideoID(ReadOnlySpan<char> code, out ulong result)
|
||||
{
|
||||
Span<char> noDash = stackalloc char[Size];
|
||||
var length = SanitizeNoDashes(code, noDash);
|
||||
if (length != noDash.Length) // didn't fill expected length
|
||||
{
|
||||
result = 0;
|
||||
return false; // invalid length
|
||||
}
|
||||
|
||||
return TryGetID(noDash, out result);
|
||||
}
|
||||
|
||||
private static int SanitizeNoDashes(ReadOnlySpan<char> input, Span<char> result)
|
||||
{
|
||||
int ctr = 0;
|
||||
foreach (var c in input)
|
||||
{
|
||||
// Check for both dashes (user entry)
|
||||
if (c is '-' or 'ー')
|
||||
continue;
|
||||
if (ctr == result.Length)
|
||||
return -1; // fail
|
||||
result[ctr++] = c;
|
||||
}
|
||||
return ctr;
|
||||
}
|
||||
|
||||
public static bool TryGetID(ReadOnlySpan<char> input, out ulong result)
|
||||
{
|
||||
Debug.Assert(input.Length == 16);
|
||||
var chk = Pull(input[..4]) >> 4; // first four chars are checksum bits
|
||||
var result = Pull(input[4..]); // next 12 chars are the 70 value bits
|
||||
result = Pull(input[4..]); // next 12 chars are the 70 value bits
|
||||
|
||||
Span<byte> temp = stackalloc byte[8];
|
||||
WriteUInt64LittleEndian(temp, result);
|
||||
var actual = Checksums.CRC16_CCITT(temp);
|
||||
valid = chk == actual;
|
||||
return result;
|
||||
return chk == actual;
|
||||
|
||||
static ulong Pull(ReadOnlySpan<char> input)
|
||||
{
|
||||
ulong val = 0;
|
||||
foreach (char c in input)
|
||||
{
|
||||
if (c == '-')
|
||||
continue;
|
||||
|
||||
val <<= 5;
|
||||
val |= Get5BitFromChar(c) & 0b11111;
|
||||
}
|
||||
|
@ -47,7 +81,7 @@ public static class BVRequestUtil
|
|||
Span<byte> temp = stackalloc byte[8];
|
||||
WriteUInt64LittleEndian(temp, input);
|
||||
uint chk = Checksums.CRC16_CCITT(temp);
|
||||
Span<char> buff = stackalloc char[16];
|
||||
Span<char> buff = stackalloc char[Size];
|
||||
int ctr = 15;
|
||||
Push(buff, ref ctr, 12, input); // store value bits
|
||||
Push(buff, ref ctr, 04, chk << 4); // store checksum bits
|
||||
|
@ -69,7 +103,7 @@ public static class BVRequestUtil
|
|||
for (int i = 0, ctr = 0; i < buff.Length; i++)
|
||||
{
|
||||
buff2[ctr++] = buff[i];
|
||||
if (i % spacer == 3 && ctr < buff2.Length)
|
||||
if (i % spacer == (spacer - 1) && ctr < buff2.Length)
|
||||
buff2[ctr++] = '-'; // add dash between every chunk of size {spacer}
|
||||
}
|
||||
return new string(buff2);
|
||||
|
|
|
@ -60,11 +60,12 @@ public static class HoneyTreeUtil
|
|||
/// </summary>
|
||||
/// <param name="seed">Current RNG state seed of the game.</param>
|
||||
/// <param name="isMunchlaxTree">If the tree is a "rare" tree based on <see cref="CalculateMunchlaxTrees"/>.</param>"/>
|
||||
/// <remarks><see cref="GameVersion.DPPt"/></remarks>
|
||||
public static (HoneyTreeSlotGroup Group, int Slot, int Shakes) GetHoneyTreeResult(uint seed, bool isMunchlaxTree)
|
||||
{
|
||||
var randGroup = LCRNG.Next16(ref seed) % 100;
|
||||
var randSlot = LCRNG.Next16(ref seed) % 100;
|
||||
var randShakes = LCRNG.Next16(ref seed) % 100;
|
||||
var randGroup = LCRNG.Next16(ref seed) / 656;
|
||||
var randSlot = LCRNG.Next16(ref seed) / 656;
|
||||
var randShakes = LCRNG.Next16(ref seed) / 656;
|
||||
|
||||
var group = GetHoneyTreeGroup(randGroup, isMunchlaxTree);
|
||||
var slot = GetHoneyTreeSlotIndex(randSlot);
|
||||
|
|
143
PKHeX.Core/Saves/Substructures/Gen8/LA/BlankBlocks8a.cs
Normal file
143
PKHeX.Core/Saves/Substructures/Gen8/LA/BlankBlocks8a.cs
Normal file
|
@ -0,0 +1,143 @@
|
|||
using System;
|
||||
|
||||
namespace PKHeX.Core;
|
||||
|
||||
/// <summary>
|
||||
/// <see cref="SCBlock"/> metadata for <see cref="GameVersion.PLA"/>
|
||||
/// </summary>
|
||||
public static class BlankBlocks8a
|
||||
{
|
||||
/// <summary>
|
||||
/// Creates a blank <see cref="SCBlock"/> array for <see cref="GameVersion.PLA"/>
|
||||
/// </summary>
|
||||
public static SCBlock[] GetBlankBlocks() => SCBlockUtil.GetBlankBlockArray(DefaultChunkSizes);
|
||||
|
||||
private static ReadOnlySpan<uint> DefaultChunkSizes =>
|
||||
[
|
||||
0x00EF4BAE, 0x00140, 0x017C3CBB, 0x00001, 0x02168706, 0x1E460, 0x022A2253, 0x00001,
|
||||
0x024C8CF3, 0x00004, 0x033D60DA, 0x00004, 0x0493AF74, 0x00004, 0x04AE4181, 0x00001,
|
||||
0x04EABECF, 0x00004, 0x050E9D63, 0x00004, 0x05E7EBEB, 0x02EE0, 0x062AF6C2, 0x00020,
|
||||
0x069EAD42, 0x00004, 0x070F34AD, 0x00020, 0x0821C372, 0x00004, 0x0A40A680, 0x00004,
|
||||
0x0A49F0EF, 0x01F40, 0x0B3C5217, 0x00004, 0x0BFDEBA1, 0x00004, 0x0E6246BE, 0x00004,
|
||||
0x0F3AD63C, 0x00004, 0x10A052BA, 0x00008, 0x10A0546D, 0x00008, 0x10D148DE, 0x00004,
|
||||
0x111933CD, 0x00004, 0x11B37EC9, 0x000C8, 0x13A0E18B, 0x00004, 0x17833C07, 0x00004,
|
||||
0x17EB7C4D, 0x00004, 0x180A4E9F, 0x00004, 0x19722C89, 0x00440, 0x1B1E3D8B, 0x00004,
|
||||
0x1B5E0528, 0x00001, 0x1B65ABFD, 0x00004, 0x1BF70FCB, 0x00004, 0x1D482A63, 0x00004,
|
||||
0x1E0F1BA3, 0x00190, 0x203A7F34, 0x00008, 0x2085565F, 0x00001, 0x20855812, 0x00001,
|
||||
0x208559C5, 0x00001, 0x208D511F, 0x00004, 0x2123FE4A, 0x00004, 0x2137FAFF, 0x00004,
|
||||
0x22540FF0, 0x00004, 0x22DEF108, 0x00004, 0x23AA6AE3, 0x00004, 0x24E0D195, 0x002F2,
|
||||
0x250F3C75, 0x00004, 0x267DD9DA, 0x00070, 0x2728E588, 0x00004, 0x27931A29, 0x00004,
|
||||
0x27986623, 0x00004, 0x279EA6CD, 0x00004, 0x27C9C8C2, 0x00100, 0x2846B7DB, 0x00004,
|
||||
0x2969F5EB, 0x00004, 0x296C9DB8, 0x00004, 0x2985FE5D, 0x008D4, 0x298D9297, 0x00004,
|
||||
0x29FB8D78, 0x00004, 0x2BBF9423, 0x00001, 0x2BBF9789, 0x00001, 0x2BBF9CA2, 0x00001,
|
||||
0x2BBF9E55, 0x00001, 0x2C0B9BF3, 0x00004, 0x2C24C5F2, 0x00020, 0x2DBE7204, 0x04B00,
|
||||
0x2EB1B190, 0x00020, 0x2F85E20D, 0x00004, 0x305FD79A, 0x00008, 0x30967638, 0x00001,
|
||||
0x3096799E, 0x00001, 0x30967B51, 0x00001, 0x30B884F9, 0x00004, 0x3279D927, 0x00004,
|
||||
0x35BDC76F, 0x00001, 0x35BDC922, 0x00001, 0x3745DA43, 0x00004, 0x37B18444, 0x00004,
|
||||
0x385F9860, 0x00004, 0x388E378D, 0x00004, 0x3AAF5E5E, 0x00004, 0x3ADB8A98, 0x000C8,
|
||||
0x3B4D705E, 0x00001, 0x3B956C1A, 0x00004, 0x3BFC2C3C, 0x000D0, 0x3C4AADD3, 0x00008,
|
||||
0x3EBEE1A7, 0x00004, 0x3F5225A0, 0x00004, 0x3F7CC8A4, 0x00004, 0x3F8120BA, 0x00002,
|
||||
0x402FAC1D, 0x00001, 0x4033C7DB, 0x00001, 0x40892A39, 0x00004, 0x40CC5A21, 0x00002,
|
||||
0x40E13871, 0x00004, 0x41309084, 0x00001, 0x416A4820, 0x00004, 0x416A49D3, 0x00004,
|
||||
0x416A4D39, 0x00004, 0x416A5252, 0x00004, 0x416A5405, 0x00004, 0x431018F0, 0x00004,
|
||||
0x43749288, 0x00010, 0x444D8A2C, 0x00001, 0x44552BFF, 0x00004, 0x451E1BAF, 0x00020,
|
||||
0x457495AE, 0x00010, 0x45851092, 0x00064, 0x4618E7E4, 0x00004, 0x46459F4E, 0x00004,
|
||||
0x46749741, 0x00010, 0x477498D4, 0x00010, 0x47E1CEAB, 0x54600, 0x481DB963, 0x00001,
|
||||
0x481DBCC9, 0x00001, 0x481DBE7C, 0x00001, 0x481DC02F, 0x00001, 0x481DCA61, 0x00001,
|
||||
0x4820CC20, 0x00001, 0x4820CDD3, 0x00001, 0x4820CF86, 0x00001, 0x4820D139, 0x00001,
|
||||
0x4820D2EC, 0x00001, 0x4820D49F, 0x00001, 0x4820D805, 0x00001, 0x4820E3EA, 0x00001,
|
||||
0x4820E59D, 0x00001, 0x4823EE28, 0x00001, 0x4823EFDB, 0x00001, 0x4823F18E, 0x00001,
|
||||
0x4823F341, 0x00001, 0x4823F4F4, 0x00001, 0x4823F6A7, 0x00001, 0x4826224C, 0x00001,
|
||||
0x48262918, 0x00001, 0x48262ACB, 0x00001, 0x48262C7E, 0x00001, 0x48262E31, 0x00001,
|
||||
0x48263197, 0x00001, 0x4826334A, 0x00001, 0x482634FD, 0x00001, 0x48749A67, 0x00010,
|
||||
0x48CE01F7, 0x000FC, 0x48DDB755, 0x00006, 0x4918E303, 0x00001, 0x49749BFA, 0x00010,
|
||||
0x4A6B888D, 0x00004, 0x4A749D8D, 0x00010, 0x4AA3F543, 0x00004, 0x4AA3F6F6, 0x00004,
|
||||
0x4AAF7FBE, 0x00004, 0x4BD70B32, 0x041A0, 0x4C5C85AB, 0x00004, 0x4CF1F5D3, 0x00004,
|
||||
0x4D7EADDD, 0x00004, 0x4DB28157, 0x00004, 0x4EB3ECBB, 0x00004, 0x4EE2B115, 0x00008,
|
||||
0x4FBDB5FF, 0x00008, 0x500164D0, 0x00004, 0x50016683, 0x00004, 0x500687A1, 0x00004,
|
||||
0x509A1AC8, 0x00004, 0x509A1C7B, 0x00004, 0x509A1FE1, 0x00004, 0x50FE632A, 0x00004,
|
||||
0x511622B3, 0x88040, 0x5297D400, 0x00001, 0x5297D766, 0x00001, 0x5297D919, 0x00001,
|
||||
0x5297DACC, 0x00001, 0x5297DC7F, 0x00001, 0x5297EBCA, 0x00001, 0x5297ED7D, 0x00001,
|
||||
0x529AE870, 0x00001, 0x529AEA23, 0x00001, 0x529AF608, 0x00001, 0x529AF7BB, 0x00001,
|
||||
0x529AF96E, 0x00001, 0x529AFB21, 0x00001, 0x529AFCD4, 0x00001, 0x529AFE87, 0x00001,
|
||||
0x529B003A, 0x00001, 0x529B01ED, 0x00001, 0x52A96788, 0x00001, 0x52A9693B, 0x00001,
|
||||
0x52A96AEE, 0x00001, 0x52A96CA1, 0x00001, 0x52A96E54, 0x00001, 0x52A97007, 0x00001,
|
||||
0x52A971BA, 0x00001, 0x52A9736D, 0x00001, 0x52AC71C6, 0x00001, 0x52AC7379, 0x00001,
|
||||
0x52AC7BF8, 0x00001, 0x52AC7DAB, 0x00001, 0x52AC7F5E, 0x00001, 0x52AC8111, 0x00001,
|
||||
0x52AC82C4, 0x00001, 0x52AC8477, 0x00001, 0x52AC862A, 0x00001, 0x52AC87DD, 0x00001,
|
||||
0x52AF8D02, 0x00001, 0x52AF8EB5, 0x00001, 0x52AF9068, 0x00001, 0x52AF921B, 0x00001,
|
||||
0x52AF93CE, 0x00001, 0x52AF9581, 0x00001, 0x52AF9734, 0x00001, 0x52AF98E7, 0x00001,
|
||||
0x52AF9C4D, 0x00001, 0x52B27C10, 0x00001, 0x52B27DC3, 0x00001, 0x52B27F76, 0x00001,
|
||||
0x52B28129, 0x00001, 0x52B282DC, 0x00001, 0x52B2848F, 0x00001, 0x52B28642, 0x00001,
|
||||
0x52B287F5, 0x00001, 0x52B289A8, 0x00001, 0x52B28B5B, 0x00001, 0x52B4B700, 0x00001,
|
||||
0x52B4B8B3, 0x00001, 0x52B4BA66, 0x00001, 0x52B4BDCC, 0x00001, 0x52B4BF7F, 0x00001,
|
||||
0x52B4C132, 0x00001, 0x52B4C2E5, 0x00001, 0x52B4CB64, 0x00001, 0x52B4CD17, 0x00001,
|
||||
0x52B7CB70, 0x00001, 0x52B7CD23, 0x00001, 0x52B7D089, 0x00001, 0x52B7D23C, 0x00001,
|
||||
0x52B7D5A2, 0x00001, 0x52B7D755, 0x00001, 0x52BAE346, 0x00001, 0x52BAE4F9, 0x00001,
|
||||
0x52BAED78, 0x00001, 0x52BAEF2B, 0x00001, 0x52BAF291, 0x00001, 0x52BAF444, 0x00001,
|
||||
0x52BAF5F7, 0x00001, 0x52BAF7AA, 0x00001, 0x52BAF95D, 0x00001, 0x52BDFB1C, 0x00001,
|
||||
0x52BDFCCF, 0x00001, 0x52BE039B, 0x00001, 0x52BE054E, 0x00001, 0x52BE0701, 0x00001,
|
||||
0x52BE08B4, 0x00001, 0x52BE0A67, 0x00001, 0x52BE0C1A, 0x00001, 0x53DB799F, 0x00004,
|
||||
0x5423DAA0, 0x00004, 0x549B6033, 0x03000, 0x54DAE9C5, 0x00004, 0x567F1330, 0x00001,
|
||||
0x567F14E3, 0x00001, 0x567F1696, 0x00001, 0x567F1849, 0x00001, 0x567F19FC, 0x00001,
|
||||
0x56823385, 0x00001, 0x56878ECA, 0x00001, 0x5687907D, 0x00001, 0x57A07D08, 0x00004,
|
||||
0x57B1D097, 0x00004, 0x5898095A, 0x00004, 0x58AB6233, 0x00064, 0x58DC8855, 0x00004,
|
||||
0x590CD38E, 0x00004, 0x5979158E, 0x00004, 0x5988DF78, 0x00004, 0x59A4D0C3, 0x00190,
|
||||
0x5A39A553, 0x00004, 0x5B1F53F3, 0x00004, 0x5C283C72, 0x00008, 0x5C283E25, 0x00008,
|
||||
0x5C283FD8, 0x00008, 0x5C28418B, 0x00008, 0x5C28433E, 0x00008, 0x5C2844F1, 0x00008,
|
||||
0x5C2846A4, 0x00008, 0x5C284857, 0x00008, 0x5C284BBD, 0x00008, 0x61A7A35B, 0x00004,
|
||||
0x62E91A65, 0x00004, 0x62F05895, 0x00004, 0x636A5ABD, 0x000C8, 0x64A1A5B0, 0x00004,
|
||||
0x64A1A763, 0x00004, 0x64A1AE2F, 0x00004, 0x64A1AFE2, 0x00004, 0x64A1B195, 0x00004,
|
||||
0x6506EE96, 0x06D60, 0x651D61A2, 0x004B0, 0x67692BB8, 0x00004, 0x67692D6B, 0x00004,
|
||||
0x67692F1E, 0x00004, 0x676935EA, 0x00004, 0x6769379D, 0x00004, 0x6960C6EF, 0x00004,
|
||||
0x6AFB0A16, 0x00004, 0x6B35BADB, 0x00060, 0x6B734EFD, 0x00004, 0x6C03D4A8, 0x00014,
|
||||
0x6C99F9A0, 0x00002, 0x6EB3E8A0, 0x00004, 0x6F36A3AC, 0x00004, 0x717DDAA3, 0x00008,
|
||||
0x71825204, 0x00001, 0x72391B04, 0x00004, 0x727AE2EE, 0x00004, 0x727AE4A1, 0x00004,
|
||||
0x727AE654, 0x00004, 0x727AE807, 0x00004, 0x727AE9BA, 0x00004, 0x74026290, 0x00004,
|
||||
0x744447B4, 0x00004, 0x75931048, 0x00004, 0x75931561, 0x00004, 0x75CE2CF6, 0x00004,
|
||||
0x7659EC88, 0x00004, 0x76AB1B01, 0x00004, 0x76ABB5CD, 0x00004, 0x77675FA0, 0x00320,
|
||||
0x7799EB86, 0x03980, 0x77B752BC, 0x00004, 0x77B75622, 0x00004, 0x77B757D5, 0x00004,
|
||||
0x78848293, 0x00001, 0x78848446, 0x00001, 0x788485F9, 0x00001, 0x78E0935E, 0x00004,
|
||||
0x79448B5D, 0x00004, 0x79C56A5C, 0x00004, 0x7A8530FD, 0x00004, 0x7ACB8CB5, 0x00004,
|
||||
0x7B8CCB0B, 0x00180, 0x7CA9D9FA, 0x00004, 0x7D249649, 0x00004, 0x7D87DC83, 0x00004,
|
||||
0x7E82513F, 0x00004, 0x8048A7DC, 0x00004, 0x8184EFB4, 0x00004, 0x81EC3A78, 0x00004,
|
||||
0x82AD5F84, 0x00004, 0x82D57F17, 0x000C8, 0x8507839C, 0x00004, 0x85166DE2, 0x00004,
|
||||
0x877CB98F, 0x009B0, 0x885E5F53, 0x00010, 0x89C1C8DE, 0x00004, 0x8A0E9425, 0x004B0,
|
||||
0x8B18A566, 0x00004, 0x8B18A719, 0x00004, 0x8B18A8CC, 0x00004, 0x8B18AA7F, 0x00004,
|
||||
0x8B18AC32, 0x00004, 0x8B18ADE5, 0x00004, 0x8B8FB439, 0x00004, 0x8BDFF0F3, 0x00040,
|
||||
0x8BEEF106, 0x00004, 0x8C46768E, 0x00004, 0x8C5F59E8, 0x00004, 0x8D781241, 0x00008,
|
||||
0x8E434F0D, 0x002D0, 0x8F0D8720, 0x00004, 0x8FC0A045, 0x00004, 0x92EB0306, 0x00004,
|
||||
0x92F697ED, 0x00004, 0x95013114, 0x00008, 0x96993D83, 0x00008, 0x96F6F453, 0x00004,
|
||||
0x9751BABE, 0x00400, 0x98785EE4, 0x00008, 0x98786097, 0x00008, 0x987863FD, 0x00008,
|
||||
0x99E1625E, 0x07EB0, 0x9AB5F3D9, 0x00001, 0x9B986D2E, 0x00004, 0x9C41123A, 0x00004,
|
||||
0x9C808BD3, 0x00004, 0x9D5D1CA5, 0x00004, 0x9E45BE99, 0x00004, 0x9E4635BB, 0x00004,
|
||||
0x9EC079DA, 0x00002, 0x9FE2790A, 0x00A8C, 0xA00A8ABB, 0x00008, 0xA2AA5B41, 0x00004,
|
||||
0xA373DA53, 0x01900, 0xA4317061, 0x00004, 0xA69E079B, 0x00004, 0xA94E1F5F, 0x00004,
|
||||
0xA9F1368B, 0x00004, 0xAB48C136, 0x00004, 0xAD319811, 0x00004, 0xAE7B3CA1, 0x00004,
|
||||
0xAE89206E, 0x00001, 0xAEE903A2, 0x00008, 0xB027F396, 0x00004, 0xB0B2A5AA, 0x00004,
|
||||
0xB1EE7CF5, 0x00004, 0xB568265C, 0x00004, 0xB79EF1FE, 0x00004, 0xB7AAB47E, 0x00004,
|
||||
0xB7DB15CC, 0x00004, 0xB8E961AD, 0x000FB, 0xB9075BC9, 0x00008, 0xB9252862, 0x00110,
|
||||
0xBA230941, 0x00004, 0xBB0B39CF, 0x00004, 0xBCC66014, 0x00004, 0xBCC72306, 0x00004,
|
||||
0xBCE74BFD, 0x00004, 0xBDDC386E, 0x00004, 0xC02AC847, 0x00004, 0xC25B0D5A, 0x00004,
|
||||
0xC2F1C1B9, 0x02580, 0xC4C6417F, 0x000C0, 0xC4FA7C8C, 0x00004, 0xC5277828, 0x00008,
|
||||
0xC5919BF6, 0x00004, 0xC5D7112B, 0x0DCA8, 0xC69F66B6, 0x00FA0, 0xC74A3FE7, 0x00010,
|
||||
0xC7652F1C, 0x00004, 0xC7F8E3BC, 0x00008, 0xC7F8E56F, 0x00008, 0xC7F8EA88, 0x00008,
|
||||
0xC7F8EC3B, 0x00008, 0xC7F8EDEE, 0x00008, 0xC7F8EFA1, 0x00008, 0xC7F8F154, 0x00008,
|
||||
0xC7F8F4BA, 0x00008, 0xC7F8F66D, 0x00008, 0xC9541EB3, 0x00002, 0xC9A81578, 0x00010,
|
||||
0xCC022CEC, 0x00008, 0xCC022E9F, 0x00008, 0xCC023052, 0x00008, 0xCD8ADF1D, 0x00004,
|
||||
0xCFC9AA03, 0x00004, 0xCFEB27B3, 0x009C4, 0xCFED4C69, 0x00004, 0xD0068A74, 0x00004,
|
||||
0xD03A595A, 0x009B0, 0xD06FD1EA, 0x00004, 0xD11C1F59, 0x00004, 0xD20DF4A0, 0x00004,
|
||||
0xD2E5D408, 0x00004, 0xD3C06782, 0x00008, 0xD48FDC48, 0x00004, 0xD6546A02, 0x00038,
|
||||
0xD6C95683, 0x00960, 0xD6F1B724, 0x00004, 0xD8048E00, 0x00004, 0xD94D71D7, 0x00004,
|
||||
0xDD548BB1, 0x00B58, 0xDED70F11, 0x00004, 0xDFA7E2D8, 0x00004, 0xE0FB1EE7, 0x00008,
|
||||
0xE1DF0672, 0x005B8, 0xE2798DDE, 0x00001, 0xE36D5700, 0x00064, 0xE450FEF7, 0x0001A,
|
||||
0xE4E75089, 0x00040, 0xE5169DA1, 0x00004, 0xE668F1A6, 0x00001, 0xE668F359, 0x00001,
|
||||
0xE668F50C, 0x00001, 0xE668F6BF, 0x00001, 0xE668FA25, 0x00001, 0xE72BDCEC, 0x00004,
|
||||
0xE733FE4D, 0x00004, 0xE7425CFF, 0x00004, 0xE793EEAE, 0x00004, 0xEA7C87F4, 0x00020,
|
||||
0xEB550C12, 0x00004, 0xEC13DFD7, 0x00004, 0xEE10F128, 0x00004, 0xEFB533F7, 0x00001,
|
||||
0xF25C070E, 0x00080, 0xF32218C2, 0x00004, 0xF3CF94FF, 0x00004, 0xF41CFF61, 0x00200,
|
||||
0xF45C3F59, 0x00004, 0xF4954B60, 0x00004, 0xF5D9F4A5, 0x00118, 0xF626721E, 0x00004,
|
||||
0xF62D79D3, 0x00004, 0xF8154AC9, 0x00004, 0xFB58B1A7, 0x00064, 0xFB5AE87D, 0x00004,
|
||||
0xFC374750, 0x00004, 0xFF400328, 0x00004, 0xFFCC05C2, 0x00001,
|
||||
];
|
||||
}
|
|
@ -1,52 +1,18 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace PKHeX.Core;
|
||||
|
||||
public static class Meta8
|
||||
/// <summary>
|
||||
/// <see cref="SCBlock"/> metadata for <see cref="GameVersion.SWSH"/>
|
||||
/// </summary>
|
||||
public static class BlankBlocks8
|
||||
{
|
||||
public static SCBlock[] GetBlankDataSWSH() => GetBlankBlockArray(DefaultChunkSizesSWSH);
|
||||
public static SCBlock[] GetBlankDataLA() => GetBlankBlockArray(DefaultChunkSizesLA);
|
||||
|
||||
/// <summary>
|
||||
/// Create a blank block array using the provided <see cref="arr"/> definition.
|
||||
/// Creates a blank <see cref="SCBlock"/> array for <see cref="GameVersion.SWSH"/>
|
||||
/// </summary>
|
||||
/// <param name="arr">Block specification tuples (key, size)</param>
|
||||
/// <returns>List of blocks</returns>
|
||||
private static SCBlock[] GetBlankBlockArray(ReadOnlySpan<uint> arr)
|
||||
{
|
||||
var blocks = new SCBlock[arr.Length / 2];
|
||||
for (int i = 0; i < blocks.Length; i++)
|
||||
{
|
||||
int index = i * 2;
|
||||
var key = arr[index];
|
||||
var length = (int) arr[index + 1];
|
||||
var dummy = new byte[length];
|
||||
blocks[i] = new SCBlock(key, SCTypeCode.None, dummy);
|
||||
}
|
||||
return blocks;
|
||||
}
|
||||
public static SCBlock[] GetBlankBlocks() => SCBlockUtil.GetBlankBlockArray(DefaultChunkSizes);
|
||||
|
||||
#if DEBUG
|
||||
public static IEnumerable<string> RipSizes(IReadOnlyCollection<SCBlock> blocks)
|
||||
{
|
||||
int ctr = 0;
|
||||
foreach (var block in blocks)
|
||||
{
|
||||
if (block.Data.Length == 0)
|
||||
continue;
|
||||
if (ctr == 4)
|
||||
{
|
||||
yield return Environment.NewLine;
|
||||
ctr = 0;
|
||||
}
|
||||
yield return $"0x{block.Key:X8}, 0x{block.Data.Length:X5}, ";
|
||||
ctr++;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
private static ReadOnlySpan<uint> DefaultChunkSizesSWSH =>
|
||||
private static ReadOnlySpan<uint> DefaultChunkSizes =>
|
||||
[
|
||||
0x00A1F55B, 0x00004, 0x0123EA7A, 0x00004, 0x017C3CBB, 0x00001, 0x0192A204, 0x00009,
|
||||
0x01A1F6EE, 0x00004, 0x01BFCAD0, 0x00002, 0x02B647B4, 0x00004, 0x02BFCC63, 0x00002,
|
||||
|
@ -269,133 +235,4 @@ public static class Meta8
|
|||
0xFEB13D33, 0x00002, 0xFEB64141, 0x00001, 0xFEE68CE1, 0x00004, 0xFF4498B1, 0x00002,
|
||||
0xFFA1F3C8, 0x00004,
|
||||
];
|
||||
|
||||
private static ReadOnlySpan<uint> DefaultChunkSizesLA =>
|
||||
[
|
||||
0x00EF4BAE, 0x00140, 0x017C3CBB, 0x00001, 0x02168706, 0x1E460, 0x022A2253, 0x00001,
|
||||
0x024C8CF3, 0x00004, 0x033D60DA, 0x00004, 0x0493AF74, 0x00004, 0x04AE4181, 0x00001,
|
||||
0x04EABECF, 0x00004, 0x050E9D63, 0x00004, 0x05E7EBEB, 0x02EE0, 0x062AF6C2, 0x00020,
|
||||
0x069EAD42, 0x00004, 0x070F34AD, 0x00020, 0x0821C372, 0x00004, 0x0A40A680, 0x00004,
|
||||
0x0A49F0EF, 0x01F40, 0x0B3C5217, 0x00004, 0x0BFDEBA1, 0x00004, 0x0E6246BE, 0x00004,
|
||||
0x0F3AD63C, 0x00004, 0x10A052BA, 0x00008, 0x10A0546D, 0x00008, 0x10D148DE, 0x00004,
|
||||
0x111933CD, 0x00004, 0x11B37EC9, 0x000C8, 0x13A0E18B, 0x00004, 0x17833C07, 0x00004,
|
||||
0x17EB7C4D, 0x00004, 0x180A4E9F, 0x00004, 0x19722C89, 0x00440, 0x1B1E3D8B, 0x00004,
|
||||
0x1B5E0528, 0x00001, 0x1B65ABFD, 0x00004, 0x1BF70FCB, 0x00004, 0x1D482A63, 0x00004,
|
||||
0x1E0F1BA3, 0x00190, 0x203A7F34, 0x00008, 0x2085565F, 0x00001, 0x20855812, 0x00001,
|
||||
0x208559C5, 0x00001, 0x208D511F, 0x00004, 0x2123FE4A, 0x00004, 0x2137FAFF, 0x00004,
|
||||
0x22540FF0, 0x00004, 0x22DEF108, 0x00004, 0x23AA6AE3, 0x00004, 0x24E0D195, 0x002F2,
|
||||
0x250F3C75, 0x00004, 0x267DD9DA, 0x00070, 0x2728E588, 0x00004, 0x27931A29, 0x00004,
|
||||
0x27986623, 0x00004, 0x279EA6CD, 0x00004, 0x27C9C8C2, 0x00100, 0x2846B7DB, 0x00004,
|
||||
0x2969F5EB, 0x00004, 0x296C9DB8, 0x00004, 0x2985FE5D, 0x008D4, 0x298D9297, 0x00004,
|
||||
0x29FB8D78, 0x00004, 0x2BBF9423, 0x00001, 0x2BBF9789, 0x00001, 0x2BBF9CA2, 0x00001,
|
||||
0x2BBF9E55, 0x00001, 0x2C0B9BF3, 0x00004, 0x2C24C5F2, 0x00020, 0x2DBE7204, 0x04B00,
|
||||
0x2EB1B190, 0x00020, 0x2F85E20D, 0x00004, 0x305FD79A, 0x00008, 0x30967638, 0x00001,
|
||||
0x3096799E, 0x00001, 0x30967B51, 0x00001, 0x30B884F9, 0x00004, 0x3279D927, 0x00004,
|
||||
0x35BDC76F, 0x00001, 0x35BDC922, 0x00001, 0x3745DA43, 0x00004, 0x37B18444, 0x00004,
|
||||
0x385F9860, 0x00004, 0x388E378D, 0x00004, 0x3AAF5E5E, 0x00004, 0x3ADB8A98, 0x000C8,
|
||||
0x3B4D705E, 0x00001, 0x3B956C1A, 0x00004, 0x3BFC2C3C, 0x000D0, 0x3C4AADD3, 0x00008,
|
||||
0x3EBEE1A7, 0x00004, 0x3F5225A0, 0x00004, 0x3F7CC8A4, 0x00004, 0x3F8120BA, 0x00002,
|
||||
0x402FAC1D, 0x00001, 0x4033C7DB, 0x00001, 0x40892A39, 0x00004, 0x40CC5A21, 0x00002,
|
||||
0x40E13871, 0x00004, 0x41309084, 0x00001, 0x416A4820, 0x00004, 0x416A49D3, 0x00004,
|
||||
0x416A4D39, 0x00004, 0x416A5252, 0x00004, 0x416A5405, 0x00004, 0x431018F0, 0x00004,
|
||||
0x43749288, 0x00010, 0x444D8A2C, 0x00001, 0x44552BFF, 0x00004, 0x451E1BAF, 0x00020,
|
||||
0x457495AE, 0x00010, 0x45851092, 0x00064, 0x4618E7E4, 0x00004, 0x46459F4E, 0x00004,
|
||||
0x46749741, 0x00010, 0x477498D4, 0x00010, 0x47E1CEAB, 0x54600, 0x481DB963, 0x00001,
|
||||
0x481DBCC9, 0x00001, 0x481DBE7C, 0x00001, 0x481DC02F, 0x00001, 0x481DCA61, 0x00001,
|
||||
0x4820CC20, 0x00001, 0x4820CDD3, 0x00001, 0x4820CF86, 0x00001, 0x4820D139, 0x00001,
|
||||
0x4820D2EC, 0x00001, 0x4820D49F, 0x00001, 0x4820D805, 0x00001, 0x4820E3EA, 0x00001,
|
||||
0x4820E59D, 0x00001, 0x4823EE28, 0x00001, 0x4823EFDB, 0x00001, 0x4823F18E, 0x00001,
|
||||
0x4823F341, 0x00001, 0x4823F4F4, 0x00001, 0x4823F6A7, 0x00001, 0x4826224C, 0x00001,
|
||||
0x48262918, 0x00001, 0x48262ACB, 0x00001, 0x48262C7E, 0x00001, 0x48262E31, 0x00001,
|
||||
0x48263197, 0x00001, 0x4826334A, 0x00001, 0x482634FD, 0x00001, 0x48749A67, 0x00010,
|
||||
0x48CE01F7, 0x000FC, 0x48DDB755, 0x00006, 0x4918E303, 0x00001, 0x49749BFA, 0x00010,
|
||||
0x4A6B888D, 0x00004, 0x4A749D8D, 0x00010, 0x4AA3F543, 0x00004, 0x4AA3F6F6, 0x00004,
|
||||
0x4AAF7FBE, 0x00004, 0x4BD70B32, 0x041A0, 0x4C5C85AB, 0x00004, 0x4CF1F5D3, 0x00004,
|
||||
0x4D7EADDD, 0x00004, 0x4DB28157, 0x00004, 0x4EB3ECBB, 0x00004, 0x4EE2B115, 0x00008,
|
||||
0x4FBDB5FF, 0x00008, 0x500164D0, 0x00004, 0x50016683, 0x00004, 0x500687A1, 0x00004,
|
||||
0x509A1AC8, 0x00004, 0x509A1C7B, 0x00004, 0x509A1FE1, 0x00004, 0x50FE632A, 0x00004,
|
||||
0x511622B3, 0x88040, 0x5297D400, 0x00001, 0x5297D766, 0x00001, 0x5297D919, 0x00001,
|
||||
0x5297DACC, 0x00001, 0x5297DC7F, 0x00001, 0x5297EBCA, 0x00001, 0x5297ED7D, 0x00001,
|
||||
0x529AE870, 0x00001, 0x529AEA23, 0x00001, 0x529AF608, 0x00001, 0x529AF7BB, 0x00001,
|
||||
0x529AF96E, 0x00001, 0x529AFB21, 0x00001, 0x529AFCD4, 0x00001, 0x529AFE87, 0x00001,
|
||||
0x529B003A, 0x00001, 0x529B01ED, 0x00001, 0x52A96788, 0x00001, 0x52A9693B, 0x00001,
|
||||
0x52A96AEE, 0x00001, 0x52A96CA1, 0x00001, 0x52A96E54, 0x00001, 0x52A97007, 0x00001,
|
||||
0x52A971BA, 0x00001, 0x52A9736D, 0x00001, 0x52AC71C6, 0x00001, 0x52AC7379, 0x00001,
|
||||
0x52AC7BF8, 0x00001, 0x52AC7DAB, 0x00001, 0x52AC7F5E, 0x00001, 0x52AC8111, 0x00001,
|
||||
0x52AC82C4, 0x00001, 0x52AC8477, 0x00001, 0x52AC862A, 0x00001, 0x52AC87DD, 0x00001,
|
||||
0x52AF8D02, 0x00001, 0x52AF8EB5, 0x00001, 0x52AF9068, 0x00001, 0x52AF921B, 0x00001,
|
||||
0x52AF93CE, 0x00001, 0x52AF9581, 0x00001, 0x52AF9734, 0x00001, 0x52AF98E7, 0x00001,
|
||||
0x52AF9C4D, 0x00001, 0x52B27C10, 0x00001, 0x52B27DC3, 0x00001, 0x52B27F76, 0x00001,
|
||||
0x52B28129, 0x00001, 0x52B282DC, 0x00001, 0x52B2848F, 0x00001, 0x52B28642, 0x00001,
|
||||
0x52B287F5, 0x00001, 0x52B289A8, 0x00001, 0x52B28B5B, 0x00001, 0x52B4B700, 0x00001,
|
||||
0x52B4B8B3, 0x00001, 0x52B4BA66, 0x00001, 0x52B4BDCC, 0x00001, 0x52B4BF7F, 0x00001,
|
||||
0x52B4C132, 0x00001, 0x52B4C2E5, 0x00001, 0x52B4CB64, 0x00001, 0x52B4CD17, 0x00001,
|
||||
0x52B7CB70, 0x00001, 0x52B7CD23, 0x00001, 0x52B7D089, 0x00001, 0x52B7D23C, 0x00001,
|
||||
0x52B7D5A2, 0x00001, 0x52B7D755, 0x00001, 0x52BAE346, 0x00001, 0x52BAE4F9, 0x00001,
|
||||
0x52BAED78, 0x00001, 0x52BAEF2B, 0x00001, 0x52BAF291, 0x00001, 0x52BAF444, 0x00001,
|
||||
0x52BAF5F7, 0x00001, 0x52BAF7AA, 0x00001, 0x52BAF95D, 0x00001, 0x52BDFB1C, 0x00001,
|
||||
0x52BDFCCF, 0x00001, 0x52BE039B, 0x00001, 0x52BE054E, 0x00001, 0x52BE0701, 0x00001,
|
||||
0x52BE08B4, 0x00001, 0x52BE0A67, 0x00001, 0x52BE0C1A, 0x00001, 0x53DB799F, 0x00004,
|
||||
0x5423DAA0, 0x00004, 0x549B6033, 0x03000, 0x54DAE9C5, 0x00004, 0x567F1330, 0x00001,
|
||||
0x567F14E3, 0x00001, 0x567F1696, 0x00001, 0x567F1849, 0x00001, 0x567F19FC, 0x00001,
|
||||
0x56823385, 0x00001, 0x56878ECA, 0x00001, 0x5687907D, 0x00001, 0x57A07D08, 0x00004,
|
||||
0x57B1D097, 0x00004, 0x5898095A, 0x00004, 0x58AB6233, 0x00064, 0x58DC8855, 0x00004,
|
||||
0x590CD38E, 0x00004, 0x5979158E, 0x00004, 0x5988DF78, 0x00004, 0x59A4D0C3, 0x00190,
|
||||
0x5A39A553, 0x00004, 0x5B1F53F3, 0x00004, 0x5C283C72, 0x00008, 0x5C283E25, 0x00008,
|
||||
0x5C283FD8, 0x00008, 0x5C28418B, 0x00008, 0x5C28433E, 0x00008, 0x5C2844F1, 0x00008,
|
||||
0x5C2846A4, 0x00008, 0x5C284857, 0x00008, 0x5C284BBD, 0x00008, 0x61A7A35B, 0x00004,
|
||||
0x62E91A65, 0x00004, 0x62F05895, 0x00004, 0x636A5ABD, 0x000C8, 0x64A1A5B0, 0x00004,
|
||||
0x64A1A763, 0x00004, 0x64A1AE2F, 0x00004, 0x64A1AFE2, 0x00004, 0x64A1B195, 0x00004,
|
||||
0x6506EE96, 0x06D60, 0x651D61A2, 0x004B0, 0x67692BB8, 0x00004, 0x67692D6B, 0x00004,
|
||||
0x67692F1E, 0x00004, 0x676935EA, 0x00004, 0x6769379D, 0x00004, 0x6960C6EF, 0x00004,
|
||||
0x6AFB0A16, 0x00004, 0x6B35BADB, 0x00060, 0x6B734EFD, 0x00004, 0x6C03D4A8, 0x00014,
|
||||
0x6C99F9A0, 0x00002, 0x6EB3E8A0, 0x00004, 0x6F36A3AC, 0x00004, 0x717DDAA3, 0x00008,
|
||||
0x71825204, 0x00001, 0x72391B04, 0x00004, 0x727AE2EE, 0x00004, 0x727AE4A1, 0x00004,
|
||||
0x727AE654, 0x00004, 0x727AE807, 0x00004, 0x727AE9BA, 0x00004, 0x74026290, 0x00004,
|
||||
0x744447B4, 0x00004, 0x75931048, 0x00004, 0x75931561, 0x00004, 0x75CE2CF6, 0x00004,
|
||||
0x7659EC88, 0x00004, 0x76AB1B01, 0x00004, 0x76ABB5CD, 0x00004, 0x77675FA0, 0x00320,
|
||||
0x7799EB86, 0x03980, 0x77B752BC, 0x00004, 0x77B75622, 0x00004, 0x77B757D5, 0x00004,
|
||||
0x78848293, 0x00001, 0x78848446, 0x00001, 0x788485F9, 0x00001, 0x78E0935E, 0x00004,
|
||||
0x79448B5D, 0x00004, 0x79C56A5C, 0x00004, 0x7A8530FD, 0x00004, 0x7ACB8CB5, 0x00004,
|
||||
0x7B8CCB0B, 0x00180, 0x7CA9D9FA, 0x00004, 0x7D249649, 0x00004, 0x7D87DC83, 0x00004,
|
||||
0x7E82513F, 0x00004, 0x8048A7DC, 0x00004, 0x8184EFB4, 0x00004, 0x81EC3A78, 0x00004,
|
||||
0x82AD5F84, 0x00004, 0x82D57F17, 0x000C8, 0x8507839C, 0x00004, 0x85166DE2, 0x00004,
|
||||
0x877CB98F, 0x009B0, 0x885E5F53, 0x00010, 0x89C1C8DE, 0x00004, 0x8A0E9425, 0x004B0,
|
||||
0x8B18A566, 0x00004, 0x8B18A719, 0x00004, 0x8B18A8CC, 0x00004, 0x8B18AA7F, 0x00004,
|
||||
0x8B18AC32, 0x00004, 0x8B18ADE5, 0x00004, 0x8B8FB439, 0x00004, 0x8BDFF0F3, 0x00040,
|
||||
0x8BEEF106, 0x00004, 0x8C46768E, 0x00004, 0x8C5F59E8, 0x00004, 0x8D781241, 0x00008,
|
||||
0x8E434F0D, 0x002D0, 0x8F0D8720, 0x00004, 0x8FC0A045, 0x00004, 0x92EB0306, 0x00004,
|
||||
0x92F697ED, 0x00004, 0x95013114, 0x00008, 0x96993D83, 0x00008, 0x96F6F453, 0x00004,
|
||||
0x9751BABE, 0x00400, 0x98785EE4, 0x00008, 0x98786097, 0x00008, 0x987863FD, 0x00008,
|
||||
0x99E1625E, 0x07EB0, 0x9AB5F3D9, 0x00001, 0x9B986D2E, 0x00004, 0x9C41123A, 0x00004,
|
||||
0x9C808BD3, 0x00004, 0x9D5D1CA5, 0x00004, 0x9E45BE99, 0x00004, 0x9E4635BB, 0x00004,
|
||||
0x9EC079DA, 0x00002, 0x9FE2790A, 0x00A8C, 0xA00A8ABB, 0x00008, 0xA2AA5B41, 0x00004,
|
||||
0xA373DA53, 0x01900, 0xA4317061, 0x00004, 0xA69E079B, 0x00004, 0xA94E1F5F, 0x00004,
|
||||
0xA9F1368B, 0x00004, 0xAB48C136, 0x00004, 0xAD319811, 0x00004, 0xAE7B3CA1, 0x00004,
|
||||
0xAE89206E, 0x00001, 0xAEE903A2, 0x00008, 0xB027F396, 0x00004, 0xB0B2A5AA, 0x00004,
|
||||
0xB1EE7CF5, 0x00004, 0xB568265C, 0x00004, 0xB79EF1FE, 0x00004, 0xB7AAB47E, 0x00004,
|
||||
0xB7DB15CC, 0x00004, 0xB8E961AD, 0x000FB, 0xB9075BC9, 0x00008, 0xB9252862, 0x00110,
|
||||
0xBA230941, 0x00004, 0xBB0B39CF, 0x00004, 0xBCC66014, 0x00004, 0xBCC72306, 0x00004,
|
||||
0xBCE74BFD, 0x00004, 0xBDDC386E, 0x00004, 0xC02AC847, 0x00004, 0xC25B0D5A, 0x00004,
|
||||
0xC2F1C1B9, 0x02580, 0xC4C6417F, 0x000C0, 0xC4FA7C8C, 0x00004, 0xC5277828, 0x00008,
|
||||
0xC5919BF6, 0x00004, 0xC5D7112B, 0x0DCA8, 0xC69F66B6, 0x00FA0, 0xC74A3FE7, 0x00010,
|
||||
0xC7652F1C, 0x00004, 0xC7F8E3BC, 0x00008, 0xC7F8E56F, 0x00008, 0xC7F8EA88, 0x00008,
|
||||
0xC7F8EC3B, 0x00008, 0xC7F8EDEE, 0x00008, 0xC7F8EFA1, 0x00008, 0xC7F8F154, 0x00008,
|
||||
0xC7F8F4BA, 0x00008, 0xC7F8F66D, 0x00008, 0xC9541EB3, 0x00002, 0xC9A81578, 0x00010,
|
||||
0xCC022CEC, 0x00008, 0xCC022E9F, 0x00008, 0xCC023052, 0x00008, 0xCD8ADF1D, 0x00004,
|
||||
0xCFC9AA03, 0x00004, 0xCFEB27B3, 0x009C4, 0xCFED4C69, 0x00004, 0xD0068A74, 0x00004,
|
||||
0xD03A595A, 0x009B0, 0xD06FD1EA, 0x00004, 0xD11C1F59, 0x00004, 0xD20DF4A0, 0x00004,
|
||||
0xD2E5D408, 0x00004, 0xD3C06782, 0x00008, 0xD48FDC48, 0x00004, 0xD6546A02, 0x00038,
|
||||
0xD6C95683, 0x00960, 0xD6F1B724, 0x00004, 0xD8048E00, 0x00004, 0xD94D71D7, 0x00004,
|
||||
0xDD548BB1, 0x00B58, 0xDED70F11, 0x00004, 0xDFA7E2D8, 0x00004, 0xE0FB1EE7, 0x00008,
|
||||
0xE1DF0672, 0x005B8, 0xE2798DDE, 0x00001, 0xE36D5700, 0x00064, 0xE450FEF7, 0x0001A,
|
||||
0xE4E75089, 0x00040, 0xE5169DA1, 0x00004, 0xE668F1A6, 0x00001, 0xE668F359, 0x00001,
|
||||
0xE668F50C, 0x00001, 0xE668F6BF, 0x00001, 0xE668FA25, 0x00001, 0xE72BDCEC, 0x00004,
|
||||
0xE733FE4D, 0x00004, 0xE7425CFF, 0x00004, 0xE793EEAE, 0x00004, 0xEA7C87F4, 0x00020,
|
||||
0xEB550C12, 0x00004, 0xEC13DFD7, 0x00004, 0xEE10F128, 0x00004, 0xEFB533F7, 0x00001,
|
||||
0xF25C070E, 0x00080, 0xF32218C2, 0x00004, 0xF3CF94FF, 0x00004, 0xF41CFF61, 0x00200,
|
||||
0xF45C3F59, 0x00004, 0xF4954B60, 0x00004, 0xF5D9F4A5, 0x00118, 0xF626721E, 0x00004,
|
||||
0xF62D79D3, 0x00004, 0xF8154AC9, 0x00004, 0xFB58B1A7, 0x00064, 0xFB5AE87D, 0x00004,
|
||||
0xFC374750, 0x00004, 0xFF400328, 0x00004, 0xFFCC05C2, 0x00001,
|
||||
];
|
||||
}
|
|
@ -1,52 +1,20 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace PKHeX.Core;
|
||||
|
||||
public static class Meta9
|
||||
/// <summary>
|
||||
/// <see cref="SCBlock"/> metadata for Generation 9 games.
|
||||
/// </summary>
|
||||
public static class BlankBlocks9
|
||||
{
|
||||
public const byte BlankRevision = 2;
|
||||
public static SCBlock[] GetBlankDataSV() => GetBlankBlockArray(DefaultChunkSizesSV);
|
||||
public const byte BlankRevision = 2; // Latest, Blueberry
|
||||
|
||||
/// <summary>
|
||||
/// Create a blank block array using the provided <see cref="arr"/> definition.
|
||||
/// Creates a blank <see cref="SCBlock"/> array for <see cref="GameVersion.SV"/>
|
||||
/// </summary>
|
||||
/// <param name="arr">Block specification tuples (key, size)</param>
|
||||
/// <returns>List of blocks</returns>
|
||||
private static SCBlock[] GetBlankBlockArray(ReadOnlySpan<uint> arr)
|
||||
{
|
||||
var blocks = new SCBlock[arr.Length / 2];
|
||||
for (int i = 0; i < blocks.Length; i++)
|
||||
{
|
||||
int index = i * 2;
|
||||
var key = arr[index];
|
||||
var length = (int) arr[index + 1];
|
||||
var dummy = new byte[length];
|
||||
blocks[i] = new SCBlock(key, SCTypeCode.None, dummy);
|
||||
}
|
||||
return blocks;
|
||||
}
|
||||
public static SCBlock[] GetBlankBlocks() => SCBlockUtil.GetBlankBlockArray(DefaultChunkSizes);
|
||||
|
||||
#if DEBUG
|
||||
public static IEnumerable<string> RipSizes(IReadOnlyCollection<SCBlock> blocks)
|
||||
{
|
||||
int ctr = 0;
|
||||
foreach (var block in blocks)
|
||||
{
|
||||
if (block.Data.Length == 0)
|
||||
continue;
|
||||
if (ctr == 4)
|
||||
{
|
||||
yield return Environment.NewLine;
|
||||
ctr = 0;
|
||||
}
|
||||
yield return $"0x{block.Key:X8}, 0x{block.Data.Length:X5}, ";
|
||||
ctr++;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
private static ReadOnlySpan<uint> DefaultChunkSizesSV =>
|
||||
private static ReadOnlySpan<uint> DefaultChunkSizes =>
|
||||
[
|
||||
0x00051292, 0x00008, 0x00182D33, 0x00008, 0x0018E0B9, 0x00008, 0x001FD42F, 0x00008,
|
||||
0x0022B5C9, 0x00008, 0x003096FA, 0x00008, 0x0031E2C7, 0x00008, 0x003D333A, 0x00020,
|
|
@ -1,12 +0,0 @@
|
|||
using System.Collections.Generic;
|
||||
|
||||
namespace PKHeX.Core;
|
||||
|
||||
public interface IRentalTeam<T> where T : PKM
|
||||
{
|
||||
T GetSlot(int slot);
|
||||
void SetSlot(int slot, T pk);
|
||||
|
||||
T[] GetTeam();
|
||||
void SetTeam(IReadOnlyList<T> team);
|
||||
}
|
|
@ -1,7 +1,17 @@
|
|||
namespace PKHeX.Core;
|
||||
namespace PKHeX.Core;
|
||||
|
||||
/// <summary>
|
||||
/// Exposes information to differentiate the save file from other patches of the same game.
|
||||
/// </summary>
|
||||
public interface ISaveFileRevision
|
||||
{
|
||||
/// <summary>
|
||||
/// Incremented magic number to differentiate feature sets available.
|
||||
/// </summary>
|
||||
int SaveRevision { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Magic string to differentiate feature sets available.
|
||||
/// </summary>
|
||||
string SaveRevisionString { get; }
|
||||
}
|
||||
|
|
|
@ -1,7 +1,18 @@
|
|||
namespace PKHeX.Core;
|
||||
|
||||
/// <summary>
|
||||
/// Stores the previous timestamp and the current timestamp.
|
||||
/// </summary>
|
||||
public interface ISecureValueStorage
|
||||
{
|
||||
/// <summary>
|
||||
/// Timestamp that the file was previously saved at.
|
||||
/// </summary>
|
||||
/// <remarks>Useful for remembering the timestamp of a backup, if present.</remarks>
|
||||
ulong TimeStampPrevious { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Timestamp that the file was last saved at.
|
||||
/// </summary>
|
||||
ulong TimeStampCurrent { get; set; }
|
||||
}
|
||||
|
|
35
PKHeX.Core/Saves/Substructures/Rentals/IRentalTeam.cs
Normal file
35
PKHeX.Core/Saves/Substructures/Rentals/IRentalTeam.cs
Normal file
|
@ -0,0 +1,35 @@
|
|||
using System;
|
||||
|
||||
namespace PKHeX.Core;
|
||||
|
||||
/// <summary>
|
||||
/// Exposes a rental team interface to fetch team data.
|
||||
/// </summary>
|
||||
/// <typeparam name="T">Type of entity stored in the rental team</typeparam>
|
||||
public interface IRentalTeam<T> where T : PKM
|
||||
{
|
||||
/// <summary>
|
||||
/// Gets the entity at a specific slot.
|
||||
/// </summary>
|
||||
T GetSlot(int slot);
|
||||
|
||||
/// <summary>
|
||||
/// Sets the entity at a specific slot.
|
||||
/// </summary>
|
||||
void SetSlot(int slot, T pk);
|
||||
|
||||
/// <summary>
|
||||
/// Gets the entire team.
|
||||
/// </summary>
|
||||
void GetTeam(Span<T> team);
|
||||
|
||||
/// <summary>
|
||||
/// Sets the entire team.
|
||||
/// </summary>
|
||||
void SetTeam(ReadOnlySpan<T> team);
|
||||
|
||||
/// <summary>
|
||||
/// Gets the entire team.
|
||||
/// </summary>
|
||||
T[] GetTeam();
|
||||
}
|
|
@ -1,6 +1,5 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using static System.Buffers.Binary.BinaryPrimitives;
|
||||
|
||||
namespace PKHeX.Core;
|
||||
|
@ -54,14 +53,19 @@ public sealed class RentalTeam8(byte[] Data) : IRentalTeam<PK8>, IPokeGroup
|
|||
public PK8[] GetTeam()
|
||||
{
|
||||
var team = new PK8[COUNT_POKE];
|
||||
for (int i = 0; i < team.Length; i++)
|
||||
team[i] = GetSlot(i);
|
||||
GetTeam(team);
|
||||
return team;
|
||||
}
|
||||
|
||||
public void SetTeam(IReadOnlyList<PK8> team)
|
||||
public void GetTeam(Span<PK8> team)
|
||||
{
|
||||
for (int i = 0; i < team.Count; i++)
|
||||
for (int i = 0; i < team.Length; i++)
|
||||
team[i] = GetSlot(i);
|
||||
}
|
||||
|
||||
public void SetTeam(ReadOnlySpan<PK8> team)
|
||||
{
|
||||
for (int i = 0; i < team.Length; i++)
|
||||
SetSlot(i, team[i]);
|
||||
}
|
||||
|
||||
|
@ -100,7 +104,7 @@ public sealed class RentalTeam8(byte[] Data) : IRentalTeam<PK8>, IPokeGroup
|
|||
get => Data[0x86D];
|
||||
set => Data[0x86D] = value;
|
||||
}
|
||||
// 0x12 bytes unused to pad out to full size 0x880
|
||||
// 0x12 bytes unused to pad out to full size 0x880
|
||||
|
||||
public IEnumerable<PKM> Contents => GetTeam();
|
||||
|
||||
|
@ -108,7 +112,12 @@ public sealed class RentalTeam8(byte[] Data) : IRentalTeam<PK8>, IPokeGroup
|
|||
{
|
||||
if (data.Length != SIZE)
|
||||
return false;
|
||||
var team = new RentalTeam8(data).GetTeam();
|
||||
return team.All(x => x.ChecksumValid);
|
||||
var team = new RentalTeam8(data);
|
||||
for (int i = 0; i < 6; i++)
|
||||
{
|
||||
if (!team.GetSlot(i).ChecksumValid)
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
}
|
|
@ -1,6 +1,5 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using static System.Buffers.Binary.BinaryPrimitives;
|
||||
|
||||
namespace PKHeX.Core;
|
||||
|
@ -87,14 +86,19 @@ public sealed class RentalTeam9(byte[] Data) : IRentalTeam<PK9>, IPokeGroup
|
|||
public PK9[] GetTeam()
|
||||
{
|
||||
var team = new PK9[COUNT_POKE];
|
||||
for (int i = 0; i < team.Length; i++)
|
||||
team[i] = GetSlot(i);
|
||||
GetTeam(team);
|
||||
return team;
|
||||
}
|
||||
|
||||
public void SetTeam(IReadOnlyList<PK9> team)
|
||||
public void GetTeam(Span<PK9> team)
|
||||
{
|
||||
for (int i = 0; i < team.Count; i++)
|
||||
for (int i = 0; i < team.Length; i++)
|
||||
team[i] = GetSlot(i);
|
||||
}
|
||||
|
||||
public void SetTeam(ReadOnlySpan<PK9> team)
|
||||
{
|
||||
for (int i = 0; i < team.Length; i++)
|
||||
SetSlot(i, team[i]);
|
||||
}
|
||||
|
||||
|
@ -111,9 +115,19 @@ public sealed class RentalTeam9(byte[] Data) : IRentalTeam<PK9>, IPokeGroup
|
|||
{
|
||||
if (data.Length != SIZE)
|
||||
return false;
|
||||
var team = new RentalTeam9(data).GetTeam();
|
||||
// Checksum can be invalid for whatever reason. Just sanity check a little.
|
||||
return team.All(x => (uint)x.Species <= x.MaxSpeciesID && x.Moves.All(y => (uint)y <= x.MaxMoveID));
|
||||
var team = new RentalTeam9(data);
|
||||
for (int i = 0; i < 6; i++)
|
||||
{
|
||||
// Checksum can be invalid for whatever reason. Just sanity check a little.
|
||||
var pk = team.GetSlot(i);
|
||||
if (pk.Species == 0)
|
||||
continue;
|
||||
if (pk.Species > pk.MaxSpeciesID)
|
||||
return false;
|
||||
if (pk.Move1 > pk.MaxMoveID || pk.Move2 > pk.MaxMoveID || pk.Move3 > pk.MaxMoveID || pk.Move4 > pk.MaxMoveID)
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
public static RentalTeam9 GetFrom(ReadOnlySpan<byte> data, int index)
|
||||
|
@ -125,5 +139,10 @@ public sealed class RentalTeam9(byte[] Data) : IRentalTeam<PK9>, IPokeGroup
|
|||
|
||||
public void WriteTo(Span<byte> data, int index) => Data.CopyTo(data[(index * SIZE)..]);
|
||||
|
||||
public ushort EntityChecksum => Checksums.CRC16_CCITT(Data.AsSpan(OFS_1, OFS_END - OFS_1));
|
||||
private Span<byte> CheckSpan => Data.AsSpan(OFS_1, 6 * LEN_POKE);
|
||||
|
||||
/// <summary>
|
||||
/// Simple checksum to detect team duplication.
|
||||
/// </summary>
|
||||
public ushort EntityChecksum => Checksums.CRC16_CCITT(CheckSpan);
|
||||
}
|
|
@ -1,4 +1,4 @@
|
|||
using System;
|
||||
using System;
|
||||
using static PKHeX.Core.StadiumSaveType;
|
||||
using static System.Buffers.Binary.BinaryPrimitives;
|
||||
|
||||
|
@ -59,6 +59,10 @@ public static class StadiumUtil
|
|||
return true;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Checks if the <see cref="magic"/> value is present either with or without byte-swapping.
|
||||
/// </summary>
|
||||
/// <remarks>Only checks for a single instance of the magic value.</remarks>
|
||||
public static StadiumSaveType IsMagicPresentAbsolute(ReadOnlySpan<byte> data, int offset, uint magic)
|
||||
{
|
||||
var actual = ReadUInt32LittleEndian(data[offset..]);
|
||||
|
|
|
@ -18,6 +18,22 @@ public static partial class Util
|
|||
return new string(result[..ctr]);
|
||||
}
|
||||
|
||||
/// <inheritdoc cref="CleanFileName(string)"/>
|
||||
public static string CleanFileName(ReadOnlySpan<char> fileName)
|
||||
{
|
||||
Span<char> result = stackalloc char[fileName.Length];
|
||||
int ctr = GetCleanFileName(fileName, result);
|
||||
if (ctr == fileName.Length)
|
||||
return fileName.ToString();
|
||||
return new string(result[..ctr]);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Removes any invalid filename characters from the input string.
|
||||
/// </summary>
|
||||
/// <param name="input">String to clean</param>
|
||||
/// <param name="output">Buffer to write the cleaned string to</param>
|
||||
/// <returns>Length of the cleaned string</returns>
|
||||
private static int GetCleanFileName(ReadOnlySpan<char> input, Span<char> output)
|
||||
{
|
||||
ReadOnlySpan<char> invalid = Path.GetInvalidFileNameChars();
|
||||
|
|
|
@ -4,6 +4,7 @@ namespace PKHeX.Core;
|
|||
|
||||
public static partial class Util
|
||||
{
|
||||
/// <inheritdoc cref="Random.Shared"/>
|
||||
public static Random Rand => Random.Shared;
|
||||
|
||||
public static uint Rand32() => Rand32(Rand);
|
||||
|
|
|
@ -42,6 +42,7 @@ public static class ReflectUtil
|
|||
return pi.GetValue(obj, null);
|
||||
return default;
|
||||
}
|
||||
|
||||
public static bool SetValue(object obj, string name, object value)
|
||||
{
|
||||
if (!TryGetPropertyInfo(obj.GetType().GetTypeInfo(), name, out var pi))
|
||||
|
|
|
@ -1,4 +1,5 @@
|
|||
using System;
|
||||
using System.Buffers;
|
||||
using System.Drawing;
|
||||
using PKHeX.Core;
|
||||
using PKHeX.Drawing.PokeSprite.Properties;
|
||||
|
@ -234,10 +235,16 @@ public static class SpriteUtil
|
|||
// If the image has any transparency, any derived background will bleed into it.
|
||||
// Need to undo any transparency values if any present.
|
||||
// Remove opaque pixels from original image, leaving only the glow effect pixels.
|
||||
var original = (byte[])pixels.Clone();
|
||||
var temp = ArrayPool<byte>.Shared.Rent(pixels.Length);
|
||||
var original = temp.AsSpan(0, pixels.Length);
|
||||
pixels.CopyTo(original);
|
||||
|
||||
ImageUtil.SetAllUsedPixelsOpaque(pixels);
|
||||
ImageUtil.GlowEdges(pixels, blue, green, red, baseSprite.Width);
|
||||
ImageUtil.RemovePixels(pixels, original);
|
||||
|
||||
original.Clear();
|
||||
ArrayPool<byte>.Shared.Return(temp);
|
||||
}
|
||||
|
||||
public static Bitmap GetLegalIndicator(bool valid) => valid ? Resources.valid : Resources.warn;
|
||||
|
|
|
@ -8,36 +8,74 @@ namespace PKHeX.Drawing;
|
|||
/// </summary>
|
||||
public static class ColorUtil
|
||||
{
|
||||
private const byte MaxStat = 180; // shift the green cap down
|
||||
/// <summary> Clamps absurdly high stats to a reasonable cap. </summary>
|
||||
private const byte MaxStat = 180;
|
||||
/// <summary> Ensures the color does not go below this value. </summary>
|
||||
private const byte MinStat = 0;
|
||||
|
||||
/// <summary> Shift the color total down a little as the BST floor isn't 0. </summary>
|
||||
private const byte ShiftDownBST = 175;
|
||||
/// <summary> Divide by a fudge factor so that we're roughly within the range of a single stat. </summary>
|
||||
private const float ShiftDivBST = 3;
|
||||
|
||||
/// <summary>
|
||||
/// Gets the <see cref="Color"/> value for the specified <see cref="stat"/> value.
|
||||
/// </summary>
|
||||
/// <param name="stat">Single stat value</param>
|
||||
public static Color ColorBaseStat(int stat)
|
||||
{
|
||||
float x = (100f * stat) / MaxStat;
|
||||
if (x > 100)
|
||||
x = 100;
|
||||
double red = 255f * (x > 50 ? 1 - (2 * (x - 50) / 100.0) : 1.0);
|
||||
double green = 255f * (x > 50 ? 1.0 : 2 * x / 100.0);
|
||||
|
||||
return Blend(Color.FromArgb((int)red, (int)green, 0), Color.White, 0.4);
|
||||
// Red to Yellow to Green, no Blue component.
|
||||
var x = (uint)stat >= MaxStat ? 1f : ((float)stat) / MaxStat;
|
||||
return GetPastelRYG(x);
|
||||
}
|
||||
|
||||
public static Color ColorBaseStatTotal(int tot)
|
||||
/// <summary>
|
||||
/// Gets the <see cref="Color"/> value for the specified <see cref="bst"/> value.
|
||||
/// </summary>
|
||||
/// <param name="bst">Base Stat Total</param>
|
||||
public static Color ColorBaseStatTotal(int bst)
|
||||
{
|
||||
const byte sumShiftDown = 175;
|
||||
const float sumDivisor = 3f;
|
||||
var sumToSingle = Math.Max(MinStat, tot - sumShiftDown) / sumDivisor;
|
||||
var sumToSingle = Math.Max(MinStat, bst - ShiftDownBST) / ShiftDivBST;
|
||||
return ColorBaseStat((int)sumToSingle);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets a pastel color from Red to Yellow to Green with a 40%/60% blend with White.
|
||||
/// </summary>
|
||||
/// <param name="x">Percentage of the way from Red to Green [0,1]</param>
|
||||
public static Color GetPastelRYG(float x)
|
||||
{
|
||||
var r = x > .5f ? 510 * (1 - x) : 255;
|
||||
var g = x > .5f ? 255 : 510 * x;
|
||||
|
||||
// Blend with white to make it lighter rather than a darker shade.
|
||||
const float white = 0.4f;
|
||||
const byte b = (byte)(0xFF * (1 - white));
|
||||
var br = (byte)((r * white) + b);
|
||||
var bg = (byte)((g * white) + b);
|
||||
|
||||
return Color.FromArgb(br, bg, b);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Combines two colors together with the specified amount.
|
||||
/// </summary>
|
||||
/// <param name="color">New color to layer atop</param>
|
||||
/// <param name="backColor">Original color to layer beneath</param>
|
||||
/// <param name="amount">Amount to prefer <see cref="color"/> over <see cref="backColor"/></param>
|
||||
public static Color Blend(Color color, Color backColor, double amount)
|
||||
{
|
||||
byte r = (byte)((color.R * amount) + (backColor.R * (1 - amount)));
|
||||
byte g = (byte)((color.G * amount) + (backColor.G * (1 - amount)));
|
||||
byte b = (byte)((color.B * amount) + (backColor.B * (1 - amount)));
|
||||
byte r = MixComponent(color.R, backColor.R, amount);
|
||||
byte g = MixComponent(color.G, backColor.G, amount);
|
||||
byte b = MixComponent(color.B, backColor.B, amount);
|
||||
return Color.FromArgb(r, g, b);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Combines two color components with the specified first color percent preference [0,1].
|
||||
/// </summary>
|
||||
/// <param name="a">First color's component</param>
|
||||
/// <param name="b">Second color's component</param>
|
||||
/// <param name="x">Percent preference of <paramref name="a"/> over <paramref name="b"/></param>
|
||||
public static byte MixComponent(byte a, byte b, double x) => (byte)((a * x) + (b * (1 - x)));
|
||||
}
|
||||
|
|
|
@ -113,16 +113,21 @@ public static class ImageUtil
|
|||
data = new byte[bmp.Width * bmp.Height * 4];
|
||||
}
|
||||
|
||||
public static Bitmap GetBitmap(byte[] data, int width, int height, PixelFormat format = PixelFormat.Format32bppArgb)
|
||||
public static Bitmap GetBitmap(byte[] data, int width, int height, int length, PixelFormat format = PixelFormat.Format32bppArgb)
|
||||
{
|
||||
var bmp = new Bitmap(width, height, format);
|
||||
var bmpData = bmp.LockBits(new Rectangle(0, 0, bmp.Width, bmp.Height), ImageLockMode.WriteOnly, format);
|
||||
var ptr = bmpData.Scan0;
|
||||
Marshal.Copy(data, 0, ptr, data.Length);
|
||||
Marshal.Copy(data, 0, ptr, length);
|
||||
bmp.UnlockBits(bmpData);
|
||||
return bmp;
|
||||
}
|
||||
|
||||
public static Bitmap GetBitmap(byte[] data, int width, int height, PixelFormat format = PixelFormat.Format32bppArgb)
|
||||
{
|
||||
return GetBitmap(data, width, height, data.Length, format);
|
||||
}
|
||||
|
||||
public static byte[] GetPixelData(Bitmap bitmap)
|
||||
{
|
||||
var argbData = new byte[bitmap.Width * bitmap.Height * 4];
|
||||
|
|
|
@ -1,4 +1,5 @@
|
|||
using System;
|
||||
using System.Buffers;
|
||||
using System.Drawing;
|
||||
using System.Timers;
|
||||
using System.Windows.Forms;
|
||||
|
@ -98,10 +99,15 @@ public sealed class BitmapAnimator : IDisposable
|
|||
var frameColor = GetFrameColor(elapsedFraction);
|
||||
|
||||
ArgumentNullException.ThrowIfNull(GlowData);
|
||||
var frameData = (byte[])GlowData.Clone();
|
||||
ImageUtil.ChangeAllColorTo(frameData, frameColor);
|
||||
|
||||
frame = ImageUtil.GetBitmap(frameData, imgWidth, imgHeight);
|
||||
var frameData = ArrayPool<byte>.Shared.Rent(GlowData.Length);
|
||||
var frameSpan = frameData.AsSpan(0, GlowData.Length);
|
||||
GlowData.AsSpan().CopyTo(frameSpan);
|
||||
ImageUtil.ChangeAllColorTo(frameSpan, frameColor);
|
||||
frame = ImageUtil.GetBitmap(frameData, imgWidth, imgHeight, GlowData.Length);
|
||||
frameSpan.Clear();
|
||||
ArrayPool<byte>.Shared.Return(frameData);
|
||||
|
||||
if (ExtraLayer != null)
|
||||
frame = ImageUtil.LayerImage(frame, ExtraLayer, 0, 0);
|
||||
if (OriginalBackground != null)
|
||||
|
|
|
@ -95,8 +95,9 @@ public class StringQualityTests
|
|||
var group = setField.GetValue(strings) as ILocationSet;
|
||||
Assert.NotNull(group);
|
||||
|
||||
foreach (var (bank, arr) in group.GetAll())
|
||||
foreach (var (bank, mem) in group.GetAll())
|
||||
{
|
||||
var arr = mem.Span;
|
||||
var hs = new HashSet<string>(arr.Length);
|
||||
bool sm0 = bank == 0 && name == nameof(GameStrings.Gen7);
|
||||
for (int index = 0; index < arr.Length; index++)
|
||||
|
|
Loading…
Reference in a new issue