mirror of
https://github.com/kwsch/PKHeX
synced 2024-11-10 06:34:19 +00:00
Refactoring: Span-based value writes and method signatures (#3361)
Existing `get`/`set` logic is flawed in that it doesn't work on Big Endian operating systems, and it allocates heap objects when it doesn't need to. `System.Buffers.Binary.BinaryPrimitives` in the `System.Memory` NuGet package provides both Little Endian and Big Endian methods to read and write data; all the `get`/`set` operations have been reworked to use this new API. This removes the need for PKHeX's manual `BigEndian` class, as all functions are already covered by the BinaryPrimitives API. The `StringConverter` has now been rewritten to accept a Span to read from & write to, no longer requiring a temporary StringBuilder. Other Fixes included: - The Super Training UI for Gen6 has been reworked according to the latest block structure additions. - Cloning a Stadium2 Save File now works correctly (opening from the Folder browser list). - Checksum & Sanity properties removed from parent PKM class, and is now implemented via interface.
This commit is contained in:
parent
a9896022ed
commit
47071b41f3
353 changed files with 7728 additions and 7066 deletions
|
@ -39,7 +39,7 @@ namespace PKHeX.Core
|
|||
public static int ApplyBallLegalRandom(PKM pkm)
|
||||
{
|
||||
var balls = GetBallListFromColor(pkm).ToArray();
|
||||
Util.Shuffle(balls);
|
||||
Util.Shuffle(balls.AsSpan());
|
||||
return ApplyFirstLegalBall(pkm, balls);
|
||||
}
|
||||
|
||||
|
@ -118,7 +118,7 @@ namespace PKHeX.Core
|
|||
{
|
||||
var matchingColors = BallColors[c];
|
||||
var extra = allBalls.Except(matchingColors).ToArray();
|
||||
Util.Shuffle(extra);
|
||||
Util.Shuffle(extra.AsSpan());
|
||||
BallColors[c] = ArrayUtil.ConcatAll(matchingColors, extra, end);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -47,7 +47,7 @@ namespace PKHeX.Core
|
|||
m = m.Intersect(learn).ToArray();
|
||||
|
||||
if (random && !la.pkm.IsEgg)
|
||||
Util.Shuffle(m);
|
||||
Util.Shuffle(m.AsSpan());
|
||||
|
||||
const int count = 4;
|
||||
if (m.Length > count)
|
||||
|
|
|
@ -432,12 +432,9 @@ namespace PKHeX.Core
|
|||
{
|
||||
switch (cmd.PropertyName)
|
||||
{
|
||||
case nameof(PKM.Nickname_Trash):
|
||||
pk.Nickname_Trash = ConvertToBytes(cmd.PropertyValue);
|
||||
return ModifyResult.Modified;
|
||||
case nameof(PKM.OT_Trash):
|
||||
pk.OT_Trash = ConvertToBytes(cmd.PropertyValue);
|
||||
return ModifyResult.Modified;
|
||||
case nameof(PKM.Nickname_Trash): ConvertToBytes(cmd.PropertyValue).CopyTo(pk.Nickname_Trash); return ModifyResult.Modified;
|
||||
case nameof(PKM.OT_Trash): ConvertToBytes(cmd.PropertyValue).CopyTo(pk.OT_Trash); return ModifyResult.Modified;
|
||||
case nameof(PKM.HT_Trash): ConvertToBytes(cmd.PropertyValue).CopyTo(pk.HT_Trash); return ModifyResult.Modified;
|
||||
default:
|
||||
return ModifyResult.Error;
|
||||
}
|
||||
|
|
|
@ -96,7 +96,7 @@ namespace PKHeX.Core
|
|||
public string Relearn2 => Get(Strings.movelist, pkm.RelearnMove2);
|
||||
public string Relearn3 => Get(Strings.movelist, pkm.RelearnMove3);
|
||||
public string Relearn4 => Get(Strings.movelist, pkm.RelearnMove4);
|
||||
public ushort Checksum => pkm.Checksum;
|
||||
public ushort Checksum => pkm is ISanityChecksum s ? s.Checksum : PokeCrypto.GetCHK(pkm.Data, pkm.SIZE_STORED);
|
||||
public int Friendship => pkm.OT_Friendship;
|
||||
public int Egg_Year => pkm.EggMetDate.GetValueOrDefault().Year;
|
||||
public int Egg_Month => pkm.EggMetDate.GetValueOrDefault().Month;
|
||||
|
|
|
@ -51,10 +51,10 @@ namespace PKHeX.Core
|
|||
switch (tr)
|
||||
{
|
||||
case SAV1 s1:
|
||||
pk12.OT_Trash = s1.OT_Trash;
|
||||
s1.OT_Trash.CopyTo(pk12.OT_Trash);
|
||||
break;
|
||||
case SAV2 s2:
|
||||
pk12.OT_Trash = s2.OT_Trash;
|
||||
s2.OT_Trash.CopyTo(pk12.OT_Trash);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -24,8 +24,8 @@ namespace PKHeX.Core
|
|||
|
||||
foreach (var s in items)
|
||||
{
|
||||
if (int.TryParse(s[0], out var val))
|
||||
Options.Add(new EventWorkVal(s[1], val));
|
||||
if (int.TryParse(s[0], out var value))
|
||||
Options.Add(new EventWorkVal(s[1], value));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -50,16 +50,16 @@ namespace PKHeX.Core
|
|||
{
|
||||
foreach (var item in g.Vars)
|
||||
{
|
||||
var val = ((EventWork<T>)item).Value;
|
||||
Block.SetWork(item.RawIndex, val);
|
||||
var value = ((EventWork<T>)item).Value;
|
||||
Block.SetWork(item.RawIndex, value);
|
||||
}
|
||||
}
|
||||
foreach (var g in Flag)
|
||||
{
|
||||
foreach (var item in g.Vars)
|
||||
{
|
||||
var val = ((EventFlag)item).Flag;
|
||||
Block.SetFlag(item.RawIndex, val);
|
||||
var value = ((EventFlag)item).Flag;
|
||||
Block.SetFlag(item.RawIndex, value);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -56,8 +56,8 @@ namespace PKHeX.Core
|
|||
public override bool ChecksumsValid => true;
|
||||
public override string ChecksumInfo => string.Empty;
|
||||
public override int Generation => 3;
|
||||
public override string GetString(byte[] data, int offset, int length) => string.Empty;
|
||||
public override byte[] SetString(string value, int maxLength, int PadToSize = 0, ushort PadWith = 0) => Array.Empty<byte>();
|
||||
public override string GetString(ReadOnlySpan<byte> data) => string.Empty;
|
||||
public override int SetString(Span<byte> destBuffer, ReadOnlySpan<char> value, int maxLength, StringConverterOption option) => 0;
|
||||
public override PersonalTable Personal => PersonalTable.RS;
|
||||
public override int MaxEV => 0;
|
||||
public override IReadOnlyList<ushort> HeldItems => Legal.HeldItems_RS;
|
||||
|
|
|
@ -55,11 +55,7 @@ namespace PKHeX.Core
|
|||
return $"{fn} @ ";
|
||||
}
|
||||
|
||||
public bool IsDataValid()
|
||||
{
|
||||
var e = Entity;
|
||||
return e.Species != 0 && e.ChecksumValid && (e.Sanity == 0 || e is BK4);
|
||||
}
|
||||
public bool IsDataValid() => Entity.Species != 0 && Entity.Valid;
|
||||
|
||||
public int CompareTo(SlotCache? other)
|
||||
{
|
||||
|
|
|
@ -311,7 +311,7 @@ namespace PKHeX.Core
|
|||
return $"{Nickname} ({specForm})";
|
||||
}
|
||||
|
||||
private static IList<string> GetStringStats(int[] stats, int ignore)
|
||||
private static IList<string> GetStringStats(ReadOnlySpan<int> stats, int ignore)
|
||||
{
|
||||
var result = new List<string>();
|
||||
for (int i = 0; i < stats.Length; i++)
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace PKHeX.Core
|
||||
{
|
||||
|
@ -31,14 +31,10 @@ namespace PKHeX.Core
|
|||
new ComboItem("CHT (繁體中文)", (int)LanguageID.ChineseT),
|
||||
};
|
||||
|
||||
// ignores Poke/Great/Ultra
|
||||
private static readonly ushort[] ball_nums = { 007, 576, 013, 492, 497, 014, 495, 493, 496, 494, 011, 498, 008, 006, 012, 015, 009, 005, 499, 010, 001, 016, 851 };
|
||||
private static readonly byte[] ball_vals = { 007, 025, 013, 017, 022, 014, 020, 018, 021, 019, 011, 023, 008, 006, 012, 015, 009, 005, 024, 010, 001, 016, 026 };
|
||||
|
||||
public GameDataSource(GameStrings s)
|
||||
{
|
||||
Strings = s;
|
||||
BallDataSource = Util.GetVariedCBListBall(s.itemlist, ball_nums, ball_vals);
|
||||
BallDataSource = GetBalls(s.itemlist);
|
||||
SpeciesDataSource = Util.GetCBList(s.specieslist);
|
||||
NatureDataSource = Util.GetCBList(s.natures);
|
||||
AbilityDataSource = Util.GetCBList(s.abilitylist);
|
||||
|
@ -75,10 +71,18 @@ namespace PKHeX.Core
|
|||
public readonly IReadOnlyList<ComboItem> HaXMoveDataSource;
|
||||
public readonly IReadOnlyList<ComboItem> GroundTileDataSource;
|
||||
|
||||
private static IReadOnlyList<ComboItem> GetBalls(string[] itemList)
|
||||
{
|
||||
// ignores Poke/Great/Ultra
|
||||
ReadOnlySpan<ushort> ball_nums = stackalloc ushort[] { 007, 576, 013, 492, 497, 014, 495, 493, 496, 494, 011, 498, 008, 006, 012, 015, 009, 005, 499, 010, 001, 016, 851 };
|
||||
ReadOnlySpan<byte> ball_vals = stackalloc byte[] { 007, 025, 013, 017, 022, 014, 020, 018, 021, 019, 011, 023, 008, 006, 012, 015, 009, 005, 024, 010, 001, 016, 026 };
|
||||
return Util.GetVariedCBListBall(itemList, ball_nums, ball_vals);
|
||||
}
|
||||
|
||||
private static IReadOnlyList<ComboItem> GetVersionList(GameStrings s)
|
||||
{
|
||||
var list = s.gamelist;
|
||||
var games = new byte[]
|
||||
ReadOnlySpan<byte> games = stackalloc byte[]
|
||||
{
|
||||
48, 49, // 8 bdsp
|
||||
44, 45, // 8 swsh
|
||||
|
@ -111,7 +115,7 @@ namespace PKHeX.Core
|
|||
|
||||
public static IReadOnlyList<ComboItem> LanguageDataSource(int gen)
|
||||
{
|
||||
var languages = LanguageList.ToList();
|
||||
var languages = new List<ComboItem>(LanguageList);
|
||||
if (gen == 3)
|
||||
languages.RemoveAll(l => l.Value >= (int)LanguageID.Korean);
|
||||
else if (gen < 7)
|
||||
|
|
|
@ -1,4 +1,5 @@
|
|||
using System.Collections.Generic;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace PKHeX.Core
|
||||
{
|
||||
|
@ -21,7 +22,7 @@ namespace PKHeX.Core
|
|||
return result;
|
||||
}
|
||||
|
||||
private EncounterArea1(byte[] data, GameVersion game) : base(game)
|
||||
private EncounterArea1(ReadOnlySpan<byte> data, GameVersion game) : base(game)
|
||||
{
|
||||
Location = data[0];
|
||||
// 1 byte unused
|
||||
|
@ -33,15 +34,21 @@ namespace PKHeX.Core
|
|||
for (int i = 0; i < slots.Length; i++)
|
||||
{
|
||||
int offset = 4 + (4 * i);
|
||||
int species = data[offset + 0];
|
||||
int slotNum = data[offset + 1];
|
||||
int min = data[offset + 2];
|
||||
int max = data[offset + 3];
|
||||
slots[i] = new EncounterSlot1(this, species, min, max, slotNum);
|
||||
var entry = data.Slice(offset, 4);
|
||||
slots[i] = ReadSlot(entry);
|
||||
}
|
||||
Slots = slots;
|
||||
}
|
||||
|
||||
private EncounterSlot1 ReadSlot(ReadOnlySpan<byte> entry)
|
||||
{
|
||||
int species = entry[0];
|
||||
int slotNum = entry[1];
|
||||
int min = entry[2];
|
||||
int max = entry[3];
|
||||
return new EncounterSlot1(this, species, min, max, slotNum);
|
||||
}
|
||||
|
||||
public override IEnumerable<EncounterSlot> GetMatchingSlots(PKM pkm, IReadOnlyList<EvoCriteria> chain)
|
||||
{
|
||||
int rate = pkm is PK1 pk1 ? pk1.Catch_Rate : -1;
|
||||
|
|
|
@ -28,7 +28,7 @@ namespace PKHeX.Core
|
|||
return result;
|
||||
}
|
||||
|
||||
private EncounterArea2(byte[] data, GameVersion game) : base(game)
|
||||
private EncounterArea2(ReadOnlySpan<byte> data, GameVersion game) : base(game)
|
||||
{
|
||||
Location = data[0];
|
||||
Time = (EncounterTime)data[1];
|
||||
|
@ -63,22 +63,28 @@ namespace PKHeX.Core
|
|||
}
|
||||
}
|
||||
|
||||
private EncounterSlot2[] ReadSlots(byte[] data, int count, int start)
|
||||
private EncounterSlot2[] ReadSlots(ReadOnlySpan<byte> data, int count, int start)
|
||||
{
|
||||
var slots = new EncounterSlot2[count];
|
||||
for (int i = 0; i < slots.Length; i++)
|
||||
{
|
||||
int offset = start + (4 * i);
|
||||
int species = data[offset + 0];
|
||||
int slotNum = data[offset + 1];
|
||||
int min = data[offset + 2];
|
||||
int max = data[offset + 3];
|
||||
slots[i] = new EncounterSlot2(this, species, min, max, slotNum);
|
||||
var entry = data.Slice(offset, 4);
|
||||
slots[i] = ReadSlot(entry);
|
||||
}
|
||||
|
||||
return slots;
|
||||
}
|
||||
|
||||
private EncounterSlot2 ReadSlot(ReadOnlySpan<byte> entry)
|
||||
{
|
||||
int species = entry[0];
|
||||
int slotNum = entry[1];
|
||||
int min = entry[2];
|
||||
int max = entry[3];
|
||||
return new EncounterSlot2(this, species, min, max, slotNum);
|
||||
}
|
||||
|
||||
public override IEnumerable<EncounterSlot> GetMatchingSlots(PKM pkm, IReadOnlyList<EvoCriteria> chain)
|
||||
{
|
||||
if (pkm is not ICaughtData2 pk2 || pk2.CaughtData == 0)
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using static System.Buffers.Binary.BinaryPrimitives;
|
||||
|
||||
namespace PKHeX.Core
|
||||
{
|
||||
|
@ -30,7 +31,7 @@ namespace PKHeX.Core
|
|||
return result;
|
||||
}
|
||||
|
||||
private EncounterArea3(byte[] data, GameVersion game) : base(game)
|
||||
private EncounterArea3(ReadOnlySpan<byte> data, GameVersion game) : base(game)
|
||||
{
|
||||
Location = data[0] | (data[1] << 8);
|
||||
Type = (SlotType)data[2];
|
||||
|
@ -39,7 +40,7 @@ namespace PKHeX.Core
|
|||
Slots = ReadRegularSlots(data);
|
||||
}
|
||||
|
||||
private EncounterArea3(byte[] data, GameVersion game, SlotType type) : base(game)
|
||||
private EncounterArea3(ReadOnlySpan<byte> data, GameVersion game, SlotType type) : base(game)
|
||||
{
|
||||
Location = data[0] | (data[1] << 8);
|
||||
Type = type;
|
||||
|
@ -48,7 +49,7 @@ namespace PKHeX.Core
|
|||
Slots = ReadSwarmSlots(data);
|
||||
}
|
||||
|
||||
private EncounterSlot3[] ReadRegularSlots(byte[] data)
|
||||
private EncounterSlot3[] ReadRegularSlots(ReadOnlySpan<byte> data)
|
||||
{
|
||||
const int size = 10;
|
||||
int count = (data.Length - 4) / size;
|
||||
|
@ -56,24 +57,29 @@ namespace PKHeX.Core
|
|||
for (int i = 0; i < slots.Length; i++)
|
||||
{
|
||||
int offset = 4 + (size * i);
|
||||
|
||||
int species = BitConverter.ToUInt16(data, offset + 0);
|
||||
int form = data[offset + 2];
|
||||
int slotNum = data[offset + 3];
|
||||
int min = data[offset + 4];
|
||||
int max = data[offset + 5];
|
||||
|
||||
int mpi = data[offset + 6];
|
||||
int mpc = data[offset + 7];
|
||||
int sti = data[offset + 8];
|
||||
int stc = data[offset + 9];
|
||||
slots[i] = new EncounterSlot3(this, species, form, min, max, slotNum, mpi, mpc, sti, stc);
|
||||
var entry = data.Slice(offset, size);
|
||||
slots[i] = ReadRegularSlot(entry);
|
||||
}
|
||||
|
||||
return slots;
|
||||
}
|
||||
|
||||
private EncounterSlot3[] ReadSwarmSlots(byte[] data)
|
||||
private EncounterSlot3 ReadRegularSlot(ReadOnlySpan<byte> entry)
|
||||
{
|
||||
int species = ReadUInt16LittleEndian(entry);
|
||||
int form = entry[2];
|
||||
int slotNum = entry[3];
|
||||
int min = entry[4];
|
||||
int max = entry[5];
|
||||
|
||||
int mpi = entry[6];
|
||||
int mpc = entry[7];
|
||||
int sti = entry[8];
|
||||
int stc = entry[9];
|
||||
return new EncounterSlot3(this, species, form, min, max, slotNum, mpi, mpc, sti, stc);
|
||||
}
|
||||
|
||||
private EncounterSlot3[] ReadSwarmSlots(ReadOnlySpan<byte> data)
|
||||
{
|
||||
const int size = 14;
|
||||
int count = (data.Length - 4) / size;
|
||||
|
@ -81,27 +87,32 @@ namespace PKHeX.Core
|
|||
for (int i = 0; i < slots.Length; i++)
|
||||
{
|
||||
int offset = 4 + (size * i);
|
||||
|
||||
int species = BitConverter.ToUInt16(data, offset + 0);
|
||||
// form always 0
|
||||
int slotNum = data[offset + 3];
|
||||
int min = data[offset + 4];
|
||||
int max = data[offset + 5];
|
||||
|
||||
int[] moves =
|
||||
{
|
||||
BitConverter.ToUInt16(data, offset + 6),
|
||||
BitConverter.ToUInt16(data, offset + 8),
|
||||
BitConverter.ToUInt16(data, offset + 10),
|
||||
BitConverter.ToUInt16(data, offset + 12),
|
||||
};
|
||||
|
||||
slots[i] = new EncounterSlot3Swarm(this, species, min, max, slotNum, moves);
|
||||
var entry = data.Slice(offset, size);
|
||||
slots[i] = ReadSwarmSlot(entry);
|
||||
}
|
||||
|
||||
return slots;
|
||||
}
|
||||
|
||||
private EncounterSlot3Swarm ReadSwarmSlot(ReadOnlySpan<byte> entry)
|
||||
{
|
||||
int species = ReadUInt16LittleEndian(entry);
|
||||
// form always 0
|
||||
int slotNum = entry[3];
|
||||
int min = entry[4];
|
||||
int max = entry[5];
|
||||
|
||||
int[] moves =
|
||||
{
|
||||
ReadUInt16LittleEndian(entry[06..]),
|
||||
ReadUInt16LittleEndian(entry[08..]),
|
||||
ReadUInt16LittleEndian(entry[10..]),
|
||||
ReadUInt16LittleEndian(entry[12..]),
|
||||
};
|
||||
|
||||
return new EncounterSlot3Swarm(this, species, min, max, slotNum, moves);
|
||||
}
|
||||
|
||||
public override IEnumerable<EncounterSlot> GetMatchingSlots(PKM pkm, IReadOnlyList<EvoCriteria> chain)
|
||||
{
|
||||
if (pkm.Format != 3) // Met Location and Met Level are changed on PK3->PK4
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using static System.Buffers.Binary.BinaryPrimitives;
|
||||
|
||||
namespace PKHeX.Core
|
||||
{
|
||||
|
@ -23,18 +24,18 @@ namespace PKHeX.Core
|
|||
return result;
|
||||
}
|
||||
|
||||
private EncounterArea4(byte[] data, GameVersion game) : base(game)
|
||||
private EncounterArea4(ReadOnlySpan<byte> data, GameVersion game) : base(game)
|
||||
{
|
||||
Location = data[0] | (data[1] << 8);
|
||||
Location = ReadUInt16LittleEndian(data);
|
||||
Type = (SlotType)data[2];
|
||||
Rate = data[3];
|
||||
// although GroundTilePermission flags are 32bit, none have values > 16bit.
|
||||
GroundTile = (GroundTilePermission) BitConverter.ToUInt16(data, 4);
|
||||
GroundTile = (GroundTilePermission)ReadUInt16LittleEndian(data[4..]);
|
||||
|
||||
Slots = ReadRegularSlots(data);
|
||||
}
|
||||
|
||||
private EncounterSlot4[] ReadRegularSlots(byte[] data)
|
||||
private EncounterSlot4[] ReadRegularSlots(ReadOnlySpan<byte> data)
|
||||
{
|
||||
const int size = 10;
|
||||
int count = (data.Length - 6) / size;
|
||||
|
@ -42,23 +43,27 @@ namespace PKHeX.Core
|
|||
for (int i = 0; i < slots.Length; i++)
|
||||
{
|
||||
int offset = 6 + (size * i);
|
||||
|
||||
int species = BitConverter.ToUInt16(data, offset + 0);
|
||||
int form = data[offset + 2];
|
||||
int slotNum = data[offset + 3];
|
||||
int min = data[offset + 4];
|
||||
int max = data[offset + 5];
|
||||
|
||||
int mpi = data[offset + 6];
|
||||
int mpc = data[offset + 7];
|
||||
int sti = data[offset + 8];
|
||||
int stc = data[offset + 9];
|
||||
slots[i] = new EncounterSlot4(this, species, form, min, max, slotNum, mpi, mpc, sti, stc);
|
||||
var entry = data.Slice(offset, size);
|
||||
slots[i] = ReadRegularSlot(entry);
|
||||
}
|
||||
|
||||
return slots;
|
||||
}
|
||||
|
||||
private EncounterSlot4 ReadRegularSlot(ReadOnlySpan<byte> entry)
|
||||
{
|
||||
int species = ReadUInt16LittleEndian(entry);
|
||||
int form = entry[2];
|
||||
int slotNum = entry[3];
|
||||
int min = entry[4];
|
||||
int max = entry[5];
|
||||
int mpi = entry[6];
|
||||
int mpc = entry[7];
|
||||
int sti = entry[8];
|
||||
int stc = entry[9];
|
||||
return new EncounterSlot4(this, species, form, min, max, slotNum, mpi, mpc, sti, stc);
|
||||
}
|
||||
|
||||
public override IEnumerable<EncounterSlot> GetMatchingSlots(PKM pkm, IReadOnlyList<EvoCriteria> chain)
|
||||
{
|
||||
if (pkm.Format != 4) // Met Location and Met Level are changed on PK4->PK5
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using static System.Buffers.Binary.BinaryPrimitives;
|
||||
|
||||
namespace PKHeX.Core
|
||||
{
|
||||
|
@ -21,15 +22,15 @@ namespace PKHeX.Core
|
|||
return result;
|
||||
}
|
||||
|
||||
private EncounterArea5(byte[] data, GameVersion game) : base(game)
|
||||
private EncounterArea5(ReadOnlySpan<byte> data, GameVersion game) : base(game)
|
||||
{
|
||||
Location = data[0] | (data[1] << 8);
|
||||
Location = ReadUInt16LittleEndian(data);
|
||||
Type = (SlotType)data[2];
|
||||
|
||||
Slots = ReadSlots(data);
|
||||
}
|
||||
|
||||
private EncounterSlot5[] ReadSlots(byte[] data)
|
||||
private EncounterSlot5[] ReadSlots(ReadOnlySpan<byte> data)
|
||||
{
|
||||
const int size = 4;
|
||||
int count = (data.Length - 4) / size;
|
||||
|
@ -37,17 +38,23 @@ namespace PKHeX.Core
|
|||
for (int i = 0; i < slots.Length; i++)
|
||||
{
|
||||
int offset = 4 + (size * i);
|
||||
ushort SpecForm = BitConverter.ToUInt16(data, offset);
|
||||
int species = SpecForm & 0x3FF;
|
||||
int form = SpecForm >> 11;
|
||||
int min = data[offset + 2];
|
||||
int max = data[offset + 3];
|
||||
slots[i] = new EncounterSlot5(this, species, form, min, max);
|
||||
var entry = data.Slice(offset, size);
|
||||
slots[i] = ReadSlot(entry);
|
||||
}
|
||||
|
||||
return slots;
|
||||
}
|
||||
|
||||
private EncounterSlot5 ReadSlot(ReadOnlySpan<byte> entry)
|
||||
{
|
||||
ushort SpecForm = ReadUInt16LittleEndian(entry);
|
||||
int species = SpecForm & 0x3FF;
|
||||
int form = SpecForm >> 11;
|
||||
int min = entry[2];
|
||||
int max = entry[3];
|
||||
return new EncounterSlot5(this, species, form, min, max);
|
||||
}
|
||||
|
||||
public override IEnumerable<EncounterSlot> GetMatchingSlots(PKM pkm, IReadOnlyList<EvoCriteria> chain)
|
||||
{
|
||||
foreach (var slot in Slots)
|
||||
|
@ -71,4 +78,4 @@ namespace PKHeX.Core
|
|||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using static System.Buffers.Binary.BinaryPrimitives;
|
||||
|
||||
namespace PKHeX.Core
|
||||
{
|
||||
|
@ -21,15 +22,15 @@ namespace PKHeX.Core
|
|||
return result;
|
||||
}
|
||||
|
||||
private EncounterArea6AO(byte[] data, GameVersion game) : base(game)
|
||||
private EncounterArea6AO(ReadOnlySpan<byte> data, GameVersion game) : base(game)
|
||||
{
|
||||
Location = data[0] | (data[1] << 8);
|
||||
Location = ReadInt16LittleEndian(data);
|
||||
Type = (SlotType)data[2];
|
||||
|
||||
Slots = ReadSlots(data);
|
||||
}
|
||||
|
||||
private EncounterSlot6AO[] ReadSlots(byte[] data)
|
||||
private EncounterSlot6AO[] ReadSlots(ReadOnlySpan<byte> data)
|
||||
{
|
||||
const int size = 4;
|
||||
int count = (data.Length - 4) / size;
|
||||
|
@ -37,17 +38,23 @@ namespace PKHeX.Core
|
|||
for (int i = 0; i < slots.Length; i++)
|
||||
{
|
||||
int offset = 4 + (size * i);
|
||||
ushort SpecForm = BitConverter.ToUInt16(data, offset);
|
||||
int species = SpecForm & 0x3FF;
|
||||
int form = SpecForm >> 11;
|
||||
int min = data[offset + 2];
|
||||
int max = data[offset + 3];
|
||||
slots[i] = new EncounterSlot6AO(this, species, form, min, max);
|
||||
var entry = data.Slice(offset, size);
|
||||
slots[i] = ReadSlot(entry);
|
||||
}
|
||||
|
||||
return slots;
|
||||
}
|
||||
|
||||
private EncounterSlot6AO ReadSlot(ReadOnlySpan<byte> entry)
|
||||
{
|
||||
ushort SpecForm = ReadUInt16LittleEndian(entry);
|
||||
int species = SpecForm & 0x3FF;
|
||||
int form = SpecForm >> 11;
|
||||
int min = entry[2];
|
||||
int max = entry[3];
|
||||
return new EncounterSlot6AO(this, species, form, min, max);
|
||||
}
|
||||
|
||||
private const int FluteBoostMin = 4; // White Flute decreases levels.
|
||||
private const int FluteBoostMax = 4; // Black Flute increases levels.
|
||||
private const int DexNavBoost = 30; // Maximum DexNav chain
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using static System.Buffers.Binary.BinaryPrimitives;
|
||||
|
||||
namespace PKHeX.Core
|
||||
{
|
||||
|
@ -30,7 +31,7 @@ namespace PKHeX.Core
|
|||
Slots = LoadSafariSlots();
|
||||
}
|
||||
|
||||
private EncounterArea6XY(byte[] data, GameVersion game) : base(game)
|
||||
private EncounterArea6XY(ReadOnlySpan<byte> data, GameVersion game) : base(game)
|
||||
{
|
||||
Location = data[0] | (data[1] << 8);
|
||||
Type = (SlotType)data[2];
|
||||
|
@ -78,11 +79,11 @@ namespace PKHeX.Core
|
|||
slots[i++] = new EncounterSlot6XY(this, (int)Species.Floette, 3, 30, 30);
|
||||
|
||||
// Region Random Vivillon
|
||||
slots[i] = new EncounterSlot6XY(this, (int)Species.Vivillon, 30, 30, 30);
|
||||
slots[i] = new EncounterSlot6XY(this, (int)Species.Vivillon, EncounterSlot.FormVivillon, 30, 30);
|
||||
return slots;
|
||||
}
|
||||
|
||||
private EncounterSlot6XY[] ReadSlots(byte[] data)
|
||||
private EncounterSlot6XY[] ReadSlots(ReadOnlySpan<byte> data)
|
||||
{
|
||||
const int size = 4;
|
||||
int count = (data.Length - 4) / size;
|
||||
|
@ -90,11 +91,12 @@ namespace PKHeX.Core
|
|||
for (int i = 0; i < slots.Length; i++)
|
||||
{
|
||||
int offset = 4 + (size * i);
|
||||
ushort SpecForm = BitConverter.ToUInt16(data, offset);
|
||||
var entry = data.Slice(offset, size);
|
||||
ushort SpecForm = ReadUInt16LittleEndian(entry);
|
||||
int species = SpecForm & 0x3FF;
|
||||
int form = SpecForm >> 11;
|
||||
int min = data[offset + 2];
|
||||
int max = data[offset + 3];
|
||||
int min = entry[2];
|
||||
int max = entry[3];
|
||||
slots[i] = new EncounterSlot6XY(this, species, form, min, max);
|
||||
}
|
||||
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using static System.Buffers.Binary.BinaryPrimitives;
|
||||
|
||||
namespace PKHeX.Core
|
||||
{
|
||||
|
@ -21,7 +22,7 @@ namespace PKHeX.Core
|
|||
return result;
|
||||
}
|
||||
|
||||
private EncounterArea7(byte[] data, GameVersion game) : base(game)
|
||||
private EncounterArea7(ReadOnlySpan<byte> data, GameVersion game) : base(game)
|
||||
{
|
||||
Location = data[0] | (data[1] << 8);
|
||||
Type = (SlotType)data[2];
|
||||
|
@ -29,7 +30,7 @@ namespace PKHeX.Core
|
|||
Slots = ReadSlots(data);
|
||||
}
|
||||
|
||||
private EncounterSlot7[] ReadSlots(byte[] data)
|
||||
private EncounterSlot7[] ReadSlots(ReadOnlySpan<byte> data)
|
||||
{
|
||||
const int size = 4;
|
||||
int count = (data.Length - 4) / size;
|
||||
|
@ -37,17 +38,23 @@ namespace PKHeX.Core
|
|||
for (int i = 0; i < slots.Length; i++)
|
||||
{
|
||||
int offset = 4 + (size * i);
|
||||
ushort SpecForm = BitConverter.ToUInt16(data, offset);
|
||||
int species = SpecForm & 0x3FF;
|
||||
int form = SpecForm >> 11;
|
||||
int min = data[offset + 2];
|
||||
int max = data[offset + 3];
|
||||
slots[i] = new EncounterSlot7(this, species, form, min, max);
|
||||
var entry = data.Slice(offset, size);
|
||||
slots[i] = ReadSlot(entry);
|
||||
}
|
||||
|
||||
return slots;
|
||||
}
|
||||
|
||||
private EncounterSlot7 ReadSlot(ReadOnlySpan<byte> entry)
|
||||
{
|
||||
ushort SpecForm = ReadUInt16LittleEndian(entry);
|
||||
int species = SpecForm & 0x3FF;
|
||||
int form = SpecForm >> 11;
|
||||
int min = entry[2];
|
||||
int max = entry[3];
|
||||
return new EncounterSlot7(this, species, form, min, max);
|
||||
}
|
||||
|
||||
public override IEnumerable<EncounterSlot> GetMatchingSlots(PKM pkm, IReadOnlyList<EvoCriteria> chain)
|
||||
{
|
||||
foreach (var slot in Slots)
|
||||
|
|
|
@ -1,4 +1,5 @@
|
|||
using System.Collections.Generic;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace PKHeX.Core
|
||||
{
|
||||
|
@ -20,13 +21,13 @@ namespace PKHeX.Core
|
|||
return result;
|
||||
}
|
||||
|
||||
private EncounterArea7b(byte[] data, GameVersion game) : base(game)
|
||||
private EncounterArea7b(ReadOnlySpan<byte> data, GameVersion game) : base(game)
|
||||
{
|
||||
Location = data[0] | (data[1] << 8);
|
||||
Slots = ReadSlots(data);
|
||||
}
|
||||
|
||||
private EncounterSlot7b[] ReadSlots(byte[] data)
|
||||
private EncounterSlot7b[] ReadSlots(ReadOnlySpan<byte> data)
|
||||
{
|
||||
const int size = 4;
|
||||
int count = (data.Length - 2) / size;
|
||||
|
@ -34,16 +35,22 @@ namespace PKHeX.Core
|
|||
for (int i = 0; i < slots.Length; i++)
|
||||
{
|
||||
int offset = 2 + (size * i);
|
||||
int species = data[offset]; // always < 255; only original 151
|
||||
// form is always 0
|
||||
int min = data[offset + 2];
|
||||
int max = data[offset + 3];
|
||||
slots[i] = new EncounterSlot7b(this, species, min, max);
|
||||
var entry = data.Slice(offset, size);
|
||||
slots[i] = ReadSlot(entry);
|
||||
}
|
||||
|
||||
return slots;
|
||||
}
|
||||
|
||||
private EncounterSlot7b ReadSlot(ReadOnlySpan<byte> entry)
|
||||
{
|
||||
int species = entry[0]; // always < 255; only original 151
|
||||
// form is always 0
|
||||
int min = entry[2];
|
||||
int max = entry[3];
|
||||
return new EncounterSlot7b(this, species, min, max);
|
||||
}
|
||||
|
||||
private const int CatchComboBonus = 1;
|
||||
|
||||
public override IEnumerable<EncounterSlot> GetMatchingSlots(PKM pkm, IReadOnlyList<EvoCriteria> chain)
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using static System.Buffers.Binary.BinaryPrimitives;
|
||||
|
||||
namespace PKHeX.Core
|
||||
{
|
||||
|
@ -37,9 +38,9 @@ namespace PKHeX.Core
|
|||
|
||||
private const int entrySize = (2 * sizeof(int)) + 2;
|
||||
|
||||
private static EncounterArea7g GetArea(byte[] data)
|
||||
private static EncounterArea7g GetArea(ReadOnlySpan<byte> data)
|
||||
{
|
||||
var sf = BitConverter.ToUInt16(data, 0);
|
||||
var sf = ReadUInt16LittleEndian(data);
|
||||
int species = sf & 0x7FF;
|
||||
int form = sf >> 11;
|
||||
|
||||
|
@ -48,20 +49,21 @@ namespace PKHeX.Core
|
|||
for (int i = 0; i < result.Length; i++)
|
||||
{
|
||||
var offset = (i * entrySize) + 2;
|
||||
result[i] = ReadSlot(data, offset, area, species, form);
|
||||
var entry = data.Slice(offset, entrySize);
|
||||
result[i] = ReadSlot(entry, area, species, form);
|
||||
}
|
||||
|
||||
return area;
|
||||
}
|
||||
|
||||
private static EncounterSlot7GO ReadSlot(byte[] data, int offset, EncounterArea7g area, int species, int form)
|
||||
private static EncounterSlot7GO ReadSlot(ReadOnlySpan<byte> entry, EncounterArea7g area, int species, int form)
|
||||
{
|
||||
int start = BitConverter.ToInt32(data, offset);
|
||||
int end = BitConverter.ToInt32(data, offset + 4);
|
||||
var sg = data[offset + 8];
|
||||
int start = ReadInt32LittleEndian(entry);
|
||||
int end = ReadInt32LittleEndian(entry[4..]);
|
||||
var sg = entry[8];
|
||||
var shiny = (Shiny)(sg & 0x3F);
|
||||
var gender = (Gender)(sg >> 6);
|
||||
var type = (PogoType)data[offset + 9];
|
||||
var type = (PogoType)entry[9];
|
||||
return new EncounterSlot7GO(area, species, form, start, end, shiny, gender, type);
|
||||
}
|
||||
|
||||
|
|
|
@ -3,6 +3,7 @@ using System.Collections.Generic;
|
|||
using System.Linq;
|
||||
using static PKHeX.Core.AreaWeather8;
|
||||
using static PKHeX.Core.AreaSlotType8;
|
||||
using static System.Buffers.Binary.BinaryPrimitives;
|
||||
|
||||
namespace PKHeX.Core
|
||||
{
|
||||
|
@ -369,7 +370,7 @@ namespace PKHeX.Core
|
|||
Slots = ReadSlots(areaData, areaData[1]);
|
||||
}
|
||||
|
||||
private EncounterSlot8[] ReadSlots(byte[] areaData, byte slotCount)
|
||||
private EncounterSlot8[] ReadSlots(ReadOnlySpan<byte> areaData, byte slotCount)
|
||||
{
|
||||
var slots = new EncounterSlot8[slotCount];
|
||||
|
||||
|
@ -378,17 +379,20 @@ namespace PKHeX.Core
|
|||
do
|
||||
{
|
||||
// Read area metadata
|
||||
var flags = (AreaWeather8) BitConverter.ToUInt16(areaData, ofs);
|
||||
var min = areaData[ofs + 2];
|
||||
var max = areaData[ofs + 3];
|
||||
var count = areaData[ofs + 4];
|
||||
var slotType = (AreaSlotType8) areaData[ofs + 5];
|
||||
var meta = areaData.Slice(ofs, 6);
|
||||
var flags = (AreaWeather8) ReadUInt16LittleEndian(meta);
|
||||
var min = meta[2];
|
||||
var max = meta[3];
|
||||
var count = meta[4];
|
||||
var slotType = (AreaSlotType8)meta[5];
|
||||
ofs += 6;
|
||||
|
||||
// Read slots
|
||||
for (int i = 0; i < count; i++, ctr++, ofs += 2)
|
||||
const int bpe = 2;
|
||||
for (int i = 0; i < count; i++, ctr++, ofs += bpe)
|
||||
{
|
||||
var specForm = BitConverter.ToUInt16(areaData, ofs);
|
||||
var entry = areaData.Slice(ofs, bpe);
|
||||
var specForm = ReadUInt16LittleEndian(entry);
|
||||
var species = specForm & 0x7FF;
|
||||
var form = specForm >> 11;
|
||||
slots[ctr] = new EncounterSlot8(this, species, form, min, max, flags, slotType);
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using static System.Buffers.Binary.BinaryPrimitives;
|
||||
|
||||
namespace PKHeX.Core
|
||||
{
|
||||
|
@ -21,7 +22,7 @@ namespace PKHeX.Core
|
|||
return result;
|
||||
}
|
||||
|
||||
private EncounterArea8b(byte[] data, GameVersion game) : base(game)
|
||||
private EncounterArea8b(ReadOnlySpan<byte> data, GameVersion game) : base(game)
|
||||
{
|
||||
Location = data[0] | (data[1] << 8);
|
||||
Type = (SlotType)data[2];
|
||||
|
@ -29,7 +30,7 @@ namespace PKHeX.Core
|
|||
Slots = ReadSlots(data);
|
||||
}
|
||||
|
||||
private EncounterSlot8b[] ReadSlots(byte[] data)
|
||||
private EncounterSlot8b[] ReadSlots(ReadOnlySpan<byte> data)
|
||||
{
|
||||
const int size = 4;
|
||||
int count = (data.Length - 4) / size;
|
||||
|
@ -37,16 +38,22 @@ namespace PKHeX.Core
|
|||
for (int i = 0; i < slots.Length; i++)
|
||||
{
|
||||
int offset = 4 + (size * i);
|
||||
ushort SpecForm = BitConverter.ToUInt16(data, offset);
|
||||
int species = SpecForm & 0x3FF;
|
||||
int form = SpecForm >> 11;
|
||||
int min = data[offset + 2];
|
||||
int max = data[offset + 3];
|
||||
slots[i] = new EncounterSlot8b(this, species, form, min, max);
|
||||
var entry = data.Slice(offset, size);
|
||||
slots[i] = ReadSlot(entry);
|
||||
}
|
||||
return slots;
|
||||
}
|
||||
|
||||
private EncounterSlot8b ReadSlot(ReadOnlySpan<byte> data)
|
||||
{
|
||||
ushort SpecForm = ReadUInt16LittleEndian(data);
|
||||
int species = SpecForm & 0x3FF;
|
||||
int form = SpecForm >> 11;
|
||||
int min = data[2];
|
||||
int max = data[3];
|
||||
return new EncounterSlot8b(this, species, form, min, max);
|
||||
}
|
||||
|
||||
public override bool IsMatchLocation(int location)
|
||||
{
|
||||
if (base.IsMatchLocation(location))
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using static System.Buffers.Binary.BinaryPrimitives;
|
||||
|
||||
namespace PKHeX.Core
|
||||
{
|
||||
|
@ -37,9 +38,9 @@ namespace PKHeX.Core
|
|||
|
||||
private const int entrySize = (2 * sizeof(int)) + 2;
|
||||
|
||||
private static EncounterArea8g GetArea(byte[] data)
|
||||
private static EncounterArea8g GetArea(ReadOnlySpan<byte> data)
|
||||
{
|
||||
var sf = BitConverter.ToUInt16(data, 0);
|
||||
var sf = ReadUInt16LittleEndian(data);
|
||||
int species = sf & 0x7FF;
|
||||
int form = sf >> 11;
|
||||
|
||||
|
@ -50,20 +51,21 @@ namespace PKHeX.Core
|
|||
for (int i = 0; i < result.Length; i++)
|
||||
{
|
||||
var offset = (i * entrySize) + 2;
|
||||
result[i] = ReadSlot(data, offset, area, species, form, group);
|
||||
var entry = data.Slice(offset, entrySize);
|
||||
result[i] = ReadSlot(entry, area, species, form, group);
|
||||
}
|
||||
|
||||
return area;
|
||||
}
|
||||
|
||||
private static EncounterSlot8GO ReadSlot(byte[] data, int offset, EncounterArea8g area, int species, int form, GameVersion group)
|
||||
private static EncounterSlot8GO ReadSlot(ReadOnlySpan<byte> entry, EncounterArea8g area, int species, int form, GameVersion group)
|
||||
{
|
||||
int start = BitConverter.ToInt32(data, offset);
|
||||
int end = BitConverter.ToInt32(data, offset + 4);
|
||||
var sg = data[offset + 8];
|
||||
int start = ReadInt32LittleEndian(entry);
|
||||
int end = ReadInt32LittleEndian(entry[4..]);
|
||||
var sg = entry[8];
|
||||
var shiny = (Shiny)(sg & 0x3F);
|
||||
var gender = (Gender)(sg >> 6);
|
||||
var type = (PogoType)data[offset + 9];
|
||||
var type = (PogoType)entry[9];
|
||||
return new EncounterSlot8GO(area, species, form, start, end, shiny, gender, type, group);
|
||||
}
|
||||
|
||||
|
|
|
@ -36,24 +36,24 @@ namespace PKHeX.Core
|
|||
/// <summary>Indicates if the databases are initialized.</summary>
|
||||
public static bool Initialized => MGDB_G3.Count != 0;
|
||||
|
||||
private static PCD[] GetPCDDB(byte[] bin) => Get(bin, PCD.Size, d => new PCD(d));
|
||||
private static PGF[] GetPGFDB(byte[] bin) => Get(bin, PGF.Size, d => new PGF(d));
|
||||
private static PCD[] GetPCDDB(ReadOnlySpan<byte> bin) => Get(bin, PCD.Size, d => new PCD(d));
|
||||
private static PGF[] GetPGFDB(ReadOnlySpan<byte> bin) => Get(bin, PGF.Size, d => new PGF(d));
|
||||
|
||||
private static WC6[] GetWC6DB(byte[] wc6bin, byte[] wc6full) => WC6Full.GetArray(wc6full, wc6bin);
|
||||
private static WC7[] GetWC7DB(byte[] wc7bin, byte[] wc7full) => WC7Full.GetArray(wc7full, wc7bin);
|
||||
private static WC6[] GetWC6DB(ReadOnlySpan<byte> wc6bin, ReadOnlySpan<byte> wc6full) => WC6Full.GetArray(wc6full, wc6bin);
|
||||
private static WC7[] GetWC7DB(ReadOnlySpan<byte> wc7bin, ReadOnlySpan<byte> wc7full) => WC7Full.GetArray(wc7full, wc7bin);
|
||||
|
||||
private static WB7[] GetWB7DB(byte[] bin) => Get(bin, WB7.SizeFull, d => new WB7(d));
|
||||
private static WC8[] GetWC8DB(byte[] bin) => Get(bin, WC8.Size, d => new WC8(d));
|
||||
private static WB8[] GetWB8DB(byte[] bin) => Get(bin, WB8.Size, d => new WB8(d));
|
||||
private static WB7[] GetWB7DB(ReadOnlySpan<byte> bin) => Get(bin, WB7.SizeFull, d => new WB7(d));
|
||||
private static WC8[] GetWC8DB(ReadOnlySpan<byte> bin) => Get(bin, WC8.Size, d => new WC8(d));
|
||||
private static WB8[] GetWB8DB(ReadOnlySpan<byte> bin) => Get(bin, WB8.Size, d => new WB8(d));
|
||||
|
||||
private static T[] Get<T>(byte[] bin, int size, Func<byte[], T> ctor)
|
||||
private static T[] Get<T>(ReadOnlySpan<byte> bin, int size, Func<byte[], T> ctor)
|
||||
{
|
||||
var result = new T[bin.Length / size];
|
||||
System.Diagnostics.Debug.Assert(result.Length * size == bin.Length);
|
||||
for (int i = 0; i < result.Length; i++)
|
||||
{
|
||||
var offset = i * size;
|
||||
var slice = bin.Slice(offset, size);
|
||||
var slice = bin.Slice(offset, size).ToArray();
|
||||
result[i] = ctor(slice);
|
||||
}
|
||||
return result;
|
||||
|
|
|
@ -165,8 +165,8 @@ namespace PKHeX.Core
|
|||
|
||||
public bool IsRandomUnspecificForm => Form >= FormDynamic;
|
||||
private const int FormDynamic = FormVivillon;
|
||||
private const int FormVivillon = 30;
|
||||
protected const int FormRandom = 31;
|
||||
protected internal const int FormVivillon = 30;
|
||||
protected internal const int FormRandom = 31;
|
||||
|
||||
private static int GetWildForm(PKM pk, int form, ITrainerInfo sav)
|
||||
{
|
||||
|
|
|
@ -1,4 +1,5 @@
|
|||
using System.Collections.Generic;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using static PKHeX.Core.AbilityPermission;
|
||||
|
||||
namespace PKHeX.Core
|
||||
|
@ -47,7 +48,7 @@ namespace PKHeX.Core
|
|||
/// <param name="encounterIVs">Encounter template's IV restrictions. Speed is not last.</param>
|
||||
/// <param name="generation">Destination generation</param>
|
||||
/// <returns>True if compatible, false if incompatible.</returns>
|
||||
public bool IsIVsCompatible(int[] encounterIVs, int generation)
|
||||
public bool IsIVsCompatible(Span<int> encounterIVs, int generation)
|
||||
{
|
||||
var IVs = encounterIVs;
|
||||
if (!ivCanMatch(IV_HP , IVs[0])) return false;
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using static PKHeX.Core.LegalityCheckStrings;
|
||||
using static System.Buffers.Binary.BinaryPrimitives;
|
||||
|
||||
namespace PKHeX.Core
|
||||
{
|
||||
|
@ -21,12 +22,13 @@ namespace PKHeX.Core
|
|||
private static Dictionary<int, MysteryGiftRestriction> GetRestriction(int generation)
|
||||
{
|
||||
var resource = RestrictionSetName(generation);
|
||||
var data = Util.GetBinaryResource(resource);
|
||||
var data = Util.GetBinaryResource(resource).AsSpan();
|
||||
var dict = new Dictionary<int, MysteryGiftRestriction>();
|
||||
for (int i = 0; i < data.Length; i += 8)
|
||||
{
|
||||
int hash = BitConverter.ToInt32(data, i + 0);
|
||||
var restrict = BitConverter.ToInt32(data, i + 4);
|
||||
var entry = data[i..];
|
||||
int hash = ReadInt32LittleEndian(entry);
|
||||
var restrict = ReadInt32LittleEndian(entry[4..]);
|
||||
dict.Add(hash, (MysteryGiftRestriction)restrict);
|
||||
}
|
||||
return dict;
|
||||
|
@ -34,21 +36,21 @@ namespace PKHeX.Core
|
|||
|
||||
public static CheckResult VerifyGift(PKM pk, MysteryGift g)
|
||||
{
|
||||
bool restricted = TryGetRestriction(g, out var val);
|
||||
bool restricted = TryGetRestriction(g, out var value);
|
||||
if (!restricted)
|
||||
return new CheckResult(CheckIdentifier.GameOrigin);
|
||||
|
||||
var ver = (int)val >> 16;
|
||||
var ver = (int)value >> 16;
|
||||
if (ver != 0 && !CanVersionReceiveGift(g.Generation, ver, pk.Version))
|
||||
return new CheckResult(Severity.Invalid, LEncGiftVersionNotDistributed, CheckIdentifier.GameOrigin);
|
||||
|
||||
var lang = val & MysteryGiftRestriction.LangRestrict;
|
||||
var lang = value & MysteryGiftRestriction.LangRestrict;
|
||||
if (lang != 0 && !lang.HasFlagFast((MysteryGiftRestriction) (1 << pk.Language)))
|
||||
return new CheckResult(Severity.Invalid, string.Format(LOTLanguage, lang.GetSuggestedLanguage(), pk.Language), CheckIdentifier.GameOrigin);
|
||||
|
||||
if (pk is IRegionOrigin tr)
|
||||
{
|
||||
var region = val & MysteryGiftRestriction.RegionRestrict;
|
||||
var region = value & MysteryGiftRestriction.RegionRestrict;
|
||||
if (region != 0 && !region.HasFlagFast((MysteryGiftRestriction)((int)MysteryGiftRestriction.RegionBase << tr.ConsoleRegion)))
|
||||
return new CheckResult(Severity.Invalid, LGeoHardwareRange, CheckIdentifier.GameOrigin);
|
||||
}
|
||||
|
|
|
@ -1,4 +1,5 @@
|
|||
using System.Collections.Generic;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using static PKHeX.Core.LegalityCheckStrings;
|
||||
using static PKHeX.Core.ParseSettings;
|
||||
|
||||
|
@ -127,7 +128,7 @@ namespace PKHeX.Core
|
|||
|
||||
private const int NO_DUPE = -1;
|
||||
|
||||
private static int IsAnyMoveDuplicate(int[] move)
|
||||
private static int IsAnyMoveDuplicate(ReadOnlySpan<int> move)
|
||||
{
|
||||
int m1 = move[0];
|
||||
int m2 = move[1];
|
||||
|
|
|
@ -8,17 +8,18 @@ namespace PKHeX.Core
|
|||
/// </summary>
|
||||
public static class EvolutionSet1
|
||||
{
|
||||
private static EvolutionMethod GetMethod(byte[] data, int offset)
|
||||
private static EvolutionMethod GetMethod(ReadOnlySpan<byte> data)
|
||||
{
|
||||
int method = data[offset];
|
||||
int species = data[offset + 1];
|
||||
int arg = data[offset + 2];
|
||||
int method = data[0];
|
||||
int species = data[1];
|
||||
int arg = data[2];
|
||||
|
||||
return (method == 1)
|
||||
? new EvolutionMethod(method, species, level: arg)
|
||||
: new EvolutionMethod(method, species, argument: arg);
|
||||
}
|
||||
|
||||
public static IReadOnlyList<EvolutionMethod[]> GetArray(byte[] data, int maxSpecies)
|
||||
public static IReadOnlyList<EvolutionMethod[]> GetArray(ReadOnlySpan<byte> data, int maxSpecies)
|
||||
{
|
||||
var evos = new EvolutionMethod[maxSpecies + 1][];
|
||||
int ofs = 0;
|
||||
|
@ -35,7 +36,7 @@ namespace PKHeX.Core
|
|||
var m = new EvolutionMethod[count];
|
||||
for (int j = 0; j < m.Length; j++)
|
||||
{
|
||||
m[j] = GetMethod(data, ofs);
|
||||
m[j] = GetMethod(data.Slice(ofs, bpe));
|
||||
ofs += bpe;
|
||||
}
|
||||
evos[i] = m;
|
||||
|
@ -43,4 +44,4 @@ namespace PKHeX.Core
|
|||
return evos;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using static System.Buffers.Binary.BinaryPrimitives;
|
||||
|
||||
namespace PKHeX.Core
|
||||
{
|
||||
|
@ -8,11 +9,11 @@ namespace PKHeX.Core
|
|||
/// </summary>
|
||||
public static class EvolutionSet3
|
||||
{
|
||||
private static EvolutionMethod GetMethod(byte[] data, int offset)
|
||||
private static EvolutionMethod GetMethod(ReadOnlySpan<byte> data)
|
||||
{
|
||||
int method = BitConverter.ToUInt16(data, offset + 0);
|
||||
int arg = BitConverter.ToUInt16(data, offset + 2);
|
||||
int species = SpeciesConverter.GetG4Species(BitConverter.ToUInt16(data, offset + 4));
|
||||
int method = ReadUInt16LittleEndian(data);
|
||||
int arg = ReadUInt16LittleEndian(data[2..]);
|
||||
int species = SpeciesConverter.GetG4Species(ReadUInt16LittleEndian(data[4..]));
|
||||
//2 bytes padding
|
||||
|
||||
switch (method)
|
||||
|
@ -42,7 +43,7 @@ namespace PKHeX.Core
|
|||
}
|
||||
}
|
||||
|
||||
public static IReadOnlyList<EvolutionMethod[]> GetArray(byte[] data)
|
||||
public static IReadOnlyList<EvolutionMethod[]> GetArray(ReadOnlySpan<byte> data)
|
||||
{
|
||||
var evos = new EvolutionMethod[Legal.MaxSpeciesID_3 + 1][];
|
||||
evos[0] = Array.Empty<EvolutionMethod>();
|
||||
|
@ -70,10 +71,10 @@ namespace PKHeX.Core
|
|||
|
||||
var set = new EvolutionMethod[count];
|
||||
for (int j = 0; j < set.Length; j++)
|
||||
set[j] = GetMethod(data, offset + (j * size));
|
||||
set[j] = GetMethod(data.Slice(offset + (j * size), size));
|
||||
evos[g4species] = set;
|
||||
}
|
||||
return evos;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using static System.Buffers.Binary.BinaryPrimitives;
|
||||
|
||||
namespace PKHeX.Core
|
||||
{
|
||||
|
@ -8,11 +9,11 @@ namespace PKHeX.Core
|
|||
/// </summary>
|
||||
public static class EvolutionSet4
|
||||
{
|
||||
private static EvolutionMethod GetMethod(byte[] data, int offset)
|
||||
private static EvolutionMethod GetMethod(ReadOnlySpan<byte> data)
|
||||
{
|
||||
var method = data[offset]; // other byte unnecessary
|
||||
int arg = BitConverter.ToUInt16(data, offset + 2);
|
||||
int species = BitConverter.ToUInt16(data, offset + 4);
|
||||
var method = data[0]; // other byte unnecessary
|
||||
int arg = ReadUInt16LittleEndian(data[2..]);
|
||||
int species = ReadUInt16LittleEndian(data[4..]);
|
||||
|
||||
if (method == 0)
|
||||
throw new ArgumentOutOfRangeException(nameof(method));
|
||||
|
@ -26,7 +27,7 @@ namespace PKHeX.Core
|
|||
return new EvolutionMethod(method, species, argument: arg, level: lvl);
|
||||
}
|
||||
|
||||
public static IReadOnlyList<EvolutionMethod[]> GetArray(byte[] data)
|
||||
public static IReadOnlyList<EvolutionMethod[]> GetArray(ReadOnlySpan<byte> data)
|
||||
{
|
||||
const int bpe = 6; // bytes per evolution entry
|
||||
const int entries = 7; // amount of entries per species
|
||||
|
@ -52,10 +53,10 @@ namespace PKHeX.Core
|
|||
|
||||
var set = new EvolutionMethod[count];
|
||||
for (int j = 0; j < set.Length; j++)
|
||||
set[j] = GetMethod(data, offset + (j * bpe));
|
||||
set[j] = GetMethod(data.Slice(offset + (j * bpe), bpe));
|
||||
evos[i] = set;
|
||||
}
|
||||
return evos;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using static System.Buffers.Binary.BinaryPrimitives;
|
||||
|
||||
namespace PKHeX.Core
|
||||
{
|
||||
|
@ -8,11 +9,11 @@ namespace PKHeX.Core
|
|||
/// </summary>
|
||||
public static class EvolutionSet5
|
||||
{
|
||||
private static EvolutionMethod GetMethod(byte[] data, int offset)
|
||||
private static EvolutionMethod GetMethod(ReadOnlySpan<byte> data)
|
||||
{
|
||||
var method = data[offset]; // other byte unnecessary
|
||||
int arg = BitConverter.ToUInt16(data, offset + 2);
|
||||
int species = BitConverter.ToUInt16(data, offset + 4);
|
||||
var method = data[0]; // other byte unnecessary
|
||||
int arg = ReadUInt16LittleEndian(data[2..]);
|
||||
int species = ReadUInt16LittleEndian(data[4..]);
|
||||
|
||||
if (method == 0)
|
||||
throw new ArgumentOutOfRangeException(nameof(method));
|
||||
|
@ -21,24 +22,18 @@ namespace PKHeX.Core
|
|||
return new EvolutionMethod(method, species, argument: arg, level: lvl);
|
||||
}
|
||||
|
||||
public static IReadOnlyList<EvolutionMethod[]> GetArray(byte[] data)
|
||||
{
|
||||
const int bpe = 6; // bytes per evolution entry
|
||||
const int entries = 7; // amount of entries per species
|
||||
const int size = entries * bpe; // bytes per species entry
|
||||
private const int bpe = 6; // bytes per evolution entry
|
||||
private const int entries = 7; // amount of entries per species
|
||||
private const int size = entries * bpe; // bytes per species entry
|
||||
|
||||
public static IReadOnlyList<EvolutionMethod[]> GetArray(ReadOnlySpan<byte> data)
|
||||
{
|
||||
var evos = new EvolutionMethod[data.Length / size][];
|
||||
for (int i = 0; i < evos.Length; i++)
|
||||
{
|
||||
int offset = i * size;
|
||||
int count = 0;
|
||||
for (; count < entries; count++)
|
||||
{
|
||||
var methodOffset = offset + (count * bpe);
|
||||
var method = data[methodOffset];
|
||||
if (method == 0)
|
||||
break;
|
||||
}
|
||||
var rawEntries = data.Slice(offset, size);
|
||||
var count = ScanCountEvolutions(rawEntries);
|
||||
if (count == 0)
|
||||
{
|
||||
evos[i] = Array.Empty<EvolutionMethod>();
|
||||
|
@ -47,10 +42,22 @@ namespace PKHeX.Core
|
|||
|
||||
var set = new EvolutionMethod[count];
|
||||
for (int j = 0; j < set.Length; j++)
|
||||
set[j] = GetMethod(data, offset + (j * bpe));
|
||||
set[j] = GetMethod(rawEntries.Slice((j * bpe), bpe));
|
||||
evos[i] = set;
|
||||
}
|
||||
return evos;
|
||||
}
|
||||
|
||||
private static int ScanCountEvolutions(ReadOnlySpan<byte> data)
|
||||
{
|
||||
for (int count = 0; count < entries; count++)
|
||||
{
|
||||
var methodOffset = count * bpe;
|
||||
var method = data[methodOffset];
|
||||
if (method == 0)
|
||||
return count;
|
||||
}
|
||||
return entries;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using static System.Buffers.Binary.BinaryPrimitives;
|
||||
|
||||
namespace PKHeX.Core
|
||||
{
|
||||
|
@ -11,23 +12,29 @@ namespace PKHeX.Core
|
|||
internal static readonly HashSet<int> EvosWithArg = new() {6, 8, 16, 17, 18, 19, 20, 21, 22, 29};
|
||||
private const int SIZE = 6;
|
||||
|
||||
private static EvolutionMethod[] GetMethods(byte[] data)
|
||||
private static EvolutionMethod[] GetMethods(ReadOnlySpan<byte> data)
|
||||
{
|
||||
var evos = new EvolutionMethod[data.Length / SIZE];
|
||||
for (int i = 0; i < data.Length; i += SIZE)
|
||||
{
|
||||
var method = BitConverter.ToUInt16(data, i + 0);
|
||||
var arg = BitConverter.ToUInt16(data, i + 2);
|
||||
var species = BitConverter.ToUInt16(data, i + 4);
|
||||
|
||||
// Argument is used by both Level argument and Item/Move/etc. Clear if appropriate.
|
||||
var lvl = EvosWithArg.Contains(method) ? 0 : arg;
|
||||
|
||||
evos[i/SIZE] = new EvolutionMethod(method, species, argument: arg, level: lvl);
|
||||
var entry = data.Slice(i, SIZE);
|
||||
evos[i/SIZE] = GetMethod(entry);
|
||||
}
|
||||
return evos;
|
||||
}
|
||||
|
||||
private static EvolutionMethod GetMethod(ReadOnlySpan<byte> entry)
|
||||
{
|
||||
var method = ReadUInt16LittleEndian(entry);
|
||||
var arg = ReadUInt16LittleEndian(entry[2..]);
|
||||
var species = ReadUInt16LittleEndian(entry[4..]);
|
||||
|
||||
// Argument is used by both Level argument and Item/Move/etc. Clear if appropriate.
|
||||
var lvl = EvosWithArg.Contains(method) ? 0 : arg;
|
||||
|
||||
return new EvolutionMethod(method, species, argument: arg, level: lvl);
|
||||
}
|
||||
|
||||
public static IReadOnlyList<EvolutionMethod[]> GetArray(IReadOnlyList<byte[]> data)
|
||||
{
|
||||
var evos = new EvolutionMethod[data.Count][];
|
||||
|
@ -36,4 +43,4 @@ namespace PKHeX.Core
|
|||
return evos;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using static System.Buffers.Binary.BinaryPrimitives;
|
||||
|
||||
namespace PKHeX.Core
|
||||
{
|
||||
|
@ -10,21 +11,27 @@ namespace PKHeX.Core
|
|||
{
|
||||
private const int SIZE = 8;
|
||||
|
||||
private static EvolutionMethod[] GetMethods(byte[] data)
|
||||
private static EvolutionMethod[] GetMethods(ReadOnlySpan<byte> data)
|
||||
{
|
||||
var evos = new EvolutionMethod[data.Length / SIZE];
|
||||
for (int i = 0; i < data.Length; i += SIZE)
|
||||
{
|
||||
var method = BitConverter.ToUInt16(data, i + 0);
|
||||
var arg = BitConverter.ToUInt16(data, i + 2);
|
||||
var species = BitConverter.ToUInt16(data, i + 4);
|
||||
var form = (sbyte) data[i + 6];
|
||||
var level = data[i + 7];
|
||||
evos[i / SIZE] = new EvolutionMethod(method, species, argument: arg, level: level, form: form);
|
||||
var entry = data.Slice(i, SIZE);
|
||||
evos[i / SIZE] = ReadEvolution(entry);
|
||||
}
|
||||
return evos;
|
||||
}
|
||||
|
||||
private static EvolutionMethod ReadEvolution(ReadOnlySpan<byte> entry)
|
||||
{
|
||||
var method = ReadUInt16LittleEndian(entry);
|
||||
var arg = ReadUInt16LittleEndian(entry[2..]);
|
||||
var species = ReadUInt16LittleEndian(entry[4..]);
|
||||
var form = (sbyte)entry[6];
|
||||
var level = entry[7];
|
||||
return new EvolutionMethod(method, species, argument: arg, level: level, form: form);
|
||||
}
|
||||
|
||||
public static IReadOnlyList<EvolutionMethod[]> GetArray(IReadOnlyList<byte[]> data)
|
||||
{
|
||||
var evos = new EvolutionMethod[data.Count][];
|
||||
|
@ -33,4 +40,4 @@ namespace PKHeX.Core
|
|||
return evos;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,4 +1,5 @@
|
|||
using System;
|
||||
using static System.Buffers.Binary.BinaryPrimitives;
|
||||
|
||||
namespace PKHeX.Core
|
||||
{
|
||||
|
@ -41,7 +42,7 @@ namespace PKHeX.Core
|
|||
/// Reads a Level up move pool definition from a contiguous chunk of GB era ROM data.
|
||||
/// </summary>
|
||||
/// <remarks>Moves and Levels are 8-bit</remarks>
|
||||
private static Learnset ReadLearnset8(byte[] data, ref int offset)
|
||||
private static Learnset ReadLearnset8(ReadOnlySpan<byte> data, ref int offset)
|
||||
{
|
||||
int end = offset; // scan for count
|
||||
if (data[end] == 0)
|
||||
|
@ -67,7 +68,7 @@ namespace PKHeX.Core
|
|||
/// Reads a Level up move pool definition from a single move pool definition.
|
||||
/// </summary>
|
||||
/// <remarks>Count of moves, followed by Moves and Levels which are 16-bit</remarks>
|
||||
private static Learnset ReadLearnset16(byte[] data)
|
||||
private static Learnset ReadLearnset16(ReadOnlySpan<byte> data)
|
||||
{
|
||||
if (data.Length == 0)
|
||||
return EMPTY;
|
||||
|
@ -76,9 +77,9 @@ namespace PKHeX.Core
|
|||
var Levels = new int[Count];
|
||||
for (int i = 0; i < Count; i++)
|
||||
{
|
||||
int ofs = i * 4;
|
||||
Moves[i] = BitConverter.ToInt16(data, ofs);
|
||||
Levels[i] = BitConverter.ToInt16(data, ofs + 2);
|
||||
var move = data.Slice(i * 4, 4);
|
||||
Moves[i] = ReadInt16LittleEndian(move);
|
||||
Levels[i] = ReadInt16LittleEndian(move[2..]);
|
||||
}
|
||||
return new Learnset(Moves, Levels);
|
||||
}
|
||||
|
|
|
@ -1,4 +1,5 @@
|
|||
using System.Runtime.CompilerServices;
|
||||
using System;
|
||||
using System.Runtime.CompilerServices;
|
||||
|
||||
namespace PKHeX.Core
|
||||
{
|
||||
|
@ -9,17 +10,19 @@ namespace PKHeX.Core
|
|||
/// </summary>
|
||||
/// <param name="rng">RNG to use</param>
|
||||
/// <param name="seed">RNG seed</param>
|
||||
/// <returns>Array of 6 IVs as <see cref="uint"/>.</returns>
|
||||
/// <param name="IVs">Expected IVs</param>
|
||||
/// <returns>True if all match.</returns>
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
internal static uint[] GetSequentialIVsUInt32(this LCRNG rng, uint seed)
|
||||
internal static bool GetSequentialIVsUInt32(this LCRNG rng, uint seed, ReadOnlySpan<uint> IVs)
|
||||
{
|
||||
uint[] ivs = new uint[6];
|
||||
for (int i = 0; i < 6; i++)
|
||||
foreach (var iv in IVs)
|
||||
{
|
||||
seed = rng.Next(seed);
|
||||
ivs[i] = seed >> 27;
|
||||
var IV = seed >> 27;
|
||||
if (IV != iv)
|
||||
return false;
|
||||
}
|
||||
return ivs;
|
||||
return true;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
|
@ -27,17 +30,16 @@ namespace PKHeX.Core
|
|||
/// </summary>
|
||||
/// <param name="rng">RNG to use</param>
|
||||
/// <param name="seed">RNG seed</param>
|
||||
/// <param name="ivs">Buffer to store generated values</param>
|
||||
/// <returns>Array of 6 IVs as <see cref="int"/>.</returns>
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
internal static int[] GetSequentialIVsInt32(this LCRNG rng, uint seed)
|
||||
internal static void GetSequentialIVsInt32(this LCRNG rng, uint seed, Span<int> ivs)
|
||||
{
|
||||
int[] ivs = new int[6];
|
||||
for (int i = 0; i < 6; i++)
|
||||
{
|
||||
seed = rng.Next(seed);
|
||||
ivs[i] = (int)(seed >> 27);
|
||||
}
|
||||
return ivs;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,4 +1,5 @@
|
|||
using System.Collections.Generic;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Diagnostics;
|
||||
using System.Linq;
|
||||
using System.Runtime.CompilerServices;
|
||||
|
@ -25,9 +26,10 @@ namespace PKHeX.Core
|
|||
var top = pid >> 16;
|
||||
var bot = pid & 0xFFFF;
|
||||
|
||||
var IVs = new uint[6];
|
||||
Span<uint> temp = stackalloc uint[6];
|
||||
for (int i = 0; i < 6; i++)
|
||||
IVs[i] = (uint)pk.GetIV(i);
|
||||
temp[i] = (uint)pk.GetIV(i);
|
||||
ReadOnlySpan<uint> IVs = temp;
|
||||
|
||||
if (GetLCRNGMatch(top, bot, IVs, out PIDIV pidiv))
|
||||
return pidiv;
|
||||
|
@ -54,7 +56,7 @@ namespace PKHeX.Core
|
|||
return PIDIV.None; // no match
|
||||
}
|
||||
|
||||
private static bool GetModifiedPIDMatch(PKM pk, uint pid, uint[] IVs, out PIDIV pidiv)
|
||||
private static bool GetModifiedPIDMatch(PKM pk, uint pid, ReadOnlySpan<uint> IVs, out PIDIV pidiv)
|
||||
{
|
||||
if (pk.IsShiny)
|
||||
{
|
||||
|
@ -79,7 +81,7 @@ namespace PKHeX.Core
|
|||
: GetG5MGShinyMatch(pk, pid, out pidiv) || (pid <= 0xFF && GetCuteCharmMatch(pk, pid, out pidiv));
|
||||
}
|
||||
|
||||
private static bool GetLCRNGMatch(uint top, uint bot, uint[] IVs, out PIDIV pidiv)
|
||||
private static bool GetLCRNGMatch(uint top, uint bot, ReadOnlySpan<uint> IVs, out PIDIV pidiv)
|
||||
{
|
||||
var reg = GetSeedsFromPID(RNG.LCRNG, top, bot);
|
||||
var iv1 = GetIVChunk(IVs, 0);
|
||||
|
@ -147,7 +149,7 @@ namespace PKHeX.Core
|
|||
return GetNonMatch(out pidiv);
|
||||
}
|
||||
|
||||
private static bool GetLCRNGUnownMatch(uint top, uint bot, uint[] IVs, out PIDIV pidiv)
|
||||
private static bool GetLCRNGUnownMatch(uint top, uint bot, ReadOnlySpan<uint> IVs, out PIDIV pidiv)
|
||||
{
|
||||
// this is an exact copy of LCRNG 1,2,4 matching, except the PID has its halves switched (BACD, BADE, BACE)
|
||||
var reg = GetSeedsFromPID(RNG.LCRNG, bot, top); // reversed!
|
||||
|
@ -216,7 +218,7 @@ namespace PKHeX.Core
|
|||
return GetNonMatch(out pidiv);
|
||||
}
|
||||
|
||||
private static bool GetLCRNGRoamerMatch(uint top, uint bot, uint[] IVs, out PIDIV pidiv)
|
||||
private static bool GetLCRNGRoamerMatch(uint top, uint bot, ReadOnlySpan<uint> IVs, out PIDIV pidiv)
|
||||
{
|
||||
if (IVs[2] != 0 || IVs[3] != 0 || IVs[4] != 0 || IVs[5] != 0 || IVs[1] > 7)
|
||||
return GetNonMatch(out pidiv);
|
||||
|
@ -235,7 +237,7 @@ namespace PKHeX.Core
|
|||
return GetNonMatch(out pidiv);
|
||||
}
|
||||
|
||||
private static bool GetXDRNGMatch(PKM pk, uint top, uint bot, uint[] IVs, out PIDIV pidiv)
|
||||
private static bool GetXDRNGMatch(PKM pk, uint top, uint bot, ReadOnlySpan<uint> IVs, out PIDIV pidiv)
|
||||
{
|
||||
var xdc = GetSeedsFromPIDEuclid(RNG.XDRNG, top, bot);
|
||||
foreach (var seed in xdc)
|
||||
|
@ -284,7 +286,7 @@ namespace PKHeX.Core
|
|||
return GetNonMatch(out pidiv);
|
||||
}
|
||||
|
||||
private static bool GetChannelMatch(uint top, uint bot, uint[] IVs, out PIDIV pidiv, PKM pk)
|
||||
private static bool GetChannelMatch(uint top, uint bot, ReadOnlySpan<uint> IVs, out PIDIV pidiv, PKM pk)
|
||||
{
|
||||
var ver = pk.Version;
|
||||
if (ver is not ((int)GameVersion.R or (int)GameVersion.S))
|
||||
|
@ -307,7 +309,7 @@ namespace PKHeX.Core
|
|||
if (E >> 31 != pk.OT_Gender)
|
||||
continue;
|
||||
|
||||
if (!RNG.XDRNG.GetSequentialIVsUInt32(E).SequenceEqual(IVs))
|
||||
if (!RNG.XDRNG.GetSequentialIVsUInt32(E, IVs))
|
||||
continue;
|
||||
|
||||
if (seed >> 16 != pk.SID)
|
||||
|
@ -319,7 +321,7 @@ namespace PKHeX.Core
|
|||
return GetNonMatch(out pidiv);
|
||||
}
|
||||
|
||||
private static bool GetMG4Match(uint pid, uint[] IVs, out PIDIV pidiv)
|
||||
private static bool GetMG4Match(uint pid, ReadOnlySpan<uint> IVs, out PIDIV pidiv)
|
||||
{
|
||||
uint mg4Rev = RNG.ARNG.Prev(pid);
|
||||
var mg4 = GetSeedsFromPID(RNG.LCRNG, mg4Rev >> 16, mg4Rev & 0xFFFF);
|
||||
|
@ -387,7 +389,7 @@ namespace PKHeX.Core
|
|||
return GetNonMatch(out pidiv);
|
||||
}
|
||||
|
||||
private static bool GetChainShinyMatch(PKM pk, uint pid, uint[] IVs, out PIDIV pidiv)
|
||||
private static bool GetChainShinyMatch(PKM pk, uint pid, ReadOnlySpan<uint> IVs, out PIDIV pidiv)
|
||||
{
|
||||
// 13 shiny bits
|
||||
// PIDH & 7
|
||||
|
@ -432,7 +434,7 @@ namespace PKHeX.Core
|
|||
|
||||
public static IEnumerable<uint> GetCuteCharmSeeds(PKM pk)
|
||||
{
|
||||
var IVs = new uint[6];
|
||||
Span<uint> IVs = stackalloc uint[6];
|
||||
for (int i = 0; i < 6; i++)
|
||||
IVs[i] = (uint)pk.GetIV(i);
|
||||
var bot = GetIVChunk(IVs, 0);
|
||||
|
@ -441,7 +443,7 @@ namespace PKHeX.Core
|
|||
return GetSeedsFromIVs(RNG.LCRNG, top, bot);
|
||||
}
|
||||
|
||||
private static bool GetBACDMatch(PKM pk, uint pid, uint[] IVs, out PIDIV pidiv)
|
||||
private static bool GetBACDMatch(PKM pk, uint pid, ReadOnlySpan<uint> IVs, out PIDIV pidiv)
|
||||
{
|
||||
var bot = GetIVChunk(IVs, 0);
|
||||
var top = GetIVChunk(IVs, 3);
|
||||
|
@ -536,7 +538,7 @@ namespace PKHeX.Core
|
|||
return pid == oldpid;
|
||||
}
|
||||
|
||||
private static bool GetColoStarterMatch(PKM pk, uint top, uint bot, uint[] IVs, out PIDIV pidiv)
|
||||
private static bool GetColoStarterMatch(PKM pk, uint top, uint bot, ReadOnlySpan<uint> IVs, out PIDIV pidiv)
|
||||
{
|
||||
if (pk.Version != (int)GameVersion.CXD || pk.Species is not ((int)Species.Espeon or (int)Species.Umbreon))
|
||||
return GetNonMatch(out pidiv);
|
||||
|
@ -700,7 +702,7 @@ namespace PKHeX.Core
|
|||
/// <param name="IVs">IVs that should be the result</param>
|
||||
/// <returns>IVs match random number IVs</returns>
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
private static bool IVsMatch(uint r1, uint r2, IReadOnlyList<uint> IVs)
|
||||
private static bool IVsMatch(uint r1, uint r2, ReadOnlySpan<uint> IVs)
|
||||
{
|
||||
if (IVs[0] != (r1 & 31))
|
||||
return false;
|
||||
|
@ -749,7 +751,7 @@ namespace PKHeX.Core
|
|||
};
|
||||
}
|
||||
|
||||
private static uint GetIVChunk(uint[] IVs, int start)
|
||||
private static uint GetIVChunk(ReadOnlySpan<uint> IVs, int start)
|
||||
{
|
||||
uint val = 0;
|
||||
for (int i = 0; i < 3; i++)
|
||||
|
|
|
@ -1,4 +1,6 @@
|
|||
namespace PKHeX.Core
|
||||
using System;
|
||||
|
||||
namespace PKHeX.Core
|
||||
{
|
||||
/// <summary>
|
||||
/// Contains logic for the Generation 8 (SW/SH) overworld spawns that walk around the overworld.
|
||||
|
@ -55,7 +57,7 @@
|
|||
pk.PID = pid;
|
||||
|
||||
// IVs
|
||||
var ivs = new[] {UNSET, UNSET, UNSET, UNSET, UNSET, UNSET};
|
||||
Span<int> ivs = stackalloc[] {UNSET, UNSET, UNSET, UNSET, UNSET, UNSET};
|
||||
const int MAX = 31;
|
||||
for (int i = 0; i < flawless; i++)
|
||||
{
|
||||
|
@ -153,7 +155,7 @@
|
|||
continue;
|
||||
|
||||
var copy = xoro;
|
||||
int[] ivs = { UNSET, UNSET, UNSET, UNSET, UNSET, UNSET };
|
||||
Span<int> ivs = stackalloc [] { UNSET, UNSET, UNSET, UNSET, UNSET, UNSET };
|
||||
const int MAX = 31;
|
||||
for (int i = 0; i < iv_count; i++)
|
||||
{
|
||||
|
@ -162,8 +164,18 @@
|
|||
ivs[index] = MAX;
|
||||
}
|
||||
|
||||
if (!IsValidSequence(pk, ivs, ref copy))
|
||||
continue;
|
||||
for (var i = 0; i < ivs.Length; i++)
|
||||
{
|
||||
if (ivs[i] == UNSET)
|
||||
ivs[i] = (int)copy.NextInt(31 + 1);
|
||||
}
|
||||
|
||||
if (ivs[0] != pk.IV_HP) continue;
|
||||
if (ivs[1] != pk.IV_ATK) continue;
|
||||
if (ivs[2] != pk.IV_DEF) continue;
|
||||
if (ivs[3] != pk.IV_SPA) continue;
|
||||
if (ivs[4] != pk.IV_SPD) continue;
|
||||
if (ivs[5] != pk.IV_SPE) continue;
|
||||
|
||||
if (pk is not IScaledSize s)
|
||||
continue;
|
||||
|
@ -179,28 +191,6 @@
|
|||
return NoMatchIVs;
|
||||
}
|
||||
|
||||
private static bool IsValidSequence(PKM pk, int[] template, ref Xoroshiro128Plus rng)
|
||||
{
|
||||
for (int i = 0; i < 6; i++)
|
||||
{
|
||||
var temp = template[i];
|
||||
var expect = temp == UNSET ? (int)rng.NextInt(32) : temp;
|
||||
var actual = i switch
|
||||
{
|
||||
0 => pk.IV_HP,
|
||||
1 => pk.IV_ATK,
|
||||
2 => pk.IV_DEF,
|
||||
3 => pk.IV_SPA,
|
||||
4 => pk.IV_SPD,
|
||||
_ => pk.IV_SPE,
|
||||
};
|
||||
if (expect != actual)
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
private static uint GetShinyPID(int tid, int sid, uint pid, int type)
|
||||
{
|
||||
return (uint)(((tid ^ sid ^ (pid & 0xFFFF) ^ type) << 16) | (pid & 0xFFFF));
|
||||
|
|
|
@ -127,7 +127,9 @@ namespace PKHeX.Core
|
|||
pk.HeldItem = (int)(C >> 31) + 169; // 0-Ganlon, 1-Salac
|
||||
pk.Version = (int)(D >> 31) + 1; // 0-Sapphire, 1-Ruby
|
||||
pk.OT_Gender = (int)(E >> 31);
|
||||
pk.IVs = rng.GetSequentialIVsInt32(E);
|
||||
Span<int> ivs = stackalloc int[6];
|
||||
rng.GetSequentialIVsInt32(E, ivs);
|
||||
pk.SetIVs(ivs);
|
||||
}
|
||||
|
||||
public static void SetValuesFromSeed(PKM pk, PIDType type, uint seed)
|
||||
|
|
|
@ -1,4 +1,6 @@
|
|||
namespace PKHeX.Core
|
||||
using System;
|
||||
|
||||
namespace PKHeX.Core
|
||||
{
|
||||
/// <summary>
|
||||
/// Contains logic for the Generation 8b (BD/SP) roaming spawns.
|
||||
|
@ -61,12 +63,12 @@
|
|||
pk.PID = pid;
|
||||
|
||||
// Check IVs: Create flawless IVs at random indexes, then the random IVs for not flawless.
|
||||
int[] ivs = { UNSET, UNSET, UNSET, UNSET, UNSET, UNSET };
|
||||
Span<int> ivs = stackalloc [] { UNSET, UNSET, UNSET, UNSET, UNSET, UNSET };
|
||||
const int MAX = 31;
|
||||
var determined = 0;
|
||||
while (determined < flawless)
|
||||
{
|
||||
var idx = xoro.NextUInt(6);
|
||||
var idx = (int)xoro.NextUInt(6);
|
||||
if (ivs[idx] != UNSET)
|
||||
continue;
|
||||
ivs[idx] = 31;
|
||||
|
@ -115,12 +117,12 @@
|
|||
return false;
|
||||
|
||||
// Check IVs: Create flawless IVs at random indexes, then the random IVs for not flawless.
|
||||
int[] ivs = { UNSET, UNSET, UNSET, UNSET, UNSET, UNSET };
|
||||
Span<int> ivs = stackalloc [] { UNSET, UNSET, UNSET, UNSET, UNSET, UNSET };
|
||||
|
||||
var determined = 0;
|
||||
while (determined < flawless)
|
||||
{
|
||||
var idx = xoro.NextUInt(6);
|
||||
var idx = (int)xoro.NextUInt(6);
|
||||
if (ivs[idx] != UNSET)
|
||||
continue;
|
||||
ivs[idx] = 31;
|
||||
|
@ -133,12 +135,12 @@
|
|||
ivs[i] = (int)xoro.NextUInt(31 + 1);
|
||||
}
|
||||
|
||||
if (ivs[0] != pk.GetIV(0)) return false;
|
||||
if (ivs[1] != pk.GetIV(1)) return false;
|
||||
if (ivs[2] != pk.GetIV(2)) return false;
|
||||
if (ivs[3] != pk.GetIV(4)) return false;
|
||||
if (ivs[4] != pk.GetIV(5)) return false;
|
||||
if (ivs[5] != pk.GetIV(3)) return false;
|
||||
if (ivs[0] != pk.IV_HP ) return false;
|
||||
if (ivs[1] != pk.IV_ATK) return false;
|
||||
if (ivs[2] != pk.IV_DEF) return false;
|
||||
if (ivs[3] != pk.IV_SPA) return false;
|
||||
if (ivs[4] != pk.IV_SPD) return false;
|
||||
if (ivs[5] != pk.IV_SPE) return false;
|
||||
|
||||
// Don't check Hidden ability, as roaming encounters are 1/2 only.
|
||||
if (pk.AbilityNumber != (1 << (int)xoro.NextUInt(2)))
|
||||
|
|
|
@ -84,8 +84,8 @@ namespace PKHeX.Core
|
|||
return true;
|
||||
if (loc is Encounters8Nest.SharedNest)
|
||||
return !PossibleGeneralLocations8.Contains(arg) || arg is 79; // dangerous place - all locations are Y-Comm locked
|
||||
if (SingleGenLocAreas.TryGetValue((byte)loc, out var val))
|
||||
return arg != val;
|
||||
if (SingleGenLocAreas.TryGetValue((byte)loc, out var value))
|
||||
return arg != value;
|
||||
if (MultiGenLocAreas.TryGetValue((byte)loc, out var arr))
|
||||
return !arr.Contains(arg);
|
||||
return false;
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
using System;
|
||||
using System.Linq;
|
||||
using static System.Buffers.Binary.BinaryPrimitives;
|
||||
|
||||
namespace PKHeX.Core
|
||||
{
|
||||
|
@ -14,16 +15,16 @@ namespace PKHeX.Core
|
|||
{
|
||||
private EggMoves2(int[] moves) : base(moves) { }
|
||||
|
||||
public static EggMoves2[] GetArray(byte[] data, int count)
|
||||
public static EggMoves2[] GetArray(ReadOnlySpan<byte> data, int count)
|
||||
{
|
||||
var entries = new EggMoves2[count + 1];
|
||||
var empty = entries[0] = new EggMoves2(Array.Empty<int>());
|
||||
|
||||
int baseOffset = BitConverter.ToInt16(data, 0) - (count * 2);
|
||||
int baseOffset = ReadInt16LittleEndian(data) - (count * 2);
|
||||
for (int i = 1; i < entries.Length; i++)
|
||||
{
|
||||
int start = BitConverter.ToInt16(data, (i - 1) * 2) - baseOffset;
|
||||
int end = Array.IndexOf(data, (byte)0xFF, start);
|
||||
int start = ReadInt16LittleEndian(data[((i - 1) * 2)..]) - baseOffset;
|
||||
int end = data[start..].IndexOf((byte)0xFF) + start;
|
||||
if (start == end)
|
||||
{
|
||||
entries[i] = empty;
|
||||
|
@ -47,15 +48,16 @@ namespace PKHeX.Core
|
|||
|
||||
private EggMoves6(int[] moves) : base(moves) { }
|
||||
|
||||
private static EggMoves6 Get(byte[] data)
|
||||
private static EggMoves6 Get(ReadOnlySpan<byte> data)
|
||||
{
|
||||
if (data.Length == 0)
|
||||
return None;
|
||||
|
||||
int count = BitConverter.ToInt16(data, 0);
|
||||
int count = ReadInt16LittleEndian(data);
|
||||
var moves = new int[count];
|
||||
var span = data[2..];
|
||||
for (int i = 0; i < moves.Length; i++)
|
||||
moves[i] = BitConverter.ToInt16(data, 2 + (i * 2));
|
||||
moves[i] = ReadInt16LittleEndian(span[(i * 2)..]);
|
||||
return new EggMoves6(moves);
|
||||
}
|
||||
|
||||
|
@ -75,16 +77,18 @@ namespace PKHeX.Core
|
|||
|
||||
private EggMoves7(int[] moves, int formIndex = 0) : base(moves) => FormTableIndex = formIndex;
|
||||
|
||||
private static EggMoves7 Get(byte[] data)
|
||||
private static EggMoves7 Get(ReadOnlySpan<byte> data)
|
||||
{
|
||||
if (data.Length == 0)
|
||||
return None;
|
||||
|
||||
int formIndex = BitConverter.ToInt16(data, 0);
|
||||
int count = BitConverter.ToInt16(data, 2);
|
||||
int formIndex = ReadInt16LittleEndian(data);
|
||||
int count = ReadInt16LittleEndian(data[2..]);
|
||||
var moves = new int[count];
|
||||
|
||||
var moveSpan = data[4..];
|
||||
for (int i = 0; i < moves.Length; i++)
|
||||
moves[i] = BitConverter.ToInt16(data, 4 + (i * 2));
|
||||
moves[i] = ReadInt16LittleEndian(moveSpan[(i * 2)..]);
|
||||
return new EggMoves7(moves, formIndex);
|
||||
}
|
||||
|
||||
|
|
|
@ -21,7 +21,7 @@ namespace PKHeX.Core
|
|||
var pkm = data.pkm;
|
||||
var train = (ISuperTrain)pkm;
|
||||
var Info = data.Info;
|
||||
uint value = BitConverter.ToUInt32(data.pkm.Data, 0x2C);
|
||||
uint value = System.Buffers.Binary.BinaryPrimitives.ReadUInt32LittleEndian(data.pkm.Data.AsSpan(0x2C));
|
||||
if ((value & 3) != 0) // 2 unused flags
|
||||
data.AddLine(GetInvalid(LSuperUnused));
|
||||
int TrainCount = train.SuperTrainingMedalCount();
|
||||
|
|
|
@ -3,6 +3,7 @@ using System.Collections.Generic;
|
|||
using System.Linq;
|
||||
using static PKHeX.Core.LegalityCheckStrings;
|
||||
using static PKHeX.Core.CheckIdentifier;
|
||||
using static System.Buffers.Binary.BinaryPrimitives;
|
||||
|
||||
namespace PKHeX.Core
|
||||
{
|
||||
|
@ -435,8 +436,12 @@ namespace PKHeX.Core
|
|||
|
||||
private static bool IsCloseEnough(float a, float b)
|
||||
{
|
||||
var ia = BitConverter.ToInt32(BitConverter.GetBytes(a), 0);
|
||||
var ib = BitConverter.ToInt32(BitConverter.GetBytes(b), 0);
|
||||
// since we don't have access to SingleToInt32Bits on net46, just do a temp write-read.
|
||||
Span<byte> ta = stackalloc byte[4];
|
||||
WriteSingleLittleEndian(ta, a);
|
||||
var ia = ReadInt32LittleEndian(ta);
|
||||
WriteSingleLittleEndian(ta, b);
|
||||
var ib = ReadInt32LittleEndian(ta);
|
||||
return Math.Abs(ia - ib) <= 7;
|
||||
}
|
||||
|
||||
|
|
|
@ -164,7 +164,7 @@ namespace PKHeX.Core
|
|||
data.AddLine(Get(msg, ParseSettings.NicknamedAnotherSpecies));
|
||||
return true;
|
||||
}
|
||||
if (pkm.Format <= 7 && StringConverter.HasEastAsianScriptCharacters(nickname) && pkm is not PB7) // East Asian Scripts
|
||||
if (pkm.Format <= 7 && StringConverter.HasEastAsianScriptCharacters(nickname.AsSpan()) && pkm is not PB7) // East Asian Scripts
|
||||
{
|
||||
data.AddLine(GetInvalid(LNickInvalidChar));
|
||||
return true;
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using static System.Buffers.Binary.BinaryPrimitives;
|
||||
|
||||
namespace PKHeX.Core
|
||||
{
|
||||
|
@ -58,7 +59,7 @@ namespace PKHeX.Core
|
|||
WB8.Size => new WB8(data),
|
||||
|
||||
// WC6/WC7: Check year
|
||||
WC6.Size => BitConverter.ToUInt32(data, 0x4C) / 10000 < 2000 ? new WC7(data) : new WC6(data),
|
||||
WC6.Size => ReadUInt32LittleEndian(data.AsSpan(0x4C)) / 10000 < 2000 ? new WC7(data) : new WC6(data),
|
||||
// WC6Full/WC7Full: 0x205 has 3 * 0x46 for gen6, now only 2.
|
||||
WC6Full.Size => data[0x205] == 0 ? new WC7Full(data).Gift : new WC6Full(data).Gift,
|
||||
_ => null,
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using static System.Buffers.Binary.BinaryPrimitives;
|
||||
|
||||
namespace PKHeX.Core
|
||||
{
|
||||
|
@ -50,7 +51,7 @@ namespace PKHeX.Core
|
|||
private PGT? _gift;
|
||||
|
||||
public Span<byte> GetMetadata() => Data.AsSpan(PGT.Size);
|
||||
public void SetMetadata(byte[] data) => data.CopyTo(Data, Data.Length - PGT.Size);
|
||||
public void SetMetadata(ReadOnlySpan<byte> data) => data.CopyTo(Data.AsSpan(PGT.Size));
|
||||
|
||||
public override bool GiftUsed { get => Gift.GiftUsed; set => Gift.GiftUsed = value; }
|
||||
public override bool IsPokémon { get => Gift.IsPokémon; set => Gift.IsPokémon = value; }
|
||||
|
@ -59,27 +60,21 @@ namespace PKHeX.Core
|
|||
|
||||
public override int CardID
|
||||
{
|
||||
get => BitConverter.ToUInt16(Data, 0x150);
|
||||
set => BitConverter.GetBytes((ushort)value).CopyTo(Data, 0x150);
|
||||
get => ReadUInt16LittleEndian(Data.AsSpan(0x150));
|
||||
set => WriteUInt16LittleEndian(Data.AsSpan(0x150), (ushort)value);
|
||||
}
|
||||
|
||||
private const int TitleLength = 0x48;
|
||||
|
||||
private Span<byte> CardTitleSpan => Data.AsSpan(0x104, TitleLength);
|
||||
|
||||
public override string CardTitle
|
||||
{
|
||||
get => StringConverter4.GetString4(Data, 0x104, TitleLength);
|
||||
set
|
||||
{
|
||||
byte[] data = StringConverter4.SetString4(value, (TitleLength / 2) - 1, TitleLength / 2, 0xFFFF);
|
||||
int len = data.Length;
|
||||
Array.Resize(ref data, 0x48);
|
||||
for (int i = 0; i < len; i++)
|
||||
data[i] = 0xFF;
|
||||
data.CopyTo(Data, 0x104);
|
||||
}
|
||||
get => StringConverter4.GetString(CardTitleSpan);
|
||||
set => StringConverter4.SetString(CardTitleSpan, value.AsSpan(), TitleLength / 2, StringConverterOption.ClearFF);
|
||||
}
|
||||
|
||||
public ushort CardCompatibility => BitConverter.ToUInt16(Data, 0x14C); // rest of bytes we don't really care about
|
||||
public ushort CardCompatibility => ReadUInt16LittleEndian(Data.AsSpan(0x14C)); // rest of bytes we don't really care about
|
||||
|
||||
public override int Species { get => Gift.IsManaphyEgg ? 490 : Gift.Species; set => Gift.Species = value; }
|
||||
public override IReadOnlyList<int> Moves { get => Gift.Moves; set => Gift.Moves = value; }
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using static System.Buffers.Binary.BinaryPrimitives;
|
||||
|
||||
namespace PKHeX.Core
|
||||
{
|
||||
|
@ -14,11 +15,11 @@ namespace PKHeX.Core
|
|||
public PGF() : this(new byte[Size]) { }
|
||||
public PGF(byte[] data) : base(data) { }
|
||||
|
||||
public override int TID { get => BitConverter.ToUInt16(Data, 0x00); set => BitConverter.GetBytes((ushort)value).CopyTo(Data, 0x00); }
|
||||
public override int SID { get => BitConverter.ToUInt16(Data, 0x02); set => BitConverter.GetBytes((ushort)value).CopyTo(Data, 0x02); }
|
||||
public override int TID { get => ReadUInt16LittleEndian(Data.AsSpan(0x00)); set => WriteUInt16LittleEndian(Data.AsSpan(0x00), (ushort)value); }
|
||||
public override int SID { get => ReadUInt16LittleEndian(Data.AsSpan(0x02)); set => WriteUInt16LittleEndian(Data.AsSpan(0x02), (ushort)value); }
|
||||
public int OriginGame { get => Data[0x04]; set => Data[0x04] = (byte)value; }
|
||||
// Unused 0x05 0x06, 0x07
|
||||
public uint PID { get => BitConverter.ToUInt32(Data, 0x08); set => BitConverter.GetBytes(value).CopyTo(Data, 0x08); }
|
||||
public uint PID { get => ReadUInt32LittleEndian(Data.AsSpan(0x08)); set => WriteUInt32LittleEndian(Data.AsSpan(0x08), value); }
|
||||
|
||||
private byte RIB0 { get => Data[0x0C]; set => Data[0x0C] = value; }
|
||||
private byte RIB1 { get => Data[0x0D]; set => Data[0x0D] = value; }
|
||||
|
@ -40,27 +41,27 @@ namespace PKHeX.Core
|
|||
public bool RIB1_7 { get => (RIB1 & (1 << 7)) == 1 << 7; set => RIB1 = (byte)((RIB1 & ~(1 << 7)) | (value ? 1 << 7 : 0)); }
|
||||
|
||||
public override int Ball { get => Data[0x0E]; set => Data[0x0E] = (byte)value; }
|
||||
public override int HeldItem { get => BitConverter.ToUInt16(Data, 0x10); set => BitConverter.GetBytes((ushort)value).CopyTo(Data, 0x10); }
|
||||
public int Move1 { get => BitConverter.ToUInt16(Data, 0x12); set => BitConverter.GetBytes((ushort)value).CopyTo(Data, 0x12); }
|
||||
public int Move2 { get => BitConverter.ToUInt16(Data, 0x14); set => BitConverter.GetBytes((ushort)value).CopyTo(Data, 0x14); }
|
||||
public int Move3 { get => BitConverter.ToUInt16(Data, 0x16); set => BitConverter.GetBytes((ushort)value).CopyTo(Data, 0x16); }
|
||||
public int Move4 { get => BitConverter.ToUInt16(Data, 0x18); set => BitConverter.GetBytes((ushort)value).CopyTo(Data, 0x18); }
|
||||
public override int Species { get => BitConverter.ToUInt16(Data, 0x1A); set => BitConverter.GetBytes((ushort)value).CopyTo(Data, 0x1A); }
|
||||
public override int HeldItem { get => ReadUInt16LittleEndian(Data.AsSpan(0x10)); set => WriteUInt16LittleEndian(Data.AsSpan(0x10), (ushort)value); }
|
||||
public int Move1 { get => ReadUInt16LittleEndian(Data.AsSpan(0x12)); set => WriteUInt16LittleEndian(Data.AsSpan(0x12), (ushort)value); }
|
||||
public int Move2 { get => ReadUInt16LittleEndian(Data.AsSpan(0x14)); set => WriteUInt16LittleEndian(Data.AsSpan(0x14), (ushort)value); }
|
||||
public int Move3 { get => ReadUInt16LittleEndian(Data.AsSpan(0x16)); set => WriteUInt16LittleEndian(Data.AsSpan(0x16), (ushort)value); }
|
||||
public int Move4 { get => ReadUInt16LittleEndian(Data.AsSpan(0x18)); set => WriteUInt16LittleEndian(Data.AsSpan(0x18), (ushort)value); }
|
||||
public override int Species { get => ReadUInt16LittleEndian(Data.AsSpan(0x1A)); set => WriteUInt16LittleEndian(Data.AsSpan(0x1A), (ushort)value); }
|
||||
public override int Form { get => Data[0x1C]; set => Data[0x1C] = (byte)value; }
|
||||
public int Language { get => Data[0x1D]; set => Data[0x1D] = (byte)value; }
|
||||
|
||||
public string Nickname
|
||||
{
|
||||
get => StringConverter.GetString5(Data, 0x1E, 11 * 2);
|
||||
set => StringConverter.SetString5(value, 11, 11, '\uFFFF').CopyTo(Data, 0x1E);
|
||||
get => StringConverter5.GetString(Data.AsSpan( 0x1E, 11 * 2));
|
||||
set => StringConverter5.SetString(Data.AsSpan(0x1E, 11 * 2), value.AsSpan(), 11, StringConverterOption.ClearFF);
|
||||
}
|
||||
|
||||
public int Nature { get => (sbyte)Data[0x34]; set => Data[0x34] = (byte)value; }
|
||||
public override int Gender { get => Data[0x35]; set => Data[0x35] = (byte)value; }
|
||||
public override int AbilityType { get => Data[0x36]; set => Data[0x36] = (byte)value; }
|
||||
public int PIDType { get => Data[0x37]; set => Data[0x37] = (byte)value; }
|
||||
public override int EggLocation { get => BitConverter.ToUInt16(Data, 0x38); set => BitConverter.GetBytes((ushort)value).CopyTo(Data, 0x38); }
|
||||
public ushort MetLocation { get => BitConverter.ToUInt16(Data, 0x3A); set => BitConverter.GetBytes(value).CopyTo(Data, 0x3A); }
|
||||
public override int EggLocation { get => ReadUInt16LittleEndian(Data.AsSpan(0x38)); set => WriteUInt16LittleEndian(Data.AsSpan(0x38), (ushort)value); }
|
||||
public ushort MetLocation { get => ReadUInt16LittleEndian(Data.AsSpan(0x3A)); set => WriteUInt16LittleEndian(Data.AsSpan(0x3A), value); }
|
||||
public int MetLevel { get => Data[0x3C]; set => Data[0x3C] = (byte)value; }
|
||||
public byte CNT_Cool { get => Data[0x3D]; set => Data[0x3D] = value; }
|
||||
public byte CNT_Beauty { get => Data[0x3E]; set => Data[0x3E] = value; }
|
||||
|
@ -77,8 +78,8 @@ namespace PKHeX.Core
|
|||
// Unused 0x49
|
||||
public override string OT_Name
|
||||
{
|
||||
get => StringConverter.GetString5(Data, 0x4A, 8 * 2);
|
||||
set => StringConverter.SetString5(value, 8, 8, '\uFFFF').CopyTo(Data, 0x4A);
|
||||
get => StringConverter5.GetString(Data.AsSpan(0x4A, 8 * 2));
|
||||
set => StringConverter5.SetString(Data.AsSpan(0x4A, 8 * 2), value.AsSpan(), 8, StringConverterOption.ClearFF);
|
||||
}
|
||||
|
||||
public int OTGender { get => Data[0x5A]; set => Data[0x5A] = (byte)value; }
|
||||
|
@ -87,14 +88,14 @@ namespace PKHeX.Core
|
|||
// Unused 0x5D 0x5E 0x5F
|
||||
public override string CardTitle
|
||||
{
|
||||
get => StringConverter.GetString5(Data, 0x60, 37 * 2);
|
||||
set => StringConverter.SetString5(value, 37, 37, 0).CopyTo(Data, 0x60);
|
||||
get => StringConverter5.GetString(Data.AsSpan(0x60, 37 * 2));
|
||||
set => StringConverter5.SetString(Data.AsSpan(0x60, 37 * 2), value.AsSpan(), 36, StringConverterOption.ClearZero);
|
||||
}
|
||||
|
||||
// Card Attributes
|
||||
public override int ItemID { get => BitConverter.ToUInt16(Data, 0x00); set => BitConverter.GetBytes((ushort)value).CopyTo(Data, 0x00); }
|
||||
public override int ItemID { get => ReadUInt16LittleEndian(Data.AsSpan(0x00)); set => WriteUInt16LittleEndian(Data.AsSpan(0x00), (ushort)value); }
|
||||
|
||||
private ushort Year { get => BitConverter.ToUInt16(Data, 0xAE); set => BitConverter.GetBytes(value).CopyTo(Data, 0xAE); }
|
||||
private ushort Year { get => ReadUInt16LittleEndian(Data.AsSpan(0xAE)); set => WriteUInt16LittleEndian(Data.AsSpan(0xAE), value); }
|
||||
private byte Month { get => Data[0xAD]; set => Data[0xAD] = value; }
|
||||
private byte Day { get => Data[0xAC]; set => Data[0xAC] = value; }
|
||||
|
||||
|
@ -133,8 +134,8 @@ namespace PKHeX.Core
|
|||
|
||||
public override int CardID
|
||||
{
|
||||
get => BitConverter.ToUInt16(Data, 0xB0);
|
||||
set => BitConverter.GetBytes((ushort)value).CopyTo(Data, 0xB0);
|
||||
get => ReadUInt16LittleEndian(Data.AsSpan(0xB0));
|
||||
set => WriteUInt16LittleEndian(Data.AsSpan(0xB0), (ushort)value);
|
||||
}
|
||||
|
||||
public int CardLocation { get => Data[0xB2]; set => Data[0xB2] = (byte)value; }
|
||||
|
@ -330,11 +331,11 @@ namespace PKHeX.Core
|
|||
|
||||
private void SetIVs(PKM pk)
|
||||
{
|
||||
int[] finalIVs = new int[6];
|
||||
Span<int> finalIVs = stackalloc int[6];
|
||||
var rnd = Util.Rand;
|
||||
for (int i = 0; i < IVs.Length; i++)
|
||||
finalIVs[i] = IVs[i] == 0xFF ? rnd.Next(32) : IVs[i];
|
||||
pk.IVs = finalIVs;
|
||||
pk.SetIVs(finalIVs);
|
||||
}
|
||||
|
||||
public override bool IsMatchExact(PKM pkm, DexLevel evo)
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using static System.Buffers.Binary.BinaryPrimitives;
|
||||
|
||||
namespace PKHeX.Core
|
||||
{
|
||||
|
@ -54,7 +55,7 @@ namespace PKHeX.Core
|
|||
// Unused 0x01
|
||||
public byte Slot { get => Data[2]; set => Data[2] = value; }
|
||||
public byte Detail { get => Data[3]; set => Data[3] = value; }
|
||||
public override int ItemID { get => BitConverter.ToUInt16(Data, 0x4); set => BitConverter.GetBytes((ushort)value).CopyTo(Data, 0x4); }
|
||||
public override int ItemID { get => ReadUInt16LittleEndian(Data.AsSpan(0x4)); set => WriteUInt16LittleEndian(Data.AsSpan(0x4), (ushort)value); }
|
||||
|
||||
public PK4 PK
|
||||
{
|
||||
|
@ -85,7 +86,7 @@ namespace PKHeX.Core
|
|||
/// <returns>True if data was encrypted, false if the data was not modified.</returns>
|
||||
public bool VerifyPKEncryption()
|
||||
{
|
||||
if (!IsPokémon || BitConverter.ToUInt32(Data, 0x64 + 8) != 0)
|
||||
if (!IsPokémon || ReadUInt32LittleEndian(Data.AsSpan(0x64 + 8)) != 0)
|
||||
return false;
|
||||
EncryptPK();
|
||||
return true;
|
||||
|
@ -93,10 +94,9 @@ namespace PKHeX.Core
|
|||
|
||||
private void EncryptPK()
|
||||
{
|
||||
byte[] ekdata = new byte[PokeCrypto.SIZE_4PARTY];
|
||||
Array.Copy(Data, 8, ekdata, 0, ekdata.Length);
|
||||
ekdata = PokeCrypto.EncryptArray45(ekdata);
|
||||
ekdata.CopyTo(Data, 8);
|
||||
var span = Data.AsSpan(8, PokeCrypto.SIZE_4PARTY);
|
||||
var ekdata = PokeCrypto.EncryptArray45(span);
|
||||
ekdata.CopyTo(span);
|
||||
}
|
||||
|
||||
private GiftType PGTGiftType { get => (GiftType)Data[0]; set => Data[0] = (byte)value; }
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using static System.Buffers.Binary.BinaryPrimitives;
|
||||
|
||||
namespace PKHeX.Core
|
||||
{
|
||||
|
@ -34,15 +35,15 @@ namespace PKHeX.Core
|
|||
/// <summary>
|
||||
/// Name of data source
|
||||
/// </summary>
|
||||
public string Origin { get => StringConverter.GetString6(Data, 0x01, 110); set => StringConverter.SetString6(value, 54, 55).CopyTo(Data, 0x01); }
|
||||
public string Origin { get => StringConverter6.GetString(Data.AsSpan(0x01, 110)); set => StringConverter6.SetString(Data.AsSpan(0x01, 110), value.AsSpan(), 54, StringConverterOption.ClearZero); }
|
||||
|
||||
// Pokemon transfer flags?
|
||||
public uint Flags_1 { get => BitConverter.ToUInt32(Data, 0x099); set => BitConverter.GetBytes(value).CopyTo(Data, 0x099); }
|
||||
public uint Flags_2 { get => BitConverter.ToUInt32(Data, 0x141); set => BitConverter.GetBytes(value).CopyTo(Data, 0x141); }
|
||||
public uint Flags_3 { get => BitConverter.ToUInt32(Data, 0x1E9); set => BitConverter.GetBytes(value).CopyTo(Data, 0x1E9); }
|
||||
public uint Flags_4 { get => BitConverter.ToUInt32(Data, 0x291); set => BitConverter.GetBytes(value).CopyTo(Data, 0x291); }
|
||||
public uint Flags_5 { get => BitConverter.ToUInt32(Data, 0x339); set => BitConverter.GetBytes(value).CopyTo(Data, 0x339); }
|
||||
public uint Flags_6 { get => BitConverter.ToUInt32(Data, 0x3E1); set => BitConverter.GetBytes(value).CopyTo(Data, 0x3E1); }
|
||||
public uint Flags_1 { get => ReadUInt32LittleEndian(Data.AsSpan(0x099)); set => WriteUInt32LittleEndian(Data.AsSpan(0x099), value); }
|
||||
public uint Flags_2 { get => ReadUInt32LittleEndian(Data.AsSpan(0x141)); set => WriteUInt32LittleEndian(Data.AsSpan(0x141), value); }
|
||||
public uint Flags_3 { get => ReadUInt32LittleEndian(Data.AsSpan(0x1E9)); set => WriteUInt32LittleEndian(Data.AsSpan(0x1E9), value); }
|
||||
public uint Flags_4 { get => ReadUInt32LittleEndian(Data.AsSpan(0x291)); set => WriteUInt32LittleEndian(Data.AsSpan(0x291), value); }
|
||||
public uint Flags_5 { get => ReadUInt32LittleEndian(Data.AsSpan(0x339)); set => WriteUInt32LittleEndian(Data.AsSpan(0x339), value); }
|
||||
public uint Flags_6 { get => ReadUInt32LittleEndian(Data.AsSpan(0x3E1)); set => WriteUInt32LittleEndian(Data.AsSpan(0x3E1), value); }
|
||||
|
||||
// Pokémon
|
||||
public PL6_PKM Poke_1 { get => new(Data.Slice(0x09D, PL6_PKM.Size)); set => value.Data.CopyTo(Data, 0x09D); }
|
||||
|
@ -53,21 +54,21 @@ namespace PKHeX.Core
|
|||
public PL6_PKM Poke_6 { get => new(Data.Slice(0x3E5, PL6_PKM.Size)); set => value.Data.CopyTo(Data, 0x3E5); }
|
||||
|
||||
// Item Properties
|
||||
public int Item_1 { get => BitConverter.ToUInt16(Data, 0x489); set => BitConverter.GetBytes((ushort)value).CopyTo(Data, 0x489); }
|
||||
public int Quantity_1 { get => BitConverter.ToUInt16(Data, 0x48B); set => BitConverter.GetBytes((ushort)value).CopyTo(Data, 0x48B); }
|
||||
public int Item_2 { get => BitConverter.ToUInt16(Data, 0x48D); set => BitConverter.GetBytes((ushort)value).CopyTo(Data, 0x48D); }
|
||||
public int Quantity_2 { get => BitConverter.ToUInt16(Data, 0x48F); set => BitConverter.GetBytes((ushort)value).CopyTo(Data, 0x48F); }
|
||||
public int Item_3 { get => BitConverter.ToUInt16(Data, 0x491); set => BitConverter.GetBytes((ushort)value).CopyTo(Data, 0x491); }
|
||||
public int Quantity_3 { get => BitConverter.ToUInt16(Data, 0x493); set => BitConverter.GetBytes((ushort)value).CopyTo(Data, 0x493); }
|
||||
public int Item_4 { get => BitConverter.ToUInt16(Data, 0x495); set => BitConverter.GetBytes((ushort)value).CopyTo(Data, 0x495); }
|
||||
public int Quantity_4 { get => BitConverter.ToUInt16(Data, 0x497); set => BitConverter.GetBytes((ushort)value).CopyTo(Data, 0x497); }
|
||||
public int Item_5 { get => BitConverter.ToUInt16(Data, 0x499); set => BitConverter.GetBytes((ushort)value).CopyTo(Data, 0x499); }
|
||||
public int Quantity_5 { get => BitConverter.ToUInt16(Data, 0x49B); set => BitConverter.GetBytes((ushort)value).CopyTo(Data, 0x49B); }
|
||||
public int Item_6 { get => BitConverter.ToUInt16(Data, 0x49D); set => BitConverter.GetBytes((ushort)value).CopyTo(Data, 0x49D); }
|
||||
public int Quantity_6 { get => BitConverter.ToUInt16(Data, 0x49F); set => BitConverter.GetBytes((ushort)value).CopyTo(Data, 0x49F); }
|
||||
public int Item_1 { get => ReadUInt16LittleEndian(Data.AsSpan(0x489)); set => WriteUInt16LittleEndian(Data.AsSpan(0x489), (ushort)value); }
|
||||
public int Quantity_1 { get => ReadUInt16LittleEndian(Data.AsSpan(0x48B)); set => WriteUInt16LittleEndian(Data.AsSpan(0x48B), (ushort)value); }
|
||||
public int Item_2 { get => ReadUInt16LittleEndian(Data.AsSpan(0x48D)); set => WriteUInt16LittleEndian(Data.AsSpan(0x48D), (ushort)value); }
|
||||
public int Quantity_2 { get => ReadUInt16LittleEndian(Data.AsSpan(0x48F)); set => WriteUInt16LittleEndian(Data.AsSpan(0x48F), (ushort)value); }
|
||||
public int Item_3 { get => ReadUInt16LittleEndian(Data.AsSpan(0x491)); set => WriteUInt16LittleEndian(Data.AsSpan(0x491), (ushort)value); }
|
||||
public int Quantity_3 { get => ReadUInt16LittleEndian(Data.AsSpan(0x493)); set => WriteUInt16LittleEndian(Data.AsSpan(0x493), (ushort)value); }
|
||||
public int Item_4 { get => ReadUInt16LittleEndian(Data.AsSpan(0x495)); set => WriteUInt16LittleEndian(Data.AsSpan(0x495), (ushort)value); }
|
||||
public int Quantity_4 { get => ReadUInt16LittleEndian(Data.AsSpan(0x497)); set => WriteUInt16LittleEndian(Data.AsSpan(0x497), (ushort)value); }
|
||||
public int Item_5 { get => ReadUInt16LittleEndian(Data.AsSpan(0x499)); set => WriteUInt16LittleEndian(Data.AsSpan(0x499), (ushort)value); }
|
||||
public int Quantity_5 { get => ReadUInt16LittleEndian(Data.AsSpan(0x49B)); set => WriteUInt16LittleEndian(Data.AsSpan(0x49B), (ushort)value); }
|
||||
public int Item_6 { get => ReadUInt16LittleEndian(Data.AsSpan(0x49D)); set => WriteUInt16LittleEndian(Data.AsSpan(0x49D), (ushort)value); }
|
||||
public int Quantity_6 { get => ReadUInt16LittleEndian(Data.AsSpan(0x49F)); set => WriteUInt16LittleEndian(Data.AsSpan(0x49F), (ushort)value); }
|
||||
|
||||
public int BattlePoints { get => BitConverter.ToUInt16(Data, 0x4A1); set => BitConverter.GetBytes((ushort)value).CopyTo(Data, 0x4A1); }
|
||||
public int Pokemiles { get => BitConverter.ToUInt16(Data, 0x4A3); set => BitConverter.GetBytes((ushort)value).CopyTo(Data, 0x4A3); }
|
||||
public int BattlePoints { get => ReadUInt16LittleEndian(Data.AsSpan(0x4A1)); set => WriteUInt16LittleEndian(Data.AsSpan(0x4A1), (ushort)value); }
|
||||
public int Pokemiles { get => ReadUInt16LittleEndian(Data.AsSpan(0x4A3)); set => WriteUInt16LittleEndian(Data.AsSpan(0x4A3), (ushort)value); }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
|
@ -86,32 +87,32 @@ namespace PKHeX.Core
|
|||
public PL6_PKM() : this(new byte[Size]) { }
|
||||
public PL6_PKM(byte[] data) => Data = data;
|
||||
|
||||
public int TID { get => BitConverter.ToUInt16(Data, 0x00); set => BitConverter.GetBytes((ushort)value).CopyTo(Data, 0x00); }
|
||||
public int SID { get => BitConverter.ToUInt16(Data, 0x02); set => BitConverter.GetBytes((ushort)value).CopyTo(Data, 0x02); }
|
||||
public int TID { get => ReadUInt16LittleEndian(Data.AsSpan(0x00)); set => WriteUInt16LittleEndian(Data.AsSpan(0x00), (ushort)value); }
|
||||
public int SID { get => ReadUInt16LittleEndian(Data.AsSpan(0x02)); set => WriteUInt16LittleEndian(Data.AsSpan(0x02), (ushort)value); }
|
||||
public int OriginGame { get => Data[0x04]; set => Data[0x04] = (byte)value; }
|
||||
public uint EncryptionConstant { get => BitConverter.ToUInt32(Data, 0x08); set => BitConverter.GetBytes(value).CopyTo(Data, 0x08); }
|
||||
public uint EncryptionConstant { get => ReadUInt32LittleEndian(Data.AsSpan(0x08)); set => WriteUInt32LittleEndian(Data.AsSpan(0x08), value); }
|
||||
public int Pokéball { get => Data[0xE]; set => Data[0xE] = (byte)value; }
|
||||
public int HeldItem { get => BitConverter.ToUInt16(Data, 0x10); set => BitConverter.GetBytes((ushort)value).CopyTo(Data, 0x10); }
|
||||
public int Move1 { get => BitConverter.ToUInt16(Data, 0x12); set => BitConverter.GetBytes((ushort)value).CopyTo(Data, 0x12); }
|
||||
public int Move2 { get => BitConverter.ToUInt16(Data, 0x14); set => BitConverter.GetBytes((ushort)value).CopyTo(Data, 0x14); }
|
||||
public int Move3 { get => BitConverter.ToUInt16(Data, 0x16); set => BitConverter.GetBytes((ushort)value).CopyTo(Data, 0x16); }
|
||||
public int Move4 { get => BitConverter.ToUInt16(Data, 0x18); set => BitConverter.GetBytes((ushort)value).CopyTo(Data, 0x18); }
|
||||
public int Species { get => BitConverter.ToUInt16(Data, 0x1A); set => BitConverter.GetBytes((ushort)value).CopyTo(Data, 0x1A); }
|
||||
public int HeldItem { get => ReadUInt16LittleEndian(Data.AsSpan(0x10)); set => WriteUInt16LittleEndian(Data.AsSpan(0x10), (ushort)value); }
|
||||
public int Move1 { get => ReadUInt16LittleEndian(Data.AsSpan(0x12)); set => WriteUInt16LittleEndian(Data.AsSpan(0x12), (ushort)value); }
|
||||
public int Move2 { get => ReadUInt16LittleEndian(Data.AsSpan(0x14)); set => WriteUInt16LittleEndian(Data.AsSpan(0x14), (ushort)value); }
|
||||
public int Move3 { get => ReadUInt16LittleEndian(Data.AsSpan(0x16)); set => WriteUInt16LittleEndian(Data.AsSpan(0x16), (ushort)value); }
|
||||
public int Move4 { get => ReadUInt16LittleEndian(Data.AsSpan(0x18)); set => WriteUInt16LittleEndian(Data.AsSpan(0x18), (ushort)value); }
|
||||
public int Species { get => ReadUInt16LittleEndian(Data.AsSpan(0x1A)); set => WriteUInt16LittleEndian(Data.AsSpan(0x1A), (ushort)value); }
|
||||
public int Form { get => Data[0x1C]; set => Data[0x1C] = (byte)value; }
|
||||
public int Language { get => Data[0x1D]; set => Data[0x1D] = (byte)value; }
|
||||
|
||||
public string Nickname
|
||||
{
|
||||
get => StringConverter.GetString6(Data, 0x1E, 0x1A);
|
||||
set => StringConverter.SetString6(value, 12, 13).CopyTo(Data, 0x1E);
|
||||
get => StringConverter6.GetString(Data.AsSpan(0x1E, 0x1A));
|
||||
set => StringConverter6.SetString(Data.AsSpan(0x1E, 0x1A), value.AsSpan(), 12, StringConverterOption.ClearZero);
|
||||
}
|
||||
|
||||
public int Nature { get => Data[0x38]; set => Data[0x38] = (byte)value; }
|
||||
public int Gender { get => Data[0x39]; set => Data[0x39] = (byte)value; }
|
||||
public int AbilityType { get => Data[0x3A]; set => Data[0x3A] = (byte)value; }
|
||||
public int PIDType { get => Data[0x3B]; set => Data[0x3B] = (byte)value; }
|
||||
public int EggLocation { get => BitConverter.ToUInt16(Data, 0x3C); set => BitConverter.GetBytes((ushort)value).CopyTo(Data, 0x3C); }
|
||||
public int MetLocation { get => BitConverter.ToUInt16(Data, 0x3E); set => BitConverter.GetBytes((ushort)value).CopyTo(Data, 0x3F); }
|
||||
public int EggLocation { get => ReadUInt16LittleEndian(Data.AsSpan(0x3C)); set => WriteUInt16LittleEndian(Data.AsSpan(0x3C), (ushort)value); }
|
||||
public int MetLocation { get => ReadUInt16LittleEndian(Data.AsSpan(0x3E)); set => WriteUInt16LittleEndian(Data.AsSpan(0x3E), (ushort)value); }
|
||||
public int MetLevel { get => Data[0x40]; set => Data[0x40] = (byte)value; }
|
||||
|
||||
public int CNT_Cool { get => Data[0x41]; set => Data[0x41] = (byte)value; }
|
||||
|
@ -132,20 +133,20 @@ namespace PKHeX.Core
|
|||
|
||||
public string OT
|
||||
{
|
||||
get => StringConverter.GetString6(Data, 0x4E, 0x1A);
|
||||
set => StringConverter.SetString6(value, 12, 13).CopyTo(Data, 0x4E);
|
||||
get => StringConverter6.GetString(Data.AsSpan(0x4E, 0x1A));
|
||||
set => StringConverter6.SetString(Data.AsSpan(0x4E, 0x1A), value.AsSpan(), 12, StringConverterOption.ClearZero);
|
||||
}
|
||||
|
||||
public int Level { get => Data[0x68]; set => Data[0x68] = (byte)value; }
|
||||
public bool IsEgg { get => Data[0x69] == 1; set => Data[0x69] = value ? (byte)1 : (byte)0; }
|
||||
public uint PID { get => BitConverter.ToUInt32(Data, 0x6C); set => BitConverter.GetBytes(value).CopyTo(Data, 0x6C); }
|
||||
public int RelearnMove1 { get => BitConverter.ToUInt16(Data, 0x70); set => BitConverter.GetBytes((ushort)value).CopyTo(Data, 0x70); }
|
||||
public int RelearnMove2 { get => BitConverter.ToUInt16(Data, 0x72); set => BitConverter.GetBytes((ushort)value).CopyTo(Data, 0x72); }
|
||||
public int RelearnMove3 { get => BitConverter.ToUInt16(Data, 0x74); set => BitConverter.GetBytes((ushort)value).CopyTo(Data, 0x74); }
|
||||
public int RelearnMove4 { get => BitConverter.ToUInt16(Data, 0x76); set => BitConverter.GetBytes((ushort)value).CopyTo(Data, 0x76); }
|
||||
public uint PID { get => ReadUInt32LittleEndian(Data.AsSpan(0x6C)); set => WriteUInt32LittleEndian(Data.AsSpan(0x6C), value); }
|
||||
public int RelearnMove1 { get => ReadUInt16LittleEndian(Data.AsSpan(0x70)); set => WriteUInt16LittleEndian(Data.AsSpan(0x70), (ushort)value); }
|
||||
public int RelearnMove2 { get => ReadUInt16LittleEndian(Data.AsSpan(0x72)); set => WriteUInt16LittleEndian(Data.AsSpan(0x72), (ushort)value); }
|
||||
public int RelearnMove3 { get => ReadUInt16LittleEndian(Data.AsSpan(0x74)); set => WriteUInt16LittleEndian(Data.AsSpan(0x74), (ushort)value); }
|
||||
public int RelearnMove4 { get => ReadUInt16LittleEndian(Data.AsSpan(0x76)); set => WriteUInt16LittleEndian(Data.AsSpan(0x76), (ushort)value); }
|
||||
public int OT_Intensity { get => Data[0x78]; set => Data[0x78] = (byte)value; }
|
||||
public int OT_Memory { get => Data[0x79]; set => Data[0x79] = (byte)value; }
|
||||
public int OT_TextVar { get => BitConverter.ToUInt16(Data, 0x7A); set => BitConverter.GetBytes((ushort)value).CopyTo(Data, 0x7A); }
|
||||
public int OT_TextVar { get => ReadUInt16LittleEndian(Data.AsSpan(0x7A)); set => WriteUInt16LittleEndian(Data.AsSpan(0x7A), (ushort)value); }
|
||||
public int OT_Feeling { get => Data[0x7C]; set => Data[0x7C] = (byte)value; }
|
||||
|
||||
private byte RIB0 { get => Data[0x0C]; set => Data[0x0C] = value; }
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using static System.Buffers.Binary. BinaryPrimitives;
|
||||
|
||||
namespace PKHeX.Core
|
||||
{
|
||||
|
@ -36,21 +36,21 @@ namespace PKHeX.Core
|
|||
// General Card Properties
|
||||
public override int CardID
|
||||
{
|
||||
get => BitConverter.ToUInt16(Data, CardStart + 0);
|
||||
set => BitConverter.GetBytes((ushort)value).CopyTo(Data, CardStart + 0);
|
||||
get => ReadUInt16LittleEndian(Data.AsSpan(CardStart + 0));
|
||||
set => WriteUInt16LittleEndian(Data.AsSpan(CardStart + 0), (ushort)value);
|
||||
}
|
||||
|
||||
public override string CardTitle
|
||||
{
|
||||
// Max len 36 char, followed by null terminator
|
||||
get => StringConverter.GetString7b(Data, CardStart + 2, 0x4A);
|
||||
set => StringConverter.SetString7b(value, 36, 37).CopyTo(Data, CardStart + 2);
|
||||
get => StringConverter8.GetString(Data.AsSpan(CardStart + 2, 0x4A));
|
||||
set => StringConverter8.SetString(Data.AsSpan(CardStart + 2, 0x4A), value.AsSpan(), 36, StringConverterOption.ClearZero);
|
||||
}
|
||||
|
||||
private uint RawDate
|
||||
{
|
||||
get => BitConverter.ToUInt32(Data, CardStart + 0x4C);
|
||||
set => BitConverter.GetBytes(value).CopyTo(Data, CardStart + 0x4C);
|
||||
get => ReadUInt32LittleEndian(Data.AsSpan(CardStart + 0x4C));
|
||||
set => WriteUInt32LittleEndian(Data.AsSpan(CardStart + 0x4C), value);
|
||||
}
|
||||
|
||||
private uint Year
|
||||
|
@ -119,16 +119,16 @@ namespace PKHeX.Core
|
|||
|
||||
// Item Properties
|
||||
public override bool IsItem { get => CardType == 1; set { if (value) CardType = 1; } }
|
||||
public override int ItemID { get => BitConverter.ToUInt16(Data, CardStart + 0x68); set => BitConverter.GetBytes((ushort)value).CopyTo(Data, CardStart + 0x68); }
|
||||
public int GetItem(int index) => BitConverter.ToUInt16(Data, CardStart + 0x68 + (0x4 * index));
|
||||
public void SetItem(int index, ushort item) => BitConverter.GetBytes(item).CopyTo(Data, CardStart + 0x68 + (4 * index));
|
||||
public int GetQuantity(int index) => BitConverter.ToUInt16(Data, CardStart + 0x6A + (0x4 * index));
|
||||
public void SetQuantity(int index, ushort quantity) => BitConverter.GetBytes(quantity).CopyTo(Data, CardStart + 0x6A + (4 * index));
|
||||
public override int ItemID { get => ReadUInt16LittleEndian(Data.AsSpan(CardStart + 0x68)); set => WriteUInt16LittleEndian(Data.AsSpan(CardStart + 0x68), (ushort)value); }
|
||||
public int GetItem(int index) => ReadUInt16LittleEndian(Data.AsSpan(CardStart + 0x68 + (0x4 * index)));
|
||||
public void SetItem(int index, ushort item) => WriteUInt16LittleEndian(Data.AsSpan(CardStart + 0x68 + (4 * index)), item);
|
||||
public int GetQuantity(int index) => ReadUInt16LittleEndian(Data.AsSpan(CardStart + 0x6A + (0x4 * index)));
|
||||
public void SetQuantity(int index, ushort quantity) => WriteUInt16LittleEndian(Data.AsSpan(CardStart + 0x6A + (4 * index)), quantity);
|
||||
|
||||
public override int Quantity
|
||||
{
|
||||
get => BitConverter.ToUInt16(Data, CardStart + 0x6A);
|
||||
set => BitConverter.GetBytes((ushort)value).CopyTo(Data, CardStart + 0x6A);
|
||||
get => ReadUInt16LittleEndian(Data.AsSpan(CardStart + 0x6A));
|
||||
set => WriteUInt16LittleEndian(Data.AsSpan(CardStart + 0x6A), (ushort)value);
|
||||
}
|
||||
|
||||
// Pokémon Properties
|
||||
|
@ -137,24 +137,24 @@ namespace PKHeX.Core
|
|||
|
||||
public override int TID
|
||||
{
|
||||
get => BitConverter.ToUInt16(Data, CardStart + 0x68);
|
||||
set => BitConverter.GetBytes((ushort)value).CopyTo(Data, CardStart + 0x68);
|
||||
get => ReadUInt16LittleEndian(Data.AsSpan(CardStart + 0x68));
|
||||
set => WriteUInt16LittleEndian(Data.AsSpan(CardStart + 0x68), (ushort)value);
|
||||
}
|
||||
|
||||
public override int SID {
|
||||
get => BitConverter.ToUInt16(Data, CardStart + 0x6A);
|
||||
set => BitConverter.GetBytes((ushort)value).CopyTo(Data, CardStart + 0x6A);
|
||||
get => ReadUInt16LittleEndian(Data.AsSpan(CardStart + 0x6A));
|
||||
set => WriteUInt16LittleEndian(Data.AsSpan(CardStart + 0x6A), (ushort)value);
|
||||
}
|
||||
|
||||
public int OriginGame
|
||||
{
|
||||
get => BitConverter.ToInt32(Data, CardStart + 0x6C);
|
||||
set => BitConverter.GetBytes(value).CopyTo(Data, CardStart + 0x6C);
|
||||
get => ReadInt32LittleEndian(Data.AsSpan(CardStart + 0x6C));
|
||||
set => WriteInt32LittleEndian(Data.AsSpan(CardStart + 0x6C), value);
|
||||
}
|
||||
|
||||
public uint EncryptionConstant {
|
||||
get => BitConverter.ToUInt32(Data, CardStart + 0x70);
|
||||
set => BitConverter.GetBytes(value).CopyTo(Data, CardStart + 0x70);
|
||||
get => ReadUInt32LittleEndian(Data.AsSpan(CardStart + 0x70));
|
||||
set => WriteUInt32LittleEndian(Data.AsSpan(CardStart + 0x70), value);
|
||||
}
|
||||
|
||||
public override int Ball
|
||||
|
@ -164,15 +164,15 @@ namespace PKHeX.Core
|
|||
|
||||
public override int HeldItem // no references
|
||||
{
|
||||
get => BitConverter.ToUInt16(Data, CardStart + 0x78);
|
||||
set => BitConverter.GetBytes((ushort)value).CopyTo(Data, CardStart + 0x78);
|
||||
get => ReadUInt16LittleEndian(Data.AsSpan(CardStart + 0x78));
|
||||
set => WriteUInt16LittleEndian(Data.AsSpan(CardStart + 0x78), (ushort)value);
|
||||
}
|
||||
|
||||
public int Move1 { get => BitConverter.ToUInt16(Data, CardStart + 0x7A); set => BitConverter.GetBytes((ushort)value).CopyTo(Data, CardStart + 0x7A); }
|
||||
public int Move2 { get => BitConverter.ToUInt16(Data, CardStart + 0x7C); set => BitConverter.GetBytes((ushort)value).CopyTo(Data, CardStart + 0x7C); }
|
||||
public int Move3 { get => BitConverter.ToUInt16(Data, CardStart + 0x7E); set => BitConverter.GetBytes((ushort)value).CopyTo(Data, CardStart + 0x7E); }
|
||||
public int Move4 { get => BitConverter.ToUInt16(Data, CardStart + 0x80); set => BitConverter.GetBytes((ushort)value).CopyTo(Data, CardStart + 0x80); }
|
||||
public override int Species { get => BitConverter.ToUInt16(Data, CardStart + 0x82); set => BitConverter.GetBytes((ushort)value).CopyTo(Data, CardStart + 0x82); }
|
||||
public int Move1 { get => ReadUInt16LittleEndian(Data.AsSpan(CardStart + 0x7A)); set => WriteUInt16LittleEndian(Data.AsSpan(CardStart + 0x7A), (ushort)value); }
|
||||
public int Move2 { get => ReadUInt16LittleEndian(Data.AsSpan(CardStart + 0x7C)); set => WriteUInt16LittleEndian(Data.AsSpan(CardStart + 0x7C), (ushort)value); }
|
||||
public int Move3 { get => ReadUInt16LittleEndian(Data.AsSpan(CardStart + 0x7E)); set => WriteUInt16LittleEndian(Data.AsSpan(CardStart + 0x7E), (ushort)value); }
|
||||
public int Move4 { get => ReadUInt16LittleEndian(Data.AsSpan(CardStart + 0x80)); set => WriteUInt16LittleEndian(Data.AsSpan(CardStart + 0x80), (ushort)value); }
|
||||
public override int Species { get => ReadUInt16LittleEndian(Data.AsSpan(CardStart + 0x82)); set => WriteUInt16LittleEndian(Data.AsSpan(CardStart + 0x82), (ushort)value); }
|
||||
public override int Form { get => Data[CardStart + 0x84]; set => Data[CardStart + 0x84] = (byte)value; }
|
||||
|
||||
// public int Language { get => Data[CardStart + 0x85]; set => Data[CardStart + 0x85] = (byte)value; }
|
||||
|
@ -187,8 +187,8 @@ namespace PKHeX.Core
|
|||
public override int Gender { get => Data[CardStart + 0xA1]; set => Data[CardStart + 0xA1] = (byte)value; }
|
||||
public override int AbilityType { get => 3; set => Data[CardStart + 0xA2] = (byte)value; } // no references, always ability 0/1
|
||||
public Shiny PIDType { get => (Shiny)Data[CardStart + 0xA3]; set => Data[CardStart + 0xA3] = (byte)value; }
|
||||
public override int EggLocation { get => BitConverter.ToUInt16(Data, CardStart + 0xA4); set => BitConverter.GetBytes((ushort)value).CopyTo(Data, CardStart + 0xA4); }
|
||||
public int MetLocation { get => BitConverter.ToUInt16(Data, CardStart + 0xA6); set => BitConverter.GetBytes((ushort)value).CopyTo(Data, CardStart + 0xA6); }
|
||||
public override int EggLocation { get => ReadUInt16LittleEndian(Data.AsSpan(CardStart + 0xA4)); set => WriteUInt16LittleEndian(Data.AsSpan(CardStart + 0xA4), (ushort)value); }
|
||||
public int MetLocation { get => ReadUInt16LittleEndian(Data.AsSpan(CardStart + 0xA6)); set => WriteUInt16LittleEndian(Data.AsSpan(CardStart + 0xA6), (ushort)value); }
|
||||
public int MetLevel { get => Data[CardStart + 0xA8]; set => Data[CardStart + 0xA8] = (byte)value; }
|
||||
|
||||
public int IV_HP { get => Data[CardStart + 0xAF]; set => Data[CardStart + 0xAF] = (byte)value; }
|
||||
|
@ -208,13 +208,13 @@ namespace PKHeX.Core
|
|||
|
||||
public override int Level { get => Data[CardStart + 0xD0]; set => Data[CardStart + 0xD0] = (byte)value; }
|
||||
public override bool IsEgg { get => Data[CardStart + 0xD1] == 1; set => Data[CardStart + 0xD1] = value ? (byte)1 : (byte)0; }
|
||||
public ushort AdditionalItem { get => BitConverter.ToUInt16(Data, CardStart + 0xD2); set => BitConverter.GetBytes(value).CopyTo(Data, CardStart + 0xD2); }
|
||||
public ushort AdditionalItem { get => ReadUInt16LittleEndian(Data.AsSpan(CardStart + 0xD2)); set => WriteUInt16LittleEndian(Data.AsSpan(CardStart + 0xD2), value); }
|
||||
|
||||
public uint PID { get => BitConverter.ToUInt32(Data, 0xD4); set => BitConverter.GetBytes(value).CopyTo(Data, 0xD4); }
|
||||
public int RelearnMove1 { get => BitConverter.ToUInt16(Data, CardStart + 0xD8); set => BitConverter.GetBytes((ushort)value).CopyTo(Data, CardStart + 0xD8); }
|
||||
public int RelearnMove2 { get => BitConverter.ToUInt16(Data, CardStart + 0xDA); set => BitConverter.GetBytes((ushort)value).CopyTo(Data, CardStart + 0xDA); }
|
||||
public int RelearnMove3 { get => BitConverter.ToUInt16(Data, CardStart + 0xDC); set => BitConverter.GetBytes((ushort)value).CopyTo(Data, CardStart + 0xDC); }
|
||||
public int RelearnMove4 { get => BitConverter.ToUInt16(Data, CardStart + 0xDE); set => BitConverter.GetBytes((ushort)value).CopyTo(Data, CardStart + 0xDE); }
|
||||
public uint PID { get => ReadUInt32LittleEndian(Data.AsSpan(0xD4)); set => WriteUInt32LittleEndian(Data.AsSpan(0xD4), value); }
|
||||
public int RelearnMove1 { get => ReadUInt16LittleEndian(Data.AsSpan(CardStart + 0xD8)); set => WriteUInt16LittleEndian(Data.AsSpan(CardStart + 0xD8), (ushort)value); }
|
||||
public int RelearnMove2 { get => ReadUInt16LittleEndian(Data.AsSpan(CardStart + 0xDA)); set => WriteUInt16LittleEndian(Data.AsSpan(CardStart + 0xDA), (ushort)value); }
|
||||
public int RelearnMove3 { get => ReadUInt16LittleEndian(Data.AsSpan(CardStart + 0xDC)); set => WriteUInt16LittleEndian(Data.AsSpan(CardStart + 0xDC), (ushort)value); }
|
||||
public int RelearnMove4 { get => ReadUInt16LittleEndian(Data.AsSpan(CardStart + 0xDE)); set => WriteUInt16LittleEndian(Data.AsSpan(CardStart + 0xDE), (ushort)value); }
|
||||
|
||||
public int AV_HP { get => Data[CardStart + 0xE5]; set => Data[CardStart + 0xE5] = (byte)value; }
|
||||
public int AV_ATK { get => Data[CardStart + 0xE6]; set => Data[CardStart + 0xE6] = (byte)value; }
|
||||
|
@ -289,11 +289,11 @@ namespace PKHeX.Core
|
|||
return redeemLanguage;
|
||||
}
|
||||
|
||||
public string GetNickname(int language) => StringConverter.GetString7b(Data, GetNicknameOffset(language), 0x1A);
|
||||
public void SetNickname(int language, string value) => StringConverter.SetString7b(value, 12, 13).CopyTo(Data, GetNicknameOffset(language));
|
||||
public string GetNickname(int language) => StringConverter8.GetString(Data.AsSpan(GetNicknameOffset(language), 0x1A));
|
||||
public void SetNickname(int language, string value) => StringConverter8.SetString(Data.AsSpan(GetNicknameOffset(language), 0x1A), value.AsSpan(), 12, StringConverterOption.ClearZero);
|
||||
|
||||
public string GetOT(int language) => StringConverter.GetString7b(Data, GetOTOffset(language), 0x1A);
|
||||
public void SetOT(int language, string value) => StringConverter.SetString7b(value, 12, 13).CopyTo(Data, GetOTOffset(language));
|
||||
public string GetOT(int language) => StringConverter8.GetString(Data.AsSpan(GetOTOffset(language), 0x1A));
|
||||
public void SetOT(int language, string value) => StringConverter8.SetString(Data.AsSpan(GetOTOffset(language), 0x1A), value.AsSpan(), 12, StringConverterOption.ClearZero);
|
||||
|
||||
private static int GetNicknameOffset(int language)
|
||||
{
|
||||
|
@ -459,7 +459,7 @@ namespace PKHeX.Core
|
|||
|
||||
private void SetIVs(PKM pk)
|
||||
{
|
||||
int[] finalIVs = new int[6];
|
||||
Span<int> finalIVs = stackalloc int[6];
|
||||
var ivflag = Array.Find(IVs, iv => (byte)(iv - 0xFC) < 3);
|
||||
var rng = Util.Rand;
|
||||
if (ivflag == 0) // Random IVs
|
||||
|
@ -471,11 +471,11 @@ namespace PKHeX.Core
|
|||
{
|
||||
int IVCount = ivflag - 0xFB;
|
||||
do { finalIVs[rng.Next(6)] = 31; }
|
||||
while (finalIVs.Count(iv => iv == 31) < IVCount);
|
||||
while (finalIVs.Count(31) < IVCount);
|
||||
for (int i = 0; i < 6; i++)
|
||||
finalIVs[i] = finalIVs[i] == 31 ? 31 : rng.Next(32);
|
||||
}
|
||||
pk.IVs = finalIVs;
|
||||
pk.SetIVs(finalIVs);
|
||||
}
|
||||
|
||||
public bool CanHaveLanguage(int language)
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using static PKHeX.Core.RibbonIndex;
|
||||
using static System.Buffers.Binary.BinaryPrimitives;
|
||||
|
||||
namespace PKHeX.Core
|
||||
{
|
||||
|
@ -40,8 +40,8 @@ namespace PKHeX.Core
|
|||
|
||||
public override int CardID
|
||||
{
|
||||
get => BitConverter.ToUInt16(Data, CardStart + 0x8);
|
||||
set => BitConverter.GetBytes((ushort)value).CopyTo(Data, CardStart + 0x8);
|
||||
get => ReadUInt16LittleEndian(Data.AsSpan(CardStart + 0x8));
|
||||
set => WriteUInt16LittleEndian(Data.AsSpan(CardStart + 0x8), (ushort)value);
|
||||
}
|
||||
|
||||
public byte CardFlags { get => Data[CardStart + 0x10]; set => Data[CardStart + 0x10] = value; }
|
||||
|
@ -77,10 +77,10 @@ namespace PKHeX.Core
|
|||
set => SetQuantity(0, (ushort)value);
|
||||
}
|
||||
|
||||
public int GetItem(int index) => BitConverter.ToUInt16(Data, CardStart + 0x20 + (0x10 * index));
|
||||
public void SetItem(int index, ushort item) => BitConverter.GetBytes(item).CopyTo(Data, CardStart + 0x20 + (0x10 * index));
|
||||
public int GetQuantity(int index) => BitConverter.ToUInt16(Data, CardStart + 0x22 + (0x10 * index));
|
||||
public void SetQuantity(int index, ushort quantity) => BitConverter.GetBytes(quantity).CopyTo(Data, CardStart + 0x22 + (0x10 * index));
|
||||
public int GetItem(int index) => ReadUInt16LittleEndian(Data.AsSpan(CardStart + 0x20 + (0x10 * index)));
|
||||
public void SetItem(int index, ushort item) => WriteUInt16LittleEndian(Data.AsSpan(CardStart + 0x20 + (0x10 * index)), item);
|
||||
public int GetQuantity(int index) => ReadUInt16LittleEndian(Data.AsSpan(CardStart + 0x22 + (0x10 * index)));
|
||||
public void SetQuantity(int index, ushort quantity) => WriteUInt16LittleEndian(Data.AsSpan(CardStart + 0x22 + (0x10 * index)), quantity);
|
||||
|
||||
// Pokémon Properties
|
||||
public override bool IsPokémon { get => CardType == GiftType.Pokemon; set { if (value) CardType = GiftType.Pokemon; } }
|
||||
|
@ -108,59 +108,59 @@ namespace PKHeX.Core
|
|||
|
||||
public override int TID
|
||||
{
|
||||
get => BitConverter.ToUInt16(Data, CardStart + 0x20);
|
||||
set => BitConverter.GetBytes((ushort)value).CopyTo(Data, CardStart + 0x20);
|
||||
get => ReadUInt16LittleEndian(Data.AsSpan(CardStart + 0x20));
|
||||
set => WriteUInt16LittleEndian(Data.AsSpan(CardStart + 0x20), (ushort)value);
|
||||
}
|
||||
|
||||
public override int SID {
|
||||
get => BitConverter.ToUInt16(Data, CardStart + 0x22);
|
||||
set => BitConverter.GetBytes((ushort)value).CopyTo(Data, CardStart + 0x22);
|
||||
get => ReadUInt16LittleEndian(Data.AsSpan(CardStart + 0x22));
|
||||
set => WriteUInt16LittleEndian(Data.AsSpan(CardStart + 0x22), (ushort)value);
|
||||
}
|
||||
|
||||
public int OriginGame
|
||||
{
|
||||
get => BitConverter.ToInt32(Data, CardStart + 0x24);
|
||||
set => BitConverter.GetBytes(value).CopyTo(Data, CardStart + 0x24);
|
||||
get => ReadInt32LittleEndian(Data.AsSpan(CardStart + 0x24));
|
||||
set => WriteInt32LittleEndian(Data.AsSpan(CardStart + 0x24), value);
|
||||
}
|
||||
|
||||
public uint EncryptionConstant
|
||||
{
|
||||
get => BitConverter.ToUInt32(Data, CardStart + 0x28);
|
||||
set => BitConverter.GetBytes(value).CopyTo(Data, CardStart + 0x28);
|
||||
get => ReadUInt32LittleEndian(Data.AsSpan(CardStart + 0x28));
|
||||
set => WriteUInt32LittleEndian(Data.AsSpan(CardStart + 0x28), value);
|
||||
}
|
||||
|
||||
public uint PID
|
||||
{
|
||||
get => BitConverter.ToUInt32(Data, CardStart + 0x2C);
|
||||
set => BitConverter.GetBytes(value).CopyTo(Data, CardStart + 0x2C);
|
||||
get => ReadUInt32LittleEndian(Data.AsSpan(CardStart + 0x2C));
|
||||
set => WriteUInt32LittleEndian(Data.AsSpan(CardStart + 0x2C), value);
|
||||
}
|
||||
|
||||
// Nicknames, OT Names 0x30 - 0x270
|
||||
public override int EggLocation { get => BitConverter.ToUInt16(Data, CardStart + 0x270); set => BitConverter.GetBytes((ushort)value).CopyTo(Data, CardStart + 0x270); }
|
||||
public int MetLocation { get => BitConverter.ToUInt16(Data, CardStart + 0x272); set => BitConverter.GetBytes((ushort)value).CopyTo(Data, CardStart + 0x272); }
|
||||
public override int EggLocation { get => ReadUInt16LittleEndian(Data.AsSpan(CardStart + 0x270)); set => WriteUInt16LittleEndian(Data.AsSpan(CardStart + 0x270), (ushort)value); }
|
||||
public int MetLocation { get => ReadUInt16LittleEndian(Data.AsSpan(CardStart + 0x272)); set => WriteUInt16LittleEndian(Data.AsSpan(CardStart + 0x272), (ushort)value); }
|
||||
|
||||
public override int Ball
|
||||
{
|
||||
get => BitConverter.ToUInt16(Data, CardStart + 0x274);
|
||||
set => BitConverter.GetBytes((ushort)value).CopyTo(Data, CardStart + 0x274);
|
||||
get => ReadUInt16LittleEndian(Data.AsSpan(CardStart + 0x274));
|
||||
set => WriteUInt16LittleEndian(Data.AsSpan(CardStart + 0x274), (ushort)value);
|
||||
}
|
||||
|
||||
public override int HeldItem
|
||||
{
|
||||
get => BitConverter.ToUInt16(Data, CardStart + 0x276);
|
||||
set => BitConverter.GetBytes((ushort)value).CopyTo(Data, CardStart + 0x276);
|
||||
get => ReadUInt16LittleEndian(Data.AsSpan(CardStart + 0x276));
|
||||
set => WriteUInt16LittleEndian(Data.AsSpan(CardStart + 0x276), (ushort)value);
|
||||
}
|
||||
|
||||
public int Move1 { get => BitConverter.ToUInt16(Data, CardStart + 0x278); set => BitConverter.GetBytes((ushort)value).CopyTo(Data, CardStart + 0x278); }
|
||||
public int Move2 { get => BitConverter.ToUInt16(Data, CardStart + 0x27A); set => BitConverter.GetBytes((ushort)value).CopyTo(Data, CardStart + 0x27A); }
|
||||
public int Move3 { get => BitConverter.ToUInt16(Data, CardStart + 0x27C); set => BitConverter.GetBytes((ushort)value).CopyTo(Data, CardStart + 0x27C); }
|
||||
public int Move4 { get => BitConverter.ToUInt16(Data, CardStart + 0x27E); set => BitConverter.GetBytes((ushort)value).CopyTo(Data, CardStart + 0x27E); }
|
||||
public int RelearnMove1 { get => BitConverter.ToUInt16(Data, CardStart + 0x280); set => BitConverter.GetBytes((ushort)value).CopyTo(Data, CardStart + 0x280); }
|
||||
public int RelearnMove2 { get => BitConverter.ToUInt16(Data, CardStart + 0x282); set => BitConverter.GetBytes((ushort)value).CopyTo(Data, CardStart + 0x282); }
|
||||
public int RelearnMove3 { get => BitConverter.ToUInt16(Data, CardStart + 0x284); set => BitConverter.GetBytes((ushort)value).CopyTo(Data, CardStart + 0x284); }
|
||||
public int RelearnMove4 { get => BitConverter.ToUInt16(Data, CardStart + 0x286); set => BitConverter.GetBytes((ushort)value).CopyTo(Data, CardStart + 0x286); }
|
||||
public int Move1 { get => ReadUInt16LittleEndian(Data.AsSpan(CardStart + 0x278)); set => WriteUInt16LittleEndian(Data.AsSpan(CardStart + 0x278), (ushort)value); }
|
||||
public int Move2 { get => ReadUInt16LittleEndian(Data.AsSpan(CardStart + 0x27A)); set => WriteUInt16LittleEndian(Data.AsSpan(CardStart + 0x27A), (ushort)value); }
|
||||
public int Move3 { get => ReadUInt16LittleEndian(Data.AsSpan(CardStart + 0x27C)); set => WriteUInt16LittleEndian(Data.AsSpan(CardStart + 0x27C), (ushort)value); }
|
||||
public int Move4 { get => ReadUInt16LittleEndian(Data.AsSpan(CardStart + 0x27E)); set => WriteUInt16LittleEndian(Data.AsSpan(CardStart + 0x27E), (ushort)value); }
|
||||
public int RelearnMove1 { get => ReadUInt16LittleEndian(Data.AsSpan(CardStart + 0x280)); set => WriteUInt16LittleEndian(Data.AsSpan(CardStart + 0x280), (ushort)value); }
|
||||
public int RelearnMove2 { get => ReadUInt16LittleEndian(Data.AsSpan(CardStart + 0x282)); set => WriteUInt16LittleEndian(Data.AsSpan(CardStart + 0x282), (ushort)value); }
|
||||
public int RelearnMove3 { get => ReadUInt16LittleEndian(Data.AsSpan(CardStart + 0x284)); set => WriteUInt16LittleEndian(Data.AsSpan(CardStart + 0x284), (ushort)value); }
|
||||
public int RelearnMove4 { get => ReadUInt16LittleEndian(Data.AsSpan(CardStart + 0x286)); set => WriteUInt16LittleEndian(Data.AsSpan(CardStart + 0x286), (ushort)value); }
|
||||
|
||||
public override int Species { get => BitConverter.ToUInt16(Data, CardStart + 0x288); set => BitConverter.GetBytes((ushort)value).CopyTo(Data, CardStart + 0x288); }
|
||||
public override int Species { get => ReadUInt16LittleEndian(Data.AsSpan(CardStart + 0x288)); set => WriteUInt16LittleEndian(Data.AsSpan(CardStart + 0x288), (ushort)value); }
|
||||
public override int Form { get => Data[CardStart + 0x28A]; set => Data[CardStart + 0x28A] = (byte)value; }
|
||||
public override int Gender { get => Data[CardStart + 0x28B]; set => Data[CardStart + 0x28B] = (byte)value; }
|
||||
public override int Level { get => Data[CardStart + 0x28C]; set => Data[CardStart + 0x28C] = (byte)value; }
|
||||
|
@ -191,10 +191,10 @@ namespace PKHeX.Core
|
|||
{
|
||||
for (int i = 0; i < RibbonBytesCount; i++)
|
||||
{
|
||||
var val = Data[RibbonBytesOffset + i];
|
||||
if (val == RibbonByteNone)
|
||||
var value = Data[RibbonBytesOffset + i];
|
||||
if (value == RibbonByteNone)
|
||||
return false;
|
||||
if ((RibbonIndex)val is >= MarkLunchtime and <= MarkSlump)
|
||||
if ((RibbonIndex)value is >= MarkLunchtime and <= MarkSlump)
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
|
@ -260,14 +260,14 @@ namespace PKHeX.Core
|
|||
}
|
||||
}
|
||||
|
||||
public bool GetIsNicknamed(int language) => BitConverter.ToUInt16(Data, GetNicknameOffset(language)) != 0;
|
||||
public bool GetIsNicknamed(int language) => ReadUInt16LittleEndian(Data.AsSpan(GetNicknameOffset(language))) != 0;
|
||||
|
||||
public bool CanBeAnyLanguage()
|
||||
{
|
||||
for (int i = 0; i < 9; i++)
|
||||
{
|
||||
var ofs = GetLanguageOffset(i);
|
||||
var lang = BitConverter.ToInt16(Data, ofs);
|
||||
var lang = ReadInt16LittleEndian(Data.AsSpan(ofs));
|
||||
if (lang != 0)
|
||||
return false;
|
||||
}
|
||||
|
@ -285,7 +285,7 @@ namespace PKHeX.Core
|
|||
for (int i = 0; i < 9; i++)
|
||||
{
|
||||
var ofs = GetLanguageOffset(i);
|
||||
var lang = BitConverter.ToInt16(Data, ofs);
|
||||
var lang = ReadInt16LittleEndian(Data.AsSpan(ofs));
|
||||
if (lang == language)
|
||||
return true;
|
||||
}
|
||||
|
@ -295,7 +295,7 @@ namespace PKHeX.Core
|
|||
public int GetLanguage(int redeemLanguage) => Data[GetLanguageOffset(GetLanguageIndex(redeemLanguage))];
|
||||
private static int GetLanguageOffset(int index) => 0x30 + (index * 0x20) + 0x1A;
|
||||
|
||||
public bool GetHasOT(int language) => BitConverter.ToUInt16(Data, GetOTOffset(language)) != 0;
|
||||
public bool GetHasOT(int language) => ReadUInt16LittleEndian(Data.AsSpan(GetOTOffset(language))) != 0;
|
||||
|
||||
private static int GetLanguageIndex(int language)
|
||||
{
|
||||
|
@ -336,11 +336,11 @@ namespace PKHeX.Core
|
|||
public bool IsNicknamed => false;
|
||||
public int Language => 2;
|
||||
|
||||
public string GetNickname(int language) => StringConverter.GetString7b(Data, GetNicknameOffset(language), 0x1A);
|
||||
public void SetNickname(int language, string value) => StringConverter.SetString7b(value, 12, 13).CopyTo(Data, GetNicknameOffset(language));
|
||||
public string GetNickname(int language) => StringConverter8.GetString(Data.AsSpan(GetNicknameOffset(language), 0x1A));
|
||||
public void SetNickname(int language, string value) => StringConverter8.SetString(Data.AsSpan(GetNicknameOffset(language), 0x1A), value.AsSpan(), 12, StringConverterOption.ClearZero);
|
||||
|
||||
public string GetOT(int language) => StringConverter.GetString7b(Data, GetOTOffset(language), 0x1A);
|
||||
public void SetOT(int language, string value) => StringConverter.SetString7b(value, 12, 13).CopyTo(Data, GetOTOffset(language));
|
||||
public string GetOT(int language) => StringConverter8.GetString(Data.AsSpan(GetOTOffset(language), 0x1A));
|
||||
public void SetOT(int language, string value) => StringConverter8.SetString(Data.AsSpan(GetOTOffset(language), 0x1A), value.AsSpan(), 12, StringConverterOption.ClearZero);
|
||||
|
||||
private static int GetNicknameOffset(int language)
|
||||
{
|
||||
|
@ -536,7 +536,7 @@ namespace PKHeX.Core
|
|||
|
||||
private void SetIVs(PKM pk)
|
||||
{
|
||||
int[] finalIVs = new int[6];
|
||||
Span<int> finalIVs = stackalloc int[6];
|
||||
var ivflag = Array.Find(IVs, iv => (byte)(iv - 0xFC) < 3);
|
||||
var rng = Util.Rand;
|
||||
if (ivflag == 0) // Random IVs
|
||||
|
@ -548,11 +548,11 @@ namespace PKHeX.Core
|
|||
{
|
||||
int IVCount = ivflag - 0xFB;
|
||||
do { finalIVs[rng.Next(6)] = 31; }
|
||||
while (finalIVs.Count(iv => iv == 31) < IVCount);
|
||||
while (finalIVs.Count(31) < IVCount);
|
||||
for (int i = 0; i < 6; i++)
|
||||
finalIVs[i] = finalIVs[i] == 31 ? 31 : rng.Next(32);
|
||||
}
|
||||
pk.IVs = finalIVs;
|
||||
pk.SetIVs(finalIVs);
|
||||
}
|
||||
|
||||
public override bool IsMatchExact(PKM pkm, DexLevel evo)
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using static System.Buffers.Binary.BinaryPrimitives;
|
||||
|
||||
namespace PKHeX.Core
|
||||
{
|
||||
|
@ -33,21 +33,21 @@ namespace PKHeX.Core
|
|||
// General Card Properties
|
||||
public override int CardID
|
||||
{
|
||||
get => BitConverter.ToUInt16(Data, 0);
|
||||
set => BitConverter.GetBytes((ushort)value).CopyTo(Data, 0);
|
||||
get => ReadUInt16LittleEndian(Data.AsSpan(0));
|
||||
set => WriteUInt16LittleEndian(Data.AsSpan(0), (ushort)value);
|
||||
}
|
||||
|
||||
public override string CardTitle
|
||||
{
|
||||
// Max len 36 char, followed by null terminator
|
||||
get => StringConverter.GetString6(Data, 2, 0x4A);
|
||||
set => StringConverter.SetString6(value, 36, 37).CopyTo(Data, 2);
|
||||
get => StringConverter6.GetString(Data.AsSpan(2, 0x4A));
|
||||
set => StringConverter6.SetString(Data.AsSpan(2, 0x4A), value.AsSpan(), 36, StringConverterOption.ClearZero);
|
||||
}
|
||||
|
||||
internal uint RawDate
|
||||
{
|
||||
get => BitConverter.ToUInt32(Data, 0x4C);
|
||||
set => BitConverter.GetBytes(value).CopyTo(Data, 0x4C);
|
||||
get => ReadUInt32LittleEndian(Data.AsSpan(0x4C));
|
||||
set => WriteUInt32LittleEndian(Data.AsSpan(0x4C), value);
|
||||
}
|
||||
|
||||
private uint Year
|
||||
|
@ -113,44 +113,44 @@ namespace PKHeX.Core
|
|||
public override bool IsItem { get => CardType == 1; set { if (value) CardType = 1; } }
|
||||
|
||||
public override int ItemID {
|
||||
get => BitConverter.ToUInt16(Data, 0x68);
|
||||
set => BitConverter.GetBytes((ushort)value).CopyTo(Data, 0x68); }
|
||||
get => ReadUInt16LittleEndian(Data.AsSpan(0x68));
|
||||
set => WriteUInt16LittleEndian(Data.AsSpan(0x68), (ushort)value); }
|
||||
|
||||
public override int Quantity {
|
||||
get => BitConverter.ToUInt16(Data, 0x70);
|
||||
set => BitConverter.GetBytes((ushort)value).CopyTo(Data, 0x70); }
|
||||
get => ReadUInt16LittleEndian(Data.AsSpan(0x70));
|
||||
set => WriteUInt16LittleEndian(Data.AsSpan(0x70), (ushort)value); }
|
||||
|
||||
// Pokémon Properties
|
||||
public override bool IsPokémon { get => CardType == 0; set { if (value) CardType = 0; } }
|
||||
public override bool IsShiny => PIDType == Shiny.Always;
|
||||
public override int TID { get => BitConverter.ToUInt16(Data, 0x68); set => BitConverter.GetBytes((ushort)value).CopyTo(Data, 0x68); }
|
||||
public override int SID { get => BitConverter.ToUInt16(Data, 0x6A); set => BitConverter.GetBytes((ushort)value).CopyTo(Data, 0x6A); }
|
||||
public override int TID { get => ReadUInt16LittleEndian(Data.AsSpan(0x68)); set => WriteUInt16LittleEndian(Data.AsSpan(0x68), (ushort)value); }
|
||||
public override int SID { get => ReadUInt16LittleEndian(Data.AsSpan(0x6A)); set => WriteUInt16LittleEndian(Data.AsSpan(0x6A), (ushort)value); }
|
||||
public int OriginGame { get => Data[0x6C]; set => Data[0x6C] = (byte)value; }
|
||||
public uint EncryptionConstant { get => BitConverter.ToUInt32(Data, 0x70); set => BitConverter.GetBytes(value).CopyTo(Data, 0x70); }
|
||||
public uint EncryptionConstant { get => ReadUInt32LittleEndian(Data.AsSpan(0x70)); set => WriteUInt32LittleEndian(Data.AsSpan(0x70), value); }
|
||||
public override int Ball { get => Data[0x76]; set => Data[0x76] = (byte)value; }
|
||||
public override int HeldItem { get => BitConverter.ToUInt16(Data, 0x78); set => BitConverter.GetBytes((ushort)value).CopyTo(Data, 0x78); }
|
||||
public override int HeldItem { get => ReadUInt16LittleEndian(Data.AsSpan(0x78)); set => WriteUInt16LittleEndian(Data.AsSpan(0x78), (ushort)value); }
|
||||
|
||||
public int Move1 { get => BitConverter.ToUInt16(Data, 0x7A); set => BitConverter.GetBytes((ushort)value).CopyTo(Data, 0x7A); }
|
||||
public int Move2 { get => BitConverter.ToUInt16(Data, 0x7C); set => BitConverter.GetBytes((ushort)value).CopyTo(Data, 0x7C); }
|
||||
public int Move3 { get => BitConverter.ToUInt16(Data, 0x7E); set => BitConverter.GetBytes((ushort)value).CopyTo(Data, 0x7E); }
|
||||
public int Move4 { get => BitConverter.ToUInt16(Data, 0x80); set => BitConverter.GetBytes((ushort)value).CopyTo(Data, 0x80); }
|
||||
public int Move1 { get => ReadUInt16LittleEndian(Data.AsSpan(0x7A)); set => WriteUInt16LittleEndian(Data.AsSpan(0x7A), (ushort)value); }
|
||||
public int Move2 { get => ReadUInt16LittleEndian(Data.AsSpan(0x7C)); set => WriteUInt16LittleEndian(Data.AsSpan(0x7C), (ushort)value); }
|
||||
public int Move3 { get => ReadUInt16LittleEndian(Data.AsSpan(0x7E)); set => WriteUInt16LittleEndian(Data.AsSpan(0x7E), (ushort)value); }
|
||||
public int Move4 { get => ReadUInt16LittleEndian(Data.AsSpan(0x80)); set => WriteUInt16LittleEndian(Data.AsSpan(0x80), (ushort)value); }
|
||||
|
||||
public override int Species { get => BitConverter.ToUInt16(Data, 0x82); set => BitConverter.GetBytes((ushort)value).CopyTo(Data, 0x82); }
|
||||
public override int Species { get => ReadUInt16LittleEndian(Data.AsSpan(0x82)); set => WriteUInt16LittleEndian(Data.AsSpan(0x82), (ushort)value); }
|
||||
public override int Form { get => Data[0x84]; set => Data[0x84] = (byte)value; }
|
||||
public int Language { get => Data[0x85]; set => Data[0x85] = (byte)value; }
|
||||
|
||||
public string Nickname
|
||||
{
|
||||
get => StringConverter.GetString6(Data, 0x86, 0x1A);
|
||||
set => StringConverter.SetString6(value, 12, 13).CopyTo(Data, 0x86);
|
||||
get => StringConverter6.GetString(Data.AsSpan(0x86, 0x1A));
|
||||
set => StringConverter6.SetString(Data.AsSpan(0x86, 0x1A), value.AsSpan(), 12, StringConverterOption.ClearZero);
|
||||
}
|
||||
|
||||
public int Nature { get => (sbyte)Data[0xA0]; set => Data[0xA0] = (byte)value; }
|
||||
public override int Gender { get => Data[0xA1]; set => Data[0xA1] = (byte)value; }
|
||||
public override int AbilityType { get => Data[0xA2]; set => Data[0xA2] = (byte)value; }
|
||||
public Shiny PIDType { get => (Shiny)Data[0xA3]; set => Data[0xA3] = (byte)value; }
|
||||
public override int EggLocation { get => BitConverter.ToUInt16(Data, 0xA4); set => BitConverter.GetBytes((ushort)value).CopyTo(Data, 0xA4); }
|
||||
public int MetLocation { get => BitConverter.ToUInt16(Data, 0xA6); set => BitConverter.GetBytes((ushort)value).CopyTo(Data, 0xA6); }
|
||||
public override int EggLocation { get => ReadUInt16LittleEndian(Data.AsSpan(0xA4)); set => WriteUInt16LittleEndian(Data.AsSpan(0xA4), (ushort)value); }
|
||||
public int MetLocation { get => ReadUInt16LittleEndian(Data.AsSpan(0xA6)); set => WriteUInt16LittleEndian(Data.AsSpan(0xA6), (ushort)value); }
|
||||
|
||||
public byte CNT_Cool { get => Data[0xA9]; set => Data[0xA9] = value; }
|
||||
public byte CNT_Beauty { get => Data[0xAA]; set => Data[0xAA] = value; }
|
||||
|
@ -170,22 +170,22 @@ namespace PKHeX.Core
|
|||
|
||||
public override string OT_Name
|
||||
{
|
||||
get => StringConverter.GetString6(Data, 0xB6, 0x1A);
|
||||
set => StringConverter.SetString6(value, 12, 13).CopyTo(Data, 0xB6);
|
||||
get => StringConverter6.GetString(Data.AsSpan(0xB6, 0x1A));
|
||||
set => StringConverter6.SetString(Data.AsSpan(0xB6, 0x1A), value.AsSpan(), 12, StringConverterOption.ClearZero);
|
||||
}
|
||||
|
||||
public override int Level { get => Data[0xD0]; set => Data[0xD0] = (byte)value; }
|
||||
public override bool IsEgg { get => Data[0xD1] == 1; set => Data[0xD1] = value ? (byte)1 : (byte)0; }
|
||||
public uint PID { get => BitConverter.ToUInt32(Data, 0xD4); set => BitConverter.GetBytes(value).CopyTo(Data, 0xD4); }
|
||||
public uint PID { get => ReadUInt32LittleEndian(Data.AsSpan(0xD4)); set => WriteUInt32LittleEndian(Data.AsSpan(0xD4), value); }
|
||||
|
||||
public int RelearnMove1 { get => BitConverter.ToUInt16(Data, 0xD8); set => BitConverter.GetBytes((ushort)value).CopyTo(Data, 0xD8); }
|
||||
public int RelearnMove2 { get => BitConverter.ToUInt16(Data, 0xDA); set => BitConverter.GetBytes((ushort)value).CopyTo(Data, 0xDA); }
|
||||
public int RelearnMove3 { get => BitConverter.ToUInt16(Data, 0xDC); set => BitConverter.GetBytes((ushort)value).CopyTo(Data, 0xDC); }
|
||||
public int RelearnMove4 { get => BitConverter.ToUInt16(Data, 0xDE); set => BitConverter.GetBytes((ushort)value).CopyTo(Data, 0xDE); }
|
||||
public int RelearnMove1 { get => ReadUInt16LittleEndian(Data.AsSpan(0xD8)); set => WriteUInt16LittleEndian(Data.AsSpan(0xD8), (ushort)value); }
|
||||
public int RelearnMove2 { get => ReadUInt16LittleEndian(Data.AsSpan(0xDA)); set => WriteUInt16LittleEndian(Data.AsSpan(0xDA), (ushort)value); }
|
||||
public int RelearnMove3 { get => ReadUInt16LittleEndian(Data.AsSpan(0xDC)); set => WriteUInt16LittleEndian(Data.AsSpan(0xDC), (ushort)value); }
|
||||
public int RelearnMove4 { get => ReadUInt16LittleEndian(Data.AsSpan(0xDE)); set => WriteUInt16LittleEndian(Data.AsSpan(0xDE), (ushort)value); }
|
||||
|
||||
public int OT_Intensity { get => Data[0xE0]; set => Data[0xE0] = (byte)value; }
|
||||
public int OT_Memory { get => Data[0xE1]; set => Data[0xE1] = (byte)value; }
|
||||
public int OT_TextVar { get => BitConverter.ToUInt16(Data, 0xE2); set => BitConverter.GetBytes((ushort)value).CopyTo(Data, 0xE2); }
|
||||
public int OT_TextVar { get => ReadUInt16LittleEndian(Data.AsSpan(0xE2)); set => WriteUInt16LittleEndian(Data.AsSpan(0xE2), (ushort)value); }
|
||||
public int OT_Feeling { get => Data[0xE4]; set => Data[0xE4] = (byte)value; }
|
||||
|
||||
public int EV_HP { get => Data[0xE5]; set => Data[0xE5] = (byte)value; }
|
||||
|
@ -448,7 +448,7 @@ namespace PKHeX.Core
|
|||
|
||||
private void SetIVs(PKM pk)
|
||||
{
|
||||
int[] finalIVs = new int[6];
|
||||
Span<int> finalIVs = stackalloc int[6];
|
||||
var ivflag = Array.Find(IVs, iv => (byte)(iv - 0xFC) < 3);
|
||||
var rnd = Util.Rand;
|
||||
if (ivflag == 0) // Random IVs
|
||||
|
@ -460,11 +460,11 @@ namespace PKHeX.Core
|
|||
{
|
||||
int IVCount = ivflag - 0xFB;
|
||||
do { finalIVs[rnd.Next(6)] = 31; }
|
||||
while (finalIVs.Count(iv => iv == 31) < IVCount);
|
||||
while (finalIVs.Count(31) < IVCount);
|
||||
for (int i = 0; i < 6; i++)
|
||||
finalIVs[i] = finalIVs[i] == 31 ? 31 : rnd.Next(32);
|
||||
}
|
||||
pk.IVs = finalIVs;
|
||||
pk.SetIVs(finalIVs);
|
||||
}
|
||||
|
||||
public override bool IsMatchExact(PKM pkm, DexLevel evo)
|
||||
|
|
|
@ -23,7 +23,8 @@ namespace PKHeX.Core
|
|||
Gift.RestrictVersion = RestrictVersion;
|
||||
Gift.RestrictLanguage = RestrictLanguage;
|
||||
}
|
||||
public static WC6[] GetArray(byte[] WC6Full, byte[] data)
|
||||
|
||||
public static WC6[] GetArray(ReadOnlySpan<byte> WC6Full, ReadOnlySpan<byte> data)
|
||||
{
|
||||
var countfull = WC6Full.Length / Size;
|
||||
var countgift = data.Length / WC6.Size;
|
||||
|
@ -38,9 +39,9 @@ namespace PKHeX.Core
|
|||
return result;
|
||||
}
|
||||
|
||||
private static WC6 ReadWC6(byte[] data, int ofs, DateTime date)
|
||||
private static WC6 ReadWC6(ReadOnlySpan<byte> data, int ofs, DateTime date)
|
||||
{
|
||||
var slice = data.Slice(ofs + GiftStart, WC6.Size);
|
||||
var slice = data.Slice(ofs + GiftStart, WC6.Size).ToArray();
|
||||
return new WC6(slice)
|
||||
{
|
||||
RestrictVersion = data[ofs],
|
||||
|
@ -49,9 +50,9 @@ namespace PKHeX.Core
|
|||
};
|
||||
}
|
||||
|
||||
private static WC6 ReadWC6Only(byte[] data, int ofs)
|
||||
private static WC6 ReadWC6Only(ReadOnlySpan<byte> data, int ofs)
|
||||
{
|
||||
var slice = data.Slice(ofs, WC6.Size);
|
||||
var slice = data.Slice(ofs, WC6.Size).ToArray();
|
||||
return new WC6(slice);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using static System.Buffers.Binary.BinaryPrimitives;
|
||||
|
||||
namespace PKHeX.Core
|
||||
{
|
||||
|
@ -32,21 +32,21 @@ namespace PKHeX.Core
|
|||
// General Card Properties
|
||||
public override int CardID
|
||||
{
|
||||
get => BitConverter.ToUInt16(Data, 0);
|
||||
set => BitConverter.GetBytes((ushort)value).CopyTo(Data, 0);
|
||||
get => ReadUInt16LittleEndian(Data.AsSpan(0));
|
||||
set => WriteUInt16LittleEndian(Data.AsSpan(0), (ushort)value);
|
||||
}
|
||||
|
||||
public override string CardTitle
|
||||
{
|
||||
// Max len 36 char, followed by null terminator
|
||||
get => StringConverter.GetString7(Data, 2, 0x4A);
|
||||
set => StringConverter.SetString7(value, 36, 37).CopyTo(Data, 2);
|
||||
get => StringConverter7.GetString(Data.AsSpan(2, 0x4A));
|
||||
set => StringConverter7.SetString(Data.AsSpan(2, 0x4A), value.AsSpan(), 36, Language, StringConverterOption.ClearZero);
|
||||
}
|
||||
|
||||
internal uint RawDate
|
||||
{
|
||||
get => BitConverter.ToUInt32(Data, 0x4C);
|
||||
set => BitConverter.GetBytes(value).CopyTo(Data, 0x4C);
|
||||
get => ReadUInt32LittleEndian(Data.AsSpan(0x4C));
|
||||
set => WriteUInt32LittleEndian(Data.AsSpan(0x4C), value);
|
||||
}
|
||||
|
||||
private uint Year
|
||||
|
@ -123,16 +123,16 @@ namespace PKHeX.Core
|
|||
|
||||
// Item Properties
|
||||
public override bool IsItem { get => CardType == 1; set { if (value) CardType = 1; } }
|
||||
public override int ItemID { get => BitConverter.ToUInt16(Data, 0x68); set => BitConverter.GetBytes((ushort)value).CopyTo(Data, 0x68); }
|
||||
public int GetItem(int index) => BitConverter.ToUInt16(Data, 0x68 + (0x4 * index));
|
||||
public void SetItem(int index, ushort item) => BitConverter.GetBytes(item).CopyTo(Data, 0x68 + (4 * index));
|
||||
public int GetQuantity(int index) => BitConverter.ToUInt16(Data, 0x6A + (0x4 * index));
|
||||
public void SetQuantity(int index, ushort quantity) => BitConverter.GetBytes(quantity).CopyTo(Data, 0x6A + (4 * index));
|
||||
public override int ItemID { get => ReadUInt16LittleEndian(Data.AsSpan(0x68)); set => WriteUInt16LittleEndian(Data.AsSpan(0x68), (ushort)value); }
|
||||
public int GetItem(int index) => ReadUInt16LittleEndian(Data.AsSpan(0x68 + (0x4 * index)));
|
||||
public void SetItem(int index, ushort item) => WriteUInt16LittleEndian(Data.AsSpan(0x68 + (4 * index)), item);
|
||||
public int GetQuantity(int index) => ReadUInt16LittleEndian(Data.AsSpan(0x6A + (0x4 * index)));
|
||||
public void SetQuantity(int index, ushort quantity) => WriteUInt16LittleEndian(Data.AsSpan(0x6A + (4 * index)), quantity);
|
||||
|
||||
public override int Quantity
|
||||
{
|
||||
get => BitConverter.ToUInt16(Data, 0x6A);
|
||||
set => BitConverter.GetBytes((ushort)value).CopyTo(Data, 0x6A);
|
||||
get => ReadUInt16LittleEndian(Data.AsSpan(0x6A));
|
||||
set => WriteUInt16LittleEndian(Data.AsSpan(0x6A), (ushort)value);
|
||||
}
|
||||
|
||||
// Pokémon Properties
|
||||
|
@ -141,13 +141,13 @@ namespace PKHeX.Core
|
|||
|
||||
public override int TID
|
||||
{
|
||||
get => BitConverter.ToUInt16(Data, 0x68);
|
||||
set => BitConverter.GetBytes((ushort)value).CopyTo(Data, 0x68);
|
||||
get => ReadUInt16LittleEndian(Data.AsSpan(0x68));
|
||||
set => WriteUInt16LittleEndian(Data.AsSpan(0x68), (ushort)value);
|
||||
}
|
||||
|
||||
public override int SID {
|
||||
get => BitConverter.ToUInt16(Data, 0x6A);
|
||||
set => BitConverter.GetBytes((ushort)value).CopyTo(Data, 0x6A);
|
||||
get => ReadUInt16LittleEndian(Data.AsSpan(0x6A));
|
||||
set => WriteUInt16LittleEndian(Data.AsSpan(0x6A), (ushort)value);
|
||||
}
|
||||
|
||||
public int OriginGame
|
||||
|
@ -157,8 +157,8 @@ namespace PKHeX.Core
|
|||
}
|
||||
|
||||
public uint EncryptionConstant {
|
||||
get => BitConverter.ToUInt32(Data, 0x70);
|
||||
set => BitConverter.GetBytes(value).CopyTo(Data, 0x70);
|
||||
get => ReadUInt32LittleEndian(Data.AsSpan(0x70));
|
||||
set => WriteUInt32LittleEndian(Data.AsSpan(0x70), value);
|
||||
}
|
||||
|
||||
public override int Ball
|
||||
|
@ -168,30 +168,30 @@ namespace PKHeX.Core
|
|||
|
||||
public override int HeldItem
|
||||
{
|
||||
get => BitConverter.ToUInt16(Data, 0x78);
|
||||
set => BitConverter.GetBytes((ushort)value).CopyTo(Data, 0x78);
|
||||
get => ReadUInt16LittleEndian(Data.AsSpan(0x78));
|
||||
set => WriteUInt16LittleEndian(Data.AsSpan(0x78), (ushort)value);
|
||||
}
|
||||
|
||||
public int Move1 { get => BitConverter.ToUInt16(Data, 0x7A); set => BitConverter.GetBytes((ushort)value).CopyTo(Data, 0x7A); }
|
||||
public int Move2 { get => BitConverter.ToUInt16(Data, 0x7C); set => BitConverter.GetBytes((ushort)value).CopyTo(Data, 0x7C); }
|
||||
public int Move3 { get => BitConverter.ToUInt16(Data, 0x7E); set => BitConverter.GetBytes((ushort)value).CopyTo(Data, 0x7E); }
|
||||
public int Move4 { get => BitConverter.ToUInt16(Data, 0x80); set => BitConverter.GetBytes((ushort)value).CopyTo(Data, 0x80); }
|
||||
public override int Species { get => BitConverter.ToUInt16(Data, 0x82); set => BitConverter.GetBytes((ushort)value).CopyTo(Data, 0x82); }
|
||||
public int Move1 { get => ReadUInt16LittleEndian(Data.AsSpan(0x7A)); set => WriteUInt16LittleEndian(Data.AsSpan(0x7A), (ushort)value); }
|
||||
public int Move2 { get => ReadUInt16LittleEndian(Data.AsSpan(0x7C)); set => WriteUInt16LittleEndian(Data.AsSpan(0x7C), (ushort)value); }
|
||||
public int Move3 { get => ReadUInt16LittleEndian(Data.AsSpan(0x7E)); set => WriteUInt16LittleEndian(Data.AsSpan(0x7E), (ushort)value); }
|
||||
public int Move4 { get => ReadUInt16LittleEndian(Data.AsSpan(0x80)); set => WriteUInt16LittleEndian(Data.AsSpan(0x80), (ushort)value); }
|
||||
public override int Species { get => ReadUInt16LittleEndian(Data.AsSpan(0x82)); set => WriteUInt16LittleEndian(Data.AsSpan(0x82), (ushort)value); }
|
||||
public override int Form { get => Data[0x84]; set => Data[0x84] = (byte)value; }
|
||||
public int Language { get => Data[0x85]; set => Data[0x85] = (byte)value; }
|
||||
|
||||
public string Nickname
|
||||
{
|
||||
get => StringConverter.GetString7(Data, 0x86, 0x1A);
|
||||
set => StringConverter.SetString7(value, 12, 13).CopyTo(Data, 0x86);
|
||||
get => StringConverter7.GetString(Data.AsSpan(0x86, 0x1A));
|
||||
set => StringConverter7.SetString(Data.AsSpan(0x86, 0x1A), value.AsSpan(), 12, Language, StringConverterOption.ClearZero);
|
||||
}
|
||||
|
||||
public int Nature { get => (sbyte)Data[0xA0]; set => Data[0xA0] = (byte)value; }
|
||||
public override int Gender { get => Data[0xA1]; set => Data[0xA1] = (byte)value; }
|
||||
public override int AbilityType { get => Data[0xA2]; set => Data[0xA2] = (byte)value; }
|
||||
public Shiny PIDType { get => (Shiny)Data[0xA3]; set => Data[0xA3] = (byte)value; }
|
||||
public override int EggLocation { get => BitConverter.ToUInt16(Data, 0xA4); set => BitConverter.GetBytes((ushort)value).CopyTo(Data, 0xA4); }
|
||||
public int MetLocation { get => BitConverter.ToUInt16(Data, 0xA6); set => BitConverter.GetBytes((ushort)value).CopyTo(Data, 0xA6); }
|
||||
public override int EggLocation { get => ReadUInt16LittleEndian(Data.AsSpan(0xA4)); set => WriteUInt16LittleEndian(Data.AsSpan(0xA4), (ushort)value); }
|
||||
public int MetLocation { get => ReadUInt16LittleEndian(Data.AsSpan(0xA6)); set => WriteUInt16LittleEndian(Data.AsSpan(0xA6), (ushort)value); }
|
||||
public int MetLevel { get => Data[0xA8]; set => Data[0xA8] = (byte)value; }
|
||||
|
||||
public byte CNT_Cool { get => Data[0xA9]; set => Data[0xA9] = value; }
|
||||
|
@ -212,23 +212,23 @@ namespace PKHeX.Core
|
|||
|
||||
public override string OT_Name
|
||||
{
|
||||
get => StringConverter.GetString7(Data, 0xB6, 0x1A);
|
||||
set => StringConverter.SetString7(value, 12, 13).CopyTo(Data, 0xB6);
|
||||
get => StringConverter7.GetString(Data.AsSpan(0xB6, 0x1A));
|
||||
set => StringConverter7.SetString(Data.AsSpan(0xB6, 0x1A), value.AsSpan(), 12, Language, StringConverterOption.ClearZero);
|
||||
}
|
||||
|
||||
public override int Level { get => Data[0xD0]; set => Data[0xD0] = (byte)value; }
|
||||
public override bool IsEgg { get => Data[0xD1] == 1; set => Data[0xD1] = value ? (byte)1 : (byte)0; }
|
||||
public ushort AdditionalItem { get => BitConverter.ToUInt16(Data, 0xD2); set => BitConverter.GetBytes(value).CopyTo(Data, 0xD2); }
|
||||
public ushort AdditionalItem { get => ReadUInt16LittleEndian(Data.AsSpan(0xD2)); set => WriteUInt16LittleEndian(Data.AsSpan(0xD2), value); }
|
||||
|
||||
public uint PID { get => BitConverter.ToUInt32(Data, 0xD4); set => BitConverter.GetBytes(value).CopyTo(Data, 0xD4); }
|
||||
public int RelearnMove1 { get => BitConverter.ToUInt16(Data, 0xD8); set => BitConverter.GetBytes((ushort)value).CopyTo(Data, 0xD8); }
|
||||
public int RelearnMove2 { get => BitConverter.ToUInt16(Data, 0xDA); set => BitConverter.GetBytes((ushort)value).CopyTo(Data, 0xDA); }
|
||||
public int RelearnMove3 { get => BitConverter.ToUInt16(Data, 0xDC); set => BitConverter.GetBytes((ushort)value).CopyTo(Data, 0xDC); }
|
||||
public int RelearnMove4 { get => BitConverter.ToUInt16(Data, 0xDE); set => BitConverter.GetBytes((ushort)value).CopyTo(Data, 0xDE); }
|
||||
public uint PID { get => ReadUInt32LittleEndian(Data.AsSpan(0xD4)); set => WriteUInt32LittleEndian(Data.AsSpan(0xD4), value); }
|
||||
public int RelearnMove1 { get => ReadUInt16LittleEndian(Data.AsSpan(0xD8)); set => WriteUInt16LittleEndian(Data.AsSpan(0xD8), (ushort)value); }
|
||||
public int RelearnMove2 { get => ReadUInt16LittleEndian(Data.AsSpan(0xDA)); set => WriteUInt16LittleEndian(Data.AsSpan(0xDA), (ushort)value); }
|
||||
public int RelearnMove3 { get => ReadUInt16LittleEndian(Data.AsSpan(0xDC)); set => WriteUInt16LittleEndian(Data.AsSpan(0xDC), (ushort)value); }
|
||||
public int RelearnMove4 { get => ReadUInt16LittleEndian(Data.AsSpan(0xDE)); set => WriteUInt16LittleEndian(Data.AsSpan(0xDE), (ushort)value); }
|
||||
|
||||
public int OT_Intensity { get => Data[0xE0]; set => Data[0xE0] = (byte)value; }
|
||||
public int OT_Memory { get => Data[0xE1]; set => Data[0xE1] = (byte)value; }
|
||||
public int OT_TextVar { get => BitConverter.ToUInt16(Data, 0xE2); set => BitConverter.GetBytes((ushort)value).CopyTo(Data, 0xE2); }
|
||||
public int OT_TextVar { get => ReadUInt16LittleEndian(Data.AsSpan(0xE2)); set => WriteUInt16LittleEndian(Data.AsSpan(0xE2), (ushort)value); }
|
||||
public int OT_Feeling { get => Data[0xE4]; set => Data[0xE4] = (byte)value; }
|
||||
|
||||
public int EV_HP { get => Data[0xE5]; set => Data[0xE5] = (byte)value; }
|
||||
|
@ -480,7 +480,7 @@ namespace PKHeX.Core
|
|||
|
||||
private void SetIVs(PKM pk)
|
||||
{
|
||||
int[] finalIVs = new int[6];
|
||||
Span<int> finalIVs = stackalloc int[6];
|
||||
var ivflag = Array.Find(IVs, iv => (byte)(iv - 0xFC) < 3);
|
||||
var rng = Util.Rand;
|
||||
if (ivflag == 0) // Random IVs
|
||||
|
@ -492,11 +492,11 @@ namespace PKHeX.Core
|
|||
{
|
||||
int IVCount = ivflag - 0xFB;
|
||||
do { finalIVs[rng.Next(6)] = 31; }
|
||||
while (finalIVs.Count(iv => iv == 31) < IVCount);
|
||||
while (finalIVs.Count(31) < IVCount);
|
||||
for (int i = 0; i < 6; i++)
|
||||
finalIVs[i] = finalIVs[i] == 31 ? 31 : rng.Next(32);
|
||||
}
|
||||
pk.IVs = finalIVs;
|
||||
pk.SetIVs(finalIVs);
|
||||
}
|
||||
|
||||
public bool IsAshGreninjaWC7(PKM pkm)
|
||||
|
|
|
@ -24,7 +24,7 @@ namespace PKHeX.Core
|
|||
Gift.RestrictLanguage = RestrictLanguage;
|
||||
}
|
||||
|
||||
public static WC7[] GetArray(byte[] wc7Full, byte[] data)
|
||||
public static WC7[] GetArray(ReadOnlySpan<byte> wc7Full, ReadOnlySpan<byte> data)
|
||||
{
|
||||
var countfull = wc7Full.Length / Size;
|
||||
var countgift = data.Length / WC7.Size;
|
||||
|
@ -39,9 +39,9 @@ namespace PKHeX.Core
|
|||
return result;
|
||||
}
|
||||
|
||||
private static WC7 ReadWC7(byte[] data, int ofs, DateTime date)
|
||||
private static WC7 ReadWC7(ReadOnlySpan<byte> data, int ofs, DateTime date)
|
||||
{
|
||||
var slice = data.Slice(ofs + GiftStart, WC7.Size);
|
||||
var slice = data.Slice(ofs + GiftStart, WC7.Size).ToArray();
|
||||
return new WC7(slice)
|
||||
{
|
||||
RestrictVersion = data[ofs],
|
||||
|
@ -50,9 +50,9 @@ namespace PKHeX.Core
|
|||
};
|
||||
}
|
||||
|
||||
private static WC7 ReadWC7Only(byte[] data, int ofs)
|
||||
private static WC7 ReadWC7Only(ReadOnlySpan<byte> data, int ofs)
|
||||
{
|
||||
var slice = data.Slice(ofs, WC7.Size);
|
||||
var slice = data.Slice(ofs, WC7.Size).ToArray();
|
||||
return new WC7(slice);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using static PKHeX.Core.RibbonIndex;
|
||||
using static System.Buffers.Binary.BinaryPrimitives;
|
||||
|
||||
namespace PKHeX.Core
|
||||
{
|
||||
|
@ -35,8 +35,8 @@ namespace PKHeX.Core
|
|||
// General Card Properties
|
||||
public override int CardID
|
||||
{
|
||||
get => BitConverter.ToUInt16(Data, CardStart + 0x8);
|
||||
set => BitConverter.GetBytes((ushort)value).CopyTo(Data, CardStart + 0x8);
|
||||
get => ReadUInt16LittleEndian(Data.AsSpan(CardStart + 0x8));
|
||||
set => WriteUInt16LittleEndian(Data.AsSpan(CardStart + 0x8), (ushort)value);
|
||||
}
|
||||
|
||||
public byte CardFlags { get => Data[CardStart + 0x10]; set => Data[CardStart + 0x10] = value; }
|
||||
|
@ -71,10 +71,10 @@ namespace PKHeX.Core
|
|||
set => SetQuantity(0, (ushort)value);
|
||||
}
|
||||
|
||||
public int GetItem(int index) => BitConverter.ToUInt16(Data, CardStart + 0x20 + (0x4 * index));
|
||||
public void SetItem(int index, ushort item) => BitConverter.GetBytes(item).CopyTo(Data, CardStart + 0x20 + (4 * index));
|
||||
public int GetQuantity(int index) => BitConverter.ToUInt16(Data, CardStart + 0x22 + (0x4 * index));
|
||||
public void SetQuantity(int index, ushort quantity) => BitConverter.GetBytes(quantity).CopyTo(Data, CardStart + 0x22 + (4 * index));
|
||||
public int GetItem(int index) => ReadUInt16LittleEndian(Data.AsSpan(CardStart + 0x20 + (0x4 * index)));
|
||||
public void SetItem(int index, ushort item) => WriteUInt16LittleEndian(Data.AsSpan(CardStart + 0x20 + (4 * index)), item);
|
||||
public int GetQuantity(int index) => ReadUInt16LittleEndian(Data.AsSpan(CardStart + 0x22 + (0x4 * index)));
|
||||
public void SetQuantity(int index, ushort quantity) => WriteUInt16LittleEndian(Data.AsSpan(CardStart + 0x22 + (4 * index)), quantity);
|
||||
|
||||
// Pokémon Properties
|
||||
public override bool IsPokémon { get => CardType == GiftType.Pokemon; set { if (value) CardType = GiftType.Pokemon; } }
|
||||
|
@ -102,59 +102,59 @@ namespace PKHeX.Core
|
|||
|
||||
public override int TID
|
||||
{
|
||||
get => BitConverter.ToUInt16(Data, CardStart + 0x20);
|
||||
set => BitConverter.GetBytes((ushort)value).CopyTo(Data, CardStart + 0x20);
|
||||
get => ReadUInt16LittleEndian(Data.AsSpan(CardStart + 0x20));
|
||||
set => WriteUInt16LittleEndian(Data.AsSpan(CardStart + 0x20), (ushort)value);
|
||||
}
|
||||
|
||||
public override int SID {
|
||||
get => BitConverter.ToUInt16(Data, CardStart + 0x22);
|
||||
set => BitConverter.GetBytes((ushort)value).CopyTo(Data, CardStart + 0x22);
|
||||
get => ReadUInt16LittleEndian(Data.AsSpan(CardStart + 0x22));
|
||||
set => WriteUInt16LittleEndian(Data.AsSpan(CardStart + 0x22), (ushort)value);
|
||||
}
|
||||
|
||||
public int OriginGame
|
||||
{
|
||||
get => BitConverter.ToInt32(Data, CardStart + 0x24);
|
||||
set => BitConverter.GetBytes(value).CopyTo(Data, CardStart + 0x24);
|
||||
get => ReadInt32LittleEndian(Data.AsSpan(CardStart + 0x24));
|
||||
set => WriteInt32LittleEndian(Data.AsSpan(CardStart + 0x24), value);
|
||||
}
|
||||
|
||||
public uint EncryptionConstant
|
||||
{
|
||||
get => BitConverter.ToUInt32(Data, CardStart + 0x28);
|
||||
set => BitConverter.GetBytes(value).CopyTo(Data, CardStart + 0x28);
|
||||
get => ReadUInt32LittleEndian(Data.AsSpan(CardStart + 0x28));
|
||||
set => WriteUInt32LittleEndian(Data.AsSpan(CardStart + 0x28), value);
|
||||
}
|
||||
|
||||
public uint PID
|
||||
{
|
||||
get => BitConverter.ToUInt32(Data, CardStart + 0x2C);
|
||||
set => BitConverter.GetBytes(value).CopyTo(Data, CardStart + 0x2C);
|
||||
get => ReadUInt32LittleEndian(Data.AsSpan(CardStart + 0x2C));
|
||||
set => WriteUInt32LittleEndian(Data.AsSpan(CardStart + 0x2C), value);
|
||||
}
|
||||
|
||||
// Nicknames, OT Names 0x30 - 0x228
|
||||
public override int EggLocation { get => BitConverter.ToUInt16(Data, CardStart + 0x228); set => BitConverter.GetBytes((ushort)value).CopyTo(Data, CardStart + 0x228); }
|
||||
public int MetLocation { get => BitConverter.ToUInt16(Data, CardStart + 0x22A); set => BitConverter.GetBytes((ushort)value).CopyTo(Data, CardStart + 0x22A); }
|
||||
public override int EggLocation { get => ReadUInt16LittleEndian(Data.AsSpan(CardStart + 0x228)); set => WriteUInt16LittleEndian(Data.AsSpan(CardStart + 0x228), (ushort)value); }
|
||||
public int MetLocation { get => ReadUInt16LittleEndian(Data.AsSpan(CardStart + 0x22A)); set => WriteUInt16LittleEndian(Data.AsSpan(CardStart + 0x22A), (ushort)value); }
|
||||
|
||||
public override int Ball
|
||||
{
|
||||
get => BitConverter.ToUInt16(Data, CardStart + 0x22C);
|
||||
set => BitConverter.GetBytes((ushort)value).CopyTo(Data, CardStart + 0x22C);
|
||||
get => ReadUInt16LittleEndian(Data.AsSpan(CardStart + 0x22C));
|
||||
set => WriteUInt16LittleEndian(Data.AsSpan(CardStart + 0x22C), (ushort)value);
|
||||
}
|
||||
|
||||
public override int HeldItem
|
||||
{
|
||||
get => BitConverter.ToUInt16(Data, CardStart + 0x22E);
|
||||
set => BitConverter.GetBytes((ushort)value).CopyTo(Data, CardStart + 0x22E);
|
||||
get => ReadUInt16LittleEndian(Data.AsSpan(CardStart + 0x22E));
|
||||
set => WriteUInt16LittleEndian(Data.AsSpan(CardStart + 0x22E), (ushort)value);
|
||||
}
|
||||
|
||||
public int Move1 { get => BitConverter.ToUInt16(Data, CardStart + 0x230); set => BitConverter.GetBytes((ushort)value).CopyTo(Data, CardStart + 0x230); }
|
||||
public int Move2 { get => BitConverter.ToUInt16(Data, CardStart + 0x232); set => BitConverter.GetBytes((ushort)value).CopyTo(Data, CardStart + 0x232); }
|
||||
public int Move3 { get => BitConverter.ToUInt16(Data, CardStart + 0x234); set => BitConverter.GetBytes((ushort)value).CopyTo(Data, CardStart + 0x234); }
|
||||
public int Move4 { get => BitConverter.ToUInt16(Data, CardStart + 0x236); set => BitConverter.GetBytes((ushort)value).CopyTo(Data, CardStart + 0x236); }
|
||||
public int RelearnMove1 { get => BitConverter.ToUInt16(Data, CardStart + 0x238); set => BitConverter.GetBytes((ushort)value).CopyTo(Data, CardStart + 0x238); }
|
||||
public int RelearnMove2 { get => BitConverter.ToUInt16(Data, CardStart + 0x23A); set => BitConverter.GetBytes((ushort)value).CopyTo(Data, CardStart + 0x23A); }
|
||||
public int RelearnMove3 { get => BitConverter.ToUInt16(Data, CardStart + 0x23C); set => BitConverter.GetBytes((ushort)value).CopyTo(Data, CardStart + 0x23C); }
|
||||
public int RelearnMove4 { get => BitConverter.ToUInt16(Data, CardStart + 0x23E); set => BitConverter.GetBytes((ushort)value).CopyTo(Data, CardStart + 0x23E); }
|
||||
public int Move1 { get => ReadUInt16LittleEndian(Data.AsSpan(CardStart + 0x230)); set => WriteUInt16LittleEndian(Data.AsSpan(CardStart + 0x230), (ushort)value); }
|
||||
public int Move2 { get => ReadUInt16LittleEndian(Data.AsSpan(CardStart + 0x232)); set => WriteUInt16LittleEndian(Data.AsSpan(CardStart + 0x232), (ushort)value); }
|
||||
public int Move3 { get => ReadUInt16LittleEndian(Data.AsSpan(CardStart + 0x234)); set => WriteUInt16LittleEndian(Data.AsSpan(CardStart + 0x234), (ushort)value); }
|
||||
public int Move4 { get => ReadUInt16LittleEndian(Data.AsSpan(CardStart + 0x236)); set => WriteUInt16LittleEndian(Data.AsSpan(CardStart + 0x236), (ushort)value); }
|
||||
public int RelearnMove1 { get => ReadUInt16LittleEndian(Data.AsSpan(CardStart + 0x238)); set => WriteUInt16LittleEndian(Data.AsSpan(CardStart + 0x238), (ushort)value); }
|
||||
public int RelearnMove2 { get => ReadUInt16LittleEndian(Data.AsSpan(CardStart + 0x23A)); set => WriteUInt16LittleEndian(Data.AsSpan(CardStart + 0x23A), (ushort)value); }
|
||||
public int RelearnMove3 { get => ReadUInt16LittleEndian(Data.AsSpan(CardStart + 0x23C)); set => WriteUInt16LittleEndian(Data.AsSpan(CardStart + 0x23C), (ushort)value); }
|
||||
public int RelearnMove4 { get => ReadUInt16LittleEndian(Data.AsSpan(CardStart + 0x23E)); set => WriteUInt16LittleEndian(Data.AsSpan(CardStart + 0x23E), (ushort)value); }
|
||||
|
||||
public override int Species { get => BitConverter.ToUInt16(Data, CardStart + 0x240); set => BitConverter.GetBytes((ushort)value).CopyTo(Data, CardStart + 0x240); }
|
||||
public override int Species { get => ReadUInt16LittleEndian(Data.AsSpan(CardStart + 0x240)); set => WriteUInt16LittleEndian(Data.AsSpan(CardStart + 0x240), (ushort)value); }
|
||||
public override int Form { get => Data[CardStart + 0x242]; set => Data[CardStart + 0x242] = (byte)value; }
|
||||
public override int Gender { get => Data[CardStart + 0x243]; set => Data[CardStart + 0x243] = (byte)value; }
|
||||
public override int Level { get => Data[CardStart + 0x244]; set => Data[CardStart + 0x244] = (byte)value; }
|
||||
|
@ -187,10 +187,10 @@ namespace PKHeX.Core
|
|||
{
|
||||
for (int i = 0; i < RibbonBytesCount; i++)
|
||||
{
|
||||
var val = Data[RibbonBytesOffset + i];
|
||||
if (val == RibbonByteNone)
|
||||
var value = Data[RibbonBytesOffset + i];
|
||||
if (value == RibbonByteNone)
|
||||
return false;
|
||||
if ((RibbonIndex)val is >= MarkLunchtime and <= MarkSlump)
|
||||
if ((RibbonIndex)value is >= MarkLunchtime and <= MarkSlump)
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
|
@ -229,7 +229,7 @@ namespace PKHeX.Core
|
|||
public int OT_Intensity { get => Data[CardStart + 0x279]; set => Data[CardStart + 0x279] = (byte)value; }
|
||||
public int OT_Memory { get => Data[CardStart + 0x27A]; set => Data[CardStart + 0x27A] = (byte)value; }
|
||||
public int OT_Feeling { get => Data[CardStart + 0x27B]; set => Data[CardStart + 0x27B] = (byte)value; }
|
||||
public int OT_TextVar { get => BitConverter.ToUInt16(Data, CardStart + 0x27C); set => BitConverter.GetBytes((ushort)value).CopyTo(Data, CardStart + 0x27C); }
|
||||
public int OT_TextVar { get => ReadUInt16LittleEndian(Data.AsSpan(CardStart + 0x27C)); set => WriteUInt16LittleEndian(Data.AsSpan(CardStart + 0x27C), (ushort)value); }
|
||||
|
||||
// Meta Accessible Properties
|
||||
public override int[] IVs
|
||||
|
@ -254,14 +254,14 @@ namespace PKHeX.Core
|
|||
}
|
||||
}
|
||||
|
||||
public bool GetIsNicknamed(int language) => BitConverter.ToUInt16(Data, GetNicknameOffset(language)) != 0;
|
||||
public bool GetIsNicknamed(int language) => ReadUInt16LittleEndian(Data.AsSpan(GetNicknameOffset(language))) != 0;
|
||||
|
||||
public bool CanBeAnyLanguage()
|
||||
{
|
||||
for (int i = 0; i < 9; i++)
|
||||
{
|
||||
var ofs = GetLanguageOffset(i);
|
||||
var lang = BitConverter.ToInt16(Data, ofs);
|
||||
var lang = ReadInt16LittleEndian(Data.AsSpan(ofs));
|
||||
if (lang != 0)
|
||||
return false;
|
||||
}
|
||||
|
@ -279,7 +279,7 @@ namespace PKHeX.Core
|
|||
for (int i = 0; i < 9; i++)
|
||||
{
|
||||
var ofs = GetLanguageOffset(i);
|
||||
var lang = BitConverter.ToInt16(Data, ofs);
|
||||
var lang = ReadInt16LittleEndian(Data.AsSpan(ofs));
|
||||
if (lang == language)
|
||||
return true;
|
||||
}
|
||||
|
@ -289,7 +289,7 @@ namespace PKHeX.Core
|
|||
public int GetLanguage(int redeemLanguage) => Data[GetLanguageOffset(GetLanguageIndex(redeemLanguage))];
|
||||
private static int GetLanguageOffset(int index) => 0x30 + (index * 0x1C) + 0x1A;
|
||||
|
||||
public bool GetHasOT(int language) => BitConverter.ToUInt16(Data, GetOTOffset(language)) != 0;
|
||||
public bool GetHasOT(int language) => ReadUInt16LittleEndian(Data.AsSpan(GetOTOffset(language))) != 0;
|
||||
|
||||
private static int GetLanguageIndex(int language)
|
||||
{
|
||||
|
@ -330,11 +330,11 @@ namespace PKHeX.Core
|
|||
public bool IsNicknamed => false;
|
||||
public int Language => 2;
|
||||
|
||||
public string GetNickname(int language) => StringConverter.GetString7b(Data, GetNicknameOffset(language), 0x1A);
|
||||
public void SetNickname(int language, string value) => StringConverter.SetString7b(value, 12, 13).CopyTo(Data, GetNicknameOffset(language));
|
||||
public string GetNickname(int language) => StringConverter8.GetString(Data.AsSpan(GetNicknameOffset(language), 0x1A));
|
||||
public void SetNickname(int language, string value) => StringConverter8.SetString(Data.AsSpan(GetNicknameOffset(language), 0x1A), value.AsSpan(), 12, StringConverterOption.ClearZero);
|
||||
|
||||
public string GetOT(int language) => StringConverter.GetString7b(Data, GetOTOffset(language), 0x1A);
|
||||
public void SetOT(int language, string value) => StringConverter.SetString7b(value, 12, 13).CopyTo(Data, GetOTOffset(language));
|
||||
public string GetOT(int language) => StringConverter8.GetString(Data.AsSpan(GetOTOffset(language), 0x1A));
|
||||
public void SetOT(int language, string value) => StringConverter8.SetString(Data.AsSpan(GetOTOffset(language), 0x1A), value.AsSpan(), 12, StringConverterOption.ClearZero);
|
||||
|
||||
private static int GetNicknameOffset(int language)
|
||||
{
|
||||
|
@ -541,7 +541,7 @@ namespace PKHeX.Core
|
|||
|
||||
private void SetIVs(PKM pk)
|
||||
{
|
||||
int[] finalIVs = new int[6];
|
||||
Span<int> finalIVs = stackalloc int[6];
|
||||
var ivflag = Array.Find(IVs, iv => (byte)(iv - 0xFC) < 3);
|
||||
var rng = Util.Rand;
|
||||
if (ivflag == 0) // Random IVs
|
||||
|
@ -553,11 +553,11 @@ namespace PKHeX.Core
|
|||
{
|
||||
int IVCount = ivflag - 0xFB;
|
||||
do { finalIVs[rng.Next(6)] = 31; }
|
||||
while (finalIVs.Count(iv => iv == 31) < IVCount);
|
||||
while (finalIVs.Count(31) < IVCount);
|
||||
for (int i = 0; i < 6; i++)
|
||||
finalIVs[i] = finalIVs[i] == 31 ? 31 : rng.Next(32);
|
||||
}
|
||||
pk.IVs = finalIVs;
|
||||
pk.SetIVs(finalIVs);
|
||||
}
|
||||
|
||||
public override bool IsMatchExact(PKM pkm, DexLevel evo)
|
||||
|
|
|
@ -1,4 +1,5 @@
|
|||
using System;
|
||||
using static System.Buffers.Binary.BinaryPrimitives;
|
||||
|
||||
namespace PKHeX.Core
|
||||
{
|
||||
|
@ -23,22 +24,22 @@ namespace PKHeX.Core
|
|||
|
||||
public uint Epoch
|
||||
{
|
||||
get => BitConverter.ToUInt32(Data, 0x00);
|
||||
set => BitConverter.GetBytes(value).CopyTo(Data, 0x00);
|
||||
get => ReadUInt32LittleEndian(Data.AsSpan(0x00));
|
||||
set => WriteUInt32LittleEndian(Data.AsSpan(0x00), value);
|
||||
}
|
||||
|
||||
public DateTime Date => new DateTime(1970, 1, 1, 0, 0, 0, DateTimeKind.Utc).AddSeconds(Epoch);
|
||||
|
||||
public override int CardID
|
||||
{
|
||||
get => BitConverter.ToUInt16(Data, 0x08);
|
||||
set => BitConverter.GetBytes((ushort)value).CopyTo(Data, 0x08);
|
||||
get => ReadUInt16LittleEndian(Data.AsSpan(0x08));
|
||||
set => WriteUInt16LittleEndian(Data.AsSpan(0x08), (ushort)value);
|
||||
}
|
||||
|
||||
public ushort CardType
|
||||
{
|
||||
get => BitConverter.ToUInt16(Data, 0x0A);
|
||||
set => BitConverter.GetBytes(value).CopyTo(Data, 0x0A);
|
||||
get => ReadUInt16LittleEndian(Data.AsSpan(0x0A));
|
||||
set => WriteUInt16LittleEndian(Data.AsSpan(0x0A), value);
|
||||
}
|
||||
|
||||
public WR7GiftType GiftType
|
||||
|
@ -57,30 +58,30 @@ namespace PKHeX.Core
|
|||
|
||||
public override int Species
|
||||
{
|
||||
get => BitConverter.ToUInt16(Data, 0x10C);
|
||||
set => BitConverter.GetBytes((ushort)value).CopyTo(Data, 0x10C);
|
||||
get => ReadUInt16LittleEndian(Data.AsSpan(0x10C));
|
||||
set => WriteUInt16LittleEndian(Data.AsSpan(0x10C), (ushort)value);
|
||||
}
|
||||
|
||||
public override bool GiftUsed { get; set; }
|
||||
|
||||
public override int Level // are moves stored? mew has '1' but this could be move
|
||||
{
|
||||
get => BitConverter.ToUInt16(Data, 0x10E);
|
||||
set => BitConverter.GetBytes((ushort)value).CopyTo(Data, 0x10E);
|
||||
get => ReadUInt16LittleEndian(Data.AsSpan(0x10E));
|
||||
set => WriteUInt16LittleEndian(Data.AsSpan(0x10E), (ushort)value);
|
||||
}
|
||||
|
||||
public override int ItemID { get => BitConverter.ToUInt16(Data, 0x110); set => BitConverter.GetBytes((ushort)value).CopyTo(Data, 0x110); }
|
||||
public ushort ItemIDCount { get => BitConverter.ToUInt16(Data, 0x112); set => BitConverter.GetBytes(value).CopyTo(Data, 0x112); }
|
||||
public ushort ItemSet2Item { get => BitConverter.ToUInt16(Data, 0x114); set => BitConverter.GetBytes(value).CopyTo(Data, 0x114); }
|
||||
public ushort ItemSet2Count { get => BitConverter.ToUInt16(Data, 0x116); set => BitConverter.GetBytes(value).CopyTo(Data, 0x116); }
|
||||
public ushort ItemSet3Item { get => BitConverter.ToUInt16(Data, 0x118); set => BitConverter.GetBytes(value).CopyTo(Data, 0x118); }
|
||||
public ushort ItemSet3Count { get => BitConverter.ToUInt16(Data, 0x11A); set => BitConverter.GetBytes(value).CopyTo(Data, 0x11A); }
|
||||
public ushort ItemSet4Item { get => BitConverter.ToUInt16(Data, 0x11C); set => BitConverter.GetBytes(value).CopyTo(Data, 0x11C); }
|
||||
public ushort ItemSet4Count { get => BitConverter.ToUInt16(Data, 0x11E); set => BitConverter.GetBytes(value).CopyTo(Data, 0x11E); }
|
||||
public ushort ItemSet5Item { get => BitConverter.ToUInt16(Data, 0x120); set => BitConverter.GetBytes(value).CopyTo(Data, 0x120); } // struct union overlaps OT Name data, beware!
|
||||
public ushort ItemSet5Count { get => BitConverter.ToUInt16(Data, 0x122); set => BitConverter.GetBytes(value).CopyTo(Data, 0x122); }
|
||||
public ushort ItemSet6Item { get => BitConverter.ToUInt16(Data, 0x124); set => BitConverter.GetBytes(value).CopyTo(Data, 0x124); }
|
||||
public ushort ItemSet6Count { get => BitConverter.ToUInt16(Data, 0x126); set => BitConverter.GetBytes(value).CopyTo(Data, 0x126); }
|
||||
public override int ItemID { get => ReadUInt16LittleEndian(Data.AsSpan(0x110)); set => WriteUInt16LittleEndian(Data.AsSpan(0x110), (ushort)value); }
|
||||
public ushort ItemIDCount { get => ReadUInt16LittleEndian(Data.AsSpan(0x112)); set => WriteUInt16LittleEndian(Data.AsSpan(0x112), value); }
|
||||
public ushort ItemSet2Item { get => ReadUInt16LittleEndian(Data.AsSpan(0x114)); set => WriteUInt16LittleEndian(Data.AsSpan(0x114), value); }
|
||||
public ushort ItemSet2Count { get => ReadUInt16LittleEndian(Data.AsSpan(0x116)); set => WriteUInt16LittleEndian(Data.AsSpan(0x116), value); }
|
||||
public ushort ItemSet3Item { get => ReadUInt16LittleEndian(Data.AsSpan(0x118)); set => WriteUInt16LittleEndian(Data.AsSpan(0x118), value); }
|
||||
public ushort ItemSet3Count { get => ReadUInt16LittleEndian(Data.AsSpan(0x11A)); set => WriteUInt16LittleEndian(Data.AsSpan(0x11A), value); }
|
||||
public ushort ItemSet4Item { get => ReadUInt16LittleEndian(Data.AsSpan(0x11C)); set => WriteUInt16LittleEndian(Data.AsSpan(0x11C), value); }
|
||||
public ushort ItemSet4Count { get => ReadUInt16LittleEndian(Data.AsSpan(0x11E)); set => WriteUInt16LittleEndian(Data.AsSpan(0x11E), value); }
|
||||
public ushort ItemSet5Item { get => ReadUInt16LittleEndian(Data.AsSpan(0x120)); set => WriteUInt16LittleEndian(Data.AsSpan(0x120), value); } // struct union overlaps OT Name data, beware!
|
||||
public ushort ItemSet5Count { get => ReadUInt16LittleEndian(Data.AsSpan(0x122)); set => WriteUInt16LittleEndian(Data.AsSpan(0x122), value); }
|
||||
public ushort ItemSet6Item { get => ReadUInt16LittleEndian(Data.AsSpan(0x124)); set => WriteUInt16LittleEndian(Data.AsSpan(0x124), value); }
|
||||
public ushort ItemSet6Count { get => ReadUInt16LittleEndian(Data.AsSpan(0x126)); set => WriteUInt16LittleEndian(Data.AsSpan(0x126), value); }
|
||||
|
||||
public override int Gender { get; set; }
|
||||
public override int Form { get; set; }
|
||||
|
@ -89,8 +90,8 @@ namespace PKHeX.Core
|
|||
|
||||
public override string OT_Name
|
||||
{
|
||||
get => StringConverter.GetString7b(Data, 0x120, 0x1A);
|
||||
set => StringConverter.SetString7b(value, 12, 13).CopyTo(Data, 0x120 + 0xB6); // careful with length
|
||||
get => StringConverter8.GetString(Data.AsSpan(0x120, 0x1A));
|
||||
set => StringConverter8.SetString(Data.AsSpan(0x120, 0x1A), value.AsSpan(), 12, StringConverterOption.ClearZero);
|
||||
}
|
||||
|
||||
public LanguageID LanguageReceived
|
||||
|
|
|
@ -1,4 +1,6 @@
|
|||
using System.Collections.Generic;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using static System.Buffers.Binary.BinaryPrimitives;
|
||||
|
||||
namespace PKHeX.Core
|
||||
{
|
||||
|
@ -25,12 +27,12 @@ namespace PKHeX.Core
|
|||
|
||||
public override bool Valid => ChecksumValid || (Sanity == 0 && Species <= MaxSpeciesID);
|
||||
|
||||
public static BK4 ReadUnshuffle(byte[] data)
|
||||
public static BK4 ReadUnshuffle(ReadOnlySpan<byte> data)
|
||||
{
|
||||
var PID = BigEndian.ToUInt32(data, 0);
|
||||
var PID = ReadUInt32BigEndian(data);
|
||||
uint sv = ((PID & 0x3E000) >> 0xD) % 24;
|
||||
var Data = PokeCrypto.ShuffleArray(data, sv, PokeCrypto.SIZE_4BLOCK);
|
||||
var result = new BK4(Data);
|
||||
var unshuffled = PokeCrypto.ShuffleArray(data, sv, PokeCrypto.SIZE_4BLOCK);
|
||||
var result = new BK4(unshuffled);
|
||||
result.RefreshChecksum();
|
||||
return result;
|
||||
}
|
||||
|
@ -45,24 +47,21 @@ namespace PKHeX.Core
|
|||
|
||||
public override PKM Clone() => new BK4((byte[])Data.Clone());
|
||||
|
||||
public string GetString(int offset, int count) => StringConverter4.GetBEString4(Data, offset, count);
|
||||
private static byte[] SetString(string value, int maxLength) => StringConverter4.SetBEString4(value, maxLength);
|
||||
|
||||
// Structure
|
||||
public override uint PID { get => BigEndian.ToUInt32(Data, 0x00); set => BigEndian.GetBytes(value).CopyTo(Data, 0x00); }
|
||||
public override ushort Sanity { get => BigEndian.ToUInt16(Data, 0x04); set => BigEndian.GetBytes(value).CopyTo(Data, 0x04); }
|
||||
public override ushort Checksum { get => BigEndian.ToUInt16(Data, 0x06); set => BigEndian.GetBytes(value).CopyTo(Data, 0x06); }
|
||||
public override uint PID { get => ReadUInt16BigEndian(Data.AsSpan(0x00)); set => WriteUInt32BigEndian(Data.AsSpan(0x00), value); }
|
||||
public override ushort Sanity { get => ReadUInt16BigEndian(Data.AsSpan(0x04)); set => WriteUInt32BigEndian(Data.AsSpan(0x04), value); }
|
||||
public override ushort Checksum { get => ReadUInt16BigEndian(Data.AsSpan(0x06)); set => WriteUInt32BigEndian(Data.AsSpan(0x06), value); }
|
||||
|
||||
#region Block A
|
||||
public override int Species { get => BigEndian.ToUInt16(Data, 0x08); set => BigEndian.GetBytes((ushort)value).CopyTo(Data, 0x08); }
|
||||
public override int HeldItem { get => BigEndian.ToUInt16(Data, 0x0A); set => BigEndian.GetBytes((ushort)value).CopyTo(Data, 0x0A); }
|
||||
public override int SID { get => BigEndian.ToUInt16(Data, 0x0C); set => BigEndian.GetBytes((ushort)value).CopyTo(Data, 0x0C); }
|
||||
public override int TID { get => BigEndian.ToUInt16(Data, 0x0E); set => BigEndian.GetBytes((ushort)value).CopyTo(Data, 0x0E); }
|
||||
public override int Species { get => ReadUInt16BigEndian(Data.AsSpan(0x08)); set => WriteUInt16BigEndian(Data.AsSpan(0x08), (ushort)value); }
|
||||
public override int HeldItem { get => ReadUInt16BigEndian(Data.AsSpan(0x0A)); set => WriteUInt16BigEndian(Data.AsSpan(0x0A), (ushort)value); }
|
||||
public override int SID { get => ReadUInt16BigEndian(Data.AsSpan(0x0C)); set => WriteUInt16BigEndian(Data.AsSpan(0x0C), (ushort)value); }
|
||||
public override int TID { get => ReadUInt16BigEndian(Data.AsSpan(0x0E)); set => WriteUInt16BigEndian(Data.AsSpan(0x0E), (ushort)value); }
|
||||
|
||||
public override uint EXP
|
||||
{
|
||||
get => BigEndian.ToUInt32(Data, 0x10);
|
||||
set => BigEndian.GetBytes(value).CopyTo(Data, 0x10);
|
||||
get => ReadUInt32BigEndian(Data.AsSpan(0x10));
|
||||
set => WriteUInt32BigEndian(Data.AsSpan(0x10), value);
|
||||
}
|
||||
|
||||
public override int OT_Friendship { get => Data[0x14]; set => Data[0x14] = (byte)value; }
|
||||
|
@ -121,10 +120,10 @@ namespace PKHeX.Core
|
|||
#endregion
|
||||
|
||||
#region Block B
|
||||
public override int Move1 { get => BigEndian.ToUInt16(Data, 0x28); set => BigEndian.GetBytes((ushort)value).CopyTo(Data, 0x28); }
|
||||
public override int Move2 { get => BigEndian.ToUInt16(Data, 0x2A); set => BigEndian.GetBytes((ushort)value).CopyTo(Data, 0x2A); }
|
||||
public override int Move3 { get => BigEndian.ToUInt16(Data, 0x2C); set => BigEndian.GetBytes((ushort)value).CopyTo(Data, 0x2C); }
|
||||
public override int Move4 { get => BigEndian.ToUInt16(Data, 0x2E); set => BigEndian.GetBytes((ushort)value).CopyTo(Data, 0x2E); }
|
||||
public override int Move1 { get => ReadUInt16BigEndian(Data.AsSpan(0x28)); set => WriteUInt16BigEndian(Data.AsSpan(0x28), (ushort)value); }
|
||||
public override int Move2 { get => ReadUInt16BigEndian(Data.AsSpan(0x2A)); set => WriteUInt16BigEndian(Data.AsSpan(0x2A), (ushort)value); }
|
||||
public override int Move3 { get => ReadUInt16BigEndian(Data.AsSpan(0x2C)); set => WriteUInt16BigEndian(Data.AsSpan(0x2C), (ushort)value); }
|
||||
public override int Move4 { get => ReadUInt16BigEndian(Data.AsSpan(0x2E)); set => WriteUInt16BigEndian(Data.AsSpan(0x2E), (ushort)value); }
|
||||
public override int Move1_PP { get => Data[0x30]; set => Data[0x30] = (byte)value; }
|
||||
public override int Move2_PP { get => Data[0x31]; set => Data[0x31] = (byte)value; }
|
||||
public override int Move3_PP { get => Data[0x32]; set => Data[0x32] = (byte)value; }
|
||||
|
@ -133,7 +132,7 @@ namespace PKHeX.Core
|
|||
public override int Move2_PPUps { get => Data[0x35]; set => Data[0x35] = (byte)value; }
|
||||
public override int Move3_PPUps { get => Data[0x36]; set => Data[0x36] = (byte)value; }
|
||||
public override int Move4_PPUps { get => Data[0x37]; set => Data[0x37] = (byte)value; }
|
||||
private uint IV32 { get => BigEndian.ToUInt32(Data, 0x38); set => BigEndian.GetBytes(value).CopyTo(Data, 0x38); }
|
||||
private uint IV32 { get => ReadUInt32BigEndian(Data.AsSpan(0x38)); set => WriteUInt32BigEndian(Data.AsSpan(0x38), value); }
|
||||
public override int IV_SPD { get => (int)(IV32 >> 02) & 0x1F; set => IV32 = ((IV32 & ~(0x1Fu << 02)) | ((value > 31 ? 31u : (uint)value) << 02)); }
|
||||
public override int IV_SPA { get => (int)(IV32 >> 07) & 0x1F; set => IV32 = ((IV32 & ~(0x1Fu << 07)) | ((value > 31 ? 31u : (uint)value) << 07)); }
|
||||
public override int IV_SPE { get => (int)(IV32 >> 12) & 0x1F; set => IV32 = ((IV32 & ~(0x1Fu << 12)) | ((value > 31 ? 31u : (uint)value) << 12)); }
|
||||
|
@ -184,11 +183,23 @@ namespace PKHeX.Core
|
|||
public override int Gender { get => (Data[0x40] >> 5) & 0x3; set => Data[0x40] = (byte)((Data[0x40] & ~0x60) | ((value & 3) << 5)); }
|
||||
public override int Form { get => Data[0x40] & 0x1F; set => Data[0x40] = (byte)((Data[0x40] & ~0x1F) | (value & 0x1F)); }
|
||||
public override int ShinyLeaf { get => Data[0x41]; set => Data[0x41] = (byte)value; }
|
||||
// 0x43-0x47 Unused
|
||||
|
||||
// 0x42-0x43 Unused
|
||||
public override ushort Egg_LocationExtended
|
||||
{
|
||||
get => ReadUInt16BigEndian(Data.AsSpan(0x44));
|
||||
set => WriteUInt16BigEndian(Data.AsSpan(0x44), value);
|
||||
}
|
||||
|
||||
public override ushort Met_LocationExtended
|
||||
{
|
||||
get => ReadUInt16BigEndian(Data.AsSpan(0x46));
|
||||
set => WriteUInt16BigEndian(Data.AsSpan(0x46), value);
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region Block C
|
||||
public override string Nickname { get => GetString(0x48, 20); set => SetString(value, 10).CopyTo(Data, 0x48); }
|
||||
public override string Nickname { get => StringConverter4GC.GetString(Nickname_Trash); set => StringConverter4GC.SetString(Nickname_Trash, value.AsSpan(), 10, StringConverterOption.None); }
|
||||
// 0x5E unused
|
||||
public override int Version { get => Data[0x5F]; set => Data[0x5F] = (byte)value; }
|
||||
private byte RIB8 { get => Data[0x60]; set => Data[0x60] = value; } // Sinnoh 3
|
||||
|
@ -231,7 +242,7 @@ namespace PKHeX.Core
|
|||
#endregion
|
||||
|
||||
#region Block D
|
||||
public override string OT_Name { get => GetString(0x68, 14); set => SetString(value, 7).CopyTo(Data, 0x68); }
|
||||
public override string OT_Name { get => StringConverter4GC.GetString(OT_Trash); set => StringConverter4GC.SetString(OT_Trash, value.AsSpan(), 7, StringConverterOption.None); }
|
||||
public override int Egg_Year { get => Data[0x78]; set => Data[0x78] = (byte)value; }
|
||||
public override int Egg_Month { get => Data[0x79]; set => Data[0x79] = (byte)value; }
|
||||
public override int Egg_Day { get => Data[0x7A]; set => Data[0x7A] = (byte)value; }
|
||||
|
@ -239,66 +250,15 @@ namespace PKHeX.Core
|
|||
public override int Met_Month { get => Data[0x7C]; set => Data[0x7C] = (byte)value; }
|
||||
public override int Met_Day { get => Data[0x7D]; set => Data[0x7D] = (byte)value; }
|
||||
|
||||
public override int Egg_Location
|
||||
public override ushort Egg_LocationDP
|
||||
{
|
||||
get
|
||||
{
|
||||
ushort hgssloc = BigEndian.ToUInt16(Data, 0x44);
|
||||
if (hgssloc != 0)
|
||||
return hgssloc;
|
||||
return BigEndian.ToUInt16(Data, 0x7E);
|
||||
}
|
||||
set
|
||||
{
|
||||
if (value == 0)
|
||||
{
|
||||
BigEndian.GetBytes((ushort)0).CopyTo(Data, 0x44);
|
||||
BigEndian.GetBytes((ushort)0).CopyTo(Data, 0x7E);
|
||||
}
|
||||
else if (Locations.IsPtHGSSLocation(value) || Locations.IsPtHGSSLocationEgg(value))
|
||||
{
|
||||
// Met location not in DP, set to Faraway Place
|
||||
BigEndian.GetBytes((ushort)value).CopyTo(Data, 0x44);
|
||||
BigEndian.GetBytes((ushort)0xBBA).CopyTo(Data, 0x7E);
|
||||
}
|
||||
else
|
||||
{
|
||||
int pthgss = PtHGSS ? value : 0; // only set to PtHGSS loc if encountered in game
|
||||
BigEndian.GetBytes((ushort)pthgss).CopyTo(Data, 0x44);
|
||||
BigEndian.GetBytes((ushort)value).CopyTo(Data, 0x7E);
|
||||
}
|
||||
}
|
||||
get => ReadUInt16BigEndian(Data.AsSpan(0x7E));
|
||||
set => WriteUInt16BigEndian(Data.AsSpan(0x7E), value);
|
||||
}
|
||||
|
||||
public override int Met_Location
|
||||
public override ushort Met_LocationDP
|
||||
{
|
||||
get
|
||||
{
|
||||
ushort hgssloc = BigEndian.ToUInt16(Data, 0x46);
|
||||
if (hgssloc != 0)
|
||||
return hgssloc;
|
||||
return BigEndian.ToUInt16(Data, 0x80);
|
||||
}
|
||||
set
|
||||
{
|
||||
if (value == 0)
|
||||
{
|
||||
BigEndian.GetBytes((ushort)0).CopyTo(Data, 0x46);
|
||||
BigEndian.GetBytes((ushort)0).CopyTo(Data, 0x80);
|
||||
}
|
||||
else if (Locations.IsPtHGSSLocation(value) || Locations.IsPtHGSSLocationEgg(value))
|
||||
{
|
||||
// Met location not in DP, set to Faraway Place
|
||||
BigEndian.GetBytes((ushort)value).CopyTo(Data, 0x46);
|
||||
BigEndian.GetBytes((ushort)0xBBA).CopyTo(Data, 0x80);
|
||||
}
|
||||
else
|
||||
{
|
||||
int pthgss = PtHGSS ? value : 0; // only set to PtHGSS loc if encountered in game
|
||||
BigEndian.GetBytes((ushort)pthgss).CopyTo(Data, 0x46);
|
||||
BigEndian.GetBytes((ushort)value).CopyTo(Data, 0x80);
|
||||
}
|
||||
}
|
||||
get => ReadUInt16BigEndian(Data.AsSpan(0x80));
|
||||
set => WriteUInt16BigEndian(Data.AsSpan(0x80), value);
|
||||
}
|
||||
|
||||
private byte PKRS { get => Data[0x82]; set => Data[0x82] = value; }
|
||||
|
@ -326,9 +286,10 @@ namespace PKHeX.Core
|
|||
// Methods
|
||||
protected override ushort CalculateChecksum()
|
||||
{
|
||||
ReadOnlySpan<byte> arr = Data.AsSpan();
|
||||
ushort chk = 0;
|
||||
for (int i = 8; i < PokeCrypto.SIZE_4STORED; i += 2)
|
||||
chk += BigEndian.ToUInt16(Data, i);
|
||||
chk += ReadUInt16BigEndian(arr[i..]);
|
||||
return chk;
|
||||
}
|
||||
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using static System.Buffers.Binary.BinaryPrimitives;
|
||||
|
||||
namespace PKHeX.Core
|
||||
{
|
||||
|
@ -27,38 +28,30 @@ namespace PKHeX.Core
|
|||
public CK3() : this(new byte[PokeCrypto.SIZE_3CSTORED]) { }
|
||||
public override PKM Clone() => new CK3((byte[])Data.Clone());
|
||||
|
||||
private string GetString(int offset, int count) => StringConverter3.GetBEString3(Data, offset, count);
|
||||
private static byte[] SetString(string value, int maxLength) => StringConverter3.SetBEString3(value, maxLength);
|
||||
|
||||
// Trash Bytes
|
||||
public override Span<byte> Nickname_Trash { get => Data.AsSpan(0x2E, 20); set { if (value.Length == 20) value.CopyTo(Data.AsSpan(0x2E)); } }
|
||||
public override Span<byte> OT_Trash { get => Data.AsSpan(0x18, 20); set { if (value.Length == 20) value.CopyTo(Data.AsSpan(0x18)); } }
|
||||
public override Span<byte> OT_Trash => Data.AsSpan(0x18, 22);
|
||||
public override Span<byte> Nickname_Trash => Data.AsSpan(0x2E, 22);
|
||||
public Span<byte> NicknameCopy_Trash => Data.AsSpan(0x44, 22);
|
||||
|
||||
// Future Attributes
|
||||
|
||||
// Silly Attributes
|
||||
public override ushort Sanity { get => 0; set { } } // valid flag set in pkm structure.
|
||||
public override ushort Checksum { get => Checksums.CRC16_CCITT(Data); set { } } // totally false, just a way to get a 'random' ident for the pkm.
|
||||
public override bool ChecksumValid => true;
|
||||
public override bool Valid { get => !Invalid; set => Invalid = !value; }
|
||||
|
||||
public override int Species { get => SpeciesConverter.GetG4Species(BigEndian.ToUInt16(Data, 0x00)); set => BigEndian.GetBytes((ushort)SpeciesConverter.GetG3Species(value)).CopyTo(Data, 0x00); }
|
||||
public override int Species { get => SpeciesConverter.GetG4Species(ReadUInt16BigEndian(Data.AsSpan(0x00))); set => WriteUInt16BigEndian(Data, (ushort)SpeciesConverter.GetG3Species(value)); }
|
||||
// 02-04 unused
|
||||
public override uint PID { get => BigEndian.ToUInt32(Data, 0x04); set => BigEndian.GetBytes(value).CopyTo(Data, 0x04); }
|
||||
public override uint PID { get => ReadUInt32BigEndian(Data.AsSpan(0x04)); set => WriteUInt32BigEndian(Data.AsSpan(0x04), value); }
|
||||
public override int Version { get => GetGBAVersionID(Data[0x08]); set => Data[0x08] = GetGCVersionID(value); }
|
||||
public int CurrentRegion { get => Data[0x09]; set => Data[0x09] = (byte)value; }
|
||||
public int OriginalRegion { get => Data[0x0A]; set => Data[0x0A] = (byte)value; }
|
||||
public override int Language { get => Core.Language.GetMainLangIDfromGC(Data[0x0B]); set => Data[0x0B] = Core.Language.GetGCLangIDfromMain((byte)value); }
|
||||
public override int Met_Location { get => BigEndian.ToUInt16(Data, 0x0C); set => BigEndian.GetBytes((ushort)value).CopyTo(Data, 0x0C); }
|
||||
public override int Met_Location { get => ReadUInt16BigEndian(Data.AsSpan(0x0C)); set => WriteUInt16BigEndian(Data.AsSpan(0x0C), (ushort)value); }
|
||||
public override int Met_Level { get => Data[0x0E]; set => Data[0x0E] = (byte)value; }
|
||||
public override int Ball { get => Data[0x0F]; set => Data[0x0F] = (byte)value; }
|
||||
public override int OT_Gender { get => Data[0x10]; set => Data[0x10] = (byte)value; }
|
||||
public override int SID { get => BigEndian.ToUInt16(Data, 0x14); set => BigEndian.GetBytes((ushort)value).CopyTo(Data, 0x14); }
|
||||
public override int TID { get => BigEndian.ToUInt16(Data, 0x16); set => BigEndian.GetBytes((ushort)value).CopyTo(Data, 0x16); }
|
||||
public override string OT_Name { get => GetString(0x18, 20); set => SetString(value, 10).CopyTo(Data, 0x18); } // +2 terminator
|
||||
public override string Nickname { get => GetString(0x2E, 20); set { SetString(value, 10).CopyTo(Data, 0x2E); NicknameCopy = value; } } // +2 terminator
|
||||
public string NicknameCopy { get => GetString(0x44, 20); set => SetString(value, 10).CopyTo(Data, 0x44); } // +2 terminator
|
||||
public override uint EXP { get => BigEndian.ToUInt32(Data, 0x5C); set => BigEndian.GetBytes(value).CopyTo(Data, 0x5C); }
|
||||
public override int SID { get => ReadUInt16BigEndian(Data.AsSpan(0x14)); set => WriteUInt16BigEndian(Data.AsSpan(0x14), (ushort)value); }
|
||||
public override int TID { get => ReadUInt16BigEndian(Data.AsSpan(0x16)); set => WriteUInt16BigEndian(Data.AsSpan(0x16), (ushort)value); }
|
||||
public override string OT_Name { get => StringConverter3GC.GetString(OT_Trash); set => StringConverter3GC.SetString(OT_Trash, value.AsSpan(), 10, StringConverterOption.None); }
|
||||
public override string Nickname { get => StringConverter3GC.GetString(Nickname_Trash); set { StringConverter3GC.SetString(Nickname_Trash, value.AsSpan(), 10, StringConverterOption.None); NicknameCopy = value; } }
|
||||
public string NicknameCopy { get => StringConverter3GC.GetString(NicknameCopy_Trash); set => StringConverter3GC.SetString(NicknameCopy_Trash, value.AsSpan(), 10, StringConverterOption.None); }
|
||||
public override uint EXP { get => ReadUInt32BigEndian(Data.AsSpan(0x5C)); set => WriteUInt32BigEndian(Data.AsSpan(0x5C), value); }
|
||||
public override int Stat_Level { get => Data[0x60]; set => Data[0x60] = (byte)value; }
|
||||
|
||||
// 0x64-0x77 are battle/status related
|
||||
|
@ -66,80 +59,80 @@ namespace PKHeX.Core
|
|||
// Not that the program cares
|
||||
|
||||
// Moves
|
||||
public override int Move1 { get => BigEndian.ToUInt16(Data, 0x78); set => BigEndian.GetBytes((ushort)value).CopyTo(Data, 0x78); }
|
||||
public override int Move1 { get => ReadUInt16BigEndian(Data.AsSpan(0x78)); set => WriteUInt16BigEndian(Data.AsSpan(0x78), (ushort)value); }
|
||||
public override int Move1_PP { get => Data[0x7A]; set => Data[0x7A] = (byte)value; }
|
||||
public override int Move1_PPUps { get => Data[0x7B]; set => Data[0x7B] = (byte)value; }
|
||||
public override int Move2 { get => BigEndian.ToUInt16(Data, 0x7C); set => BigEndian.GetBytes((ushort)value).CopyTo(Data, 0x7C); }
|
||||
public override int Move2 { get => ReadUInt16BigEndian(Data.AsSpan(0x7C)); set => WriteUInt16BigEndian(Data.AsSpan(0x7C), (ushort)value); }
|
||||
public override int Move2_PP { get => Data[0x7E]; set => Data[0x7E] = (byte)value; }
|
||||
public override int Move2_PPUps { get => Data[0x7F]; set => Data[0x7F] = (byte)value; }
|
||||
public override int Move3 { get => BigEndian.ToUInt16(Data, 0x80); set => BigEndian.GetBytes((ushort)value).CopyTo(Data, 0x80); }
|
||||
public override int Move3 { get => ReadUInt16BigEndian(Data.AsSpan(0x80)); set => WriteUInt16BigEndian(Data.AsSpan(0x80), (ushort)value); }
|
||||
public override int Move3_PP { get => Data[0x82]; set => Data[0x82] = (byte)value; }
|
||||
public override int Move3_PPUps { get => Data[0x83]; set => Data[0x83] = (byte)value; }
|
||||
public override int Move4 { get => BigEndian.ToUInt16(Data, 0x84); set => BigEndian.GetBytes((ushort)value).CopyTo(Data, 0x84); }
|
||||
public override int Move4 { get => ReadUInt16BigEndian(Data.AsSpan(0x84)); set => WriteUInt16BigEndian(Data.AsSpan(0x84), (ushort)value); }
|
||||
public override int Move4_PP { get => Data[0x86]; set => Data[0x86] = (byte)value; }
|
||||
public override int Move4_PPUps { get => Data[0x87]; set => Data[0x87] = (byte)value; }
|
||||
|
||||
public override int SpriteItem => ItemConverter.GetItemFuture3((ushort)HeldItem);
|
||||
public override int HeldItem { get => BigEndian.ToUInt16(Data, 0x88); set => BigEndian.GetBytes((ushort)value).CopyTo(Data, 0x88); }
|
||||
public override int HeldItem { get => ReadUInt16BigEndian(Data.AsSpan(0x88)); set => WriteUInt16BigEndian(Data.AsSpan(0x88), (ushort)value); }
|
||||
|
||||
// More party stats
|
||||
public override int Stat_HPCurrent { get => BigEndian.ToUInt16(Data, 0x8A); set => BigEndian.GetBytes((ushort)value).CopyTo(Data, 0x8A); }
|
||||
public override int Stat_HPMax { get => BigEndian.ToUInt16(Data, 0x8C); set => BigEndian.GetBytes((ushort)value).CopyTo(Data, 0x8C); }
|
||||
public override int Stat_ATK { get => BigEndian.ToUInt16(Data, 0x8E); set => BigEndian.GetBytes((ushort)value).CopyTo(Data, 0x8E); }
|
||||
public override int Stat_DEF { get => BigEndian.ToUInt16(Data, 0x90); set => BigEndian.GetBytes((ushort)value).CopyTo(Data, 0x90); }
|
||||
public override int Stat_SPA { get => BigEndian.ToUInt16(Data, 0x92); set => BigEndian.GetBytes((ushort)value).CopyTo(Data, 0x92); }
|
||||
public override int Stat_SPD { get => BigEndian.ToUInt16(Data, 0x94); set => BigEndian.GetBytes((ushort)value).CopyTo(Data, 0x94); }
|
||||
public override int Stat_SPE { get => BigEndian.ToUInt16(Data, 0x96); set => BigEndian.GetBytes((ushort)value).CopyTo(Data, 0x96); }
|
||||
public override int Stat_HPCurrent { get => ReadUInt16BigEndian(Data.AsSpan(0x8A)); set => WriteUInt16BigEndian(Data.AsSpan(0x8A), (ushort)value); }
|
||||
public override int Stat_HPMax { get => ReadUInt16BigEndian(Data.AsSpan(0x8C)); set => WriteUInt16BigEndian(Data.AsSpan(0x8C), (ushort)value); }
|
||||
public override int Stat_ATK { get => ReadUInt16BigEndian(Data.AsSpan(0x8E)); set => WriteUInt16BigEndian(Data.AsSpan(0x8E), (ushort)value); }
|
||||
public override int Stat_DEF { get => ReadUInt16BigEndian(Data.AsSpan(0x90)); set => WriteUInt16BigEndian(Data.AsSpan(0x90), (ushort)value); }
|
||||
public override int Stat_SPA { get => ReadUInt16BigEndian(Data.AsSpan(0x92)); set => WriteUInt16BigEndian(Data.AsSpan(0x92), (ushort)value); }
|
||||
public override int Stat_SPD { get => ReadUInt16BigEndian(Data.AsSpan(0x94)); set => WriteUInt16BigEndian(Data.AsSpan(0x94), (ushort)value); }
|
||||
public override int Stat_SPE { get => ReadUInt16BigEndian(Data.AsSpan(0x96)); set => WriteUInt16BigEndian(Data.AsSpan(0x96), (ushort)value); }
|
||||
|
||||
// EVs
|
||||
public override int EV_HP {
|
||||
get => Math.Min(byte.MaxValue, BigEndian.ToUInt16(Data, 0x98));
|
||||
set => BigEndian.GetBytes((ushort)(value & 0xFF)).CopyTo(Data, 0x98); }
|
||||
get => Math.Min(byte.MaxValue, ReadUInt16BigEndian(Data.AsSpan(0x98)));
|
||||
set => WriteUInt16BigEndian(Data.AsSpan(0x98), (ushort)(value & 0xFF)); }
|
||||
|
||||
public override int EV_ATK {
|
||||
get => Math.Min(byte.MaxValue, BigEndian.ToUInt16(Data, 0x9A));
|
||||
set => BigEndian.GetBytes((ushort)(value & 0xFF)).CopyTo(Data, 0x9A); }
|
||||
get => Math.Min(byte.MaxValue, ReadUInt16BigEndian(Data.AsSpan(0x9A)));
|
||||
set => WriteUInt16BigEndian(Data.AsSpan(0x9A), (ushort)(value & 0xFF)); }
|
||||
|
||||
public override int EV_DEF {
|
||||
get => Math.Min(byte.MaxValue, BigEndian.ToUInt16(Data, 0x9C));
|
||||
set => BigEndian.GetBytes((ushort)(value & 0xFF)).CopyTo(Data, 0x9C); }
|
||||
get => Math.Min(byte.MaxValue, ReadUInt16BigEndian(Data.AsSpan(0x9C)));
|
||||
set => WriteUInt16BigEndian(Data.AsSpan(0x9C), (ushort)(value & 0xFF)); }
|
||||
|
||||
public override int EV_SPA {
|
||||
get => Math.Min(byte.MaxValue, BigEndian.ToUInt16(Data, 0x9E));
|
||||
set => BigEndian.GetBytes((ushort)(value & 0xFF)).CopyTo(Data, 0x9E); }
|
||||
get => Math.Min(byte.MaxValue, ReadUInt16BigEndian(Data.AsSpan(0x9E)));
|
||||
set => WriteUInt16BigEndian(Data.AsSpan(0x9E), (ushort)(value & 0xFF)); }
|
||||
|
||||
public override int EV_SPD {
|
||||
get => Math.Min(byte.MaxValue, BigEndian.ToUInt16(Data, 0xA0));
|
||||
set => BigEndian.GetBytes((ushort)(value & 0xFF)).CopyTo(Data, 0xA0); }
|
||||
get => Math.Min(byte.MaxValue, ReadUInt16BigEndian(Data.AsSpan(0xA0)));
|
||||
set => WriteUInt16BigEndian(Data.AsSpan(0xA0), (ushort)(value & 0xFF)); }
|
||||
|
||||
public override int EV_SPE {
|
||||
get => Math.Min(byte.MaxValue, BigEndian.ToUInt16(Data, 0xA2));
|
||||
set => BigEndian.GetBytes((ushort)(value & 0xFF)).CopyTo(Data, 0xA2); }
|
||||
get => Math.Min(byte.MaxValue, ReadUInt16BigEndian(Data.AsSpan(0xA2)));
|
||||
set => WriteUInt16BigEndian(Data.AsSpan(0xA2), (ushort)(value & 0xFF)); }
|
||||
|
||||
// IVs
|
||||
public override int IV_HP {
|
||||
get => Math.Min((ushort)31, BigEndian.ToUInt16(Data, 0xA4));
|
||||
set => BigEndian.GetBytes((ushort)(value & 0x1F)).CopyTo(Data, 0xA4); }
|
||||
get => Math.Min((ushort)31, ReadUInt16BigEndian(Data.AsSpan(0xA4)));
|
||||
set => WriteUInt16BigEndian(Data.AsSpan(0xA4), (ushort)(value & 0x1F)); }
|
||||
|
||||
public override int IV_ATK {
|
||||
get => Math.Min((ushort)31, BigEndian.ToUInt16(Data, 0xA6));
|
||||
set => BigEndian.GetBytes((ushort)(value & 0x1F)).CopyTo(Data, 0xA6); }
|
||||
get => Math.Min((ushort)31, ReadUInt16BigEndian(Data.AsSpan(0xA6)));
|
||||
set => WriteUInt16BigEndian(Data.AsSpan(0xA6), (ushort)(value & 0x1F)); }
|
||||
|
||||
public override int IV_DEF {
|
||||
get => Math.Min((ushort)31, BigEndian.ToUInt16(Data, 0xA8));
|
||||
set => BigEndian.GetBytes((ushort)(value & 0x1F)).CopyTo(Data, 0xA8); }
|
||||
get => Math.Min((ushort)31, ReadUInt16BigEndian(Data.AsSpan(0xA8)));
|
||||
set => WriteUInt16BigEndian(Data.AsSpan(0xA8), (ushort)(value & 0x1F)); }
|
||||
|
||||
public override int IV_SPA {
|
||||
get => Math.Min((ushort)31, BigEndian.ToUInt16(Data, 0xAA));
|
||||
set => BigEndian.GetBytes((ushort)(value & 0x1F)).CopyTo(Data, 0xAA); }
|
||||
get => Math.Min((ushort)31, ReadUInt16BigEndian(Data.AsSpan(0xAA)));
|
||||
set => WriteUInt16BigEndian(Data.AsSpan(0xAA), (ushort)(value & 0x1F)); }
|
||||
|
||||
public override int IV_SPD {
|
||||
get => Math.Min((ushort)31, BigEndian.ToUInt16(Data, 0xAC));
|
||||
set => BigEndian.GetBytes((ushort)(value & 0x1F)).CopyTo(Data, 0xAC); }
|
||||
get => Math.Min((ushort)31, ReadUInt16BigEndian(Data.AsSpan(0xAC)));
|
||||
set => WriteUInt16BigEndian(Data.AsSpan(0xAC), (ushort)(value & 0x1F)); }
|
||||
|
||||
public override int IV_SPE {
|
||||
get => Math.Min((ushort)31, BigEndian.ToUInt16(Data, 0xAE));
|
||||
set => BigEndian.GetBytes((ushort)(value & 0x1F)).CopyTo(Data, 0xAE); }
|
||||
get => Math.Min((ushort)31, ReadUInt16BigEndian(Data.AsSpan(0xAE)));
|
||||
set => WriteUInt16BigEndian(Data.AsSpan(0xAE), (ushort)(value & 0x1F)); }
|
||||
|
||||
public override int OT_Friendship { get => Data[0xB0]; set => Data[0xB0] = (byte)value; }
|
||||
|
||||
|
@ -178,15 +171,15 @@ namespace PKHeX.Core
|
|||
public override int PKRS_Strain { get => Data[0xCA] & 0xF; set => Data[0xCA] = (byte)(value & 0xF); }
|
||||
public override bool IsEgg { get => Data[0xCB] == 1; set => Data[0xCB] = value ? (byte)1 : (byte)0; }
|
||||
public override bool AbilityBit { get => Data[0xCC] == 1; set => Data[0xCC] = value ? (byte)1 : (byte)0; }
|
||||
private bool Invalid { get => Data[0xCD] != 0; set => Data[0xCD] = value ? (byte)1 : (byte)0; }
|
||||
public override bool Valid { get => Data[0xCD] == 0; set => Data[0xCD] = !value ? (byte)1 : (byte)0; }
|
||||
|
||||
public override int MarkValue { get => SwapBits(Data[0xCF], 1, 2); protected set => Data[0xCF] = (byte)SwapBits(value, 1, 2); }
|
||||
public override int PKRS_Days { get => Math.Max((sbyte)Data[0xD0], (sbyte)0); set => Data[0xD0] = (byte)(value == 0 ? 0xFF : value & 0xF); }
|
||||
|
||||
public int PartySlot { get => Data[0xD7]; set => Data[0xD7] = (byte)value; } // or not; only really used while in party?
|
||||
public int ShadowID { get => BigEndian.ToUInt16(Data, 0xD8); set => BigEndian.GetBytes((ushort)value).CopyTo(Data, 0xD8); }
|
||||
public int Purification { get => BigEndian.ToInt32(Data, 0xDC); set => BigEndian.GetBytes(value).CopyTo(Data, 0xDC); }
|
||||
public uint EXP_Shadow { get => BigEndian.ToUInt32(Data, 0xC0); set => BigEndian.GetBytes(value).CopyTo(Data, 0xC0); }
|
||||
public int ShadowID { get => ReadUInt16BigEndian(Data.AsSpan(0xD8)); set => WriteUInt16BigEndian(Data.AsSpan(0xD8), (ushort)value); }
|
||||
public int Purification { get => ReadInt32BigEndian(Data.AsSpan(0xDC)); set => WriteInt32BigEndian(Data.AsSpan(0xDC), value); }
|
||||
public uint EXP_Shadow { get => ReadUInt32BigEndian(Data.AsSpan(0xC0)); set => WriteUInt32BigEndian(Data.AsSpan(0xC0), value); }
|
||||
|
||||
public const int Purified = -100;
|
||||
public bool IsShadow => ShadowID != 0 && Purification != Purified;
|
||||
|
|
|
@ -1,9 +1,10 @@
|
|||
using System;
|
||||
using static System.Buffers.Binary.BinaryPrimitives;
|
||||
|
||||
namespace PKHeX.Core
|
||||
{
|
||||
/// <summary> Generation 8 <see cref="PKM"/> format. </summary>
|
||||
public abstract class G8PKM : PKM,
|
||||
public abstract class G8PKM : PKM, ISanityChecksum,
|
||||
IRibbonSetEvent3, IRibbonSetEvent4, IRibbonSetCommon3, IRibbonSetCommon4, IRibbonSetCommon6, IRibbonSetCommon7, IRibbonSetCommon8, IRibbonSetMark8, IRibbonSetAffixed,
|
||||
IContestStats, IContestStatsMutable, IHyperTrain, IScaledSize, IGigantamax, IFavorite, IDynamaxLevel, IRibbonIndex, IHandlerLanguage, IFormArgument, IHomeTrack, IBattleVersion, ITrainerMemories
|
||||
{
|
||||
|
@ -18,11 +19,11 @@ namespace PKHeX.Core
|
|||
return data;
|
||||
}
|
||||
|
||||
protected override ushort CalculateChecksum()
|
||||
private ushort CalculateChecksum()
|
||||
{
|
||||
ushort chk = 0;
|
||||
for (int i = 8; i < PokeCrypto.SIZE_8STORED; i += 2)
|
||||
chk += BitConverter.ToUInt16(Data, i);
|
||||
chk += ReadUInt16LittleEndian(Data.AsSpan(i));
|
||||
return chk;
|
||||
}
|
||||
|
||||
|
@ -33,16 +34,17 @@ namespace PKHeX.Core
|
|||
set { if (CurrentHandler == 0) OT_Friendship = value; else HT_Friendship = value; }
|
||||
}
|
||||
|
||||
private string GetString(int offset, int count) => StringConverter.GetString7b(Data, offset, count);
|
||||
private static byte[] SetString(string value, int maxLength) => StringConverter.SetString7b(value, maxLength);
|
||||
|
||||
public override int SIZE_PARTY => PokeCrypto.SIZE_8PARTY;
|
||||
public override int SIZE_STORED => PokeCrypto.SIZE_8STORED;
|
||||
|
||||
public sealed override bool ChecksumValid => CalculateChecksum() == Checksum;
|
||||
public sealed override void RefreshChecksum() => Checksum = CalculateChecksum();
|
||||
public sealed override bool Valid { get => Sanity == 0 && ChecksumValid; set { if (!value) return; Sanity = 0; RefreshChecksum(); } }
|
||||
|
||||
// Trash Bytes
|
||||
public override Span<byte> Nickname_Trash { get => Data.AsSpan(0x58, 24); set { if (value.Length == 24) value.CopyTo(Data.AsSpan(0x58)); } }
|
||||
public override Span<byte> HT_Trash { get => Data.AsSpan(0xA8, 24); set { if (value.Length == 24) value.CopyTo(Data.AsSpan(0xA8)); } }
|
||||
public override Span<byte> OT_Trash { get => Data.AsSpan(0xF8, 24); set { if (value.Length == 24) value.CopyTo(Data.AsSpan(0xF8)); } }
|
||||
public override Span<byte> Nickname_Trash => Data.AsSpan(0x58, 26);
|
||||
public override Span<byte> HT_Trash => Data.AsSpan(0xA8, 26);
|
||||
public override Span<byte> OT_Trash => Data.AsSpan(0xF8, 26);
|
||||
|
||||
// Maximums
|
||||
public override int MaxIV => 31;
|
||||
|
@ -104,26 +106,26 @@ namespace PKHeX.Core
|
|||
}
|
||||
}
|
||||
|
||||
public override uint EncryptionConstant { get => BitConverter.ToUInt32(Data, 0x00); set => BitConverter.GetBytes(value).CopyTo(Data, 0x00); }
|
||||
public override ushort Sanity { get => BitConverter.ToUInt16(Data, 0x04); set => BitConverter.GetBytes(value).CopyTo(Data, 0x04); }
|
||||
public override ushort Checksum { get => BitConverter.ToUInt16(Data, 0x06); set => BitConverter.GetBytes(value).CopyTo(Data, 0x06); }
|
||||
public override uint EncryptionConstant { get => ReadUInt32LittleEndian(Data.AsSpan(0x00)); set => WriteUInt32LittleEndian(Data.AsSpan(0x00), value); }
|
||||
public ushort Sanity { get => ReadUInt16LittleEndian(Data.AsSpan(0x04)); set => WriteUInt16LittleEndian(Data.AsSpan(0x04), value); }
|
||||
public ushort Checksum { get => ReadUInt16LittleEndian(Data.AsSpan(0x06)); set => WriteUInt16LittleEndian(Data.AsSpan(0x06), value); }
|
||||
|
||||
// Structure
|
||||
#region Block A
|
||||
public override int Species { get => BitConverter.ToUInt16(Data, 0x08); set => BitConverter.GetBytes((ushort)value).CopyTo(Data, 0x08); }
|
||||
public override int HeldItem { get => BitConverter.ToUInt16(Data, 0x0A); set => BitConverter.GetBytes((ushort)value).CopyTo(Data, 0x0A); }
|
||||
public override int TID { get => BitConverter.ToUInt16(Data, 0x0C); set => BitConverter.GetBytes((ushort)value).CopyTo(Data, 0x0C); }
|
||||
public override int SID { get => BitConverter.ToUInt16(Data, 0x0E); set => BitConverter.GetBytes((ushort)value).CopyTo(Data, 0x0E); }
|
||||
public override uint EXP { get => BitConverter.ToUInt32(Data, 0x10); set => BitConverter.GetBytes(value).CopyTo(Data, 0x10); }
|
||||
public override int Ability { get => BitConverter.ToUInt16(Data, 0x14); set => BitConverter.GetBytes((ushort)value).CopyTo(Data, 0x14); }
|
||||
public override int Species { get => ReadUInt16LittleEndian(Data.AsSpan(0x08)); set => WriteUInt16LittleEndian(Data.AsSpan(0x08), (ushort)value); }
|
||||
public override int HeldItem { get => ReadUInt16LittleEndian(Data.AsSpan(0x0A)); set => WriteUInt16LittleEndian(Data.AsSpan(0x0A), (ushort)value); }
|
||||
public override int TID { get => ReadUInt16LittleEndian(Data.AsSpan(0x0C)); set => WriteUInt16LittleEndian(Data.AsSpan(0x0C), (ushort)value); }
|
||||
public override int SID { get => ReadUInt16LittleEndian(Data.AsSpan(0x0E)); set => WriteUInt16LittleEndian(Data.AsSpan(0x0E), (ushort)value); }
|
||||
public override uint EXP { get => ReadUInt32LittleEndian(Data.AsSpan(0x10)); set => WriteUInt32LittleEndian(Data.AsSpan(0x10), value); }
|
||||
public override int Ability { get => ReadUInt16LittleEndian(Data.AsSpan(0x14)); set => WriteUInt16LittleEndian(Data.AsSpan(0x14), (ushort)value); }
|
||||
public override int AbilityNumber { get => Data[0x16] & 7; set => Data[0x16] = (byte)((Data[0x16] & ~7) | (value & 7)); }
|
||||
public bool Favorite { get => (Data[0x16] & 8) != 0; set => Data[0x16] = (byte)((Data[0x16] & ~8) | ((value ? 1 : 0) << 3)); } // unused, was in LGPE but not in SWSH
|
||||
public bool CanGigantamax { get => (Data[0x16] & 16) != 0; set => Data[0x16] = (byte)((Data[0x16] & ~16) | (value ? 16 : 0)); }
|
||||
// 0x17 alignment unused
|
||||
public override int MarkValue { get => BitConverter.ToUInt16(Data, 0x18); protected set => BitConverter.GetBytes((ushort)value).CopyTo(Data, 0x18); }
|
||||
public override int MarkValue { get => ReadUInt16LittleEndian(Data.AsSpan(0x18)); protected set => WriteUInt16LittleEndian(Data.AsSpan(0x18), (ushort)value); }
|
||||
// 0x1A alignment unused
|
||||
// 0x1B alignment unused
|
||||
public override uint PID { get => BitConverter.ToUInt32(Data, 0x1C); set => BitConverter.GetBytes(value).CopyTo(Data, 0x1C); }
|
||||
public override uint PID { get => ReadUInt32LittleEndian(Data.AsSpan(0x1C)); set => WriteUInt32LittleEndian(Data.AsSpan(0x1C), value); }
|
||||
public override int Nature { get => Data[0x20]; set => Data[0x20] = (byte)value; }
|
||||
public override int StatNature { get => Data[0x21]; set => Data[0x21] = (byte)value; }
|
||||
public override bool FatefulEncounter { get => (Data[0x22] & 1) == 1; set => Data[0x22] = (byte)((Data[0x22] & ~0x01) | (value ? 1 : 0)); }
|
||||
|
@ -131,7 +133,7 @@ namespace PKHeX.Core
|
|||
public override int Gender { get => (Data[0x22] >> 2) & 0x3; set => Data[0x22] = (byte)((Data[0x22] & 0xF3) | (value << 2)); }
|
||||
// 0x23 alignment unused
|
||||
|
||||
public override int Form { get => BitConverter.ToUInt16(Data, 0x24); set => BitConverter.GetBytes((ushort)value).CopyTo(Data, 0x24); }
|
||||
public override int Form { get => ReadUInt16LittleEndian(Data.AsSpan(0x24)); set => WriteUInt16LittleEndian(Data.AsSpan(0x24), (ushort)value); }
|
||||
public override int EV_HP { get => Data[0x26]; set => Data[0x26] = (byte)value; }
|
||||
public override int EV_ATK { get => Data[0x27]; set => Data[0x27] = (byte)value; }
|
||||
public override int EV_DEF { get => Data[0x28]; set => Data[0x28] = (byte)value; }
|
||||
|
@ -303,15 +305,15 @@ namespace PKHeX.Core
|
|||
|
||||
public bool HasMark()
|
||||
{
|
||||
var d = Data;
|
||||
if ((BitConverter.ToUInt16(d, 0x3A) & 0xFFE0) != 0)
|
||||
var d = Data.AsSpan();
|
||||
if ((ReadUInt16LittleEndian(d[0x3A..]) & 0xFFE0) != 0)
|
||||
return true;
|
||||
if (BitConverter.ToUInt32(d, 0x40) != 0)
|
||||
if (ReadUInt32LittleEndian(d[0x40..]) != 0)
|
||||
return true;
|
||||
return (d[0x44] & 3) != 0;
|
||||
}
|
||||
|
||||
public uint Sociability { get => BitConverter.ToUInt32(Data, 0x48); set => BitConverter.GetBytes(value).CopyTo(Data, 0x48); }
|
||||
public uint Sociability { get => ReadUInt32LittleEndian(Data.AsSpan(0x48)); set => WriteUInt32LittleEndian(Data.AsSpan(0x48), value); }
|
||||
|
||||
// 0x4C-0x4F unused
|
||||
|
||||
|
@ -324,16 +326,16 @@ namespace PKHeX.Core
|
|||
#region Block B
|
||||
public override string Nickname
|
||||
{
|
||||
get => GetString(0x58, 24);
|
||||
set => SetString(value, 12).CopyTo(Data, 0x58);
|
||||
get => StringConverter8.GetString(Nickname_Trash);
|
||||
set => StringConverter8.SetString(Nickname_Trash, value.AsSpan(), 12, StringConverterOption.None);
|
||||
}
|
||||
|
||||
// 2 bytes for \0, automatically handled above
|
||||
|
||||
public override int Move1 { get => BitConverter.ToUInt16(Data, 0x72); set => BitConverter.GetBytes((ushort)value).CopyTo(Data, 0x72); }
|
||||
public override int Move2 { get => BitConverter.ToUInt16(Data, 0x74); set => BitConverter.GetBytes((ushort)value).CopyTo(Data, 0x74); }
|
||||
public override int Move3 { get => BitConverter.ToUInt16(Data, 0x76); set => BitConverter.GetBytes((ushort)value).CopyTo(Data, 0x76); }
|
||||
public override int Move4 { get => BitConverter.ToUInt16(Data, 0x78); set => BitConverter.GetBytes((ushort)value).CopyTo(Data, 0x78); }
|
||||
public override int Move1 { get => ReadUInt16LittleEndian(Data.AsSpan(0x72)); set => WriteUInt16LittleEndian(Data.AsSpan(0x72), (ushort)value); }
|
||||
public override int Move2 { get => ReadUInt16LittleEndian(Data.AsSpan(0x74)); set => WriteUInt16LittleEndian(Data.AsSpan(0x74), (ushort)value); }
|
||||
public override int Move3 { get => ReadUInt16LittleEndian(Data.AsSpan(0x76)); set => WriteUInt16LittleEndian(Data.AsSpan(0x76), (ushort)value); }
|
||||
public override int Move4 { get => ReadUInt16LittleEndian(Data.AsSpan(0x78)); set => WriteUInt16LittleEndian(Data.AsSpan(0x78), (ushort)value); }
|
||||
|
||||
public override int Move1_PP { get => Data[0x7A]; set => Data[0x7A] = (byte)value; }
|
||||
public override int Move2_PP { get => Data[0x7B]; set => Data[0x7B] = (byte)value; }
|
||||
|
@ -344,14 +346,14 @@ namespace PKHeX.Core
|
|||
public override int Move3_PPUps { get => Data[0x80]; set => Data[0x80] = (byte)value; }
|
||||
public override int Move4_PPUps { get => Data[0x81]; set => Data[0x81] = (byte)value; }
|
||||
|
||||
public override int RelearnMove1 { get => BitConverter.ToUInt16(Data, 0x82); set => BitConverter.GetBytes((ushort)value).CopyTo(Data, 0x82); }
|
||||
public override int RelearnMove2 { get => BitConverter.ToUInt16(Data, 0x84); set => BitConverter.GetBytes((ushort)value).CopyTo(Data, 0x84); }
|
||||
public override int RelearnMove3 { get => BitConverter.ToUInt16(Data, 0x86); set => BitConverter.GetBytes((ushort)value).CopyTo(Data, 0x86); }
|
||||
public override int RelearnMove4 { get => BitConverter.ToUInt16(Data, 0x88); set => BitConverter.GetBytes((ushort)value).CopyTo(Data, 0x88); }
|
||||
public override int RelearnMove1 { get => ReadUInt16LittleEndian(Data.AsSpan(0x82)); set => WriteUInt16LittleEndian(Data.AsSpan(0x82), (ushort)value); }
|
||||
public override int RelearnMove2 { get => ReadUInt16LittleEndian(Data.AsSpan(0x84)); set => WriteUInt16LittleEndian(Data.AsSpan(0x84), (ushort)value); }
|
||||
public override int RelearnMove3 { get => ReadUInt16LittleEndian(Data.AsSpan(0x86)); set => WriteUInt16LittleEndian(Data.AsSpan(0x86), (ushort)value); }
|
||||
public override int RelearnMove4 { get => ReadUInt16LittleEndian(Data.AsSpan(0x88)); set => WriteUInt16LittleEndian(Data.AsSpan(0x88), (ushort)value); }
|
||||
|
||||
public override int Stat_HPCurrent { get => BitConverter.ToUInt16(Data, 0x8A); set => BitConverter.GetBytes((ushort)value).CopyTo(Data, 0x8A); }
|
||||
public override int Stat_HPCurrent { get => ReadUInt16LittleEndian(Data.AsSpan(0x8A)); set => WriteUInt16LittleEndian(Data.AsSpan(0x8A), (ushort)value); }
|
||||
|
||||
private uint IV32 { get => BitConverter.ToUInt32(Data, 0x8C); set => BitConverter.GetBytes(value).CopyTo(Data, 0x8C); }
|
||||
private uint IV32 { get => ReadUInt32LittleEndian(Data.AsSpan(0x8C)); set => WriteUInt32LittleEndian(Data.AsSpan(0x8C), value); }
|
||||
public override int IV_HP { get => (int)(IV32 >> 00) & 0x1F; set => IV32 = (IV32 & ~(0x1Fu << 00)) | ((value > 31 ? 31u : (uint)value) << 00); }
|
||||
public override int IV_ATK { get => (int)(IV32 >> 05) & 0x1F; set => IV32 = (IV32 & ~(0x1Fu << 05)) | ((value > 31 ? 31u : (uint)value) << 05); }
|
||||
public override int IV_DEF { get => (int)(IV32 >> 10) & 0x1F; set => IV32 = (IV32 & ~(0x1Fu << 10)) | ((value > 31 ? 31u : (uint)value) << 10); }
|
||||
|
@ -365,24 +367,29 @@ namespace PKHeX.Core
|
|||
|
||||
// 0x90-0x93 unused
|
||||
|
||||
public override int Status_Condition { get => BitConverter.ToInt32(Data, 0x94); set => BitConverter.GetBytes(value).CopyTo(Data, 0x94); }
|
||||
public int Unk98 { get => BitConverter.ToInt32(Data, 0x98); set => BitConverter.GetBytes(value).CopyTo(Data, 0x98); }
|
||||
public override int Status_Condition { get => ReadInt32LittleEndian(Data.AsSpan(0x94)); set => WriteInt32LittleEndian(Data.AsSpan(0x94), value); }
|
||||
public int Unk98 { get => ReadInt32LittleEndian(Data.AsSpan(0x98)); set => WriteInt32LittleEndian(Data.AsSpan(0x98), value); }
|
||||
|
||||
// 0x9C-0xA7 unused
|
||||
|
||||
#endregion
|
||||
#region Block C
|
||||
public override string HT_Name { get => GetString(0xA8, 24); set => SetString(value, 12).CopyTo(Data, 0xA8); }
|
||||
public override string HT_Name
|
||||
{
|
||||
get => StringConverter8.GetString(HT_Trash);
|
||||
set => StringConverter8.SetString(HT_Trash, value.AsSpan(), 12, StringConverterOption.None);
|
||||
}
|
||||
|
||||
public override int HT_Gender { get => Data[0xC2]; set => Data[0xC2] = (byte)value; }
|
||||
public int HT_Language { get => Data[0xC3]; set => Data[0xC3] = (byte)value; }
|
||||
public override int CurrentHandler { get => Data[0xC4]; set => Data[0xC4] = (byte)value; }
|
||||
// 0xC5 unused (alignment)
|
||||
public int HT_TrainerID { get => BitConverter.ToUInt16(Data, 0xC6); set => BitConverter.GetBytes((ushort)value).CopyTo(Data, 0xC6); } // unused?
|
||||
public int HT_TrainerID { get => ReadUInt16LittleEndian(Data.AsSpan(0xC6)); set => WriteUInt16LittleEndian(Data.AsSpan(0xC6), (ushort)value); } // unused?
|
||||
public override int HT_Friendship { get => Data[0xC8]; set => Data[0xC8] = (byte)value; }
|
||||
public int HT_Intensity { get => Data[0xC9]; set => Data[0xC9] = (byte)value; }
|
||||
public int HT_Memory { get => Data[0xCA]; set => Data[0xCA] = (byte)value; }
|
||||
public int HT_Feeling { get => Data[0xCB]; set => Data[0xCB] = (byte)value; }
|
||||
public int HT_TextVar { get => BitConverter.ToUInt16(Data, 0xCC); set => BitConverter.GetBytes((ushort)value).CopyTo(Data, 0xCC); }
|
||||
public int HT_TextVar { get => ReadUInt16LittleEndian(Data.AsSpan(0xCC)); set => WriteUInt16LittleEndian(Data.AsSpan(0xCC), (ushort)value); }
|
||||
|
||||
// 0xCE-0xDB unused
|
||||
|
||||
|
@ -394,7 +401,7 @@ namespace PKHeX.Core
|
|||
// public override int ConsoleRegion { get => Data[0xE1]; set => Data[0xE1] = (byte)value; }
|
||||
public override int Language { get => Data[0xE2]; set => Data[0xE2] = (byte)value; }
|
||||
public int UnkE3 { get => Data[0xE3]; set => Data[0xE3] = (byte)value; }
|
||||
public uint FormArgument { get => BitConverter.ToUInt32(Data, 0xE4); set => BitConverter.GetBytes(value).CopyTo(Data, 0xE4); }
|
||||
public uint FormArgument { get => ReadUInt32LittleEndian(Data.AsSpan(0xE4)); set => WriteUInt32LittleEndian(Data.AsSpan(0xE4), value); }
|
||||
public byte FormArgumentRemain { get => (byte)FormArgument; set => FormArgument = (FormArgument & ~0xFFu) | value; }
|
||||
public byte FormArgumentElapsed { get => (byte)(FormArgument >> 8); set => FormArgument = (FormArgument & ~0xFF00u) | (uint)(value << 8); }
|
||||
public byte FormArgumentMaximum { get => (byte)(FormArgument >> 16); set => FormArgument = (FormArgument & ~0xFF0000u) | (uint)(value << 16); }
|
||||
|
@ -403,12 +410,17 @@ namespace PKHeX.Core
|
|||
|
||||
#endregion
|
||||
#region Block D
|
||||
public override string OT_Name { get => GetString(0xF8, 24); set => SetString(value, 12).CopyTo(Data, 0xF8); }
|
||||
public override string OT_Name
|
||||
{
|
||||
get => StringConverter8.GetString(OT_Trash);
|
||||
set => StringConverter8.SetString(OT_Trash, value.AsSpan(), 12, StringConverterOption.None);
|
||||
}
|
||||
|
||||
public override int OT_Friendship { get => Data[0x112]; set => Data[0x112] = (byte)value; }
|
||||
public int OT_Intensity { get => Data[0x113]; set => Data[0x113] = (byte)value; }
|
||||
public int OT_Memory { get => Data[0x114]; set => Data[0x114] = (byte)value; }
|
||||
// 0x115 unused align
|
||||
public int OT_TextVar { get => BitConverter.ToUInt16(Data, 0x116); set => BitConverter.GetBytes((ushort)value).CopyTo(Data, 0x116); }
|
||||
public int OT_TextVar { get => ReadUInt16LittleEndian(Data.AsSpan(0x116)); set => WriteUInt16LittleEndian(Data.AsSpan(0x116), (ushort)value); }
|
||||
public int OT_Feeling { get => Data[0x118]; set => Data[0x118] = (byte)value; }
|
||||
public override int Egg_Year { get => Data[0x119]; set => Data[0x119] = (byte)value; }
|
||||
public override int Egg_Month { get => Data[0x11A]; set => Data[0x11A] = (byte)value; }
|
||||
|
@ -417,8 +429,8 @@ namespace PKHeX.Core
|
|||
public override int Met_Month { get => Data[0x11D]; set => Data[0x11D] = (byte)value; }
|
||||
public override int Met_Day { get => Data[0x11E]; set => Data[0x11E] = (byte)value; }
|
||||
// 0x11F unused align
|
||||
public override int Egg_Location { get => BitConverter.ToUInt16(Data, 0x120); set => BitConverter.GetBytes((ushort)value).CopyTo(Data, 0x120); }
|
||||
public override int Met_Location { get => BitConverter.ToUInt16(Data, 0x122); set => BitConverter.GetBytes((ushort)value).CopyTo(Data, 0x122); }
|
||||
public override int Egg_Location { get => ReadUInt16LittleEndian(Data.AsSpan(0x120)); set => WriteUInt16LittleEndian(Data.AsSpan(0x120), (ushort)value); }
|
||||
public override int Met_Location { get => ReadUInt16LittleEndian(Data.AsSpan(0x122)); set => WriteUInt16LittleEndian(Data.AsSpan(0x122), (ushort)value); }
|
||||
public override int Ball { get => Data[0x124]; set => Data[0x124] = (byte)value; }
|
||||
public override int Met_Level { get => Data[0x125] & ~0x80; set => Data[0x125] = (byte)((Data[0x125] & 0x80) | value); }
|
||||
public override int OT_Gender { get => Data[0x125] >> 7; set => Data[0x125] = (byte)((Data[0x125] & ~0x80) | (value << 7)); }
|
||||
|
@ -451,20 +463,20 @@ namespace PKHeX.Core
|
|||
// Why did you mis-align this field, GameFreak?
|
||||
public ulong Tracker
|
||||
{
|
||||
get => BitConverter.ToUInt64(Data, 0x135);
|
||||
set => BitConverter.GetBytes(value).CopyTo(Data, 0x135);
|
||||
get => ReadUInt64LittleEndian(Data.AsSpan(0x135));
|
||||
set => WriteUInt64LittleEndian(Data.AsSpan(0x135), value);
|
||||
}
|
||||
|
||||
#endregion
|
||||
#region Battle Stats
|
||||
public override int Stat_Level { get => Data[0x148]; set => Data[0x148] = (byte)value; }
|
||||
// 0x149 unused alignment
|
||||
public override int Stat_HPMax { get => BitConverter.ToUInt16(Data, 0x14A); set => BitConverter.GetBytes((ushort)value).CopyTo(Data, 0x14A); }
|
||||
public override int Stat_ATK { get => BitConverter.ToUInt16(Data, 0x14C); set => BitConverter.GetBytes((ushort)value).CopyTo(Data, 0x14C); }
|
||||
public override int Stat_DEF { get => BitConverter.ToUInt16(Data, 0x14E); set => BitConverter.GetBytes((ushort)value).CopyTo(Data, 0x14E); }
|
||||
public override int Stat_SPE { get => BitConverter.ToUInt16(Data, 0x150); set => BitConverter.GetBytes((ushort)value).CopyTo(Data, 0x150); }
|
||||
public override int Stat_SPA { get => BitConverter.ToUInt16(Data, 0x152); set => BitConverter.GetBytes((ushort)value).CopyTo(Data, 0x152); }
|
||||
public override int Stat_SPD { get => BitConverter.ToUInt16(Data, 0x154); set => BitConverter.GetBytes((ushort)value).CopyTo(Data, 0x154); }
|
||||
public override int Stat_HPMax { get => ReadUInt16LittleEndian(Data.AsSpan(0x14A)); set => WriteUInt16LittleEndian(Data.AsSpan(0x14A), (ushort)value); }
|
||||
public override int Stat_ATK { get => ReadUInt16LittleEndian(Data.AsSpan(0x14C)); set => WriteUInt16LittleEndian(Data.AsSpan(0x14C), (ushort)value); }
|
||||
public override int Stat_DEF { get => ReadUInt16LittleEndian(Data.AsSpan(0x14E)); set => WriteUInt16LittleEndian(Data.AsSpan(0x14E), (ushort)value); }
|
||||
public override int Stat_SPE { get => ReadUInt16LittleEndian(Data.AsSpan(0x150)); set => WriteUInt16LittleEndian(Data.AsSpan(0x150), (ushort)value); }
|
||||
public override int Stat_SPA { get => ReadUInt16LittleEndian(Data.AsSpan(0x152)); set => WriteUInt16LittleEndian(Data.AsSpan(0x152), (ushort)value); }
|
||||
public override int Stat_SPD { get => ReadUInt16LittleEndian(Data.AsSpan(0x154)); set => WriteUInt16LittleEndian(Data.AsSpan(0x154), (ushort)value); }
|
||||
#endregion
|
||||
|
||||
public override int[] Markings
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Runtime.CompilerServices;
|
||||
using static System.Buffers.Binary.BinaryPrimitives;
|
||||
|
||||
namespace PKHeX.Core
|
||||
{
|
||||
|
@ -41,68 +42,65 @@ namespace PKHeX.Core
|
|||
|
||||
public override PKM Clone() => new PB7((byte[])Data.Clone());
|
||||
|
||||
private string GetString(int offset, int count) => StringConverter.GetString7b(Data, offset, count);
|
||||
private static byte[] SetString(string value, int maxLength) => StringConverter.SetString7b(value, maxLength);
|
||||
|
||||
// Structure
|
||||
#region Block A
|
||||
public override uint EncryptionConstant
|
||||
{
|
||||
get => BitConverter.ToUInt32(Data, 0x00);
|
||||
set => BitConverter.GetBytes(value).CopyTo(Data, 0x00);
|
||||
get => ReadUInt32LittleEndian(Data.AsSpan(0x00));
|
||||
set => WriteUInt32LittleEndian(Data.AsSpan(0x00), value);
|
||||
}
|
||||
|
||||
public override ushort Sanity
|
||||
{
|
||||
get => BitConverter.ToUInt16(Data, 0x04);
|
||||
set => BitConverter.GetBytes(value).CopyTo(Data, 0x04);
|
||||
get => ReadUInt16LittleEndian(Data.AsSpan(0x04));
|
||||
set => WriteUInt16LittleEndian(Data.AsSpan(0x04), value);
|
||||
}
|
||||
|
||||
public override ushort Checksum
|
||||
{
|
||||
get => BitConverter.ToUInt16(Data, 0x06);
|
||||
set => BitConverter.GetBytes(value).CopyTo(Data, 0x06);
|
||||
get => ReadUInt16LittleEndian(Data.AsSpan(0x06));
|
||||
set => WriteUInt16LittleEndian(Data.AsSpan(0x06), value);
|
||||
}
|
||||
|
||||
public override int Species
|
||||
{
|
||||
get => BitConverter.ToUInt16(Data, 0x08);
|
||||
set => BitConverter.GetBytes((ushort)value).CopyTo(Data, 0x08);
|
||||
get => ReadUInt16LittleEndian(Data.AsSpan(0x08));
|
||||
set => WriteUInt16LittleEndian(Data.AsSpan(0x08), (ushort)value);
|
||||
}
|
||||
|
||||
public override int HeldItem
|
||||
{
|
||||
get => BitConverter.ToUInt16(Data, 0x0A);
|
||||
set => BitConverter.GetBytes((ushort)value).CopyTo(Data, 0x0A);
|
||||
get => ReadUInt16LittleEndian(Data.AsSpan(0x0A));
|
||||
set => WriteUInt16LittleEndian(Data.AsSpan(0x0A), (ushort)value);
|
||||
}
|
||||
|
||||
public override int TID
|
||||
{
|
||||
get => BitConverter.ToUInt16(Data, 0x0C);
|
||||
set => BitConverter.GetBytes((ushort)value).CopyTo(Data, 0x0C);
|
||||
get => ReadUInt16LittleEndian(Data.AsSpan(0x0C));
|
||||
set => WriteUInt16LittleEndian(Data.AsSpan(0x0C), (ushort)value);
|
||||
}
|
||||
|
||||
public override int SID
|
||||
{
|
||||
get => BitConverter.ToUInt16(Data, 0x0E);
|
||||
set => BitConverter.GetBytes((ushort)value).CopyTo(Data, 0x0E);
|
||||
get => ReadUInt16LittleEndian(Data.AsSpan(0x0E));
|
||||
set => WriteUInt16LittleEndian(Data.AsSpan(0x0E), (ushort)value);
|
||||
}
|
||||
|
||||
public override uint EXP
|
||||
{
|
||||
get => BitConverter.ToUInt32(Data, 0x10);
|
||||
set => BitConverter.GetBytes(value).CopyTo(Data, 0x10);
|
||||
get => ReadUInt32LittleEndian(Data.AsSpan(0x10));
|
||||
set => WriteUInt32LittleEndian(Data.AsSpan(0x10), value);
|
||||
}
|
||||
|
||||
public override int Ability { get => Data[0x14]; set => Data[0x14] = (byte)value; }
|
||||
public override int AbilityNumber { get => Data[0x15] & 7; set => Data[0x15] = (byte)((Data[0x15] & ~7) | (value & 7)); }
|
||||
public bool Favorite { get => (Data[0x15] & 8) != 0; set => Data[0x15] = (byte)((Data[0x15] & ~8) | ((value ? 1 : 0) << 3)); }
|
||||
public override int MarkValue { get => BitConverter.ToUInt16(Data, 0x16); protected set => BitConverter.GetBytes((ushort)value).CopyTo(Data, 0x16); }
|
||||
public override int MarkValue { get => ReadUInt16LittleEndian(Data.AsSpan(0x16)); protected set => WriteUInt16LittleEndian(Data.AsSpan(0x16), (ushort)value); }
|
||||
|
||||
public override uint PID
|
||||
{
|
||||
get => BitConverter.ToUInt32(Data, 0x18);
|
||||
set => BitConverter.GetBytes(value).CopyTo(Data, 0x18);
|
||||
get => ReadUInt32LittleEndian(Data.AsSpan(0x18));
|
||||
set => WriteUInt32LittleEndian(Data.AsSpan(0x18), value);
|
||||
}
|
||||
|
||||
public override int Nature { get => Data[0x1C]; set => Data[0x1C] = (byte)value; }
|
||||
|
@ -125,12 +123,12 @@ namespace PKHeX.Core
|
|||
private byte PKRS { get => Data[0x2B]; set => Data[0x2B] = value; }
|
||||
public override int PKRS_Days { get => PKRS & 0xF; set => PKRS = (byte)((PKRS & ~0xF) | value); }
|
||||
public override int PKRS_Strain { get => PKRS >> 4; set => PKRS = (byte)((PKRS & 0xF) | value << 4); }
|
||||
public float HeightAbsolute { get => BitConverter.ToSingle(Data, 0x2C); set => BitConverter.GetBytes(value).CopyTo(Data, 0x2C); }
|
||||
public float HeightAbsolute { get => ReadSingleLittleEndian(Data.AsSpan(0x2C)); set => WriteSingleLittleEndian(Data.AsSpan(0x2C), value); }
|
||||
// 0x38 Unused
|
||||
// 0x39 Unused
|
||||
public int HeightScalar { get => Data[0x3A]; set => Data[0x3A] = (byte)value; }
|
||||
public int WeightScalar { get => Data[0x3B]; set => Data[0x3B] = (byte)value; }
|
||||
public uint FormArgument { get => BitConverter.ToUInt32(Data, 0x3C); set => BitConverter.GetBytes(value).CopyTo(Data, 0x3C); }
|
||||
public uint FormArgument { get => ReadUInt32LittleEndian(Data.AsSpan(0x3C)); set => WriteUInt32LittleEndian(Data.AsSpan(0x3C), value); }
|
||||
public byte FormArgumentRemain { get => (byte)FormArgument; set => FormArgument = (FormArgument & ~0xFFu) | value; }
|
||||
public byte FormArgumentElapsed { get => (byte)(FormArgument >> 8); set => FormArgument = (FormArgument & ~0xFF00u) | (uint)(value << 8); }
|
||||
public byte FormArgumentMaximum { get => (byte)(FormArgument >> 16); set => FormArgument = (FormArgument & ~0xFF0000u) | (uint)(value << 16); }
|
||||
|
@ -139,32 +137,32 @@ namespace PKHeX.Core
|
|||
#region Block B
|
||||
public override string Nickname
|
||||
{
|
||||
get => GetString(0x40, 24);
|
||||
set => SetString(value, 12).CopyTo(Data, 0x40);
|
||||
get => StringConverter8.GetString(Nickname_Trash);
|
||||
set => StringConverter8.SetString(Nickname_Trash, value.AsSpan(), 12, StringConverterOption.None);
|
||||
}
|
||||
|
||||
public override int Move1
|
||||
{
|
||||
get => BitConverter.ToUInt16(Data, 0x5A);
|
||||
set => BitConverter.GetBytes((ushort)value).CopyTo(Data, 0x5A);
|
||||
get => ReadUInt16LittleEndian(Data.AsSpan(0x5A));
|
||||
set => WriteUInt16LittleEndian(Data.AsSpan(0x5A), (ushort)value);
|
||||
}
|
||||
|
||||
public override int Move2
|
||||
{
|
||||
get => BitConverter.ToUInt16(Data, 0x5C);
|
||||
set => BitConverter.GetBytes((ushort)value).CopyTo(Data, 0x5C);
|
||||
get => ReadUInt16LittleEndian(Data.AsSpan(0x5C));
|
||||
set => WriteUInt16LittleEndian(Data.AsSpan(0x5C), (ushort)value);
|
||||
}
|
||||
|
||||
public override int Move3
|
||||
{
|
||||
get => BitConverter.ToUInt16(Data, 0x5E);
|
||||
set => BitConverter.GetBytes((ushort)value).CopyTo(Data, 0x5E);
|
||||
get => ReadUInt16LittleEndian(Data.AsSpan(0x5E));
|
||||
set => WriteUInt16LittleEndian(Data.AsSpan(0x5E), (ushort)value);
|
||||
}
|
||||
|
||||
public override int Move4
|
||||
{
|
||||
get => BitConverter.ToUInt16(Data, 0x60);
|
||||
set => BitConverter.GetBytes((ushort)value).CopyTo(Data, 0x60);
|
||||
get => ReadUInt16LittleEndian(Data.AsSpan(0x60));
|
||||
set => WriteUInt16LittleEndian(Data.AsSpan(0x60), (ushort)value);
|
||||
}
|
||||
|
||||
public override int Move1_PP { get => Data[0x62]; set => Data[0x62] = (byte)value; }
|
||||
|
@ -178,31 +176,31 @@ namespace PKHeX.Core
|
|||
|
||||
public override int RelearnMove1
|
||||
{
|
||||
get => BitConverter.ToUInt16(Data, 0x6A);
|
||||
set => BitConverter.GetBytes((ushort)value).CopyTo(Data, 0x6A);
|
||||
get => ReadUInt16LittleEndian(Data.AsSpan(0x6A));
|
||||
set => WriteUInt16LittleEndian(Data.AsSpan(0x6A), (ushort)value);
|
||||
}
|
||||
|
||||
public override int RelearnMove2
|
||||
{
|
||||
get => BitConverter.ToUInt16(Data, 0x6C);
|
||||
set => BitConverter.GetBytes((ushort)value).CopyTo(Data, 0x6C);
|
||||
get => ReadUInt16LittleEndian(Data.AsSpan(0x6C));
|
||||
set => WriteUInt16LittleEndian(Data.AsSpan(0x6C), (ushort)value);
|
||||
}
|
||||
|
||||
public override int RelearnMove3
|
||||
{
|
||||
get => BitConverter.ToUInt16(Data, 0x6E);
|
||||
set => BitConverter.GetBytes((ushort)value).CopyTo(Data, 0x6E);
|
||||
get => ReadUInt16LittleEndian(Data.AsSpan(0x6E));
|
||||
set => WriteUInt16LittleEndian(Data.AsSpan(0x6E), (ushort)value);
|
||||
}
|
||||
|
||||
public override int RelearnMove4
|
||||
{
|
||||
get => BitConverter.ToUInt16(Data, 0x70);
|
||||
set => BitConverter.GetBytes((ushort)value).CopyTo(Data, 0x70);
|
||||
get => ReadUInt16LittleEndian(Data.AsSpan(0x70));
|
||||
set => WriteUInt16LittleEndian(Data.AsSpan(0x70), (ushort)value);
|
||||
}
|
||||
|
||||
// 0x72 Unused
|
||||
// 0x73 Unused
|
||||
private uint IV32 { get => BitConverter.ToUInt32(Data, 0x74); set => BitConverter.GetBytes(value).CopyTo(Data, 0x74); }
|
||||
private uint IV32 { get => ReadUInt32LittleEndian(Data.AsSpan(0x74)); set => WriteUInt32LittleEndian(Data.AsSpan(0x74), value); }
|
||||
public override int IV_HP { get => (int)(IV32 >> 00) & 0x1F; set => IV32 = (IV32 & ~(0x1Fu << 00)) | ((value > 31 ? 31u : (uint)value) << 00); }
|
||||
public override int IV_ATK { get => (int)(IV32 >> 05) & 0x1F; set => IV32 = (IV32 & ~(0x1Fu << 05)) | ((value > 31 ? 31u : (uint)value) << 05); }
|
||||
public override int IV_DEF { get => (int)(IV32 >> 10) & 0x1F; set => IV32 = (IV32 & ~(0x1Fu << 10)) | ((value > 31 ? 31u : (uint)value) << 10); }
|
||||
|
@ -213,7 +211,12 @@ namespace PKHeX.Core
|
|||
public override bool IsNicknamed { get => ((IV32 >> 31) & 1) == 1; set => IV32 = (IV32 & 0x7FFFFFFFu) | (value ? 0x80000000u : 0u); }
|
||||
#endregion
|
||||
#region Block C
|
||||
public override string HT_Name { get => GetString(0x78, 24); set => SetString(value, 12).CopyTo(Data, 0x78); }
|
||||
public override string HT_Name
|
||||
{
|
||||
get => StringConverter8.GetString(HT_Trash);
|
||||
set => StringConverter8.SetString(HT_Trash, value.AsSpan(), 12, StringConverterOption.None);
|
||||
}
|
||||
|
||||
public override int HT_Gender { get => Data[0x92]; set => Data[0x92] = (byte)value; }
|
||||
public override int CurrentHandler { get => Data[0x93]; set => Data[0x93] = (byte)value; }
|
||||
// 0x94 Unused
|
||||
|
@ -236,7 +239,7 @@ namespace PKHeX.Core
|
|||
public int HT_Memory { get => Data[0xA5]; set => Data[0xA5] = (byte)value; }
|
||||
public int HT_Feeling { get => Data[0xA6]; set => Data[0xA6] = (byte)value; }
|
||||
// 0xA7 Unused
|
||||
public int HT_TextVar { get => BitConverter.ToUInt16(Data, 0xA8); set => BitConverter.GetBytes((ushort)value).CopyTo(Data, 0xA8); }
|
||||
public int HT_TextVar { get => ReadUInt16LittleEndian(Data.AsSpan(0xA8)); set => WriteUInt16LittleEndian(Data.AsSpan(0xA8), (ushort)value); }
|
||||
// 0xAA Unused
|
||||
// 0xAB Unused
|
||||
public byte FieldEventFatigue1 { get => Data[0xAC]; set => Data[0xAC] = value; }
|
||||
|
@ -245,7 +248,12 @@ namespace PKHeX.Core
|
|||
public override byte Enjoyment { get => Data[0xAF]; set => Data[0xAF] = value; }
|
||||
#endregion
|
||||
#region Block D
|
||||
public override string OT_Name { get => GetString(0xB0, 24); set => SetString(value, 12).CopyTo(Data, 0xB0); }
|
||||
public override string OT_Name
|
||||
{
|
||||
get => StringConverter8.GetString(OT_Trash);
|
||||
set => StringConverter8.SetString(OT_Trash, value.AsSpan(), 12, StringConverterOption.None);
|
||||
}
|
||||
|
||||
public override int OT_Friendship { get => Data[0xCA]; set => Data[0xCA] = (byte)value; }
|
||||
// 0xCB Unused
|
||||
// 0xCC Unused
|
||||
|
@ -260,8 +268,8 @@ namespace PKHeX.Core
|
|||
public override int Met_Month { get => Data[0xD5]; set => Data[0xD5] = (byte)value; }
|
||||
public override int Met_Day { get => Data[0xD6]; set => Data[0xD6] = (byte)value; }
|
||||
public int Rank { get => Data[0xD7]; set => Data[0xD7] = (byte)value; } // unused but fetched for stat calcs, and set for trpoke data?
|
||||
public override int Egg_Location { get => BitConverter.ToUInt16(Data, 0xD8); set => BitConverter.GetBytes((ushort)value).CopyTo(Data, 0xD8); }
|
||||
public override int Met_Location { get => BitConverter.ToUInt16(Data, 0xDA); set => BitConverter.GetBytes((ushort)value).CopyTo(Data, 0xDA); }
|
||||
public override int Egg_Location { get => ReadUInt16LittleEndian(Data.AsSpan(0xD8)); set => WriteUInt16LittleEndian(Data.AsSpan(0xD8), (ushort)value); }
|
||||
public override int Met_Location { get => ReadUInt16LittleEndian(Data.AsSpan(0xDA)); set => WriteUInt16LittleEndian(Data.AsSpan(0xDA), (ushort)value); }
|
||||
public override int Ball { get => Data[0xDC]; set => Data[0xDC] = (byte)value; }
|
||||
public override int Met_Level { get => Data[0xDD] & ~0x80; set => Data[0xDD] = (byte)((Data[0xDD] & 0x80) | value); }
|
||||
public override int OT_Gender { get => Data[0xDD] >> 7; set => Data[0xDD] = (byte)((Data[0xDD] & ~0x80) | (value << 7)); }
|
||||
|
@ -277,22 +285,22 @@ namespace PKHeX.Core
|
|||
// 0xE1 Unused
|
||||
// 0xE2 Unused
|
||||
public override int Language { get => Data[0xE3]; set => Data[0xE3] = (byte)value; }
|
||||
public float WeightAbsolute { get => BitConverter.ToSingle(Data, 0xE4); set => BitConverter.GetBytes(value).CopyTo(Data, 0xE4); }
|
||||
public float WeightAbsolute { get => ReadSingleLittleEndian(Data.AsSpan(0xE4)); set => WriteSingleLittleEndian(Data.AsSpan(0xE4), value); }
|
||||
#endregion
|
||||
#region Battle Stats
|
||||
public override int Status_Condition { get => BitConverter.ToInt32(Data, 0xE8); set => BitConverter.GetBytes(value).CopyTo(Data, 0xE8); }
|
||||
public override int Status_Condition { get => ReadInt32LittleEndian(Data.AsSpan(0xE8)); set => WriteInt32LittleEndian(Data.AsSpan(0xE8), value); }
|
||||
public override int Stat_Level { get => Data[0xEC]; set => Data[0xEC] = (byte)value; }
|
||||
public byte DirtType { get => Data[0xED]; set => Data[0xED] = value; }
|
||||
public byte DirtLocation { get => Data[0xEE]; set => Data[0xEE] = value; }
|
||||
// 0xEF unused
|
||||
public override int Stat_HPCurrent { get => BitConverter.ToUInt16(Data, 0xF0); set => BitConverter.GetBytes((ushort)value).CopyTo(Data, 0xF0); }
|
||||
public override int Stat_HPMax { get => BitConverter.ToUInt16(Data, 0xF2); set => BitConverter.GetBytes((ushort)value).CopyTo(Data, 0xF2); }
|
||||
public override int Stat_ATK { get => BitConverter.ToUInt16(Data, 0xF4); set => BitConverter.GetBytes((ushort)value).CopyTo(Data, 0xF4); }
|
||||
public override int Stat_DEF { get => BitConverter.ToUInt16(Data, 0xF6); set => BitConverter.GetBytes((ushort)value).CopyTo(Data, 0xF6); }
|
||||
public override int Stat_SPE { get => BitConverter.ToUInt16(Data, 0xF8); set => BitConverter.GetBytes((ushort)value).CopyTo(Data, 0xF8); }
|
||||
public override int Stat_SPA { get => BitConverter.ToUInt16(Data, 0xFA); set => BitConverter.GetBytes((ushort)value).CopyTo(Data, 0xFA); }
|
||||
public override int Stat_SPD { get => BitConverter.ToUInt16(Data, 0xFC); set => BitConverter.GetBytes((ushort)value).CopyTo(Data, 0xFC); }
|
||||
public int Stat_CP { get => BitConverter.ToUInt16(Data, 0xFE); set => BitConverter.GetBytes((ushort)value).CopyTo(Data, 0xFE); }
|
||||
public override int Stat_HPCurrent { get => ReadUInt16LittleEndian(Data.AsSpan(0xF0)); set => WriteUInt16LittleEndian(Data.AsSpan(0xF0), (ushort)value); }
|
||||
public override int Stat_HPMax { get => ReadUInt16LittleEndian(Data.AsSpan(0xF2)); set => WriteUInt16LittleEndian(Data.AsSpan(0xF2), (ushort)value); }
|
||||
public override int Stat_ATK { get => ReadUInt16LittleEndian(Data.AsSpan(0xF4)); set => WriteUInt16LittleEndian(Data.AsSpan(0xF4), (ushort)value); }
|
||||
public override int Stat_DEF { get => ReadUInt16LittleEndian(Data.AsSpan(0xF6)); set => WriteUInt16LittleEndian(Data.AsSpan(0xF6), (ushort)value); }
|
||||
public override int Stat_SPE { get => ReadUInt16LittleEndian(Data.AsSpan(0xF8)); set => WriteUInt16LittleEndian(Data.AsSpan(0xF8), (ushort)value); }
|
||||
public override int Stat_SPA { get => ReadUInt16LittleEndian(Data.AsSpan(0xFA)); set => WriteUInt16LittleEndian(Data.AsSpan(0xFA), (ushort)value); }
|
||||
public override int Stat_SPD { get => ReadUInt16LittleEndian(Data.AsSpan(0xFC)); set => WriteUInt16LittleEndian(Data.AsSpan(0xFC), (ushort)value); }
|
||||
public int Stat_CP { get => ReadUInt16LittleEndian(Data.AsSpan(0xFE)); set => WriteUInt16LittleEndian(Data.AsSpan(0xFE), (ushort)value); }
|
||||
public bool Stat_Mega { get => Data[0x100] != 0; set => Data[0x100] = value ? (byte)1 : (byte)0; }
|
||||
public int Stat_MegaForm { get => Data[0x101]; set => Data[0x101] = (byte)value; }
|
||||
// 102/103 unused
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using static System.Buffers.Binary.BinaryPrimitives;
|
||||
|
||||
namespace PKHeX.Core
|
||||
{
|
||||
|
@ -26,18 +27,20 @@ namespace PKHeX.Core
|
|||
return data;
|
||||
}
|
||||
|
||||
public override PKM Clone() => new PK1((byte[])Data.Clone(), Japanese)
|
||||
public override PKM Clone()
|
||||
{
|
||||
OT_Trash = RawOT,
|
||||
Nickname_Trash = RawNickname,
|
||||
};
|
||||
var clone = new PK1((byte[])Data.Clone(), Japanese);
|
||||
OT_Trash.CopyTo(clone.OT_Trash);
|
||||
Nickname_Trash.CopyTo(clone.Nickname_Trash);
|
||||
return clone;
|
||||
}
|
||||
|
||||
protected override byte[] Encrypt() => new PokeList1(this).Write();
|
||||
|
||||
#region Stored Attributes
|
||||
public byte SpeciesID1 { get => Data[0]; set => Data[0] = value; } // raw access
|
||||
public override int Species { get => SpeciesConverter.GetG1Species(SpeciesID1); set => SetSpeciesValues(value); }
|
||||
public override int Stat_HPCurrent { get => BigEndian.ToUInt16(Data, 0x1); set => BigEndian.GetBytes((ushort)value).CopyTo(Data, 0x1); }
|
||||
public override int Stat_HPCurrent { get => ReadUInt16BigEndian(Data.AsSpan(0x1)); set => WriteUInt16BigEndian(Data.AsSpan(0x1), (ushort)value); }
|
||||
public int Stat_LevelBox { get => Data[3]; set => Data[3] = (byte)value; }
|
||||
public override int Status_Condition { get => Data[4]; set => Data[4] = (byte)value; }
|
||||
public int Type_A { get => Data[5]; set => Data[5] = (byte)value; }
|
||||
|
@ -47,14 +50,14 @@ namespace PKHeX.Core
|
|||
public override int Move2 { get => Data[9]; set => Data[9] = (byte)value; }
|
||||
public override int Move3 { get => Data[10]; set => Data[10] = (byte)value; }
|
||||
public override int Move4 { get => Data[11]; set => Data[11] = (byte)value; }
|
||||
public override int TID { get => BigEndian.ToUInt16(Data, 0xC); set => BigEndian.GetBytes((ushort)value).CopyTo(Data, 0xC); }
|
||||
public override uint EXP { get => BigEndian.ToUInt32(Data, 0xE) >> 8; set => Array.Copy(BigEndian.GetBytes(value << 8), 0, Data, 0xE, 3); }
|
||||
public override int EV_HP { get => BigEndian.ToUInt16(Data, 0x11); set => BigEndian.GetBytes((ushort)value).CopyTo(Data, 0x11); }
|
||||
public override int EV_ATK { get => BigEndian.ToUInt16(Data, 0x13); set => BigEndian.GetBytes((ushort)value).CopyTo(Data, 0x13); }
|
||||
public override int EV_DEF { get => BigEndian.ToUInt16(Data, 0x15); set => BigEndian.GetBytes((ushort)value).CopyTo(Data, 0x15); }
|
||||
public override int EV_SPE { get => BigEndian.ToUInt16(Data, 0x17); set => BigEndian.GetBytes((ushort)value).CopyTo(Data, 0x17); }
|
||||
public override int EV_SPC { get => BigEndian.ToUInt16(Data, 0x19); set => BigEndian.GetBytes((ushort)value).CopyTo(Data, 0x19); }
|
||||
public override ushort DV16 { get => BigEndian.ToUInt16(Data, 0x1B); set => BigEndian.GetBytes(value).CopyTo(Data, 0x1B); }
|
||||
public override int TID { get => ReadUInt16BigEndian(Data.AsSpan(0xC)); set => WriteUInt16BigEndian(Data.AsSpan(0xC), (ushort)value); }
|
||||
public override uint EXP { get => ReadUInt32BigEndian(Data.AsSpan(0xE)) >> 8; set => WriteUInt32BigEndian(Data.AsSpan(0xE), (value << 8) | Data[0x11]); }
|
||||
public override int EV_HP { get => ReadUInt16BigEndian(Data.AsSpan(0x11)); set => WriteUInt16BigEndian(Data.AsSpan(0x11), (ushort)value); }
|
||||
public override int EV_ATK { get => ReadUInt16BigEndian(Data.AsSpan(0x13)); set => WriteUInt16BigEndian(Data.AsSpan(0x13), (ushort)value); }
|
||||
public override int EV_DEF { get => ReadUInt16BigEndian(Data.AsSpan(0x15)); set => WriteUInt16BigEndian(Data.AsSpan(0x15), (ushort)value); }
|
||||
public override int EV_SPE { get => ReadUInt16BigEndian(Data.AsSpan(0x17)); set => WriteUInt16BigEndian(Data.AsSpan(0x17), (ushort)value); }
|
||||
public override int EV_SPC { get => ReadUInt16BigEndian(Data.AsSpan(0x19)); set => WriteUInt16BigEndian(Data.AsSpan(0x19), (ushort)value); }
|
||||
public override ushort DV16 { get => ReadUInt16BigEndian(Data.AsSpan(0x1B)); set => WriteUInt16BigEndian(Data.AsSpan(0x1B), value); }
|
||||
public override int Move1_PP { get => Data[0x1D] & 0x3F; set => Data[0x1D] = (byte)((Data[0x1D] & 0xC0) | Math.Min(63, value)); }
|
||||
public override int Move2_PP { get => Data[0x1E] & 0x3F; set => Data[0x1E] = (byte)((Data[0x1E] & 0xC0) | Math.Min(63, value)); }
|
||||
public override int Move3_PP { get => Data[0x1F] & 0x3F; set => Data[0x1F] = (byte)((Data[0x1F] & 0xC0) | Math.Min(63, value)); }
|
||||
|
@ -67,11 +70,11 @@ namespace PKHeX.Core
|
|||
|
||||
#region Party Attributes
|
||||
public override int Stat_Level { get => Data[0x21]; set => Stat_LevelBox = Data[0x21] = (byte)value; }
|
||||
public override int Stat_HPMax { get => BigEndian.ToUInt16(Data, 0x22); set => BigEndian.GetBytes((ushort)value).CopyTo(Data, 0x22); }
|
||||
public override int Stat_ATK { get => BigEndian.ToUInt16(Data, 0x24); set => BigEndian.GetBytes((ushort)value).CopyTo(Data, 0x24); }
|
||||
public override int Stat_DEF { get => BigEndian.ToUInt16(Data, 0x26); set => BigEndian.GetBytes((ushort)value).CopyTo(Data, 0x26); }
|
||||
public override int Stat_SPE { get => BigEndian.ToUInt16(Data, 0x28); set => BigEndian.GetBytes((ushort)value).CopyTo(Data, 0x28); }
|
||||
public int Stat_SPC { get => BigEndian.ToUInt16(Data, 0x2A); set => BigEndian.GetBytes((ushort)value).CopyTo(Data, 0x2A); }
|
||||
public override int Stat_HPMax { get => ReadUInt16BigEndian(Data.AsSpan(0x22)); set => WriteUInt16BigEndian(Data.AsSpan(0x22), (ushort)value); }
|
||||
public override int Stat_ATK { get => ReadUInt16BigEndian(Data.AsSpan(0x24)); set => WriteUInt16BigEndian(Data.AsSpan(0x24), (ushort)value); }
|
||||
public override int Stat_DEF { get => ReadUInt16BigEndian(Data.AsSpan(0x26)); set => WriteUInt16BigEndian(Data.AsSpan(0x26), (ushort)value); }
|
||||
public override int Stat_SPE { get => ReadUInt16BigEndian(Data.AsSpan(0x28)); set => WriteUInt16BigEndian(Data.AsSpan(0x28), (ushort)value); }
|
||||
public int Stat_SPC { get => ReadUInt16BigEndian(Data.AsSpan(0x2A)); set => WriteUInt16BigEndian(Data.AsSpan(0x2A), (ushort)value); }
|
||||
// Leave SPA and SPD as alias for SPC
|
||||
public override int Stat_SPA { get => Stat_SPC; set => Stat_SPC = value; }
|
||||
public override int Stat_SPD { get => Stat_SPC; set { } }
|
||||
|
@ -195,15 +198,15 @@ namespace PKHeX.Core
|
|||
pk7.OT_Friendship = pk7.HT_Friendship = PersonalTable.SM[Species].BaseFriendship;
|
||||
|
||||
// IVs
|
||||
var new_ivs = new int[6];
|
||||
Span<int> finalIVs = stackalloc int[6];
|
||||
int flawless = Species == (int)Core.Species.Mew ? 5 : 3;
|
||||
var rnd = Util.Rand;
|
||||
for (var i = 0; i < new_ivs.Length; i++)
|
||||
new_ivs[i] = rnd.Next(32);
|
||||
for (var i = 0; i < finalIVs.Length; i++)
|
||||
finalIVs[i] = rnd.Next(32);
|
||||
for (var i = 0; i < flawless; i++)
|
||||
new_ivs[i] = 31;
|
||||
Util.Shuffle(new_ivs);
|
||||
pk7.IVs = new_ivs;
|
||||
finalIVs[i] = 31;
|
||||
Util.Shuffle(finalIVs);
|
||||
pk7.SetIVs(finalIVs);
|
||||
|
||||
switch (IsShiny ? Shiny.Always : Shiny.Never)
|
||||
{
|
||||
|
|
|
@ -1,4 +1,5 @@
|
|||
using System;
|
||||
using static System.Buffers.Binary.BinaryPrimitives;
|
||||
|
||||
namespace PKHeX.Core
|
||||
{
|
||||
|
@ -26,12 +27,13 @@ namespace PKHeX.Core
|
|||
return data;
|
||||
}
|
||||
|
||||
public override PKM Clone() => new PK2((byte[])Data.Clone(), Japanese)
|
||||
public override PKM Clone()
|
||||
{
|
||||
OT_Trash = RawOT,
|
||||
Nickname_Trash = RawNickname,
|
||||
IsEgg = IsEgg,
|
||||
};
|
||||
var clone = new PK2((byte[])Data.Clone(), Japanese) { IsEgg = IsEgg };
|
||||
OT_Trash.CopyTo(clone.OT_Trash);
|
||||
Nickname_Trash.CopyTo(clone.Nickname_Trash);
|
||||
return clone;
|
||||
}
|
||||
|
||||
protected override byte[] Encrypt() => new PokeList2(this).Write();
|
||||
|
||||
|
@ -43,14 +45,14 @@ namespace PKHeX.Core
|
|||
public override int Move2 { get => Data[3]; set => Data[3] = (byte)value; }
|
||||
public override int Move3 { get => Data[4]; set => Data[4] = (byte)value; }
|
||||
public override int Move4 { get => Data[5]; set => Data[5] = (byte)value; }
|
||||
public override int TID { get => BigEndian.ToUInt16(Data, 6); set => BigEndian.GetBytes((ushort)value).CopyTo(Data, 6); }
|
||||
public override uint EXP { get => BigEndian.ToUInt32(Data, 8) >> 8; set => Array.Copy(BigEndian.GetBytes(value << 8), 0, Data, 8, 3); }
|
||||
public override int EV_HP { get => BigEndian.ToUInt16(Data, 0xB); set => BigEndian.GetBytes((ushort)value).CopyTo(Data, 0xB); }
|
||||
public override int EV_ATK { get => BigEndian.ToUInt16(Data, 0xD); set => BigEndian.GetBytes((ushort)value).CopyTo(Data, 0xD); }
|
||||
public override int EV_DEF { get => BigEndian.ToUInt16(Data, 0xF); set => BigEndian.GetBytes((ushort)value).CopyTo(Data, 0xF); }
|
||||
public override int EV_SPE { get => BigEndian.ToUInt16(Data, 0x11); set => BigEndian.GetBytes((ushort)value).CopyTo(Data, 0x11); }
|
||||
public override int EV_SPC { get => BigEndian.ToUInt16(Data, 0x13); set => BigEndian.GetBytes((ushort)value).CopyTo(Data, 0x13); }
|
||||
public override ushort DV16 { get => BigEndian.ToUInt16(Data, 0x15); set => BigEndian.GetBytes(value).CopyTo(Data, 0x15); }
|
||||
public override int TID { get => ReadUInt16BigEndian(Data.AsSpan(6)); set => WriteUInt16BigEndian(Data.AsSpan(6), (ushort)value); }
|
||||
public override uint EXP { get => ReadUInt32BigEndian(Data.AsSpan(0x08)) >> 8; set => WriteUInt32BigEndian(Data.AsSpan(8), (value << 8) | Data[0xB]); }
|
||||
public override int EV_HP { get => ReadUInt16BigEndian(Data.AsSpan(0x0B)); set => WriteUInt16BigEndian(Data.AsSpan(0xB), (ushort)value); }
|
||||
public override int EV_ATK { get => ReadUInt16BigEndian(Data.AsSpan(0x0D)); set => WriteUInt16BigEndian(Data.AsSpan(0xD), (ushort)value); }
|
||||
public override int EV_DEF { get => ReadUInt16BigEndian(Data.AsSpan(0x0F)); set => WriteUInt16BigEndian(Data.AsSpan(0xF), (ushort)value); }
|
||||
public override int EV_SPE { get => ReadUInt16BigEndian(Data.AsSpan(0x11)); set => WriteUInt16BigEndian(Data.AsSpan(0x11), (ushort)value); }
|
||||
public override int EV_SPC { get => ReadUInt16BigEndian(Data.AsSpan(0x13)); set => WriteUInt16BigEndian(Data.AsSpan(0x13), (ushort)value); }
|
||||
public override ushort DV16 { get => ReadUInt16BigEndian(Data.AsSpan(0x15)); set => WriteUInt16BigEndian(Data.AsSpan(0x15), value); }
|
||||
public override int Move1_PP { get => Data[0x17] & 0x3F; set => Data[0x17] = (byte)((Data[0x17] & 0xC0) | Math.Min(63, value)); }
|
||||
public override int Move2_PP { get => Data[0x18] & 0x3F; set => Data[0x18] = (byte)((Data[0x18] & 0xC0) | Math.Min(63, value)); }
|
||||
public override int Move3_PP { get => Data[0x19] & 0x3F; set => Data[0x19] = (byte)((Data[0x19] & 0xC0) | Math.Min(63, value)); }
|
||||
|
@ -64,7 +66,7 @@ namespace PKHeX.Core
|
|||
public override int PKRS_Days { get => PKRS & 0xF; set => PKRS = (byte)((PKRS & ~0xF) | value); }
|
||||
public override int PKRS_Strain { get => PKRS >> 4; set => PKRS = (byte)((PKRS & 0xF) | value << 4); }
|
||||
// Crystal only Caught Data
|
||||
public int CaughtData { get => BigEndian.ToUInt16(Data, 0x1D); set => BigEndian.GetBytes((ushort)value).CopyTo(Data, 0x1D); }
|
||||
public int CaughtData { get => ReadUInt16BigEndian(Data.AsSpan(0x1D)); set => WriteUInt16BigEndian(Data.AsSpan(0x1D), (ushort)value); }
|
||||
public int Met_TimeOfDay { get => (CaughtData >> 14) & 0x3; set => CaughtData = (CaughtData & 0x3FFF) | ((value & 0x3) << 14); }
|
||||
public override int Met_Level { get => (CaughtData >> 8) & 0x3F; set => CaughtData = (CaughtData & 0xC0FF) | ((value & 0x3F) << 8); }
|
||||
public override int OT_Gender { get => (CaughtData >> 7) & 1; set => CaughtData = (CaughtData & 0xFF7F) | ((value & 1) << 7); }
|
||||
|
@ -81,13 +83,13 @@ namespace PKHeX.Core
|
|||
#region Party Attributes
|
||||
public override int Status_Condition { get => Data[0x20]; set => Data[0x20] = (byte)value; }
|
||||
|
||||
public override int Stat_HPCurrent { get => BigEndian.ToUInt16(Data, 0x22); set => BigEndian.GetBytes((ushort)value).CopyTo(Data, 0x22); }
|
||||
public override int Stat_HPMax { get => BigEndian.ToUInt16(Data, 0x24); set => BigEndian.GetBytes((ushort)value).CopyTo(Data, 0x24); }
|
||||
public override int Stat_ATK { get => BigEndian.ToUInt16(Data, 0x26); set => BigEndian.GetBytes((ushort)value).CopyTo(Data, 0x26); }
|
||||
public override int Stat_DEF { get => BigEndian.ToUInt16(Data, 0x28); set => BigEndian.GetBytes((ushort)value).CopyTo(Data, 0x28); }
|
||||
public override int Stat_SPE { get => BigEndian.ToUInt16(Data, 0x2A); set => BigEndian.GetBytes((ushort)value).CopyTo(Data, 0x2A); }
|
||||
public override int Stat_SPA { get => BigEndian.ToUInt16(Data, 0x2C); set => BigEndian.GetBytes((ushort)value).CopyTo(Data, 0x2C); }
|
||||
public override int Stat_SPD { get => BigEndian.ToUInt16(Data, 0x2E); set => BigEndian.GetBytes((ushort)value).CopyTo(Data, 0x2E); }
|
||||
public override int Stat_HPCurrent { get => ReadUInt16BigEndian(Data.AsSpan(0x22)); set => WriteUInt16BigEndian(Data.AsSpan(0x22), (ushort)value); }
|
||||
public override int Stat_HPMax { get => ReadUInt16BigEndian(Data.AsSpan(0x24)); set => WriteUInt16BigEndian(Data.AsSpan(0x24), (ushort)value); }
|
||||
public override int Stat_ATK { get => ReadUInt16BigEndian(Data.AsSpan(0x26)); set => WriteUInt16BigEndian(Data.AsSpan(0x26), (ushort)value); }
|
||||
public override int Stat_DEF { get => ReadUInt16BigEndian(Data.AsSpan(0x28)); set => WriteUInt16BigEndian(Data.AsSpan(0x28), (ushort)value); }
|
||||
public override int Stat_SPE { get => ReadUInt16BigEndian(Data.AsSpan(0x2A)); set => WriteUInt16BigEndian(Data.AsSpan(0x2A), (ushort)value); }
|
||||
public override int Stat_SPA { get => ReadUInt16BigEndian(Data.AsSpan(0x2C)); set => WriteUInt16BigEndian(Data.AsSpan(0x2C), (ushort)value); }
|
||||
public override int Stat_SPD { get => ReadUInt16BigEndian(Data.AsSpan(0x2E)); set => WriteUInt16BigEndian(Data.AsSpan(0x2E), (ushort)value); }
|
||||
#endregion
|
||||
|
||||
public override bool IsEgg { get; set; }
|
||||
|
@ -119,8 +121,8 @@ namespace PKHeX.Core
|
|||
pk1.Stat_Level = Stat_Level;
|
||||
}
|
||||
// Status = 0
|
||||
pk1.OT_Trash = RawOT;
|
||||
pk1.Nickname_Trash = RawNickname;
|
||||
OT_Trash.CopyTo(pk1.OT_Trash);
|
||||
Nickname_Trash.CopyTo(pk1.OT_Trash);
|
||||
|
||||
pk1.ClearInvalidMoves();
|
||||
|
||||
|
@ -168,15 +170,15 @@ namespace PKHeX.Core
|
|||
|
||||
// IVs
|
||||
var special = Species is 151 or 251;
|
||||
var new_ivs = new int[6];
|
||||
Span<int> finalIVs = stackalloc int[6];
|
||||
int flawless = special ? 5 : 3;
|
||||
var rnd = Util.Rand;
|
||||
for (var i = 0; i < new_ivs.Length; i++)
|
||||
new_ivs[i] = rnd.Next(32);
|
||||
for (var i = 0; i < finalIVs.Length; i++)
|
||||
finalIVs[i] = rnd.Next(32);
|
||||
for (var i = 0; i < flawless; i++)
|
||||
new_ivs[i] = 31;
|
||||
Util.Shuffle(new_ivs);
|
||||
pk7.IVs = new_ivs;
|
||||
finalIVs[i] = 31;
|
||||
Util.Shuffle(finalIVs);
|
||||
pk7.SetIVs(finalIVs);
|
||||
|
||||
switch (IsShiny ? Shiny.Always : Shiny.Never)
|
||||
{
|
||||
|
|
|
@ -1,10 +1,11 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using static System.Buffers.Binary.BinaryPrimitives;
|
||||
|
||||
namespace PKHeX.Core
|
||||
{
|
||||
/// <summary> Generation 3 <see cref="PKM"/> format. </summary>
|
||||
public sealed class PK3 : G3PKM
|
||||
public sealed class PK3 : G3PKM, ISanityChecksum
|
||||
{
|
||||
private static readonly ushort[] Unused =
|
||||
{
|
||||
|
@ -37,33 +38,38 @@ namespace PKHeX.Core
|
|||
return pk;
|
||||
}
|
||||
|
||||
private string GetString(int offset, int count) => StringConverter3.GetString3(Data, offset, count, Japanese);
|
||||
private byte[] SetString(string value, int maxLength) => StringConverter3.SetString3(value, maxLength, Japanese);
|
||||
|
||||
private const string EggNameJapanese = "タマゴ";
|
||||
|
||||
// Trash Bytes
|
||||
public override Span<byte> Nickname_Trash { get => Data.AsSpan(0x08, 10); set { if (value.Length == 10) value.CopyTo(Data.AsSpan(0x08)); } }
|
||||
public override Span<byte> OT_Trash { get => Data.AsSpan(0x14, 7); set { if (value.Length == 7) value.CopyTo(Data.AsSpan(0x14)); } }
|
||||
public override Span<byte> Nickname_Trash => Data.AsSpan(0x08, 10); // no inaccessible terminator
|
||||
public override Span<byte> OT_Trash => Data.AsSpan(0x14, 7); // no inaccessible terminator
|
||||
|
||||
// At top for System.Reflection execution order hack
|
||||
|
||||
// 0x20 Intro
|
||||
public override uint PID { get => BitConverter.ToUInt32(Data, 0x00); set => BitConverter.GetBytes(value).CopyTo(Data, 0x00); }
|
||||
public override int TID { get => BitConverter.ToUInt16(Data, 0x04); set => BitConverter.GetBytes((ushort)value).CopyTo(Data, 0x04); }
|
||||
public override int SID { get => BitConverter.ToUInt16(Data, 0x06); set => BitConverter.GetBytes((ushort)value).CopyTo(Data, 0x06); }
|
||||
public override string Nickname { get => GetString(0x08, 10); set => SetString(IsEgg ? EggNameJapanese : value, 10).CopyTo(Data, 0x08); }
|
||||
public override uint PID { get => ReadUInt32LittleEndian(Data.AsSpan(0x00)); set => WriteUInt32LittleEndian(Data.AsSpan(0x00), value); }
|
||||
public override int TID { get => ReadUInt16LittleEndian(Data.AsSpan(0x04)); set => WriteUInt16LittleEndian(Data.AsSpan(0x04), (ushort)value); }
|
||||
public override int SID { get => ReadUInt16LittleEndian(Data.AsSpan(0x06)); set => WriteUInt16LittleEndian(Data.AsSpan(0x06), (ushort)value); }
|
||||
public override string Nickname
|
||||
{
|
||||
get => StringConverter3.GetString(Nickname_Trash, Japanese);
|
||||
set => StringConverter3.SetString(Nickname_Trash, (IsEgg ? EggNameJapanese : value).AsSpan(), 10, Japanese, StringConverterOption.None);
|
||||
}
|
||||
public override int Language { get => Data[0x12]; set => Data[0x12] = (byte)value; }
|
||||
public bool FlagIsBadEgg { get => (Data[0x13] & 1) != 0; set => Data[0x13] = (byte)((Data[0x13] & ~1) | (value ? 1 : 0)); }
|
||||
public bool FlagHasSpecies { get => (Data[0x13] & 2) != 0; set => Data[0x13] = (byte)((Data[0x13] & ~2) | (value ? 2 : 0)); }
|
||||
public bool FlagIsEgg { get => (Data[0x13] & 4) != 0; set => Data[0x13] = (byte)((Data[0x13] & ~4) | (value ? 4 : 0)); }
|
||||
public override string OT_Name { get => GetString(0x14, 7); set => SetString(value, 7).CopyTo(Data, 0x14); }
|
||||
public override string OT_Name
|
||||
{
|
||||
get => StringConverter3.GetString(OT_Trash, Japanese);
|
||||
set => StringConverter3.SetString(OT_Trash, value.AsSpan(), 7, Japanese, StringConverterOption.None);
|
||||
}
|
||||
public override int MarkValue { get => SwapBits(Data[0x1B], 1, 2); protected set => Data[0x1B] = (byte)SwapBits(value, 1, 2); }
|
||||
public override ushort Checksum { get => BitConverter.ToUInt16(Data, 0x1C); set => BitConverter.GetBytes(value).CopyTo(Data, 0x1C); }
|
||||
public override ushort Sanity { get => BitConverter.ToUInt16(Data, 0x1E); set => BitConverter.GetBytes(value).CopyTo(Data, 0x1E); }
|
||||
public ushort Checksum { get => ReadUInt16LittleEndian(Data.AsSpan(0x1C)); set => WriteUInt16LittleEndian(Data.AsSpan(0x1C), value); }
|
||||
public ushort Sanity { get => ReadUInt16LittleEndian(Data.AsSpan(0x1E)); set => WriteUInt16LittleEndian(Data.AsSpan(0x1E), value); }
|
||||
|
||||
#region Block A
|
||||
public int SpeciesID3 { get => BitConverter.ToUInt16(Data, 0x20); set => BitConverter.GetBytes((ushort)value).CopyTo(Data, 0x20); } // raw access
|
||||
public int SpeciesID3 { get => ReadUInt16LittleEndian(Data.AsSpan(0x20)); set => WriteUInt16LittleEndian(Data.AsSpan(0x20), (ushort)value); } // raw access
|
||||
|
||||
public override int Species
|
||||
{
|
||||
|
@ -76,9 +82,9 @@ namespace PKHeX.Core
|
|||
}
|
||||
|
||||
public override int SpriteItem => ItemConverter.GetItemFuture3((ushort)HeldItem);
|
||||
public override int HeldItem { get => BitConverter.ToUInt16(Data, 0x22); set => BitConverter.GetBytes((ushort)value).CopyTo(Data, 0x22); }
|
||||
public override int HeldItem { get => ReadUInt16LittleEndian(Data.AsSpan(0x22)); set => WriteUInt16LittleEndian(Data.AsSpan(0x22), (ushort)value); }
|
||||
|
||||
public override uint EXP { get => BitConverter.ToUInt32(Data, 0x24); set => BitConverter.GetBytes(value).CopyTo(Data, 0x24); }
|
||||
public override uint EXP { get => ReadUInt32LittleEndian(Data.AsSpan(0x24)); set => WriteUInt32LittleEndian(Data.AsSpan(0x24), value); }
|
||||
private byte PPUps { get => Data[0x28]; set => Data[0x28] = value; }
|
||||
public override int Move1_PPUps { get => (PPUps >> 0) & 3; set => PPUps = (byte)((PPUps & ~(3 << 0)) | value << 0); }
|
||||
public override int Move2_PPUps { get => (PPUps >> 2) & 3; set => PPUps = (byte)((PPUps & ~(3 << 2)) | value << 2); }
|
||||
|
@ -89,10 +95,10 @@ namespace PKHeX.Core
|
|||
#endregion
|
||||
|
||||
#region Block B
|
||||
public override int Move1 { get => BitConverter.ToUInt16(Data, 0x2C); set => BitConverter.GetBytes((ushort)value).CopyTo(Data, 0x2C); }
|
||||
public override int Move2 { get => BitConverter.ToUInt16(Data, 0x2E); set => BitConverter.GetBytes((ushort)value).CopyTo(Data, 0x2E); }
|
||||
public override int Move3 { get => BitConverter.ToUInt16(Data, 0x30); set => BitConverter.GetBytes((ushort)value).CopyTo(Data, 0x30); }
|
||||
public override int Move4 { get => BitConverter.ToUInt16(Data, 0x32); set => BitConverter.GetBytes((ushort)value).CopyTo(Data, 0x32); }
|
||||
public override int Move1 { get => ReadUInt16LittleEndian(Data.AsSpan(0x2C)); set => WriteUInt16LittleEndian(Data.AsSpan(0x2C), (ushort)value); }
|
||||
public override int Move2 { get => ReadUInt16LittleEndian(Data.AsSpan(0x2E)); set => WriteUInt16LittleEndian(Data.AsSpan(0x2E), (ushort)value); }
|
||||
public override int Move3 { get => ReadUInt16LittleEndian(Data.AsSpan(0x30)); set => WriteUInt16LittleEndian(Data.AsSpan(0x30), (ushort)value); }
|
||||
public override int Move4 { get => ReadUInt16LittleEndian(Data.AsSpan(0x32)); set => WriteUInt16LittleEndian(Data.AsSpan(0x32), (ushort)value); }
|
||||
public override int Move1_PP { get => Data[0x34]; set => Data[0x34] = (byte)value; }
|
||||
public override int Move2_PP { get => Data[0x35]; set => Data[0x35] = (byte)value; }
|
||||
public override int Move3_PP { get => Data[0x36]; set => Data[0x36] = (byte)value; }
|
||||
|
@ -120,13 +126,13 @@ namespace PKHeX.Core
|
|||
public override int PKRS_Strain { get => PKRS >> 4; set => PKRS = (byte)((PKRS & 0xF) | value << 4); }
|
||||
public override int Met_Location { get => Data[0x45]; set => Data[0x45] = (byte)value; }
|
||||
// Origins
|
||||
private ushort Origins { get => BitConverter.ToUInt16(Data, 0x46); set => BitConverter.GetBytes(value).CopyTo(Data, 0x46); }
|
||||
private ushort Origins { get => ReadUInt16LittleEndian(Data.AsSpan(0x46)); set => WriteUInt16LittleEndian(Data.AsSpan(0x46), value); }
|
||||
public override int Met_Level { get => Origins & 0x7F; set => Origins = (ushort)((Origins & ~0x7F) | value); }
|
||||
public override int Version { get => (Origins >> 7) & 0xF; set => Origins = (ushort)((Origins & ~0x780) | ((value & 0xF) << 7)); }
|
||||
public override int Ball { get => (Origins >> 11) & 0xF; set => Origins = (ushort)((Origins & ~0x7800) | ((value & 0xF) << 11)); }
|
||||
public override int OT_Gender { get => (Origins >> 15) & 1; set => Origins = (ushort)((Origins & ~(1 << 15)) | ((value & 1) << 15)); }
|
||||
|
||||
public uint IV32 { get => BitConverter.ToUInt32(Data, 0x48); set => BitConverter.GetBytes(value).CopyTo(Data, 0x48); }
|
||||
public uint IV32 { get => ReadUInt32LittleEndian(Data.AsSpan(0x48)); set => WriteUInt32LittleEndian(Data.AsSpan(0x48), value); }
|
||||
public override int IV_HP { get => (int)(IV32 >> 00) & 0x1F; set => IV32 = (IV32 & ~(0x1Fu << 00)) | ((value > 31 ? 31u : (uint)value) << 00); }
|
||||
public override int IV_ATK { get => (int)(IV32 >> 05) & 0x1F; set => IV32 = (IV32 & ~(0x1Fu << 05)) | ((value > 31 ? 31u : (uint)value) << 05); }
|
||||
public override int IV_DEF { get => (int)(IV32 >> 10) & 0x1F; set => IV32 = (IV32 & ~(0x1Fu << 10)) | ((value > 31 ? 31u : (uint)value) << 10); }
|
||||
|
@ -151,7 +157,7 @@ namespace PKHeX.Core
|
|||
|
||||
public override bool AbilityBit { get => IV32 >> 31 == 1; set => IV32 = (IV32 & 0x7FFFFFFF) | (value ? 1u << 31 : 0u); }
|
||||
|
||||
private uint RIB0 { get => BitConverter.ToUInt32(Data, 0x4C); set => BitConverter.GetBytes(value).CopyTo(Data, 0x4C); }
|
||||
private uint RIB0 { get => ReadUInt32LittleEndian(Data.AsSpan(0x4C)); set => WriteUInt32LittleEndian(Data.AsSpan(0x4C), value); }
|
||||
public override int RibbonCountG3Cool { get => (int)(RIB0 >> 00) & 7; set => RIB0 = ((RIB0 & ~(7u << 00)) | (uint)(value & 7) << 00); }
|
||||
public override int RibbonCountG3Beauty { get => (int)(RIB0 >> 03) & 7; set => RIB0 = ((RIB0 & ~(7u << 03)) | (uint)(value & 7) << 03); }
|
||||
public override int RibbonCountG3Cute { get => (int)(RIB0 >> 06) & 7; set => RIB0 = ((RIB0 & ~(7u << 06)) | (uint)(value & 7) << 06); }
|
||||
|
@ -177,16 +183,16 @@ namespace PKHeX.Core
|
|||
#endregion
|
||||
|
||||
#region Battle Stats
|
||||
public override int Status_Condition { get => BitConverter.ToInt32(Data, 0x50); set => BitConverter.GetBytes(value).CopyTo(Data, 0x50); }
|
||||
public override int Status_Condition { get => ReadInt32LittleEndian(Data.AsSpan(0x50)); set => WriteInt32LittleEndian(Data.AsSpan(0x50), value); }
|
||||
public override int Stat_Level { get => Data[0x54]; set => Data[0x54] = (byte)value; }
|
||||
public sbyte HeldMailID { get => (sbyte)Data[0x55]; set => Data[0x55] = (byte)value; }
|
||||
public override int Stat_HPCurrent { get => BitConverter.ToUInt16(Data, 0x56); set => BitConverter.GetBytes((ushort)value).CopyTo(Data, 0x56); }
|
||||
public override int Stat_HPMax { get => BitConverter.ToUInt16(Data, 0x58); set => BitConverter.GetBytes((ushort)value).CopyTo(Data, 0x58); }
|
||||
public override int Stat_ATK { get => BitConverter.ToUInt16(Data, 0x5A); set => BitConverter.GetBytes((ushort)value).CopyTo(Data, 0x5A); }
|
||||
public override int Stat_DEF { get => BitConverter.ToUInt16(Data, 0x5C); set => BitConverter.GetBytes((ushort)value).CopyTo(Data, 0x5C); }
|
||||
public override int Stat_SPE { get => BitConverter.ToUInt16(Data, 0x5E); set => BitConverter.GetBytes((ushort)value).CopyTo(Data, 0x5E); }
|
||||
public override int Stat_SPA { get => BitConverter.ToUInt16(Data, 0x60); set => BitConverter.GetBytes((ushort)value).CopyTo(Data, 0x60); }
|
||||
public override int Stat_SPD { get => BitConverter.ToUInt16(Data, 0x62); set => BitConverter.GetBytes((ushort)value).CopyTo(Data, 0x62); }
|
||||
public override int Stat_HPCurrent { get => ReadUInt16LittleEndian(Data.AsSpan(0x56)); set => WriteUInt16LittleEndian(Data.AsSpan(0x56), (ushort)value); }
|
||||
public override int Stat_HPMax { get => ReadUInt16LittleEndian(Data.AsSpan(0x58)); set => WriteUInt16LittleEndian(Data.AsSpan(0x58), (ushort)value); }
|
||||
public override int Stat_ATK { get => ReadUInt16LittleEndian(Data.AsSpan(0x5A)); set => WriteUInt16LittleEndian(Data.AsSpan(0x5A), (ushort)value); }
|
||||
public override int Stat_DEF { get => ReadUInt16LittleEndian(Data.AsSpan(0x5C)); set => WriteUInt16LittleEndian(Data.AsSpan(0x5C), (ushort)value); }
|
||||
public override int Stat_SPE { get => ReadUInt16LittleEndian(Data.AsSpan(0x5E)); set => WriteUInt16LittleEndian(Data.AsSpan(0x5E), (ushort)value); }
|
||||
public override int Stat_SPA { get => ReadUInt16LittleEndian(Data.AsSpan(0x60)); set => WriteUInt16LittleEndian(Data.AsSpan(0x60), (ushort)value); }
|
||||
public override int Stat_SPD { get => ReadUInt16LittleEndian(Data.AsSpan(0x62)); set => WriteUInt16LittleEndian(Data.AsSpan(0x62), (ushort)value); }
|
||||
#endregion
|
||||
|
||||
protected override byte[] Encrypt()
|
||||
|
@ -198,10 +204,11 @@ namespace PKHeX.Core
|
|||
public override void RefreshChecksum()
|
||||
{
|
||||
FlagIsBadEgg = false;
|
||||
base.RefreshChecksum();
|
||||
Checksum = PokeCrypto.GetCHK3(Data);
|
||||
}
|
||||
|
||||
protected override ushort CalculateChecksum() => PokeCrypto.GetCHK3(Data);
|
||||
public override bool ChecksumValid => CalculateChecksum() == Checksum;
|
||||
private ushort CalculateChecksum() => PokeCrypto.GetCHK3(Data);
|
||||
|
||||
public PK4 ConvertToPK4()
|
||||
{
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using static System.Buffers.Binary.BinaryPrimitives;
|
||||
|
||||
namespace PKHeX.Core
|
||||
{
|
||||
|
@ -30,20 +31,17 @@ namespace PKHeX.Core
|
|||
|
||||
public override PKM Clone() => new PK4((byte[])Data.Clone());
|
||||
|
||||
private string GetString(int offset, int count) => StringConverter4.GetString4(Data, offset, count);
|
||||
private static byte[] SetString(string value, int maxLength) => StringConverter4.SetString4(value, maxLength);
|
||||
|
||||
// Structure
|
||||
public override uint PID { get => BitConverter.ToUInt32(Data, 0x00); set => BitConverter.GetBytes(value).CopyTo(Data, 0x00); }
|
||||
public override ushort Sanity { get => BitConverter.ToUInt16(Data, 0x04); set => BitConverter.GetBytes(value).CopyTo(Data, 0x04); }
|
||||
public override ushort Checksum { get => BitConverter.ToUInt16(Data, 0x06); set => BitConverter.GetBytes(value).CopyTo(Data, 0x06); }
|
||||
public override uint PID { get => ReadUInt32LittleEndian(Data.AsSpan(0x00)); set => WriteUInt32LittleEndian(Data.AsSpan(0x00), value); }
|
||||
public override ushort Sanity { get => ReadUInt16LittleEndian(Data.AsSpan(0x04)); set => WriteUInt16LittleEndian(Data.AsSpan(0x04), value); }
|
||||
public override ushort Checksum { get => ReadUInt16LittleEndian(Data.AsSpan(0x06)); set => WriteUInt16LittleEndian(Data.AsSpan(0x06), value); }
|
||||
|
||||
#region Block A
|
||||
public override int Species { get => BitConverter.ToUInt16(Data, 0x08); set => BitConverter.GetBytes((ushort)value).CopyTo(Data, 0x08); }
|
||||
public override int HeldItem { get => BitConverter.ToUInt16(Data, 0x0A); set => BitConverter.GetBytes((ushort)value).CopyTo(Data, 0x0A); }
|
||||
public override int TID { get => BitConverter.ToUInt16(Data, 0x0C); set => BitConverter.GetBytes((ushort)value).CopyTo(Data, 0x0C); }
|
||||
public override int SID { get => BitConverter.ToUInt16(Data, 0x0E); set => BitConverter.GetBytes((ushort)value).CopyTo(Data, 0x0E); }
|
||||
public override uint EXP { get => BitConverter.ToUInt32(Data, 0x10); set => BitConverter.GetBytes(value).CopyTo(Data, 0x10); }
|
||||
public override int Species { get => ReadUInt16LittleEndian(Data.AsSpan(0x08)); set => WriteUInt16LittleEndian(Data.AsSpan(0x08), (ushort)value); }
|
||||
public override int HeldItem { get => ReadUInt16LittleEndian(Data.AsSpan(0x0A)); set => WriteUInt16LittleEndian(Data.AsSpan(0x0A), (ushort)value); }
|
||||
public override int TID { get => ReadUInt16LittleEndian(Data.AsSpan(0x0C)); set => WriteUInt16LittleEndian(Data.AsSpan(0x0C), (ushort)value); }
|
||||
public override int SID { get => ReadUInt16LittleEndian(Data.AsSpan(0x0E)); set => WriteUInt16LittleEndian(Data.AsSpan(0x0E), (ushort)value); }
|
||||
public override uint EXP { get => ReadUInt32LittleEndian(Data.AsSpan(0x10)); set => WriteUInt32LittleEndian(Data.AsSpan(0x10), value); }
|
||||
public override int OT_Friendship { get => Data[0x14]; set => Data[0x14] = (byte)value; }
|
||||
public override int Ability { get => Data[0x15]; set => Data[0x15] = (byte)value; }
|
||||
public override int MarkValue { get => Data[0x16]; protected set => Data[0x16] = (byte)value; }
|
||||
|
@ -100,10 +98,10 @@ namespace PKHeX.Core
|
|||
#endregion
|
||||
|
||||
#region Block B
|
||||
public override int Move1 { get => BitConverter.ToUInt16(Data, 0x28); set => BitConverter.GetBytes((ushort)value).CopyTo(Data, 0x28); }
|
||||
public override int Move2 { get => BitConverter.ToUInt16(Data, 0x2A); set => BitConverter.GetBytes((ushort)value).CopyTo(Data, 0x2A); }
|
||||
public override int Move3 { get => BitConverter.ToUInt16(Data, 0x2C); set => BitConverter.GetBytes((ushort)value).CopyTo(Data, 0x2C); }
|
||||
public override int Move4 { get => BitConverter.ToUInt16(Data, 0x2E); set => BitConverter.GetBytes((ushort)value).CopyTo(Data, 0x2E); }
|
||||
public override int Move1 { get => ReadUInt16LittleEndian(Data.AsSpan(0x28)); set => WriteUInt16LittleEndian(Data.AsSpan(0x28), (ushort)value); }
|
||||
public override int Move2 { get => ReadUInt16LittleEndian(Data.AsSpan(0x2A)); set => WriteUInt16LittleEndian(Data.AsSpan(0x2A), (ushort)value); }
|
||||
public override int Move3 { get => ReadUInt16LittleEndian(Data.AsSpan(0x2C)); set => WriteUInt16LittleEndian(Data.AsSpan(0x2C), (ushort)value); }
|
||||
public override int Move4 { get => ReadUInt16LittleEndian(Data.AsSpan(0x2E)); set => WriteUInt16LittleEndian(Data.AsSpan(0x2E), (ushort)value); }
|
||||
public override int Move1_PP { get => Data[0x30]; set => Data[0x30] = (byte)value; }
|
||||
public override int Move2_PP { get => Data[0x31]; set => Data[0x31] = (byte)value; }
|
||||
public override int Move3_PP { get => Data[0x32]; set => Data[0x32] = (byte)value; }
|
||||
|
@ -112,7 +110,7 @@ namespace PKHeX.Core
|
|||
public override int Move2_PPUps { get => Data[0x35]; set => Data[0x35] = (byte)value; }
|
||||
public override int Move3_PPUps { get => Data[0x36]; set => Data[0x36] = (byte)value; }
|
||||
public override int Move4_PPUps { get => Data[0x37]; set => Data[0x37] = (byte)value; }
|
||||
public uint IV32 { get => BitConverter.ToUInt32(Data, 0x38); set => BitConverter.GetBytes(value).CopyTo(Data, 0x38); }
|
||||
public uint IV32 { get => ReadUInt32LittleEndian(Data.AsSpan(0x38)); set => WriteUInt32LittleEndian(Data.AsSpan(0x38), value); }
|
||||
public override int IV_HP { get => (int)(IV32 >> 00) & 0x1F; set => IV32 = (IV32 & ~(0x1Fu << 00)) | ((value > 31 ? 31u : (uint)value) << 00); }
|
||||
public override int IV_ATK { get => (int)(IV32 >> 05) & 0x1F; set => IV32 = (IV32 & ~(0x1Fu << 05)) | ((value > 31 ? 31u : (uint)value) << 05); }
|
||||
public override int IV_DEF { get => (int)(IV32 >> 10) & 0x1F; set => IV32 = (IV32 & ~(0x1Fu << 10)) | ((value > 31 ? 31u : (uint)value) << 10); }
|
||||
|
@ -163,11 +161,28 @@ namespace PKHeX.Core
|
|||
public override int Gender { get => (Data[0x40] >> 1) & 0x3; set => Data[0x40] = (byte)((Data[0x40] & ~0x06) | (value << 1)); }
|
||||
public override int Form { get => Data[0x40] >> 3; set => Data[0x40] = (byte)((Data[0x40] & 0x07) | (value << 3)); }
|
||||
public override int ShinyLeaf { get => Data[0x41]; set => Data[0x41] = (byte) value; }
|
||||
// 0x43-0x47 Unused
|
||||
// 0x42-0x43 Unused
|
||||
public override ushort Egg_LocationExtended
|
||||
{
|
||||
get => ReadUInt16LittleEndian(Data.AsSpan(0x44));
|
||||
set => WriteUInt16LittleEndian(Data.AsSpan(0x44), value);
|
||||
}
|
||||
|
||||
public override ushort Met_LocationExtended
|
||||
{
|
||||
get => ReadUInt16LittleEndian(Data.AsSpan(0x46));
|
||||
set => WriteUInt16LittleEndian(Data.AsSpan(0x46), value);
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Block C
|
||||
public override string Nickname { get => GetString(0x48, 20); set => SetString(value, 10).CopyTo(Data, 0x48); }
|
||||
public override string Nickname
|
||||
{
|
||||
get => StringConverter4.GetString(Nickname_Trash);
|
||||
set => StringConverter4.SetString(Nickname_Trash, value.AsSpan(), 10, StringConverterOption.None);
|
||||
}
|
||||
|
||||
// 0x5E unused
|
||||
public override int Version { get => Data[0x5F]; set => Data[0x5F] = (byte)value; }
|
||||
private byte RIB8 { get => Data[0x60]; set => Data[0x60] = value; } // Sinnoh 3
|
||||
|
@ -210,7 +225,12 @@ namespace PKHeX.Core
|
|||
#endregion
|
||||
|
||||
#region Block D
|
||||
public override string OT_Name { get => GetString(0x68, 14); set => SetString(value, 7).CopyTo(Data, 0x68); }
|
||||
public override string OT_Name
|
||||
{
|
||||
get => StringConverter4.GetString(OT_Trash);
|
||||
set => StringConverter4.SetString(OT_Trash, value.AsSpan(), 7, StringConverterOption.None);
|
||||
}
|
||||
|
||||
public override int Egg_Year { get => Data[0x78]; set => Data[0x78] = (byte)value; }
|
||||
public override int Egg_Month { get => Data[0x79]; set => Data[0x79] = (byte)value; }
|
||||
public override int Egg_Day { get => Data[0x7A]; set => Data[0x7A] = (byte)value; }
|
||||
|
@ -218,66 +238,15 @@ namespace PKHeX.Core
|
|||
public override int Met_Month { get => Data[0x7C]; set => Data[0x7C] = (byte)value; }
|
||||
public override int Met_Day { get => Data[0x7D]; set => Data[0x7D] = (byte)value; }
|
||||
|
||||
public override int Egg_Location
|
||||
public override ushort Egg_LocationDP
|
||||
{
|
||||
get
|
||||
{
|
||||
ushort hgssloc = BitConverter.ToUInt16(Data, 0x44);
|
||||
if (hgssloc != 0)
|
||||
return hgssloc;
|
||||
return BitConverter.ToUInt16(Data, 0x7E);
|
||||
}
|
||||
set
|
||||
{
|
||||
if (value == 0)
|
||||
{
|
||||
BitConverter.GetBytes((ushort)0).CopyTo(Data, 0x44);
|
||||
BitConverter.GetBytes((ushort)0).CopyTo(Data, 0x7E);
|
||||
}
|
||||
else if (Locations.IsPtHGSSLocation(value) || Locations.IsPtHGSSLocationEgg(value))
|
||||
{
|
||||
// Met location not in DP, set to Faraway Place
|
||||
BitConverter.GetBytes((ushort)value).CopyTo(Data, 0x44);
|
||||
BitConverter.GetBytes((ushort)0xBBA).CopyTo(Data, 0x7E);
|
||||
}
|
||||
else
|
||||
{
|
||||
int pthgss = PtHGSS ? value : 0; // only set to PtHGSS loc if encountered in game
|
||||
BitConverter.GetBytes((ushort)pthgss).CopyTo(Data, 0x44);
|
||||
BitConverter.GetBytes((ushort)value).CopyTo(Data, 0x7E);
|
||||
}
|
||||
}
|
||||
get => ReadUInt16LittleEndian(Data.AsSpan(0x7E));
|
||||
set => WriteUInt16LittleEndian(Data.AsSpan(0x7E), value);
|
||||
}
|
||||
|
||||
public override int Met_Location
|
||||
public override ushort Met_LocationDP
|
||||
{
|
||||
get
|
||||
{
|
||||
ushort hgssloc = BitConverter.ToUInt16(Data, 0x46);
|
||||
if (hgssloc != 0)
|
||||
return hgssloc;
|
||||
return BitConverter.ToUInt16(Data, 0x80);
|
||||
}
|
||||
set
|
||||
{
|
||||
if (value == 0)
|
||||
{
|
||||
BitConverter.GetBytes((ushort)0).CopyTo(Data, 0x46);
|
||||
BitConverter.GetBytes((ushort)0).CopyTo(Data, 0x80);
|
||||
}
|
||||
else if (Locations.IsPtHGSSLocation(value) || Locations.IsPtHGSSLocationEgg(value))
|
||||
{
|
||||
// Met location not in DP, set to Faraway Place
|
||||
BitConverter.GetBytes((ushort)value).CopyTo(Data, 0x46);
|
||||
BitConverter.GetBytes((ushort)0xBBA).CopyTo(Data, 0x80);
|
||||
}
|
||||
else
|
||||
{
|
||||
int pthgss = PtHGSS ? value : 0; // only set to PtHGSS loc if encountered in game
|
||||
BitConverter.GetBytes((ushort)pthgss).CopyTo(Data, 0x46);
|
||||
BitConverter.GetBytes((ushort)value).CopyTo(Data, 0x80);
|
||||
}
|
||||
}
|
||||
get => ReadUInt16LittleEndian(Data.AsSpan(0x80));
|
||||
set => WriteUInt16LittleEndian(Data.AsSpan(0x80), value);
|
||||
}
|
||||
|
||||
private byte PKRS { get => Data[0x82]; set => Data[0x82] = value; }
|
||||
|
@ -292,15 +261,15 @@ namespace PKHeX.Core
|
|||
#endregion
|
||||
|
||||
#region Battle Stats
|
||||
public override int Status_Condition { get => BitConverter.ToInt32(Data, 0x88); set => BitConverter.GetBytes(value).CopyTo(Data, 0x88); }
|
||||
public override int Status_Condition { get => ReadInt32LittleEndian(Data.AsSpan(0x88)); set => WriteInt32LittleEndian(Data.AsSpan(0x88), value); }
|
||||
public override int Stat_Level { get => Data[0x8C]; set => Data[0x8C] = (byte)value; }
|
||||
public override int Stat_HPCurrent { get => BitConverter.ToUInt16(Data, 0x8E); set => BitConverter.GetBytes((ushort)value).CopyTo(Data, 0x8E); }
|
||||
public override int Stat_HPMax { get => BitConverter.ToUInt16(Data, 0x90); set => BitConverter.GetBytes((ushort)value).CopyTo(Data, 0x90); }
|
||||
public override int Stat_ATK { get => BitConverter.ToUInt16(Data, 0x92); set => BitConverter.GetBytes((ushort)value).CopyTo(Data, 0x92); }
|
||||
public override int Stat_DEF { get => BitConverter.ToUInt16(Data, 0x94); set => BitConverter.GetBytes((ushort)value).CopyTo(Data, 0x94); }
|
||||
public override int Stat_SPE { get => BitConverter.ToUInt16(Data, 0x96); set => BitConverter.GetBytes((ushort)value).CopyTo(Data, 0x96); }
|
||||
public override int Stat_SPA { get => BitConverter.ToUInt16(Data, 0x98); set => BitConverter.GetBytes((ushort)value).CopyTo(Data, 0x98); }
|
||||
public override int Stat_SPD { get => BitConverter.ToUInt16(Data, 0x9A); set => BitConverter.GetBytes((ushort)value).CopyTo(Data, 0x9A); }
|
||||
public override int Stat_HPCurrent { get => ReadUInt16LittleEndian(Data.AsSpan(0x8E)); set => WriteUInt16LittleEndian(Data.AsSpan(0x8E), (ushort)value); }
|
||||
public override int Stat_HPMax { get => ReadUInt16LittleEndian(Data.AsSpan(0x90)); set => WriteUInt16LittleEndian(Data.AsSpan(0x90), (ushort)value); }
|
||||
public override int Stat_ATK { get => ReadUInt16LittleEndian(Data.AsSpan(0x92)); set => WriteUInt16LittleEndian(Data.AsSpan(0x92), (ushort)value); }
|
||||
public override int Stat_DEF { get => ReadUInt16LittleEndian(Data.AsSpan(0x94)); set => WriteUInt16LittleEndian(Data.AsSpan(0x94), (ushort)value); }
|
||||
public override int Stat_SPE { get => ReadUInt16LittleEndian(Data.AsSpan(0x96)); set => WriteUInt16LittleEndian(Data.AsSpan(0x96), (ushort)value); }
|
||||
public override int Stat_SPA { get => ReadUInt16LittleEndian(Data.AsSpan(0x98)); set => WriteUInt16LittleEndian(Data.AsSpan(0x98), (ushort)value); }
|
||||
public override int Stat_SPD { get => ReadUInt16LittleEndian(Data.AsSpan(0x9A)); set => WriteUInt16LittleEndian(Data.AsSpan(0x9A), (ushort)value); }
|
||||
|
||||
public byte[] GetHeldMailData() => Data.Slice(0x9C, 0x38);
|
||||
public void SetHeldMailData(byte[] value) => value.CopyTo(Data, 0x9C);
|
||||
|
@ -330,7 +299,7 @@ namespace PKHeX.Core
|
|||
public PK5 ConvertToPK5()
|
||||
{
|
||||
// Double Check Location Data to see if we're already a PK5
|
||||
if (Data[0x5F] < 0x10 && BitConverter.ToUInt16(Data, 0x80) > 0x4000)
|
||||
if (Data[0x5F] < 0x10 && ReadUInt16LittleEndian(Data.AsSpan(0x80)) > 0x4000)
|
||||
return new PK5(Data);
|
||||
|
||||
DateTime moment = DateTime.Now;
|
||||
|
@ -360,7 +329,7 @@ namespace PKHeX.Core
|
|||
pk5.Nature = Nature;
|
||||
|
||||
// Delete Platinum/HGSS Met Location Data
|
||||
BitConverter.GetBytes((uint)0).CopyTo(pk5.Data, 0x44);
|
||||
WriteUInt32LittleEndian(pk5.Data.AsSpan(0x44), 0);
|
||||
|
||||
// Met / Crown Data Detection
|
||||
pk5.Met_Location = Legal.GetTransfer45MetLocation(pk5);
|
||||
|
@ -369,7 +338,7 @@ namespace PKHeX.Core
|
|||
// pk5.Egg_Location = Egg_Location;
|
||||
|
||||
// Delete HGSS Data
|
||||
BitConverter.GetBytes((ushort)0).CopyTo(pk5.Data, 0x86);
|
||||
WriteUInt16LittleEndian(pk5.Data.AsSpan(0x86), 0);
|
||||
pk5.Ball = Ball;
|
||||
|
||||
// Transfer Nickname and OT Name, update encoding
|
||||
|
|
|
@ -1,10 +1,11 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using static System.Buffers.Binary.BinaryPrimitives;
|
||||
|
||||
namespace PKHeX.Core
|
||||
{
|
||||
/// <summary> Generation 5 <see cref="PKM"/> format. </summary>
|
||||
public sealed class PK5 : PKM,
|
||||
public sealed class PK5 : PKM, ISanityChecksum,
|
||||
IRibbonSetEvent3, IRibbonSetEvent4, IRibbonSetUnique3, IRibbonSetUnique4, IRibbonSetCommon3, IRibbonSetCommon4,
|
||||
IContestStats, IContestStatsMutable, IGroundTile
|
||||
{
|
||||
|
@ -36,13 +37,14 @@ namespace PKHeX.Core
|
|||
}
|
||||
|
||||
public override PKM Clone() => new PK5((byte[])Data.Clone());
|
||||
|
||||
private string GetString(int offset, int count) => StringConverter.GetString5(Data, offset, count);
|
||||
private static byte[] SetString(string value, int maxLength) => StringConverter.SetString5(value, maxLength);
|
||||
public override void RefreshChecksum() => Checksum = CalculateChecksum();
|
||||
public override bool ChecksumValid => CalculateChecksum() == Checksum;
|
||||
public override bool Valid { get => Sanity == 0 && ChecksumValid; set { if (!value) return; Sanity = 0; RefreshChecksum(); } }
|
||||
private ushort CalculateChecksum() => PokeCrypto.GetCHK(Data, PokeCrypto.SIZE_4STORED);
|
||||
|
||||
// Trash Bytes
|
||||
public override Span<byte> Nickname_Trash { get => Data.AsSpan(0x48, 22); set { if (value.Length == 22) value.CopyTo(Data.AsSpan(0x48)); } }
|
||||
public override Span<byte> OT_Trash { get => Data.AsSpan(0x68, 16); set { if (value.Length == 16) value.CopyTo(Data.AsSpan(0x68)); } }
|
||||
public override Span<byte> Nickname_Trash => Data.AsSpan(0x48, 22);
|
||||
public override Span<byte> OT_Trash => Data.AsSpan(0x68, 16);
|
||||
|
||||
// Future Attributes
|
||||
public override uint EncryptionConstant { get => PID; set { } }
|
||||
|
@ -51,16 +53,16 @@ namespace PKHeX.Core
|
|||
public override int AbilityNumber { get => HiddenAbility ? 4 : 1 << PIDAbility; set { } }
|
||||
|
||||
// Structure
|
||||
public override uint PID { get => BitConverter.ToUInt32(Data, 0x00); set => BitConverter.GetBytes(value).CopyTo(Data, 0x00); }
|
||||
public override ushort Sanity { get => BitConverter.ToUInt16(Data, 0x04); set => BitConverter.GetBytes(value).CopyTo(Data, 0x04); }
|
||||
public override ushort Checksum { get => BitConverter.ToUInt16(Data, 0x06); set => BitConverter.GetBytes(value).CopyTo(Data, 0x06); }
|
||||
public override uint PID { get => ReadUInt32LittleEndian(Data.AsSpan(0x00)); set => WriteUInt32LittleEndian(Data.AsSpan(0x00), value); }
|
||||
public ushort Sanity { get => ReadUInt16LittleEndian(Data.AsSpan(0x04)); set => WriteUInt16LittleEndian(Data.AsSpan(0x04), value); }
|
||||
public ushort Checksum { get => ReadUInt16LittleEndian(Data.AsSpan(0x06)); set => WriteUInt16LittleEndian(Data.AsSpan(0x06), value); }
|
||||
|
||||
#region Block A
|
||||
public override int Species { get => BitConverter.ToUInt16(Data, 0x08); set => BitConverter.GetBytes((ushort)value).CopyTo(Data, 0x08); }
|
||||
public override int HeldItem { get => BitConverter.ToUInt16(Data, 0x0A); set => BitConverter.GetBytes((ushort)value).CopyTo(Data, 0x0A); }
|
||||
public override int TID { get => BitConverter.ToUInt16(Data, 0x0C); set => BitConverter.GetBytes((ushort)value).CopyTo(Data, 0x0C); }
|
||||
public override int SID { get => BitConverter.ToUInt16(Data, 0x0E); set => BitConverter.GetBytes((ushort)value).CopyTo(Data, 0x0E); }
|
||||
public override uint EXP { get => BitConverter.ToUInt32(Data, 0x10); set => BitConverter.GetBytes(value).CopyTo(Data, 0x10); }
|
||||
public override int Species { get => ReadUInt16LittleEndian(Data.AsSpan(0x08)); set => WriteUInt16LittleEndian(Data.AsSpan(0x08), (ushort)value); }
|
||||
public override int HeldItem { get => ReadUInt16LittleEndian(Data.AsSpan(0x0A)); set => WriteUInt16LittleEndian(Data.AsSpan(0x0A), (ushort)value); }
|
||||
public override int TID { get => ReadUInt16LittleEndian(Data.AsSpan(0x0C)); set => WriteUInt16LittleEndian(Data.AsSpan(0x0C), (ushort)value); }
|
||||
public override int SID { get => ReadUInt16LittleEndian(Data.AsSpan(0x0E)); set => WriteUInt16LittleEndian(Data.AsSpan(0x0E), (ushort)value); }
|
||||
public override uint EXP { get => ReadUInt32LittleEndian(Data.AsSpan(0x10)); set => WriteUInt32LittleEndian(Data.AsSpan(0x10), value); }
|
||||
public override int OT_Friendship { get => Data[0x14]; set => Data[0x14] = (byte)value; }
|
||||
public override int Ability { get => Data[0x15]; set => Data[0x15] = (byte)value; }
|
||||
public override int MarkValue { get => Data[0x16]; protected set => Data[0x16] = (byte)value; }
|
||||
|
@ -117,10 +119,10 @@ namespace PKHeX.Core
|
|||
#endregion
|
||||
|
||||
#region Block B
|
||||
public override int Move1 { get => BitConverter.ToUInt16(Data, 0x28); set => BitConverter.GetBytes((ushort)value).CopyTo(Data, 0x28); }
|
||||
public override int Move2 { get => BitConverter.ToUInt16(Data, 0x2A); set => BitConverter.GetBytes((ushort)value).CopyTo(Data, 0x2A); }
|
||||
public override int Move3 { get => BitConverter.ToUInt16(Data, 0x2C); set => BitConverter.GetBytes((ushort)value).CopyTo(Data, 0x2C); }
|
||||
public override int Move4 { get => BitConverter.ToUInt16(Data, 0x2E); set => BitConverter.GetBytes((ushort)value).CopyTo(Data, 0x2E); }
|
||||
public override int Move1 { get => ReadUInt16LittleEndian(Data.AsSpan(0x28)); set => WriteUInt16LittleEndian(Data.AsSpan(0x28), (ushort)value); }
|
||||
public override int Move2 { get => ReadUInt16LittleEndian(Data.AsSpan(0x2A)); set => WriteUInt16LittleEndian(Data.AsSpan(0x2A), (ushort)value); }
|
||||
public override int Move3 { get => ReadUInt16LittleEndian(Data.AsSpan(0x2C)); set => WriteUInt16LittleEndian(Data.AsSpan(0x2C), (ushort)value); }
|
||||
public override int Move4 { get => ReadUInt16LittleEndian(Data.AsSpan(0x2E)); set => WriteUInt16LittleEndian(Data.AsSpan(0x2E), (ushort)value); }
|
||||
public override int Move1_PP { get => Data[0x30]; set => Data[0x30] = (byte)value; }
|
||||
public override int Move2_PP { get => Data[0x31]; set => Data[0x31] = (byte)value; }
|
||||
public override int Move3_PP { get => Data[0x32]; set => Data[0x32] = (byte)value; }
|
||||
|
@ -129,7 +131,7 @@ namespace PKHeX.Core
|
|||
public override int Move2_PPUps { get => Data[0x35]; set => Data[0x35] = (byte)value; }
|
||||
public override int Move3_PPUps { get => Data[0x36]; set => Data[0x36] = (byte)value; }
|
||||
public override int Move4_PPUps { get => Data[0x37]; set => Data[0x37] = (byte)value; }
|
||||
private uint IV32 { get => BitConverter.ToUInt32(Data, 0x38); set => BitConverter.GetBytes(value).CopyTo(Data, 0x38); }
|
||||
private uint IV32 { get => ReadUInt32LittleEndian(Data.AsSpan(0x38)); set => WriteUInt32LittleEndian(Data.AsSpan(0x38), value); }
|
||||
public override int IV_HP { get => (int)(IV32 >> 00) & 0x1F; set => IV32 = (IV32 & ~(0x1Fu << 00)) | ((value > 31 ? 31u : (uint)value) << 00); }
|
||||
public override int IV_ATK { get => (int)(IV32 >> 05) & 0x1F; set => IV32 = (IV32 & ~(0x1Fu << 05)) | ((value > 31 ? 31u : (uint)value) << 05); }
|
||||
public override int IV_DEF { get => (int)(IV32 >> 10) & 0x1F; set => IV32 = (IV32 & ~(0x1Fu << 10)) | ((value > 31 ? 31u : (uint)value) << 10); }
|
||||
|
@ -186,7 +188,7 @@ namespace PKHeX.Core
|
|||
#endregion
|
||||
|
||||
#region Block C
|
||||
public override string Nickname { get => GetString(0x48, 20); set => SetString(value, 10).CopyTo(Data, 0x48); }
|
||||
public override string Nickname { get => StringConverter5.GetString(Nickname_Trash); set => StringConverter5.SetString(Nickname_Trash, value.AsSpan(), 10, StringConverterOption.None); }
|
||||
// 0x5E unused
|
||||
public override int Version { get => Data[0x5F]; set => Data[0x5F] = (byte)value; }
|
||||
private byte RIB8 { get => Data[0x60]; set => Data[0x60] = value; } // Sinnoh 3
|
||||
|
@ -229,15 +231,15 @@ namespace PKHeX.Core
|
|||
#endregion
|
||||
|
||||
#region Block D
|
||||
public override string OT_Name { get => GetString(0x68, 14); set => SetString(value, 7).CopyTo(Data, 0x68); }
|
||||
public override string OT_Name { get => StringConverter5.GetString(OT_Trash); set => StringConverter5.SetString(OT_Trash, value.AsSpan(), 7, StringConverterOption.None); }
|
||||
public override int Egg_Year { get => Data[0x78]; set => Data[0x78] = (byte)value; }
|
||||
public override int Egg_Month { get => Data[0x79]; set => Data[0x79] = (byte)value; }
|
||||
public override int Egg_Day { get => Data[0x7A]; set => Data[0x7A] = (byte)value; }
|
||||
public override int Met_Year { get => Data[0x7B]; set => Data[0x7B] = (byte)value; }
|
||||
public override int Met_Month { get => Data[0x7C]; set => Data[0x7C] = (byte)value; }
|
||||
public override int Met_Day { get => Data[0x7D]; set => Data[0x7D] = (byte)value; }
|
||||
public override int Egg_Location { get => BitConverter.ToUInt16(Data, 0x7E); set => BitConverter.GetBytes((ushort)value).CopyTo(Data, 0x7E); }
|
||||
public override int Met_Location { get => BitConverter.ToUInt16(Data, 0x80); set => BitConverter.GetBytes((ushort)value).CopyTo(Data, 0x80); }
|
||||
public override int Egg_Location { get => ReadUInt16LittleEndian(Data.AsSpan(0x7E)); set => WriteUInt16LittleEndian(Data.AsSpan(0x7E), (ushort)value); }
|
||||
public override int Met_Location { get => ReadUInt16LittleEndian(Data.AsSpan(0x80)); set => WriteUInt16LittleEndian(Data.AsSpan(0x80), (ushort)value); }
|
||||
private byte PKRS { get => Data[0x82]; set => Data[0x82] = value; }
|
||||
public override int PKRS_Days { get => PKRS & 0xF; set => PKRS = (byte)((PKRS & ~0xF) | value); }
|
||||
public override int PKRS_Strain { get => PKRS >> 4; set => PKRS = (byte)((PKRS & 0xF) | (value << 4)); }
|
||||
|
@ -251,15 +253,15 @@ namespace PKHeX.Core
|
|||
#endregion
|
||||
|
||||
#region Battle Stats
|
||||
public override int Status_Condition { get => BitConverter.ToInt32(Data, 0x88); set => BitConverter.GetBytes(value).CopyTo(Data, 0x88); }
|
||||
public override int Status_Condition { get => ReadInt32LittleEndian(Data.AsSpan(0x88)); set => WriteInt32LittleEndian(Data.AsSpan(0x88), value); }
|
||||
public override int Stat_Level { get => Data[0x8C]; set => Data[0x8C] = (byte)value; }
|
||||
public override int Stat_HPCurrent { get => BitConverter.ToUInt16(Data, 0x8E); set => BitConverter.GetBytes((ushort)value).CopyTo(Data, 0x8E); }
|
||||
public override int Stat_HPMax { get => BitConverter.ToUInt16(Data, 0x90); set => BitConverter.GetBytes((ushort)value).CopyTo(Data, 0x90); }
|
||||
public override int Stat_ATK { get => BitConverter.ToUInt16(Data, 0x92); set => BitConverter.GetBytes((ushort)value).CopyTo(Data, 0x92); }
|
||||
public override int Stat_DEF { get => BitConverter.ToUInt16(Data, 0x94); set => BitConverter.GetBytes((ushort)value).CopyTo(Data, 0x94); }
|
||||
public override int Stat_SPE { get => BitConverter.ToUInt16(Data, 0x96); set => BitConverter.GetBytes((ushort)value).CopyTo(Data, 0x96); }
|
||||
public override int Stat_SPA { get => BitConverter.ToUInt16(Data, 0x98); set => BitConverter.GetBytes((ushort)value).CopyTo(Data, 0x98); }
|
||||
public override int Stat_SPD { get => BitConverter.ToUInt16(Data, 0x9A); set => BitConverter.GetBytes((ushort)value).CopyTo(Data, 0x9A); }
|
||||
public override int Stat_HPCurrent { get => ReadUInt16LittleEndian(Data.AsSpan(0x8E)); set => WriteUInt16LittleEndian(Data.AsSpan(0x8E), (ushort)value); }
|
||||
public override int Stat_HPMax { get => ReadUInt16LittleEndian(Data.AsSpan(0x90)); set => WriteUInt16LittleEndian(Data.AsSpan(0x90), (ushort)value); }
|
||||
public override int Stat_ATK { get => ReadUInt16LittleEndian(Data.AsSpan(0x92)); set => WriteUInt16LittleEndian(Data.AsSpan(0x92), (ushort)value); }
|
||||
public override int Stat_DEF { get => ReadUInt16LittleEndian(Data.AsSpan(0x94)); set => WriteUInt16LittleEndian(Data.AsSpan(0x94), (ushort)value); }
|
||||
public override int Stat_SPE { get => ReadUInt16LittleEndian(Data.AsSpan(0x96)); set => WriteUInt16LittleEndian(Data.AsSpan(0x96), (ushort)value); }
|
||||
public override int Stat_SPA { get => ReadUInt16LittleEndian(Data.AsSpan(0x98)); set => WriteUInt16LittleEndian(Data.AsSpan(0x98), (ushort)value); }
|
||||
public override int Stat_SPD { get => ReadUInt16LittleEndian(Data.AsSpan(0x9A)); set => WriteUInt16LittleEndian(Data.AsSpan(0x9A), (ushort)value); }
|
||||
|
||||
public byte[] GetHeldMailData() => Data.Slice(0x9C, 0x38);
|
||||
public void SetHeldMailData(byte[] value) => value.CopyTo(Data, 0x9C);
|
||||
|
@ -476,8 +478,8 @@ namespace PKHeX.Core
|
|||
pk6.HealPP();
|
||||
|
||||
// Fix Name Strings
|
||||
pk6.Nickname = StringConverter345.TransferGlyphs56(pk6.Nickname);
|
||||
pk6.OT_Name = StringConverter345.TransferGlyphs56(pk6.OT_Name);
|
||||
StringConverter345.TransferGlyphs56(pk6.Nickname_Trash);
|
||||
StringConverter345.TransferGlyphs56(pk6.OT_Trash);
|
||||
|
||||
// Fix Checksum
|
||||
pk6.RefreshChecksum();
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using static System.Buffers.Binary.BinaryPrimitives;
|
||||
|
||||
namespace PKHeX.Core
|
||||
{
|
||||
|
@ -29,57 +30,54 @@ namespace PKHeX.Core
|
|||
|
||||
public override PKM Clone() => new PK6((byte[])Data.Clone());
|
||||
|
||||
private string GetString(int offset, int count) => StringConverter.GetString6(Data, offset, count);
|
||||
private static byte[] SetString(string value, int maxLength) => StringConverter.SetString6(value, maxLength);
|
||||
|
||||
// Structure
|
||||
#region Block A
|
||||
public override uint EncryptionConstant
|
||||
{
|
||||
get => BitConverter.ToUInt32(Data, 0x00);
|
||||
set => BitConverter.GetBytes(value).CopyTo(Data, 0x00);
|
||||
get => ReadUInt32LittleEndian(Data.AsSpan(0x00));
|
||||
set => WriteUInt32LittleEndian(Data.AsSpan(0x00), value);
|
||||
}
|
||||
|
||||
public override ushort Sanity
|
||||
{
|
||||
get => BitConverter.ToUInt16(Data, 0x04);
|
||||
set => BitConverter.GetBytes(value).CopyTo(Data, 0x04);
|
||||
get => ReadUInt16LittleEndian(Data.AsSpan(0x04));
|
||||
set => WriteUInt16LittleEndian(Data.AsSpan(0x04), value);
|
||||
}
|
||||
|
||||
public override ushort Checksum
|
||||
{
|
||||
get => BitConverter.ToUInt16(Data, 0x06);
|
||||
set => BitConverter.GetBytes(value).CopyTo(Data, 0x06);
|
||||
get => ReadUInt16LittleEndian(Data.AsSpan(0x06));
|
||||
set => WriteUInt16LittleEndian(Data.AsSpan(0x06), value);
|
||||
}
|
||||
|
||||
public override int Species
|
||||
{
|
||||
get => BitConverter.ToUInt16(Data, 0x08);
|
||||
set => BitConverter.GetBytes((ushort)value).CopyTo(Data, 0x08);
|
||||
get => ReadUInt16LittleEndian(Data.AsSpan(0x08));
|
||||
set => WriteUInt16LittleEndian(Data.AsSpan(0x08), (ushort)value);
|
||||
}
|
||||
|
||||
public override int HeldItem
|
||||
{
|
||||
get => BitConverter.ToUInt16(Data, 0x0A);
|
||||
set => BitConverter.GetBytes((ushort)value).CopyTo(Data, 0x0A);
|
||||
get => ReadUInt16LittleEndian(Data.AsSpan(0x0A));
|
||||
set => WriteUInt16LittleEndian(Data.AsSpan(0x0A), (ushort)value);
|
||||
}
|
||||
|
||||
public override int TID
|
||||
{
|
||||
get => BitConverter.ToUInt16(Data, 0x0C);
|
||||
set => BitConverter.GetBytes((ushort)value).CopyTo(Data, 0x0C);
|
||||
get => ReadUInt16LittleEndian(Data.AsSpan(0x0C));
|
||||
set => WriteUInt16LittleEndian(Data.AsSpan(0x0C), (ushort)value);
|
||||
}
|
||||
|
||||
public override int SID
|
||||
{
|
||||
get => BitConverter.ToUInt16(Data, 0x0E);
|
||||
set => BitConverter.GetBytes((ushort)value).CopyTo(Data, 0x0E);
|
||||
get => ReadUInt16LittleEndian(Data.AsSpan(0x0E));
|
||||
set => WriteUInt16LittleEndian(Data.AsSpan(0x0E), (ushort)value);
|
||||
}
|
||||
|
||||
public override uint EXP
|
||||
{
|
||||
get => BitConverter.ToUInt32(Data, 0x10);
|
||||
set => BitConverter.GetBytes(value).CopyTo(Data, 0x10);
|
||||
get => ReadUInt32LittleEndian(Data.AsSpan(0x10));
|
||||
set => WriteUInt32LittleEndian(Data.AsSpan(0x10), value);
|
||||
}
|
||||
|
||||
public override int Ability { get => Data[0x14]; set => Data[0x14] = (byte)value; }
|
||||
|
@ -89,8 +87,8 @@ namespace PKHeX.Core
|
|||
|
||||
public override uint PID
|
||||
{
|
||||
get => BitConverter.ToUInt32(Data, 0x18);
|
||||
set => BitConverter.GetBytes(value).CopyTo(Data, 0x18);
|
||||
get => ReadUInt32LittleEndian(Data.AsSpan(0x18));
|
||||
set => WriteUInt32LittleEndian(Data.AsSpan(0x18), value);
|
||||
}
|
||||
|
||||
public override int Nature { get => Data[0x1C]; set => Data[0x1C] = (byte)value; }
|
||||
|
@ -149,7 +147,7 @@ namespace PKHeX.Core
|
|||
public bool SuperTrain7_2 { get => (ST4 & (1 << 5)) == 1 << 5; set => ST4 = (byte)((ST4 & ~(1 << 5)) | (value ? 1 << 5 : 0)); }
|
||||
public bool SuperTrain7_3 { get => (ST4 & (1 << 6)) == 1 << 6; set => ST4 = (byte)((ST4 & ~(1 << 6)) | (value ? 1 << 6 : 0)); }
|
||||
public bool SuperTrain8_1 { get => (ST4 & (1 << 7)) == 1 << 7; set => ST4 = (byte)((ST4 & ~(1 << 7)) | (value ? 1 << 7 : 0)); }
|
||||
public uint SuperTrainBitFlags { get => BitConverter.ToUInt32(Data, 0x2C); set => BitConverter.GetBytes(value).CopyTo(Data); }
|
||||
public uint SuperTrainBitFlags { get => ReadUInt32LittleEndian(Data.AsSpan(0x2C)); set => WriteUInt32LittleEndian(Data.AsSpan(0x2C), value); }
|
||||
private byte RIB0 { get => Data[0x30]; set => Data[0x30] = value; } // Ribbons are read as uints, but let's keep them per byte.
|
||||
private byte RIB1 { get => Data[0x31]; set => Data[0x31] = value; }
|
||||
private byte RIB2 { get => Data[0x32]; set => Data[0x32] = value; }
|
||||
|
@ -206,7 +204,7 @@ namespace PKHeX.Core
|
|||
public bool RIB5_7 { get => (RIB5 & (1 << 7)) == 1 << 7; set => RIB5 = (byte)((RIB5 & ~(1 << 7)) | (value ? 1 << 7 : 0)); } // Unused
|
||||
public int RibbonCountMemoryContest { get => Data[0x38]; set => HasContestMemoryRibbon = (Data[0x38] = (byte)value) != 0; }
|
||||
public int RibbonCountMemoryBattle { get => Data[0x39]; set => HasBattleMemoryRibbon = (Data[0x39] = (byte)value) != 0; }
|
||||
private ushort DistByte { get => BitConverter.ToUInt16(Data, 0x3A); set => BitConverter.GetBytes(value).CopyTo(Data, 0x3A); }
|
||||
private ushort DistByte { get => ReadUInt16LittleEndian(Data.AsSpan(0x3A)); set => WriteUInt16LittleEndian(Data.AsSpan(0x3A), value); }
|
||||
public bool DistSuperTrain1 { get => (DistByte & (1 << 0)) == 1 << 0; set => DistByte = (byte)((DistByte & ~(1 << 0)) | (value ? 1 << 0 : 0)); }
|
||||
public bool DistSuperTrain2 { get => (DistByte & (1 << 1)) == 1 << 1; set => DistByte = (byte)((DistByte & ~(1 << 1)) | (value ? 1 << 1 : 0)); }
|
||||
public bool DistSuperTrain3 { get => (DistByte & (1 << 2)) == 1 << 2; set => DistByte = (byte)((DistByte & ~(1 << 2)) | (value ? 1 << 2 : 0)); }
|
||||
|
@ -215,34 +213,38 @@ namespace PKHeX.Core
|
|||
public bool DistSuperTrain6 { get => (DistByte & (1 << 5)) == 1 << 5; set => DistByte = (byte)((DistByte & ~(1 << 5)) | (value ? 1 << 5 : 0)); }
|
||||
public bool Dist7 { get => (DistByte & (1 << 6)) == 1 << 6; set => DistByte = (byte)((DistByte & ~(1 << 6)) | (value ? 1 << 6 : 0)); }
|
||||
public bool Dist8 { get => (DistByte & (1 << 7)) == 1 << 7; set => DistByte = (byte)((DistByte & ~(1 << 7)) | (value ? 1 << 7 : 0)); }
|
||||
public uint FormArgument { get => BitConverter.ToUInt32(Data, 0x3C); set => BitConverter.GetBytes(value).CopyTo(Data, 0x3C); }
|
||||
public uint FormArgument { get => ReadUInt32LittleEndian(Data.AsSpan(0x3C)); set => WriteUInt32LittleEndian(Data.AsSpan(0x3C), value); }
|
||||
public byte FormArgumentMaximum { get => (byte)FormArgument; set => FormArgument = value & 0xFFu; }
|
||||
#endregion
|
||||
#region Block B
|
||||
public override string Nickname { get => GetString(0x40, 24); set => SetString(value, 12).CopyTo(Data, 0x40); }
|
||||
public override string Nickname
|
||||
{
|
||||
get => StringConverter6.GetString(Nickname_Trash);
|
||||
set => StringConverter6.SetString(Nickname_Trash, value.AsSpan(), 12, StringConverterOption.None);
|
||||
}
|
||||
|
||||
public override int Move1
|
||||
{
|
||||
get => BitConverter.ToUInt16(Data, 0x5A);
|
||||
set => BitConverter.GetBytes((ushort)value).CopyTo(Data, 0x5A);
|
||||
get => ReadUInt16LittleEndian(Data.AsSpan(0x5A));
|
||||
set => WriteUInt16LittleEndian(Data.AsSpan(0x5A), (ushort)value);
|
||||
}
|
||||
|
||||
public override int Move2
|
||||
{
|
||||
get => BitConverter.ToUInt16(Data, 0x5C);
|
||||
set => BitConverter.GetBytes((ushort)value).CopyTo(Data, 0x5C);
|
||||
get => ReadUInt16LittleEndian(Data.AsSpan(0x5C));
|
||||
set => WriteUInt16LittleEndian(Data.AsSpan(0x5C), (ushort)value);
|
||||
}
|
||||
|
||||
public override int Move3
|
||||
{
|
||||
get => BitConverter.ToUInt16(Data, 0x5E);
|
||||
set => BitConverter.GetBytes((ushort)value).CopyTo(Data, 0x5E);
|
||||
get => ReadUInt16LittleEndian(Data.AsSpan(0x5E));
|
||||
set => WriteUInt16LittleEndian(Data.AsSpan(0x5E), (ushort)value);
|
||||
}
|
||||
|
||||
public override int Move4
|
||||
{
|
||||
get => BitConverter.ToUInt16(Data, 0x60);
|
||||
set => BitConverter.GetBytes((ushort)value).CopyTo(Data, 0x60);
|
||||
get => ReadUInt16LittleEndian(Data.AsSpan(0x60));
|
||||
set => WriteUInt16LittleEndian(Data.AsSpan(0x60), (ushort)value);
|
||||
}
|
||||
|
||||
public override int Move1_PP { get => Data[0x62]; set => Data[0x62] = (byte)value; }
|
||||
|
@ -256,32 +258,32 @@ namespace PKHeX.Core
|
|||
|
||||
public override int RelearnMove1
|
||||
{
|
||||
get => BitConverter.ToUInt16(Data, 0x6A);
|
||||
set => BitConverter.GetBytes((ushort)value).CopyTo(Data, 0x6A);
|
||||
get => ReadUInt16LittleEndian(Data.AsSpan(0x6A));
|
||||
set => WriteUInt16LittleEndian(Data.AsSpan(0x6A), (ushort)value);
|
||||
}
|
||||
|
||||
public override int RelearnMove2
|
||||
{
|
||||
get => BitConverter.ToUInt16(Data, 0x6C);
|
||||
set => BitConverter.GetBytes((ushort)value).CopyTo(Data, 0x6C);
|
||||
get => ReadUInt16LittleEndian(Data.AsSpan(0x6C));
|
||||
set => WriteUInt16LittleEndian(Data.AsSpan(0x6C), (ushort)value);
|
||||
}
|
||||
|
||||
public override int RelearnMove3
|
||||
{
|
||||
get => BitConverter.ToUInt16(Data, 0x6E);
|
||||
set => BitConverter.GetBytes((ushort)value).CopyTo(Data, 0x6E);
|
||||
get => ReadUInt16LittleEndian(Data.AsSpan(0x6E));
|
||||
set => WriteUInt16LittleEndian(Data.AsSpan(0x6E), (ushort)value);
|
||||
}
|
||||
|
||||
public override int RelearnMove4
|
||||
{
|
||||
get => BitConverter.ToUInt16(Data, 0x70);
|
||||
set => BitConverter.GetBytes((ushort)value).CopyTo(Data, 0x70);
|
||||
get => ReadUInt16LittleEndian(Data.AsSpan(0x70));
|
||||
set => WriteUInt16LittleEndian(Data.AsSpan(0x70), (ushort)value);
|
||||
}
|
||||
|
||||
public bool SecretSuperTrainingUnlocked { get => (Data[0x72] & 1) == 1; set => Data[0x72] = (byte)((Data[0x72] & ~1) | (value ? 1 : 0)); }
|
||||
public bool SecretSuperTrainingComplete { get => (Data[0x72] & 2) == 2; set => Data[0x72] = (byte)((Data[0x72] & ~2) | (value ? 2 : 0)); }
|
||||
// 0x73 Unused
|
||||
private uint IV32 { get => BitConverter.ToUInt32(Data, 0x74); set => BitConverter.GetBytes(value).CopyTo(Data, 0x74); }
|
||||
private uint IV32 { get => ReadUInt32LittleEndian(Data.AsSpan(0x74)); set => WriteUInt32LittleEndian(Data.AsSpan(0x74), value); }
|
||||
public override int IV_HP { get => (int)(IV32 >> 00) & 0x1F; set => IV32 = (IV32 & ~(0x1Fu << 00)) | ((value > 31 ? 31u : (uint)value) << 00); }
|
||||
public override int IV_ATK { get => (int)(IV32 >> 05) & 0x1F; set => IV32 = (IV32 & ~(0x1Fu << 05)) | ((value > 31 ? 31u : (uint)value) << 05); }
|
||||
public override int IV_DEF { get => (int)(IV32 >> 10) & 0x1F; set => IV32 = (IV32 & ~(0x1Fu << 10)) | ((value > 31 ? 31u : (uint)value) << 10); }
|
||||
|
@ -292,7 +294,11 @@ namespace PKHeX.Core
|
|||
public override bool IsNicknamed { get => ((IV32 >> 31) & 1) == 1; set => IV32 = (IV32 & 0x7FFFFFFFu) | (value ? 0x80000000u : 0u); }
|
||||
#endregion
|
||||
#region Block C
|
||||
public override string HT_Name { get => GetString(0x78, 24); set => SetString(value, 12).CopyTo(Data, 0x78); }
|
||||
public override string HT_Name
|
||||
{
|
||||
get => StringConverter6.GetString(HT_Trash);
|
||||
set => StringConverter6.SetString(HT_Trash, value.AsSpan(), 12, StringConverterOption.None);
|
||||
}
|
||||
public override int HT_Gender { get => Data[0x92]; set => Data[0x92] = (byte)value; }
|
||||
public override int CurrentHandler { get => Data[0x93]; set => Data[0x93] = (byte)value; }
|
||||
public byte Geo1_Region { get => Data[0x94]; set => Data[0x94] = value; }
|
||||
|
@ -315,7 +321,7 @@ namespace PKHeX.Core
|
|||
public int HT_Memory { get => Data[0xA5]; set => Data[0xA5] = (byte)value; }
|
||||
public int HT_Feeling { get => Data[0xA6]; set => Data[0xA6] = (byte)value; }
|
||||
// 0xA7 Unused
|
||||
public int HT_TextVar { get => BitConverter.ToUInt16(Data, 0xA8); set => BitConverter.GetBytes((ushort)value).CopyTo(Data, 0xA8); }
|
||||
public int HT_TextVar { get => ReadUInt16LittleEndian(Data.AsSpan(0xA8)); set => WriteUInt16LittleEndian(Data.AsSpan(0xA8), (ushort)value); }
|
||||
// 0xAA Unused
|
||||
// 0xAB Unused
|
||||
// 0xAC Unused
|
||||
|
@ -324,12 +330,16 @@ namespace PKHeX.Core
|
|||
public override byte Enjoyment { get => Data[0xAF]; set => Data[0xAF] = value; }
|
||||
#endregion
|
||||
#region Block D
|
||||
public override string OT_Name { get => GetString(0xB0, 24); set => SetString(value, 12).CopyTo(Data, 0xB0); }
|
||||
public override string OT_Name
|
||||
{
|
||||
get => StringConverter6.GetString(OT_Trash);
|
||||
set => StringConverter6.SetString(OT_Trash, value.AsSpan(), 12, StringConverterOption.None);
|
||||
}
|
||||
public override int OT_Friendship { get => Data[0xCA]; set => Data[0xCA] = (byte)value; }
|
||||
public int OT_Affection { get => Data[0xCB]; set => Data[0xCB] = (byte)value; }
|
||||
public int OT_Intensity { get => Data[0xCC]; set => Data[0xCC] = (byte)value; }
|
||||
public int OT_Memory { get => Data[0xCD]; set => Data[0xCD] = (byte)value; }
|
||||
public int OT_TextVar { get => BitConverter.ToUInt16(Data, 0xCE); set => BitConverter.GetBytes((ushort)value).CopyTo(Data, 0xCE); }
|
||||
public int OT_TextVar { get => ReadUInt16LittleEndian(Data.AsSpan(0xCE)); set => WriteUInt16LittleEndian(Data.AsSpan(0xCE), (ushort)value); }
|
||||
public int OT_Feeling { get => Data[0xD0]; set => Data[0xD0] = (byte)value; }
|
||||
public override int Egg_Year { get => Data[0xD1]; set => Data[0xD1] = (byte)value; }
|
||||
public override int Egg_Month { get => Data[0xD2]; set => Data[0xD2] = (byte)value; }
|
||||
|
@ -338,8 +348,8 @@ namespace PKHeX.Core
|
|||
public override int Met_Month { get => Data[0xD5]; set => Data[0xD5] = (byte)value; }
|
||||
public override int Met_Day { get => Data[0xD6]; set => Data[0xD6] = (byte)value; }
|
||||
// 0xD7 Unused
|
||||
public override int Egg_Location { get => BitConverter.ToUInt16(Data, 0xD8); set => BitConverter.GetBytes((ushort)value).CopyTo(Data, 0xD8); }
|
||||
public override int Met_Location { get => BitConverter.ToUInt16(Data, 0xDA); set => BitConverter.GetBytes((ushort)value).CopyTo(Data, 0xDA); }
|
||||
public override int Egg_Location { get => ReadUInt16LittleEndian(Data.AsSpan(0xD8)); set => WriteUInt16LittleEndian(Data.AsSpan(0xD8), (ushort)value); }
|
||||
public override int Met_Location { get => ReadUInt16LittleEndian(Data.AsSpan(0xDA)); set => WriteUInt16LittleEndian(Data.AsSpan(0xDA), (ushort)value); }
|
||||
public override int Ball { get => Data[0xDC]; set => Data[0xDC] = (byte)value; }
|
||||
public override int Met_Level { get => Data[0xDD] & ~0x80; set => Data[0xDD] = (byte)((Data[0xDD] & 0x80) | value); }
|
||||
public override int OT_Gender { get => Data[0xDD] >> 7; set => Data[0xDD] = (byte)((Data[0xDD] & ~0x80) | (value << 7)); }
|
||||
|
@ -351,17 +361,17 @@ namespace PKHeX.Core
|
|||
public override int Language { get => Data[0xE3]; set => Data[0xE3] = (byte)value; }
|
||||
#endregion
|
||||
#region Battle Stats
|
||||
public override int Status_Condition { get => BitConverter.ToInt32(Data, 0xE8); set => BitConverter.GetBytes(value).CopyTo(Data, 0xE8); }
|
||||
public override int Status_Condition { get => ReadInt32LittleEndian(Data.AsSpan(0xE8)); set => WriteInt32LittleEndian(Data.AsSpan(0xE8), value); }
|
||||
public override int Stat_Level { get => Data[0xEC]; set => Data[0xEC] = (byte)value; }
|
||||
public byte FormArgumentRemain { get => Data[0xED]; set => Data[0xED] = value; }
|
||||
public byte FormArgumentElapsed { get => Data[0xEE]; set => Data[0xEE] = value; }
|
||||
public override int Stat_HPCurrent { get => BitConverter.ToUInt16(Data, 0xF0); set => BitConverter.GetBytes((ushort)value).CopyTo(Data, 0xF0); }
|
||||
public override int Stat_HPMax { get => BitConverter.ToUInt16(Data, 0xF2); set => BitConverter.GetBytes((ushort)value).CopyTo(Data, 0xF2); }
|
||||
public override int Stat_ATK { get => BitConverter.ToUInt16(Data, 0xF4); set => BitConverter.GetBytes((ushort)value).CopyTo(Data, 0xF4); }
|
||||
public override int Stat_DEF { get => BitConverter.ToUInt16(Data, 0xF6); set => BitConverter.GetBytes((ushort)value).CopyTo(Data, 0xF6); }
|
||||
public override int Stat_SPE { get => BitConverter.ToUInt16(Data, 0xF8); set => BitConverter.GetBytes((ushort)value).CopyTo(Data, 0xF8); }
|
||||
public override int Stat_SPA { get => BitConverter.ToUInt16(Data, 0xFA); set => BitConverter.GetBytes((ushort)value).CopyTo(Data, 0xFA); }
|
||||
public override int Stat_SPD { get => BitConverter.ToUInt16(Data, 0xFC); set => BitConverter.GetBytes((ushort)value).CopyTo(Data, 0xFC); }
|
||||
public override int Stat_HPCurrent { get => ReadUInt16LittleEndian(Data.AsSpan(0xF0)); set => WriteUInt16LittleEndian(Data.AsSpan(0xF0), (ushort)value); }
|
||||
public override int Stat_HPMax { get => ReadUInt16LittleEndian(Data.AsSpan(0xF2)); set => WriteUInt16LittleEndian(Data.AsSpan(0xF2), (ushort)value); }
|
||||
public override int Stat_ATK { get => ReadUInt16LittleEndian(Data.AsSpan(0xF4)); set => WriteUInt16LittleEndian(Data.AsSpan(0xF4), (ushort)value); }
|
||||
public override int Stat_DEF { get => ReadUInt16LittleEndian(Data.AsSpan(0xF6)); set => WriteUInt16LittleEndian(Data.AsSpan(0xF6), (ushort)value); }
|
||||
public override int Stat_SPE { get => ReadUInt16LittleEndian(Data.AsSpan(0xF8)); set => WriteUInt16LittleEndian(Data.AsSpan(0xF8), (ushort)value); }
|
||||
public override int Stat_SPA { get => ReadUInt16LittleEndian(Data.AsSpan(0xFA)); set => WriteUInt16LittleEndian(Data.AsSpan(0xFA), (ushort)value); }
|
||||
public override int Stat_SPD { get => ReadUInt16LittleEndian(Data.AsSpan(0xFC)); set => WriteUInt16LittleEndian(Data.AsSpan(0xFC), (ushort)value); }
|
||||
#endregion
|
||||
|
||||
public int SuperTrainingMedalCount(int maxCount = 30)
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using static System.Buffers.Binary.BinaryPrimitives;
|
||||
|
||||
namespace PKHeX.Core
|
||||
{
|
||||
|
@ -30,67 +31,64 @@ namespace PKHeX.Core
|
|||
|
||||
public override PKM Clone() => new PK7((byte[])Data.Clone());
|
||||
|
||||
private string GetString(int offset, int count) => StringConverter.GetString7(Data, offset, count);
|
||||
private byte[] SetString(string value, int maxLength, bool chinese = false) => StringConverter.SetString7(value, maxLength, Language, chinese: chinese);
|
||||
|
||||
// Structure
|
||||
#region Block A
|
||||
public override uint EncryptionConstant
|
||||
{
|
||||
get => BitConverter.ToUInt32(Data, 0x00);
|
||||
set => BitConverter.GetBytes(value).CopyTo(Data, 0x00);
|
||||
get => ReadUInt32LittleEndian(Data.AsSpan(0x00));
|
||||
set => WriteUInt32LittleEndian(Data.AsSpan(0x00), value);
|
||||
}
|
||||
|
||||
public override ushort Sanity
|
||||
{
|
||||
get => BitConverter.ToUInt16(Data, 0x04);
|
||||
set => BitConverter.GetBytes(value).CopyTo(Data, 0x04);
|
||||
get => ReadUInt16LittleEndian(Data.AsSpan(0x04));
|
||||
set => WriteUInt16LittleEndian(Data.AsSpan(0x04), value);
|
||||
}
|
||||
|
||||
public override ushort Checksum
|
||||
{
|
||||
get => BitConverter.ToUInt16(Data, 0x06);
|
||||
set => BitConverter.GetBytes(value).CopyTo(Data, 0x06);
|
||||
get => ReadUInt16LittleEndian(Data.AsSpan(0x06));
|
||||
set => WriteUInt16LittleEndian(Data.AsSpan(0x06), value);
|
||||
}
|
||||
|
||||
public override int Species
|
||||
{
|
||||
get => BitConverter.ToUInt16(Data, 0x08);
|
||||
set => BitConverter.GetBytes((ushort)value).CopyTo(Data, 0x08);
|
||||
get => ReadUInt16LittleEndian(Data.AsSpan(0x08));
|
||||
set => WriteUInt16LittleEndian(Data.AsSpan(0x08), (ushort)value);
|
||||
}
|
||||
|
||||
public override int HeldItem
|
||||
{
|
||||
get => BitConverter.ToUInt16(Data, 0x0A);
|
||||
set => BitConverter.GetBytes((ushort)value).CopyTo(Data, 0x0A);
|
||||
get => ReadUInt16LittleEndian(Data.AsSpan(0x0A));
|
||||
set => WriteUInt16LittleEndian(Data.AsSpan(0x0A), (ushort)value);
|
||||
}
|
||||
|
||||
public override int TID
|
||||
{
|
||||
get => BitConverter.ToUInt16(Data, 0x0C);
|
||||
set => BitConverter.GetBytes((ushort)value).CopyTo(Data, 0x0C);
|
||||
get => ReadUInt16LittleEndian(Data.AsSpan(0x0C));
|
||||
set => WriteUInt16LittleEndian(Data.AsSpan(0x0C), (ushort)value);
|
||||
}
|
||||
|
||||
public override int SID
|
||||
{
|
||||
get => BitConverter.ToUInt16(Data, 0x0E);
|
||||
set => BitConverter.GetBytes((ushort)value).CopyTo(Data, 0x0E);
|
||||
get => ReadUInt16LittleEndian(Data.AsSpan(0x0E));
|
||||
set => WriteUInt16LittleEndian(Data.AsSpan(0x0E), (ushort)value);
|
||||
}
|
||||
|
||||
public override uint EXP
|
||||
{
|
||||
get => BitConverter.ToUInt32(Data, 0x10);
|
||||
set => BitConverter.GetBytes(value).CopyTo(Data, 0x10);
|
||||
get => ReadUInt32LittleEndian(Data.AsSpan(0x10));
|
||||
set => WriteUInt32LittleEndian(Data.AsSpan(0x10), value);
|
||||
}
|
||||
|
||||
public override int Ability { get => Data[0x14]; set => Data[0x14] = (byte)value; }
|
||||
public override int AbilityNumber { get => Data[0x15] & 7; set => Data[0x15] = (byte)((Data[0x15] & ~7) | (value & 7)); }
|
||||
public override int MarkValue { get => BitConverter.ToUInt16(Data, 0x16); protected set => BitConverter.GetBytes((ushort)value).CopyTo(Data, 0x16); }
|
||||
public override int MarkValue { get => ReadUInt16LittleEndian(Data.AsSpan(0x16)); protected set => WriteUInt16LittleEndian(Data.AsSpan(0x16), (ushort)value); }
|
||||
|
||||
public override uint PID
|
||||
{
|
||||
get => BitConverter.ToUInt32(Data, 0x18);
|
||||
set => BitConverter.GetBytes(value).CopyTo(Data, 0x18);
|
||||
get => ReadUInt32LittleEndian(Data.AsSpan(0x18));
|
||||
set => WriteUInt32LittleEndian(Data.AsSpan(0x18), value);
|
||||
}
|
||||
|
||||
public override int Nature { get => Data[0x1C]; set => Data[0x1C] = (byte)value; }
|
||||
|
@ -149,7 +147,7 @@ namespace PKHeX.Core
|
|||
public bool SuperTrain7_2 { get => (ST4 & (1 << 5)) == 1 << 5; set => ST4 = (byte)((ST4 & ~(1 << 5)) | (value ? 1 << 5 : 0)); }
|
||||
public bool SuperTrain7_3 { get => (ST4 & (1 << 6)) == 1 << 6; set => ST4 = (byte)((ST4 & ~(1 << 6)) | (value ? 1 << 6 : 0)); }
|
||||
public bool SuperTrain8_1 { get => (ST4 & (1 << 7)) == 1 << 7; set => ST4 = (byte)((ST4 & ~(1 << 7)) | (value ? 1 << 7 : 0)); }
|
||||
public uint SuperTrainBitFlags { get => BitConverter.ToUInt32(Data, 0x2C); set => BitConverter.GetBytes(value).CopyTo(Data); }
|
||||
public uint SuperTrainBitFlags { get => ReadUInt32LittleEndian(Data.AsSpan(0x2C)); set => WriteUInt32LittleEndian(Data.AsSpan(0x2C), value); }
|
||||
private byte RIB0 { get => Data[0x30]; set => Data[0x30] = value; } // Ribbons are read as uints, but let's keep them per byte.
|
||||
private byte RIB1 { get => Data[0x31]; set => Data[0x31] = value; }
|
||||
private byte RIB2 { get => Data[0x32]; set => Data[0x32] = value; }
|
||||
|
@ -216,7 +214,7 @@ namespace PKHeX.Core
|
|||
public bool RIB6_7 { get => (RIB6 & (1 << 7)) == 1 << 7; set => RIB6 = (byte)((RIB6 & ~(1 << 7)) | (value ? 1 << 7 : 0)); } // Unused
|
||||
public int RibbonCountMemoryContest { get => Data[0x38]; set => HasContestMemoryRibbon = (Data[0x38] = (byte)value) != 0; }
|
||||
public int RibbonCountMemoryBattle { get => Data[0x39]; set => HasBattleMemoryRibbon = (Data[0x39] = (byte)value) != 0; }
|
||||
private ushort DistByte { get => BitConverter.ToUInt16(Data, 0x3A); set => BitConverter.GetBytes(value).CopyTo(Data, 0x3A); }
|
||||
private ushort DistByte { get => ReadUInt16LittleEndian(Data.AsSpan(0x3A)); set => WriteUInt16LittleEndian(Data.AsSpan(0x3A), value); }
|
||||
public bool DistSuperTrain1 { get => (DistByte & (1 << 0)) == 1 << 0; set => DistByte = (byte)((DistByte & ~(1 << 0)) | (value ? 1 << 0 : 0)); }
|
||||
public bool DistSuperTrain2 { get => (DistByte & (1 << 1)) == 1 << 1; set => DistByte = (byte)((DistByte & ~(1 << 1)) | (value ? 1 << 1 : 0)); }
|
||||
public bool DistSuperTrain3 { get => (DistByte & (1 << 2)) == 1 << 2; set => DistByte = (byte)((DistByte & ~(1 << 2)) | (value ? 1 << 2 : 0)); }
|
||||
|
@ -225,7 +223,7 @@ namespace PKHeX.Core
|
|||
public bool DistSuperTrain6 { get => (DistByte & (1 << 5)) == 1 << 5; set => DistByte = (byte)((DistByte & ~(1 << 5)) | (value ? 1 << 5 : 0)); }
|
||||
public bool Dist7 { get => (DistByte & (1 << 6)) == 1 << 6; set => DistByte = (byte)((DistByte & ~(1 << 6)) | (value ? 1 << 6 : 0)); }
|
||||
public bool Dist8 { get => (DistByte & (1 << 7)) == 1 << 7; set => DistByte = (byte)((DistByte & ~(1 << 7)) | (value ? 1 << 7 : 0)); }
|
||||
public uint FormArgument { get => BitConverter.ToUInt32(Data, 0x3C); set => BitConverter.GetBytes(value).CopyTo(Data, 0x3C); }
|
||||
public uint FormArgument { get => ReadUInt32LittleEndian(Data.AsSpan(0x3C)); set => WriteUInt32LittleEndian(Data.AsSpan(0x3C), value); }
|
||||
public byte FormArgumentRemain { get => (byte)FormArgument; set => FormArgument = (FormArgument & ~0xFFu) | value; }
|
||||
public byte FormArgumentElapsed { get => (byte)(FormArgument >> 8); set => FormArgument = (FormArgument & ~0xFF00u) | (uint)(value << 8); }
|
||||
public byte FormArgumentMaximum { get => (byte)(FormArgument >> 16); set => FormArgument = (FormArgument & ~0xFF0000u) | (uint)(value << 16); }
|
||||
|
@ -233,7 +231,7 @@ namespace PKHeX.Core
|
|||
#region Block B
|
||||
public override string Nickname
|
||||
{
|
||||
get => GetString(0x40, 24);
|
||||
get => StringConverter7.GetString(Nickname_Trash);
|
||||
set
|
||||
{
|
||||
if (!IsNicknamed)
|
||||
|
@ -241,36 +239,36 @@ namespace PKHeX.Core
|
|||
int lang = SpeciesName.GetSpeciesNameLanguage(Species, Language, value, 7);
|
||||
if (lang is (int)LanguageID.ChineseS or (int)LanguageID.ChineseT)
|
||||
{
|
||||
StringConverter.SetString7(value, 12, lang, chinese: true).CopyTo(Data, 0x40);
|
||||
StringConverter7.SetString(Nickname_Trash, value.AsSpan(), 12, lang, StringConverterOption.None, chinese: true);
|
||||
return;
|
||||
}
|
||||
}
|
||||
SetString(value, 12).CopyTo(Data, 0x40);
|
||||
StringConverter7.SetString(Nickname_Trash, value.AsSpan(), 12, 0, StringConverterOption.None);
|
||||
}
|
||||
}
|
||||
|
||||
public override int Move1
|
||||
{
|
||||
get => BitConverter.ToUInt16(Data, 0x5A);
|
||||
set => BitConverter.GetBytes((ushort)value).CopyTo(Data, 0x5A);
|
||||
get => ReadUInt16LittleEndian(Data.AsSpan(0x5A));
|
||||
set => WriteUInt16LittleEndian(Data.AsSpan(0x5A), (ushort)value);
|
||||
}
|
||||
|
||||
public override int Move2
|
||||
{
|
||||
get => BitConverter.ToUInt16(Data, 0x5C);
|
||||
set => BitConverter.GetBytes((ushort)value).CopyTo(Data, 0x5C);
|
||||
get => ReadUInt16LittleEndian(Data.AsSpan(0x5C));
|
||||
set => WriteUInt16LittleEndian(Data.AsSpan(0x5C), (ushort)value);
|
||||
}
|
||||
|
||||
public override int Move3
|
||||
{
|
||||
get => BitConverter.ToUInt16(Data, 0x5E);
|
||||
set => BitConverter.GetBytes((ushort)value).CopyTo(Data, 0x5E);
|
||||
get => ReadUInt16LittleEndian(Data.AsSpan(0x5E));
|
||||
set => WriteUInt16LittleEndian(Data.AsSpan(0x5E), (ushort)value);
|
||||
}
|
||||
|
||||
public override int Move4
|
||||
{
|
||||
get => BitConverter.ToUInt16(Data, 0x60);
|
||||
set => BitConverter.GetBytes((ushort)value).CopyTo(Data, 0x60);
|
||||
get => ReadUInt16LittleEndian(Data.AsSpan(0x60));
|
||||
set => WriteUInt16LittleEndian(Data.AsSpan(0x60), (ushort)value);
|
||||
}
|
||||
|
||||
public override int Move1_PP { get => Data[0x62]; set => Data[0x62] = (byte)value; }
|
||||
|
@ -284,32 +282,32 @@ namespace PKHeX.Core
|
|||
|
||||
public override int RelearnMove1
|
||||
{
|
||||
get => BitConverter.ToUInt16(Data, 0x6A);
|
||||
set => BitConverter.GetBytes((ushort)value).CopyTo(Data, 0x6A);
|
||||
get => ReadUInt16LittleEndian(Data.AsSpan(0x6A));
|
||||
set => WriteUInt16LittleEndian(Data.AsSpan(0x6A), (ushort)value);
|
||||
}
|
||||
|
||||
public override int RelearnMove2
|
||||
{
|
||||
get => BitConverter.ToUInt16(Data, 0x6C);
|
||||
set => BitConverter.GetBytes((ushort)value).CopyTo(Data, 0x6C);
|
||||
get => ReadUInt16LittleEndian(Data.AsSpan(0x6C));
|
||||
set => WriteUInt16LittleEndian(Data.AsSpan(0x6C), (ushort)value);
|
||||
}
|
||||
|
||||
public override int RelearnMove3
|
||||
{
|
||||
get => BitConverter.ToUInt16(Data, 0x6E);
|
||||
set => BitConverter.GetBytes((ushort)value).CopyTo(Data, 0x6E);
|
||||
get => ReadUInt16LittleEndian(Data.AsSpan(0x6E));
|
||||
set => WriteUInt16LittleEndian(Data.AsSpan(0x6E), (ushort)value);
|
||||
}
|
||||
|
||||
public override int RelearnMove4
|
||||
{
|
||||
get => BitConverter.ToUInt16(Data, 0x70);
|
||||
set => BitConverter.GetBytes((ushort)value).CopyTo(Data, 0x70);
|
||||
get => ReadUInt16LittleEndian(Data.AsSpan(0x70));
|
||||
set => WriteUInt16LittleEndian(Data.AsSpan(0x70), (ushort)value);
|
||||
}
|
||||
|
||||
public bool SecretSuperTrainingUnlocked { get => (Data[0x72] & 1) == 1; set => Data[0x72] = (byte)((Data[0x72] & ~1) | (value ? 1 : 0)); }
|
||||
public bool SecretSuperTrainingComplete { get => (Data[0x72] & 2) == 2; set => Data[0x72] = (byte)((Data[0x72] & ~2) | (value ? 2 : 0)); }
|
||||
// 0x73 Unused
|
||||
private uint IV32 { get => BitConverter.ToUInt32(Data, 0x74); set => BitConverter.GetBytes(value).CopyTo(Data, 0x74); }
|
||||
private uint IV32 { get => ReadUInt32LittleEndian(Data.AsSpan(0x74)); set => WriteUInt32LittleEndian(Data.AsSpan(0x74), value); }
|
||||
public override int IV_HP { get => (int)(IV32 >> 00) & 0x1F; set => IV32 = (IV32 & ~(0x1Fu << 00)) | ((value > 31 ? 31u : (uint)value) << 00); }
|
||||
public override int IV_ATK { get => (int)(IV32 >> 05) & 0x1F; set => IV32 = (IV32 & ~(0x1Fu << 05)) | ((value > 31 ? 31u : (uint)value) << 05); }
|
||||
public override int IV_DEF { get => (int)(IV32 >> 10) & 0x1F; set => IV32 = (IV32 & ~(0x1Fu << 10)) | ((value > 31 ? 31u : (uint)value) << 10); }
|
||||
|
@ -320,7 +318,12 @@ namespace PKHeX.Core
|
|||
public override bool IsNicknamed { get => ((IV32 >> 31) & 1) == 1; set => IV32 = (IV32 & 0x7FFFFFFFu) | (value ? 0x80000000u : 0u); }
|
||||
#endregion
|
||||
#region Block C
|
||||
public override string HT_Name { get => GetString(0x78, 24); set => SetString(value, 12).CopyTo(Data, 0x78); }
|
||||
public override string HT_Name
|
||||
{
|
||||
get => StringConverter7.GetString(HT_Trash);
|
||||
set => StringConverter7.SetString(HT_Trash, value.AsSpan(), 12, 0, StringConverterOption.None);
|
||||
}
|
||||
|
||||
public override int HT_Gender { get => Data[0x92]; set => Data[0x92] = (byte)value; }
|
||||
public override int CurrentHandler { get => Data[0x93]; set => Data[0x93] = (byte)value; }
|
||||
public byte Geo1_Region { get => Data[0x94]; set => Data[0x94] = value; }
|
||||
|
@ -343,7 +346,7 @@ namespace PKHeX.Core
|
|||
public int HT_Memory { get => Data[0xA5]; set => Data[0xA5] = (byte)value; }
|
||||
public int HT_Feeling { get => Data[0xA6]; set => Data[0xA6] = (byte)value; }
|
||||
// 0xA7 Unused
|
||||
public int HT_TextVar { get => BitConverter.ToUInt16(Data, 0xA8); set => BitConverter.GetBytes((ushort)value).CopyTo(Data, 0xA8); }
|
||||
public int HT_TextVar { get => ReadUInt16LittleEndian(Data.AsSpan(0xA8)); set => WriteUInt16LittleEndian(Data.AsSpan(0xA8), (ushort)value); }
|
||||
// 0xAA Unused
|
||||
// 0xAB Unused
|
||||
// 0xAC Unused
|
||||
|
@ -352,12 +355,17 @@ namespace PKHeX.Core
|
|||
public override byte Enjoyment { get => Data[0xAF]; set => Data[0xAF] = value; }
|
||||
#endregion
|
||||
#region Block D
|
||||
public override string OT_Name { get => GetString(0xB0, 24); set => SetString(value, 12).CopyTo(Data, 0xB0); }
|
||||
public override string OT_Name
|
||||
{
|
||||
get => StringConverter7.GetString(OT_Trash);
|
||||
set => StringConverter7.SetString(OT_Trash, value.AsSpan(), 12, 0, StringConverterOption.None);
|
||||
}
|
||||
|
||||
public override int OT_Friendship { get => Data[0xCA]; set => Data[0xCA] = (byte)value; }
|
||||
public int OT_Affection { get => Data[0xCB]; set => Data[0xCB] = (byte)value; }
|
||||
public int OT_Intensity { get => Data[0xCC]; set => Data[0xCC] = (byte)value; }
|
||||
public int OT_Memory { get => Data[0xCD]; set => Data[0xCD] = (byte)value; }
|
||||
public int OT_TextVar { get => BitConverter.ToUInt16(Data, 0xCE); set => BitConverter.GetBytes((ushort)value).CopyTo(Data, 0xCE); }
|
||||
public int OT_TextVar { get => ReadUInt16LittleEndian(Data.AsSpan(0xCE)); set => WriteUInt16LittleEndian(Data.AsSpan(0xCE), (ushort)value); }
|
||||
public int OT_Feeling { get => Data[0xD0]; set => Data[0xD0] = (byte)value; }
|
||||
public override int Egg_Year { get => Data[0xD1]; set => Data[0xD1] = (byte)value; }
|
||||
public override int Egg_Month { get => Data[0xD2]; set => Data[0xD2] = (byte)value; }
|
||||
|
@ -366,8 +374,8 @@ namespace PKHeX.Core
|
|||
public override int Met_Month { get => Data[0xD5]; set => Data[0xD5] = (byte)value; }
|
||||
public override int Met_Day { get => Data[0xD6]; set => Data[0xD6] = (byte)value; }
|
||||
// Unused 0xD7
|
||||
public override int Egg_Location { get => BitConverter.ToUInt16(Data, 0xD8); set => BitConverter.GetBytes((ushort)value).CopyTo(Data, 0xD8); }
|
||||
public override int Met_Location { get => BitConverter.ToUInt16(Data, 0xDA); set => BitConverter.GetBytes((ushort)value).CopyTo(Data, 0xDA); }
|
||||
public override int Egg_Location { get => ReadUInt16LittleEndian(Data.AsSpan(0xD8)); set => WriteUInt16LittleEndian(Data.AsSpan(0xD8), (ushort)value); }
|
||||
public override int Met_Location { get => ReadUInt16LittleEndian(Data.AsSpan(0xDA)); set => WriteUInt16LittleEndian(Data.AsSpan(0xDA), (ushort)value); }
|
||||
public override int Ball { get => Data[0xDC]; set => Data[0xDC] = (byte)value; }
|
||||
public override int Met_Level { get => Data[0xDD] & ~0x80; set => Data[0xDD] = (byte)((Data[0xDD] & 0x80) | value); }
|
||||
public override int OT_Gender { get => Data[0xDD] >> 7; set => Data[0xDD] = (byte)((Data[0xDD] & ~0x80) | (value << 7)); }
|
||||
|
@ -385,18 +393,18 @@ namespace PKHeX.Core
|
|||
public override int Language { get => Data[0xE3]; set => Data[0xE3] = (byte)value; }
|
||||
#endregion
|
||||
#region Battle Stats
|
||||
public override int Status_Condition { get => BitConverter.ToInt32(Data, 0xE8); set => BitConverter.GetBytes(value).CopyTo(Data, 0xE8); }
|
||||
public override int Status_Condition { get => ReadInt32LittleEndian(Data.AsSpan(0xE8)); set => WriteInt32LittleEndian(Data.AsSpan(0xE8), value); }
|
||||
public override int Stat_Level { get => Data[0xEC]; set => Data[0xEC] = (byte)value; }
|
||||
public byte DirtType { get => Data[0xED]; set => Data[0xED] = value; }
|
||||
public byte DirtLocation { get => Data[0xEE]; set => Data[0xEE] = value; }
|
||||
// 0xEF unused
|
||||
public override int Stat_HPCurrent { get => BitConverter.ToUInt16(Data, 0xF0); set => BitConverter.GetBytes((ushort)value).CopyTo(Data, 0xF0); }
|
||||
public override int Stat_HPMax { get => BitConverter.ToUInt16(Data, 0xF2); set => BitConverter.GetBytes((ushort)value).CopyTo(Data, 0xF2); }
|
||||
public override int Stat_ATK { get => BitConverter.ToUInt16(Data, 0xF4); set => BitConverter.GetBytes((ushort)value).CopyTo(Data, 0xF4); }
|
||||
public override int Stat_DEF { get => BitConverter.ToUInt16(Data, 0xF6); set => BitConverter.GetBytes((ushort)value).CopyTo(Data, 0xF6); }
|
||||
public override int Stat_SPE { get => BitConverter.ToUInt16(Data, 0xF8); set => BitConverter.GetBytes((ushort)value).CopyTo(Data, 0xF8); }
|
||||
public override int Stat_SPA { get => BitConverter.ToUInt16(Data, 0xFA); set => BitConverter.GetBytes((ushort)value).CopyTo(Data, 0xFA); }
|
||||
public override int Stat_SPD { get => BitConverter.ToUInt16(Data, 0xFC); set => BitConverter.GetBytes((ushort)value).CopyTo(Data, 0xFC); }
|
||||
public override int Stat_HPCurrent { get => ReadUInt16LittleEndian(Data.AsSpan(0xF0)); set => WriteUInt16LittleEndian(Data.AsSpan(0xF0), (ushort)value); }
|
||||
public override int Stat_HPMax { get => ReadUInt16LittleEndian(Data.AsSpan(0xF2)); set => WriteUInt16LittleEndian(Data.AsSpan(0xF2), (ushort)value); }
|
||||
public override int Stat_ATK { get => ReadUInt16LittleEndian(Data.AsSpan(0xF4)); set => WriteUInt16LittleEndian(Data.AsSpan(0xF4), (ushort)value); }
|
||||
public override int Stat_DEF { get => ReadUInt16LittleEndian(Data.AsSpan(0xF6)); set => WriteUInt16LittleEndian(Data.AsSpan(0xF6), (ushort)value); }
|
||||
public override int Stat_SPE { get => ReadUInt16LittleEndian(Data.AsSpan(0xF8)); set => WriteUInt16LittleEndian(Data.AsSpan(0xF8), (ushort)value); }
|
||||
public override int Stat_SPA { get => ReadUInt16LittleEndian(Data.AsSpan(0xFA)); set => WriteUInt16LittleEndian(Data.AsSpan(0xFA), (ushort)value); }
|
||||
public override int Stat_SPD { get => ReadUInt16LittleEndian(Data.AsSpan(0xFC)); set => WriteUInt16LittleEndian(Data.AsSpan(0xFC), (ushort)value); }
|
||||
#endregion
|
||||
|
||||
public int SuperTrainingMedalCount(int maxCount = 30)
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using static System.Buffers.Binary.BinaryPrimitives;
|
||||
|
||||
namespace PKHeX.Core
|
||||
{
|
||||
|
@ -49,7 +50,7 @@ namespace PKHeX.Core
|
|||
TradeHT(tr);
|
||||
}
|
||||
|
||||
public int DynamaxType { get => BitConverter.ToUInt16(Data, 0x156); set => BitConverter.GetBytes((ushort)value).CopyTo(Data, 0x156); }
|
||||
public int DynamaxType { get => ReadUInt16LittleEndian(Data.AsSpan(0x156)); set => WriteUInt16LittleEndian(Data.AsSpan(0x156), (ushort)value); }
|
||||
|
||||
public void FixMemories()
|
||||
{
|
||||
|
|
|
@ -23,19 +23,20 @@ namespace PKHeX.Core
|
|||
protected PKM(byte[] data) => Data = data;
|
||||
protected PKM(int size) => Data = new byte[size];
|
||||
|
||||
public virtual byte[] EncryptedPartyData => ArrayUtil.Truncate(Encrypt(), SIZE_PARTY);
|
||||
public virtual byte[] EncryptedBoxData => ArrayUtil.Truncate(Encrypt(), SIZE_STORED);
|
||||
public virtual byte[] DecryptedPartyData => ArrayUtil.Truncate(Write(), SIZE_PARTY);
|
||||
public virtual byte[] DecryptedBoxData => ArrayUtil.Truncate(Write(), SIZE_STORED);
|
||||
public virtual byte[] EncryptedPartyData => Encrypt().AsSpan()[..SIZE_PARTY].ToArray();
|
||||
public virtual byte[] EncryptedBoxData => Encrypt().AsSpan()[..SIZE_STORED].ToArray();
|
||||
public virtual byte[] DecryptedPartyData => Write().AsSpan()[..SIZE_PARTY].ToArray();
|
||||
public virtual byte[] DecryptedBoxData => Write().AsSpan()[..SIZE_STORED].ToArray();
|
||||
|
||||
public virtual bool Valid { get => ChecksumValid && Sanity == 0; set { if (!value) return; Sanity = 0; RefreshChecksum(); } }
|
||||
/// <summary>
|
||||
/// Rough indication if the data is junk or not.
|
||||
/// </summary>
|
||||
public abstract bool Valid { get; set; }
|
||||
|
||||
// Trash Bytes
|
||||
public abstract Span<byte> Nickname_Trash { get; set; }
|
||||
public abstract Span<byte> OT_Trash { get; set; }
|
||||
public virtual Span<byte> HT_Trash { get => Span<byte>.Empty; set { } }
|
||||
|
||||
protected virtual ushort CalculateChecksum() => PokeCrypto.GetCHK(Data, SIZE_STORED);
|
||||
public abstract Span<byte> Nickname_Trash { get; }
|
||||
public abstract Span<byte> OT_Trash { get; }
|
||||
public virtual Span<byte> HT_Trash => Span<byte>.Empty;
|
||||
|
||||
protected abstract byte[] Encrypt();
|
||||
public abstract int Format { get; }
|
||||
|
@ -108,8 +109,6 @@ namespace PKHeX.Core
|
|||
|
||||
public abstract uint EncryptionConstant { get; set; }
|
||||
public abstract uint PID { get; set; }
|
||||
public abstract ushort Sanity { get; set; }
|
||||
public abstract ushort Checksum { get; set; }
|
||||
|
||||
// Misc Properties
|
||||
public abstract int Language { get; set; }
|
||||
|
@ -336,7 +335,6 @@ namespace PKHeX.Core
|
|||
}
|
||||
}
|
||||
|
||||
public virtual bool ChecksumValid => Checksum == CalculateChecksum();
|
||||
public int CurrentLevel { get => Experience.GetLevel(EXP, PersonalInfo.EXPGrowth); set => EXP = Experience.GetEXP(Stat_Level = value, PersonalInfo.EXPGrowth); }
|
||||
public int MarkCircle { get => Markings[0]; set { var marks = Markings; marks[0] = value; Markings = marks; } }
|
||||
public int MarkTriangle { get => Markings[1]; set { var marks = Markings; marks[1] = value; Markings = marks; } }
|
||||
|
@ -371,13 +369,19 @@ namespace PKHeX.Core
|
|||
public int[] IVs
|
||||
{
|
||||
get => new[] { IV_HP, IV_ATK, IV_DEF, IV_SPE, IV_SPA, IV_SPD };
|
||||
set
|
||||
{
|
||||
if (value.Length != 6)
|
||||
return;
|
||||
IV_HP = value[0]; IV_ATK = value[1]; IV_DEF = value[2];
|
||||
IV_SPE = value[3]; IV_SPA = value[4]; IV_SPD = value[5];
|
||||
}
|
||||
set => SetIVs(value);
|
||||
}
|
||||
|
||||
public void SetIVs(ReadOnlySpan<int> value)
|
||||
{
|
||||
if (value.Length != 6)
|
||||
return;
|
||||
IV_HP = value[0];
|
||||
IV_ATK = value[1];
|
||||
IV_DEF = value[2];
|
||||
IV_SPE = value[3];
|
||||
IV_SPA = value[4];
|
||||
IV_SPD = value[5];
|
||||
}
|
||||
|
||||
public int[] EVs
|
||||
|
@ -575,7 +579,13 @@ namespace PKHeX.Core
|
|||
/// <summary>
|
||||
/// Updates the checksum of the <see cref="PKM"/>.
|
||||
/// </summary>
|
||||
public virtual void RefreshChecksum() => Checksum = CalculateChecksum();
|
||||
public abstract void RefreshChecksum();
|
||||
|
||||
/// <summary>
|
||||
/// Indicates if the data has a proper checksum.
|
||||
/// </summary>
|
||||
/// <remarks>Returns true for structures that do not compute or contain a checksum in the structure.</remarks>
|
||||
public abstract bool ChecksumValid { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Reorders moves and fixes PP if necessary.
|
||||
|
@ -891,7 +901,7 @@ namespace PKHeX.Core
|
|||
{
|
||||
for (int i = 0; i < count; i++)
|
||||
ivs[i] = MaxIV;
|
||||
Util.Shuffle(ivs, 0, ivs.Length, rnd); // Randomize IV order
|
||||
Util.Shuffle(ivs.AsSpan(), 0, ivs.Length, rnd); // Randomize IV order
|
||||
}
|
||||
return IVs = ivs;
|
||||
}
|
||||
|
|
|
@ -1,4 +1,5 @@
|
|||
using System;
|
||||
using static System.Buffers.Binary.BinaryPrimitives;
|
||||
|
||||
namespace PKHeX.Core
|
||||
{
|
||||
|
@ -39,14 +40,14 @@ namespace PKHeX.Core
|
|||
public override int Move2 { get => Data[3]; set => Data[3] = (byte)value; }
|
||||
public override int Move3 { get => Data[4]; set => Data[4] = (byte)value; }
|
||||
public override int Move4 { get => Data[5]; set => Data[5] = (byte)value; }
|
||||
public override int TID { get => BigEndian.ToUInt16(Data, 6); set => BigEndian.GetBytes((ushort)value).CopyTo(Data, 6); }
|
||||
public override uint EXP { get => BigEndian.ToUInt32(Data, 8); set => BigEndian.GetBytes(value).CopyTo(Data, 8); } // not 3 bytes like in PK2
|
||||
public override int EV_HP { get => BigEndian.ToUInt16(Data, 0x0C); set => BigEndian.GetBytes((ushort)value).CopyTo(Data, 0x0C); }
|
||||
public override int EV_ATK { get => BigEndian.ToUInt16(Data, 0x0E); set => BigEndian.GetBytes((ushort)value).CopyTo(Data, 0x0E); }
|
||||
public override int EV_DEF { get => BigEndian.ToUInt16(Data, 0x10); set => BigEndian.GetBytes((ushort)value).CopyTo(Data, 0x10); }
|
||||
public override int EV_SPE { get => BigEndian.ToUInt16(Data, 0x12); set => BigEndian.GetBytes((ushort)value).CopyTo(Data, 0x12); }
|
||||
public override int EV_SPC { get => BigEndian.ToUInt16(Data, 0x14); set => BigEndian.GetBytes((ushort)value).CopyTo(Data, 0x14); }
|
||||
public override ushort DV16 { get => BigEndian.ToUInt16(Data, 0x16); set => BigEndian.GetBytes(value).CopyTo(Data, 0x16); }
|
||||
public override int TID { get => ReadUInt16BigEndian(Data.AsSpan(6)); set => WriteUInt16BigEndian(Data.AsSpan(6), (ushort)value); }
|
||||
public override uint EXP { get => ReadUInt32BigEndian(Data.AsSpan(8)); set => WriteUInt32BigEndian(Data.AsSpan(8), value); } // not 3 bytes like in PK2
|
||||
public override int EV_HP { get => ReadUInt16BigEndian(Data.AsSpan(0x0C)); set => WriteUInt16BigEndian(Data.AsSpan(0x0C), (ushort)value); }
|
||||
public override int EV_ATK { get => ReadUInt16BigEndian(Data.AsSpan(0x0E)); set => WriteUInt16BigEndian(Data.AsSpan(0x0E), (ushort)value); }
|
||||
public override int EV_DEF { get => ReadUInt16BigEndian(Data.AsSpan(0x10)); set => WriteUInt16BigEndian(Data.AsSpan(0x10), (ushort)value); }
|
||||
public override int EV_SPE { get => ReadUInt16BigEndian(Data.AsSpan(0x12)); set => WriteUInt16BigEndian(Data.AsSpan(0x12), (ushort)value); }
|
||||
public override int EV_SPC { get => ReadUInt16BigEndian(Data.AsSpan(0x14)); set => WriteUInt16BigEndian(Data.AsSpan(0x14), (ushort)value); }
|
||||
public override ushort DV16 { get => ReadUInt16BigEndian(Data.AsSpan(0x16)); set => WriteUInt16BigEndian(Data.AsSpan(0x16), value); }
|
||||
public override int Move1_PP { get => Data[0x18] & 0x3F; set => Data[0x18] = (byte)((Data[0x18] & 0xC0) | Math.Min(63, value)); }
|
||||
public override int Move2_PP { get => Data[0x19] & 0x3F; set => Data[0x19] = (byte)((Data[0x19] & 0xC0) | Math.Min(63, value)); }
|
||||
public override int Move3_PP { get => Data[0x1A] & 0x3F; set => Data[0x1A] = (byte)((Data[0x1A] & 0xC0) | Math.Min(63, value)); }
|
||||
|
@ -83,31 +84,36 @@ namespace PKHeX.Core
|
|||
public override int PKRS_Days { get => PKRS & 0xF; set => PKRS = (byte)((PKRS & ~0xF) | value); }
|
||||
public override int PKRS_Strain { get => PKRS >> 4; set => PKRS = (byte)((PKRS & 0xF) | value << 4); }
|
||||
|
||||
public int CaughtData { get => BigEndian.ToUInt16(Data, 0x21); set => BigEndian.GetBytes((ushort)value).CopyTo(Data, 0x21); }
|
||||
public int CaughtData { get => ReadUInt16BigEndian(Data.AsSpan(0x21)); set => WriteUInt16BigEndian(Data.AsSpan(0x21), (ushort)value); }
|
||||
|
||||
public int Met_TimeOfDay { get => (CaughtData >> 14) & 0x3; set => CaughtData = (CaughtData & 0x3FFF) | ((value & 0x3) << 14); }
|
||||
public override int Met_Level { get => (CaughtData >> 8) & 0x3F; set => CaughtData = (CaughtData & 0xC0FF) | ((value & 0x3F) << 8); }
|
||||
public override int OT_Gender { get => (CaughtData >> 7) & 1; set => CaughtData = (CaughtData & 0xFF7F) | ((value & 1) << 7); }
|
||||
public override int Met_Location { get => CaughtData & 0x7F; set => CaughtData = (CaughtData & 0xFF80) | (value & 0x7F); }
|
||||
|
||||
public override string Nickname { get => GetString(0x24, StringLength); set => StringConverter12.SetString1(value, 12, Japanese).CopyTo(Data, 0x24); }
|
||||
public override string Nickname
|
||||
{
|
||||
get => StringConverter12.GetString(Nickname_Trash, Japanese);
|
||||
set => StringConverter12.SetString(Nickname_Trash, value.AsSpan(), 12, Japanese, StringConverterOption.None);
|
||||
}
|
||||
|
||||
public override string OT_Name
|
||||
{
|
||||
get => GetString(0x30, StringLength);
|
||||
get => StringConverter12.GetString(OT_Trash, Japanese);
|
||||
set
|
||||
{
|
||||
if (IsRental)
|
||||
{
|
||||
Array.Clear(Data, 0x30, StringLength);
|
||||
OT_Trash.Clear();
|
||||
return;
|
||||
}
|
||||
SetString(value, StringLength).CopyTo(Data, 0x30);
|
||||
StringConverter12.SetString(OT_Trash, value.AsSpan(), StringLength, Japanese, StringConverterOption.None);
|
||||
}
|
||||
}
|
||||
|
||||
public override Span<byte> Nickname_Trash { get => Data.AsSpan(0x24, 12); set { if (value.Length == 12) value.CopyTo(Data.AsSpan(0x24)); } }
|
||||
public override Span<byte> OT_Trash { get => Data.AsSpan(0x30, 12); set { if (value.Length == 12) value.CopyTo(Data.AsSpan(0x30)); } }
|
||||
public override Span<byte> Nickname_Trash => Data.AsSpan(0x24, 12);
|
||||
public override Span<byte> OT_Trash => Data.AsSpan(0x30, 12);
|
||||
|
||||
#endregion
|
||||
|
||||
#region Party Attributes
|
||||
|
@ -125,19 +131,18 @@ namespace PKHeX.Core
|
|||
public override bool HasOriginalMetLocation => CaughtData != 0;
|
||||
public override int Version { get => (int)GameVersion.GSC; set { } }
|
||||
|
||||
private string GetString(int offset, int length) => StringConverter12.GetString1(Data, offset, length - 1, Japanese);
|
||||
private byte[] SetString(string value, int length) => StringConverter12.SetString1(value, length - 1, Japanese);
|
||||
|
||||
protected override byte[] GetNonNickname(int language)
|
||||
{
|
||||
var name = SpeciesName.GetSpeciesNameGeneration(Species, language, Format);
|
||||
return SetString(name, StringLength);
|
||||
var name = SpeciesName.GetSpeciesNameGeneration(Species, language, 2);
|
||||
byte[] data = new byte[name.Length];
|
||||
StringConverter12.SetString(data, name.AsSpan(), data.Length, Japanese, StringConverterOption.Clear50);
|
||||
return data;
|
||||
}
|
||||
|
||||
public override void SetNotNicknamed(int language)
|
||||
{
|
||||
var name = SpeciesName.GetSpeciesNameGeneration(Species, language, Format);
|
||||
Array.Clear(Data, 0x24, 0xC);
|
||||
var name = SpeciesName.GetSpeciesNameGeneration(Species, language, 2);
|
||||
Nickname_Trash.Clear();
|
||||
Nickname = name;
|
||||
}
|
||||
|
||||
|
|
|
@ -46,6 +46,10 @@
|
|||
AbilityBit = n == 1 && ((PersonalInfoG3)PersonalInfo).HasSecondAbility;
|
||||
}
|
||||
|
||||
public override bool Valid { get => true; set { } }
|
||||
public override void RefreshChecksum() { }
|
||||
public override bool ChecksumValid => Valid;
|
||||
|
||||
public abstract bool RibbonEarth { get; set; }
|
||||
public abstract bool RibbonNational { get; set; }
|
||||
public abstract bool RibbonCountry { get; set; }
|
||||
|
|
|
@ -43,9 +43,16 @@ namespace PKHeX.Core
|
|||
}
|
||||
}
|
||||
|
||||
public abstract ushort Sanity { get; set; }
|
||||
public abstract ushort Checksum { get; set; }
|
||||
public sealed override void RefreshChecksum() => Checksum = CalculateChecksum();
|
||||
public sealed override bool ChecksumValid => CalculateChecksum() == Checksum;
|
||||
public override bool Valid { get => Sanity == 0 && ChecksumValid; set { if (!value) return; Sanity = 0; RefreshChecksum(); } }
|
||||
protected virtual ushort CalculateChecksum() => PokeCrypto.GetCHK(Data, PokeCrypto.SIZE_4STORED);
|
||||
|
||||
// Trash Bytes
|
||||
public sealed override Span<byte> Nickname_Trash { get => Data.AsSpan(0x48, 22); set { if (value.Length == 22) value.CopyTo(Data.AsSpan(0x48)); } }
|
||||
public sealed override Span<byte> OT_Trash { get => Data.AsSpan(0x68, 16); set { if (value.Length == 16) value.CopyTo(Data.AsSpan(0x68)); } }
|
||||
public sealed override Span<byte> Nickname_Trash => Data.AsSpan(0x48, 22);
|
||||
public sealed override Span<byte> OT_Trash => Data.AsSpan(0x68, 16);
|
||||
|
||||
// Future Attributes
|
||||
public sealed override uint EncryptionConstant { get => PID; set { } }
|
||||
|
@ -169,6 +176,71 @@ namespace PKHeX.Core
|
|||
public abstract byte BallHGSS { get; set; }
|
||||
public abstract byte PokéathlonStat { get; set; }
|
||||
|
||||
public abstract ushort Egg_LocationDP { get; set; }
|
||||
public abstract ushort Egg_LocationExtended { get; set; }
|
||||
public abstract ushort Met_LocationDP { get; set; }
|
||||
public abstract ushort Met_LocationExtended { get; set; }
|
||||
|
||||
public sealed override int Egg_Location
|
||||
{
|
||||
get
|
||||
{
|
||||
ushort hgssloc = Egg_LocationExtended;
|
||||
if (hgssloc != 0)
|
||||
return hgssloc;
|
||||
return Egg_LocationDP;
|
||||
}
|
||||
set
|
||||
{
|
||||
if (value == 0)
|
||||
{
|
||||
Egg_LocationDP = Egg_LocationExtended = 0;
|
||||
}
|
||||
else if (Locations.IsPtHGSSLocation(value) || Locations.IsPtHGSSLocationEgg(value))
|
||||
{
|
||||
// Met location not in DP, set to Faraway Place
|
||||
Egg_LocationDP = Locations.Faraway4;
|
||||
Egg_LocationExtended = (ushort)value;
|
||||
}
|
||||
else
|
||||
{
|
||||
int pthgss = PtHGSS ? value : 0; // only set to PtHGSS loc if encountered in game
|
||||
Egg_LocationDP = (ushort)pthgss;
|
||||
Egg_LocationExtended = (ushort)value;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public sealed override int Met_Location
|
||||
{
|
||||
get
|
||||
{
|
||||
ushort hgssloc = Met_LocationExtended;
|
||||
if (hgssloc != 0)
|
||||
return hgssloc;
|
||||
return Met_LocationDP;
|
||||
}
|
||||
set
|
||||
{
|
||||
if (value == 0)
|
||||
{
|
||||
Met_LocationDP = Met_LocationExtended = 0;
|
||||
}
|
||||
else if (Locations.IsPtHGSSLocation(value) || Locations.IsPtHGSSLocationEgg(value))
|
||||
{
|
||||
// Met location not in DP, set to Faraway Place
|
||||
Met_LocationDP = Locations.Faraway4;
|
||||
Met_LocationExtended = (ushort)value;
|
||||
}
|
||||
else
|
||||
{
|
||||
int pthgss = PtHGSS ? value : 0; // only set to PtHGSS loc if encountered in game
|
||||
Met_LocationDP = (ushort)pthgss;
|
||||
Met_LocationExtended = (ushort)value;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public sealed override int Ball
|
||||
{
|
||||
// HG/SS added new ball IDs mid-generation, and the previous Gen4 games couldn't handle invalid ball values.
|
||||
|
|
|
@ -1,9 +1,10 @@
|
|||
using System;
|
||||
using static System.Buffers.Binary.BinaryPrimitives;
|
||||
|
||||
namespace PKHeX.Core
|
||||
{
|
||||
/// <summary> Generation 6 <see cref="PKM"/> format. </summary>
|
||||
public abstract class G6PKM : PKM
|
||||
public abstract class G6PKM : PKM, ISanityChecksum
|
||||
{
|
||||
public override int SIZE_PARTY => PokeCrypto.SIZE_6PARTY;
|
||||
public override int SIZE_STORED => PokeCrypto.SIZE_6STORED;
|
||||
|
@ -11,15 +12,21 @@ namespace PKHeX.Core
|
|||
protected G6PKM(int size) : base(size) { }
|
||||
|
||||
// Trash Bytes
|
||||
public sealed override Span<byte> Nickname_Trash { get => Data.AsSpan(0x40, 24); set { if (value.Length == 24) value.CopyTo(Data.AsSpan(0x40)); } }
|
||||
public sealed override Span<byte> HT_Trash { get => Data.AsSpan(0x78, 24); set { if (value.Length == 24) value.CopyTo(Data.AsSpan(0x78)); } }
|
||||
public sealed override Span<byte> OT_Trash { get => Data.AsSpan(0xB0, 24); set { if (value.Length == 24) value.CopyTo(Data.AsSpan(0xB0)); } }
|
||||
public sealed override Span<byte> Nickname_Trash => Data.AsSpan(0x40, 26);
|
||||
public sealed override Span<byte> HT_Trash => Data.AsSpan(0x78, 26);
|
||||
public sealed override Span<byte> OT_Trash => Data.AsSpan(0xB0, 26);
|
||||
|
||||
protected sealed override ushort CalculateChecksum()
|
||||
public abstract ushort Sanity { get; set; }
|
||||
public abstract ushort Checksum { get; set; }
|
||||
public sealed override void RefreshChecksum() => Checksum = CalculateChecksum();
|
||||
public sealed override bool ChecksumValid => CalculateChecksum() == Checksum;
|
||||
public sealed override bool Valid { get => Sanity == 0 && ChecksumValid; set { if (!value) return; Sanity = 0; RefreshChecksum(); } }
|
||||
|
||||
private ushort CalculateChecksum()
|
||||
{
|
||||
ushort chk = 0;
|
||||
for (int i = 8; i < PokeCrypto.SIZE_6STORED; i += 2) // don't use SIZE_STORED property; pb7 overrides stored size
|
||||
chk += BitConverter.ToUInt16(Data, i);
|
||||
chk += ReadUInt16LittleEndian(Data.AsSpan(i));
|
||||
return chk;
|
||||
}
|
||||
|
||||
|
|
|
@ -28,6 +28,9 @@ namespace PKHeX.Core
|
|||
public sealed override byte[] DecryptedBoxData => Encrypt();
|
||||
public sealed override byte[] DecryptedPartyData => Encrypt();
|
||||
|
||||
public override bool Valid { get => true; set { } }
|
||||
public sealed override void RefreshChecksum() { }
|
||||
|
||||
protected abstract byte[] GetNonNickname(int language);
|
||||
|
||||
private bool? _isnicknamed;
|
||||
|
@ -101,9 +104,7 @@ namespace PKHeX.Core
|
|||
public sealed override uint EncryptionConstant { get => 0; set { } }
|
||||
public sealed override uint PID { get => 0; set { } }
|
||||
public sealed override int Nature { get => 0; set { } }
|
||||
public sealed override ushort Sanity { get => 0; set { } }
|
||||
public sealed override bool ChecksumValid => true;
|
||||
public sealed override ushort Checksum { get => 0; set { } }
|
||||
public sealed override bool FatefulEncounter { get => false; set { } }
|
||||
public sealed override int TSV => 0x0000;
|
||||
public sealed override int PSV => 0xFFFF;
|
||||
|
|
|
@ -18,8 +18,8 @@ namespace PKHeX.Core
|
|||
internal readonly byte[] RawNickname;
|
||||
|
||||
// Trash Bytes
|
||||
public sealed override Span<byte> Nickname_Trash { get => RawNickname; set { if (value.Length == RawNickname.Length) value.CopyTo(RawNickname); } }
|
||||
public sealed override Span<byte> OT_Trash { get => RawOT; set { if (value.Length == RawOT.Length) value.CopyTo(RawOT); } }
|
||||
public sealed override Span<byte> Nickname_Trash => RawNickname;
|
||||
public sealed override Span<byte> OT_Trash => RawOT;
|
||||
|
||||
protected GBPKML(int size, bool jp = false) : base(size)
|
||||
{
|
||||
|
@ -28,8 +28,8 @@ namespace PKHeX.Core
|
|||
// initialize string buffers
|
||||
RawOT = new byte[strLen];
|
||||
RawNickname = new byte[strLen];
|
||||
for (int i = 0; i < RawOT.Length; i++)
|
||||
RawOT[i] = RawNickname[i] = StringConverter12.G1TerminatorCode;
|
||||
RawOT.AsSpan().Fill(StringConverter12.G1TerminatorCode);
|
||||
RawNickname.AsSpan().Fill(StringConverter12.G1TerminatorCode);
|
||||
}
|
||||
|
||||
protected GBPKML(byte[] data, bool jp = false) : base(data)
|
||||
|
@ -39,8 +39,8 @@ namespace PKHeX.Core
|
|||
// initialize string buffers
|
||||
RawOT = new byte[strLen];
|
||||
RawNickname = new byte[strLen];
|
||||
for (int i = 0; i < RawOT.Length; i++)
|
||||
RawOT[i] = RawNickname[i] = StringConverter12.G1TerminatorCode;
|
||||
RawOT.AsSpan().Fill(StringConverter12.G1TerminatorCode);
|
||||
RawNickname.AsSpan().Fill(StringConverter12.G1TerminatorCode);
|
||||
}
|
||||
|
||||
public override void SetNotNicknamed(int language) => GetNonNickname(language).CopyTo(RawNickname);
|
||||
|
@ -49,7 +49,8 @@ namespace PKHeX.Core
|
|||
{
|
||||
var name = SpeciesName.GetSpeciesNameGeneration(Species, language, Format);
|
||||
var len = Nickname_Trash.Length;
|
||||
var data = SetString(name, len, len, 0x50);
|
||||
byte[] data = new byte[len];
|
||||
SetString(name.AsSpan(), data, len, StringConverterOption.Clear50);
|
||||
if (!Korean)
|
||||
{
|
||||
// Decimal point<->period fix
|
||||
|
@ -62,11 +63,11 @@ namespace PKHeX.Core
|
|||
return data;
|
||||
}
|
||||
|
||||
private byte[] SetString(string value, int maxLength, int padTo = 0, byte padWith = 0)
|
||||
private void SetString(ReadOnlySpan<char> value, Span<byte> destBuffer, int maxLength, StringConverterOption option = StringConverterOption.None)
|
||||
{
|
||||
if (Korean)
|
||||
return StringConverter2KOR.SetString2KOR(value, maxLength - 1, padTo, padWith);
|
||||
return StringConverter12.SetString1(value, maxLength - 1, Japanese, padTo, padWith);
|
||||
StringConverter2KOR.SetString(value, destBuffer, maxLength, option);
|
||||
StringConverter12.SetString(destBuffer, value, maxLength, Japanese, option);
|
||||
}
|
||||
|
||||
public sealed override string Nickname
|
||||
|
@ -74,15 +75,15 @@ namespace PKHeX.Core
|
|||
get
|
||||
{
|
||||
if (Korean)
|
||||
return StringConverter2KOR.GetString2KOR(RawNickname, 0, RawNickname.Length);
|
||||
return StringConverter12.GetString1(RawNickname, 0, RawNickname.Length, Japanese);
|
||||
return StringConverter2KOR.GetString(RawNickname);
|
||||
return StringConverter12.GetString(RawNickname, Japanese);
|
||||
}
|
||||
set
|
||||
{
|
||||
if (!IsNicknamed && Nickname == value)
|
||||
return;
|
||||
|
||||
SetStringKeepTerminatorStyle(value, RawNickname);
|
||||
SetStringKeepTerminatorStyle(value.AsSpan(), RawNickname);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -91,28 +92,27 @@ namespace PKHeX.Core
|
|||
get
|
||||
{
|
||||
if (Korean)
|
||||
return StringConverter2KOR.GetString2KOR(RawOT, 0, RawOT.Length);
|
||||
return StringConverter12.GetString1(RawOT, 0, RawOT.Length, Japanese);
|
||||
return StringConverter2KOR.GetString(RawOT.AsSpan());
|
||||
return StringConverter12.GetString(RawOT.AsSpan(), Japanese);
|
||||
}
|
||||
set
|
||||
{
|
||||
if (value == OT_Name)
|
||||
return;
|
||||
SetStringKeepTerminatorStyle(value, RawOT);
|
||||
SetStringKeepTerminatorStyle(value.AsSpan(), RawOT);
|
||||
}
|
||||
}
|
||||
|
||||
private void SetStringKeepTerminatorStyle(string value, byte[] exist)
|
||||
private void SetStringKeepTerminatorStyle(ReadOnlySpan<char> value, Span<byte> exist)
|
||||
{
|
||||
// Reset the destination buffer based on the termination style of the existing string.
|
||||
bool zeroed = Array.IndexOf(exist, (byte)0) != -1;
|
||||
bool zeroed = exist.IndexOf((byte)0) != -1;
|
||||
byte fill = zeroed ? (byte)0 : StringConverter12.G1TerminatorCode;
|
||||
for (int i = 0; i < exist.Length; i++)
|
||||
exist[i] = fill;
|
||||
|
||||
int finalLength = Math.Min(value.Length + 1, exist.Length);
|
||||
byte[] strdata = SetString(value, finalLength);
|
||||
strdata.CopyTo(exist, 0);
|
||||
SetString(value, exist, finalLength);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
8
PKHeX.Core/PKM/Shared/ISanityChecksum.cs
Normal file
8
PKHeX.Core/PKM/Shared/ISanityChecksum.cs
Normal file
|
@ -0,0 +1,8 @@
|
|||
namespace PKHeX.Core
|
||||
{
|
||||
public interface ISanityChecksum
|
||||
{
|
||||
ushort Sanity { get; set; }
|
||||
ushort Checksum { get; set; }
|
||||
}
|
||||
}
|
|
@ -1,3 +1,5 @@
|
|||
using System;
|
||||
|
||||
namespace PKHeX.Core
|
||||
{
|
||||
/// <summary>
|
||||
|
@ -6,7 +8,14 @@ namespace PKHeX.Core
|
|||
public sealed class PokeList1 : PokeListGB<PK1>
|
||||
{
|
||||
protected override byte GetSpeciesBoxIdentifier(PK1 pk) => SpeciesConverter.SetG1Species(pk.Species);
|
||||
protected override PK1 GetEntry(byte[] dat, byte[] otname, byte[] nick, bool egg) => new(dat, Japanese) { OT_Trash = otname, Nickname_Trash = nick };
|
||||
protected override PK1 GetEntry(byte[] dat, byte[] otname, byte[] nick, bool egg)
|
||||
{
|
||||
var result = new PK1(dat, Japanese); // no eggs
|
||||
otname.AsSpan().CopyTo(result.OT_Trash);
|
||||
nick.AsSpan().CopyTo(result.Nickname_Trash);
|
||||
return result;
|
||||
}
|
||||
|
||||
protected override int GetEntrySize() => GetEntrySize(IsFormatParty);
|
||||
|
||||
public PokeList1(byte[] d, PokeListType c = PokeListType.Single, bool jp = false) : base(d, c, jp) { }
|
||||
|
|
|
@ -1,3 +1,5 @@
|
|||
using System;
|
||||
|
||||
namespace PKHeX.Core
|
||||
{
|
||||
/// <summary>
|
||||
|
@ -6,7 +8,14 @@ namespace PKHeX.Core
|
|||
public sealed class PokeList2 : PokeListGB<PK2>
|
||||
{
|
||||
protected override byte GetSpeciesBoxIdentifier(PK2 pk) => pk.IsEgg ? PK2.EggSpeciesValue : (byte)pk.Species;
|
||||
protected override PK2 GetEntry(byte[] dat, byte[] otname, byte[] nick, bool egg) => new(dat, Japanese) { OT_Trash = otname, Nickname_Trash = nick, IsEgg = egg };
|
||||
protected override PK2 GetEntry(byte[] dat, byte[] otname, byte[] nick, bool egg)
|
||||
{
|
||||
var result = new PK2(dat, Japanese) { IsEgg = egg };
|
||||
otname.AsSpan().CopyTo(result.OT_Trash);
|
||||
nick.AsSpan().CopyTo(result.Nickname_Trash);
|
||||
return result;
|
||||
}
|
||||
|
||||
protected override int GetEntrySize() => GetEntrySize(IsFormatParty);
|
||||
|
||||
public PokeList2(byte[] d, PokeListType c = PokeListType.Single, bool jp = false) : base(d, c, jp) { }
|
||||
|
|
|
@ -1,4 +1,5 @@
|
|||
using System;
|
||||
using static System.Buffers.Binary.BinaryPrimitives;
|
||||
|
||||
namespace PKHeX.Core
|
||||
{
|
||||
|
@ -15,7 +16,7 @@ namespace PKHeX.Core
|
|||
public const int SIZE = 0x30;
|
||||
public QRPK7(byte[] d) => Data = (byte[])d.Clone();
|
||||
|
||||
public uint EncryptionConstant => BitConverter.ToUInt32(Data, 0);
|
||||
public uint EncryptionConstant => ReadUInt32LittleEndian(Data.AsSpan(0));
|
||||
public int HT_Flags => Data[4];
|
||||
public int Unk_5 => Data[5];
|
||||
public int Unk_6 => Data[6];
|
||||
|
@ -24,20 +25,20 @@ namespace PKHeX.Core
|
|||
public int Move2_PPUps => Data[9];
|
||||
public int Move3_PPUps => Data[0xA];
|
||||
public int Move4_PPUps => Data[0xB];
|
||||
public uint IV32 { get => BitConverter.ToUInt32(Data, 0xC); set => BitConverter.GetBytes(value).CopyTo(Data, 0xC); }
|
||||
public uint IV32 { get => ReadUInt32LittleEndian(Data.AsSpan(0xC)); set => WriteUInt32LittleEndian(Data.AsSpan(0xC), value); }
|
||||
public int IV_HP { get => (int)(IV32 >> 00) & 0x1F; set => IV32 = (uint)((IV32 & ~(0x1F << 00)) | (uint)((value > 31 ? 31 : value) << 00)); }
|
||||
public int IV_ATK { get => (int)(IV32 >> 05) & 0x1F; set => IV32 = (uint)((IV32 & ~(0x1F << 05)) | (uint)((value > 31 ? 31 : value) << 05)); }
|
||||
public int IV_DEF { get => (int)(IV32 >> 10) & 0x1F; set => IV32 = (uint)((IV32 & ~(0x1F << 10)) | (uint)((value > 31 ? 31 : value) << 10)); }
|
||||
public int IV_SPE { get => (int)(IV32 >> 15) & 0x1F; set => IV32 = (uint)((IV32 & ~(0x1F << 15)) | (uint)((value > 31 ? 31 : value) << 15)); }
|
||||
public int IV_SPA { get => (int)(IV32 >> 20) & 0x1F; set => IV32 = (uint)((IV32 & ~(0x1F << 20)) | (uint)((value > 31 ? 31 : value) << 20)); }
|
||||
public int IV_SPD { get => (int)(IV32 >> 25) & 0x1F; set => IV32 = (uint)((IV32 & ~(0x1F << 25)) | (uint)((value > 31 ? 31 : value) << 25)); }
|
||||
public uint PID => BitConverter.ToUInt32(Data, 0x10);
|
||||
public int Species => BitConverter.ToUInt16(Data, 0x14);
|
||||
public ushort HeldItem => BitConverter.ToUInt16(Data, 0x16);
|
||||
public ushort Move1 => BitConverter.ToUInt16(Data, 0x18);
|
||||
public ushort Move2 => BitConverter.ToUInt16(Data, 0x1A);
|
||||
public ushort Move3 => BitConverter.ToUInt16(Data, 0x1C);
|
||||
public ushort Move4 => BitConverter.ToUInt16(Data, 0x1E);
|
||||
public uint PID => ReadUInt32LittleEndian(Data.AsSpan(0x10));
|
||||
public int Species => ReadUInt16LittleEndian(Data.AsSpan(0x14));
|
||||
public ushort HeldItem => ReadUInt16LittleEndian(Data.AsSpan(0x16));
|
||||
public ushort Move1 => ReadUInt16LittleEndian(Data.AsSpan(0x18));
|
||||
public ushort Move2 => ReadUInt16LittleEndian(Data.AsSpan(0x1A));
|
||||
public ushort Move3 => ReadUInt16LittleEndian(Data.AsSpan(0x1C));
|
||||
public ushort Move4 => ReadUInt16LittleEndian(Data.AsSpan(0x1E));
|
||||
public int Unk_20 => Data[0x20];
|
||||
public int AbilityIndex => Data[0x21];
|
||||
public int Nature => Data[0x22];
|
||||
|
|
|
@ -1,290 +1,125 @@
|
|||
using System;
|
||||
using System.Text;
|
||||
using static PKHeX.Core.StringConverter7ZH;
|
||||
|
||||
namespace PKHeX.Core
|
||||
namespace PKHeX.Core;
|
||||
|
||||
/// <summary>
|
||||
/// Logic for converting a <see cref="string"/> between the various generation specific encoding formats.
|
||||
/// </summary>
|
||||
public static class StringConverter
|
||||
{
|
||||
/// <summary>
|
||||
/// Logic for converting a <see cref="string"/> between the various generation specific encoding formats.
|
||||
/// Converts bytes to a string according to the input parameters.
|
||||
/// </summary>
|
||||
public static class StringConverter
|
||||
/// <param name="data">Encoded data</param>
|
||||
/// <param name="generation">Generation string format</param>
|
||||
/// <param name="jp">Encoding is Japanese</param>
|
||||
/// <param name="isBigEndian">Encoding is Big Endian</param>
|
||||
/// <returns>Decoded string.</returns>
|
||||
public static string GetString(ReadOnlySpan<byte> data, int generation, bool jp, bool isBigEndian = false) => generation switch
|
||||
{
|
||||
private const char TerminatorNull = (char)0;
|
||||
private const char TerminatorFFFF = (char)0xFFFF;
|
||||
3 when isBigEndian => StringConverter3GC.GetString(data),
|
||||
4 when isBigEndian => StringConverter4GC.GetString(data),
|
||||
|
||||
/// <summary>
|
||||
/// Converts bytes to a string according to the input parameters.
|
||||
/// </summary>
|
||||
/// <param name="data">Encoded data</param>
|
||||
/// <param name="generation">Generation string format</param>
|
||||
/// <param name="jp">Encoding is Japanese</param>
|
||||
/// <param name="isBigEndian">Encoding is Big Endian</param>
|
||||
/// <param name="count">Length of data to read.</param>
|
||||
/// <param name="offset">Offset to read from</param>
|
||||
/// <returns>Decoded string.</returns>
|
||||
public static string GetString(byte[] data, int generation, bool jp, bool isBigEndian, int count, int offset = 0)
|
||||
1 or 2 => StringConverter12.GetString(data, jp),
|
||||
3 => StringConverter3.GetString(data, jp),
|
||||
4 => StringConverter4.GetString(data),
|
||||
5 => StringConverter5.GetString(data),
|
||||
6 => StringConverter6.GetString(data),
|
||||
7 => StringConverter7.GetString(data),
|
||||
8 => StringConverter8.GetString(data),
|
||||
_ => throw new ArgumentOutOfRangeException(nameof(generation)),
|
||||
};
|
||||
|
||||
/// <summary>
|
||||
/// Gets the bytes for a Generation specific string according to the input parameters.
|
||||
/// </summary>
|
||||
/// <param name="destBuffer"></param>
|
||||
/// <param name="value">Decoded string.</param>
|
||||
/// <param name="maxLength">Maximum length of the input <see cref="value"/></param>
|
||||
/// <param name="option"></param>
|
||||
/// <param name="generation">Generation string format</param>
|
||||
/// <param name="jp">Encoding is Japanese</param>
|
||||
/// <param name="isBigEndian">Encoding is Big Endian</param>
|
||||
/// <param name="language">Language specific conversion (Chinese)</param>
|
||||
/// <returns>Encoded data.</returns>
|
||||
public static int SetString(Span<byte> destBuffer, ReadOnlySpan<char> value, int maxLength, StringConverterOption option,
|
||||
int generation, bool jp, bool isBigEndian, int language = 0) => generation switch
|
||||
{
|
||||
3 when isBigEndian => StringConverter3GC.SetString(destBuffer, value, maxLength, option),
|
||||
4 when isBigEndian => StringConverter4GC.SetString(destBuffer, value, maxLength, option),
|
||||
|
||||
1 or 2 => StringConverter12.SetString(destBuffer, value, maxLength, jp, option),
|
||||
3 => StringConverter3.SetString(destBuffer, value, maxLength, jp, option),
|
||||
4 => StringConverter4.SetString(destBuffer, value, maxLength, option),
|
||||
5 => StringConverter5.SetString(destBuffer, value, maxLength, option),
|
||||
6 => StringConverter6.SetString(destBuffer, value, maxLength, option),
|
||||
7 => StringConverter7.SetString(destBuffer, value, maxLength, language, option),
|
||||
8 => StringConverter8.SetString(destBuffer, value, maxLength, option),
|
||||
_ => throw new ArgumentOutOfRangeException(nameof(generation)),
|
||||
};
|
||||
|
||||
/// <summary>
|
||||
/// Converts full width to single width
|
||||
/// </summary>
|
||||
/// <param name="chr">Input character to sanitize.</param>
|
||||
internal static char SanitizeChar(char chr) => chr switch
|
||||
{
|
||||
'\uE08F' => '♀',
|
||||
'\uE08E' => '♂',
|
||||
'\u246E' => '♀',
|
||||
'\u246D' => '♂',
|
||||
_ => chr,
|
||||
};
|
||||
|
||||
/// <summary>
|
||||
/// Converts full width to half width when appropriate
|
||||
/// </summary>
|
||||
/// <param name="chr">Input character to set back to data</param>
|
||||
/// <param name="fullWidth">Checks if the overall string is full-width</param>
|
||||
internal static char UnSanitizeChar(char chr, bool fullWidth = false)
|
||||
{
|
||||
if (fullWidth) // jp/ko/zh strings
|
||||
return chr; // keep as full width
|
||||
|
||||
return chr switch
|
||||
{
|
||||
if (isBigEndian)
|
||||
return generation == 3 ? StringConverter3.GetBEString3(data, offset, count) : StringConverter4.GetBEString4(data, offset, count);
|
||||
'\u2640' => '\uE08F',
|
||||
'\u2642' => '\uE08E',
|
||||
_ => chr,
|
||||
};
|
||||
}
|
||||
|
||||
return generation switch
|
||||
{
|
||||
1 or 2 => StringConverter12.GetString1(data, offset, count, jp),
|
||||
3 => StringConverter3.GetString3(data, offset, count, jp),
|
||||
4 => StringConverter4.GetString4(data, offset, count),
|
||||
5 => GetString5(data, offset, count),
|
||||
6 => GetString6(data, offset, count),
|
||||
7 => GetString7(data, offset, count),
|
||||
_ => GetString7b(data, offset, count),
|
||||
};
|
||||
/// <summary>
|
||||
/// Converts full width to half width when appropriate, for Gen5 and prior.
|
||||
/// </summary>
|
||||
/// <param name="chr">Input character to set back to data</param>
|
||||
internal static char UnSanitizeChar5(char chr) => chr switch
|
||||
{
|
||||
'\u2640' => '\u246E',
|
||||
'\u2642' => '\u246D',
|
||||
_ => chr,
|
||||
};
|
||||
|
||||
internal static bool GetIsFullWidthString(ReadOnlySpan<char> str)
|
||||
{
|
||||
foreach (var c in str)
|
||||
{
|
||||
if (c >> 12 is (0 or 0xE))
|
||||
continue;
|
||||
if (c is '\u2640' or '\u2642') // ♀♂
|
||||
continue;
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets the bytes for a Generation specific string according to the input parameters.
|
||||
/// </summary>
|
||||
/// <param name="value">Decoded string.</param>
|
||||
/// <param name="generation">Generation string format</param>
|
||||
/// <param name="jp">Encoding is Japanese</param>
|
||||
/// <param name="isBigEndian">Encoding is Big Endian</param>
|
||||
/// <param name="maxLength">Maximum length of the input <see cref="value"/></param>
|
||||
/// <param name="language">Language specific conversion (Chinese)</param>
|
||||
/// <param name="padTo">Pad the input <see cref="value"/> to given length</param>
|
||||
/// <param name="padWith">Pad the input <see cref="value"/> with this character value</param>
|
||||
/// <returns>Encoded data.</returns>
|
||||
public static byte[] SetString(string value, int generation, bool jp, bool isBigEndian, int maxLength, int language = 0, int padTo = 0, ushort padWith = 0)
|
||||
public static bool HasEastAsianScriptCharacters(ReadOnlySpan<char> str)
|
||||
{
|
||||
foreach (var c in str)
|
||||
{
|
||||
if (isBigEndian)
|
||||
return generation == 3 ? StringConverter3.SetBEString3(value, maxLength, padTo, padWith) : StringConverter4.SetBEString4(value, maxLength, padTo, padWith);
|
||||
|
||||
return generation switch
|
||||
{
|
||||
1 or 2 => StringConverter12.SetString1(value, maxLength, jp, padTo, (byte)padWith),
|
||||
3 => StringConverter3.SetString3(value, maxLength, jp, padTo, padWith),
|
||||
4 => StringConverter4.SetString4(value, maxLength, padTo, padWith),
|
||||
5 => SetString5(value, maxLength, padTo, padWith),
|
||||
6 => SetString6(value, maxLength, padTo, padWith),
|
||||
7 => SetString7(value, maxLength, language, padTo, padWith),
|
||||
_ => SetString7b(value, maxLength, padTo, padWith),
|
||||
};
|
||||
}
|
||||
|
||||
/// <summary>Converts Generation 5 encoded data to decoded string.</summary>
|
||||
/// <param name="data">Encoded data</param>
|
||||
/// <param name="offset">Offset to read from</param>
|
||||
/// <param name="count">Length of data to read.</param>
|
||||
/// <returns>Decoded string.</returns>
|
||||
public static string GetString5(byte[] data, int offset, int count)
|
||||
{
|
||||
var raw = Encoding.Unicode.GetString(data, offset, count);
|
||||
var sb = new StringBuilder(raw);
|
||||
Util.TrimFromFirst(sb, TerminatorFFFF);
|
||||
SanitizeString(sb);
|
||||
return sb.ToString();
|
||||
}
|
||||
|
||||
/// <summary>Gets the bytes for a Generation 5 string.</summary>
|
||||
/// <param name="value">Decoded string.</param>
|
||||
/// <param name="maxLength">Maximum length of the input <see cref="value"/></param>
|
||||
/// <param name="padTo">Pad the input <see cref="value"/> to given length</param>
|
||||
/// <param name="padWith">Pad the input <see cref="value"/> with this character value</param>
|
||||
/// <returns>Encoded data.</returns>
|
||||
public static byte[] SetString5(string value, int maxLength, int padTo = 0, ushort padWith = 0)
|
||||
{
|
||||
var sb = new StringBuilder(value, Math.Max(maxLength, padTo));
|
||||
var delta = sb.Length - maxLength;
|
||||
if (delta > 0)
|
||||
sb.Remove(maxLength, delta);
|
||||
|
||||
// Replace Special Characters and add Terminator
|
||||
UnSanitizeString(sb, 5);
|
||||
sb.Append(TerminatorFFFF);
|
||||
var d2 = padTo - sb.Length;
|
||||
if (d2 > 0)
|
||||
sb.Append((char)padWith, d2);
|
||||
|
||||
return Encoding.Unicode.GetBytes(sb.ToString());
|
||||
}
|
||||
|
||||
/// <summary>Converts Generation 6 encoded data to decoded string.</summary>
|
||||
/// <param name="data">Encoded data</param>
|
||||
/// <param name="offset">Offset to read from</param>
|
||||
/// <param name="count">Length of data to read.</param>
|
||||
/// <returns>Decoded string.</returns>
|
||||
public static string GetString6(byte[] data, int offset, int count)
|
||||
{
|
||||
var raw = Encoding.Unicode.GetString(data, offset, count);
|
||||
var sb = new StringBuilder(raw);
|
||||
Util.TrimFromFirst(sb, TerminatorNull);
|
||||
SanitizeString(sb);
|
||||
return sb.ToString();
|
||||
}
|
||||
|
||||
/// <summary>Gets the bytes for a Generation 6 string.</summary>
|
||||
/// <param name="value">Decoded string.</param>
|
||||
/// <param name="maxLength">Maximum length of the input <see cref="value"/></param>
|
||||
/// <param name="padTo">Pad the input <see cref="value"/> to given length</param>
|
||||
/// <param name="padWith">Pad the input <see cref="value"/> with this character value</param>
|
||||
/// <returns>Encoded data.</returns>
|
||||
public static byte[] SetString6(string value, int maxLength, int padTo = 0, ushort padWith = 0)
|
||||
{
|
||||
var sb = new StringBuilder(value);
|
||||
var delta = sb.Length - maxLength;
|
||||
if (delta > 0)
|
||||
sb.Remove(maxLength, delta);
|
||||
|
||||
// Replace Special Characters and add Terminator
|
||||
UnSanitizeString(sb, 6);
|
||||
sb.Append(TerminatorNull);
|
||||
var d2 = padTo - sb.Length;
|
||||
if (d2 > 0)
|
||||
sb.Append((char)padWith, d2);
|
||||
|
||||
return Encoding.Unicode.GetBytes(sb.ToString());
|
||||
}
|
||||
|
||||
/// <summary>Converts Generation 7 encoded data to decoded string.</summary>
|
||||
/// <param name="data">Encoded data</param>
|
||||
/// <param name="offset">Offset to read from</param>
|
||||
/// <param name="count">Length of data to read.</param>
|
||||
/// <returns>Decoded string.</returns>
|
||||
public static string GetString7(byte[] data, int offset, int count)
|
||||
{
|
||||
var raw = Encoding.Unicode.GetString(data, offset, count);
|
||||
var sb = new StringBuilder(raw);
|
||||
Util.TrimFromFirst(sb, TerminatorNull);
|
||||
SanitizeString(sb);
|
||||
RemapChineseGlyphsBin2String(sb);
|
||||
return sb.ToString();
|
||||
}
|
||||
|
||||
/// <summary>Converts Generation 7-Beluga encoded data to decoded string.</summary>
|
||||
/// <param name="data">Encoded data</param>
|
||||
/// <param name="offset">Offset to read from</param>
|
||||
/// <param name="count">Length of data to read.</param>
|
||||
/// <returns>Decoded string.</returns>
|
||||
public static string GetString7b(byte[] data, int offset, int count)
|
||||
{
|
||||
var raw = Encoding.Unicode.GetString(data, offset, count);
|
||||
var sb = new StringBuilder(raw);
|
||||
Util.TrimFromFirst(sb, TerminatorNull);
|
||||
SanitizeString(sb);
|
||||
//RemapChineseGlyphsBin2String(sb);
|
||||
return sb.ToString();
|
||||
}
|
||||
|
||||
/// <summary>Gets the bytes for a Generation 7 string.</summary>
|
||||
/// <param name="value">Decoded string.</param>
|
||||
/// <param name="maxLength">Maximum length of the input <see cref="value"/></param>
|
||||
/// <param name="language">Language specific conversion (Chinese)</param>
|
||||
/// <param name="padTo">Pad the input <see cref="value"/> to given length</param>
|
||||
/// <param name="padWith">Pad the input <see cref="value"/> with this character value</param>
|
||||
/// <param name="chinese">Chinese string remapping should be attempted</param>
|
||||
/// <returns>Encoded data.</returns>
|
||||
public static byte[] SetString7(string value, int maxLength, int language, int padTo = 0, ushort padWith = 0, bool chinese = false)
|
||||
{
|
||||
var sb = new StringBuilder(value);
|
||||
var delta = sb.Length - maxLength;
|
||||
if (delta > 0)
|
||||
sb.Remove(maxLength, delta);
|
||||
if (chinese)
|
||||
ConvertString2BinG7_zh(sb, language);
|
||||
|
||||
// Replace Special Characters and add Terminator
|
||||
UnSanitizeString(sb, 7);
|
||||
sb.Append(TerminatorNull);
|
||||
var d2 = padTo - sb.Length;
|
||||
if (d2 > 0)
|
||||
sb.Append((char)padWith, d2);
|
||||
|
||||
return Encoding.Unicode.GetBytes(sb.ToString());
|
||||
}
|
||||
|
||||
/// <summary>Gets the bytes for a Generation 7-Beluga string.</summary>
|
||||
/// <param name="value">Decoded string.</param>
|
||||
/// <param name="maxLength">Maximum length of the input <see cref="value"/></param>
|
||||
/// <param name="padTo">Pad the input <see cref="value"/> to given length</param>
|
||||
/// <param name="padWith">Pad the input <see cref="value"/> with this character value</param>
|
||||
/// <returns>Encoded data.</returns>
|
||||
public static byte[] SetString7b(string value, int maxLength, int padTo = 0, ushort padWith = 0)
|
||||
{
|
||||
var sb = new StringBuilder(value);
|
||||
var delta = sb.Length - maxLength;
|
||||
if (delta > 0)
|
||||
sb.Remove(maxLength, delta);
|
||||
|
||||
// Replace Special Characters and add Terminator
|
||||
// No special characters!
|
||||
sb.Append(TerminatorNull);
|
||||
var d2 = padTo - sb.Length;
|
||||
if (d2 > 0)
|
||||
sb.Append((char)padWith, d2);
|
||||
|
||||
return Encoding.Unicode.GetBytes(sb.ToString());
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Converts full width to single width
|
||||
/// </summary>
|
||||
/// <param name="s">Input string to sanitize.</param>
|
||||
/// <returns></returns>
|
||||
internal static void SanitizeString(StringBuilder s)
|
||||
{
|
||||
if (s.Length == 0)
|
||||
return;
|
||||
|
||||
// remap custom glyphs to unicode
|
||||
s.Replace('\uE08F', '♀'); // ♀ (gen6+)
|
||||
s.Replace('\uE08E', '♂'); // ♂ (gen6+)
|
||||
s.Replace('\u246E', '♀'); // ♀ (gen5)
|
||||
s.Replace('\u246D', '♂'); // ♂ (gen5)
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Converts full width to half width when appropriate
|
||||
/// </summary>
|
||||
/// <param name="str">Input string to set.</param>
|
||||
/// <param name="generation">Generation specific context</param>
|
||||
/// <returns></returns>
|
||||
internal static void UnSanitizeString(StringBuilder str, int generation)
|
||||
{
|
||||
if (generation <= 5)
|
||||
{
|
||||
str.Replace('\u2640', '\u246E'); // ♀
|
||||
str.Replace('\u2642', '\u246D'); // ♂
|
||||
return;
|
||||
}
|
||||
|
||||
bool fullwidth = GetIsFullWidthString(str);
|
||||
if (fullwidth) // jp/ko/zh strings
|
||||
return; // keep as full width
|
||||
|
||||
// Convert back to half width glyphs
|
||||
str.Replace('\u2640', '\uE08F'); // ♀
|
||||
str.Replace('\u2642', '\uE08E'); // ♂
|
||||
}
|
||||
|
||||
private static bool GetIsFullWidthString(StringBuilder str)
|
||||
{
|
||||
for (int i = 0; i < str.Length; i++)
|
||||
{
|
||||
var c = str[i];
|
||||
if (c >> 12 is (0 or 0xE))
|
||||
continue;
|
||||
if (c is '\u2640' or '\u2642') // ♀♂
|
||||
continue;
|
||||
if (c is >= '\u4E00' and <= '\u9FFF')
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
public static bool HasEastAsianScriptCharacters(string str)
|
||||
{
|
||||
foreach (var c in str)
|
||||
{
|
||||
if (c is >= '\u4E00' and <= '\u9FFF')
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
|
File diff suppressed because it is too large
Load diff
|
@ -1,130 +1,141 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
|
||||
namespace PKHeX.Core
|
||||
namespace PKHeX.Core;
|
||||
|
||||
/// <summary>
|
||||
/// Logic for converting a <see cref="string"/> from Generation 1 & 2 games to Generation 7.
|
||||
/// </summary>
|
||||
public static class StringConverter12Transporter
|
||||
{
|
||||
private const ushort Terminator = 0;
|
||||
|
||||
/// <summary>
|
||||
/// Logic for converting a <see cref="string"/> from Generation 1 & 2 games to Generation 7.
|
||||
/// Converts Generation 1 encoded data the same way Bank converts.
|
||||
/// </summary>
|
||||
public static class StringConverter12Transporter
|
||||
/// <param name="data">Generation 1 encoded data.</param>
|
||||
/// <param name="jp">Data source is Japanese.</param>
|
||||
/// <returns>Decoded string.</returns>
|
||||
public static string GetString(ReadOnlySpan<byte> data, bool jp)
|
||||
{
|
||||
/// <summary>
|
||||
/// Converts Generation 1 encoded data the same way Bank converts.
|
||||
/// </summary>
|
||||
/// <param name="data">Generation 1 encoded data.</param>
|
||||
/// <param name="jp">Data source is Japanese.</param>
|
||||
/// <returns>Decoded string.</returns>
|
||||
public static string GetString(byte[] data, bool jp)
|
||||
{
|
||||
var table = jp ? jp_table : us_table;
|
||||
var chars = GetG1ConvertedChar(data, table);
|
||||
if (jp)
|
||||
chars = CheckKata(chars);
|
||||
|
||||
return string.Concat(chars);
|
||||
}
|
||||
|
||||
private static IEnumerable<char> GetG1ConvertedChar(byte[] data, ushort[] table)
|
||||
{
|
||||
foreach (var b in data)
|
||||
{
|
||||
if (b == 0)
|
||||
yield break;
|
||||
|
||||
var val = table[b];
|
||||
if (val == 0)
|
||||
yield break;
|
||||
|
||||
yield return (char)val;
|
||||
}
|
||||
}
|
||||
|
||||
private static IEnumerable<char> CheckKata(IEnumerable<char> chars)
|
||||
{
|
||||
var arr = chars.ToArray();
|
||||
if (!arr.Any(Katakana.Contains))
|
||||
return arr;
|
||||
|
||||
if (!IsHiragana(arr))
|
||||
return arr;
|
||||
|
||||
for (int i = 0; i < arr.Length; i++)
|
||||
{
|
||||
int index = Array.IndexOf(Katakana, arr[i]);
|
||||
if (index == -1)
|
||||
continue;
|
||||
arr[i] = Hiragana[index];
|
||||
}
|
||||
|
||||
return arr;
|
||||
}
|
||||
|
||||
private static bool IsHiragana(IEnumerable<char> chars)
|
||||
{
|
||||
foreach (var c in chars)
|
||||
{
|
||||
if ((uint)(c - 0x3041) < 0x53)
|
||||
return true;
|
||||
if ((uint)(c - 0x30A1) < 0x56)
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
private static readonly char[] Katakana = { 'ベ', 'ペ', 'ヘ', 'リ' };
|
||||
private static readonly char[] Hiragana = { 'べ', 'ぺ', 'へ', 'り' };
|
||||
|
||||
/// <summary>
|
||||
/// International 1->7 character translation table
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// Exported from Gen1's VC string transferring, with manual modifications for the two permitted accent marks:
|
||||
/// <br>0xC1 at arr[0xBF] = Á (Spanish In-game Trade Voltorb, FALCÁN)</br>
|
||||
/// <br>0xCD at arr[0xC9] = Í (Spanish In-game Trade Shuckle, MANÍA)</br>
|
||||
/// <br>All other new language sensitive re-mapping (or lack thereof) are inaccessible via the character entry screen.</br>
|
||||
/// </remarks>
|
||||
private static readonly ushort[] us_table =
|
||||
{
|
||||
0x0020, 0x0020, 0x0020, 0x0020, 0x0020, 0x0020, 0x0020, 0x0020, 0x0020, 0x0020, 0x0020, 0x0020, 0x0020, 0x0020, 0x0020, 0x0020, // 0
|
||||
0x0020, 0x0020, 0x0020, 0x0020, 0x0020, 0x0020, 0x0020, 0x0020, 0x0020, 0x0020, 0x0020, 0x0020, 0x0020, 0x0020, 0x0020, 0x0020, // 1
|
||||
0x0020, 0x0020, 0x0020, 0x0020, 0x0020, 0x0020, 0x0020, 0x0020, 0x0020, 0x0020, 0x0020, 0x0020, 0x0020, 0x0020, 0x0020, 0x0020, // 2
|
||||
0x0020, 0x0020, 0x0020, 0x0020, 0x0020, 0x0020, 0x0020, 0x0020, 0x0020, 0x0020, 0x0020, 0x0020, 0x0020, 0x0020, 0x0020, 0x0020, // 3
|
||||
0x0020, 0x0020, 0x0020, 0x0020, 0x0020, 0x0020, 0x0020, 0x0020, 0x0020, 0x0020, 0x0020, 0x0020, 0x0020, 0x0020, 0x0020, 0x0020, // 4
|
||||
0x0000, 0x0020, 0x0020, 0x0020, 0x0020, 0x0020, 0x0020, 0x0020, 0x0020, 0x0020, 0x0020, 0x0020, 0x0020, 0x0020, 0x0020, 0x0020, // 5
|
||||
0x0020, 0x0020, 0x0020, 0x0020, 0x0020, 0x0020, 0x0020, 0x0020, 0x0020, 0x0020, 0x0020, 0x0020, 0x0020, 0x0020, 0x0020, 0x0020, // 6
|
||||
0x0020, 0x0020, 0x0020, 0x0020, 0x0020, 0x0020, 0x0020, 0x0020, 0x0020, 0x0020, 0x0020, 0x0020, 0x0020, 0x0020, 0x0020, 0x0020, // 7
|
||||
0x0041, 0x0042, 0x0043, 0x0044, 0x0045, 0x0046, 0x0047, 0x0048, 0x0049, 0x004A, 0x004B, 0x004C, 0x004D, 0x004E, 0x004F, 0x0050, // 8
|
||||
0x0051, 0x0052, 0x0053, 0x0054, 0x0055, 0x0056, 0x0057, 0x0058, 0x0059, 0x005A, 0x0028, 0x0029, 0x003A, 0x003B, 0x0028, 0x0029, // 9
|
||||
0x0061, 0x0062, 0x0063, 0x0064, 0x0065, 0x0066, 0x0067, 0x0068, 0x0069, 0x006A, 0x006B, 0x006C, 0x006D, 0x006E, 0x006F, 0x0070, // A
|
||||
0x0071, 0x0072, 0x0073, 0x0074, 0x0075, 0x0076, 0x0077, 0x0078, 0x0079, 0x007A, 0x0020, 0x0020, 0x0020, 0x0020, 0x0020, 0x00C1, // B
|
||||
0x00C4, 0x00D6, 0x00DC, 0x00E4, 0x00F6, 0x00FC, 0x0020, 0x0020, 0x0020, 0x00CD, 0x0020, 0x0020, 0x0020, 0x0020, 0x0020, 0x0020, // C
|
||||
0x0020, 0x0020, 0x0020, 0x0020, 0x0020, 0x0020, 0x0020, 0x0020, 0x0020, 0x0020, 0x0020, 0x0020, 0x0020, 0x0020, 0x0020, 0x0020, // D
|
||||
0x0020, 0x0050, 0x004D, 0x002D, 0x0020, 0x0020, 0x003F, 0x0021, 0x002D, 0x0020, 0x0020, 0x0020, 0x0020, 0x0020, 0x0020, 0xE08E, // E
|
||||
0x0020, 0x0078, 0x002E, 0x002F, 0x002C, 0xE08F, 0x0020, 0x0020, 0x0020, 0x0020, 0x0020, 0x0020, 0x0020, 0x0020, 0x0020, 0x0020, // F
|
||||
};
|
||||
|
||||
/// <summary>
|
||||
/// Japanese 1->7 character translation table
|
||||
/// </summary>
|
||||
private static readonly ushort[] jp_table =
|
||||
{
|
||||
0x3000, 0x3000, 0x3000, 0x3000, 0x3000, 0x30AC, 0x30AE, 0x30B0, 0x30B2, 0x30B4, 0x30B6, 0x30B8, 0x30BA, 0x30BC, 0x30BE, 0x30C0, // 0
|
||||
0x30C2, 0x30C5, 0x30C7, 0x30C9, 0x3000, 0x3000, 0x3000, 0x3000, 0x3000, 0x30D0, 0x30D3, 0x30D6, 0x30DC, 0x3000, 0x3000, 0x3000, // 1
|
||||
0x3000, 0x3000, 0x3000, 0x3000, 0x3000, 0x3000, 0x304C, 0x304E, 0x3050, 0x3052, 0x3054, 0x3056, 0x3058, 0x305A, 0x305C, 0x305E, // 2
|
||||
0x3060, 0x3062, 0x3065, 0x3067, 0x3069, 0x3000, 0x3000, 0x3000, 0x3000, 0x3000, 0x3070, 0x3073, 0x3076, 0x30D9, 0x307C, 0x3000, // 3
|
||||
0x30D1, 0x30D4, 0x30D7, 0x30DD, 0x3071, 0x3074, 0x3077, 0x30DA, 0x307D, 0x3000, 0x3000, 0x3000, 0x3000, 0x3000, 0x3000, 0x3000, // 4
|
||||
0x0000, 0x3000, 0x3000, 0x3000, 0x3000, 0x3000, 0x3000, 0x3000, 0x3000, 0x3000, 0x3000, 0x3000, 0x3000, 0x3000, 0x3000, 0x3000, // 5
|
||||
0x3000, 0x3000, 0x3000, 0x3000, 0x3000, 0x3000, 0x3000, 0x3000, 0x3000, 0x3000, 0x3000, 0x3000, 0x3000, 0x3000, 0x3000, 0x3000, // 6
|
||||
0x3000, 0x3000, 0x3000, 0x3000, 0x3000, 0x3000, 0x3000, 0x3000, 0x3000, 0x3000, 0x3000, 0x3000, 0x3000, 0x3000, 0x3000, 0x3000, // 7
|
||||
0x30A2, 0x30A4, 0x30A6, 0x30A8, 0x30AA, 0x30AB, 0x30AD, 0x30AF, 0x30B1, 0x30B3, 0x30B5, 0x30B7, 0x30B9, 0x30BB, 0x30BD, 0x30BF, // 8
|
||||
0x30C1, 0x30C4, 0x30C6, 0x30C8, 0x30CA, 0x30CB, 0x30CC, 0x30CD, 0x30CE, 0x30CF, 0x30D2, 0x30D5, 0x30DB, 0x30DE, 0x30DF, 0x30E0, // 9
|
||||
0x30E1, 0x30E2, 0x30E4, 0x30E6, 0x30E8, 0x30E9, 0x30EB, 0x30EC, 0x30ED, 0x30EF, 0x30F2, 0x30F3, 0x30C3, 0x30E3, 0x30E5, 0x30E7, // A
|
||||
0x30A3, 0x3042, 0x3044, 0x3046, 0x3048, 0x304A, 0x304B, 0x304D, 0x304F, 0x3051, 0x3053, 0x3055, 0x3057, 0x3059, 0x305B, 0x305D, // B
|
||||
0x305F, 0x3061, 0x3064, 0x3066, 0x3068, 0x306A, 0x306B, 0x306C, 0x306D, 0x306E, 0x306F, 0x3072, 0x3075, 0x30D8, 0x307B, 0x307E, // C
|
||||
0x307F, 0x3080, 0x3081, 0x3082, 0x3084, 0x3086, 0x3088, 0x3089, 0x30EA, 0x308B, 0x308C, 0x308D, 0x308F, 0x3092, 0x3093, 0x3063, // D
|
||||
0x3083, 0x3085, 0x3087, 0x30FC, 0x3000, 0x3000, 0x3000, 0x3000, 0x3000, 0x30A1, 0x30A5, 0x30A7, 0x3000, 0x3000, 0x3000, 0x2642, // E
|
||||
0x3000, 0x3000, 0x3000, 0x3000, 0x30A9, 0x2640, 0x3000, 0x3000, 0x3000, 0x3000, 0x3000, 0x3000, 0x3000, 0x3000, 0x3000, 0x3000, // F
|
||||
};
|
||||
Span<char> result = stackalloc char[data.Length];
|
||||
int length = LoadString1(data, result, jp);
|
||||
return new string(result[..length].ToArray());
|
||||
}
|
||||
|
||||
private static int LoadString1(ReadOnlySpan<byte> data, Span<char> result, bool jp)
|
||||
{
|
||||
var table = jp ? jp_table : us_table;
|
||||
int i = 0;
|
||||
for (; i < data.Length; i++)
|
||||
{
|
||||
var b = data[i];
|
||||
if (b == 0)
|
||||
break;
|
||||
|
||||
var value = table[b];
|
||||
if (value == Terminator)
|
||||
break;
|
||||
|
||||
result[i] = (char)value;
|
||||
}
|
||||
CheckKata(result[..i]);
|
||||
return i;
|
||||
}
|
||||
|
||||
private static void CheckKata(Span<char> chars)
|
||||
{
|
||||
bool isAnyKata = IsKata(chars);
|
||||
if (!isAnyKata)
|
||||
return;
|
||||
|
||||
if (!IsHiragana(chars))
|
||||
return;
|
||||
|
||||
var span = Katakana.AsSpan();
|
||||
for (int i = 0; i < chars.Length; i++)
|
||||
{
|
||||
int index = span.IndexOf(chars[i]);
|
||||
if (index == -1)
|
||||
continue;
|
||||
chars[i] = Hiragana[index];
|
||||
}
|
||||
}
|
||||
|
||||
private static bool IsKata(ReadOnlySpan<char> chars)
|
||||
{
|
||||
var span = Katakana.AsSpan();
|
||||
foreach (var c in chars)
|
||||
{
|
||||
if (span.IndexOf(c) != -1)
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
private static bool IsHiragana(ReadOnlySpan<char> chars)
|
||||
{
|
||||
foreach (var c in chars)
|
||||
{
|
||||
if ((uint)(c - 0x3041) < 0x53)
|
||||
return true;
|
||||
if ((uint)(c - 0x30A1) < 0x56)
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
private static readonly char[] Katakana = { 'ベ', 'ペ', 'ヘ', 'リ' };
|
||||
private static readonly char[] Hiragana = { 'べ', 'ぺ', 'へ', 'り' };
|
||||
|
||||
/// <summary>
|
||||
/// International 1->7 character translation table
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// Exported from Gen1's VC string transferring, with manual modifications for the two permitted accent marks:
|
||||
/// <br>0xC1 at arr[0xBF] = Á (Spanish In-game Trade Voltorb, FALCÁN)</br>
|
||||
/// <br>0xCD at arr[0xC9] = Í (Spanish In-game Trade Shuckle, MANÍA)</br>
|
||||
/// <br>All other new language sensitive re-mapping (or lack thereof) are inaccessible via the character entry screen.</br>
|
||||
/// </remarks>
|
||||
private static readonly ushort[] us_table =
|
||||
{
|
||||
0x0020, 0x0020, 0x0020, 0x0020, 0x0020, 0x0020, 0x0020, 0x0020, 0x0020, 0x0020, 0x0020, 0x0020, 0x0020, 0x0020, 0x0020, 0x0020, // 0
|
||||
0x0020, 0x0020, 0x0020, 0x0020, 0x0020, 0x0020, 0x0020, 0x0020, 0x0020, 0x0020, 0x0020, 0x0020, 0x0020, 0x0020, 0x0020, 0x0020, // 1
|
||||
0x0020, 0x0020, 0x0020, 0x0020, 0x0020, 0x0020, 0x0020, 0x0020, 0x0020, 0x0020, 0x0020, 0x0020, 0x0020, 0x0020, 0x0020, 0x0020, // 2
|
||||
0x0020, 0x0020, 0x0020, 0x0020, 0x0020, 0x0020, 0x0020, 0x0020, 0x0020, 0x0020, 0x0020, 0x0020, 0x0020, 0x0020, 0x0020, 0x0020, // 3
|
||||
0x0020, 0x0020, 0x0020, 0x0020, 0x0020, 0x0020, 0x0020, 0x0020, 0x0020, 0x0020, 0x0020, 0x0020, 0x0020, 0x0020, 0x0020, 0x0020, // 4
|
||||
0x0000, 0x0020, 0x0020, 0x0020, 0x0020, 0x0020, 0x0020, 0x0020, 0x0020, 0x0020, 0x0020, 0x0020, 0x0020, 0x0020, 0x0020, 0x0020, // 5
|
||||
0x0020, 0x0020, 0x0020, 0x0020, 0x0020, 0x0020, 0x0020, 0x0020, 0x0020, 0x0020, 0x0020, 0x0020, 0x0020, 0x0020, 0x0020, 0x0020, // 6
|
||||
0x0020, 0x0020, 0x0020, 0x0020, 0x0020, 0x0020, 0x0020, 0x0020, 0x0020, 0x0020, 0x0020, 0x0020, 0x0020, 0x0020, 0x0020, 0x0020, // 7
|
||||
0x0041, 0x0042, 0x0043, 0x0044, 0x0045, 0x0046, 0x0047, 0x0048, 0x0049, 0x004A, 0x004B, 0x004C, 0x004D, 0x004E, 0x004F, 0x0050, // 8
|
||||
0x0051, 0x0052, 0x0053, 0x0054, 0x0055, 0x0056, 0x0057, 0x0058, 0x0059, 0x005A, 0x0028, 0x0029, 0x003A, 0x003B, 0x0028, 0x0029, // 9
|
||||
0x0061, 0x0062, 0x0063, 0x0064, 0x0065, 0x0066, 0x0067, 0x0068, 0x0069, 0x006A, 0x006B, 0x006C, 0x006D, 0x006E, 0x006F, 0x0070, // A
|
||||
0x0071, 0x0072, 0x0073, 0x0074, 0x0075, 0x0076, 0x0077, 0x0078, 0x0079, 0x007A, 0x0020, 0x0020, 0x0020, 0x0020, 0x0020, 0x00C1, // B
|
||||
0x00C4, 0x00D6, 0x00DC, 0x00E4, 0x00F6, 0x00FC, 0x0020, 0x0020, 0x0020, 0x00CD, 0x0020, 0x0020, 0x0020, 0x0020, 0x0020, 0x0020, // C
|
||||
0x0020, 0x0020, 0x0020, 0x0020, 0x0020, 0x0020, 0x0020, 0x0020, 0x0020, 0x0020, 0x0020, 0x0020, 0x0020, 0x0020, 0x0020, 0x0020, // D
|
||||
0x0020, 0x0050, 0x004D, 0x002D, 0x0020, 0x0020, 0x003F, 0x0021, 0x002D, 0x0020, 0x0020, 0x0020, 0x0020, 0x0020, 0x0020, 0xE08E, // E
|
||||
0x0020, 0x0078, 0x002E, 0x002F, 0x002C, 0xE08F, 0x0020, 0x0020, 0x0020, 0x0020, 0x0020, 0x0020, 0x0020, 0x0020, 0x0020, 0x0020, // F
|
||||
};
|
||||
|
||||
/// <summary>
|
||||
/// Japanese 1->7 character translation table
|
||||
/// </summary>
|
||||
private static readonly ushort[] jp_table =
|
||||
{
|
||||
0x3000, 0x3000, 0x3000, 0x3000, 0x3000, 0x30AC, 0x30AE, 0x30B0, 0x30B2, 0x30B4, 0x30B6, 0x30B8, 0x30BA, 0x30BC, 0x30BE, 0x30C0, // 0
|
||||
0x30C2, 0x30C5, 0x30C7, 0x30C9, 0x3000, 0x3000, 0x3000, 0x3000, 0x3000, 0x30D0, 0x30D3, 0x30D6, 0x30DC, 0x3000, 0x3000, 0x3000, // 1
|
||||
0x3000, 0x3000, 0x3000, 0x3000, 0x3000, 0x3000, 0x304C, 0x304E, 0x3050, 0x3052, 0x3054, 0x3056, 0x3058, 0x305A, 0x305C, 0x305E, // 2
|
||||
0x3060, 0x3062, 0x3065, 0x3067, 0x3069, 0x3000, 0x3000, 0x3000, 0x3000, 0x3000, 0x3070, 0x3073, 0x3076, 0x30D9, 0x307C, 0x3000, // 3
|
||||
0x30D1, 0x30D4, 0x30D7, 0x30DD, 0x3071, 0x3074, 0x3077, 0x30DA, 0x307D, 0x3000, 0x3000, 0x3000, 0x3000, 0x3000, 0x3000, 0x3000, // 4
|
||||
0x0000, 0x3000, 0x3000, 0x3000, 0x3000, 0x3000, 0x3000, 0x3000, 0x3000, 0x3000, 0x3000, 0x3000, 0x3000, 0x3000, 0x3000, 0x3000, // 5
|
||||
0x3000, 0x3000, 0x3000, 0x3000, 0x3000, 0x3000, 0x3000, 0x3000, 0x3000, 0x3000, 0x3000, 0x3000, 0x3000, 0x3000, 0x3000, 0x3000, // 6
|
||||
0x3000, 0x3000, 0x3000, 0x3000, 0x3000, 0x3000, 0x3000, 0x3000, 0x3000, 0x3000, 0x3000, 0x3000, 0x3000, 0x3000, 0x3000, 0x3000, // 7
|
||||
0x30A2, 0x30A4, 0x30A6, 0x30A8, 0x30AA, 0x30AB, 0x30AD, 0x30AF, 0x30B1, 0x30B3, 0x30B5, 0x30B7, 0x30B9, 0x30BB, 0x30BD, 0x30BF, // 8
|
||||
0x30C1, 0x30C4, 0x30C6, 0x30C8, 0x30CA, 0x30CB, 0x30CC, 0x30CD, 0x30CE, 0x30CF, 0x30D2, 0x30D5, 0x30DB, 0x30DE, 0x30DF, 0x30E0, // 9
|
||||
0x30E1, 0x30E2, 0x30E4, 0x30E6, 0x30E8, 0x30E9, 0x30EB, 0x30EC, 0x30ED, 0x30EF, 0x30F2, 0x30F3, 0x30C3, 0x30E3, 0x30E5, 0x30E7, // A
|
||||
0x30A3, 0x3042, 0x3044, 0x3046, 0x3048, 0x304A, 0x304B, 0x304D, 0x304F, 0x3051, 0x3053, 0x3055, 0x3057, 0x3059, 0x305B, 0x305D, // B
|
||||
0x305F, 0x3061, 0x3064, 0x3066, 0x3068, 0x306A, 0x306B, 0x306C, 0x306D, 0x306E, 0x306F, 0x3072, 0x3075, 0x30D8, 0x307B, 0x307E, // C
|
||||
0x307F, 0x3080, 0x3081, 0x3082, 0x3084, 0x3086, 0x3088, 0x3089, 0x30EA, 0x308B, 0x308C, 0x308D, 0x308F, 0x3092, 0x3093, 0x3063, // D
|
||||
0x3083, 0x3085, 0x3087, 0x30FC, 0x3000, 0x3000, 0x3000, 0x3000, 0x3000, 0x30A1, 0x30A5, 0x30A7, 0x3000, 0x3000, 0x3000, 0x2642, // E
|
||||
0x3000, 0x3000, 0x3000, 0x3000, 0x30A9, 0x2640, 0x3000, 0x3000, 0x3000, 0x3000, 0x3000, 0x3000, 0x3000, 0x3000, 0x3000, 0x3000, // F
|
||||
};
|
||||
}
|
||||
|
|
File diff suppressed because it is too large
Load diff
|
@ -1,196 +1,144 @@
|
|||
using System;
|
||||
using System.Text;
|
||||
|
||||
namespace PKHeX.Core
|
||||
namespace PKHeX.Core;
|
||||
|
||||
/// <summary>
|
||||
/// Logic for converting a <see cref="string"/> for Generation 3.
|
||||
/// </summary>
|
||||
public static class StringConverter3
|
||||
{
|
||||
private const byte TerminatorByte = 0xFF;
|
||||
private const char Terminator = (char)TerminatorByte;
|
||||
|
||||
/// <summary>
|
||||
/// Logic for converting a <see cref="string"/> for Generation 3.
|
||||
/// Converts a Generation 3 encoded value array to string.
|
||||
/// </summary>
|
||||
public static class StringConverter3
|
||||
/// <param name="data">Byte array containing string data.</param>
|
||||
/// <param name="jp">Value source is Japanese font.</param>
|
||||
/// <returns>Decoded string.</returns>
|
||||
public static string GetString(ReadOnlySpan<byte> data, bool jp)
|
||||
{
|
||||
private const byte TerminatorByte = 0xFF;
|
||||
private const char Terminator = (char)TerminatorByte;
|
||||
private const char TerminatorBigEndian = (char)0; // GC
|
||||
|
||||
/// <summary>
|
||||
/// Converts a Generation 3 encoded value array to string.
|
||||
/// </summary>
|
||||
/// <param name="data">Byte array containing string data.</param>
|
||||
/// <param name="offset">Offset to read from</param>
|
||||
/// <param name="count">Length of data to read.</param>
|
||||
/// <param name="jp">Value source is Japanese font.</param>
|
||||
/// <returns>Decoded string.</returns>
|
||||
public static string GetString3(byte[] data, int offset, int count, bool jp) => GetString3(data.AsSpan(offset, count), jp);
|
||||
|
||||
/// <summary>
|
||||
/// Converts a Generation 3 encoded value array to string.
|
||||
/// </summary>
|
||||
/// <param name="data">Byte array containing string data.</param>
|
||||
/// <param name="jp">Value source is Japanese font.</param>
|
||||
/// <returns>Decoded string.</returns>
|
||||
public static string GetString3(ReadOnlySpan<byte> data, bool jp)
|
||||
Span<char> result = stackalloc char[data.Length];
|
||||
int i = 0;
|
||||
for (; i < data.Length; i++)
|
||||
{
|
||||
var s = new StringBuilder(data.Length);
|
||||
foreach (var val in data)
|
||||
{
|
||||
var c = GetG3Char(val, jp); // Convert to Unicode
|
||||
if (c == Terminator) // Stop if Terminator/Invalid
|
||||
break;
|
||||
s.Append(c);
|
||||
}
|
||||
StringConverter.SanitizeString(s);
|
||||
return s.ToString();
|
||||
var value = data[i];
|
||||
var c = GetG3Char(value, jp); // Convert to Unicode
|
||||
if (c == Terminator) // Stop if Terminator/Invalid
|
||||
break;
|
||||
result[i] = c;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Converts a string to a Generation 3 encoded value array.
|
||||
/// </summary>
|
||||
/// <param name="value">Decoded string.</param>
|
||||
/// <param name="maxLength">Maximum length of the input <see cref="value"/></param>
|
||||
/// <param name="jp">String destination is Japanese font.</param>
|
||||
/// <param name="padTo">Pad the input <see cref="value"/> to given length</param>
|
||||
/// <param name="padWith">Pad the input <see cref="value"/> with this character value</param>
|
||||
/// <returns>Encoded data.</returns>
|
||||
public static byte[] SetString3(string value, int maxLength, bool jp, int padTo = 0, ushort padWith = 0)
|
||||
{
|
||||
if (value.Length > maxLength)
|
||||
value = value[..maxLength]; // Hard cap
|
||||
var data = new byte[value.Length + 1]; // +1 for Terminator
|
||||
for (int i = 0; i < value.Length; i++)
|
||||
{
|
||||
var chr = value[i];
|
||||
var val = SetG3Char(chr, jp);
|
||||
if (val == Terminator) // end
|
||||
{
|
||||
Array.Resize(ref data, i + 1);
|
||||
break;
|
||||
}
|
||||
data[i] = val;
|
||||
}
|
||||
if (data.Length > 0)
|
||||
data[^1] = TerminatorByte;
|
||||
if (data.Length > maxLength && padTo <= maxLength)
|
||||
{
|
||||
// Truncate
|
||||
Array.Resize(ref data, maxLength);
|
||||
return data;
|
||||
}
|
||||
if (data.Length < padTo)
|
||||
{
|
||||
var start = data.Length;
|
||||
Array.Resize(ref data, padTo);
|
||||
for (int i = start; i < data.Length; i++)
|
||||
data[i] = (byte)padWith;
|
||||
}
|
||||
return data;
|
||||
}
|
||||
|
||||
/// <summary>Converts Big Endian encoded data to decoded string.</summary>
|
||||
/// <param name="data">Encoded data</param>
|
||||
/// <param name="offset">Offset to read from</param>
|
||||
/// <param name="count">Length of data to read.</param>
|
||||
/// <returns>Decoded string.</returns>
|
||||
public static string GetBEString3(byte[] data, int offset, int count)
|
||||
{
|
||||
var raw = Encoding.BigEndianUnicode.GetString(data, offset, count);
|
||||
var sb = new StringBuilder(raw);
|
||||
Util.TrimFromFirst(sb, TerminatorBigEndian);
|
||||
return sb.ToString();
|
||||
}
|
||||
|
||||
/// <summary>Gets the bytes for a Big Endian string.</summary>
|
||||
/// <param name="value">Decoded string.</param>
|
||||
/// <param name="maxLength">Maximum length of the input <see cref="value"/></param>
|
||||
/// <param name="padTo">Pad the input <see cref="value"/> to given length</param>
|
||||
/// <param name="padWith">Pad the input <see cref="value"/> with this character value</param>
|
||||
/// <returns>Encoded data.</returns>
|
||||
public static byte[] SetBEString3(string value, int maxLength, int padTo = 0, ushort padWith = TerminatorBigEndian)
|
||||
{
|
||||
if (value.Length > maxLength)
|
||||
value = value[..maxLength]; // Hard cap
|
||||
var sb = new StringBuilder(value);
|
||||
StringConverter.SanitizeString(sb);
|
||||
sb.Append(TerminatorBigEndian);
|
||||
var delta = padTo - value.Length;
|
||||
if (delta > 0)
|
||||
sb.Append((char)padWith, delta);
|
||||
var result = sb.ToString();
|
||||
return Encoding.BigEndianUnicode.GetBytes(result);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Decodes a character from a Generation 3 encoded value.
|
||||
/// </summary>
|
||||
/// <param name="chr">Generation 4 decoded character.</param>
|
||||
/// <param name="jp">Character destination is Japanese font.</param>
|
||||
/// <returns>Generation 3 encoded value.</returns>
|
||||
private static char GetG3Char(byte chr, bool jp)
|
||||
{
|
||||
var table = jp ? G3_JP : G3_EN;
|
||||
return table[chr];
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Encodes a character to a Generation 3 encoded value.
|
||||
/// </summary>
|
||||
/// <param name="chr">Generation 4 decoded character.</param>
|
||||
/// <param name="jp">Character destination is Japanese font.</param>
|
||||
/// <returns>Generation 3 encoded value.</returns>
|
||||
private static byte SetG3Char(char chr, bool jp)
|
||||
{
|
||||
if (chr == '\'') // ’
|
||||
return 0xB4;
|
||||
var table = jp ? G3_JP : G3_EN;
|
||||
var index = Array.IndexOf(table, chr);
|
||||
if (index == -1)
|
||||
return TerminatorByte;
|
||||
return (byte)index;
|
||||
}
|
||||
|
||||
private static readonly char[] G3_EN =
|
||||
{
|
||||
' ', 'À', 'Á', 'Â', 'Ç', 'È', 'É', 'Ê', 'Ë', 'Ì', 'こ', 'Î', 'Ï', 'Ò', 'Ó', 'Ô', // 0
|
||||
'Œ', 'Ù', 'Ú', 'Û', 'Ñ', 'ß', 'à', 'á', 'ね', 'Ç', 'È', 'é', 'ê', 'ë', 'ì', 'í', // 1
|
||||
'î', 'ï', 'ò', 'ó', 'ô', 'œ', 'ù', 'ú', 'û', 'ñ', 'º', 'ª', '⒅', '&', '+', 'あ', // 2
|
||||
'ぃ', 'ぅ', 'ぇ', 'ぉ', 'ゃ', '=', 'ょ', 'が', 'ぎ', 'ぐ', 'げ', 'ご', 'ざ', 'じ', 'ず', 'ぜ', // 3
|
||||
'ぞ', 'だ', 'ぢ', 'づ', 'で', 'ど', 'ば', 'び', 'ぶ', 'べ', 'ぼ', 'ぱ', 'ぴ', 'ぷ', 'ぺ', 'ぽ', // 4
|
||||
'っ', '¿', '¡', '⒆', '⒇', 'オ', 'カ', 'キ', 'ク', 'ケ', 'Í', 'コ', 'サ', 'ス', 'セ', 'ソ', // 5
|
||||
'タ', 'チ', 'ツ', 'テ', 'ト', 'ナ', 'ニ', 'ヌ', 'â', 'ノ', 'ハ', 'ヒ', 'フ', 'ヘ', 'ホ', 'í', // 6
|
||||
'ミ', 'ム', 'メ', 'モ', 'ヤ', 'ユ', 'ヨ', 'ラ', 'リ', 'ル', 'レ', 'ロ', 'ワ', 'ヲ', 'ン', 'ァ', // 7
|
||||
'ィ', 'ゥ', 'ェ', 'ォ', 'ャ', 'ュ', 'ョ', 'ガ', 'ギ', 'グ', 'ゲ', 'ゴ', 'ザ', 'ジ', 'ズ', 'ゼ', // 8
|
||||
'ゾ', 'ダ', 'ヂ', 'ヅ', 'デ', 'ド', 'バ', 'ビ', 'ブ', 'ベ', 'ボ', 'パ', 'ピ', 'プ', 'ペ', 'ポ', // 9
|
||||
'ッ', '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', '!', '?', '.', '-', '・',// A
|
||||
'⑬', '“', '”', '‘', '’', '♂', '♀', '$', ',', '⑧', '/', 'A', 'B', 'C', 'D', 'E', // B
|
||||
'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', // C
|
||||
'V', 'W', 'X', 'Y', 'Z', 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', // D
|
||||
'l', 'm', 'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z', '0', // E
|
||||
':', 'Ä', 'Ö', 'Ü', 'ä', 'ö', 'ü', // F
|
||||
|
||||
// Make the total length 256 so that any byte access is always within the array
|
||||
Terminator, Terminator, Terminator, Terminator, Terminator, Terminator, Terminator, Terminator, Terminator,
|
||||
};
|
||||
|
||||
private static readonly char[] G3_JP =
|
||||
{
|
||||
' ', 'あ', 'い', 'う', 'え', 'お', 'か', 'き', 'く', 'け', 'こ', 'さ', 'し', 'す', 'せ', 'そ', // 0
|
||||
'た', 'ち', 'つ', 'て', 'と', 'な', 'に', 'ぬ', 'ね', 'の', 'は', 'ひ', 'ふ', 'へ', 'ほ', 'ま', // 1
|
||||
'み', 'む', 'め', 'も', 'や', 'ゆ', 'よ', 'ら', 'り', 'る', 'れ', 'ろ', 'わ', 'を', 'ん', 'ぁ', // 2
|
||||
'ぃ', 'ぅ', 'ぇ', 'ぉ', 'ゃ', 'ゅ', 'ょ', 'が', 'ぎ', 'ぐ', 'げ', 'ご', 'ざ', 'じ', 'ず', 'ぜ', // 3
|
||||
'ぞ', 'だ', 'ぢ', 'づ', 'で', 'ど', 'ば', 'び', 'ぶ', 'べ', 'ぼ', 'ぱ', 'ぴ', 'ぷ', 'ぺ', 'ぽ', // 4
|
||||
'っ', 'ア', 'イ', 'ウ', 'エ', 'オ', 'カ', 'キ', 'ク', 'ケ', 'コ', 'サ', 'シ', 'ス', 'セ', 'ソ', // 5
|
||||
'タ', 'チ', 'ツ', 'テ', 'ト', 'ナ', 'ニ', 'ヌ', 'ネ', 'ノ', 'ハ', 'ヒ', 'フ', 'ヘ', 'ホ', 'マ', // 6
|
||||
'ミ', 'ム', 'メ', 'モ', 'ヤ', 'ユ', 'ヨ', 'ラ', 'リ', 'ル', 'レ', 'ロ', 'ワ', 'ヲ', 'ン', 'ァ', // 7
|
||||
'ィ', 'ゥ', 'ェ', 'ォ', 'ャ', 'ュ', 'ョ', 'ガ', 'ギ', 'グ', 'ゲ', 'ゴ', 'ザ', 'ジ', 'ズ', 'ゼ', // 8
|
||||
'ゾ', 'ダ', 'ヂ', 'ヅ', 'デ', 'ド', 'バ', 'ビ', 'ブ', 'ベ', 'ボ', 'パ', 'ピ', 'プ', 'ペ', 'ポ', // 9
|
||||
'ッ', '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', '!', '?', '。', 'ー', '・', // A
|
||||
'⋯', '『', '』', '「', '」', '♂', '♀', '$', '.', '⑧', '/', 'A', 'B', 'C', 'D', 'E', // B
|
||||
'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', // C
|
||||
'V', 'W', 'X', 'Y', 'Z', 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', // D
|
||||
'l', 'm', 'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z', '0', // E
|
||||
':', 'Ä', 'Ö', 'Ü', 'ä', 'ö', 'ü', // F
|
||||
|
||||
// Make the total length 256 so that any byte access is always within the array
|
||||
Terminator, Terminator, Terminator, Terminator, Terminator, Terminator, Terminator, Terminator, Terminator,
|
||||
};
|
||||
return new string(result[..i].ToArray());
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Converts a string to a Generation 3 encoded value array.
|
||||
/// </summary>
|
||||
/// <param name="buffer"></param>
|
||||
/// <param name="value">Decoded string.</param>
|
||||
/// <param name="maxLength">Maximum length of the input <see cref="value"/></param>
|
||||
/// <param name="jp">String destination is Japanese font.</param>
|
||||
/// <param name="option"></param>
|
||||
/// <returns>Encoded data.</returns>
|
||||
public static int SetString(Span<byte> buffer, ReadOnlySpan<char> value, int maxLength, bool jp,
|
||||
StringConverterOption option = StringConverterOption.ClearFF)
|
||||
{
|
||||
if (value.Length > maxLength)
|
||||
value = value[..maxLength]; // Hard cap
|
||||
|
||||
if (option is StringConverterOption.ClearFF)
|
||||
buffer.Fill(0xFF);
|
||||
else if (option is StringConverterOption.ClearZero)
|
||||
buffer.Clear();
|
||||
|
||||
int i = 0;
|
||||
for (; i < value.Length; i++)
|
||||
{
|
||||
var chr = value[i];
|
||||
var b = SetG3Char(chr, jp);
|
||||
if (b == TerminatorByte)
|
||||
break;
|
||||
buffer[i] = b;
|
||||
}
|
||||
|
||||
int count = i;
|
||||
if (count < buffer.Length)
|
||||
buffer[count++] = TerminatorByte;
|
||||
return count;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Decodes a character from a Generation 3 encoded value.
|
||||
/// </summary>
|
||||
/// <param name="chr">Generation 4 decoded character.</param>
|
||||
/// <param name="jp">Character destination is Japanese font.</param>
|
||||
/// <returns>Generation 3 encoded value.</returns>
|
||||
private static char GetG3Char(byte chr, bool jp)
|
||||
{
|
||||
var table = jp ? G3_JP : G3_EN;
|
||||
return table[chr];
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Encodes a character to a Generation 3 encoded value.
|
||||
/// </summary>
|
||||
/// <param name="chr">Generation 4 decoded character.</param>
|
||||
/// <param name="jp">Character destination is Japanese font.</param>
|
||||
/// <returns>Generation 3 encoded value.</returns>
|
||||
private static byte SetG3Char(char chr, bool jp)
|
||||
{
|
||||
if (chr == '\'') // ’
|
||||
return 0xB4;
|
||||
var table = jp ? G3_JP : G3_EN;
|
||||
var index = Array.IndexOf(table, chr);
|
||||
if (index == -1)
|
||||
return TerminatorByte;
|
||||
return (byte)index;
|
||||
}
|
||||
|
||||
private static readonly char[] G3_EN =
|
||||
{
|
||||
' ', 'À', 'Á', 'Â', 'Ç', 'È', 'É', 'Ê', 'Ë', 'Ì', 'こ', 'Î', 'Ï', 'Ò', 'Ó', 'Ô', // 0
|
||||
'Œ', 'Ù', 'Ú', 'Û', 'Ñ', 'ß', 'à', 'á', 'ね', 'Ç', 'È', 'é', 'ê', 'ë', 'ì', 'í', // 1
|
||||
'î', 'ï', 'ò', 'ó', 'ô', 'œ', 'ù', 'ú', 'û', 'ñ', 'º', 'ª', '⒅', '&', '+', 'あ', // 2
|
||||
'ぃ', 'ぅ', 'ぇ', 'ぉ', 'ゃ', '=', 'ょ', 'が', 'ぎ', 'ぐ', 'げ', 'ご', 'ざ', 'じ', 'ず', 'ぜ', // 3
|
||||
'ぞ', 'だ', 'ぢ', 'づ', 'で', 'ど', 'ば', 'び', 'ぶ', 'べ', 'ぼ', 'ぱ', 'ぴ', 'ぷ', 'ぺ', 'ぽ', // 4
|
||||
'っ', '¿', '¡', '⒆', '⒇', 'オ', 'カ', 'キ', 'ク', 'ケ', 'Í', 'コ', 'サ', 'ス', 'セ', 'ソ', // 5
|
||||
'タ', 'チ', 'ツ', 'テ', 'ト', 'ナ', 'ニ', 'ヌ', 'â', 'ノ', 'ハ', 'ヒ', 'フ', 'ヘ', 'ホ', 'í', // 6
|
||||
'ミ', 'ム', 'メ', 'モ', 'ヤ', 'ユ', 'ヨ', 'ラ', 'リ', 'ル', 'レ', 'ロ', 'ワ', 'ヲ', 'ン', 'ァ', // 7
|
||||
'ィ', 'ゥ', 'ェ', 'ォ', 'ャ', 'ュ', 'ョ', 'ガ', 'ギ', 'グ', 'ゲ', 'ゴ', 'ザ', 'ジ', 'ズ', 'ゼ', // 8
|
||||
'ゾ', 'ダ', 'ヂ', 'ヅ', 'デ', 'ド', 'バ', 'ビ', 'ブ', 'ベ', 'ボ', 'パ', 'ピ', 'プ', 'ペ', 'ポ', // 9
|
||||
'ッ', '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', '!', '?', '.', '-', '・',// A
|
||||
'⑬', '“', '”', '‘', '’', '♂', '♀', '$', ',', '⑧', '/', 'A', 'B', 'C', 'D', 'E', // B
|
||||
'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', // C
|
||||
'V', 'W', 'X', 'Y', 'Z', 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', // D
|
||||
'l', 'm', 'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z', '0', // E
|
||||
':', 'Ä', 'Ö', 'Ü', 'ä', 'ö', 'ü', // F
|
||||
|
||||
// Make the total length 256 so that any byte access is always within the array
|
||||
Terminator, Terminator, Terminator, Terminator, Terminator, Terminator, Terminator, Terminator, Terminator,
|
||||
};
|
||||
|
||||
private static readonly char[] G3_JP =
|
||||
{
|
||||
' ', 'あ', 'い', 'う', 'え', 'お', 'か', 'き', 'く', 'け', 'こ', 'さ', 'し', 'す', 'せ', 'そ', // 0
|
||||
'た', 'ち', 'つ', 'て', 'と', 'な', 'に', 'ぬ', 'ね', 'の', 'は', 'ひ', 'ふ', 'へ', 'ほ', 'ま', // 1
|
||||
'み', 'む', 'め', 'も', 'や', 'ゆ', 'よ', 'ら', 'り', 'る', 'れ', 'ろ', 'わ', 'を', 'ん', 'ぁ', // 2
|
||||
'ぃ', 'ぅ', 'ぇ', 'ぉ', 'ゃ', 'ゅ', 'ょ', 'が', 'ぎ', 'ぐ', 'げ', 'ご', 'ざ', 'じ', 'ず', 'ぜ', // 3
|
||||
'ぞ', 'だ', 'ぢ', 'づ', 'で', 'ど', 'ば', 'び', 'ぶ', 'べ', 'ぼ', 'ぱ', 'ぴ', 'ぷ', 'ぺ', 'ぽ', // 4
|
||||
'っ', 'ア', 'イ', 'ウ', 'エ', 'オ', 'カ', 'キ', 'ク', 'ケ', 'コ', 'サ', 'シ', 'ス', 'セ', 'ソ', // 5
|
||||
'タ', 'チ', 'ツ', 'テ', 'ト', 'ナ', 'ニ', 'ヌ', 'ネ', 'ノ', 'ハ', 'ヒ', 'フ', 'ヘ', 'ホ', 'マ', // 6
|
||||
'ミ', 'ム', 'メ', 'モ', 'ヤ', 'ユ', 'ヨ', 'ラ', 'リ', 'ル', 'レ', 'ロ', 'ワ', 'ヲ', 'ン', 'ァ', // 7
|
||||
'ィ', 'ゥ', 'ェ', 'ォ', 'ャ', 'ュ', 'ョ', 'ガ', 'ギ', 'グ', 'ゲ', 'ゴ', 'ザ', 'ジ', 'ズ', 'ゼ', // 8
|
||||
'ゾ', 'ダ', 'ヂ', 'ヅ', 'デ', 'ド', 'バ', 'ビ', 'ブ', 'ベ', 'ボ', 'パ', 'ピ', 'プ', 'ペ', 'ポ', // 9
|
||||
'ッ', '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', '!', '?', '。', 'ー', '・', // A
|
||||
'⋯', '『', '』', '「', '」', '♂', '♀', '$', '.', '⑧', '/', 'A', 'B', 'C', 'D', 'E', // B
|
||||
'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', // C
|
||||
'V', 'W', 'X', 'Y', 'Z', 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', // D
|
||||
'l', 'm', 'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z', '0', // E
|
||||
':', 'Ä', 'Ö', 'Ü', 'ä', 'ö', 'ü', // F
|
||||
|
||||
// Make the total length 256 so that any byte access is always within the array
|
||||
Terminator, Terminator, Terminator, Terminator, Terminator, Terminator, Terminator, Terminator, Terminator,
|
||||
};
|
||||
}
|
||||
|
|
|
@ -1,67 +1,66 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using static System.Buffers.Binary.BinaryPrimitives;
|
||||
|
||||
namespace PKHeX.Core
|
||||
namespace PKHeX.Core;
|
||||
|
||||
/// <summary>
|
||||
/// Logic for converting a <see cref="string"/> for to future Generations.
|
||||
/// </summary>
|
||||
public static class StringConverter345
|
||||
{
|
||||
/// <summary>
|
||||
/// Logic for converting a <see cref="string"/> for to future Generations.
|
||||
/// Trash Bytes for Generation 3->4
|
||||
/// </summary>
|
||||
public static class StringConverter345
|
||||
/// <remarks>String buffers are reused, data is not cleared which yields the trash bytes.</remarks>
|
||||
public static readonly byte[][] G4TransferTrashBytes = {
|
||||
Array.Empty<byte>(), // Unused
|
||||
new byte[] { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 },
|
||||
new byte[] { 0x18, 0x20, 0x0D, 0x02, 0x42, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x48, 0xA1, 0x0C, 0x02, 0xE0, 0xFF },
|
||||
new byte[] { 0x74, 0x20, 0x0D, 0x02, 0x42, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xA4, 0xA1, 0x0C, 0x02, 0xE0, 0xFF },
|
||||
new byte[] { 0x54, 0x20, 0x0D, 0x02, 0x42, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x84, 0xA1, 0x0C, 0x02, 0xE0, 0xFF },
|
||||
new byte[] { 0x74, 0x20, 0x0D, 0x02, 0x42, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xA4, 0xA1, 0x0C, 0x02, 0xE0, 0xFF },
|
||||
Array.Empty<byte>(), // Unused
|
||||
new byte[] { 0x74, 0x20, 0x0D, 0x02, 0x42, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xA4, 0xA1, 0x0C, 0x02, 0xE0, 0xFF },
|
||||
};
|
||||
|
||||
/// <summary>
|
||||
/// Remaps Gen5 Glyphs to unicode codepoint.
|
||||
/// </summary>
|
||||
/// <param name="buffer">Input characters to transfer in place</param>
|
||||
/// <returns>Remapped string</returns>
|
||||
public static void TransferGlyphs56(Span<byte> buffer)
|
||||
{
|
||||
/// <summary>
|
||||
/// Trash Bytes for Generation 3->4
|
||||
/// </summary>
|
||||
/// <remarks>String buffers are reused, data is not cleared which yields the trash bytes.</remarks>
|
||||
public static readonly byte[][] G4TransferTrashBytes = {
|
||||
Array.Empty<byte>(), // Unused
|
||||
new byte[] { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 },
|
||||
new byte[] { 0x18, 0x20, 0x0D, 0x02, 0x42, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x48, 0xA1, 0x0C, 0x02, 0xE0, 0xFF },
|
||||
new byte[] { 0x74, 0x20, 0x0D, 0x02, 0x42, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xA4, 0xA1, 0x0C, 0x02, 0xE0, 0xFF },
|
||||
new byte[] { 0x54, 0x20, 0x0D, 0x02, 0x42, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x84, 0xA1, 0x0C, 0x02, 0xE0, 0xFF },
|
||||
new byte[] { 0x74, 0x20, 0x0D, 0x02, 0x42, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xA4, 0xA1, 0x0C, 0x02, 0xE0, 0xFF },
|
||||
Array.Empty<byte>(), // Unused
|
||||
new byte[] { 0x74, 0x20, 0x0D, 0x02, 0x42, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xA4, 0xA1, 0x0C, 0x02, 0xE0, 0xFF },
|
||||
};
|
||||
|
||||
/// <summary>
|
||||
/// Remaps Gen5 Glyphs to unicode codepoint.
|
||||
/// </summary>
|
||||
/// <param name="str">Input string</param>
|
||||
/// <returns>Remapped string</returns>
|
||||
public static string TransferGlyphs56(string str)
|
||||
var table = Glyph56;
|
||||
for (int i = 0; i < buffer.Length; i += 2)
|
||||
{
|
||||
var result = new char[str.Length];
|
||||
var table = Glyph56;
|
||||
for (int i = 0; i < str.Length; i++)
|
||||
{
|
||||
var c = str[i];
|
||||
result[i] = table.TryGetValue(c, out var translated) ? translated : c;
|
||||
}
|
||||
return new string(result);
|
||||
var c = (char)ReadUInt16LittleEndian(buffer[i..]);
|
||||
if (table.TryGetValue(c, out c))
|
||||
WriteUInt16LittleEndian(buffer[i..], c);
|
||||
}
|
||||
|
||||
private static readonly Dictionary<char, char> Glyph56 = new()
|
||||
{
|
||||
{'\u2467', '\u00d7'}, // ×
|
||||
{'\u2468', '\u00f7'}, // ÷
|
||||
|
||||
{'\u246c', '\uE08D'}, // …
|
||||
{'\u246d', '\uE08E'}, // ♂
|
||||
{'\u246e', '\uE08F'}, // ♀
|
||||
{'\u246f', '\uE090'}, // ♠
|
||||
{'\u2470', '\uE091'}, // ♣
|
||||
{'\u2471', '\uE092'}, // ♥
|
||||
{'\u2472', '\uE093'}, // ♦
|
||||
{'\u2473', '\uE094'}, // ★
|
||||
{'\u2474', '\uE095'}, // ◎
|
||||
{'\u2475', '\uE096'}, // ○
|
||||
{'\u2476', '\uE097'}, // □
|
||||
{'\u2477', '\uE098'}, // △
|
||||
{'\u2478', '\uE099'}, // ◇
|
||||
{'\u2479', '\uE09A'}, // ♪
|
||||
{'\u247a', '\uE09B'}, // ☀
|
||||
{'\u247b', '\uE09C'}, // ☁
|
||||
{'\u247d', '\uE09D'}, // ☂
|
||||
};
|
||||
}
|
||||
|
||||
private static readonly Dictionary<char, char> Glyph56 = new()
|
||||
{
|
||||
{'\u2467', '\u00d7'}, // ×
|
||||
{'\u2468', '\u00f7'}, // ÷
|
||||
|
||||
{'\u246c', '\uE08D'}, // …
|
||||
{'\u246d', '\uE08E'}, // ♂
|
||||
{'\u246e', '\uE08F'}, // ♀
|
||||
{'\u246f', '\uE090'}, // ♠
|
||||
{'\u2470', '\uE091'}, // ♣
|
||||
{'\u2471', '\uE092'}, // ♥
|
||||
{'\u2472', '\uE093'}, // ♦
|
||||
{'\u2473', '\uE094'}, // ★
|
||||
{'\u2474', '\uE095'}, // ◎
|
||||
{'\u2475', '\uE096'}, // ○
|
||||
{'\u2476', '\uE097'}, // □
|
||||
{'\u2477', '\uE098'}, // △
|
||||
{'\u2478', '\uE099'}, // ◇
|
||||
{'\u2479', '\uE09A'}, // ♪
|
||||
{'\u247a', '\uE09B'}, // ☀
|
||||
{'\u247b', '\uE09C'}, // ☁
|
||||
{'\u247d', '\uE09D'}, // ☂
|
||||
};
|
||||
}
|
||||
|
|
59
PKHeX.Core/PKM/Strings/StringConverter3GC.cs
Normal file
59
PKHeX.Core/PKM/Strings/StringConverter3GC.cs
Normal file
|
@ -0,0 +1,59 @@
|
|||
using System;
|
||||
using static System.Buffers.Binary.BinaryPrimitives;
|
||||
|
||||
namespace PKHeX.Core;
|
||||
|
||||
public static class StringConverter3GC
|
||||
{
|
||||
private const char TerminatorBigEndian = (char)0; // GC
|
||||
|
||||
/// <summary>Converts Big Endian encoded data to decoded string.</summary>
|
||||
/// <param name="data">Encoded data</param>
|
||||
/// <returns>Decoded string.</returns>
|
||||
public static string GetString(ReadOnlySpan<byte> data)
|
||||
{
|
||||
Span<char> result = stackalloc char[data.Length];
|
||||
int length = LoadString(data, result);
|
||||
return new string(result[..length].ToArray());
|
||||
}
|
||||
|
||||
private static int LoadString(ReadOnlySpan<byte> data, Span<char> result)
|
||||
{
|
||||
int i = 0;
|
||||
for (; i < data.Length; i += 2)
|
||||
{
|
||||
var value = (char)ReadUInt16BigEndian(data[i..]);
|
||||
if (value == TerminatorBigEndian)
|
||||
break;
|
||||
result[i/2] = value;
|
||||
}
|
||||
return i/2;
|
||||
}
|
||||
|
||||
/// <summary>Gets the bytes for a Big Endian string.</summary>
|
||||
/// <param name="destBuffer"></param>
|
||||
/// <param name="value">Decoded string.</param>
|
||||
/// <param name="maxLength">Maximum length of the input <see cref="value"/></param>
|
||||
/// <param name="option">Option to clear the buffer. Only <see cref="StringConverterOption.ClearZero"/> is recognized.</param>
|
||||
/// <returns>Encoded data.</returns>
|
||||
public static int SetString(Span<byte> destBuffer, ReadOnlySpan<char> value, int maxLength,
|
||||
StringConverterOption option)
|
||||
{
|
||||
if (value.Length > maxLength)
|
||||
value = value[..maxLength]; // Hard cap
|
||||
|
||||
if (option is StringConverterOption.ClearZero)
|
||||
destBuffer.Clear();
|
||||
|
||||
for (int i = 0; i < value.Length; i++)
|
||||
{
|
||||
var c = value[i];
|
||||
WriteUInt16BigEndian(destBuffer[(i * 2)..], c);
|
||||
}
|
||||
|
||||
if (destBuffer.Length == value.Length * 2)
|
||||
return value.Length * 2;
|
||||
WriteUInt16BigEndian(destBuffer[(value.Length * 2)..], TerminatorBigEndian);
|
||||
return (value.Length * 2) + 2;
|
||||
}
|
||||
}
|
|
@ -1,608 +1,71 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using static PKHeX.Core.StringConverter4Util;
|
||||
using static System.Buffers.Binary.BinaryPrimitives;
|
||||
|
||||
namespace PKHeX.Core
|
||||
namespace PKHeX.Core;
|
||||
|
||||
/// <summary>
|
||||
/// Logic for converting a <see cref="string"/> for Generation 4.
|
||||
/// </summary>
|
||||
public static class StringConverter4
|
||||
{
|
||||
/// <summary>
|
||||
/// Logic for converting a <see cref="string"/> for Generation 4.
|
||||
/// </summary>
|
||||
public static class StringConverter4
|
||||
private const ushort Terminator = 0xFFFF;
|
||||
private const char TerminatorChar = (char)Terminator;
|
||||
|
||||
/// <summary>Converts Generation 4 encoded data to decoded string.</summary>
|
||||
/// <param name="data">Encoded data</param>
|
||||
/// <returns>Decoded string.</returns>
|
||||
public static string GetString(ReadOnlySpan<byte> data)
|
||||
{
|
||||
private const ushort Terminator = 0xFFFF;
|
||||
private const char TerminatorChar = (char)Terminator;
|
||||
Span<char> result = stackalloc char[data.Length];
|
||||
var length = LoadString(data, result);
|
||||
return new string(result[..length].ToArray());
|
||||
}
|
||||
|
||||
/// <summary>Converts Generation 4 encoded data to decoded string.</summary>
|
||||
/// <param name="data">Encoded data</param>
|
||||
/// <param name="offset">Offset to read from</param>
|
||||
/// <param name="count">Length of data to read.</param>
|
||||
/// <returns>Decoded string.</returns>
|
||||
public static string GetString4(byte[] data, int offset, int count)
|
||||
private static int LoadString(ReadOnlySpan<byte> data, Span<char> result)
|
||||
{
|
||||
int i = 0;
|
||||
for (; i < data.Length; i += 2)
|
||||
{
|
||||
var s = new StringBuilder(count / 2);
|
||||
for (int i = 0; i < count; i += 2)
|
||||
{
|
||||
var val = BitConverter.ToUInt16(data, offset + i);
|
||||
if (val == Terminator)
|
||||
break;
|
||||
var chr = ConvertValue2CharG4(val);
|
||||
if (chr == TerminatorChar)
|
||||
break;
|
||||
s.Append((char)chr);
|
||||
}
|
||||
StringConverter.SanitizeString(s);
|
||||
return s.ToString();
|
||||
}
|
||||
|
||||
/// <summary>Gets the bytes for a 4th Generation String</summary>
|
||||
/// <param name="value">Decoded string.</param>
|
||||
/// <param name="maxLength">Maximum length of the input <see cref="value"/></param>
|
||||
/// <param name="padTo">Pad the input <see cref="value"/> to given length</param>
|
||||
/// <param name="padWith">Pad the input <see cref="value"/> with this character value</param>
|
||||
/// <returns>Encoded data.</returns>
|
||||
public static byte[] SetString4(string value, int maxLength, int padTo = 0, ushort padWith = 0)
|
||||
{
|
||||
var sb = new StringBuilder(value);
|
||||
var delta = sb.Length - maxLength;
|
||||
if (delta > 0)
|
||||
sb.Remove(maxLength, delta);
|
||||
|
||||
// Replace Special Characters and add Terminator
|
||||
StringConverter.UnSanitizeString(sb, 4);
|
||||
sb.Append(TerminatorChar);
|
||||
var d2 = padTo - sb.Length;
|
||||
if (d2 > 0)
|
||||
sb.Append((char)padWith, d2);
|
||||
|
||||
var data = new byte[sb.Length * 2];
|
||||
for (int i = 0; i < sb.Length; i++)
|
||||
{
|
||||
var chr = sb[i];
|
||||
var val = ConvertChar2ValueG4(chr);
|
||||
BitConverter.GetBytes(val).CopyTo(data, i * 2);
|
||||
}
|
||||
return data;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Converts Generation 4 Big Endian encoded character data to string.
|
||||
/// </summary>
|
||||
/// <param name="data">Byte array containing encoded character data.</param>
|
||||
/// <param name="offset">Offset to read from</param>
|
||||
/// <param name="count">Length of data to read.</param>
|
||||
/// <returns>Converted string.</returns>
|
||||
public static string GetBEString4(byte[] data, int offset, int count)
|
||||
{
|
||||
var sb = new StringBuilder(count / 2);
|
||||
for (int i = 0; i < count; i += 2)
|
||||
{
|
||||
var val = BigEndian.ToUInt16(data, offset + i);
|
||||
if (val == Terminator)
|
||||
break;
|
||||
var chr = ConvertValue2CharG4(val);
|
||||
if (chr == TerminatorChar)
|
||||
break;
|
||||
sb.Append((char)chr);
|
||||
}
|
||||
StringConverter.SanitizeString(sb);
|
||||
return sb.ToString();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Converts a string to Generation 4 Big Endian encoded character data.
|
||||
/// </summary>
|
||||
/// <param name="value">String to be converted.</param>
|
||||
/// <param name="maxLength">Maximum length of string</param>
|
||||
/// <param name="padTo">Pad the input <see cref="value"/> to given length</param>
|
||||
/// <param name="padWith">Pad the input <see cref="value"/> with this character value</param>
|
||||
/// <returns>Byte array containing encoded character data</returns>
|
||||
public static byte[] SetBEString4(string value, int maxLength, int padTo = 0, ushort padWith = 0)
|
||||
{
|
||||
var sb = new StringBuilder(value);
|
||||
var delta = sb.Length - maxLength;
|
||||
if (delta > 0)
|
||||
sb.Remove(maxLength, delta);
|
||||
|
||||
// Replace Special Characters and add Terminator
|
||||
StringConverter.UnSanitizeString(sb, 4);
|
||||
sb.Append(TerminatorChar);
|
||||
var d2 = padTo - sb.Length;
|
||||
if (d2 > 0)
|
||||
sb.Append((char)padWith, d2);
|
||||
|
||||
var data = new byte[sb.Length * 2];
|
||||
for (int i = 0; i < sb.Length; i++)
|
||||
{
|
||||
var chr = sb[i];
|
||||
var val = ConvertChar2ValueG4(chr);
|
||||
BigEndian.GetBytes(val).CopyTo(data, i * 2);
|
||||
}
|
||||
return data;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Converts Generation 4 Big Endian encoded character data to string, with direct Unicode characters.
|
||||
/// </summary>
|
||||
/// <remarks>Used by the Save File's internal strings.</remarks>
|
||||
/// <param name="data">Byte array containing encoded character data.</param>
|
||||
/// <param name="offset">Offset to read from</param>
|
||||
/// <param name="count">Length of data to read.</param>
|
||||
/// <returns>Converted string.</returns>
|
||||
public static string GetBEString4Unicode(byte[] data, int offset, int count)
|
||||
{
|
||||
// Scan for null terminator
|
||||
for (int i = 0; i < count; i+=2)
|
||||
{
|
||||
if (BitConverter.ToInt16(data, offset + i) != 0)
|
||||
continue;
|
||||
count = i;
|
||||
var value = ReadUInt16LittleEndian(data[i..]);
|
||||
if (value == Terminator)
|
||||
break;
|
||||
}
|
||||
return Encoding.BigEndianUnicode.GetString(data, offset, count);
|
||||
char chr = (char)ConvertValue2CharG4(value);
|
||||
if (chr == TerminatorChar)
|
||||
break;
|
||||
chr = StringConverter.SanitizeChar(chr);
|
||||
result[i/2] = chr;
|
||||
}
|
||||
return i/2;
|
||||
}
|
||||
|
||||
/// <summary>Gets the bytes for a 4th Generation String</summary>
|
||||
/// <param name="destBuffer"></param>
|
||||
/// <param name="value">Decoded string.</param>
|
||||
/// <param name="maxLength">Maximum length of the input <see cref="value"/></param>
|
||||
/// <param name="option"></param>
|
||||
/// <returns>Encoded data.</returns>
|
||||
public static int SetString(Span<byte> destBuffer, ReadOnlySpan<char> value, int maxLength,
|
||||
StringConverterOption option = StringConverterOption.ClearZero)
|
||||
{
|
||||
if (value.Length > maxLength)
|
||||
value = value[..maxLength]; // Hard cap
|
||||
|
||||
if (option is StringConverterOption.ClearZero)
|
||||
destBuffer.Clear();
|
||||
|
||||
for (int i = 0; i < value.Length; i++)
|
||||
{
|
||||
var chr = value[i];
|
||||
chr = StringConverter.UnSanitizeChar5(chr);
|
||||
ushort val = ConvertChar2ValueG4(chr);
|
||||
WriteUInt16LittleEndian(destBuffer[(i * 2)..], val);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Converts a string to Generation 4 Big Endian encoded character data, with direct Unicode characters.
|
||||
/// </summary>
|
||||
/// <remarks>Used by the Save File's internal strings.</remarks>
|
||||
/// <param name="value">String to be converted.</param>
|
||||
/// <param name="maxLength">Maximum length of string</param>
|
||||
/// <param name="padTo">Pad the input <see cref="value"/> to given length</param>
|
||||
/// <param name="padWith">Pad the input <see cref="value"/> with this character value</param>
|
||||
/// <returns>Byte array containing encoded character data</returns>
|
||||
public static byte[] SetBEString4Unicode(string value, int maxLength, int padTo = 0, ushort padWith = 0)
|
||||
{
|
||||
var sb = new StringBuilder(value);
|
||||
var delta = sb.Length - maxLength;
|
||||
if (delta > 0)
|
||||
sb.Remove(maxLength, delta);
|
||||
|
||||
sb.Append((char)0);
|
||||
var d2 = padTo - sb.Length;
|
||||
if (d2 > 0)
|
||||
sb.Append((char)padWith, d2);
|
||||
|
||||
var data = new byte[sb.Length * 2];
|
||||
for (int i = 0; i < sb.Length; i++)
|
||||
{
|
||||
var ofs = i * 2;
|
||||
var c = (ushort)sb[i];
|
||||
data[ofs + 1] = (byte)c;
|
||||
data[ofs] = (byte)(c >> 8);
|
||||
}
|
||||
return data;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Converts a Generation 4 value to Unicode character.
|
||||
/// </summary>
|
||||
/// <param name="val">Encoded value.</param>
|
||||
/// <returns>Decoded value (unicode).</returns>
|
||||
public static ushort ConvertValue2CharG4(ushort val)
|
||||
{
|
||||
return G4ValueId.TryGetValue(val, out int index)
|
||||
? G4Chars[index] : '?';
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Converts a Unicode character to Generation 4 value.
|
||||
/// </summary>
|
||||
/// <param name="chr">Decoded value (unicode).</param>
|
||||
/// <returns>Encoded value.</returns>
|
||||
public static ushort ConvertChar2ValueG4(ushort chr)
|
||||
{
|
||||
return G4CharId.TryGetValue(chr, out int index)
|
||||
? G4Values[index] : (ushort)00428; // '?'
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Strips diacritics on gen1-4 french pkm names
|
||||
/// </summary>
|
||||
/// <param name="input">String to clean</param>
|
||||
/// <returns>Cleaned string</returns>
|
||||
/// <remarks>Only 4 characters are accented in gen1-4</remarks>
|
||||
public static void StripDiacriticsFR4(StringBuilder input)
|
||||
{
|
||||
for (int i = 0; i < input.Length; i++)
|
||||
{
|
||||
if (FrDiacritic.TryGetValue(input[i], out var value))
|
||||
input[i] = value;
|
||||
}
|
||||
}
|
||||
|
||||
private static readonly Dictionary<char, char> FrDiacritic = new(4)
|
||||
{
|
||||
{ 'È', 'E' },
|
||||
{ 'É', 'E' },
|
||||
{ 'Ê', 'E' },
|
||||
{ 'Ï', 'I' },
|
||||
};
|
||||
|
||||
#region Conversion Data
|
||||
|
||||
/// <summary>
|
||||
/// Values (stored value)
|
||||
/// </summary>
|
||||
private static readonly ushort[] G4Values =
|
||||
{
|
||||
00001, 00002, 00003, 00004, 00005, 00006, 00007, 00008, 00009, 00010, 00011, 00012, 00013, 00014, 00015, 00016,
|
||||
00017, 00018, 00019, 00020, 00021, 00022, 00023, 00024, 00025, 00026, 00027, 00028, 00029, 00030, 00031, 00032,
|
||||
00033, 00034, 00035, 00036, 00037, 00038, 00039, 00040, 00041, 00042, 00043, 00044, 00045, 00046, 00047, 00048,
|
||||
00049, 00050, 00051, 00052, 00053, 00054, 00055, 00056, 00057, 00058, 00059, 00060, 00061, 00062, 00063, 00064,
|
||||
00065, 00066, 00067, 00068, 00069, 00070, 00071, 00072, 00073, 00074, 00075, 00076, 00077, 00078, 00079, 00080,
|
||||
00081, 00082, 00083, 00084, 00085, 00086, 00087, 00088, 00089, 00090, 00091, 00092, 00093, 00094, 00095, 00096,
|
||||
00097, 00098, 00099, 00100, 00101, 00102, 00103, 00104, 00105, 00106, 00107, 00108, 00109, 00110, 00111, 00112,
|
||||
00113, 00114, 00115, 00116, 00117, 00118, 00119, 00120, 00121, 00122, 00123, 00124, 00125, 00126, 00127, 00128,
|
||||
00129, 00130, 00131, 00132, 00133, 00134, 00135, 00136, 00137, 00138, 00139, 00140, 00141, 00142, 00143, 00144,
|
||||
00145, 00146, 00147, 00148, 00149, 00150, 00151, 00152, 00153, 00154, 00155, 00156, 00157, 00158, 00159, 00160,
|
||||
00161, 00162, 00163, 00164, 00165, 00166, 00167, 00168, 00169, 00170, 00171, 00172, 00173, 00174, 00175, 00176,
|
||||
00177, 00178, 00179, 00180, 00181, 00182, 00183, 00184, 00185, 00186, 00187, 00188, 00189, 00190, 00191, 00192,
|
||||
00193, 00194, 00195, 00196, 00197, 00198, 00199, 00200, 00201, 00202, 00203, 00204, 00205, 00206, 00207, 00208,
|
||||
00209, 00210, 00211, 00212, 00213, 00214, 00215, 00216, 00217, 00218, 00219, 00220, 00221, 00222, 00223, 00225,
|
||||
00226, 00227, 00228, 00229, 00230, 00231, 00232, 00233, 00234, 00235, 00236, 00237, 00238, 00239, 00240, 00241,
|
||||
00242, 00243, 00244, 00245, 00246, 00247, 00248, 00249, 00250, 00251, 00252, 00253, 00254, 00255, 00256, 00257,
|
||||
00258, 00259, 00260, 00261, 00262, 00263, 00264, 00265, 00266, 00267, 00268, 00269, 00270, 00271, 00272, 00273,
|
||||
00275, 00276, 00277, 00278, 00279, 00280, 00281, 00282, 00283, 00284, 00285, 00286, 00287, 00288, 00289,
|
||||
00290, 00291, 00292, 00293, 00294, 00295, 00296, 00297, 00298, 00299, 00300, 00301, 00302, 00303, 00304, 00305,
|
||||
00306, 00307, 00308, 00309, 00310, 00311, 00312, 00313, 00314, 00315, 00316, 00317, 00318, 00319, 00320, 00321,
|
||||
00322, 00323, 00324, 00325, 00326, 00327, 00328, 00329, 00330, 00331, 00332, 00333, 00334, 00335, 00336, 00337,
|
||||
00338, 00339, 00340, 00341, 00342, 00343, 00344, 00345, 00346, 00347, 00348, 00349, 00350, 00351, 00352, 00353,
|
||||
00354, 00355, 00356, 00357, 00358, 00359, 00360, 00361, 00362, 00363, 00364, 00365, 00366, 00367, 00368, 00369,
|
||||
00370, 00371, 00372, 00373, 00374, 00375, 00376, 00377, 00378, 00379, 00380, 00381, 00382, 00383, 00384, 00385,
|
||||
00386, 00387, 00388, 00389, 00390, 00391, 00392, 00393, 00394, 00395, 00396, 00397, 00398, 00399, 00400, 00401,
|
||||
00402, 00403, 00404, 00405, 00406, 00407, 00408, 00409, 00410, 00411, 00412, 00413, 00414, 00415, 00416, 00417,
|
||||
00418, 00419, 00420, 00421, 00422, 00423, 00424, 00425, 00426, 00427, 00428, 00429, 00430, 00431, 00432, 00433,
|
||||
00434, 00435, 00436, 00437, 00438, 00439, 00440, 00441, 00442, 00443, 00444, 00445, 00446, 00447, 00448, 00449,
|
||||
00450, 00451, 00452, 00453, 00454, 00455, 00456, 00457, 00458, 00459, 00460, 00461, 00462, 00463, 00464, 00465,
|
||||
00466, 00467, 00468, 00469, 00470, 00471, 00472, 00473, 00474, 00475, 00476, 00477, 00478,
|
||||
01025, 01026, 01027, 01028, 01029, 01030, 01031, 01032, 01033, 01034, 01035, 01036, 01037,
|
||||
01038, 01039, 01040, 01041, 01042, 01043, 01044, 01045, 01046, 01047, 01048, 01049, 01050, 01051, 01052, 01053,
|
||||
01054, 01055, 01056, 01057, 01058, 01059, 01060, 01061, 01062, 01063, 01064, 01065, 01066, 01067, 01068, 01069,
|
||||
01070, 01071, 01072, 01073, 01074, 01075, 01076, 01077, 01078, 01079, 01080, 01081, 01082, 01083, 01084, 01085,
|
||||
01086, 01087, 01088, 01089, 01090, 01091, 01092, 01093, 01094, 01095, 01096, 01097, 01098, 01099, 01100, 01101,
|
||||
01102, 01103, 01104, 01105, 01106, 01107, 01108, 01109, 01110, 01111, 01112, 01113, 01114, 01115, 01116, 01117,
|
||||
01118, 01119, 01120, 01121, 01122, 01123, 01124, 01125, 01126, 01127, 01128, 01129, 01130, 01131, 01132, 01133,
|
||||
01134, 01135, 01136, 01137, 01138, 01139, 01140, 01141, 01142, 01143, 01144, 01145, 01146, 01147, 01148, 01149,
|
||||
01150, 01151, 01152, 01153, 01154, 01155, 01156, 01157, 01158, 01159, 01160, 01161, 01162, 01163, 01164, 01165,
|
||||
01166, 01167, 01168, 01169, 01170, 01171, 01172, 01173, 01174, 01175, 01176, 01177, 01178, 01179, 01180, 01181,
|
||||
01182, 01183, 01184, 01185, 01186, 01187, 01188, 01189, 01190, 01191, 01192, 01193, 01194, 01195, 01196, 01197,
|
||||
01198, 01199, 01200, 01201, 01202, 01203, 01204, 01205, 01206, 01207, 01208, 01209, 01210, 01211, 01212, 01213,
|
||||
01214, 01215, 01216, 01217, 01218, 01219, 01220, 01221, 01222, 01223, 01224, 01225, 01226, 01227, 01228, 01229,
|
||||
01230, 01231, 01232, 01233, 01234, 01235, 01236, 01237, 01238, 01239, 01240, 01241, 01242, 01243, 01244, 01245,
|
||||
01246, 01247, 01248, 01249, 01250, 01251, 01252, 01253, 01254, 01255, 01256, 01257, 01258, 01259, 01260, 01261,
|
||||
01262, 01263, 01264, 01265, 01266, 01267, 01268, 01269, 01270, 01271, 01272, 01273, 01274, 01275, 01276, 01277,
|
||||
01278, 01279, 01280, 01281, 01282, 01283, 01284, 01285, 01286, 01287, 01288, 01289, 01290, 01291, 01292, 01293,
|
||||
01294, 01295, 01296, 01297, 01298, 01299, 01300, 01301, 01302, 01303, 01304, 01305, 01306, 01307, 01308, 01309,
|
||||
01310, 01311, 01312, 01313, 01314, 01315, 01316, 01317, 01318, 01319, 01320, 01321, 01322, 01323, 01324, 01325,
|
||||
01326, 01327, 01328, 01329, 01330, 01331, 01332, 01333, 01334, 01335, 01336, 01337, 01338, 01339, 01340, 01341,
|
||||
01342, 01343, 01344, 01345, 01346, 01347, 01348, 01349, 01350, 01351, 01352, 01353, 01354, 01355, 01356, 01357,
|
||||
01358, 01359, 01360, 01361, 01362, 01363, 01364, 01365, 01366, 01367, 01368, 01369, 01370, 01371, 01372, 01373,
|
||||
01374, 01375, 01376, 01377, 01378, 01379, 01380, 01381, 01382, 01383, 01384, 01385, 01386, 01387, 01388, 01389,
|
||||
01390, 01391, 01392, 01393, 01394, 01395, 01396, 01397, 01398, 01399, 01400, 01401, 01402, 01403, 01404, 01405,
|
||||
01406, 01407, 01408, 01409, 01410, 01411, 01412, 01413, 01414, 01415, 01416, 01417, 01418, 01419, 01420, 01421,
|
||||
01422, 01423, 01424, 01425, 01426, 01427, 01428, 01429, 01430, 01431, 01432, 01433, 01434, 01435, 01436, 01437,
|
||||
01438, 01439, 01440, 01441, 01442, 01443, 01444, 01445, 01446, 01447, 01448, 01449, 01450, 01451, 01452, 01453,
|
||||
01454, 01455, 01456, 01457, 01458, 01459, 01460, 01461, 01462, 01463, 01464, 01465, 01466, 01467, 01468, 01469,
|
||||
01470, 01471, 01472, 01473, 01474, 01475, 01476, 01477, 01478, 01479, 01480, 01481, 01482, 01483, 01484, 01485,
|
||||
01486, 01487, 01488, 01489, 01490, 01491, 01492, 01493, 01494, 01495, 01496, 01497, 01498, 01499, 01500, 01501,
|
||||
01502, 01503, 01504, 01505, 01506, 01507, 01508, 01509, 01510, 01511, 01512, 01513, 01514, 01515, 01516, 01517,
|
||||
01518, 01519, 01520, 01521, 01522, 01523, 01524, 01525, 01526, 01527, 01528, 01529, 01530, 01531, 01532, 01533,
|
||||
01534, 01535, 01536, 01537, 01538, 01539, 01540, 01541, 01542, 01543, 01544, 01545, 01546, 01547, 01548, 01549,
|
||||
01550, 01551, 01552, 01553, 01554, 01555, 01556, 01557, 01558, 01559, 01560, 01561, 01562, 01563, 01564, 01565,
|
||||
01566, 01567, 01568, 01569, 01570, 01571, 01572, 01573, 01574, 01575, 01576, 01577, 01578, 01579, 01580, 01581,
|
||||
01582, 01583, 01584, 01585, 01586, 01587, 01588, 01589, 01590, 01591, 01592, 01593, 01594, 01595, 01596, 01597,
|
||||
01598, 01599, 01600, 01601, 01602, 01603, 01604, 01605, 01606, 01607, 01608, 01609, 01610, 01611, 01612, 01613,
|
||||
01614, 01615, 01616, 01617, 01618, 01619, 01620, 01621, 01622, 01623, 01624, 01625, 01626, 01627, 01628, 01629,
|
||||
01630, 01631, 01632, 01633, 01634, 01635, 01636, 01637, 01638, 01639, 01640, 01641, 01642, 01643, 01644, 01645,
|
||||
01646, 01647, 01648, 01649, 01650, 01651, 01652, 01653, 01654, 01655, 01656, 01657, 01658, 01659, 01660, 01661,
|
||||
01662, 01663, 01664, 01665, 01666, 01667, 01668, 01669, 01670, 01671, 01672, 01673, 01674, 01675, 01676, 01677,
|
||||
01678, 01679, 01680, 01681, 01682, 01683, 01684, 01685, 01686, 01687, 01688, 01689, 01690, 01691, 01692, 01693,
|
||||
01694, 01695, 01696, 01697, 01698, 01699, 01700, 01701, 01702, 01703, 01704, 01705, 01706, 01707, 01708, 01709,
|
||||
01710, 01711, 01712, 01713, 01714, 01715, 01716, 01717, 01718, 01719, 01720, 01721, 01722, 01723, 01724, 01725,
|
||||
01726, 01727, 01728, 01729, 01730, 01731, 01732, 01733, 01734, 01735, 01736, 01737, 01738, 01739, 01740, 01741,
|
||||
01742, 01743, 01744, 01745, 01746, 01747, 01748, 01749, 01750, 01751, 01752, 01753, 01754, 01755, 01756, 01757,
|
||||
01758, 01759, 01760, 01761, 01762, 01763, 01764, 01765, 01766, 01767, 01768, 01769, 01770, 01771, 01772, 01773,
|
||||
01774, 01775, 01776, 01777, 01778, 01779, 01780, 01781, 01782, 01783, 01784, 01785, 01786, 01787, 01788, 01789,
|
||||
01790, 01791, 01792, 01793, 01794, 01795, 01796, 01797, 01798, 01799, 01800, 01801, 01802, 01803, 01804, 01805,
|
||||
01806, 01807, 01808, 01809, 01810, 01811, 01812, 01813, 01814, 01815, 01816, 01817, 01818, 01819, 01820, 01821,
|
||||
01822, 01823, 01824, 01825, 01826, 01827, 01828, 01829, 01830, 01831, 01832, 01833, 01834, 01835, 01836, 01837,
|
||||
01838, 01839, 01840, 01841, 01842, 01843, 01844, 01845, 01846, 01847, 01848, 01849, 01850, 01851, 01852, 01853,
|
||||
01854, 01855, 01856, 01857, 01858, 01859, 01860, 01861, 01862, 01863, 01864, 01865, 01866, 01867, 01868, 01869,
|
||||
01870, 01871, 01872, 01873, 01874, 01875, 01876, 01877, 01878, 01879, 01880, 01881, 01882, 01883, 01884, 01885,
|
||||
01886, 01887, 01888, 01889, 01890, 01891, 01892, 01893, 01894, 01895, 01896, 01897, 01898, 01899, 01900, 01901,
|
||||
01902, 01903, 01904, 01905, 01906, 01907, 01908, 01909, 01910, 01911, 01912, 01913, 01914, 01915, 01916, 01917,
|
||||
01918, 01919, 01920, 01921, 01922, 01923, 01924, 01925, 01926, 01927, 01928, 01929, 01930, 01931, 01932, 01933,
|
||||
01934, 01935, 01936, 01937, 01938, 01939, 01940, 01941, 01942, 01943, 01944, 01945, 01946, 01947, 01948, 01949,
|
||||
01950, 01951, 01952, 01953, 01954, 01955, 01956, 01957, 01958, 01959, 01960, 01961, 01962, 01963, 01964, 01965,
|
||||
01966, 01967, 01968, 01969, 01970, 01971, 01972, 01973, 01974, 01975, 01976, 01977, 01978, 01979, 01980, 01981,
|
||||
01982, 01983, 01984, 01985, 01986, 01987, 01988, 01989, 01990, 01991, 01992, 01993, 01994, 01995, 01996, 01997,
|
||||
01998, 01999, 02000, 02001, 02002, 02003, 02004, 02005, 02006, 02007, 02008, 02009, 02010, 02011, 02012, 02013,
|
||||
02014, 02015, 02016, 02017, 02018, 02019, 02020, 02021, 02022, 02023, 02024, 02025, 02026, 02027, 02028, 02029,
|
||||
02030, 02031, 02032, 02033, 02034, 02035, 02036, 02037, 02038, 02039, 02040, 02041, 02042, 02043, 02044, 02045,
|
||||
02046, 02047, 02048, 02049, 02050, 02051, 02052, 02053, 02054, 02055, 02056, 02057, 02058, 02059, 02060, 02061,
|
||||
02062, 02063, 02064, 02065, 02066, 02067, 02068, 02069, 02070, 02071, 02072, 02073, 02074, 02075, 02076, 02077,
|
||||
02078, 02079, 02080, 02081, 02082, 02083, 02084, 02085, 02086, 02087, 02088, 02089, 02090, 02091, 02092, 02093,
|
||||
02094, 02095, 02096, 02097, 02098, 02099, 02100, 02101, 02102, 02103, 02104, 02105, 02106, 02107, 02108, 02109,
|
||||
02110, 02111, 02112, 02113, 02114, 02115, 02116, 02117, 02118, 02119, 02120, 02121, 02122, 02123, 02124, 02125,
|
||||
02126, 02127, 02128, 02129, 02130, 02131, 02132, 02133, 02134, 02135, 02136, 02137, 02138, 02139, 02140, 02141,
|
||||
02142, 02143, 02144, 02145, 02146, 02147, 02148, 02149, 02150, 02151, 02152, 02153, 02154, 02155, 02156, 02157,
|
||||
02158, 02159, 02160, 02161, 02162, 02163, 02164, 02165, 02166, 02167, 02168, 02169, 02170, 02171, 02172, 02173,
|
||||
02174, 02175, 02176, 02177, 02178, 02179, 02180, 02181, 02182, 02183, 02184, 02185, 02186, 02187, 02188, 02189,
|
||||
02190, 02191, 02192, 02193, 02194, 02195, 02196, 02197, 02198, 02199, 02200, 02201, 02202, 02203, 02204, 02205,
|
||||
02206, 02207, 02208, 02209, 02210, 02211, 02212, 02213, 02214, 02215, 02216, 02217, 02218, 02219, 02220, 02221,
|
||||
02222, 02223, 02224, 02225, 02226, 02227, 02228, 02229, 02230, 02231, 02232, 02233, 02234, 02235, 02236, 02237,
|
||||
02238, 02239, 02240, 02241, 02242, 02243, 02244, 02245, 02246, 02247, 02248, 02249, 02250, 02251, 02252, 02253,
|
||||
02254, 02255, 02256, 02257, 02258, 02259, 02260, 02261, 02262, 02263, 02264, 02265, 02266, 02267, 02268, 02269,
|
||||
02270, 02271, 02272, 02273, 02274, 02275, 02276, 02277, 02278, 02279, 02280, 02281, 02282, 02283, 02284, 02285,
|
||||
02286, 02287, 02288, 02289, 02290, 02291, 02292, 02293, 02294, 02295, 02296, 02297, 02298, 02299, 02300, 02301,
|
||||
02302, 02303, 02304, 02305, 02306, 02307, 02308, 02309, 02310, 02311, 02312, 02313, 02314, 02315, 02316, 02317,
|
||||
02318, 02319, 02320, 02321, 02322, 02323, 02324, 02325, 02326, 02327, 02328, 02329, 02330, 02331, 02332, 02333,
|
||||
02334, 02335, 02336, 02337, 02338, 02339, 02340, 02341, 02342, 02343, 02344, 02345, 02346, 02347, 02348, 02349,
|
||||
02350, 02351, 02352, 02353, 02354, 02355, 02356, 02357, 02358, 02359, 02360, 02361, 02362, 02363, 02364, 02365,
|
||||
02366, 02367, 02368, 02369, 02370, 02371, 02372, 02373, 02374, 02375, 02376, 02377, 02378, 02379, 02380, 02381,
|
||||
02382, 02383, 02384, 02385, 02386, 02387, 02388, 02389, 02390, 02391, 02392, 02393, 02394, 02395, 02396, 02397,
|
||||
02398, 02399, 02400, 02401, 02402, 02403, 02404, 02405, 02406, 02407, 02408, 02409, 02410, 02411, 02412, 02413,
|
||||
02414, 02415, 02416, 02417, 02418, 02419, 02420, 02421, 02422, 02423, 02424, 02425, 02426, 02427, 02428, 02429,
|
||||
02430, 02431, 02432, 02433, 02434, 02435, 02436, 02437, 02438, 02439, 02440, 02441, 02442, 02443, 02444, 02445,
|
||||
02446, 02447, 02448, 02449, 02450, 02451, 02452, 02453, 02454, 02455, 02456, 02457, 02458, 02459, 02460, 02461,
|
||||
02462, 02463, 02464, 02465, 02466, 02467, 02468, 02469, 02470, 02471, 02472, 02473, 02474, 02475, 02476, 02477,
|
||||
02478, 02479, 02480, 02481, 02482, 02483, 02484, 02485, 02486, 02487, 02488, 02489, 02490, 02491, 02492, 02493,
|
||||
02494, 02495, 02496, 02497, 02498, 02499, 02500, 02501, 02502, 02503, 02504, 02505, 02506, 02507, 02508, 02509,
|
||||
02510, 02511, 02512, 02513, 02514, 02515, 02516, 02517, 02518, 02519, 02520, 02521, 02522, 02523, 02524, 02525,
|
||||
02526, 02527, 02528, 02529, 02530, 02531, 02532, 02533, 02534, 02535, 02536, 02537, 02538, 02539, 02540, 02541,
|
||||
02542, 02543, 02544, 02545, 02546, 02547, 02548, 02549, 02550, 02551, 02552, 02553, 02554, 02555, 02556, 02557,
|
||||
02558, 02559, 02560, 02561, 02562, 02563, 02564, 02565, 02566, 02567, 02568, 02569, 02570, 02571, 02572, 02573,
|
||||
02574, 02575, 02576, 02577, 02578, 02579, 02580, 02581, 02582, 02583, 02584, 02585, 02586, 02587, 02588, 02589,
|
||||
02590, 02591, 02592, 02593, 02594, 02595, 02596, 02597, 02598, 02599, 02600, 02601, 02602, 02603, 02604, 02605,
|
||||
02606, 02607, 02608, 02609, 02610, 02611, 02612, 02613, 02614, 02615, 02616, 02617, 02618, 02619, 02620, 02621,
|
||||
02622, 02623, 02624, 02625, 02626, 02627, 02628, 02629, 02630, 02631, 02632, 02633, 02634, 02635, 02636, 02637,
|
||||
02638, 02639, 02640, 02641, 02642, 02643, 02644, 02645, 02646, 02647, 02648, 02649, 02650, 02651, 02652, 02653,
|
||||
02654, 02655, 02656, 02657, 02658, 02659, 02660, 02661, 02662, 02663, 02664, 02665, 02666, 02667, 02668, 02669,
|
||||
02670, 02671, 02672, 02673, 02674, 02675, 02676, 02677, 02678, 02679, 02680, 02681, 02682, 02683, 02684, 02685,
|
||||
02686, 02687, 02688, 02689, 02690, 02691, 02692, 02693, 02694, 02695, 02696, 02697, 02698, 02699, 02700, 02701,
|
||||
02702, 02703, 02704, 02705, 02706, 02707, 02708, 02709, 02710, 02711, 02712, 02713, 02714, 02715, 02716, 02717,
|
||||
02718, 02719, 02720, 02721, 02722, 02723, 02724, 02725, 02726, 02727, 02728, 02729, 02730, 02731, 02732, 02733,
|
||||
02734, 02735, 02736, 02737, 02738, 02739, 02740, 02741, 02742, 02743, 02744, 02745, 02746, 02747, 02748, 02749,
|
||||
02750, 02751, 02752, 02753, 02754, 02755, 02756, 02757, 02758, 02759, 02760, 02761, 02762, 02763, 02764, 02765,
|
||||
02766, 02767, 02768, 02769, 02770, 02771, 02772, 02773, 02774, 02775, 02776, 02777, 02778, 02779, 02780, 02781,
|
||||
02782, 02783, 02784, 02785, 02786, 02787, 02788, 02789, 02790, 02791, 02792, 02793, 02794, 02795, 02796, 02797,
|
||||
02798, 02799, 02800, 02801, 02802, 02803, 02804, 02805, 02806, 02807, 02808, 02809, 02810, 02811, 02812, 02813,
|
||||
02814, 02815, 02816, 02817, 02818, 02819, 02820, 02821, 02822, 02823, 02824, 02825, 02826, 02827, 02828, 02829,
|
||||
02830, 02831, 02832, 02833, 02834, 02835, 02836, 02837, 02838, 02839, 02840, 02841, 02842, 02843, 02844, 02845,
|
||||
02846, 02847, 02848, 02849, 02850, 02851, 02852, 02853, 02854, 02855, 02856, 02857, 02858, 02859, 02860, 02861,
|
||||
02862, 02863, 02864, 02865, 02866, 02867, 02868, 02869, 02870, 02871, 02872, 02873, 02874, 02875, 02876, 02877,
|
||||
02878, 02879, 02880, 02881, 02882, 02883, 02884, 02885, 02886, 02887, 02888, 02889, 02890, 02891, 02892, 02893,
|
||||
02894, 02895, 02896, 02897, 02898, 02899, 02900, 02901, 02902, 02903, 02904, 02905, 02906, 02907, 02908, 02909,
|
||||
02910, 02911, 02912, 02913, 02914, 02915, 02916, 02917, 02918, 02919, 02920, 02921, 02922, 02923, 02924, 02925,
|
||||
02926, 02927, 02928, 02929, 02930, 02931, 02932, 02933, 02934, 02935, 02936, 02937, 02938, 02939, 02940, 02941,
|
||||
02942, 02943, 02944, 02945, 02946, 02947, 02948, 02949, 02950, 02951, 02952, 02953, 02954, 02955, 02956, 02957,
|
||||
02958, 02959, 02960, 02961, 02962, 02963, 02964, 02965, 02966, 02967, 02968, 02969, 02970, 02971, 02972, 02973,
|
||||
02974, 02975, 02976, 02977, 02978, 02979, 02980, 02981, 02982, 02983, 02984, 02985, 02986, 02987, 02988, 02989,
|
||||
02990, 02991, 02992, 02993, 02994, 02995, 02996, 02997, 02998, 02999, 03000, 03001, 03002, 03003, 03004, 03005,
|
||||
03006, 03007, 03008, 03009, 03010, 03011, 03012, 03013, 03014, 03015, 03016, 03017, 03018, 03019, 03020, 03021,
|
||||
03022, 03023, 03024, 03025, 03026, 03027, 03028, 03029, 03030, 03031, 03032, 03033, 03034, 03035, 03036, 03037,
|
||||
03038, 03039, 03040, 03041, 03042, 03043, 03044, 03045, 03046, 03047, 03048, 03049, 03050, 03051, 03052, 03053,
|
||||
03054, 03055, 03056, 03057, 03058, 03059, 03060, 03061, 03062, 03063, 03064, 03065, 03066, 03067, 03068, 03069,
|
||||
03070, 03071, 03072, 03073, 03074, 03075, 03076, 03077, 03078, 03079, 03080, 03081, 03082, 03083, 03084, 03085,
|
||||
03086, 03087, 03088, 03089, 03090, 03091, 03092, 03093, 03094, 03095, 03096, 03097, 03098, 03099, 03100, 03101,
|
||||
03102, 03103, 03104, 03105, 03106, 03107, 03108, 03109, 03110, 03111, 03112, 03113, 03114, 03115, 03116, 03117,
|
||||
03118, 03119, 03120, 03121, 03122, 03123, 03124, 03125, 03126, 03127, 03128, 03129, 03130, 03131, 03132, 03133,
|
||||
03134, 03135, 03136, 03137, 03138, 03139, 03140, 03141, 03142, 03143, 03144, 03145, 03146, 03147, 03148, 03149,
|
||||
03150, 03151, 03152, 03153, 03154, 03155, 03156, 03157, 03158, 03159, 03160, 03161, 03162, 03163, 03164, 03165,
|
||||
03166, 03167, 03168, 03169, 03170, 03171, 03172, 03173, 03174, 03175, 03176, 03177, 03178, 03179, 03180, 03181,
|
||||
03182, 03183, 03184, 03185, 03186, 03187, 03188, 03189, 03190, 03191, 03192, 03193, 03194, 03195, 03196, 03197,
|
||||
03198, 03199, 03200, 03201, 03202, 03203, 03204, 03205, 03206, 03207, 03208, 03209, 03210, 03211, 03212, 03213,
|
||||
03214, 03215, 03216, 03217, 03218, 03219, 03220, 03221, 03222, 03223, 03224, 03225, 03226, 03227, 03228, 03229,
|
||||
03230, 03231, 03232, 03233, 03234, 03235, 03236, 03237, 03238, 03239, 03240, 03241, 03242, 03243, 03244, 03245,
|
||||
03246, 03247, 03248, 03249, 03250, 03251, 03252, 03253, 03254, 03255, 03256, 03257, 03258, 03259, 03260, 03261,
|
||||
03262, 03263, 03264, 03265, 03266, 03267, 03268, 03269, 03270, 03271, 03272, 03273, 03274, 03275, 03276, 03277,
|
||||
03278, 03279, 03280, 03281, 03282, 03283, 03284, 03285, 03286, 03287, 03288, 03289, 03290, 03291, 03292, 03293,
|
||||
03294, 03295, 03296, 03297, 03298, 03299, 03300, 03301, 03302, 03303, 03304, 03305, 03306, 03307, 03308, 03309,
|
||||
03310, 03311, 03312, 03313, 03314, 03315, 03316, 03317, 03318, 03319, 03320, 03321, 03322, 03323, 03324, 03325,
|
||||
03326, 03327, 03328, 03329, 03330, 03331, 03332, 03333, 03334, 03335, 03336, 03337, 03338, 03339, 03340, 03341,
|
||||
03342, 03343, 03344, 03345, 03346, 03347, 03348, 03349, 03350, 03351, 03352, 03353, 03354, 03355, 03356, 03357,
|
||||
03358, 03359, 03360, 03361, 03362, 03363, 03364, 03365, 03366, 03367, 03368, 03369, 03370, 03371, 03372, 03373,
|
||||
03374, 03377, 03378, 03379, 03380, 03381, 03382, 03383, 03384, 03385, 03386, 03387, 03388, 03389, 03390, 03391,
|
||||
03392, 03393, 03394, 03395, 03396, 03397, 03398, 03399, 03400, 03401, 03402, 03403, 03404, 03405, 03406, 03407,
|
||||
03408, 03409, 03425, 03426, 03427, 03428, 03429, 65535,
|
||||
};
|
||||
|
||||
/// <summary>
|
||||
/// Characters (Unicode representation)
|
||||
/// </summary>
|
||||
private static readonly ushort[] G4Chars =
|
||||
{
|
||||
12288, 12353, 12354, 12355, 12356, 12357, 12358, 12359, 12360, 12361, 12362, 12363, 12364, 12365, 12366, 12367,
|
||||
12368, 12369, 12370, 12371, 12372, 12373, 12374, 12375, 12376, 12377, 12378, 12379, 12380, 12381, 12382, 12383,
|
||||
12384, 12385, 12386, 12387, 12388, 12389, 12390, 12391, 12392, 12393, 12394, 12395, 12396, 12397, 12398, 12399,
|
||||
12400, 12401, 12402, 12403, 12404, 12405, 12406, 12407, 12408, 12409, 12410, 12411, 12412, 12413, 12414, 12415,
|
||||
12416, 12417, 12418, 12419, 12420, 12421, 12422, 12423, 12424, 12425, 12426, 12427, 12428, 12429, 12431, 12434,
|
||||
12435, 12449, 12450, 12451, 12452, 12453, 12454, 12455, 12456, 12457, 12458, 12459, 12460, 12461, 12462, 12463,
|
||||
12464, 12465, 12466, 12467, 12468, 12469, 12470, 12471, 12472, 12473, 12474, 12475, 12476, 12477, 12478, 12479,
|
||||
12480, 12481, 12482, 12483, 12484, 12485, 12486, 12487, 12488, 12489, 12490, 12491, 12492, 12493, 12494, 12495,
|
||||
12496, 12497, 12498, 12499, 12500, 12501, 12502, 12503, 12504, 12505, 12506, 12507, 12508, 12509, 12510, 12511,
|
||||
12512, 12513, 12514, 12515, 12516, 12517, 12518, 12519, 12520, 12521, 12522, 12523, 12524, 12525, 12527, 12530,
|
||||
12531, 65296, 65297, 65298, 65299, 65300, 65301, 65302, 65303, 65304, 65305, 65313, 65314, 65315, 65316, 65317,
|
||||
65318, 65319, 65320, 65321, 65322, 65323, 65324, 65325, 65326, 65327, 65328, 65329, 65330, 65331, 65332, 65333,
|
||||
65334, 65335, 65336, 65337, 65338, 65345, 65346, 65347, 65348, 65349, 65350, 65351, 65352, 65353, 65354, 65355,
|
||||
65356, 65357, 65358, 65359, 65360, 65361, 65362, 65363, 65364, 65365, 65366, 65367, 65368, 65369, 65370, 65281,
|
||||
65311, 12289, 12290, 08943, 12539, 65295, 12300, 12301, 12302, 12303, 65288, 65289, 09325, 09326, 65291, 12540,
|
||||
09319, 09320, 65309, 65374, 65306, 65307, 65294, 65292, 09824, 09827, 09829, 09830, 09733, 09678, 09675, 09633,
|
||||
09651, 09671, 65312, 09834, 65285, 09728, 09729, 09730, 09731, 09312, 09313, 09314, 09738, 09316, 09317, 09318,
|
||||
09800, 09801, 09802, 09803, 09804, 09805, 09806, 09807, 08592, 08593, 08595, 08594, 08227, 65286, 00048,
|
||||
00049, 00050, 00051, 00052, 00053, 00054, 00055, 00056, 00057, 00065, 00066, 00067, 00068, 00069, 00070, 00071,
|
||||
00072, 00073, 00074, 00075, 00076, 00077, 00078, 00079, 00080, 00081, 00082, 00083, 00084, 00085, 00086, 00087,
|
||||
00088, 00089, 00090, 00097, 00098, 00099, 00100, 00101, 00102, 00103, 00104, 00105, 00106, 00107, 00108, 00109,
|
||||
00110, 00111, 00112, 00113, 00114, 00115, 00116, 00117, 00118, 00119, 00120, 00121, 00122, 00192, 00193, 00194,
|
||||
00195, 00196, 00197, 00198, 00199, 00200, 00201, 00202, 00203, 00204, 00205, 00206, 00207, 00208, 00209, 00210,
|
||||
00211, 00212, 00213, 00214, 00215, 00216, 00217, 00218, 00219, 00220, 00221, 00222, 00223, 00224, 00225, 00226,
|
||||
00227, 00228, 00229, 00230, 00231, 00232, 00233, 00234, 00235, 00236, 00237, 00238, 00239, 00240, 00241, 00242,
|
||||
00243, 00244, 00245, 00246, 00247, 00248, 00249, 00250, 00251, 00252, 00253, 00254, 00255, 00338, 00339, 00350,
|
||||
00351, 00170, 00186, 00185, 00178, 00179, 00036, 00161, 00191, 00033, 00063, 00044, 00046, 09324, 65381, 00047,
|
||||
08216, 08217, 08220, 08221, 08222, 12298, 12299, 00040, 00041, 09794, 09792, 00043, 00045, 00042, 00035, 00061,
|
||||
00038, 00126, 00058, 00059, 09327, 09328, 09329, 09330, 09331, 09332, 09333, 09334, 09335, 09336, 00064, 09337,
|
||||
00037, 09338, 09339, 09340, 09341, 09342, 09343, 09344, 09345, 09346, 09347, 09348, 00032,
|
||||
44032, 44033, 44036, 44039, 44040, 44041, 44042, 44048, 44049, 44050, 44051, 44052, 44053,
|
||||
44054, 44055, 44057, 44058, 44059, 44060, 44061, 44064, 44068, 44076, 44077, 44079, 44080, 44081, 44088, 44089,
|
||||
44092, 44096, 44107, 44109, 44116, 44120, 44124, 44144, 44145, 44148, 44151, 44152, 44154, 44160, 44161, 44163,
|
||||
44164, 44165, 44166, 44169, 44170, 44171, 44172, 44176, 44180, 44188, 44189, 44191, 44192, 44193, 44200, 44201,
|
||||
44202, 44204, 44207, 44208, 44216, 44217, 44219, 44220, 44221, 44225, 44228, 44232, 44236, 44245, 44247, 44256,
|
||||
44257, 44260, 44263, 44264, 44266, 44268, 44271, 44272, 44273, 44275, 44277, 44278, 44284, 44285, 44288, 44292,
|
||||
44294, 44300, 44301, 44303, 44305, 44312, 44316, 44320, 44329, 44332, 44333, 44340, 44341, 44344, 44348, 44356,
|
||||
44357, 44359, 44361, 44368, 44372, 44376, 44385, 44387, 44396, 44397, 44400, 44403, 44404, 44405, 44406, 44411,
|
||||
44412, 44413, 44415, 44417, 44418, 44424, 44425, 44428, 44432, 44444, 44445, 44452, 44471, 44480, 44481, 44484,
|
||||
44488, 44496, 44497, 44499, 44508, 44512, 44516, 44536, 44537, 44540, 44543, 44544, 44545, 44552, 44553, 44555,
|
||||
44557, 44564, 44592, 44593, 44596, 44599, 44600, 44602, 44608, 44609, 44611, 44613, 44614, 44618, 44620, 44621,
|
||||
44622, 44624, 44628, 44630, 44636, 44637, 44639, 44640, 44641, 44645, 44648, 44649, 44652, 44656, 44664, 44665,
|
||||
44667, 44668, 44669, 44676, 44677, 44684, 44732, 44733, 44734, 44736, 44740, 44748, 44749, 44751, 44752, 44753,
|
||||
44760, 44761, 44764, 44776, 44779, 44781, 44788, 44792, 44796, 44807, 44808, 44813, 44816, 44844, 44845, 44848,
|
||||
44850, 44852, 44860, 44861, 44863, 44865, 44866, 44867, 44872, 44873, 44880, 44892, 44893, 44900, 44901, 44921,
|
||||
44928, 44932, 44936, 44944, 44945, 44949, 44956, 44984, 44985, 44988, 44992, 44999, 45000, 45001, 45003, 45005,
|
||||
45006, 45012, 45020, 45032, 45033, 45040, 45041, 45044, 45048, 45056, 45057, 45060, 45068, 45072, 45076, 45084,
|
||||
45085, 45096, 45124, 45125, 45128, 45130, 45132, 45134, 45139, 45140, 45141, 45143, 45145, 45149, 45180, 45181,
|
||||
45184, 45188, 45196, 45197, 45199, 45201, 45208, 45209, 45210, 45212, 45215, 45216, 45217, 45218, 45224, 45225,
|
||||
45227, 45228, 45229, 45230, 45231, 45233, 45235, 45236, 45237, 45240, 45244, 45252, 45253, 45255, 45256, 45257,
|
||||
45264, 45265, 45268, 45272, 45280, 45285, 45320, 45321, 45323, 45324, 45328, 45330, 45331, 45336, 45337, 45339,
|
||||
45340, 45341, 45347, 45348, 45349, 45352, 45356, 45364, 45365, 45367, 45368, 45369, 45376, 45377, 45380, 45384,
|
||||
45392, 45393, 45396, 45397, 45400, 45404, 45408, 45432, 45433, 45436, 45440, 45442, 45448, 45449, 45451, 45453,
|
||||
45458, 45459, 45460, 45464, 45468, 45480, 45516, 45520, 45524, 45532, 45533, 45535, 45544, 45545, 45548, 45552,
|
||||
45561, 45563, 45565, 45572, 45573, 45576, 45579, 45580, 45588, 45589, 45591, 45593, 45600, 45620, 45628, 45656,
|
||||
45660, 45664, 45672, 45673, 45684, 45685, 45692, 45700, 45701, 45705, 45712, 45713, 45716, 45720, 45721, 45722,
|
||||
45728, 45729, 45731, 45733, 45734, 45738, 45740, 45744, 45748, 45768, 45769, 45772, 45776, 45778, 45784, 45785,
|
||||
45787, 45789, 45794, 45796, 45797, 45798, 45800, 45803, 45804, 45805, 45806, 45807, 45811, 45812, 45813, 45815,
|
||||
45816, 45817, 45818, 45819, 45823, 45824, 45825, 45828, 45832, 45840, 45841, 45843, 45844, 45845, 45852, 45908,
|
||||
45909, 45910, 45912, 45915, 45916, 45918, 45919, 45924, 45925, 45927, 45929, 45931, 45934, 45936, 45937, 45940,
|
||||
45944, 45952, 45953, 45955, 45956, 45957, 45964, 45968, 45972, 45984, 45985, 45992, 45996, 46020, 46021, 46024,
|
||||
46027, 46028, 46030, 46032, 46036, 46037, 46039, 46041, 46043, 46045, 46048, 46052, 46056, 46076, 46096, 46104,
|
||||
46108, 46112, 46120, 46121, 46123, 46132, 46160, 46161, 46164, 46168, 46176, 46177, 46179, 46181, 46188, 46208,
|
||||
46216, 46237, 46244, 46248, 46252, 46261, 46263, 46265, 46272, 46276, 46280, 46288, 46293, 46300, 46301, 46304,
|
||||
46307, 46308, 46310, 46316, 46317, 46319, 46321, 46328, 46356, 46357, 46360, 46363, 46364, 46372, 46373, 46375,
|
||||
46376, 46377, 46378, 46384, 46385, 46388, 46392, 46400, 46401, 46403, 46404, 46405, 46411, 46412, 46413, 46416,
|
||||
46420, 46428, 46429, 46431, 46432, 46433, 46496, 46497, 46500, 46504, 46506, 46507, 46512, 46513, 46515, 46516,
|
||||
46517, 46523, 46524, 46525, 46528, 46532, 46540, 46541, 46543, 46544, 46545, 46552, 46572, 46608, 46609, 46612,
|
||||
46616, 46629, 46636, 46644, 46664, 46692, 46696, 46748, 46749, 46752, 46756, 46763, 46764, 46769, 46804, 46832,
|
||||
46836, 46840, 46848, 46849, 46853, 46888, 46889, 46892, 46895, 46896, 46904, 46905, 46907, 46916, 46920, 46924,
|
||||
46932, 46933, 46944, 46948, 46952, 46960, 46961, 46963, 46965, 46972, 46973, 46976, 46980, 46988, 46989, 46991,
|
||||
46992, 46993, 46994, 46998, 46999, 47000, 47001, 47004, 47008, 47016, 47017, 47019, 47020, 47021, 47028, 47029,
|
||||
47032, 47047, 47049, 47084, 47085, 47088, 47092, 47100, 47101, 47103, 47104, 47105, 47111, 47112, 47113, 47116,
|
||||
47120, 47128, 47129, 47131, 47133, 47140, 47141, 47144, 47148, 47156, 47157, 47159, 47160, 47161, 47168, 47172,
|
||||
47185, 47187, 47196, 47197, 47200, 47204, 47212, 47213, 47215, 47217, 47224, 47228, 47245, 47272, 47280, 47284,
|
||||
47288, 47296, 47297, 47299, 47301, 47308, 47312, 47316, 47325, 47327, 47329, 47336, 47337, 47340, 47344, 47352,
|
||||
47353, 47355, 47357, 47364, 47384, 47392, 47420, 47421, 47424, 47428, 47436, 47439, 47441, 47448, 47449, 47452,
|
||||
47456, 47464, 47465, 47467, 47469, 47476, 47477, 47480, 47484, 47492, 47493, 47495, 47497, 47498, 47501, 47502,
|
||||
47532, 47533, 47536, 47540, 47548, 47549, 47551, 47553, 47560, 47561, 47564, 47566, 47567, 47568, 47569, 47570,
|
||||
47576, 47577, 47579, 47581, 47582, 47585, 47587, 47588, 47589, 47592, 47596, 47604, 47605, 47607, 47608, 47609,
|
||||
47610, 47616, 47617, 47624, 47637, 47672, 47673, 47676, 47680, 47682, 47688, 47689, 47691, 47693, 47694, 47699,
|
||||
47700, 47701, 47704, 47708, 47716, 47717, 47719, 47720, 47721, 47728, 47729, 47732, 47736, 47747, 47748, 47749,
|
||||
47751, 47756, 47784, 47785, 47787, 47788, 47792, 47794, 47800, 47801, 47803, 47805, 47812, 47816, 47832, 47833,
|
||||
47868, 47872, 47876, 47885, 47887, 47889, 47896, 47900, 47904, 47913, 47915, 47924, 47925, 47926, 47928, 47931,
|
||||
47932, 47933, 47934, 47940, 47941, 47943, 47945, 47949, 47951, 47952, 47956, 47960, 47969, 47971, 47980, 48008,
|
||||
48012, 48016, 48036, 48040, 48044, 48052, 48055, 48064, 48068, 48072, 48080, 48083, 48120, 48121, 48124, 48127,
|
||||
48128, 48130, 48136, 48137, 48139, 48140, 48141, 48143, 48145, 48148, 48149, 48150, 48151, 48152, 48155, 48156,
|
||||
48157, 48158, 48159, 48164, 48165, 48167, 48169, 48173, 48176, 48177, 48180, 48184, 48192, 48193, 48195, 48196,
|
||||
48197, 48201, 48204, 48205, 48208, 48221, 48260, 48261, 48264, 48267, 48268, 48270, 48276, 48277, 48279, 48281,
|
||||
48282, 48288, 48289, 48292, 48295, 48296, 48304, 48305, 48307, 48308, 48309, 48316, 48317, 48320, 48324, 48333,
|
||||
48335, 48336, 48337, 48341, 48344, 48348, 48372, 48373, 48374, 48376, 48380, 48388, 48389, 48391, 48393, 48400,
|
||||
48404, 48420, 48428, 48448, 48456, 48457, 48460, 48464, 48472, 48473, 48484, 48488, 48512, 48513, 48516, 48519,
|
||||
48520, 48521, 48522, 48528, 48529, 48531, 48533, 48537, 48538, 48540, 48548, 48560, 48568, 48596, 48597, 48600,
|
||||
48604, 48617, 48624, 48628, 48632, 48640, 48643, 48645, 48652, 48653, 48656, 48660, 48668, 48669, 48671, 48708,
|
||||
48709, 48712, 48716, 48718, 48724, 48725, 48727, 48729, 48730, 48731, 48736, 48737, 48740, 48744, 48746, 48752,
|
||||
48753, 48755, 48756, 48757, 48763, 48764, 48765, 48768, 48772, 48780, 48781, 48783, 48784, 48785, 48792, 48793,
|
||||
48808, 48848, 48849, 48852, 48855, 48856, 48864, 48867, 48868, 48869, 48876, 48897, 48904, 48905, 48920, 48921,
|
||||
48923, 48924, 48925, 48960, 48961, 48964, 48968, 48976, 48977, 48981, 49044, 49072, 49093, 49100, 49101, 49104,
|
||||
49108, 49116, 49119, 49121, 49212, 49233, 49240, 49244, 49248, 49256, 49257, 49296, 49297, 49300, 49304, 49312,
|
||||
49313, 49315, 49317, 49324, 49325, 49327, 49328, 49331, 49332, 49333, 49334, 49340, 49341, 49343, 49344, 49345,
|
||||
49349, 49352, 49353, 49356, 49360, 49368, 49369, 49371, 49372, 49373, 49380, 49381, 49384, 49388, 49396, 49397,
|
||||
49399, 49401, 49408, 49412, 49416, 49424, 49429, 49436, 49437, 49438, 49439, 49440, 49443, 49444, 49446, 49447,
|
||||
49452, 49453, 49455, 49456, 49457, 49462, 49464, 49465, 49468, 49472, 49480, 49481, 49483, 49484, 49485, 49492,
|
||||
49493, 49496, 49500, 49508, 49509, 49511, 49512, 49513, 49520, 49524, 49528, 49541, 49548, 49549, 49550, 49552,
|
||||
49556, 49558, 49564, 49565, 49567, 49569, 49573, 49576, 49577, 49580, 49584, 49597, 49604, 49608, 49612, 49620,
|
||||
49623, 49624, 49632, 49636, 49640, 49648, 49649, 49651, 49660, 49661, 49664, 49668, 49676, 49677, 49679, 49681,
|
||||
49688, 49689, 49692, 49695, 49696, 49704, 49705, 49707, 49709, 49711, 49713, 49714, 49716, 49736, 49744, 49745,
|
||||
49748, 49752, 49760, 49765, 49772, 49773, 49776, 49780, 49788, 49789, 49791, 49793, 49800, 49801, 49808, 49816,
|
||||
49819, 49821, 49828, 49829, 49832, 49836, 49837, 49844, 49845, 49847, 49849, 49884, 49885, 49888, 49891, 49892,
|
||||
49899, 49900, 49901, 49903, 49905, 49910, 49912, 49913, 49915, 49916, 49920, 49928, 49929, 49932, 49933, 49939,
|
||||
49940, 49941, 49944, 49948, 49956, 49957, 49960, 49961, 49989, 50024, 50025, 50028, 50032, 50034, 50040, 50041,
|
||||
50044, 50045, 50052, 50056, 50060, 50112, 50136, 50137, 50140, 50143, 50144, 50146, 50152, 50153, 50157, 50164,
|
||||
50165, 50168, 50184, 50192, 50212, 50220, 50224, 50228, 50236, 50237, 50248, 50276, 50277, 50280, 50284, 50292,
|
||||
50293, 50297, 50304, 50324, 50332, 50360, 50364, 50409, 50416, 50417, 50420, 50424, 50426, 50431, 50432, 50433,
|
||||
50444, 50448, 50452, 50460, 50472, 50473, 50476, 50480, 50488, 50489, 50491, 50493, 50500, 50501, 50504, 50505,
|
||||
50506, 50508, 50509, 50510, 50515, 50516, 50517, 50519, 50520, 50521, 50525, 50526, 50528, 50529, 50532, 50536,
|
||||
50544, 50545, 50547, 50548, 50549, 50556, 50557, 50560, 50564, 50567, 50572, 50573, 50575, 50577, 50581, 50583,
|
||||
50584, 50588, 50592, 50601, 50612, 50613, 50616, 50617, 50619, 50620, 50621, 50622, 50628, 50629, 50630, 50631,
|
||||
50632, 50633, 50634, 50636, 50638, 50640, 50641, 50644, 50648, 50656, 50657, 50659, 50661, 50668, 50669, 50670,
|
||||
50672, 50676, 50678, 50679, 50684, 50685, 50686, 50687, 50688, 50689, 50693, 50694, 50695, 50696, 50700, 50704,
|
||||
50712, 50713, 50715, 50716, 50724, 50725, 50728, 50732, 50733, 50734, 50736, 50739, 50740, 50741, 50743, 50745,
|
||||
50747, 50752, 50753, 50756, 50760, 50768, 50769, 50771, 50772, 50773, 50780, 50781, 50784, 50796, 50799, 50801,
|
||||
50808, 50809, 50812, 50816, 50824, 50825, 50827, 50829, 50836, 50837, 50840, 50844, 50852, 50853, 50855, 50857,
|
||||
50864, 50865, 50868, 50872, 50873, 50874, 50880, 50881, 50883, 50885, 50892, 50893, 50896, 50900, 50908, 50909,
|
||||
50912, 50913, 50920, 50921, 50924, 50928, 50936, 50937, 50941, 50948, 50949, 50952, 50956, 50964, 50965, 50967,
|
||||
50969, 50976, 50977, 50980, 50984, 50992, 50993, 50995, 50997, 50999, 51004, 51005, 51008, 51012, 51018, 51020,
|
||||
51021, 51023, 51025, 51026, 51027, 51028, 51029, 51030, 51031, 51032, 51036, 51040, 51048, 51051, 51060, 51061,
|
||||
51064, 51068, 51069, 51070, 51075, 51076, 51077, 51079, 51080, 51081, 51082, 51086, 51088, 51089, 51092, 51094,
|
||||
51095, 51096, 51098, 51104, 51105, 51107, 51108, 51109, 51110, 51116, 51117, 51120, 51124, 51132, 51133, 51135,
|
||||
51136, 51137, 51144, 51145, 51148, 51150, 51152, 51160, 51165, 51172, 51176, 51180, 51200, 51201, 51204, 51208,
|
||||
51210, 51216, 51217, 51219, 51221, 51222, 51228, 51229, 51232, 51236, 51244, 51245, 51247, 51249, 51256, 51260,
|
||||
51264, 51272, 51273, 51276, 51277, 51284, 51312, 51313, 51316, 51320, 51322, 51328, 51329, 51331, 51333, 51334,
|
||||
51335, 51339, 51340, 51341, 51348, 51357, 51359, 51361, 51368, 51388, 51389, 51396, 51400, 51404, 51412, 51413,
|
||||
51415, 51417, 51424, 51425, 51428, 51445, 51452, 51453, 51456, 51460, 51461, 51462, 51468, 51469, 51471, 51473,
|
||||
51480, 51500, 51508, 51536, 51537, 51540, 51544, 51552, 51553, 51555, 51564, 51568, 51572, 51580, 51592, 51593,
|
||||
51596, 51600, 51608, 51609, 51611, 51613, 51648, 51649, 51652, 51655, 51656, 51658, 51664, 51665, 51667, 51669,
|
||||
51670, 51673, 51674, 51676, 51677, 51680, 51682, 51684, 51687, 51692, 51693, 51695, 51696, 51697, 51704, 51705,
|
||||
51708, 51712, 51720, 51721, 51723, 51724, 51725, 51732, 51736, 51753, 51788, 51789, 51792, 51796, 51804, 51805,
|
||||
51807, 51808, 51809, 51816, 51837, 51844, 51864, 51900, 51901, 51904, 51908, 51916, 51917, 51919, 51921, 51923,
|
||||
51928, 51929, 51936, 51948, 51956, 51976, 51984, 51988, 51992, 52000, 52001, 52033, 52040, 52041, 52044, 52048,
|
||||
52056, 52057, 52061, 52068, 52088, 52089, 52124, 52152, 52180, 52196, 52199, 52201, 52236, 52237, 52240, 52244,
|
||||
52252, 52253, 52257, 52258, 52263, 52264, 52265, 52268, 52270, 52272, 52280, 52281, 52283, 52284, 52285, 52286,
|
||||
52292, 52293, 52296, 52300, 52308, 52309, 52311, 52312, 52313, 52320, 52324, 52326, 52328, 52336, 52341, 52376,
|
||||
52377, 52380, 52384, 52392, 52393, 52395, 52396, 52397, 52404, 52405, 52408, 52412, 52420, 52421, 52423, 52425,
|
||||
52432, 52436, 52452, 52460, 52464, 52481, 52488, 52489, 52492, 52496, 52504, 52505, 52507, 52509, 52516, 52520,
|
||||
52524, 52537, 52572, 52576, 52580, 52588, 52589, 52591, 52593, 52600, 52616, 52628, 52629, 52632, 52636, 52644,
|
||||
52645, 52647, 52649, 52656, 52676, 52684, 52688, 52712, 52716, 52720, 52728, 52729, 52731, 52733, 52740, 52744,
|
||||
52748, 52756, 52761, 52768, 52769, 52772, 52776, 52784, 52785, 52787, 52789, 52824, 52825, 52828, 52831, 52832,
|
||||
52833, 52840, 52841, 52843, 52845, 52852, 52853, 52856, 52860, 52868, 52869, 52871, 52873, 52880, 52881, 52884,
|
||||
52888, 52896, 52897, 52899, 52900, 52901, 52908, 52909, 52929, 52964, 52965, 52968, 52971, 52972, 52980, 52981,
|
||||
52983, 52984, 52985, 52992, 52993, 52996, 53000, 53008, 53009, 53011, 53013, 53020, 53024, 53028, 53036, 53037,
|
||||
53039, 53040, 53041, 53048, 53076, 53077, 53080, 53084, 53092, 53093, 53095, 53097, 53104, 53105, 53108, 53112,
|
||||
53120, 53125, 53132, 53153, 53160, 53168, 53188, 53216, 53217, 53220, 53224, 53232, 53233, 53235, 53237, 53244,
|
||||
53248, 53252, 53265, 53272, 53293, 53300, 53301, 53304, 53308, 53316, 53317, 53319, 53321, 53328, 53332, 53336,
|
||||
53344, 53356, 53357, 53360, 53364, 53372, 53373, 53377, 53412, 53413, 53416, 53420, 53428, 53429, 53431, 53433,
|
||||
53440, 53441, 53444, 53448, 53449, 53456, 53457, 53459, 53460, 53461, 53468, 53469, 53472, 53476, 53484, 53485,
|
||||
53487, 53488, 53489, 53496, 53517, 53552, 53553, 53556, 53560, 53562, 53568, 53569, 53571, 53572, 53573, 53580,
|
||||
53581, 53584, 53588, 53596, 53597, 53599, 53601, 53608, 53612, 53628, 53636, 53640, 53664, 53665, 53668, 53672,
|
||||
53680, 53681, 53683, 53685, 53690, 53692, 53696, 53720, 53748, 53752, 53767, 53769, 53776, 53804, 53805, 53808,
|
||||
53812, 53820, 53821, 53823, 53825, 53832, 53852, 53860, 53888, 53889, 53892, 53896, 53904, 53905, 53909, 53916,
|
||||
53920, 53924, 53932, 53937, 53944, 53945, 53948, 53951, 53952, 53954, 53960, 53961, 53963, 53972, 53976, 53980,
|
||||
53988, 53989, 54000, 54001, 54004, 54008, 54016, 54017, 54019, 54021, 54028, 54029, 54030, 54032, 54036, 54038,
|
||||
54044, 54045, 54047, 54048, 54049, 54053, 54056, 54057, 54060, 54064, 54072, 54073, 54075, 54076, 54077, 54084,
|
||||
54085, 54140, 54141, 54144, 54148, 54156, 54157, 54159, 54160, 54161, 54168, 54169, 54172, 54176, 54184, 54185,
|
||||
54187, 54189, 54196, 54200, 54204, 54212, 54213, 54216, 54217, 54224, 54232, 54241, 54243, 54252, 54253, 54256,
|
||||
54260, 54268, 54269, 54271, 54273, 54280, 54301, 54336, 54340, 54364, 54368, 54372, 54381, 54383, 54392, 54393,
|
||||
54396, 54399, 54400, 54402, 54408, 54409, 54411, 54413, 54420, 54441, 54476, 54480, 54484, 54492, 54495, 54504,
|
||||
54508, 54512, 54520, 54523, 54525, 54532, 54536, 54540, 54548, 54549, 54551, 54588, 54589, 54592, 54596, 54604,
|
||||
54605, 54607, 54609, 54616, 54617, 54620, 54624, 54629, 54632, 54633, 54635, 54637, 54644, 54645, 54648, 54652,
|
||||
54660, 54661, 54663, 54664, 54665, 54672, 54693, 54728, 54729, 54732, 54736, 54738, 54744, 54745, 54747, 54749,
|
||||
54756, 54757, 54760, 54764, 54772, 54773, 54775, 54777, 54784, 54785, 54788, 54792, 54800, 54801, 54803, 54804,
|
||||
54805, 54812, 54816, 54820, 54829, 54840, 54841, 54844, 54848, 54853, 54856, 54857, 54859, 54861, 54865, 54868,
|
||||
54869, 54872, 54876, 54887, 54889, 54896, 54897, 54900, 54915, 54917, 54924, 54925, 54928, 54932, 54941, 54943,
|
||||
54945, 54952, 54956, 54960, 54969, 54971, 54980, 54981, 54984, 54988, 54993, 54996, 54999, 55001, 55008, 55012,
|
||||
55016, 55024, 55029, 55036, 55037, 55040, 55044, 55057, 55064, 55065, 55068, 55072, 55080, 55081, 55083, 55085,
|
||||
55092, 55093, 55096, 55100, 55108, 55111, 55113, 55120, 55121, 55124, 55126, 55127, 55128, 55129, 55136, 55137,
|
||||
55139, 55141, 55145, 55148, 55152, 55156, 55164, 55165, 55169, 55176, 55177, 55180, 55184, 55192, 55193, 55195,
|
||||
55197, 04352, 04353, 04354, 04355, 04356, 04357, 04358, 04359, 04360, 04361, 04362, 04363, 04364, 04365, 04366,
|
||||
04367, 04368, 04369, 04370, 04449, 04450, 04451, 04452, 04453, 04454, 04455, 04456, 04457, 04461, 04462, 04466,
|
||||
04467, 04469, 47252, 49968, 50108, 50388, 52012, 65535,
|
||||
};
|
||||
|
||||
private static readonly Dictionary<ushort, int> G4ValueId = G4Values
|
||||
.Select((value, index) => new KeyValuePair<ushort, int>(value, index))
|
||||
.ToDictionary(pair => pair.Key, pair => pair.Value);
|
||||
|
||||
private static readonly Dictionary<ushort, int> G4CharId = G4Chars
|
||||
.Select((value, index) => new KeyValuePair<ushort, int>(value, index))
|
||||
.ToDictionary(pair => pair.Key, pair => pair.Value);
|
||||
|
||||
#endregion
|
||||
int count = value.Length * 2;
|
||||
if (count == destBuffer.Length)
|
||||
return count;
|
||||
WriteUInt16LittleEndian(destBuffer[count..], Terminator);
|
||||
return count + 2;
|
||||
}
|
||||
}
|
||||
|
|
130
PKHeX.Core/PKM/Strings/StringConverter4GC.cs
Normal file
130
PKHeX.Core/PKM/Strings/StringConverter4GC.cs
Normal file
|
@ -0,0 +1,130 @@
|
|||
using System;
|
||||
using static PKHeX.Core.StringConverter4Util;
|
||||
using static System.Buffers.Binary.BinaryPrimitives;
|
||||
|
||||
namespace PKHeX.Core;
|
||||
|
||||
public static class StringConverter4GC
|
||||
{
|
||||
private const ushort Terminator = 0xFFFF;
|
||||
private const char TerminatorChar = (char)Terminator;
|
||||
|
||||
/// <summary>
|
||||
/// Converts Generation 4 Big Endian encoded character data to string.
|
||||
/// </summary>
|
||||
/// <param name="data">Byte array containing encoded character data.</param>
|
||||
/// <returns>Converted string.</returns>
|
||||
public static string GetString(ReadOnlySpan<byte> data)
|
||||
{
|
||||
Span<char> result = stackalloc char[data.Length];
|
||||
var length = LoadString(data, result);
|
||||
return new string(result[..length].ToArray());
|
||||
}
|
||||
|
||||
private static int LoadString(ReadOnlySpan<byte> data, Span<char> result)
|
||||
{
|
||||
int i = 0;
|
||||
for (; i < data.Length; i += 2)
|
||||
{
|
||||
var value = ReadUInt16BigEndian(data[i..]);
|
||||
if (value == Terminator)
|
||||
break;
|
||||
char chr = (char)ConvertValue2CharG4(value);
|
||||
if (chr == TerminatorChar)
|
||||
break;
|
||||
chr = StringConverter.SanitizeChar(chr);
|
||||
result[i/2] = chr;
|
||||
}
|
||||
return i/2;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Converts a string to Generation 4 Big Endian encoded character data.
|
||||
/// </summary>
|
||||
/// <param name="destBuffer"></param>
|
||||
/// <param name="value">String to be converted.</param>
|
||||
/// <param name="maxLength">Maximum length of string</param>
|
||||
/// <param name="option"></param>
|
||||
/// <returns>Byte array containing encoded character data</returns>
|
||||
public static int SetString(Span<byte> destBuffer, ReadOnlySpan<char> value, int maxLength,
|
||||
StringConverterOption option = StringConverterOption.ClearZero)
|
||||
{
|
||||
if (value.Length > maxLength)
|
||||
value = value[..maxLength]; // Hard cap
|
||||
|
||||
if (option is StringConverterOption.ClearZero)
|
||||
destBuffer.Clear();
|
||||
|
||||
for (int i = 0; i < value.Length; i++)
|
||||
{
|
||||
var chr = value[i];
|
||||
chr = StringConverter.UnSanitizeChar5(chr);
|
||||
ushort val = ConvertChar2ValueG4(chr);
|
||||
WriteUInt16BigEndian(destBuffer[(i * 2)..], val);
|
||||
}
|
||||
|
||||
var count = value.Length * 2;
|
||||
if (count == destBuffer.Length)
|
||||
return count;
|
||||
WriteUInt16BigEndian(destBuffer[count..], Terminator);
|
||||
return count + 2;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Converts Generation 4 Big Endian encoded character data to string, with direct Unicode characters.
|
||||
/// </summary>
|
||||
/// <remarks>Used by the Save File's internal strings.</remarks>
|
||||
/// <param name="data">Byte array containing encoded character data.</param>
|
||||
/// <returns>Converted string.</returns>
|
||||
public static string GetStringUnicode(ReadOnlySpan<byte> data)
|
||||
{
|
||||
Span<char> result = stackalloc char[data.Length];
|
||||
var length = LoadStringUnicode(data, result);
|
||||
return new string(result[..length].ToArray());
|
||||
}
|
||||
|
||||
private static int LoadStringUnicode(ReadOnlySpan<byte> data, Span<char> result)
|
||||
{
|
||||
int i = 0;
|
||||
for (; i < data.Length; i += 2)
|
||||
{
|
||||
char chr = (char)ReadUInt16BigEndian(data[i..]);
|
||||
if (chr == TerminatorChar)
|
||||
break;
|
||||
chr = StringConverter.SanitizeChar(chr);
|
||||
result[i/2] = chr;
|
||||
}
|
||||
return i/2;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Converts a string to Generation 4 Big Endian encoded character data, with direct Unicode characters.
|
||||
/// </summary>
|
||||
/// <remarks>Used by the Save File's internal strings.</remarks>
|
||||
/// <param name="value">String to be converted.</param>
|
||||
/// <param name="destBuffer"></param>
|
||||
/// <param name="maxLength">Maximum length of string</param>
|
||||
/// <param name="option"></param>
|
||||
/// <returns>Byte array containing encoded character data</returns>
|
||||
public static int SetStringUnicode(ReadOnlySpan<char> value, Span<byte> destBuffer, int maxLength, StringConverterOption option = StringConverterOption.ClearZero)
|
||||
{
|
||||
if (value.Length > maxLength)
|
||||
value = value[..maxLength]; // Hard cap
|
||||
|
||||
if (option is StringConverterOption.ClearZero)
|
||||
destBuffer.Clear();
|
||||
|
||||
for (int i = 0; i < value.Length; i++)
|
||||
{
|
||||
var c = value[i];
|
||||
c = StringConverter.UnSanitizeChar5(c);
|
||||
WriteUInt16BigEndian(destBuffer[(i * 2)..], c);
|
||||
}
|
||||
|
||||
var count = value.Length * 2;
|
||||
if (count == destBuffer.Length)
|
||||
return count;
|
||||
WriteUInt16BigEndian(destBuffer[count..], 0);
|
||||
return count + 2;
|
||||
}
|
||||
}
|
439
PKHeX.Core/PKM/Strings/StringConverter4Util.cs
Normal file
439
PKHeX.Core/PKM/Strings/StringConverter4Util.cs
Normal file
|
@ -0,0 +1,439 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
|
||||
namespace PKHeX.Core;
|
||||
|
||||
public static class StringConverter4Util
|
||||
{
|
||||
/// <summary>
|
||||
/// Converts a Generation 4 value to Unicode character.
|
||||
/// </summary>
|
||||
/// <param name="val">Encoded value.</param>
|
||||
/// <returns>Decoded value (unicode).</returns>
|
||||
public static ushort ConvertValue2CharG4(ushort val)
|
||||
{
|
||||
return G4ValueId.TryGetValue(val, out int index)
|
||||
? G4Chars[index] : '?';
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Converts a Unicode character to Generation 4 value.
|
||||
/// </summary>
|
||||
/// <param name="chr">Decoded value (unicode).</param>
|
||||
/// <returns>Encoded value.</returns>
|
||||
public static ushort ConvertChar2ValueG4(ushort chr)
|
||||
{
|
||||
return G4CharId.TryGetValue(chr, out int index)
|
||||
? G4Values[index] : (ushort)00428; // '?'
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Strips diacritics on gen1-4 french pkm names
|
||||
/// </summary>
|
||||
/// <param name="input">String to clean</param>
|
||||
/// <returns>Cleaned string</returns>
|
||||
/// <remarks>Only 4 characters are accented in gen1-4</remarks>
|
||||
public static void StripDiacriticsFR4(Span<char> input)
|
||||
{
|
||||
for (int i = 0; i < input.Length; i++)
|
||||
{
|
||||
if (FrDiacritic.TryGetValue(input[i], out var value))
|
||||
input[i] = value;
|
||||
}
|
||||
}
|
||||
|
||||
private static readonly Dictionary<char, char> FrDiacritic = new(4)
|
||||
{
|
||||
{ 'È', 'E' },
|
||||
{ 'É', 'E' },
|
||||
{ 'Ê', 'E' },
|
||||
{ 'Ï', 'I' },
|
||||
};
|
||||
|
||||
#region Conversion Data
|
||||
|
||||
/// <summary>
|
||||
/// Values (stored value)
|
||||
/// </summary>
|
||||
private static readonly ushort[] G4Values =
|
||||
{
|
||||
00001, 00002, 00003, 00004, 00005, 00006, 00007, 00008, 00009, 00010, 00011, 00012, 00013, 00014, 00015, 00016,
|
||||
00017, 00018, 00019, 00020, 00021, 00022, 00023, 00024, 00025, 00026, 00027, 00028, 00029, 00030, 00031, 00032,
|
||||
00033, 00034, 00035, 00036, 00037, 00038, 00039, 00040, 00041, 00042, 00043, 00044, 00045, 00046, 00047, 00048,
|
||||
00049, 00050, 00051, 00052, 00053, 00054, 00055, 00056, 00057, 00058, 00059, 00060, 00061, 00062, 00063, 00064,
|
||||
00065, 00066, 00067, 00068, 00069, 00070, 00071, 00072, 00073, 00074, 00075, 00076, 00077, 00078, 00079, 00080,
|
||||
00081, 00082, 00083, 00084, 00085, 00086, 00087, 00088, 00089, 00090, 00091, 00092, 00093, 00094, 00095, 00096,
|
||||
00097, 00098, 00099, 00100, 00101, 00102, 00103, 00104, 00105, 00106, 00107, 00108, 00109, 00110, 00111, 00112,
|
||||
00113, 00114, 00115, 00116, 00117, 00118, 00119, 00120, 00121, 00122, 00123, 00124, 00125, 00126, 00127, 00128,
|
||||
00129, 00130, 00131, 00132, 00133, 00134, 00135, 00136, 00137, 00138, 00139, 00140, 00141, 00142, 00143, 00144,
|
||||
00145, 00146, 00147, 00148, 00149, 00150, 00151, 00152, 00153, 00154, 00155, 00156, 00157, 00158, 00159, 00160,
|
||||
00161, 00162, 00163, 00164, 00165, 00166, 00167, 00168, 00169, 00170, 00171, 00172, 00173, 00174, 00175, 00176,
|
||||
00177, 00178, 00179, 00180, 00181, 00182, 00183, 00184, 00185, 00186, 00187, 00188, 00189, 00190, 00191, 00192,
|
||||
00193, 00194, 00195, 00196, 00197, 00198, 00199, 00200, 00201, 00202, 00203, 00204, 00205, 00206, 00207, 00208,
|
||||
00209, 00210, 00211, 00212, 00213, 00214, 00215, 00216, 00217, 00218, 00219, 00220, 00221, 00222, 00223, 00225,
|
||||
00226, 00227, 00228, 00229, 00230, 00231, 00232, 00233, 00234, 00235, 00236, 00237, 00238, 00239, 00240, 00241,
|
||||
00242, 00243, 00244, 00245, 00246, 00247, 00248, 00249, 00250, 00251, 00252, 00253, 00254, 00255, 00256, 00257,
|
||||
00258, 00259, 00260, 00261, 00262, 00263, 00264, 00265, 00266, 00267, 00268, 00269, 00270, 00271, 00272, 00273,
|
||||
00275, 00276, 00277, 00278, 00279, 00280, 00281, 00282, 00283, 00284, 00285, 00286, 00287, 00288, 00289,
|
||||
00290, 00291, 00292, 00293, 00294, 00295, 00296, 00297, 00298, 00299, 00300, 00301, 00302, 00303, 00304, 00305,
|
||||
00306, 00307, 00308, 00309, 00310, 00311, 00312, 00313, 00314, 00315, 00316, 00317, 00318, 00319, 00320, 00321,
|
||||
00322, 00323, 00324, 00325, 00326, 00327, 00328, 00329, 00330, 00331, 00332, 00333, 00334, 00335, 00336, 00337,
|
||||
00338, 00339, 00340, 00341, 00342, 00343, 00344, 00345, 00346, 00347, 00348, 00349, 00350, 00351, 00352, 00353,
|
||||
00354, 00355, 00356, 00357, 00358, 00359, 00360, 00361, 00362, 00363, 00364, 00365, 00366, 00367, 00368, 00369,
|
||||
00370, 00371, 00372, 00373, 00374, 00375, 00376, 00377, 00378, 00379, 00380, 00381, 00382, 00383, 00384, 00385,
|
||||
00386, 00387, 00388, 00389, 00390, 00391, 00392, 00393, 00394, 00395, 00396, 00397, 00398, 00399, 00400, 00401,
|
||||
00402, 00403, 00404, 00405, 00406, 00407, 00408, 00409, 00410, 00411, 00412, 00413, 00414, 00415, 00416, 00417,
|
||||
00418, 00419, 00420, 00421, 00422, 00423, 00424, 00425, 00426, 00427, 00428, 00429, 00430, 00431, 00432, 00433,
|
||||
00434, 00435, 00436, 00437, 00438, 00439, 00440, 00441, 00442, 00443, 00444, 00445, 00446, 00447, 00448, 00449,
|
||||
00450, 00451, 00452, 00453, 00454, 00455, 00456, 00457, 00458, 00459, 00460, 00461, 00462, 00463, 00464, 00465,
|
||||
00466, 00467, 00468, 00469, 00470, 00471, 00472, 00473, 00474, 00475, 00476, 00477, 00478,
|
||||
01025, 01026, 01027, 01028, 01029, 01030, 01031, 01032, 01033, 01034, 01035, 01036, 01037,
|
||||
01038, 01039, 01040, 01041, 01042, 01043, 01044, 01045, 01046, 01047, 01048, 01049, 01050, 01051, 01052, 01053,
|
||||
01054, 01055, 01056, 01057, 01058, 01059, 01060, 01061, 01062, 01063, 01064, 01065, 01066, 01067, 01068, 01069,
|
||||
01070, 01071, 01072, 01073, 01074, 01075, 01076, 01077, 01078, 01079, 01080, 01081, 01082, 01083, 01084, 01085,
|
||||
01086, 01087, 01088, 01089, 01090, 01091, 01092, 01093, 01094, 01095, 01096, 01097, 01098, 01099, 01100, 01101,
|
||||
01102, 01103, 01104, 01105, 01106, 01107, 01108, 01109, 01110, 01111, 01112, 01113, 01114, 01115, 01116, 01117,
|
||||
01118, 01119, 01120, 01121, 01122, 01123, 01124, 01125, 01126, 01127, 01128, 01129, 01130, 01131, 01132, 01133,
|
||||
01134, 01135, 01136, 01137, 01138, 01139, 01140, 01141, 01142, 01143, 01144, 01145, 01146, 01147, 01148, 01149,
|
||||
01150, 01151, 01152, 01153, 01154, 01155, 01156, 01157, 01158, 01159, 01160, 01161, 01162, 01163, 01164, 01165,
|
||||
01166, 01167, 01168, 01169, 01170, 01171, 01172, 01173, 01174, 01175, 01176, 01177, 01178, 01179, 01180, 01181,
|
||||
01182, 01183, 01184, 01185, 01186, 01187, 01188, 01189, 01190, 01191, 01192, 01193, 01194, 01195, 01196, 01197,
|
||||
01198, 01199, 01200, 01201, 01202, 01203, 01204, 01205, 01206, 01207, 01208, 01209, 01210, 01211, 01212, 01213,
|
||||
01214, 01215, 01216, 01217, 01218, 01219, 01220, 01221, 01222, 01223, 01224, 01225, 01226, 01227, 01228, 01229,
|
||||
01230, 01231, 01232, 01233, 01234, 01235, 01236, 01237, 01238, 01239, 01240, 01241, 01242, 01243, 01244, 01245,
|
||||
01246, 01247, 01248, 01249, 01250, 01251, 01252, 01253, 01254, 01255, 01256, 01257, 01258, 01259, 01260, 01261,
|
||||
01262, 01263, 01264, 01265, 01266, 01267, 01268, 01269, 01270, 01271, 01272, 01273, 01274, 01275, 01276, 01277,
|
||||
01278, 01279, 01280, 01281, 01282, 01283, 01284, 01285, 01286, 01287, 01288, 01289, 01290, 01291, 01292, 01293,
|
||||
01294, 01295, 01296, 01297, 01298, 01299, 01300, 01301, 01302, 01303, 01304, 01305, 01306, 01307, 01308, 01309,
|
||||
01310, 01311, 01312, 01313, 01314, 01315, 01316, 01317, 01318, 01319, 01320, 01321, 01322, 01323, 01324, 01325,
|
||||
01326, 01327, 01328, 01329, 01330, 01331, 01332, 01333, 01334, 01335, 01336, 01337, 01338, 01339, 01340, 01341,
|
||||
01342, 01343, 01344, 01345, 01346, 01347, 01348, 01349, 01350, 01351, 01352, 01353, 01354, 01355, 01356, 01357,
|
||||
01358, 01359, 01360, 01361, 01362, 01363, 01364, 01365, 01366, 01367, 01368, 01369, 01370, 01371, 01372, 01373,
|
||||
01374, 01375, 01376, 01377, 01378, 01379, 01380, 01381, 01382, 01383, 01384, 01385, 01386, 01387, 01388, 01389,
|
||||
01390, 01391, 01392, 01393, 01394, 01395, 01396, 01397, 01398, 01399, 01400, 01401, 01402, 01403, 01404, 01405,
|
||||
01406, 01407, 01408, 01409, 01410, 01411, 01412, 01413, 01414, 01415, 01416, 01417, 01418, 01419, 01420, 01421,
|
||||
01422, 01423, 01424, 01425, 01426, 01427, 01428, 01429, 01430, 01431, 01432, 01433, 01434, 01435, 01436, 01437,
|
||||
01438, 01439, 01440, 01441, 01442, 01443, 01444, 01445, 01446, 01447, 01448, 01449, 01450, 01451, 01452, 01453,
|
||||
01454, 01455, 01456, 01457, 01458, 01459, 01460, 01461, 01462, 01463, 01464, 01465, 01466, 01467, 01468, 01469,
|
||||
01470, 01471, 01472, 01473, 01474, 01475, 01476, 01477, 01478, 01479, 01480, 01481, 01482, 01483, 01484, 01485,
|
||||
01486, 01487, 01488, 01489, 01490, 01491, 01492, 01493, 01494, 01495, 01496, 01497, 01498, 01499, 01500, 01501,
|
||||
01502, 01503, 01504, 01505, 01506, 01507, 01508, 01509, 01510, 01511, 01512, 01513, 01514, 01515, 01516, 01517,
|
||||
01518, 01519, 01520, 01521, 01522, 01523, 01524, 01525, 01526, 01527, 01528, 01529, 01530, 01531, 01532, 01533,
|
||||
01534, 01535, 01536, 01537, 01538, 01539, 01540, 01541, 01542, 01543, 01544, 01545, 01546, 01547, 01548, 01549,
|
||||
01550, 01551, 01552, 01553, 01554, 01555, 01556, 01557, 01558, 01559, 01560, 01561, 01562, 01563, 01564, 01565,
|
||||
01566, 01567, 01568, 01569, 01570, 01571, 01572, 01573, 01574, 01575, 01576, 01577, 01578, 01579, 01580, 01581,
|
||||
01582, 01583, 01584, 01585, 01586, 01587, 01588, 01589, 01590, 01591, 01592, 01593, 01594, 01595, 01596, 01597,
|
||||
01598, 01599, 01600, 01601, 01602, 01603, 01604, 01605, 01606, 01607, 01608, 01609, 01610, 01611, 01612, 01613,
|
||||
01614, 01615, 01616, 01617, 01618, 01619, 01620, 01621, 01622, 01623, 01624, 01625, 01626, 01627, 01628, 01629,
|
||||
01630, 01631, 01632, 01633, 01634, 01635, 01636, 01637, 01638, 01639, 01640, 01641, 01642, 01643, 01644, 01645,
|
||||
01646, 01647, 01648, 01649, 01650, 01651, 01652, 01653, 01654, 01655, 01656, 01657, 01658, 01659, 01660, 01661,
|
||||
01662, 01663, 01664, 01665, 01666, 01667, 01668, 01669, 01670, 01671, 01672, 01673, 01674, 01675, 01676, 01677,
|
||||
01678, 01679, 01680, 01681, 01682, 01683, 01684, 01685, 01686, 01687, 01688, 01689, 01690, 01691, 01692, 01693,
|
||||
01694, 01695, 01696, 01697, 01698, 01699, 01700, 01701, 01702, 01703, 01704, 01705, 01706, 01707, 01708, 01709,
|
||||
01710, 01711, 01712, 01713, 01714, 01715, 01716, 01717, 01718, 01719, 01720, 01721, 01722, 01723, 01724, 01725,
|
||||
01726, 01727, 01728, 01729, 01730, 01731, 01732, 01733, 01734, 01735, 01736, 01737, 01738, 01739, 01740, 01741,
|
||||
01742, 01743, 01744, 01745, 01746, 01747, 01748, 01749, 01750, 01751, 01752, 01753, 01754, 01755, 01756, 01757,
|
||||
01758, 01759, 01760, 01761, 01762, 01763, 01764, 01765, 01766, 01767, 01768, 01769, 01770, 01771, 01772, 01773,
|
||||
01774, 01775, 01776, 01777, 01778, 01779, 01780, 01781, 01782, 01783, 01784, 01785, 01786, 01787, 01788, 01789,
|
||||
01790, 01791, 01792, 01793, 01794, 01795, 01796, 01797, 01798, 01799, 01800, 01801, 01802, 01803, 01804, 01805,
|
||||
01806, 01807, 01808, 01809, 01810, 01811, 01812, 01813, 01814, 01815, 01816, 01817, 01818, 01819, 01820, 01821,
|
||||
01822, 01823, 01824, 01825, 01826, 01827, 01828, 01829, 01830, 01831, 01832, 01833, 01834, 01835, 01836, 01837,
|
||||
01838, 01839, 01840, 01841, 01842, 01843, 01844, 01845, 01846, 01847, 01848, 01849, 01850, 01851, 01852, 01853,
|
||||
01854, 01855, 01856, 01857, 01858, 01859, 01860, 01861, 01862, 01863, 01864, 01865, 01866, 01867, 01868, 01869,
|
||||
01870, 01871, 01872, 01873, 01874, 01875, 01876, 01877, 01878, 01879, 01880, 01881, 01882, 01883, 01884, 01885,
|
||||
01886, 01887, 01888, 01889, 01890, 01891, 01892, 01893, 01894, 01895, 01896, 01897, 01898, 01899, 01900, 01901,
|
||||
01902, 01903, 01904, 01905, 01906, 01907, 01908, 01909, 01910, 01911, 01912, 01913, 01914, 01915, 01916, 01917,
|
||||
01918, 01919, 01920, 01921, 01922, 01923, 01924, 01925, 01926, 01927, 01928, 01929, 01930, 01931, 01932, 01933,
|
||||
01934, 01935, 01936, 01937, 01938, 01939, 01940, 01941, 01942, 01943, 01944, 01945, 01946, 01947, 01948, 01949,
|
||||
01950, 01951, 01952, 01953, 01954, 01955, 01956, 01957, 01958, 01959, 01960, 01961, 01962, 01963, 01964, 01965,
|
||||
01966, 01967, 01968, 01969, 01970, 01971, 01972, 01973, 01974, 01975, 01976, 01977, 01978, 01979, 01980, 01981,
|
||||
01982, 01983, 01984, 01985, 01986, 01987, 01988, 01989, 01990, 01991, 01992, 01993, 01994, 01995, 01996, 01997,
|
||||
01998, 01999, 02000, 02001, 02002, 02003, 02004, 02005, 02006, 02007, 02008, 02009, 02010, 02011, 02012, 02013,
|
||||
02014, 02015, 02016, 02017, 02018, 02019, 02020, 02021, 02022, 02023, 02024, 02025, 02026, 02027, 02028, 02029,
|
||||
02030, 02031, 02032, 02033, 02034, 02035, 02036, 02037, 02038, 02039, 02040, 02041, 02042, 02043, 02044, 02045,
|
||||
02046, 02047, 02048, 02049, 02050, 02051, 02052, 02053, 02054, 02055, 02056, 02057, 02058, 02059, 02060, 02061,
|
||||
02062, 02063, 02064, 02065, 02066, 02067, 02068, 02069, 02070, 02071, 02072, 02073, 02074, 02075, 02076, 02077,
|
||||
02078, 02079, 02080, 02081, 02082, 02083, 02084, 02085, 02086, 02087, 02088, 02089, 02090, 02091, 02092, 02093,
|
||||
02094, 02095, 02096, 02097, 02098, 02099, 02100, 02101, 02102, 02103, 02104, 02105, 02106, 02107, 02108, 02109,
|
||||
02110, 02111, 02112, 02113, 02114, 02115, 02116, 02117, 02118, 02119, 02120, 02121, 02122, 02123, 02124, 02125,
|
||||
02126, 02127, 02128, 02129, 02130, 02131, 02132, 02133, 02134, 02135, 02136, 02137, 02138, 02139, 02140, 02141,
|
||||
02142, 02143, 02144, 02145, 02146, 02147, 02148, 02149, 02150, 02151, 02152, 02153, 02154, 02155, 02156, 02157,
|
||||
02158, 02159, 02160, 02161, 02162, 02163, 02164, 02165, 02166, 02167, 02168, 02169, 02170, 02171, 02172, 02173,
|
||||
02174, 02175, 02176, 02177, 02178, 02179, 02180, 02181, 02182, 02183, 02184, 02185, 02186, 02187, 02188, 02189,
|
||||
02190, 02191, 02192, 02193, 02194, 02195, 02196, 02197, 02198, 02199, 02200, 02201, 02202, 02203, 02204, 02205,
|
||||
02206, 02207, 02208, 02209, 02210, 02211, 02212, 02213, 02214, 02215, 02216, 02217, 02218, 02219, 02220, 02221,
|
||||
02222, 02223, 02224, 02225, 02226, 02227, 02228, 02229, 02230, 02231, 02232, 02233, 02234, 02235, 02236, 02237,
|
||||
02238, 02239, 02240, 02241, 02242, 02243, 02244, 02245, 02246, 02247, 02248, 02249, 02250, 02251, 02252, 02253,
|
||||
02254, 02255, 02256, 02257, 02258, 02259, 02260, 02261, 02262, 02263, 02264, 02265, 02266, 02267, 02268, 02269,
|
||||
02270, 02271, 02272, 02273, 02274, 02275, 02276, 02277, 02278, 02279, 02280, 02281, 02282, 02283, 02284, 02285,
|
||||
02286, 02287, 02288, 02289, 02290, 02291, 02292, 02293, 02294, 02295, 02296, 02297, 02298, 02299, 02300, 02301,
|
||||
02302, 02303, 02304, 02305, 02306, 02307, 02308, 02309, 02310, 02311, 02312, 02313, 02314, 02315, 02316, 02317,
|
||||
02318, 02319, 02320, 02321, 02322, 02323, 02324, 02325, 02326, 02327, 02328, 02329, 02330, 02331, 02332, 02333,
|
||||
02334, 02335, 02336, 02337, 02338, 02339, 02340, 02341, 02342, 02343, 02344, 02345, 02346, 02347, 02348, 02349,
|
||||
02350, 02351, 02352, 02353, 02354, 02355, 02356, 02357, 02358, 02359, 02360, 02361, 02362, 02363, 02364, 02365,
|
||||
02366, 02367, 02368, 02369, 02370, 02371, 02372, 02373, 02374, 02375, 02376, 02377, 02378, 02379, 02380, 02381,
|
||||
02382, 02383, 02384, 02385, 02386, 02387, 02388, 02389, 02390, 02391, 02392, 02393, 02394, 02395, 02396, 02397,
|
||||
02398, 02399, 02400, 02401, 02402, 02403, 02404, 02405, 02406, 02407, 02408, 02409, 02410, 02411, 02412, 02413,
|
||||
02414, 02415, 02416, 02417, 02418, 02419, 02420, 02421, 02422, 02423, 02424, 02425, 02426, 02427, 02428, 02429,
|
||||
02430, 02431, 02432, 02433, 02434, 02435, 02436, 02437, 02438, 02439, 02440, 02441, 02442, 02443, 02444, 02445,
|
||||
02446, 02447, 02448, 02449, 02450, 02451, 02452, 02453, 02454, 02455, 02456, 02457, 02458, 02459, 02460, 02461,
|
||||
02462, 02463, 02464, 02465, 02466, 02467, 02468, 02469, 02470, 02471, 02472, 02473, 02474, 02475, 02476, 02477,
|
||||
02478, 02479, 02480, 02481, 02482, 02483, 02484, 02485, 02486, 02487, 02488, 02489, 02490, 02491, 02492, 02493,
|
||||
02494, 02495, 02496, 02497, 02498, 02499, 02500, 02501, 02502, 02503, 02504, 02505, 02506, 02507, 02508, 02509,
|
||||
02510, 02511, 02512, 02513, 02514, 02515, 02516, 02517, 02518, 02519, 02520, 02521, 02522, 02523, 02524, 02525,
|
||||
02526, 02527, 02528, 02529, 02530, 02531, 02532, 02533, 02534, 02535, 02536, 02537, 02538, 02539, 02540, 02541,
|
||||
02542, 02543, 02544, 02545, 02546, 02547, 02548, 02549, 02550, 02551, 02552, 02553, 02554, 02555, 02556, 02557,
|
||||
02558, 02559, 02560, 02561, 02562, 02563, 02564, 02565, 02566, 02567, 02568, 02569, 02570, 02571, 02572, 02573,
|
||||
02574, 02575, 02576, 02577, 02578, 02579, 02580, 02581, 02582, 02583, 02584, 02585, 02586, 02587, 02588, 02589,
|
||||
02590, 02591, 02592, 02593, 02594, 02595, 02596, 02597, 02598, 02599, 02600, 02601, 02602, 02603, 02604, 02605,
|
||||
02606, 02607, 02608, 02609, 02610, 02611, 02612, 02613, 02614, 02615, 02616, 02617, 02618, 02619, 02620, 02621,
|
||||
02622, 02623, 02624, 02625, 02626, 02627, 02628, 02629, 02630, 02631, 02632, 02633, 02634, 02635, 02636, 02637,
|
||||
02638, 02639, 02640, 02641, 02642, 02643, 02644, 02645, 02646, 02647, 02648, 02649, 02650, 02651, 02652, 02653,
|
||||
02654, 02655, 02656, 02657, 02658, 02659, 02660, 02661, 02662, 02663, 02664, 02665, 02666, 02667, 02668, 02669,
|
||||
02670, 02671, 02672, 02673, 02674, 02675, 02676, 02677, 02678, 02679, 02680, 02681, 02682, 02683, 02684, 02685,
|
||||
02686, 02687, 02688, 02689, 02690, 02691, 02692, 02693, 02694, 02695, 02696, 02697, 02698, 02699, 02700, 02701,
|
||||
02702, 02703, 02704, 02705, 02706, 02707, 02708, 02709, 02710, 02711, 02712, 02713, 02714, 02715, 02716, 02717,
|
||||
02718, 02719, 02720, 02721, 02722, 02723, 02724, 02725, 02726, 02727, 02728, 02729, 02730, 02731, 02732, 02733,
|
||||
02734, 02735, 02736, 02737, 02738, 02739, 02740, 02741, 02742, 02743, 02744, 02745, 02746, 02747, 02748, 02749,
|
||||
02750, 02751, 02752, 02753, 02754, 02755, 02756, 02757, 02758, 02759, 02760, 02761, 02762, 02763, 02764, 02765,
|
||||
02766, 02767, 02768, 02769, 02770, 02771, 02772, 02773, 02774, 02775, 02776, 02777, 02778, 02779, 02780, 02781,
|
||||
02782, 02783, 02784, 02785, 02786, 02787, 02788, 02789, 02790, 02791, 02792, 02793, 02794, 02795, 02796, 02797,
|
||||
02798, 02799, 02800, 02801, 02802, 02803, 02804, 02805, 02806, 02807, 02808, 02809, 02810, 02811, 02812, 02813,
|
||||
02814, 02815, 02816, 02817, 02818, 02819, 02820, 02821, 02822, 02823, 02824, 02825, 02826, 02827, 02828, 02829,
|
||||
02830, 02831, 02832, 02833, 02834, 02835, 02836, 02837, 02838, 02839, 02840, 02841, 02842, 02843, 02844, 02845,
|
||||
02846, 02847, 02848, 02849, 02850, 02851, 02852, 02853, 02854, 02855, 02856, 02857, 02858, 02859, 02860, 02861,
|
||||
02862, 02863, 02864, 02865, 02866, 02867, 02868, 02869, 02870, 02871, 02872, 02873, 02874, 02875, 02876, 02877,
|
||||
02878, 02879, 02880, 02881, 02882, 02883, 02884, 02885, 02886, 02887, 02888, 02889, 02890, 02891, 02892, 02893,
|
||||
02894, 02895, 02896, 02897, 02898, 02899, 02900, 02901, 02902, 02903, 02904, 02905, 02906, 02907, 02908, 02909,
|
||||
02910, 02911, 02912, 02913, 02914, 02915, 02916, 02917, 02918, 02919, 02920, 02921, 02922, 02923, 02924, 02925,
|
||||
02926, 02927, 02928, 02929, 02930, 02931, 02932, 02933, 02934, 02935, 02936, 02937, 02938, 02939, 02940, 02941,
|
||||
02942, 02943, 02944, 02945, 02946, 02947, 02948, 02949, 02950, 02951, 02952, 02953, 02954, 02955, 02956, 02957,
|
||||
02958, 02959, 02960, 02961, 02962, 02963, 02964, 02965, 02966, 02967, 02968, 02969, 02970, 02971, 02972, 02973,
|
||||
02974, 02975, 02976, 02977, 02978, 02979, 02980, 02981, 02982, 02983, 02984, 02985, 02986, 02987, 02988, 02989,
|
||||
02990, 02991, 02992, 02993, 02994, 02995, 02996, 02997, 02998, 02999, 03000, 03001, 03002, 03003, 03004, 03005,
|
||||
03006, 03007, 03008, 03009, 03010, 03011, 03012, 03013, 03014, 03015, 03016, 03017, 03018, 03019, 03020, 03021,
|
||||
03022, 03023, 03024, 03025, 03026, 03027, 03028, 03029, 03030, 03031, 03032, 03033, 03034, 03035, 03036, 03037,
|
||||
03038, 03039, 03040, 03041, 03042, 03043, 03044, 03045, 03046, 03047, 03048, 03049, 03050, 03051, 03052, 03053,
|
||||
03054, 03055, 03056, 03057, 03058, 03059, 03060, 03061, 03062, 03063, 03064, 03065, 03066, 03067, 03068, 03069,
|
||||
03070, 03071, 03072, 03073, 03074, 03075, 03076, 03077, 03078, 03079, 03080, 03081, 03082, 03083, 03084, 03085,
|
||||
03086, 03087, 03088, 03089, 03090, 03091, 03092, 03093, 03094, 03095, 03096, 03097, 03098, 03099, 03100, 03101,
|
||||
03102, 03103, 03104, 03105, 03106, 03107, 03108, 03109, 03110, 03111, 03112, 03113, 03114, 03115, 03116, 03117,
|
||||
03118, 03119, 03120, 03121, 03122, 03123, 03124, 03125, 03126, 03127, 03128, 03129, 03130, 03131, 03132, 03133,
|
||||
03134, 03135, 03136, 03137, 03138, 03139, 03140, 03141, 03142, 03143, 03144, 03145, 03146, 03147, 03148, 03149,
|
||||
03150, 03151, 03152, 03153, 03154, 03155, 03156, 03157, 03158, 03159, 03160, 03161, 03162, 03163, 03164, 03165,
|
||||
03166, 03167, 03168, 03169, 03170, 03171, 03172, 03173, 03174, 03175, 03176, 03177, 03178, 03179, 03180, 03181,
|
||||
03182, 03183, 03184, 03185, 03186, 03187, 03188, 03189, 03190, 03191, 03192, 03193, 03194, 03195, 03196, 03197,
|
||||
03198, 03199, 03200, 03201, 03202, 03203, 03204, 03205, 03206, 03207, 03208, 03209, 03210, 03211, 03212, 03213,
|
||||
03214, 03215, 03216, 03217, 03218, 03219, 03220, 03221, 03222, 03223, 03224, 03225, 03226, 03227, 03228, 03229,
|
||||
03230, 03231, 03232, 03233, 03234, 03235, 03236, 03237, 03238, 03239, 03240, 03241, 03242, 03243, 03244, 03245,
|
||||
03246, 03247, 03248, 03249, 03250, 03251, 03252, 03253, 03254, 03255, 03256, 03257, 03258, 03259, 03260, 03261,
|
||||
03262, 03263, 03264, 03265, 03266, 03267, 03268, 03269, 03270, 03271, 03272, 03273, 03274, 03275, 03276, 03277,
|
||||
03278, 03279, 03280, 03281, 03282, 03283, 03284, 03285, 03286, 03287, 03288, 03289, 03290, 03291, 03292, 03293,
|
||||
03294, 03295, 03296, 03297, 03298, 03299, 03300, 03301, 03302, 03303, 03304, 03305, 03306, 03307, 03308, 03309,
|
||||
03310, 03311, 03312, 03313, 03314, 03315, 03316, 03317, 03318, 03319, 03320, 03321, 03322, 03323, 03324, 03325,
|
||||
03326, 03327, 03328, 03329, 03330, 03331, 03332, 03333, 03334, 03335, 03336, 03337, 03338, 03339, 03340, 03341,
|
||||
03342, 03343, 03344, 03345, 03346, 03347, 03348, 03349, 03350, 03351, 03352, 03353, 03354, 03355, 03356, 03357,
|
||||
03358, 03359, 03360, 03361, 03362, 03363, 03364, 03365, 03366, 03367, 03368, 03369, 03370, 03371, 03372, 03373,
|
||||
03374, 03377, 03378, 03379, 03380, 03381, 03382, 03383, 03384, 03385, 03386, 03387, 03388, 03389, 03390, 03391,
|
||||
03392, 03393, 03394, 03395, 03396, 03397, 03398, 03399, 03400, 03401, 03402, 03403, 03404, 03405, 03406, 03407,
|
||||
03408, 03409, 03425, 03426, 03427, 03428, 03429, 65535,
|
||||
};
|
||||
|
||||
/// <summary>
|
||||
/// Characters (Unicode representation)
|
||||
/// </summary>
|
||||
private static readonly ushort[] G4Chars =
|
||||
{
|
||||
12288, 12353, 12354, 12355, 12356, 12357, 12358, 12359, 12360, 12361, 12362, 12363, 12364, 12365, 12366, 12367,
|
||||
12368, 12369, 12370, 12371, 12372, 12373, 12374, 12375, 12376, 12377, 12378, 12379, 12380, 12381, 12382, 12383,
|
||||
12384, 12385, 12386, 12387, 12388, 12389, 12390, 12391, 12392, 12393, 12394, 12395, 12396, 12397, 12398, 12399,
|
||||
12400, 12401, 12402, 12403, 12404, 12405, 12406, 12407, 12408, 12409, 12410, 12411, 12412, 12413, 12414, 12415,
|
||||
12416, 12417, 12418, 12419, 12420, 12421, 12422, 12423, 12424, 12425, 12426, 12427, 12428, 12429, 12431, 12434,
|
||||
12435, 12449, 12450, 12451, 12452, 12453, 12454, 12455, 12456, 12457, 12458, 12459, 12460, 12461, 12462, 12463,
|
||||
12464, 12465, 12466, 12467, 12468, 12469, 12470, 12471, 12472, 12473, 12474, 12475, 12476, 12477, 12478, 12479,
|
||||
12480, 12481, 12482, 12483, 12484, 12485, 12486, 12487, 12488, 12489, 12490, 12491, 12492, 12493, 12494, 12495,
|
||||
12496, 12497, 12498, 12499, 12500, 12501, 12502, 12503, 12504, 12505, 12506, 12507, 12508, 12509, 12510, 12511,
|
||||
12512, 12513, 12514, 12515, 12516, 12517, 12518, 12519, 12520, 12521, 12522, 12523, 12524, 12525, 12527, 12530,
|
||||
12531, 65296, 65297, 65298, 65299, 65300, 65301, 65302, 65303, 65304, 65305, 65313, 65314, 65315, 65316, 65317,
|
||||
65318, 65319, 65320, 65321, 65322, 65323, 65324, 65325, 65326, 65327, 65328, 65329, 65330, 65331, 65332, 65333,
|
||||
65334, 65335, 65336, 65337, 65338, 65345, 65346, 65347, 65348, 65349, 65350, 65351, 65352, 65353, 65354, 65355,
|
||||
65356, 65357, 65358, 65359, 65360, 65361, 65362, 65363, 65364, 65365, 65366, 65367, 65368, 65369, 65370, 65281,
|
||||
65311, 12289, 12290, 08943, 12539, 65295, 12300, 12301, 12302, 12303, 65288, 65289, 09325, 09326, 65291, 12540,
|
||||
09319, 09320, 65309, 65374, 65306, 65307, 65294, 65292, 09824, 09827, 09829, 09830, 09733, 09678, 09675, 09633,
|
||||
09651, 09671, 65312, 09834, 65285, 09728, 09729, 09730, 09731, 09312, 09313, 09314, 09738, 09316, 09317, 09318,
|
||||
09800, 09801, 09802, 09803, 09804, 09805, 09806, 09807, 08592, 08593, 08595, 08594, 08227, 65286, 00048,
|
||||
00049, 00050, 00051, 00052, 00053, 00054, 00055, 00056, 00057, 00065, 00066, 00067, 00068, 00069, 00070, 00071,
|
||||
00072, 00073, 00074, 00075, 00076, 00077, 00078, 00079, 00080, 00081, 00082, 00083, 00084, 00085, 00086, 00087,
|
||||
00088, 00089, 00090, 00097, 00098, 00099, 00100, 00101, 00102, 00103, 00104, 00105, 00106, 00107, 00108, 00109,
|
||||
00110, 00111, 00112, 00113, 00114, 00115, 00116, 00117, 00118, 00119, 00120, 00121, 00122, 00192, 00193, 00194,
|
||||
00195, 00196, 00197, 00198, 00199, 00200, 00201, 00202, 00203, 00204, 00205, 00206, 00207, 00208, 00209, 00210,
|
||||
00211, 00212, 00213, 00214, 00215, 00216, 00217, 00218, 00219, 00220, 00221, 00222, 00223, 00224, 00225, 00226,
|
||||
00227, 00228, 00229, 00230, 00231, 00232, 00233, 00234, 00235, 00236, 00237, 00238, 00239, 00240, 00241, 00242,
|
||||
00243, 00244, 00245, 00246, 00247, 00248, 00249, 00250, 00251, 00252, 00253, 00254, 00255, 00338, 00339, 00350,
|
||||
00351, 00170, 00186, 00185, 00178, 00179, 00036, 00161, 00191, 00033, 00063, 00044, 00046, 09324, 65381, 00047,
|
||||
08216, 08217, 08220, 08221, 08222, 12298, 12299, 00040, 00041, 09794, 09792, 00043, 00045, 00042, 00035, 00061,
|
||||
00038, 00126, 00058, 00059, 09327, 09328, 09329, 09330, 09331, 09332, 09333, 09334, 09335, 09336, 00064, 09337,
|
||||
00037, 09338, 09339, 09340, 09341, 09342, 09343, 09344, 09345, 09346, 09347, 09348, 00032,
|
||||
44032, 44033, 44036, 44039, 44040, 44041, 44042, 44048, 44049, 44050, 44051, 44052, 44053,
|
||||
44054, 44055, 44057, 44058, 44059, 44060, 44061, 44064, 44068, 44076, 44077, 44079, 44080, 44081, 44088, 44089,
|
||||
44092, 44096, 44107, 44109, 44116, 44120, 44124, 44144, 44145, 44148, 44151, 44152, 44154, 44160, 44161, 44163,
|
||||
44164, 44165, 44166, 44169, 44170, 44171, 44172, 44176, 44180, 44188, 44189, 44191, 44192, 44193, 44200, 44201,
|
||||
44202, 44204, 44207, 44208, 44216, 44217, 44219, 44220, 44221, 44225, 44228, 44232, 44236, 44245, 44247, 44256,
|
||||
44257, 44260, 44263, 44264, 44266, 44268, 44271, 44272, 44273, 44275, 44277, 44278, 44284, 44285, 44288, 44292,
|
||||
44294, 44300, 44301, 44303, 44305, 44312, 44316, 44320, 44329, 44332, 44333, 44340, 44341, 44344, 44348, 44356,
|
||||
44357, 44359, 44361, 44368, 44372, 44376, 44385, 44387, 44396, 44397, 44400, 44403, 44404, 44405, 44406, 44411,
|
||||
44412, 44413, 44415, 44417, 44418, 44424, 44425, 44428, 44432, 44444, 44445, 44452, 44471, 44480, 44481, 44484,
|
||||
44488, 44496, 44497, 44499, 44508, 44512, 44516, 44536, 44537, 44540, 44543, 44544, 44545, 44552, 44553, 44555,
|
||||
44557, 44564, 44592, 44593, 44596, 44599, 44600, 44602, 44608, 44609, 44611, 44613, 44614, 44618, 44620, 44621,
|
||||
44622, 44624, 44628, 44630, 44636, 44637, 44639, 44640, 44641, 44645, 44648, 44649, 44652, 44656, 44664, 44665,
|
||||
44667, 44668, 44669, 44676, 44677, 44684, 44732, 44733, 44734, 44736, 44740, 44748, 44749, 44751, 44752, 44753,
|
||||
44760, 44761, 44764, 44776, 44779, 44781, 44788, 44792, 44796, 44807, 44808, 44813, 44816, 44844, 44845, 44848,
|
||||
44850, 44852, 44860, 44861, 44863, 44865, 44866, 44867, 44872, 44873, 44880, 44892, 44893, 44900, 44901, 44921,
|
||||
44928, 44932, 44936, 44944, 44945, 44949, 44956, 44984, 44985, 44988, 44992, 44999, 45000, 45001, 45003, 45005,
|
||||
45006, 45012, 45020, 45032, 45033, 45040, 45041, 45044, 45048, 45056, 45057, 45060, 45068, 45072, 45076, 45084,
|
||||
45085, 45096, 45124, 45125, 45128, 45130, 45132, 45134, 45139, 45140, 45141, 45143, 45145, 45149, 45180, 45181,
|
||||
45184, 45188, 45196, 45197, 45199, 45201, 45208, 45209, 45210, 45212, 45215, 45216, 45217, 45218, 45224, 45225,
|
||||
45227, 45228, 45229, 45230, 45231, 45233, 45235, 45236, 45237, 45240, 45244, 45252, 45253, 45255, 45256, 45257,
|
||||
45264, 45265, 45268, 45272, 45280, 45285, 45320, 45321, 45323, 45324, 45328, 45330, 45331, 45336, 45337, 45339,
|
||||
45340, 45341, 45347, 45348, 45349, 45352, 45356, 45364, 45365, 45367, 45368, 45369, 45376, 45377, 45380, 45384,
|
||||
45392, 45393, 45396, 45397, 45400, 45404, 45408, 45432, 45433, 45436, 45440, 45442, 45448, 45449, 45451, 45453,
|
||||
45458, 45459, 45460, 45464, 45468, 45480, 45516, 45520, 45524, 45532, 45533, 45535, 45544, 45545, 45548, 45552,
|
||||
45561, 45563, 45565, 45572, 45573, 45576, 45579, 45580, 45588, 45589, 45591, 45593, 45600, 45620, 45628, 45656,
|
||||
45660, 45664, 45672, 45673, 45684, 45685, 45692, 45700, 45701, 45705, 45712, 45713, 45716, 45720, 45721, 45722,
|
||||
45728, 45729, 45731, 45733, 45734, 45738, 45740, 45744, 45748, 45768, 45769, 45772, 45776, 45778, 45784, 45785,
|
||||
45787, 45789, 45794, 45796, 45797, 45798, 45800, 45803, 45804, 45805, 45806, 45807, 45811, 45812, 45813, 45815,
|
||||
45816, 45817, 45818, 45819, 45823, 45824, 45825, 45828, 45832, 45840, 45841, 45843, 45844, 45845, 45852, 45908,
|
||||
45909, 45910, 45912, 45915, 45916, 45918, 45919, 45924, 45925, 45927, 45929, 45931, 45934, 45936, 45937, 45940,
|
||||
45944, 45952, 45953, 45955, 45956, 45957, 45964, 45968, 45972, 45984, 45985, 45992, 45996, 46020, 46021, 46024,
|
||||
46027, 46028, 46030, 46032, 46036, 46037, 46039, 46041, 46043, 46045, 46048, 46052, 46056, 46076, 46096, 46104,
|
||||
46108, 46112, 46120, 46121, 46123, 46132, 46160, 46161, 46164, 46168, 46176, 46177, 46179, 46181, 46188, 46208,
|
||||
46216, 46237, 46244, 46248, 46252, 46261, 46263, 46265, 46272, 46276, 46280, 46288, 46293, 46300, 46301, 46304,
|
||||
46307, 46308, 46310, 46316, 46317, 46319, 46321, 46328, 46356, 46357, 46360, 46363, 46364, 46372, 46373, 46375,
|
||||
46376, 46377, 46378, 46384, 46385, 46388, 46392, 46400, 46401, 46403, 46404, 46405, 46411, 46412, 46413, 46416,
|
||||
46420, 46428, 46429, 46431, 46432, 46433, 46496, 46497, 46500, 46504, 46506, 46507, 46512, 46513, 46515, 46516,
|
||||
46517, 46523, 46524, 46525, 46528, 46532, 46540, 46541, 46543, 46544, 46545, 46552, 46572, 46608, 46609, 46612,
|
||||
46616, 46629, 46636, 46644, 46664, 46692, 46696, 46748, 46749, 46752, 46756, 46763, 46764, 46769, 46804, 46832,
|
||||
46836, 46840, 46848, 46849, 46853, 46888, 46889, 46892, 46895, 46896, 46904, 46905, 46907, 46916, 46920, 46924,
|
||||
46932, 46933, 46944, 46948, 46952, 46960, 46961, 46963, 46965, 46972, 46973, 46976, 46980, 46988, 46989, 46991,
|
||||
46992, 46993, 46994, 46998, 46999, 47000, 47001, 47004, 47008, 47016, 47017, 47019, 47020, 47021, 47028, 47029,
|
||||
47032, 47047, 47049, 47084, 47085, 47088, 47092, 47100, 47101, 47103, 47104, 47105, 47111, 47112, 47113, 47116,
|
||||
47120, 47128, 47129, 47131, 47133, 47140, 47141, 47144, 47148, 47156, 47157, 47159, 47160, 47161, 47168, 47172,
|
||||
47185, 47187, 47196, 47197, 47200, 47204, 47212, 47213, 47215, 47217, 47224, 47228, 47245, 47272, 47280, 47284,
|
||||
47288, 47296, 47297, 47299, 47301, 47308, 47312, 47316, 47325, 47327, 47329, 47336, 47337, 47340, 47344, 47352,
|
||||
47353, 47355, 47357, 47364, 47384, 47392, 47420, 47421, 47424, 47428, 47436, 47439, 47441, 47448, 47449, 47452,
|
||||
47456, 47464, 47465, 47467, 47469, 47476, 47477, 47480, 47484, 47492, 47493, 47495, 47497, 47498, 47501, 47502,
|
||||
47532, 47533, 47536, 47540, 47548, 47549, 47551, 47553, 47560, 47561, 47564, 47566, 47567, 47568, 47569, 47570,
|
||||
47576, 47577, 47579, 47581, 47582, 47585, 47587, 47588, 47589, 47592, 47596, 47604, 47605, 47607, 47608, 47609,
|
||||
47610, 47616, 47617, 47624, 47637, 47672, 47673, 47676, 47680, 47682, 47688, 47689, 47691, 47693, 47694, 47699,
|
||||
47700, 47701, 47704, 47708, 47716, 47717, 47719, 47720, 47721, 47728, 47729, 47732, 47736, 47747, 47748, 47749,
|
||||
47751, 47756, 47784, 47785, 47787, 47788, 47792, 47794, 47800, 47801, 47803, 47805, 47812, 47816, 47832, 47833,
|
||||
47868, 47872, 47876, 47885, 47887, 47889, 47896, 47900, 47904, 47913, 47915, 47924, 47925, 47926, 47928, 47931,
|
||||
47932, 47933, 47934, 47940, 47941, 47943, 47945, 47949, 47951, 47952, 47956, 47960, 47969, 47971, 47980, 48008,
|
||||
48012, 48016, 48036, 48040, 48044, 48052, 48055, 48064, 48068, 48072, 48080, 48083, 48120, 48121, 48124, 48127,
|
||||
48128, 48130, 48136, 48137, 48139, 48140, 48141, 48143, 48145, 48148, 48149, 48150, 48151, 48152, 48155, 48156,
|
||||
48157, 48158, 48159, 48164, 48165, 48167, 48169, 48173, 48176, 48177, 48180, 48184, 48192, 48193, 48195, 48196,
|
||||
48197, 48201, 48204, 48205, 48208, 48221, 48260, 48261, 48264, 48267, 48268, 48270, 48276, 48277, 48279, 48281,
|
||||
48282, 48288, 48289, 48292, 48295, 48296, 48304, 48305, 48307, 48308, 48309, 48316, 48317, 48320, 48324, 48333,
|
||||
48335, 48336, 48337, 48341, 48344, 48348, 48372, 48373, 48374, 48376, 48380, 48388, 48389, 48391, 48393, 48400,
|
||||
48404, 48420, 48428, 48448, 48456, 48457, 48460, 48464, 48472, 48473, 48484, 48488, 48512, 48513, 48516, 48519,
|
||||
48520, 48521, 48522, 48528, 48529, 48531, 48533, 48537, 48538, 48540, 48548, 48560, 48568, 48596, 48597, 48600,
|
||||
48604, 48617, 48624, 48628, 48632, 48640, 48643, 48645, 48652, 48653, 48656, 48660, 48668, 48669, 48671, 48708,
|
||||
48709, 48712, 48716, 48718, 48724, 48725, 48727, 48729, 48730, 48731, 48736, 48737, 48740, 48744, 48746, 48752,
|
||||
48753, 48755, 48756, 48757, 48763, 48764, 48765, 48768, 48772, 48780, 48781, 48783, 48784, 48785, 48792, 48793,
|
||||
48808, 48848, 48849, 48852, 48855, 48856, 48864, 48867, 48868, 48869, 48876, 48897, 48904, 48905, 48920, 48921,
|
||||
48923, 48924, 48925, 48960, 48961, 48964, 48968, 48976, 48977, 48981, 49044, 49072, 49093, 49100, 49101, 49104,
|
||||
49108, 49116, 49119, 49121, 49212, 49233, 49240, 49244, 49248, 49256, 49257, 49296, 49297, 49300, 49304, 49312,
|
||||
49313, 49315, 49317, 49324, 49325, 49327, 49328, 49331, 49332, 49333, 49334, 49340, 49341, 49343, 49344, 49345,
|
||||
49349, 49352, 49353, 49356, 49360, 49368, 49369, 49371, 49372, 49373, 49380, 49381, 49384, 49388, 49396, 49397,
|
||||
49399, 49401, 49408, 49412, 49416, 49424, 49429, 49436, 49437, 49438, 49439, 49440, 49443, 49444, 49446, 49447,
|
||||
49452, 49453, 49455, 49456, 49457, 49462, 49464, 49465, 49468, 49472, 49480, 49481, 49483, 49484, 49485, 49492,
|
||||
49493, 49496, 49500, 49508, 49509, 49511, 49512, 49513, 49520, 49524, 49528, 49541, 49548, 49549, 49550, 49552,
|
||||
49556, 49558, 49564, 49565, 49567, 49569, 49573, 49576, 49577, 49580, 49584, 49597, 49604, 49608, 49612, 49620,
|
||||
49623, 49624, 49632, 49636, 49640, 49648, 49649, 49651, 49660, 49661, 49664, 49668, 49676, 49677, 49679, 49681,
|
||||
49688, 49689, 49692, 49695, 49696, 49704, 49705, 49707, 49709, 49711, 49713, 49714, 49716, 49736, 49744, 49745,
|
||||
49748, 49752, 49760, 49765, 49772, 49773, 49776, 49780, 49788, 49789, 49791, 49793, 49800, 49801, 49808, 49816,
|
||||
49819, 49821, 49828, 49829, 49832, 49836, 49837, 49844, 49845, 49847, 49849, 49884, 49885, 49888, 49891, 49892,
|
||||
49899, 49900, 49901, 49903, 49905, 49910, 49912, 49913, 49915, 49916, 49920, 49928, 49929, 49932, 49933, 49939,
|
||||
49940, 49941, 49944, 49948, 49956, 49957, 49960, 49961, 49989, 50024, 50025, 50028, 50032, 50034, 50040, 50041,
|
||||
50044, 50045, 50052, 50056, 50060, 50112, 50136, 50137, 50140, 50143, 50144, 50146, 50152, 50153, 50157, 50164,
|
||||
50165, 50168, 50184, 50192, 50212, 50220, 50224, 50228, 50236, 50237, 50248, 50276, 50277, 50280, 50284, 50292,
|
||||
50293, 50297, 50304, 50324, 50332, 50360, 50364, 50409, 50416, 50417, 50420, 50424, 50426, 50431, 50432, 50433,
|
||||
50444, 50448, 50452, 50460, 50472, 50473, 50476, 50480, 50488, 50489, 50491, 50493, 50500, 50501, 50504, 50505,
|
||||
50506, 50508, 50509, 50510, 50515, 50516, 50517, 50519, 50520, 50521, 50525, 50526, 50528, 50529, 50532, 50536,
|
||||
50544, 50545, 50547, 50548, 50549, 50556, 50557, 50560, 50564, 50567, 50572, 50573, 50575, 50577, 50581, 50583,
|
||||
50584, 50588, 50592, 50601, 50612, 50613, 50616, 50617, 50619, 50620, 50621, 50622, 50628, 50629, 50630, 50631,
|
||||
50632, 50633, 50634, 50636, 50638, 50640, 50641, 50644, 50648, 50656, 50657, 50659, 50661, 50668, 50669, 50670,
|
||||
50672, 50676, 50678, 50679, 50684, 50685, 50686, 50687, 50688, 50689, 50693, 50694, 50695, 50696, 50700, 50704,
|
||||
50712, 50713, 50715, 50716, 50724, 50725, 50728, 50732, 50733, 50734, 50736, 50739, 50740, 50741, 50743, 50745,
|
||||
50747, 50752, 50753, 50756, 50760, 50768, 50769, 50771, 50772, 50773, 50780, 50781, 50784, 50796, 50799, 50801,
|
||||
50808, 50809, 50812, 50816, 50824, 50825, 50827, 50829, 50836, 50837, 50840, 50844, 50852, 50853, 50855, 50857,
|
||||
50864, 50865, 50868, 50872, 50873, 50874, 50880, 50881, 50883, 50885, 50892, 50893, 50896, 50900, 50908, 50909,
|
||||
50912, 50913, 50920, 50921, 50924, 50928, 50936, 50937, 50941, 50948, 50949, 50952, 50956, 50964, 50965, 50967,
|
||||
50969, 50976, 50977, 50980, 50984, 50992, 50993, 50995, 50997, 50999, 51004, 51005, 51008, 51012, 51018, 51020,
|
||||
51021, 51023, 51025, 51026, 51027, 51028, 51029, 51030, 51031, 51032, 51036, 51040, 51048, 51051, 51060, 51061,
|
||||
51064, 51068, 51069, 51070, 51075, 51076, 51077, 51079, 51080, 51081, 51082, 51086, 51088, 51089, 51092, 51094,
|
||||
51095, 51096, 51098, 51104, 51105, 51107, 51108, 51109, 51110, 51116, 51117, 51120, 51124, 51132, 51133, 51135,
|
||||
51136, 51137, 51144, 51145, 51148, 51150, 51152, 51160, 51165, 51172, 51176, 51180, 51200, 51201, 51204, 51208,
|
||||
51210, 51216, 51217, 51219, 51221, 51222, 51228, 51229, 51232, 51236, 51244, 51245, 51247, 51249, 51256, 51260,
|
||||
51264, 51272, 51273, 51276, 51277, 51284, 51312, 51313, 51316, 51320, 51322, 51328, 51329, 51331, 51333, 51334,
|
||||
51335, 51339, 51340, 51341, 51348, 51357, 51359, 51361, 51368, 51388, 51389, 51396, 51400, 51404, 51412, 51413,
|
||||
51415, 51417, 51424, 51425, 51428, 51445, 51452, 51453, 51456, 51460, 51461, 51462, 51468, 51469, 51471, 51473,
|
||||
51480, 51500, 51508, 51536, 51537, 51540, 51544, 51552, 51553, 51555, 51564, 51568, 51572, 51580, 51592, 51593,
|
||||
51596, 51600, 51608, 51609, 51611, 51613, 51648, 51649, 51652, 51655, 51656, 51658, 51664, 51665, 51667, 51669,
|
||||
51670, 51673, 51674, 51676, 51677, 51680, 51682, 51684, 51687, 51692, 51693, 51695, 51696, 51697, 51704, 51705,
|
||||
51708, 51712, 51720, 51721, 51723, 51724, 51725, 51732, 51736, 51753, 51788, 51789, 51792, 51796, 51804, 51805,
|
||||
51807, 51808, 51809, 51816, 51837, 51844, 51864, 51900, 51901, 51904, 51908, 51916, 51917, 51919, 51921, 51923,
|
||||
51928, 51929, 51936, 51948, 51956, 51976, 51984, 51988, 51992, 52000, 52001, 52033, 52040, 52041, 52044, 52048,
|
||||
52056, 52057, 52061, 52068, 52088, 52089, 52124, 52152, 52180, 52196, 52199, 52201, 52236, 52237, 52240, 52244,
|
||||
52252, 52253, 52257, 52258, 52263, 52264, 52265, 52268, 52270, 52272, 52280, 52281, 52283, 52284, 52285, 52286,
|
||||
52292, 52293, 52296, 52300, 52308, 52309, 52311, 52312, 52313, 52320, 52324, 52326, 52328, 52336, 52341, 52376,
|
||||
52377, 52380, 52384, 52392, 52393, 52395, 52396, 52397, 52404, 52405, 52408, 52412, 52420, 52421, 52423, 52425,
|
||||
52432, 52436, 52452, 52460, 52464, 52481, 52488, 52489, 52492, 52496, 52504, 52505, 52507, 52509, 52516, 52520,
|
||||
52524, 52537, 52572, 52576, 52580, 52588, 52589, 52591, 52593, 52600, 52616, 52628, 52629, 52632, 52636, 52644,
|
||||
52645, 52647, 52649, 52656, 52676, 52684, 52688, 52712, 52716, 52720, 52728, 52729, 52731, 52733, 52740, 52744,
|
||||
52748, 52756, 52761, 52768, 52769, 52772, 52776, 52784, 52785, 52787, 52789, 52824, 52825, 52828, 52831, 52832,
|
||||
52833, 52840, 52841, 52843, 52845, 52852, 52853, 52856, 52860, 52868, 52869, 52871, 52873, 52880, 52881, 52884,
|
||||
52888, 52896, 52897, 52899, 52900, 52901, 52908, 52909, 52929, 52964, 52965, 52968, 52971, 52972, 52980, 52981,
|
||||
52983, 52984, 52985, 52992, 52993, 52996, 53000, 53008, 53009, 53011, 53013, 53020, 53024, 53028, 53036, 53037,
|
||||
53039, 53040, 53041, 53048, 53076, 53077, 53080, 53084, 53092, 53093, 53095, 53097, 53104, 53105, 53108, 53112,
|
||||
53120, 53125, 53132, 53153, 53160, 53168, 53188, 53216, 53217, 53220, 53224, 53232, 53233, 53235, 53237, 53244,
|
||||
53248, 53252, 53265, 53272, 53293, 53300, 53301, 53304, 53308, 53316, 53317, 53319, 53321, 53328, 53332, 53336,
|
||||
53344, 53356, 53357, 53360, 53364, 53372, 53373, 53377, 53412, 53413, 53416, 53420, 53428, 53429, 53431, 53433,
|
||||
53440, 53441, 53444, 53448, 53449, 53456, 53457, 53459, 53460, 53461, 53468, 53469, 53472, 53476, 53484, 53485,
|
||||
53487, 53488, 53489, 53496, 53517, 53552, 53553, 53556, 53560, 53562, 53568, 53569, 53571, 53572, 53573, 53580,
|
||||
53581, 53584, 53588, 53596, 53597, 53599, 53601, 53608, 53612, 53628, 53636, 53640, 53664, 53665, 53668, 53672,
|
||||
53680, 53681, 53683, 53685, 53690, 53692, 53696, 53720, 53748, 53752, 53767, 53769, 53776, 53804, 53805, 53808,
|
||||
53812, 53820, 53821, 53823, 53825, 53832, 53852, 53860, 53888, 53889, 53892, 53896, 53904, 53905, 53909, 53916,
|
||||
53920, 53924, 53932, 53937, 53944, 53945, 53948, 53951, 53952, 53954, 53960, 53961, 53963, 53972, 53976, 53980,
|
||||
53988, 53989, 54000, 54001, 54004, 54008, 54016, 54017, 54019, 54021, 54028, 54029, 54030, 54032, 54036, 54038,
|
||||
54044, 54045, 54047, 54048, 54049, 54053, 54056, 54057, 54060, 54064, 54072, 54073, 54075, 54076, 54077, 54084,
|
||||
54085, 54140, 54141, 54144, 54148, 54156, 54157, 54159, 54160, 54161, 54168, 54169, 54172, 54176, 54184, 54185,
|
||||
54187, 54189, 54196, 54200, 54204, 54212, 54213, 54216, 54217, 54224, 54232, 54241, 54243, 54252, 54253, 54256,
|
||||
54260, 54268, 54269, 54271, 54273, 54280, 54301, 54336, 54340, 54364, 54368, 54372, 54381, 54383, 54392, 54393,
|
||||
54396, 54399, 54400, 54402, 54408, 54409, 54411, 54413, 54420, 54441, 54476, 54480, 54484, 54492, 54495, 54504,
|
||||
54508, 54512, 54520, 54523, 54525, 54532, 54536, 54540, 54548, 54549, 54551, 54588, 54589, 54592, 54596, 54604,
|
||||
54605, 54607, 54609, 54616, 54617, 54620, 54624, 54629, 54632, 54633, 54635, 54637, 54644, 54645, 54648, 54652,
|
||||
54660, 54661, 54663, 54664, 54665, 54672, 54693, 54728, 54729, 54732, 54736, 54738, 54744, 54745, 54747, 54749,
|
||||
54756, 54757, 54760, 54764, 54772, 54773, 54775, 54777, 54784, 54785, 54788, 54792, 54800, 54801, 54803, 54804,
|
||||
54805, 54812, 54816, 54820, 54829, 54840, 54841, 54844, 54848, 54853, 54856, 54857, 54859, 54861, 54865, 54868,
|
||||
54869, 54872, 54876, 54887, 54889, 54896, 54897, 54900, 54915, 54917, 54924, 54925, 54928, 54932, 54941, 54943,
|
||||
54945, 54952, 54956, 54960, 54969, 54971, 54980, 54981, 54984, 54988, 54993, 54996, 54999, 55001, 55008, 55012,
|
||||
55016, 55024, 55029, 55036, 55037, 55040, 55044, 55057, 55064, 55065, 55068, 55072, 55080, 55081, 55083, 55085,
|
||||
55092, 55093, 55096, 55100, 55108, 55111, 55113, 55120, 55121, 55124, 55126, 55127, 55128, 55129, 55136, 55137,
|
||||
55139, 55141, 55145, 55148, 55152, 55156, 55164, 55165, 55169, 55176, 55177, 55180, 55184, 55192, 55193, 55195,
|
||||
55197, 04352, 04353, 04354, 04355, 04356, 04357, 04358, 04359, 04360, 04361, 04362, 04363, 04364, 04365, 04366,
|
||||
04367, 04368, 04369, 04370, 04449, 04450, 04451, 04452, 04453, 04454, 04455, 04456, 04457, 04461, 04462, 04466,
|
||||
04467, 04469, 47252, 49968, 50108, 50388, 52012, 65535,
|
||||
};
|
||||
|
||||
private static readonly Dictionary<ushort, int> G4ValueId = G4Values
|
||||
.Select((value, index) => new KeyValuePair<ushort, int>(value, index))
|
||||
.ToDictionary(pair => pair.Key, pair => pair.Value);
|
||||
|
||||
private static readonly Dictionary<ushort, int> G4CharId = G4Chars
|
||||
.Select((value, index) => new KeyValuePair<ushort, int>(value, index))
|
||||
.ToDictionary(pair => pair.Key, pair => pair.Value);
|
||||
|
||||
#endregion
|
||||
}
|
63
PKHeX.Core/PKM/Strings/StringConverter5.cs
Normal file
63
PKHeX.Core/PKM/Strings/StringConverter5.cs
Normal file
|
@ -0,0 +1,63 @@
|
|||
using System;
|
||||
using static System.Buffers.Binary.BinaryPrimitives;
|
||||
|
||||
namespace PKHeX.Core;
|
||||
|
||||
public static class StringConverter5
|
||||
{
|
||||
private const char TerminatorFFFF = (char)0xFFFF;
|
||||
|
||||
/// <summary>Converts Generation 5 encoded data to decoded string.</summary>
|
||||
/// <param name="data">Encoded data</param>
|
||||
/// <returns>Decoded string.</returns>
|
||||
public static string GetString(ReadOnlySpan<byte> data)
|
||||
{
|
||||
Span<char> result = stackalloc char[data.Length];
|
||||
int length = LoadString(data, result);
|
||||
return new string(result[..length].ToArray());
|
||||
}
|
||||
|
||||
private static int LoadString(ReadOnlySpan<byte> data, Span<char> result)
|
||||
{
|
||||
int i = 0;
|
||||
for (; i < data.Length; i += 2)
|
||||
{
|
||||
var value = ReadUInt16LittleEndian(data[i..]);
|
||||
if (value == TerminatorFFFF)
|
||||
break;
|
||||
result[i/2] = StringConverter.SanitizeChar((char)value);
|
||||
}
|
||||
return i/2;
|
||||
}
|
||||
|
||||
/// <summary>Gets the bytes for a Generation 5 string.</summary>
|
||||
/// <param name="destBuffer"></param>
|
||||
/// <param name="value">Decoded string.</param>
|
||||
/// <param name="maxLength">Maximum length of the input <see cref="value"/></param>
|
||||
/// <param name="option"></param>
|
||||
/// <returns>Encoded data.</returns>
|
||||
public static int SetString(Span<byte> destBuffer, ReadOnlySpan<char> value, int maxLength,
|
||||
StringConverterOption option = StringConverterOption.ClearZero)
|
||||
{
|
||||
if (value.Length > maxLength)
|
||||
value = value[..maxLength]; // Hard cap
|
||||
|
||||
if (option is StringConverterOption.ClearZero)
|
||||
destBuffer.Clear();
|
||||
else if (option is StringConverterOption.ClearFF)
|
||||
destBuffer.Fill(0xFF);
|
||||
|
||||
for (int i = 0; i < value.Length; i++)
|
||||
{
|
||||
char c = value[i];
|
||||
ushort val = StringConverter.UnSanitizeChar5(c);
|
||||
WriteUInt16LittleEndian(destBuffer[(i * 2)..], val);
|
||||
}
|
||||
|
||||
int count = value.Length * 2;
|
||||
if (count == destBuffer.Length)
|
||||
return count;
|
||||
WriteUInt16LittleEndian(destBuffer[count..], TerminatorFFFF);
|
||||
return count + 2;
|
||||
}
|
||||
}
|
63
PKHeX.Core/PKM/Strings/StringConverter6.cs
Normal file
63
PKHeX.Core/PKM/Strings/StringConverter6.cs
Normal file
|
@ -0,0 +1,63 @@
|
|||
using System;
|
||||
using static System.Buffers.Binary.BinaryPrimitives;
|
||||
|
||||
namespace PKHeX.Core;
|
||||
|
||||
public static class StringConverter6
|
||||
{
|
||||
private const ushort TerminatorNull = 0;
|
||||
|
||||
/// <summary>Converts Generation 6 encoded data to decoded string.</summary>
|
||||
/// <param name="data">Encoded data</param>
|
||||
/// <returns>Decoded string.</returns>
|
||||
public static string GetString(ReadOnlySpan<byte> data)
|
||||
{
|
||||
Span<char> result = stackalloc char[data.Length];
|
||||
int length = LoadString(data, result);
|
||||
return new string(result[..length].ToArray());
|
||||
}
|
||||
|
||||
private static int LoadString(ReadOnlySpan<byte> data, Span<char> result)
|
||||
{
|
||||
int i = 0;
|
||||
for (; i < data.Length; i += 2)
|
||||
{
|
||||
var value = ReadUInt16LittleEndian(data[i..]);
|
||||
if (value == TerminatorNull)
|
||||
break;
|
||||
result[i/2] = StringConverter.SanitizeChar((char)value);
|
||||
}
|
||||
return i/2;
|
||||
}
|
||||
|
||||
/// <summary>Gets the bytes for a Generation 6 string.</summary>
|
||||
/// <param name="destBuffer"></param>
|
||||
/// <param name="value">Decoded string.</param>
|
||||
/// <param name="maxLength">Maximum length of the input <see cref="value"/></param>
|
||||
/// <param name="option"></param>
|
||||
/// <returns>Encoded data.</returns>
|
||||
public static int SetString(Span<byte> destBuffer, ReadOnlySpan<char> value, int maxLength,
|
||||
StringConverterOption option = StringConverterOption.ClearZero)
|
||||
{
|
||||
if (value.Length > maxLength)
|
||||
value = value[..maxLength]; // Hard cap
|
||||
|
||||
if (option is StringConverterOption.ClearZero)
|
||||
destBuffer.Clear();
|
||||
|
||||
bool isFullWidth = StringConverter.GetIsFullWidthString(value);
|
||||
for (int i = 0; i < value.Length; i++)
|
||||
{
|
||||
char c = value[i];
|
||||
if (!isFullWidth)
|
||||
c = StringConverter.UnSanitizeChar(c);
|
||||
WriteUInt16LittleEndian(destBuffer[(i * 2)..], c);
|
||||
}
|
||||
|
||||
int count = value.Length * 2;
|
||||
if (count == destBuffer.Length)
|
||||
return count;
|
||||
WriteUInt16LittleEndian(destBuffer[count..], TerminatorNull);
|
||||
return count + 2;
|
||||
}
|
||||
}
|
71
PKHeX.Core/PKM/Strings/StringConverter7.cs
Normal file
71
PKHeX.Core/PKM/Strings/StringConverter7.cs
Normal file
|
@ -0,0 +1,71 @@
|
|||
using System;
|
||||
using static System.Buffers.Binary.BinaryPrimitives;
|
||||
|
||||
namespace PKHeX.Core;
|
||||
|
||||
public static class StringConverter7
|
||||
{
|
||||
private const ushort TerminatorNull = 0;
|
||||
|
||||
/// <summary>Converts Generation 7 encoded data to decoded string.</summary>
|
||||
/// <param name="data">Encoded data</param>
|
||||
/// <returns>Decoded string.</returns>
|
||||
public static string GetString(ReadOnlySpan<byte> data)
|
||||
{
|
||||
Span<char> result = stackalloc char[data.Length];
|
||||
int length = LoadString(data, result);
|
||||
return new string(result[..length].ToArray());
|
||||
}
|
||||
|
||||
private static int LoadString(ReadOnlySpan<byte> data, Span<char> result)
|
||||
{
|
||||
int i = 0;
|
||||
for (; i < data.Length; i += 2)
|
||||
{
|
||||
var value = ReadUInt16LittleEndian(data[i..]);
|
||||
if (value == TerminatorNull)
|
||||
break;
|
||||
result[i/2] = StringConverter.SanitizeChar((char)value);
|
||||
}
|
||||
|
||||
var span = result[..(i/2)];
|
||||
StringConverter7ZH.RemapChineseGlyphsBin2String(span);
|
||||
return i/2;
|
||||
}
|
||||
|
||||
/// <summary>Gets the bytes for a Generation 7 string.</summary>
|
||||
/// <param name="destBuffer"></param>
|
||||
/// <param name="value">Decoded string.</param>
|
||||
/// <param name="maxLength">Maximum length of the input <see cref="value"/></param>
|
||||
/// <param name="language">Language specific conversion (Chinese)</param>
|
||||
/// <param name="option"></param>
|
||||
/// <param name="chinese">Chinese string remapping should be attempted</param>
|
||||
/// <returns>Encoded data.</returns>
|
||||
public static int SetString(Span<byte> destBuffer, ReadOnlySpan<char> value, int maxLength, int language,
|
||||
StringConverterOption option = StringConverterOption.ClearZero, bool chinese = false)
|
||||
{
|
||||
if (value.Length > maxLength)
|
||||
value = value[..maxLength]; // Hard cap
|
||||
|
||||
if (option is StringConverterOption.ClearZero)
|
||||
destBuffer.Clear();
|
||||
|
||||
bool trad = StringConverter7ZH.IsTraditional(value, language);
|
||||
bool isFullWidth = StringConverter.GetIsFullWidthString(value);
|
||||
for (int i = 0; i < value.Length; i++)
|
||||
{
|
||||
char c = value[i];
|
||||
if (!isFullWidth)
|
||||
c = StringConverter.UnSanitizeChar(c);
|
||||
if (chinese)
|
||||
c = StringConverter7ZH.ConvertString2BinG7_zh(c, trad);
|
||||
WriteUInt16LittleEndian(destBuffer[(i * 2)..], c);
|
||||
}
|
||||
|
||||
int count = value.Length * 2;
|
||||
if (count == destBuffer.Length)
|
||||
return count;
|
||||
WriteUInt16LittleEndian(destBuffer[count..], TerminatorNull);
|
||||
return count + 2;
|
||||
}
|
||||
}
|
|
@ -1,103 +1,96 @@
|
|||
using System.Collections.Generic;
|
||||
using System.Text;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace PKHeX.Core
|
||||
namespace PKHeX.Core;
|
||||
|
||||
/// <summary>
|
||||
/// Logic for remapping reserved Chinese characters to and from Unicode, used by Generation 7 3DS games.
|
||||
/// </summary>
|
||||
public static class StringConverter7ZH
|
||||
{
|
||||
/// <summary>
|
||||
/// Logic for remapping reserved Chinese characters to and from Unicode, used by Generation 7 3DS games.
|
||||
/// </summary>
|
||||
public static class StringConverter7ZH
|
||||
// To accommodate for Chinese characters in Generation 7 3DS games, GameFreak has allocated a list of used ones in the unused 0xE800 region.
|
||||
// Why? Dunno, cuz Unicode has these already.
|
||||
// Maybe they wanted a quick way to sanity check Chinese strings, only allowing within the 0xE800 range.
|
||||
#region Gen 7 Chinese Character Tables
|
||||
public const string Gen7_ZHRaw = "蛋妙蛙种子草花小火龙恐喷杰尼龟卡咪水箭绿毛虫铁甲蛹巴大蝶独角壳针蜂波比鸟拉达烈雀嘴阿柏蛇怪皮丘雷穿山鼠王多兰娜后朗力诺可西六尾九胖丁超音蝠走路臭霸派斯特球摩鲁蛾地三喵猫老鸭哥猴暴蒂狗风速蚊香蝌蚪君泳士凯勇基胡腕豪喇叭芽口呆食玛瑙母毒刺拳石隆岩马焰兽磁合一葱嘟利海狮白泥舌贝鬼通耿催眠貘引梦人钳蟹巨霹雳电顽弹椰树嘎啦飞腿郎快头瓦双犀牛钻吉蔓藤袋墨金鱼星宝魔墙偶天螳螂迷唇姐击罗肯泰鲤普百变伊布边菊化盔镰刀翼急冻闪你哈克幻叶月桂竺葵锯鳄蓝立咕夜鹰芭瓢安圆丝蛛叉字灯笼古然咩羊茸美丽露才皇毽棉长手向日蜻蜓乌沼太阳亮黑暗鸦妖未知图腾果翁麒麟奇榛佛托土弟蝎钢千壶赫狃熊圈熔蜗猪珊瑚炮章桶信使翅戴加象顿Ⅱ惊鹿犬无畏战舞娃奶罐幸福公炎帝幼沙班洛亚凤时木守宫森林蜥蜴稚鸡壮跃狼纹直冲茧狩猎盾粉莲童帽乐河橡实鼻狡猾傲骨燕鸥莉奈朵溜糖雨蘑菇斗笠懒獭过动猿请假居忍面者脱妞吼爆幕下掌朝北优雅勾魂眼那恰姆落正拍负萤甜蔷薇溶吞牙鲨鲸驼煤炭跳噗晃斑颚蚁漠仙歌青绵七夕鼬斩饭匙鳅鲶虾兵螯秤念触摇篮羽丑纳飘浮泡隐怨影诅咒巡灵彷徨热带铃勃梭雪冰护豹珍珠樱空棘爱心哑属艾欧盖固坐祈代希苗台猛曼拿儿狸法师箱蟀勒伦琴含羞苞槌城结贵妇绅蜜女帕兹潜兔随卷耳魅东施铛响坦铜镜钟盆聒噪陆尖咬不良骷荧光霓虹自舔狂远Z由卢席恩骑色霏莱谢米尔宙提主暖炒武刃丸剑探步哨约扒酷冷蚀豆鸽高雉幔庞滚蝙螺钉差搬运匠修建蟾蜍投摔打包保足蜈蚣车轮精根裙野蛮鲈混流氓红倒狒殿滑巾征哭具死神棺原肋始祖破灰尘索沫栗德单卵细胞造鹅倍四季萌哎呀败轻蜘坚齿组麻鳗宇烛幽晶斧嚏几何敏捷功夫父赤驹劈司令炸雄秃丫首恶燃烧毕云酋迪耶塔赛里狐呱贺掘彩蓓洁能鞘芳芙妮好鱿贼脚铠垃藻臂枪伞咚碎黏钥朽南瓜嗡哲裴格枭狙射炽咆哮虎漾壬笃啄铳少强锹农胜虻鬃弱坏驴仔重挽滴伪睡罩盗着竹疗环智挥猩掷胆噬堡爷参性:银伴陨枕戈谜拟Q磨舵鳞杖璞・鸣哞鳍科莫迦虚吾肌费束辉纸御机夏蛋妙蛙種子草花小火龍恐噴傑尼龜卡咪水箭綠毛蟲鐵甲蛹巴大蝶獨角殼針蜂波比鳥拉達烈雀嘴阿柏蛇怪皮丘雷穿山鼠王多蘭娜后朗力諾可西六尾九胖丁超音蝠走路臭霸派斯特球摩魯蛾地三喵貓老鴨哥猴爆蒂狗風速蚊香蝌蚪君泳士凱勇基胡腕豪喇叭芽口呆食瑪瑙母毒刺拳石隆岩馬焰獸磁合一蔥嘟利海獅白泥舌貝鬼通耿催眠貘引夢人鉗蟹巨霹靂電頑彈椰樹嘎啦飛腿郎快頭瓦雙犀牛鑽吉蔓藤袋墨金魚星寶魔牆偶天螳螂迷唇姐擊羅肯泰鯉暴普百變伊布邊菊化盔鐮刀翼急凍閃你哈克幻葉月桂竺葵鋸鱷藍立咕夜鷹芭瓢安圓絲蛛叉字燈籠古然咩羊茸美麗露才皇毽棉長手向日蜻蜓烏沼太陽亮黑暗鴉妖未知圖騰果翁麒麟奇榛佛托土弟蠍鋼千壺赫狃熊圈熔蝸豬珊瑚炮章桶信使翅戴加象頓Ⅱ驚鹿犬無畏戰舞娃奶罐幸福公炎帝幼沙班洛亞鳳時木守宮森林蜥蜴稚雞壯躍狼紋直衝繭狩獵盾粉蓮童帽樂河橡實鼻狡猾傲骨燕鷗莉奈朵溜糖雨蘑菇斗笠懶獺過動猿請假居忍面者脫妞吼幕下掌朝北優雅勾魂眼那恰姆落正拍負螢甜薔薇溶吞牙鯊鯨駝煤炭跳噗晃斑顎蟻漠仙歌青綿七夕鼬斬飯匙鰍鯰蝦兵螯秤念觸搖籃羽醜納飄浮泡隱怨影詛咒巡靈彷徨熱帶鈴勃梭雪冰護豹珍珠櫻空棘愛心啞屬艾歐蓋固坐祈代希苗台猛曼拿兒狸法師箱蟀勒倫琴含羞苞槌城結貴婦紳蜜女帕茲潛兔隨捲耳魅東施鐺響坦銅鏡鐘盆聒噪陸尖咬不良骷光霓虹自舔狂遠Z由盧席恩騎色霏萊謝米爾宙提主暖炒武刃丸劍探步哨約扒酷冷蝕豆鴿高雉幔龐滾蝙螺釘差搬運匠修建蟾蜍投摔打包保足蜈蚣車輪毬精根裙野蠻鱸混流氓紅倒狒殿滑巾徵哭具死神棺原肋始祖破灰塵索沫栗德單卵細胞造鵝倍四季萌哎呀敗輕蜘堅齒組麻鰻宇燭幽晶斧嚏幾何敏捷功夫父赤駒劈司令炸雄禿丫首惡燃燒畢雲酋迪耶塔賽里狐呱賀掘彩蓓潔能鞘芳芙妮好魷賊腳鎧垃藻臂槍傘咚碎黏鑰朽南瓜嗡哲裴格梟狙射熾咆哮虎漾壬篤啄銃少強鍬農勝虻鬃弱壞驢仔重挽滴偽睡罩盜著竹療環智揮猩擲膽噬堡爺參性:銀伴隕枕戈謎擬Q磨舵鱗杖璞・鳴哞鰭科莫迦虛吾肌費束輝紙御機夏垒磊砰奥壘磊砰丑奧";
|
||||
public const int Gen7_ZHLength = 0x627;
|
||||
|
||||
private const char Gen7_ZH_Ofs = '\uE800';
|
||||
private const ushort SM_ZHCharTable_Size = 0x30F;
|
||||
private const ushort USUM_CHS_Size = 0x4;
|
||||
private static bool GetisG7CHSChar(int idx) => idx is < SM_ZHCharTable_Size or >= SM_ZHCharTable_Size * 2 and < (SM_ZHCharTable_Size * 2) + USUM_CHS_Size;
|
||||
|
||||
// Unicode -> u16 conversion
|
||||
private static readonly Dictionary<char, char> G7_CHS = GetRemapper(true);
|
||||
private static readonly Dictionary<char, char> G7_CHT = GetRemapper(false);
|
||||
|
||||
private static Dictionary<char, char> GetRemapper(bool simplified)
|
||||
{
|
||||
// To accommodate for Chinese characters in Generation 7 3DS games, GameFreak has allocated a list of used ones in the unused 0xE800 region.
|
||||
// Why? Dunno, cuz Unicode has these already.
|
||||
// Maybe they wanted a quick way to sanity check Chinese strings, only allowing within the 0xE800 range.
|
||||
#region Gen 7 Chinese Character Tables
|
||||
public const string Gen7_ZHRaw = "蛋妙蛙种子草花小火龙恐喷杰尼龟卡咪水箭绿毛虫铁甲蛹巴大蝶独角壳针蜂波比鸟拉达烈雀嘴阿柏蛇怪皮丘雷穿山鼠王多兰娜后朗力诺可西六尾九胖丁超音蝠走路臭霸派斯特球摩鲁蛾地三喵猫老鸭哥猴暴蒂狗风速蚊香蝌蚪君泳士凯勇基胡腕豪喇叭芽口呆食玛瑙母毒刺拳石隆岩马焰兽磁合一葱嘟利海狮白泥舌贝鬼通耿催眠貘引梦人钳蟹巨霹雳电顽弹椰树嘎啦飞腿郎快头瓦双犀牛钻吉蔓藤袋墨金鱼星宝魔墙偶天螳螂迷唇姐击罗肯泰鲤普百变伊布边菊化盔镰刀翼急冻闪你哈克幻叶月桂竺葵锯鳄蓝立咕夜鹰芭瓢安圆丝蛛叉字灯笼古然咩羊茸美丽露才皇毽棉长手向日蜻蜓乌沼太阳亮黑暗鸦妖未知图腾果翁麒麟奇榛佛托土弟蝎钢千壶赫狃熊圈熔蜗猪珊瑚炮章桶信使翅戴加象顿Ⅱ惊鹿犬无畏战舞娃奶罐幸福公炎帝幼沙班洛亚凤时木守宫森林蜥蜴稚鸡壮跃狼纹直冲茧狩猎盾粉莲童帽乐河橡实鼻狡猾傲骨燕鸥莉奈朵溜糖雨蘑菇斗笠懒獭过动猿请假居忍面者脱妞吼爆幕下掌朝北优雅勾魂眼那恰姆落正拍负萤甜蔷薇溶吞牙鲨鲸驼煤炭跳噗晃斑颚蚁漠仙歌青绵七夕鼬斩饭匙鳅鲶虾兵螯秤念触摇篮羽丑纳飘浮泡隐怨影诅咒巡灵彷徨热带铃勃梭雪冰护豹珍珠樱空棘爱心哑属艾欧盖固坐祈代希苗台猛曼拿儿狸法师箱蟀勒伦琴含羞苞槌城结贵妇绅蜜女帕兹潜兔随卷耳魅东施铛响坦铜镜钟盆聒噪陆尖咬不良骷荧光霓虹自舔狂远Z由卢席恩骑色霏莱谢米尔宙提主暖炒武刃丸剑探步哨约扒酷冷蚀豆鸽高雉幔庞滚蝙螺钉差搬运匠修建蟾蜍投摔打包保足蜈蚣车轮精根裙野蛮鲈混流氓红倒狒殿滑巾征哭具死神棺原肋始祖破灰尘索沫栗德单卵细胞造鹅倍四季萌哎呀败轻蜘坚齿组麻鳗宇烛幽晶斧嚏几何敏捷功夫父赤驹劈司令炸雄秃丫首恶燃烧毕云酋迪耶塔赛里狐呱贺掘彩蓓洁能鞘芳芙妮好鱿贼脚铠垃藻臂枪伞咚碎黏钥朽南瓜嗡哲裴格枭狙射炽咆哮虎漾壬笃啄铳少强锹农胜虻鬃弱坏驴仔重挽滴伪睡罩盗着竹疗环智挥猩掷胆噬堡爷参性:银伴陨枕戈谜拟Q磨舵鳞杖璞・鸣哞鳍科莫迦虚吾肌费束辉纸御机夏蛋妙蛙種子草花小火龍恐噴傑尼龜卡咪水箭綠毛蟲鐵甲蛹巴大蝶獨角殼針蜂波比鳥拉達烈雀嘴阿柏蛇怪皮丘雷穿山鼠王多蘭娜后朗力諾可西六尾九胖丁超音蝠走路臭霸派斯特球摩魯蛾地三喵貓老鴨哥猴爆蒂狗風速蚊香蝌蚪君泳士凱勇基胡腕豪喇叭芽口呆食瑪瑙母毒刺拳石隆岩馬焰獸磁合一蔥嘟利海獅白泥舌貝鬼通耿催眠貘引夢人鉗蟹巨霹靂電頑彈椰樹嘎啦飛腿郎快頭瓦雙犀牛鑽吉蔓藤袋墨金魚星寶魔牆偶天螳螂迷唇姐擊羅肯泰鯉暴普百變伊布邊菊化盔鐮刀翼急凍閃你哈克幻葉月桂竺葵鋸鱷藍立咕夜鷹芭瓢安圓絲蛛叉字燈籠古然咩羊茸美麗露才皇毽棉長手向日蜻蜓烏沼太陽亮黑暗鴉妖未知圖騰果翁麒麟奇榛佛托土弟蠍鋼千壺赫狃熊圈熔蝸豬珊瑚炮章桶信使翅戴加象頓Ⅱ驚鹿犬無畏戰舞娃奶罐幸福公炎帝幼沙班洛亞鳳時木守宮森林蜥蜴稚雞壯躍狼紋直衝繭狩獵盾粉蓮童帽樂河橡實鼻狡猾傲骨燕鷗莉奈朵溜糖雨蘑菇斗笠懶獺過動猿請假居忍面者脫妞吼幕下掌朝北優雅勾魂眼那恰姆落正拍負螢甜薔薇溶吞牙鯊鯨駝煤炭跳噗晃斑顎蟻漠仙歌青綿七夕鼬斬飯匙鰍鯰蝦兵螯秤念觸搖籃羽醜納飄浮泡隱怨影詛咒巡靈彷徨熱帶鈴勃梭雪冰護豹珍珠櫻空棘愛心啞屬艾歐蓋固坐祈代希苗台猛曼拿兒狸法師箱蟀勒倫琴含羞苞槌城結貴婦紳蜜女帕茲潛兔隨捲耳魅東施鐺響坦銅鏡鐘盆聒噪陸尖咬不良骷光霓虹自舔狂遠Z由盧席恩騎色霏萊謝米爾宙提主暖炒武刃丸劍探步哨約扒酷冷蝕豆鴿高雉幔龐滾蝙螺釘差搬運匠修建蟾蜍投摔打包保足蜈蚣車輪毬精根裙野蠻鱸混流氓紅倒狒殿滑巾徵哭具死神棺原肋始祖破灰塵索沫栗德單卵細胞造鵝倍四季萌哎呀敗輕蜘堅齒組麻鰻宇燭幽晶斧嚏幾何敏捷功夫父赤駒劈司令炸雄禿丫首惡燃燒畢雲酋迪耶塔賽里狐呱賀掘彩蓓潔能鞘芳芙妮好魷賊腳鎧垃藻臂槍傘咚碎黏鑰朽南瓜嗡哲裴格梟狙射熾咆哮虎漾壬篤啄銃少強鍬農勝虻鬃弱壞驢仔重挽滴偽睡罩盜著竹療環智揮猩擲膽噬堡爺參性:銀伴隕枕戈謎擬Q磨舵鱗杖璞・鳴哞鰭科莫迦虛吾肌費束輝紙御機夏垒磊砰奥壘磊砰丑奧";
|
||||
public const int Gen7_ZHLength = 0x627;
|
||||
|
||||
private const char Gen7_ZH_Ofs = '\uE800';
|
||||
private const ushort SM_ZHCharTable_Size = 0x30F;
|
||||
private const ushort USUM_CHS_Size = 0x4;
|
||||
private static bool GetisG7CHSChar(int idx) => idx is < SM_ZHCharTable_Size or >= SM_ZHCharTable_Size * 2 and < (SM_ZHCharTable_Size * 2) + USUM_CHS_Size;
|
||||
|
||||
// Unicode -> u16 conversion
|
||||
private static readonly Dictionary<char, char> G7_CHS = GetRemapper(true);
|
||||
private static readonly Dictionary<char, char> G7_CHT = GetRemapper(false);
|
||||
|
||||
private static Dictionary<char, char> GetRemapper(bool simplified)
|
||||
const string raw = Gen7_ZHRaw;
|
||||
var result = new Dictionary<char, char>(788); // raw.Length
|
||||
for (int i = 0; i < raw.Length; i++)
|
||||
{
|
||||
const string raw = Gen7_ZHRaw;
|
||||
var result = new Dictionary<char, char>(788); // raw.Length
|
||||
for (int i = 0; i < raw.Length; i++)
|
||||
{
|
||||
var isCHS = GetisG7CHSChar(i);
|
||||
if (isCHS != simplified)
|
||||
continue;
|
||||
var isCHS = GetisG7CHSChar(i);
|
||||
if (isCHS != simplified)
|
||||
continue;
|
||||
|
||||
var c = raw[i];
|
||||
result.Add(c, (char)(Gen7_ZH_Ofs + i));
|
||||
}
|
||||
return result;
|
||||
var c = raw[i];
|
||||
result.Add(c, (char)(Gen7_ZH_Ofs + i));
|
||||
}
|
||||
#endregion
|
||||
return result;
|
||||
}
|
||||
#endregion
|
||||
|
||||
/// <summary>
|
||||
/// Converts a Unicode string to Generation 7 in-game Chinese string.
|
||||
/// </summary>
|
||||
/// <param name="sb">Unicode string.</param>
|
||||
/// <param name="language">Detection of language for Traditional Chinese check</param>
|
||||
/// <returns>In-game Chinese string.</returns>
|
||||
internal static void ConvertString2BinG7_zh(StringBuilder sb, int language)
|
||||
/// <summary>
|
||||
/// Converts a Unicode string to Generation 7 in-game Chinese string.
|
||||
/// </summary>
|
||||
/// <param name="chr">Unicode character.</param>
|
||||
/// <param name="traditional">Detection of language for Traditional Chinese check</param>
|
||||
/// <returns>In-game Chinese string.</returns>
|
||||
internal static char ConvertString2BinG7_zh(char chr, bool traditional)
|
||||
{
|
||||
var table = traditional ? G7_CHT : G7_CHS;
|
||||
|
||||
if (table.TryGetValue(chr, out var remap))
|
||||
return remap;
|
||||
return chr;
|
||||
}
|
||||
|
||||
public static bool IsTraditional(ReadOnlySpan<char> input, int lang)
|
||||
{
|
||||
// A string cannot contain a mix of CHS and CHT characters.
|
||||
foreach (var chr in input)
|
||||
{
|
||||
bool traditional = IsTraditional(language, sb);
|
||||
var table = traditional ? G7_CHT : G7_CHS;
|
||||
|
||||
for (int i = 0; i < sb.Length; i++)
|
||||
{
|
||||
var chr = sb[i];
|
||||
if (table.TryGetValue(chr, out var remap))
|
||||
sb[i] = remap;
|
||||
}
|
||||
if (G7_CHT.ContainsKey(chr) && !G7_CHS.ContainsKey(chr))
|
||||
return true;
|
||||
}
|
||||
|
||||
private static bool IsTraditional(int lang, StringBuilder input)
|
||||
{
|
||||
// A string cannot contain a mix of CHS and CHT characters.
|
||||
for (var i = 0; i < input.Length; i++)
|
||||
{
|
||||
var chr = input[i];
|
||||
if (G7_CHT.ContainsKey(chr) && !G7_CHS.ContainsKey(chr))
|
||||
return true;
|
||||
}
|
||||
|
||||
if (lang != (int)LanguageID.ChineseT)
|
||||
return false;
|
||||
|
||||
// CHS and CHT have the same display name
|
||||
for (var i = 0; i < input.Length; i++)
|
||||
{
|
||||
var chr = input[i];
|
||||
if (G7_CHT.ContainsKey(chr) != G7_CHS.ContainsKey(chr))
|
||||
return true;
|
||||
}
|
||||
|
||||
if (lang != (int)LanguageID.ChineseT)
|
||||
return false;
|
||||
|
||||
// CHS and CHT have the same display name
|
||||
foreach (var chr in input)
|
||||
{
|
||||
if (G7_CHT.ContainsKey(chr) != G7_CHS.ContainsKey(chr))
|
||||
return true;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Converts a Generation 7 in-game Chinese string to Unicode string.
|
||||
/// </summary>
|
||||
/// <param name="input">In-game Chinese string.</param>
|
||||
/// <returns>Unicode string.</returns>
|
||||
internal static void RemapChineseGlyphsBin2String(StringBuilder input)
|
||||
return false;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Converts a Generation 7 in-game Chinese string to Unicode string.
|
||||
/// </summary>
|
||||
/// <param name="input">In-game Chinese string.</param>
|
||||
/// <returns>Unicode string.</returns>
|
||||
internal static void RemapChineseGlyphsBin2String(Span<char> input)
|
||||
{
|
||||
for (int i = 0; i < input.Length; i++)
|
||||
{
|
||||
for (int i = 0; i < input.Length; i++)
|
||||
{
|
||||
char val = input[i];
|
||||
var unmap = (uint)val - Gen7_ZH_Ofs;
|
||||
if (unmap < Gen7_ZHLength)
|
||||
input[i] = Gen7_ZHRaw[(int)unmap];
|
||||
}
|
||||
char val = input[i];
|
||||
var unmap = (uint)val - Gen7_ZH_Ofs;
|
||||
if (unmap < Gen7_ZHLength)
|
||||
input[i] = Gen7_ZHRaw[(int)unmap];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
63
PKHeX.Core/PKM/Strings/StringConverter8.cs
Normal file
63
PKHeX.Core/PKM/Strings/StringConverter8.cs
Normal file
|
@ -0,0 +1,63 @@
|
|||
using System;
|
||||
using static System.Buffers.Binary.BinaryPrimitives;
|
||||
|
||||
namespace PKHeX.Core;
|
||||
|
||||
public static class StringConverter8
|
||||
{
|
||||
private const ushort TerminatorNull = 0;
|
||||
|
||||
/// <summary>Converts Generation 7-Beluga encoded data to decoded string.</summary>
|
||||
/// <param name="data">Encoded data</param>
|
||||
/// <returns>Decoded string.</returns>
|
||||
public static string GetString(ReadOnlySpan<byte> data)
|
||||
{
|
||||
Span<char> result = stackalloc char[data.Length];
|
||||
int length = LoadString(data, result);
|
||||
return new string(result[..length].ToArray());
|
||||
}
|
||||
|
||||
private static int LoadString(ReadOnlySpan<byte> data, Span<char> result)
|
||||
{
|
||||
int i = 0;
|
||||
for (; i < data.Length; i += 2)
|
||||
{
|
||||
var value = ReadUInt16LittleEndian(data[i..]);
|
||||
if (value == TerminatorNull)
|
||||
break;
|
||||
result[i/2] = StringConverter.SanitizeChar((char)value);
|
||||
}
|
||||
return i/2;
|
||||
}
|
||||
|
||||
/// <summary>Gets the bytes for a Generation 7-Beluga string.</summary>
|
||||
/// <param name="destBuffer"></param>
|
||||
/// <param name="value">Decoded string.</param>
|
||||
/// <param name="maxLength">Maximum length of the input <see cref="value"/></param>
|
||||
/// <param name="option"></param>
|
||||
/// <returns>Encoded data.</returns>
|
||||
public static int SetString(Span<byte> destBuffer, ReadOnlySpan<char> value, int maxLength,
|
||||
StringConverterOption option = StringConverterOption.ClearZero)
|
||||
{
|
||||
if (value.Length > maxLength)
|
||||
value = value[..maxLength]; // Hard cap
|
||||
|
||||
if (option is StringConverterOption.ClearZero)
|
||||
destBuffer.Clear();
|
||||
|
||||
bool isFullWidth = StringConverter.GetIsFullWidthString(value);
|
||||
for (int i = 0; i < value.Length; i++)
|
||||
{
|
||||
char c = value[i];
|
||||
if (!isFullWidth)
|
||||
c = StringConverter.UnSanitizeChar(c);
|
||||
WriteUInt16LittleEndian(destBuffer[(i * 2)..], c);
|
||||
}
|
||||
|
||||
int count = value.Length * 2;
|
||||
if (count == destBuffer.Length)
|
||||
return count;
|
||||
WriteUInt16LittleEndian(destBuffer[count..], TerminatorNull);
|
||||
return count + 2;
|
||||
}
|
||||
}
|
10
PKHeX.Core/PKM/Strings/StringConverterOption.cs
Normal file
10
PKHeX.Core/PKM/Strings/StringConverterOption.cs
Normal file
|
@ -0,0 +1,10 @@
|
|||
namespace PKHeX.Core;
|
||||
|
||||
public enum StringConverterOption
|
||||
{
|
||||
None,
|
||||
ClearZero,
|
||||
Clear50,
|
||||
Clear7F,
|
||||
ClearFF,
|
||||
}
|
|
@ -28,7 +28,8 @@
|
|||
{
|
||||
string form = pk.Form > 0 ? $"-{pk.Form:00}" : string.Empty;
|
||||
string star = pk.IsShiny ? " ★" : string.Empty;
|
||||
return $"{pk.Species:000}{form}{star} - {pk.Nickname} - {pk.Checksum:X4}{pk.EncryptionConstant:X8}";
|
||||
var chk = pk is ISanityChecksum s ? s.Checksum : PokeCrypto.GetCHK(pk.Data, pk.SIZE_STORED);
|
||||
return $"{pk.Species:000}{form}{star} - {pk.Nickname} - {chk:X4}{pk.EncryptionConstant:X8}";
|
||||
}
|
||||
|
||||
private static string GetGBPKM(GBPKM gb)
|
||||
|
|
|
@ -3,6 +3,7 @@ using System.Diagnostics;
|
|||
using System.Linq;
|
||||
using System.Reflection;
|
||||
|
||||
using static System.Buffers.Binary.BinaryPrimitives;
|
||||
using static PKHeX.Core.MessageStrings;
|
||||
|
||||
namespace PKHeX.Core
|
||||
|
@ -48,7 +49,7 @@ namespace PKHeX.Core
|
|||
/// </summary>
|
||||
/// <param name="data">Raw data representing a Pokemon.</param>
|
||||
/// <returns>An integer indicating the generation of the PKM file, or -1 if the data is invalid.</returns>
|
||||
public static int GetPKMDataFormat(byte[] data)
|
||||
public static int GetPKMDataFormat(ReadOnlySpan<byte> data)
|
||||
{
|
||||
if (!PKX.IsPKM(data.Length))
|
||||
return -1;
|
||||
|
@ -66,17 +67,17 @@ namespace PKHeX.Core
|
|||
return 3;
|
||||
case PokeCrypto.SIZE_4PARTY or PokeCrypto.SIZE_4STORED:
|
||||
case PokeCrypto.SIZE_5PARTY:
|
||||
if ((BitConverter.ToUInt16(data, 0x4) == 0) && (BitConverter.ToUInt16(data, 0x80) >= 0x3333 || data[0x5F] >= 0x10) && BitConverter.ToUInt16(data, 0x46) == 0) // PK5
|
||||
if ((ReadUInt16LittleEndian(data[0x4..]) == 0) && (ReadUInt16LittleEndian(data.Slice(0x80)) >= 0x3333 || data[0x5F] >= 0x10) && ReadUInt16LittleEndian(data[0x46..]) == 0) // PK5
|
||||
return 5;
|
||||
return 4;
|
||||
case PokeCrypto.SIZE_6STORED:
|
||||
return 6;
|
||||
case PokeCrypto.SIZE_6PARTY: // collision with PGT, same size.
|
||||
if (BitConverter.ToUInt16(data, 0x4) != 0) // Bad Sanity?
|
||||
if (ReadUInt16LittleEndian(data[0x4..]) != 0) // Bad Sanity?
|
||||
return -1;
|
||||
if (BitConverter.ToUInt32(data, 0x06) == PokeCrypto.GetCHK(data, PokeCrypto.SIZE_6STORED))
|
||||
if (ReadUInt32LittleEndian(data[0x06..]) == PokeCrypto.GetCHK(data, PokeCrypto.SIZE_6STORED))
|
||||
return 6;
|
||||
if (BitConverter.ToUInt16(data, 0x58) != 0) // Encrypted?
|
||||
if (ReadUInt16LittleEndian(data[0x58..]) != 0) // Encrypted?
|
||||
{
|
||||
for (int i = data.Length - 0x10; i < data.Length; i++) // 0x10 of 00's at the end != PK6
|
||||
{
|
||||
|
@ -114,7 +115,7 @@ namespace PKHeX.Core
|
|||
PokeCrypto.SIZE_3XSTORED => new XK3(data),
|
||||
_ => new PK3(data),
|
||||
},
|
||||
4 => BitConverter.ToUInt16(data, 0x04) == 0 ? new PK4(data) : new BK4(data),
|
||||
4 => ReadUInt16LittleEndian(data.AsSpan(0x04)) == 0 ? new PK4(data) : new BK4(data),
|
||||
5 => new PK5(data),
|
||||
6 => CheckPKMFormat7(new PK6(data), prefer),
|
||||
8 => CheckPKMFormat8(data),
|
||||
|
@ -181,7 +182,7 @@ namespace PKHeX.Core
|
|||
return true;
|
||||
}
|
||||
|
||||
int mb = BitConverter.ToUInt16(pk.Data, 0x16);
|
||||
int mb = ReadUInt16LittleEndian(pk.Data.AsSpan(0x16));
|
||||
if (mb > 0xAAA)
|
||||
return false;
|
||||
for (int i = 0; i < 6; i++)
|
||||
|
|
Some files were not shown because too many files have changed in this diff Show more
Loading…
Reference in a new issue