mirror of
https://github.com/kwsch/PKHeX
synced 2024-11-27 06:20:25 +00:00
Extract PokemonList* to inherited class
Logic is essentially identical; implement a base class and have the generation specific structures implment the differences. Reduce the verbosity a little
This commit is contained in:
parent
84185dc6c9
commit
fc73eee570
9 changed files with 289 additions and 362 deletions
|
@ -11,8 +11,6 @@ namespace PKHeX.Core
|
||||||
internal byte[] nick;
|
internal byte[] nick;
|
||||||
public override PersonalInfo PersonalInfo => PersonalTable.Y[Species];
|
public override PersonalInfo PersonalInfo => PersonalTable.Y[Species];
|
||||||
|
|
||||||
public byte[] OT_Name_Raw => (byte[])otname.Clone();
|
|
||||||
public byte[] Nickname_Raw => (byte[])nick.Clone();
|
|
||||||
public override bool Valid => Species <= 151 && (Data[0] == 0 || Species != 0);
|
public override bool Valid => Species <= 151 && (Data[0] == 0 || Species != 0);
|
||||||
|
|
||||||
public override int SIZE_PARTY => PKX.SIZE_1PARTY;
|
public override int SIZE_PARTY => PKX.SIZE_1PARTY;
|
||||||
|
@ -97,7 +95,7 @@ namespace PKHeX.Core
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
protected override byte[] Encrypt() => new PokemonList1(this).GetBytes();
|
protected override byte[] Encrypt() => new PokeList1(this).Write();
|
||||||
public override byte[] EncryptedPartyData => Encrypt();
|
public override byte[] EncryptedPartyData => Encrypt();
|
||||||
public override byte[] EncryptedBoxData => Encrypt();
|
public override byte[] EncryptedBoxData => Encrypt();
|
||||||
public override byte[] DecryptedBoxData => Encrypt();
|
public override byte[] DecryptedBoxData => Encrypt();
|
||||||
|
@ -434,121 +432,4 @@ namespace PKHeX.Core
|
||||||
return pk7;
|
return pk7;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public class PokemonList1
|
|
||||||
{
|
|
||||||
private const int CAPACITY_DAYCARE = 1;
|
|
||||||
private const int CAPACITY_PARTY = 6;
|
|
||||||
private const int CAPACITY_STORED = 20;
|
|
||||||
private const int CAPACITY_STORED_JP = 30;
|
|
||||||
|
|
||||||
private readonly bool Japanese;
|
|
||||||
|
|
||||||
private int StringLength => Japanese ? PK1.STRLEN_J : PK1.STRLEN_U;
|
|
||||||
|
|
||||||
public enum CapacityType
|
|
||||||
{
|
|
||||||
Daycare = CAPACITY_DAYCARE,
|
|
||||||
Party = CAPACITY_PARTY,
|
|
||||||
Stored = CAPACITY_STORED,
|
|
||||||
StoredJP = CAPACITY_STORED_JP,
|
|
||||||
Single
|
|
||||||
}
|
|
||||||
|
|
||||||
private static int GetEntrySize(CapacityType c) => c == CapacityType.Single || c == CapacityType.Party
|
|
||||||
? PKX.SIZE_1PARTY
|
|
||||||
: PKX.SIZE_1STORED;
|
|
||||||
private static byte GetCapacity(CapacityType c) => c == CapacityType.Single ? (byte)1 : (byte)c;
|
|
||||||
|
|
||||||
private static byte[] GetEmptyList(CapacityType c, bool is_JP = false)
|
|
||||||
{
|
|
||||||
int cap = GetCapacity(c);
|
|
||||||
return new[] { (byte)0 }.Concat(Enumerable.Repeat((byte)0xFF, cap + 1)).Concat(Enumerable.Repeat((byte)0, GetEntrySize(c) * cap)).Concat(Enumerable.Repeat((byte)0x50, (is_JP ? PK1.STRLEN_J : PK1.STRLEN_U) * 2 * cap)).ToArray();
|
|
||||||
}
|
|
||||||
|
|
||||||
public PokemonList1(byte[] d, CapacityType c = CapacityType.Single, bool jp = false)
|
|
||||||
{
|
|
||||||
Japanese = jp;
|
|
||||||
Data = d ?? GetEmptyList(c, Japanese);
|
|
||||||
Capacity = GetCapacity(c);
|
|
||||||
Entry_Size = GetEntrySize(c);
|
|
||||||
|
|
||||||
if (Data.Length != DataSize)
|
|
||||||
Array.Resize(ref Data, DataSize);
|
|
||||||
|
|
||||||
Pokemon = new PK1[Capacity];
|
|
||||||
for (int i = 0; i < Capacity; i++)
|
|
||||||
{
|
|
||||||
int base_ofs = 2 + Capacity;
|
|
||||||
byte[] dat = new byte[Entry_Size];
|
|
||||||
byte[] otname = new byte[StringLength];
|
|
||||||
byte[] nick = new byte[StringLength];
|
|
||||||
Buffer.BlockCopy(Data, base_ofs + Entry_Size * i, dat, 0, Entry_Size);
|
|
||||||
Buffer.BlockCopy(Data, base_ofs + Capacity * Entry_Size + StringLength * i, otname, 0, StringLength);
|
|
||||||
Buffer.BlockCopy(Data, base_ofs + Capacity * Entry_Size + StringLength * (i + Capacity), nick, 0, StringLength);
|
|
||||||
|
|
||||||
Pokemon[i] = new PK1(dat, null, jp) {otname = otname, nick = nick};
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public PokemonList1(CapacityType c = CapacityType.Single, bool jp = false)
|
|
||||||
: this(null, c, jp) => Count = 1;
|
|
||||||
|
|
||||||
public PokemonList1(PK1 pk)
|
|
||||||
: this(CapacityType.Single, pk.Japanese)
|
|
||||||
{
|
|
||||||
this[0] = pk;
|
|
||||||
Count = 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
private readonly byte[] Data;
|
|
||||||
private readonly byte Capacity;
|
|
||||||
private readonly int Entry_Size;
|
|
||||||
|
|
||||||
public byte Count
|
|
||||||
{
|
|
||||||
get => Data[0];
|
|
||||||
set => Data[0] = value > Capacity ? Capacity : value;
|
|
||||||
}
|
|
||||||
|
|
||||||
public readonly PK1[] Pokemon;
|
|
||||||
|
|
||||||
public PK1 this[int i]
|
|
||||||
{
|
|
||||||
get
|
|
||||||
{
|
|
||||||
if (i > Capacity || i < 0) throw new ArgumentOutOfRangeException($"Invalid PokemonList Access: {i}");
|
|
||||||
return Pokemon[i];
|
|
||||||
}
|
|
||||||
set
|
|
||||||
{
|
|
||||||
if (value == null) return;
|
|
||||||
Pokemon[i] = (PK1)value.Clone();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private void Update()
|
|
||||||
{
|
|
||||||
int count = Array.FindIndex(Pokemon, pk => pk.Species == 0);
|
|
||||||
Count = count < 0 ? Capacity : (byte)count;
|
|
||||||
for (int i = 0; i < Count; i++)
|
|
||||||
{
|
|
||||||
int base_ofs = 2 + Capacity;
|
|
||||||
Data[1 + i] = (byte)SpeciesConverter.SetG1Species(Pokemon[i].Species);
|
|
||||||
Array.Copy(Pokemon[i].Data, 0, Data, base_ofs + Entry_Size * i, Entry_Size);
|
|
||||||
Array.Copy(Pokemon[i].OT_Name_Raw, 0, Data, base_ofs + Capacity * Entry_Size + StringLength * i, StringLength);
|
|
||||||
Array.Copy(Pokemon[i].Nickname_Raw, 0, Data, base_ofs + Capacity * Entry_Size + StringLength * (i + Capacity), StringLength);
|
|
||||||
}
|
|
||||||
Data[1 + Count] = byte.MaxValue;
|
|
||||||
}
|
|
||||||
|
|
||||||
public byte[] GetBytes()
|
|
||||||
{
|
|
||||||
Update();
|
|
||||||
return Data;
|
|
||||||
}
|
|
||||||
|
|
||||||
private int DataSize => Capacity * (Entry_Size + 1 + 2 * StringLength) + 2;
|
|
||||||
public static int GetDataLength(CapacityType c, bool jp = false) => GetCapacity(c) * (GetEntrySize(c) + 1 + 2 * (jp ? PK1.STRLEN_J : PK1.STRLEN_U)) + 2;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -11,8 +11,6 @@ namespace PKHeX.Core
|
||||||
internal byte[] nick;
|
internal byte[] nick;
|
||||||
public override PersonalInfo PersonalInfo => PersonalTable.C[Species];
|
public override PersonalInfo PersonalInfo => PersonalTable.C[Species];
|
||||||
|
|
||||||
public byte[] OT_Name_Raw => (byte[])otname.Clone();
|
|
||||||
public byte[] Nickname_Raw => (byte[])nick.Clone();
|
|
||||||
public override bool Valid => Species <= 252;
|
public override bool Valid => Species <= 252;
|
||||||
|
|
||||||
public override int SIZE_PARTY => PKX.SIZE_2PARTY;
|
public override int SIZE_PARTY => PKX.SIZE_2PARTY;
|
||||||
|
@ -119,7 +117,7 @@ namespace PKHeX.Core
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
protected override byte[] Encrypt() => new PokemonList2(this).GetBytes();
|
protected override byte[] Encrypt() => new PokeList2(this).Write();
|
||||||
public override byte[] EncryptedPartyData => Encrypt();
|
public override byte[] EncryptedPartyData => Encrypt();
|
||||||
public override byte[] EncryptedBoxData => Encrypt();
|
public override byte[] EncryptedBoxData => Encrypt();
|
||||||
public override byte[] DecryptedBoxData => Encrypt();
|
public override byte[] DecryptedBoxData => Encrypt();
|
||||||
|
@ -361,7 +359,7 @@ namespace PKHeX.Core
|
||||||
|
|
||||||
public PK1 ConvertToPK1()
|
public PK1 ConvertToPK1()
|
||||||
{
|
{
|
||||||
PK1 pk1 = new PK1(null, Identifier, Japanese) {TradebackStatus = TradebackType.WasTradeback};
|
PK1 pk1 = new PK1(null, Identifier) {TradebackStatus = TradebackType.WasTradeback};
|
||||||
Array.Copy(Data, 0x1, pk1.Data, 0x7, 0x1A);
|
Array.Copy(Data, 0x1, pk1.Data, 0x7, 0x1A);
|
||||||
pk1.Species = Species; // This will take care of Typing :)
|
pk1.Species = Species; // This will take care of Typing :)
|
||||||
|
|
||||||
|
@ -377,8 +375,8 @@ namespace PKHeX.Core
|
||||||
pk1.Stat_Level = Stat_Level;
|
pk1.Stat_Level = Stat_Level;
|
||||||
}
|
}
|
||||||
// Status = 0
|
// Status = 0
|
||||||
Array.Copy(otname, 0, pk1.otname, 0, otname.Length);
|
pk1.otname = (byte[])otname.Clone();
|
||||||
Array.Copy(nick, 0, pk1.nick, 0, nick.Length);
|
pk1.nick = (byte[])nick.Clone();
|
||||||
|
|
||||||
pk1.ClearInvalidMoves();
|
pk1.ClearInvalidMoves();
|
||||||
|
|
||||||
|
@ -479,122 +477,4 @@ namespace PKHeX.Core
|
||||||
return pk7;
|
return pk7;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public class PokemonList2
|
|
||||||
{
|
|
||||||
private const int CAPACITY_DAYCARE = 1;
|
|
||||||
private const int CAPACITY_PARTY = 6;
|
|
||||||
private const int CAPACITY_STORED = 20;
|
|
||||||
private const int CAPACITY_STORED_JP = 30;
|
|
||||||
|
|
||||||
private readonly bool Japanese;
|
|
||||||
|
|
||||||
private int StringLength => Japanese ? PK2.STRLEN_J : PK2.STRLEN_U;
|
|
||||||
|
|
||||||
public enum CapacityType
|
|
||||||
{
|
|
||||||
Daycare = CAPACITY_DAYCARE,
|
|
||||||
Party = CAPACITY_PARTY,
|
|
||||||
Stored = CAPACITY_STORED,
|
|
||||||
StoredJP = CAPACITY_STORED_JP,
|
|
||||||
Single
|
|
||||||
}
|
|
||||||
|
|
||||||
private static int GetEntrySize(CapacityType c) => c == CapacityType.Single || c == CapacityType.Party
|
|
||||||
? PKX.SIZE_2PARTY
|
|
||||||
: PKX.SIZE_2STORED;
|
|
||||||
|
|
||||||
private static byte GetCapacity(CapacityType c) => c == CapacityType.Single ? (byte)1 : (byte)c;
|
|
||||||
|
|
||||||
private static byte[] GetEmptyList(CapacityType c, bool is_JP = false)
|
|
||||||
{
|
|
||||||
int cap = GetCapacity(c);
|
|
||||||
return new[] { (byte)0 }.Concat(Enumerable.Repeat((byte)0xFF, cap + 1)).Concat(Enumerable.Repeat((byte)0, GetEntrySize(c) * cap)).Concat(Enumerable.Repeat((byte)0x50, (is_JP ? PK2.STRLEN_J : PK2.STRLEN_U) * 2 * cap)).ToArray();
|
|
||||||
}
|
|
||||||
|
|
||||||
public PokemonList2(byte[] d, CapacityType c = CapacityType.Single, bool jp = false)
|
|
||||||
{
|
|
||||||
Japanese = jp;
|
|
||||||
Data = d ?? GetEmptyList(c, Japanese);
|
|
||||||
Capacity = GetCapacity(c);
|
|
||||||
Entry_Size = GetEntrySize(c);
|
|
||||||
|
|
||||||
if (Data.Length != DataSize)
|
|
||||||
{
|
|
||||||
Array.Resize(ref Data, DataSize);
|
|
||||||
}
|
|
||||||
|
|
||||||
Pokemon = new PK2[Capacity];
|
|
||||||
for (int i = 0; i < Capacity; i++)
|
|
||||||
{
|
|
||||||
int base_ofs = 2 + Capacity;
|
|
||||||
byte[] dat = new byte[Entry_Size];
|
|
||||||
byte[] otname = new byte[StringLength];
|
|
||||||
byte[] nick = new byte[StringLength];
|
|
||||||
Buffer.BlockCopy(Data, base_ofs + Entry_Size * i, dat, 0, Entry_Size);
|
|
||||||
Buffer.BlockCopy(Data, base_ofs + Capacity * Entry_Size + StringLength * i, otname, 0, StringLength);
|
|
||||||
Buffer.BlockCopy(Data, base_ofs + Capacity * Entry_Size + StringLength * (i + Capacity), nick, 0, StringLength);
|
|
||||||
Pokemon[i] = new PK2(dat, null, jp) {IsEgg = Data[1 + i] == 0xFD, otname = otname, nick = nick};
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public PokemonList2(CapacityType c = CapacityType.Single, bool jp = false)
|
|
||||||
: this(null, c, jp) => Count = 1;
|
|
||||||
|
|
||||||
public PokemonList2(PK2 pk)
|
|
||||||
: this(CapacityType.Single, pk.Japanese)
|
|
||||||
{
|
|
||||||
this[0] = pk;
|
|
||||||
Count = 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
private readonly byte[] Data;
|
|
||||||
private readonly byte Capacity;
|
|
||||||
private readonly int Entry_Size;
|
|
||||||
|
|
||||||
public byte Count
|
|
||||||
{
|
|
||||||
get => Data[0];
|
|
||||||
set => Data[0] = value > Capacity ? Capacity : value;
|
|
||||||
}
|
|
||||||
|
|
||||||
public readonly PK2[] Pokemon;
|
|
||||||
|
|
||||||
public PK2 this[int i]
|
|
||||||
{
|
|
||||||
get
|
|
||||||
{
|
|
||||||
if (i > Capacity || i < 0) throw new ArgumentOutOfRangeException($"Invalid PokemonList Access: {i}");
|
|
||||||
return Pokemon[i];
|
|
||||||
}
|
|
||||||
set
|
|
||||||
{
|
|
||||||
if (value == null) return;
|
|
||||||
Pokemon[i] = (PK2)value.Clone();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private void Update()
|
|
||||||
{
|
|
||||||
int count = Array.FindIndex(Pokemon, pk => pk.Species == 0);
|
|
||||||
Count = count < 0 ? Capacity : (byte)count;
|
|
||||||
for (int i = 0; i < Count; i++)
|
|
||||||
{
|
|
||||||
Data[1 + i] = Pokemon[i].IsEgg ? (byte)0xFD : (byte)Pokemon[i].Species;
|
|
||||||
Array.Copy(Pokemon[i].Data, 0, Data, 2 + Capacity + Entry_Size * i, Entry_Size);
|
|
||||||
Array.Copy(Pokemon[i].OT_Name_Raw, 0, Data, 2 + Capacity + Capacity * Entry_Size + StringLength * i, StringLength);
|
|
||||||
Array.Copy(Pokemon[i].Nickname_Raw, 0, Data, 2 + Capacity + Capacity * Entry_Size + StringLength * Capacity + StringLength * i, StringLength);
|
|
||||||
}
|
|
||||||
Data[1 + Count] = byte.MaxValue;
|
|
||||||
}
|
|
||||||
|
|
||||||
public byte[] GetBytes()
|
|
||||||
{
|
|
||||||
Update();
|
|
||||||
return Data;
|
|
||||||
}
|
|
||||||
|
|
||||||
private int DataSize => Capacity * (Entry_Size + 1 + 2 * StringLength) + 2;
|
|
||||||
public static int GetDataLength(CapacityType c, bool jp = false) => GetCapacity(c) * (GetEntrySize(c) + 1 + 2 * (jp ? PK2.STRLEN_J : PK2.STRLEN_U)) + 2;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
17
PKHeX.Core/PKM/Shared/PokeList1.cs
Normal file
17
PKHeX.Core/PKM/Shared/PokeList1.cs
Normal file
|
@ -0,0 +1,17 @@
|
||||||
|
namespace PKHeX.Core
|
||||||
|
{
|
||||||
|
public sealed class PokeList1 : PokeListGB<PK1>
|
||||||
|
{
|
||||||
|
protected override byte GetSpeciesBoxIdentifier(PK1 pk) => (byte)SpeciesConverter.SetG1Species(pk.Species);
|
||||||
|
protected override PK1 GetEntry(byte[] dat, byte[] otname, byte[] nick, bool egg) => new PK1(dat) { otname = otname, nick = nick };
|
||||||
|
protected override int GetEntrySize() => GetEntrySize(IsFormatParty);
|
||||||
|
|
||||||
|
public PokeList1(byte[] d, PokeListType c = PokeListType.Single, bool jp = false) : base(d, c, jp) { }
|
||||||
|
public PokeList1(PokeListType c = PokeListType.Single, bool jp = false) : base(c, jp) { }
|
||||||
|
public PokeList1(byte[] d) : base(d, PokeListType.Single, d.Length == PKX.SIZE_1JLIST) { }
|
||||||
|
public PokeList1(PK1 pk) : base(pk) { }
|
||||||
|
|
||||||
|
private static int GetEntrySize(bool party) => party ? PKX.SIZE_1PARTY : PKX.SIZE_1STORED;
|
||||||
|
public static int GetDataLength(PokeListType c, bool jp) => GetDataSize(c, jp, GetEntrySize(IsCapacityPartyFormat(c)));
|
||||||
|
}
|
||||||
|
}
|
17
PKHeX.Core/PKM/Shared/PokeList2.cs
Normal file
17
PKHeX.Core/PKM/Shared/PokeList2.cs
Normal file
|
@ -0,0 +1,17 @@
|
||||||
|
namespace PKHeX.Core
|
||||||
|
{
|
||||||
|
public sealed class PokeList2 : PokeListGB<PK2>
|
||||||
|
{
|
||||||
|
protected override byte GetSpeciesBoxIdentifier(PK2 pk) => pk.IsEgg ? (byte)0xFD : (byte)pk.Species;
|
||||||
|
protected override PK2 GetEntry(byte[] dat, byte[] otname, byte[] nick, bool egg) => new PK2(dat) { IsEgg = egg, otname = otname, nick = nick };
|
||||||
|
protected override int GetEntrySize() => GetEntrySize(IsFormatParty);
|
||||||
|
|
||||||
|
public PokeList2(byte[] d, PokeListType c = PokeListType.Single, bool jp = false) : base(d, c, jp) { }
|
||||||
|
public PokeList2(PokeListType c = PokeListType.Single, bool jp = false) : base (c, jp) { }
|
||||||
|
public PokeList2(byte[] d) : base(d, PokeListType.Single, d.Length == PKX.SIZE_2JLIST) { }
|
||||||
|
public PokeList2(PK2 pk) : base(pk) { }
|
||||||
|
|
||||||
|
private static int GetEntrySize(bool party) => party ? PKX.SIZE_2PARTY : PKX.SIZE_2STORED;
|
||||||
|
public static int GetDataLength(PokeListType c, bool jp) => GetDataSize(c, jp, GetEntrySize(IsCapacityPartyFormat(c)));
|
||||||
|
}
|
||||||
|
}
|
129
PKHeX.Core/PKM/Shared/PokeListGB.cs
Normal file
129
PKHeX.Core/PKM/Shared/PokeListGB.cs
Normal file
|
@ -0,0 +1,129 @@
|
||||||
|
using System;
|
||||||
|
using System.Linq;
|
||||||
|
|
||||||
|
namespace PKHeX.Core
|
||||||
|
{
|
||||||
|
public abstract class PokeListGB<T> where T : PKM
|
||||||
|
{
|
||||||
|
private readonly int StringLength;
|
||||||
|
private readonly byte[] Data;
|
||||||
|
private readonly byte Capacity;
|
||||||
|
private readonly int Entry_Size;
|
||||||
|
|
||||||
|
public readonly T[] Pokemon;
|
||||||
|
|
||||||
|
public byte Count { get => Data[0]; private set => Data[0] = value > Capacity ? Capacity : value; }
|
||||||
|
|
||||||
|
protected PokeListGB(byte[] d, PokeListType c = PokeListType.Single, bool jp = false)
|
||||||
|
{
|
||||||
|
Data = d ?? GetEmptyList(c, jp);
|
||||||
|
StringLength = GetStringLength(jp);
|
||||||
|
Capacity = (byte)c;
|
||||||
|
Entry_Size = GetEntrySize();
|
||||||
|
var dataSize = 2 + (Capacity * (Entry_Size + 1 + (2 * StringLength)));
|
||||||
|
|
||||||
|
if (Data.Length != dataSize)
|
||||||
|
Array.Resize(ref Data, dataSize);
|
||||||
|
|
||||||
|
Pokemon = Read();
|
||||||
|
}
|
||||||
|
|
||||||
|
protected PokeListGB(PokeListType c = PokeListType.Single, bool jp = false)
|
||||||
|
: this(null, c, jp) => Count = 1;
|
||||||
|
|
||||||
|
protected PokeListGB(T pk)
|
||||||
|
: this(PokeListType.Single, pk.Japanese)
|
||||||
|
{
|
||||||
|
this[0] = pk;
|
||||||
|
Count = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
private byte[] GetEmptyList(PokeListType c, bool jp = false)
|
||||||
|
{
|
||||||
|
int capacity = (byte)c;
|
||||||
|
var intro = Enumerable.Repeat((byte) 0xFF, capacity + 1);
|
||||||
|
var pkm = Enumerable.Repeat((byte) 0, GetEntrySize() * capacity);
|
||||||
|
var strings = Enumerable.Repeat((byte) 0x50, GetStringLength(jp) * 2 * capacity);
|
||||||
|
return new[] { (byte)0 }.Concat(intro).Concat(pkm).Concat(strings).ToArray();
|
||||||
|
}
|
||||||
|
|
||||||
|
private int GetOffsetPKMData(int base_ofs, int i) => base_ofs + (Entry_Size * i);
|
||||||
|
private int GetOffsetPKMOT(int base_ofs, int i) => GetOffsetPKMData(base_ofs, Capacity) + (StringLength * i);
|
||||||
|
private int GetOffsetPKMNickname(int base_ofs, int i) => GetOffsetPKMOT(base_ofs, Capacity) + (StringLength * i);
|
||||||
|
|
||||||
|
private static int GetStringLength(bool jp) => jp ? PK1.STRLEN_J : PK1.STRLEN_U;
|
||||||
|
protected bool IsFormatParty => IsCapacityPartyFormat((PokeListType)Capacity);
|
||||||
|
protected static bool IsCapacityPartyFormat(PokeListType Capacity) => Capacity == PokeListType.Single || Capacity == PokeListType.Party;
|
||||||
|
|
||||||
|
protected static int GetDataSize(PokeListType c, bool jp, int entrySize)
|
||||||
|
{
|
||||||
|
var entryLength = 1 + entrySize + (2 * GetStringLength(jp));
|
||||||
|
return 2 + ((byte)c * entryLength);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected abstract int GetEntrySize();
|
||||||
|
protected abstract byte GetSpeciesBoxIdentifier(T pk);
|
||||||
|
protected abstract T GetEntry(byte[] dat, byte[] otname, byte[] nick, bool egg);
|
||||||
|
|
||||||
|
public T this[int i]
|
||||||
|
{
|
||||||
|
get
|
||||||
|
{
|
||||||
|
if (i > Capacity || i < 0) throw new ArgumentOutOfRangeException($"Invalid {nameof(PokeListGB<T>)} Access: {i}");
|
||||||
|
return Pokemon[i];
|
||||||
|
}
|
||||||
|
set
|
||||||
|
{
|
||||||
|
if (value == null) return;
|
||||||
|
Pokemon[i] = (T)value.Clone();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private T[] Read()
|
||||||
|
{
|
||||||
|
var arr = new T[Capacity];
|
||||||
|
int base_ofs = 2 + Capacity;
|
||||||
|
for (int i = 0; i < Capacity; i++)
|
||||||
|
arr[i] = GetEntry(base_ofs, i);
|
||||||
|
return arr;
|
||||||
|
}
|
||||||
|
|
||||||
|
public byte[] Write()
|
||||||
|
{
|
||||||
|
int count = Array.FindIndex(Pokemon, pk => pk.Species == 0);
|
||||||
|
Count = count < 0 ? Capacity : (byte)count;
|
||||||
|
int base_ofs = 2 + Capacity;
|
||||||
|
for (int i = 0; i < Count; i++)
|
||||||
|
{
|
||||||
|
Data[1 + i] = GetSpeciesBoxIdentifier(Pokemon[i]);
|
||||||
|
SetEntry(base_ofs, i);
|
||||||
|
}
|
||||||
|
Data[1 + Count] = byte.MaxValue;
|
||||||
|
return Data;
|
||||||
|
}
|
||||||
|
|
||||||
|
private T GetEntry(int base_ofs, int i)
|
||||||
|
{
|
||||||
|
byte[] dat = new byte[Entry_Size];
|
||||||
|
byte[] otname = new byte[StringLength];
|
||||||
|
byte[] nick = new byte[StringLength];
|
||||||
|
int pkOfs = GetOffsetPKMData(base_ofs, i);
|
||||||
|
int otOfs = GetOffsetPKMOT(base_ofs, i);
|
||||||
|
int nkOfs = GetOffsetPKMNickname(base_ofs, i);
|
||||||
|
Buffer.BlockCopy(Data, pkOfs, dat, 0, Entry_Size);
|
||||||
|
Buffer.BlockCopy(Data, otOfs, otname, 0, StringLength);
|
||||||
|
Buffer.BlockCopy(Data, nkOfs, nick, 0, StringLength);
|
||||||
|
return GetEntry(dat, otname, nick, Data[1 + i] == 0xFD);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void SetEntry(int base_ofs, int i)
|
||||||
|
{
|
||||||
|
int pkOfs = GetOffsetPKMData(base_ofs, i);
|
||||||
|
int otOfs = GetOffsetPKMOT(base_ofs, i);
|
||||||
|
int nkOfs = GetOffsetPKMNickname(base_ofs, i);
|
||||||
|
Array.Copy(Pokemon[i].Data, 0, Data, pkOfs, Entry_Size);
|
||||||
|
Array.Copy(Pokemon[i].OT_Trash, 0, Data, otOfs, StringLength);
|
||||||
|
Array.Copy(Pokemon[i].Nickname_Trash, 0, Data, nkOfs, StringLength);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
10
PKHeX.Core/PKM/Shared/PokeListType.cs
Normal file
10
PKHeX.Core/PKM/Shared/PokeListType.cs
Normal file
|
@ -0,0 +1,10 @@
|
||||||
|
namespace PKHeX.Core
|
||||||
|
{
|
||||||
|
public enum PokeListType : byte
|
||||||
|
{
|
||||||
|
Single = 1,
|
||||||
|
Party = 6,
|
||||||
|
Stored = 20,
|
||||||
|
StoredJP = 30,
|
||||||
|
}
|
||||||
|
}
|
|
@ -86,12 +86,12 @@ namespace PKHeX.Core
|
||||||
switch (format)
|
switch (format)
|
||||||
{
|
{
|
||||||
case 1:
|
case 1:
|
||||||
var PL1 = new PokemonList1(data, PokemonList1.CapacityType.Single, data.Length == PKX.SIZE_1JLIST);
|
var PL1 = new PokeList1(data);
|
||||||
if (ident != null)
|
if (ident != null)
|
||||||
PL1[0].Identifier = ident;
|
PL1[0].Identifier = ident;
|
||||||
return PL1[0];
|
return PL1[0];
|
||||||
case 2:
|
case 2:
|
||||||
var PL2 = new PokemonList2(data, PokemonList2.CapacityType.Single, data.Length == PKX.SIZE_2JLIST);
|
var PL2 = new PokeList2(data);
|
||||||
if (ident != null)
|
if (ident != null)
|
||||||
PL2[0].Identifier = ident;
|
PL2[0].Identifier = ident;
|
||||||
return PL2[0];
|
return PL2[0];
|
||||||
|
|
|
@ -41,71 +41,56 @@ namespace PKHeX.Core
|
||||||
Personal = PersonalTable.Y;
|
Personal = PersonalTable.Y;
|
||||||
|
|
||||||
// Stash boxes after the save file's end.
|
// Stash boxes after the save file's end.
|
||||||
byte[] TempBox = new byte[SIZE_STOREDBOX];
|
int stored = SIZE_STOREDBOX;
|
||||||
|
int baseDest = Data.Length - SIZE_RESERVED;
|
||||||
|
var capacity = Japanese ? PokeListType.StoredJP : PokeListType.Stored;
|
||||||
for (int i = 0; i < BoxCount; i++)
|
for (int i = 0; i < BoxCount; i++)
|
||||||
{
|
{
|
||||||
if (i < BoxCount / 2)
|
int ofs = GetBoxRawDataOffset(i);
|
||||||
Array.Copy(Data, 0x4000 + i * TempBox.Length, TempBox, 0, TempBox.Length);
|
var box = GetData(ofs, stored);
|
||||||
else
|
var boxDest = baseDest + (i * SIZE_BOX);
|
||||||
Array.Copy(Data, 0x6000 + (i - BoxCount / 2) * TempBox.Length, TempBox, 0, TempBox.Length);
|
var boxPL = new PokeList1(box, capacity, Japanese);
|
||||||
PokemonList1 PL1 = new PokemonList1(TempBox, Japanese ? PokemonList1.CapacityType.StoredJP : PokemonList1.CapacityType.Stored, Japanese);
|
for (int j = 0; j < boxPL.Pokemon.Length; j++)
|
||||||
for (int j = 0; j < PL1.Pokemon.Length; j++)
|
|
||||||
{
|
{
|
||||||
if (j < PL1.Count)
|
var dest = boxDest + (j * SIZE_STORED);
|
||||||
{
|
var pkDat = (j < boxPL.Count)
|
||||||
byte[] pkDat = new PokemonList1(PL1[j]).GetBytes();
|
? new PokeList1(boxPL[j]).Write()
|
||||||
pkDat.CopyTo(Data, Data.Length - SIZE_RESERVED + i * SIZE_BOX + j * SIZE_STORED);
|
: new byte[PokeList1.GetDataLength(PokeListType.Single, Japanese)];
|
||||||
}
|
pkDat.CopyTo(Data, dest);
|
||||||
else
|
|
||||||
{
|
|
||||||
byte[] pkDat = new byte[PokemonList1.GetDataLength(PokemonList1.CapacityType.Single, Japanese)];
|
|
||||||
pkDat.CopyTo(Data, Data.Length - SIZE_RESERVED + i * SIZE_BOX + j * SIZE_STORED);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Array.Copy(Data, Japanese ? 0x302D : 0x30C0, TempBox, 0, TempBox.Length);
|
var current = GetData(Japanese ? 0x302D : 0x30C0, SIZE_STOREDBOX);
|
||||||
PokemonList1 curBoxPL = new PokemonList1(TempBox, Japanese ? PokemonList1.CapacityType.StoredJP : PokemonList1.CapacityType.Stored, Japanese);
|
var curBoxPL = new PokeList1(current, capacity, Japanese);
|
||||||
for (int i = 0; i < curBoxPL.Pokemon.Length; i++)
|
for (int i = 0; i < curBoxPL.Pokemon.Length; i++)
|
||||||
{
|
{
|
||||||
if (i < curBoxPL.Count)
|
var dest = Data.Length - SIZE_RESERVED + CurrentBox * SIZE_BOX + i * SIZE_STORED;
|
||||||
{
|
var pkDat = i < curBoxPL.Count
|
||||||
byte[] pkDat = new PokemonList1(curBoxPL[i]).GetBytes();
|
? new PokeList1(curBoxPL[i]).Write()
|
||||||
pkDat.CopyTo(Data, Data.Length - SIZE_RESERVED + CurrentBox * SIZE_BOX + i * SIZE_STORED);
|
: new byte[PokeList1.GetDataLength(PokeListType.Single, Japanese)];
|
||||||
}
|
pkDat.CopyTo(Data, dest);
|
||||||
else
|
|
||||||
{
|
|
||||||
byte[] pkDat = new byte[PokemonList1.GetDataLength(PokemonList1.CapacityType.Single, Japanese)];
|
|
||||||
pkDat.CopyTo(Data, Data.Length - SIZE_RESERVED + CurrentBox * SIZE_BOX + i * SIZE_STORED);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
byte[] TempParty = new byte[PokemonList1.GetDataLength(PokemonList1.CapacityType.Party, Japanese)];
|
var party = GetData(Japanese ? 0x2ED5 : 0x2F2C, SIZE_STOREDPARTY);
|
||||||
Array.Copy(Data, Japanese ? 0x2ED5 : 0x2F2C, TempParty, 0, TempParty.Length);
|
var partyPL = new PokeList1(party, PokeListType.Party, Japanese);
|
||||||
PokemonList1 partyList = new PokemonList1(TempParty, PokemonList1.CapacityType.Party, Japanese);
|
for (int i = 0; i < partyPL.Pokemon.Length; i++)
|
||||||
for (int i = 0; i < partyList.Pokemon.Length; i++)
|
|
||||||
{
|
{
|
||||||
if (i < partyList.Count)
|
var dest = GetPartyOffset(i);
|
||||||
{
|
var pkDat = i < partyPL.Count
|
||||||
byte[] pkDat = new PokemonList1(partyList[i]).GetBytes();
|
? new PokeList1(partyPL[i]).Write()
|
||||||
pkDat.CopyTo(Data, GetPartyOffset(i));
|
: new byte[PokeList1.GetDataLength(PokeListType.Single, Japanese)];
|
||||||
}
|
pkDat.CopyTo(Data, dest);
|
||||||
else
|
|
||||||
{
|
|
||||||
byte[] pkDat = new byte[PokemonList1.GetDataLength(PokemonList1.CapacityType.Single, Japanese)];
|
|
||||||
pkDat.CopyTo(Data, GetPartyOffset(i));
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
byte[] rawDC = new byte[0x38];
|
byte[] rawDC = new byte[0x38];
|
||||||
Array.Copy(Data, Japanese ? 0x2CA7 : 0x2CF4, rawDC, 0, rawDC.Length);
|
Array.Copy(Data, Japanese ? 0x2CA7 : 0x2CF4, rawDC, 0, rawDC.Length);
|
||||||
byte[] TempDaycare = new byte[PokemonList1.GetDataLength(PokemonList1.CapacityType.Single, Japanese)];
|
byte[] TempDaycare = new byte[PokeList1.GetDataLength(PokeListType.Single, Japanese)];
|
||||||
TempDaycare[0] = rawDC[0];
|
TempDaycare[0] = rawDC[0];
|
||||||
Array.Copy(rawDC, 1, TempDaycare, 2 + 1 + PKX.SIZE_1PARTY + StringLength, StringLength);
|
Array.Copy(rawDC, 1, TempDaycare, 2 + 1 + PKX.SIZE_1PARTY + StringLength, StringLength);
|
||||||
Array.Copy(rawDC, 1 + StringLength, TempDaycare, 2 + 1 + PKX.SIZE_1PARTY, StringLength);
|
Array.Copy(rawDC, 1 + StringLength, TempDaycare, 2 + 1 + PKX.SIZE_1PARTY, StringLength);
|
||||||
Array.Copy(rawDC, 1 + 2 * StringLength, TempDaycare, 2 + 1, PKX.SIZE_1STORED);
|
Array.Copy(rawDC, 1 + 2 * StringLength, TempDaycare, 2 + 1, PKX.SIZE_1STORED);
|
||||||
PokemonList1 daycareList = new PokemonList1(TempDaycare, PokemonList1.CapacityType.Single, Japanese);
|
PokeList1 daycareList = new PokeList1(TempDaycare, PokeListType.Single, Japanese);
|
||||||
daycareList.GetBytes().CopyTo(Data, GetPartyOffset(7));
|
daycareList.Write().CopyTo(Data, GetPartyOffset(7));
|
||||||
Daycare = GetPartyOffset(7);
|
Daycare = GetPartyOffset(7);
|
||||||
|
|
||||||
EventFlag = Japanese ? 0x29E9 : 0x29F3;
|
EventFlag = Japanese ? 0x29E9 : 0x29F3;
|
||||||
|
@ -127,25 +112,29 @@ namespace PKHeX.Core
|
||||||
|
|
||||||
protected override byte[] Write(bool DSV)
|
protected override byte[] Write(bool DSV)
|
||||||
{
|
{
|
||||||
|
var capacity = Japanese ? PokeListType.StoredJP : PokeListType.Stored;
|
||||||
for (int i = 0; i < BoxCount; i++)
|
for (int i = 0; i < BoxCount; i++)
|
||||||
{
|
{
|
||||||
PokemonList1 boxPL = new PokemonList1(Japanese ? PokemonList1.CapacityType.StoredJP : PokemonList1.CapacityType.Stored, Japanese);
|
var boxPL = new PokeList1(capacity, Japanese);
|
||||||
int slot = 0;
|
int slot = 0;
|
||||||
for (int j = 0; j < boxPL.Pokemon.Length; j++)
|
for (int j = 0; j < boxPL.Pokemon.Length; j++)
|
||||||
{
|
{
|
||||||
PK1 boxPK = (PK1) GetPKM(GetData(GetBoxOffset(i) + j*SIZE_STORED, SIZE_STORED));
|
PK1 boxPK = (PK1)GetPKM(GetData(GetBoxOffset(i) + (j * SIZE_STORED), SIZE_STORED));
|
||||||
if (boxPK.Species > 0)
|
if (boxPK.Species > 0)
|
||||||
boxPL[slot++] = boxPK;
|
boxPL[slot++] = boxPK;
|
||||||
}
|
}
|
||||||
if (i < BoxCount / 2)
|
|
||||||
boxPL.GetBytes().CopyTo(Data, 0x4000 + i * SIZE_STOREDBOX);
|
// copy to box location
|
||||||
else
|
var boxdata = boxPL.Write();
|
||||||
boxPL.GetBytes().CopyTo(Data, 0x6000 + (i - BoxCount / 2) * SIZE_STOREDBOX);
|
int ofs = GetBoxRawDataOffset(i);
|
||||||
|
SetData(boxdata, ofs);
|
||||||
|
|
||||||
|
// copy to active loc if current box
|
||||||
if (i == CurrentBox)
|
if (i == CurrentBox)
|
||||||
boxPL.GetBytes().CopyTo(Data, Japanese ? 0x302D : 0x30C0);
|
SetData(boxdata, Japanese ? 0x302D : 0x30C0);
|
||||||
}
|
}
|
||||||
|
|
||||||
PokemonList1 partyPL = new PokemonList1(PokemonList1.CapacityType.Party, Japanese);
|
var partyPL = new PokeList1(PokeListType.Party, Japanese);
|
||||||
int pSlot = 0;
|
int pSlot = 0;
|
||||||
for (int i = 0; i < 6; i++)
|
for (int i = 0; i < 6; i++)
|
||||||
{
|
{
|
||||||
|
@ -153,7 +142,7 @@ namespace PKHeX.Core
|
||||||
if (partyPK.Species > 0)
|
if (partyPK.Species > 0)
|
||||||
partyPL[pSlot++] = partyPK;
|
partyPL[pSlot++] = partyPK;
|
||||||
}
|
}
|
||||||
partyPL.GetBytes().CopyTo(Data, Japanese ? 0x2ED5 : 0x2F2C);
|
partyPL.Write().CopyTo(Data, Japanese ? 0x2ED5 : 0x2F2C);
|
||||||
|
|
||||||
// Daycare is read-only, but in case it ever becomes editable, copy it back in.
|
// Daycare is read-only, but in case it ever becomes editable, copy it back in.
|
||||||
byte[] rawDC = GetData(GetDaycareSlotOffset(loc: 0, slot: 0), SIZE_STORED);
|
byte[] rawDC = GetData(GetDaycareSlotOffset(loc: 0, slot: 0), SIZE_STORED);
|
||||||
|
@ -170,13 +159,21 @@ namespace PKHeX.Core
|
||||||
return outData;
|
return outData;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private int GetBoxRawDataOffset(int i)
|
||||||
|
{
|
||||||
|
if (i < BoxCount / 2)
|
||||||
|
return 0x4000 + (i * SIZE_STOREDBOX);
|
||||||
|
return 0x6000 + ((i - (BoxCount / 2)) * SIZE_STOREDBOX);
|
||||||
|
}
|
||||||
|
|
||||||
// Configuration
|
// Configuration
|
||||||
public override SaveFile Clone() { return new SAV1(Write(DSV: false)); }
|
public override SaveFile Clone() { return new SAV1(Write(DSV: false)); }
|
||||||
|
|
||||||
public override int SIZE_STORED => Japanese ? PKX.SIZE_1JLIST : PKX.SIZE_1ULIST;
|
public override int SIZE_STORED => Japanese ? PKX.SIZE_1JLIST : PKX.SIZE_1ULIST;
|
||||||
protected override int SIZE_PARTY => Japanese ? PKX.SIZE_1JLIST : PKX.SIZE_1ULIST;
|
protected override int SIZE_PARTY => Japanese ? PKX.SIZE_1JLIST : PKX.SIZE_1ULIST;
|
||||||
private int SIZE_BOX => BoxSlotCount*SIZE_STORED;
|
private int SIZE_BOX => BoxSlotCount*SIZE_STORED;
|
||||||
private int SIZE_STOREDBOX => PokemonList1.GetDataLength(Japanese ? PokemonList1.CapacityType.StoredJP : PokemonList1.CapacityType.Stored, Japanese);
|
private int SIZE_STOREDBOX => PokeList1.GetDataLength(Japanese ? PokeListType.StoredJP : PokeListType.Stored, Japanese);
|
||||||
|
private int SIZE_STOREDPARTY => PokeList1.GetDataLength(PokeListType.Party, Japanese);
|
||||||
|
|
||||||
public override PKM BlankPKM => new PK1(null, null, Japanese);
|
public override PKM BlankPKM => new PK1(null, null, Japanese);
|
||||||
public override Type PKMType => typeof(PK1);
|
public override Type PKMType => typeof(PK1);
|
||||||
|
@ -441,7 +438,7 @@ namespace PKHeX.Core
|
||||||
public override PKM GetPKM(byte[] data)
|
public override PKM GetPKM(byte[] data)
|
||||||
{
|
{
|
||||||
if (data.Length == SIZE_STORED)
|
if (data.Length == SIZE_STORED)
|
||||||
return new PokemonList1(data, PokemonList1.CapacityType.Single, Japanese)[0];
|
return new PokeList1(data, PokeListType.Single, Japanese)[0];
|
||||||
return new PK1(data);
|
return new PK1(data);
|
||||||
}
|
}
|
||||||
public override byte[] DecryptPKM(byte[] data)
|
public override byte[] DecryptPKM(byte[] data)
|
||||||
|
|
|
@ -54,60 +54,47 @@ namespace PKHeX.Core
|
||||||
HeldItems = Legal.HeldItems_GSC;
|
HeldItems = Legal.HeldItems_GSC;
|
||||||
|
|
||||||
// Stash boxes after the save file's end.
|
// Stash boxes after the save file's end.
|
||||||
byte[] TempBox = new byte[SIZE_STOREDBOX];
|
int splitAtIndex = (Japanese ? 6 : 7);
|
||||||
|
int stored = SIZE_STOREDBOX;
|
||||||
|
int baseDest = Data.Length - SIZE_RESERVED;
|
||||||
|
var capacity = Japanese ? PokeListType.StoredJP : PokeListType.Stored;
|
||||||
for (int i = 0; i < BoxCount; i++)
|
for (int i = 0; i < BoxCount; i++)
|
||||||
{
|
{
|
||||||
if (i < (Japanese ? 6 : 7))
|
int ofs = GetBoxRawDataOffset(i, splitAtIndex);
|
||||||
Array.Copy(Data, 0x4000 + i * (TempBox.Length + 2), TempBox, 0, TempBox.Length);
|
var box = GetData(ofs, stored);
|
||||||
else
|
var boxDest = baseDest + (i * SIZE_BOX);
|
||||||
Array.Copy(Data, 0x6000 + (i - (Japanese ? 6 : 7)) * (TempBox.Length + 2), TempBox, 0, TempBox.Length);
|
var boxPL = new PokeList2(box, capacity, Japanese);
|
||||||
PokemonList2 PL2 = new PokemonList2(TempBox, Japanese ? PokemonList2.CapacityType.StoredJP : PokemonList2.CapacityType.Stored, Japanese);
|
for (int j = 0; j < boxPL.Pokemon.Length; j++)
|
||||||
for (int j = 0; j < PL2.Pokemon.Length; j++)
|
|
||||||
{
|
{
|
||||||
if (j < PL2.Count)
|
var dest = boxDest + (j * SIZE_STORED);
|
||||||
{
|
var pkDat = (j < boxPL.Count)
|
||||||
byte[] pkDat = new PokemonList2(PL2[j]).GetBytes();
|
? new PokeList2(boxPL[j]).Write()
|
||||||
pkDat.CopyTo(Data, Data.Length - SIZE_RESERVED + i * SIZE_BOX + j * SIZE_STORED);
|
: new byte[PokeList2.GetDataLength(PokeListType.Single, Japanese)];
|
||||||
}
|
pkDat.CopyTo(Data, dest);
|
||||||
else
|
|
||||||
{
|
|
||||||
byte[] pkDat = new byte[PokemonList2.GetDataLength(PokemonList2.CapacityType.Single, Japanese)];
|
|
||||||
pkDat.CopyTo(Data, Data.Length - SIZE_RESERVED + i * SIZE_BOX + j * SIZE_STORED);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Array.Copy(Data, Offsets.CurrentBox, TempBox, 0, TempBox.Length);
|
var current = GetData(Offsets.CurrentBox, stored);
|
||||||
PokemonList2 curBoxPL = new PokemonList2(TempBox, Japanese ? PokemonList2.CapacityType.StoredJP : PokemonList2.CapacityType.Stored, Japanese);
|
var curBoxPL = new PokeList2(current, capacity, Japanese);
|
||||||
|
var curDest = baseDest + (CurrentBox * SIZE_BOX);
|
||||||
for (int i = 0; i < curBoxPL.Pokemon.Length; i++)
|
for (int i = 0; i < curBoxPL.Pokemon.Length; i++)
|
||||||
{
|
{
|
||||||
if (i < curBoxPL.Count)
|
var dest = curDest + (i * SIZE_STORED);
|
||||||
{
|
var pkDat = i < curBoxPL.Count
|
||||||
byte[] pkDat = new PokemonList2(curBoxPL[i]).GetBytes();
|
? new PokeList2(curBoxPL[i]).Write()
|
||||||
pkDat.CopyTo(Data, Data.Length - SIZE_RESERVED + CurrentBox * SIZE_BOX + i * SIZE_STORED);
|
: new byte[PokeList2.GetDataLength(PokeListType.Single, Japanese)];
|
||||||
}
|
pkDat.CopyTo(Data, dest);
|
||||||
else
|
|
||||||
{
|
|
||||||
byte[] pkDat = new byte[PokemonList2.GetDataLength(PokemonList2.CapacityType.Single, Japanese)];
|
|
||||||
pkDat.CopyTo(Data, Data.Length - SIZE_RESERVED + CurrentBox * SIZE_BOX + i * SIZE_STORED);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
byte[] TempParty = new byte[PokemonList2.GetDataLength(PokemonList2.CapacityType.Party, Japanese)];
|
var party = GetData(Offsets.Party, SIZE_STOREDPARTY);
|
||||||
Array.Copy(Data, Offsets.Party, TempParty, 0, TempParty.Length);
|
var partyPL = new PokeList2(party, PokeListType.Party, Japanese);
|
||||||
PokemonList2 partyList = new PokemonList2(TempParty, PokemonList2.CapacityType.Party, Japanese);
|
for (int i = 0; i < partyPL.Pokemon.Length; i++)
|
||||||
for (int i = 0; i < partyList.Pokemon.Length; i++)
|
|
||||||
{
|
{
|
||||||
if (i < partyList.Count)
|
var dest = GetPartyOffset(i);
|
||||||
{
|
var pkDat = i < partyPL.Count
|
||||||
byte[] pkDat = new PokemonList2(partyList[i]).GetBytes();
|
? new PokeList2(partyPL[i]).Write()
|
||||||
pkDat.CopyTo(Data, GetPartyOffset(i));
|
: new byte[PokeList2.GetDataLength(PokeListType.Single, Japanese)];
|
||||||
}
|
pkDat.CopyTo(Data, dest);
|
||||||
else
|
|
||||||
{
|
|
||||||
byte[] pkDat = new byte[PokemonList2.GetDataLength(PokemonList2.CapacityType.Single, Japanese)];
|
|
||||||
pkDat.CopyTo(Data, GetPartyOffset(i));
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Daycare currently undocumented for all Gen II games.
|
// Daycare currently undocumented for all Gen II games.
|
||||||
|
@ -117,21 +104,21 @@ namespace PKHeX.Core
|
||||||
|
|
||||||
DaycareFlags[0] = Data[offset]; offset++;
|
DaycareFlags[0] = Data[offset]; offset++;
|
||||||
var pk1 = ReadPKMFromOffset(offset); // parent 1
|
var pk1 = ReadPKMFromOffset(offset); // parent 1
|
||||||
var daycare1 = new PokemonList2(pk1);
|
var daycare1 = new PokeList2(pk1);
|
||||||
offset += StringLength * 2 + 0x20; // nick/ot/pkm
|
offset += StringLength * 2 + 0x20; // nick/ot/pkm
|
||||||
DaycareFlags[1] = Data[offset]; offset++;
|
DaycareFlags[1] = Data[offset]; offset++;
|
||||||
byte steps = Data[offset]; offset++;
|
byte steps = Data[offset]; offset++;
|
||||||
byte BreedMotherOrNonDitto = Data[offset]; offset++;
|
byte BreedMotherOrNonDitto = Data[offset]; offset++;
|
||||||
var pk2 = ReadPKMFromOffset(offset); // parent 2
|
var pk2 = ReadPKMFromOffset(offset); // parent 2
|
||||||
var daycare2 = new PokemonList2(pk2);
|
var daycare2 = new PokeList2(pk2);
|
||||||
offset += StringLength * 2 + PKX.SIZE_2STORED; // nick/ot/pkm
|
offset += StringLength * 2 + PKX.SIZE_2STORED; // nick/ot/pkm
|
||||||
var pk3 = ReadPKMFromOffset(offset); // egg!
|
var pk3 = ReadPKMFromOffset(offset); // egg!
|
||||||
pk3.IsEgg = true;
|
pk3.IsEgg = true;
|
||||||
var daycare3 = new PokemonList2(pk3);
|
var daycare3 = new PokeList2(pk3);
|
||||||
|
|
||||||
daycare1.GetBytes().CopyTo(Data, GetPartyOffset(7 + (0 * 2)));
|
daycare1.Write().CopyTo(Data, GetPartyOffset(7 + (0 * 2)));
|
||||||
daycare2.GetBytes().CopyTo(Data, GetPartyOffset(7 + (1 * 2)));
|
daycare2.Write().CopyTo(Data, GetPartyOffset(7 + (1 * 2)));
|
||||||
daycare3.GetBytes().CopyTo(Data, GetPartyOffset(7 + (2 * 2)));
|
daycare3.Write().CopyTo(Data, GetPartyOffset(7 + (2 * 2)));
|
||||||
Daycare = Offsets.Daycare;
|
Daycare = Offsets.Daycare;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -160,11 +147,20 @@ namespace PKHeX.Core
|
||||||
public bool Korean { get; }
|
public bool Korean { get; }
|
||||||
private readonly SAV2Offsets Offsets;
|
private readonly SAV2Offsets Offsets;
|
||||||
|
|
||||||
|
private int GetBoxRawDataOffset(int i, int splitAtIndex)
|
||||||
|
{
|
||||||
|
if (i < splitAtIndex)
|
||||||
|
return 0x4000 + (i * (SIZE_STOREDBOX + 2));
|
||||||
|
return 0x6000 + ((i - splitAtIndex) * (SIZE_STOREDBOX + 2));
|
||||||
|
}
|
||||||
|
|
||||||
protected override byte[] Write(bool DSV)
|
protected override byte[] Write(bool DSV)
|
||||||
{
|
{
|
||||||
|
int len = SIZE_STOREDBOX;
|
||||||
|
int splitAtIndex = (Japanese ? 6 : 7);
|
||||||
for (int i = 0; i < BoxCount; i++)
|
for (int i = 0; i < BoxCount; i++)
|
||||||
{
|
{
|
||||||
PokemonList2 boxPL = new PokemonList2(Japanese ? PokemonList2.CapacityType.StoredJP : PokemonList2.CapacityType.Stored, Japanese);
|
var boxPL = new PokeList2(Japanese ? PokeListType.StoredJP : PokeListType.Stored, Japanese);
|
||||||
int slot = 0;
|
int slot = 0;
|
||||||
for (int j = 0; j < boxPL.Pokemon.Length; j++)
|
for (int j = 0; j < boxPL.Pokemon.Length; j++)
|
||||||
{
|
{
|
||||||
|
@ -172,15 +168,14 @@ namespace PKHeX.Core
|
||||||
if (boxPK.Species > 0)
|
if (boxPK.Species > 0)
|
||||||
boxPL[slot++] = boxPK;
|
boxPL[slot++] = boxPK;
|
||||||
}
|
}
|
||||||
if (i < (Japanese ? 6 : 7))
|
|
||||||
boxPL.GetBytes().CopyTo(Data, 0x4000 + i * (SIZE_STOREDBOX + 2));
|
int src = GetBoxRawDataOffset(i, splitAtIndex);
|
||||||
else
|
boxPL.Write().CopyTo(Data, src);
|
||||||
boxPL.GetBytes().CopyTo(Data, 0x6000 + (i - (Japanese ? 6 : 7)) * (SIZE_STOREDBOX + 2));
|
|
||||||
if (i == CurrentBox)
|
if (i == CurrentBox)
|
||||||
boxPL.GetBytes().CopyTo(Data, Offsets.CurrentBox);
|
boxPL.Write().CopyTo(Data, Offsets.CurrentBox);
|
||||||
}
|
}
|
||||||
|
|
||||||
PokemonList2 partyPL = new PokemonList2(PokemonList2.CapacityType.Party, Japanese);
|
var partyPL = new PokeList2(PokeListType.Party, Japanese);
|
||||||
int pSlot = 0;
|
int pSlot = 0;
|
||||||
for (int i = 0; i < 6; i++)
|
for (int i = 0; i < 6; i++)
|
||||||
{
|
{
|
||||||
|
@ -188,7 +183,7 @@ namespace PKHeX.Core
|
||||||
if (partyPK.Species > 0)
|
if (partyPK.Species > 0)
|
||||||
partyPL[pSlot++] = partyPK;
|
partyPL[pSlot++] = partyPK;
|
||||||
}
|
}
|
||||||
partyPL.GetBytes().CopyTo(Data, Offsets.Party);
|
partyPL.Write().CopyTo(Data, Offsets.Party);
|
||||||
|
|
||||||
SetChecksums();
|
SetChecksums();
|
||||||
if (Japanese)
|
if (Japanese)
|
||||||
|
@ -246,7 +241,8 @@ namespace PKHeX.Core
|
||||||
public override Type PKMType => typeof(PK2);
|
public override Type PKMType => typeof(PK2);
|
||||||
|
|
||||||
private int SIZE_BOX => BoxSlotCount*SIZE_STORED;
|
private int SIZE_BOX => BoxSlotCount*SIZE_STORED;
|
||||||
private int SIZE_STOREDBOX => PokemonList2.GetDataLength(Japanese ? PokemonList2.CapacityType.StoredJP : PokemonList2.CapacityType.Stored, Japanese);
|
private int SIZE_STOREDBOX => PokeList2.GetDataLength(Japanese ? PokeListType.StoredJP : PokeListType.Stored, Japanese);
|
||||||
|
private int SIZE_STOREDPARTY => PokeList2.GetDataLength(PokeListType.Party, Japanese);
|
||||||
|
|
||||||
public override int MaxMoveID => Legal.MaxMoveID_2;
|
public override int MaxMoveID => Legal.MaxMoveID_2;
|
||||||
public override int MaxSpeciesID => Legal.MaxSpeciesID_2;
|
public override int MaxSpeciesID => Legal.MaxSpeciesID_2;
|
||||||
|
@ -482,7 +478,7 @@ namespace PKHeX.Core
|
||||||
public override PKM GetPKM(byte[] data)
|
public override PKM GetPKM(byte[] data)
|
||||||
{
|
{
|
||||||
if (data.Length == SIZE_STORED)
|
if (data.Length == SIZE_STORED)
|
||||||
return new PokemonList2(data, PokemonList2.CapacityType.Single, Japanese)[0];
|
return new PokeList2(data, PokeListType.Single, Japanese)[0];
|
||||||
return new PK2(data);
|
return new PK2(data);
|
||||||
}
|
}
|
||||||
public override byte[] DecryptPKM(byte[] data)
|
public override byte[] DecryptPKM(byte[] data)
|
||||||
|
|
Loading…
Reference in a new issue