mirror of
https://github.com/mm201/pkmn-classic-framework.git
synced 2026-09-11 11:45:16 -05:00
Created base class for GTS records implementing BinarySerializableBase
This commit is contained in:
@@ -90,6 +90,7 @@
|
||||
<Compile Include="Structures\GtsRecord5.cs" />
|
||||
<Compile Include="Structures\Enums.cs" />
|
||||
<Compile Include="Structures\GtsRecord4.cs" />
|
||||
<Compile Include="Structures\GtsRecordBase.cs" />
|
||||
<Compile Include="Structures\IvStatValues.cs" />
|
||||
<Compile Include="Structures\MoveSlot.cs" />
|
||||
<Compile Include="Structures\MusicalRecord5.cs" />
|
||||
|
||||
@@ -13,19 +13,24 @@ namespace PkmnFoundations.Structures
|
||||
/// Includes a Pokémon box structure and metadata related to the trainer
|
||||
/// and request.
|
||||
/// </summary>
|
||||
public class GtsRecord4 : IEquatable<GtsRecord4>
|
||||
public class GtsRecord4 : GtsRecordBase, IEquatable<GtsRecord4>
|
||||
{
|
||||
// todo: We should have a base class for Gen4/5 GTS records.
|
||||
|
||||
public GtsRecord4()
|
||||
public GtsRecord4() : base()
|
||||
{
|
||||
Initialize();
|
||||
}
|
||||
|
||||
public GtsRecord4(byte[] data)
|
||||
public GtsRecord4(byte[] data) : base()
|
||||
{
|
||||
Initialize();
|
||||
Load(data);
|
||||
}
|
||||
|
||||
private void Initialize()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Obfuscated Pokémon (pkm) data. 236 bytes
|
||||
/// </summary>
|
||||
@@ -83,66 +88,65 @@ namespace PkmnFoundations.Structures
|
||||
public byte TrainerVersion;
|
||||
public byte TrainerLanguage;
|
||||
|
||||
public byte[] Save()
|
||||
protected override void Save(BinaryWriter writer)
|
||||
{
|
||||
// todo: enclose in properties and validate these when assigning.
|
||||
if (Data.Length != 0xEC) throw new FormatException("PKM length is incorrect");
|
||||
if (TrainerName.RawData.Length != 0x10) throw new FormatException("Trainer name length is incorrect");
|
||||
byte[] data = new byte[292];
|
||||
MemoryStream s = new MemoryStream(data);
|
||||
s.Write(Data, 0, 0xEC);
|
||||
s.Write(BitConverter.GetBytes(Species), 0, 2);
|
||||
s.WriteByte((byte)Gender);
|
||||
s.WriteByte(Level);
|
||||
s.Write(BitConverter.GetBytes(RequestedSpecies), 0, 2);
|
||||
s.WriteByte((byte)RequestedGender);
|
||||
s.WriteByte(RequestedMinLevel);
|
||||
s.WriteByte(RequestedMaxLevel);
|
||||
s.WriteByte(Unknown1);
|
||||
s.WriteByte((byte)TrainerGender);
|
||||
s.WriteByte(Unknown2);
|
||||
s.Write(BitConverter.GetBytes(DateToTimestamp(TimeDeposited)), 0, 8);
|
||||
s.Write(BitConverter.GetBytes(DateToTimestamp(TimeExchanged)), 0, 8);
|
||||
s.Write(BitConverter.GetBytes(PID), 0, 4);
|
||||
s.Write(TrainerName.RawData, 0, 0x10);
|
||||
s.Write(BitConverter.GetBytes(TrainerOT), 0, 2);
|
||||
s.WriteByte(TrainerCountry);
|
||||
s.WriteByte(TrainerRegion);
|
||||
s.WriteByte(TrainerClass);
|
||||
s.WriteByte(IsExchanged);
|
||||
s.WriteByte(TrainerVersion);
|
||||
s.WriteByte(TrainerLanguage);
|
||||
s.Close();
|
||||
return data;
|
||||
|
||||
writer.Write(Data, 0, 0xEC); // 0x0000
|
||||
writer.Write(Species); // 0x00EC
|
||||
writer.Write((byte)Gender); // 0x00EE
|
||||
writer.Write(Level); // 0x00EF
|
||||
writer.Write(RequestedSpecies); // 0x00F0
|
||||
writer.Write((byte)RequestedGender); // 0x00F2
|
||||
writer.Write(RequestedMinLevel); // 0x00F3
|
||||
writer.Write(RequestedMaxLevel); // 0x00F4
|
||||
writer.Write(Unknown1); // 0x00F5
|
||||
writer.Write((byte)TrainerGender); // 0x00F6
|
||||
writer.Write(Unknown2); // 0x00F7
|
||||
writer.Write(DateToTimestamp(TimeDeposited)); // 0x00F8
|
||||
writer.Write(DateToTimestamp(TimeExchanged)); // 0x0100
|
||||
writer.Write(PID); // 0x0108
|
||||
writer.Write(TrainerName.RawData, 0, 0x10); // 0x010C
|
||||
writer.Write(TrainerOT); // 0x011C
|
||||
writer.Write(TrainerCountry); // 0x011E
|
||||
writer.Write(TrainerRegion); // 0x011F
|
||||
writer.Write(TrainerClass); // 0x0120
|
||||
writer.Write(IsExchanged); // 0x0121
|
||||
writer.Write(TrainerVersion); // 0x0122
|
||||
writer.Write(TrainerLanguage); // 0x0123
|
||||
}
|
||||
|
||||
public void Load(byte[] data)
|
||||
protected override void Load(BinaryReader reader)
|
||||
{
|
||||
if (data.Length != 292) throw new FormatException("GTS record length is incorrect.");
|
||||
Data = reader.ReadBytes(0xEC); // 0x0000
|
||||
Species = reader.ReadUInt16(); // 0x00EC
|
||||
Gender = (Genders)reader.ReadByte(); // 0x00EE
|
||||
Level = reader.ReadByte(); // 0x00EF
|
||||
RequestedSpecies = reader.ReadUInt16(); // 0x00F0
|
||||
RequestedGender = (Genders)reader.ReadByte(); // 0x00F2
|
||||
RequestedMinLevel = reader.ReadByte(); // 0x00F3
|
||||
RequestedMaxLevel = reader.ReadByte(); // 0x00F4
|
||||
Unknown1 = reader.ReadByte(); // 0x00F5
|
||||
TrainerGender = (TrainerGenders)reader.ReadByte(); // 0x00F6
|
||||
Unknown2 = reader.ReadByte(); // 0x00F7
|
||||
TimeDeposited = TimestampToDate(reader.ReadUInt64()); // 0x00F8
|
||||
TimeExchanged = TimestampToDate(reader.ReadUInt64()); // 0x0100
|
||||
PID = reader.ReadInt32(); // 0x0108
|
||||
TrainerName = new EncodedString4(reader.ReadBytes(0x10)); // 0x010C
|
||||
TrainerOT = reader.ReadUInt16(); // 0x011C
|
||||
TrainerCountry = reader.ReadByte(); // 0x011E
|
||||
TrainerRegion = reader.ReadByte(); // 0x011F
|
||||
TrainerClass = reader.ReadByte(); // 0x0120
|
||||
IsExchanged = reader.ReadByte(); // 0x0121
|
||||
TrainerVersion = reader.ReadByte(); // 0x0122
|
||||
TrainerLanguage = reader.ReadByte(); // 0x0123
|
||||
}
|
||||
|
||||
Data = new byte[0xEC];
|
||||
Array.Copy(data, 0, Data, 0, 0xEC);
|
||||
Species = BitConverter.ToUInt16(data, 0xEC);
|
||||
Gender = (Genders)data[0xEE];
|
||||
Level = data[0xEF];
|
||||
RequestedSpecies = BitConverter.ToUInt16(data, 0xF0);
|
||||
RequestedGender = (Genders)data[0xF2];
|
||||
RequestedMinLevel = data[0xF3];
|
||||
RequestedMaxLevel = data[0xF4];
|
||||
Unknown1 = data[0xF5];
|
||||
TrainerGender = (TrainerGenders)data[0xF6];
|
||||
Unknown2 = data[0xF7];
|
||||
TimeDeposited = TimestampToDate(BitConverter.ToUInt64(data, 0xF8));
|
||||
TimeExchanged = TimestampToDate(BitConverter.ToUInt64(data, 0x100));
|
||||
PID = BitConverter.ToInt32(data, 0x108);
|
||||
TrainerName = new EncodedString4(data, 0x10C, 0x10);
|
||||
TrainerOT = BitConverter.ToUInt16(data, 0x11C);
|
||||
TrainerCountry = data[0x11E];
|
||||
TrainerRegion = data[0x11F];
|
||||
TrainerClass = data[0x120];
|
||||
IsExchanged = data[0x121];
|
||||
TrainerVersion = data[0x122];
|
||||
TrainerLanguage = data[0x123];
|
||||
public override int Size
|
||||
{
|
||||
get { return 292; }
|
||||
}
|
||||
|
||||
public GtsRecord4 Clone()
|
||||
@@ -187,47 +191,6 @@ namespace PkmnFoundations.Structures
|
||||
IsExchanged = 0x01;
|
||||
}
|
||||
|
||||
public static bool CheckLevels(byte min, byte max, byte other)
|
||||
{
|
||||
if (max == 0) max = 255;
|
||||
return other >= min && other <= max;
|
||||
}
|
||||
|
||||
public static DateTime ? TimestampToDate(ulong timestamp)
|
||||
{
|
||||
if (timestamp == 0) return null;
|
||||
|
||||
ushort year = (ushort)((timestamp >> 0x30) & 0xffff);
|
||||
byte month = (byte)((timestamp >> 0x28) & 0xff);
|
||||
byte day = (byte)((timestamp >> 0x20) & 0xff);
|
||||
byte hour = (byte)((timestamp >> 0x18) & 0xff);
|
||||
byte minute = (byte)((timestamp >> 0x10) & 0xff);
|
||||
byte second = (byte)((timestamp >> 0x08) & 0xff);
|
||||
//byte fractional = (byte)(timestamp & 0xff); // always 0
|
||||
|
||||
try
|
||||
{
|
||||
return new DateTime(year, month, day, hour, minute, second);
|
||||
}
|
||||
catch (ArgumentOutOfRangeException)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
public static ulong DateToTimestamp(DateTime ? date)
|
||||
{
|
||||
if (date == null) return 0;
|
||||
DateTime date2 = (DateTime)date;
|
||||
|
||||
return (ulong)(date2.Year & 0xffff) << 0x30
|
||||
| (ulong)(date2.Month & 0xff) << 0x28
|
||||
| (ulong)(date2.Day & 0xff) << 0x20
|
||||
| (ulong)(date2.Hour & 0xff) << 0x18
|
||||
| (ulong)(date2.Minute & 0xff) << 0x10
|
||||
| (ulong)(date2.Second & 0xff) << 0x08;
|
||||
}
|
||||
|
||||
public static bool operator ==(GtsRecord4 a, GtsRecord4 b)
|
||||
{
|
||||
if ((object)a == null && (object)b == null) return true;
|
||||
|
||||
@@ -13,19 +13,24 @@ namespace PkmnFoundations.Structures
|
||||
/// Includes a Pokémon box structure and metadata related to the trainer
|
||||
/// and request.
|
||||
/// </summary>
|
||||
public class GtsRecord5 : IEquatable<GtsRecord5>
|
||||
public class GtsRecord5 : GtsRecordBase, IEquatable<GtsRecord5>
|
||||
{
|
||||
// todo: We should have a base class for Gen4/5 GTS records.
|
||||
|
||||
public GtsRecord5()
|
||||
{
|
||||
Initialize();
|
||||
}
|
||||
|
||||
public GtsRecord5(byte[] data)
|
||||
{
|
||||
Initialize();
|
||||
Load(data);
|
||||
}
|
||||
|
||||
private void Initialize()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
// xxx: Data and Unknown0 should be one field.
|
||||
|
||||
/// <summary>
|
||||
@@ -93,73 +98,72 @@ namespace PkmnFoundations.Structures
|
||||
public byte TrainerBadges; // speculative. Usually 8.
|
||||
public byte TrainerUnityTower;
|
||||
|
||||
public byte[] Save()
|
||||
protected override void Save(BinaryWriter writer)
|
||||
{
|
||||
// todo: enclose in properties and validate these when assigning.
|
||||
if (Data.Length != 0xDC) throw new FormatException("PKM length is incorrect");
|
||||
if (TrainerName.RawData.Length != 0x10) throw new FormatException("Trainer name length is incorrect");
|
||||
byte[] data = new byte[296];
|
||||
MemoryStream s = new MemoryStream(data);
|
||||
s.Write(Data, 0, 0xDC);
|
||||
s.Write(Unknown0, 0, 0x10);
|
||||
s.Write(BitConverter.GetBytes(Species), 0, 2);
|
||||
s.WriteByte((byte)Gender);
|
||||
s.WriteByte(Level);
|
||||
s.Write(BitConverter.GetBytes(RequestedSpecies), 0, 2);
|
||||
s.WriteByte((byte)RequestedGender);
|
||||
s.WriteByte(RequestedMinLevel);
|
||||
s.WriteByte(RequestedMaxLevel);
|
||||
s.WriteByte(Unknown1);
|
||||
s.WriteByte((byte)TrainerGender);
|
||||
s.WriteByte(Unknown2);
|
||||
s.Write(BitConverter.GetBytes(GtsRecord4.DateToTimestamp(TimeDeposited)), 0, 8);
|
||||
s.Write(BitConverter.GetBytes(GtsRecord4.DateToTimestamp(TimeExchanged)), 0, 8);
|
||||
s.Write(BitConverter.GetBytes(PID), 0, 4);
|
||||
s.Write(BitConverter.GetBytes(TrainerOT), 0, 4);
|
||||
s.Write(TrainerName.RawData, 0, 0x10);
|
||||
s.WriteByte(TrainerCountry);
|
||||
s.WriteByte(TrainerRegion);
|
||||
s.WriteByte(TrainerClass);
|
||||
s.WriteByte(IsExchanged);
|
||||
s.WriteByte(TrainerVersion);
|
||||
s.WriteByte(TrainerLanguage);
|
||||
s.WriteByte(TrainerBadges);
|
||||
s.WriteByte(TrainerUnityTower);
|
||||
s.Close();
|
||||
return data;
|
||||
|
||||
writer.Write(Data, 0, 0xDC); // 0x0000
|
||||
writer.Write(Unknown0, 0, 0x10); // 0x00DC
|
||||
|
||||
writer.Write(Species); // 0x00EC
|
||||
writer.Write((byte)Gender); // 0x00EE
|
||||
writer.Write(Level); // 0x00EF
|
||||
writer.Write(RequestedSpecies); // 0x00F0
|
||||
writer.Write((byte)RequestedGender); // 0x00F2
|
||||
writer.Write(RequestedMinLevel); // 0x00F3
|
||||
writer.Write(RequestedMaxLevel); // 0x00F4
|
||||
writer.Write(Unknown1); // 0x00F5
|
||||
writer.Write((byte)TrainerGender); // 0x00F6
|
||||
writer.Write(Unknown2); // 0x00F7
|
||||
writer.Write(DateToTimestamp(TimeDeposited)); // 0x00F8
|
||||
writer.Write(DateToTimestamp(TimeExchanged)); // 0x0100
|
||||
writer.Write(PID); // 0x0108
|
||||
writer.Write(TrainerOT); // 0x010C
|
||||
writer.Write(TrainerName.RawData, 0, 0x10); // 0x0110
|
||||
writer.Write(TrainerCountry); // 0x0120
|
||||
writer.Write(TrainerRegion); // 0x0121
|
||||
writer.Write(TrainerClass); // 0x0122
|
||||
writer.Write(IsExchanged); // 0x0123
|
||||
writer.Write(TrainerVersion); // 0x0124
|
||||
writer.Write(TrainerLanguage); // 0x0125
|
||||
writer.Write(TrainerBadges); // 0x0126
|
||||
writer.Write(TrainerUnityTower); // 0x0127
|
||||
}
|
||||
|
||||
public void Load(byte[] data)
|
||||
protected override void Load(BinaryReader reader)
|
||||
{
|
||||
if (data.Length != 296) throw new FormatException("GTS record length is incorrect.");
|
||||
Data = reader.ReadBytes(0xDC); // 0x0000
|
||||
Unknown0 = reader.ReadBytes(0x10); // 0x00DC
|
||||
Species = reader.ReadUInt16(); // 0x00EC
|
||||
Gender = (Genders)reader.ReadByte(); // 0x00EE
|
||||
Level = reader.ReadByte(); // 0x00EF
|
||||
RequestedSpecies = reader.ReadUInt16(); // 0x00F0
|
||||
RequestedGender = (Genders)reader.ReadByte(); // 0x00F2
|
||||
RequestedMinLevel = reader.ReadByte(); // 0x00F3
|
||||
RequestedMaxLevel = reader.ReadByte(); // 0x00F4
|
||||
Unknown1 = reader.ReadByte(); // 0x00F5
|
||||
TrainerGender = (TrainerGenders)reader.ReadByte(); // 0x00F6
|
||||
Unknown2 = reader.ReadByte(); // 0x00F7
|
||||
TimeDeposited = TimestampToDate(reader.ReadUInt64()); // 0x00F8
|
||||
TimeExchanged = TimestampToDate(reader.ReadUInt64()); // 0x0100
|
||||
PID = reader.ReadInt32(); // 0x0108
|
||||
TrainerOT = reader.ReadUInt32(); // 0x010C
|
||||
TrainerName = new EncodedString5(reader.ReadBytes(0x10)); // 0x0110
|
||||
TrainerCountry = reader.ReadByte(); // 0x0120
|
||||
TrainerRegion = reader.ReadByte(); // 0x0121
|
||||
TrainerClass = reader.ReadByte(); // 0x0122
|
||||
IsExchanged = reader.ReadByte(); // 0x0123
|
||||
TrainerVersion = reader.ReadByte(); // 0x0124
|
||||
TrainerLanguage = reader.ReadByte(); // 0x0125
|
||||
TrainerBadges = reader.ReadByte(); // 0x0126
|
||||
TrainerUnityTower = reader.ReadByte(); // 0x0127
|
||||
}
|
||||
|
||||
Data = new byte[0xDC];
|
||||
Array.Copy(data, 0, Data, 0, 0xDC);
|
||||
Unknown0 = new byte[0x10];
|
||||
Array.Copy(data, 0xDC, Unknown0, 0, 0x10);
|
||||
Species = BitConverter.ToUInt16(data, 0xEC);
|
||||
Gender = (Genders)data[0xEE];
|
||||
Level = data[0xEF];
|
||||
RequestedSpecies = BitConverter.ToUInt16(data, 0xF0);
|
||||
RequestedGender = (Genders)data[0xF2];
|
||||
RequestedMinLevel = data[0xF3];
|
||||
RequestedMaxLevel = data[0xF4];
|
||||
Unknown1 = data[0xF5];
|
||||
TrainerGender = (TrainerGenders)data[0xF6];
|
||||
Unknown2 = data[0xF7];
|
||||
TimeDeposited = GtsRecord4.TimestampToDate(BitConverter.ToUInt64(data, 0xF8));
|
||||
TimeExchanged = GtsRecord4.TimestampToDate(BitConverter.ToUInt64(data, 0x100));
|
||||
PID = BitConverter.ToInt32(data, 0x108);
|
||||
TrainerOT = BitConverter.ToUInt32(data, 0x10C);
|
||||
TrainerName = new EncodedString5(data, 0x110, 0x10);
|
||||
TrainerCountry = data[0x120];
|
||||
TrainerRegion = data[0x121];
|
||||
TrainerClass = data[0x122];
|
||||
IsExchanged = data[0x123];
|
||||
TrainerVersion = data[0x124];
|
||||
TrainerLanguage = data[0x125];
|
||||
TrainerBadges = data[0x126];
|
||||
TrainerUnityTower = data[0x127];
|
||||
public override int Size
|
||||
{
|
||||
get { return 296; }
|
||||
}
|
||||
|
||||
public GtsRecord5 Clone()
|
||||
@@ -204,12 +208,6 @@ namespace PkmnFoundations.Structures
|
||||
IsExchanged = 0x01;
|
||||
}
|
||||
|
||||
public static bool CheckLevels(byte min, byte max, byte other)
|
||||
{
|
||||
if (max == 0) max = 255;
|
||||
return other >= min && other <= max;
|
||||
}
|
||||
|
||||
public static bool operator ==(GtsRecord5 a, GtsRecord5 b)
|
||||
{
|
||||
if ((object)a == null && (object)b == null) return true;
|
||||
|
||||
53
library/Structures/GtsRecordBase.cs
Normal file
53
library/Structures/GtsRecordBase.cs
Normal file
@@ -0,0 +1,53 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
|
||||
namespace PkmnFoundations.Structures
|
||||
{
|
||||
public abstract class GtsRecordBase : BinarySerializableBase
|
||||
{
|
||||
|
||||
|
||||
public static bool CheckLevels(byte min, byte max, byte other)
|
||||
{
|
||||
if (max == 0) max = 255;
|
||||
return other >= min && other <= max;
|
||||
}
|
||||
|
||||
public static ulong DateToTimestamp(DateTime? date)
|
||||
{
|
||||
if (date == null) return 0;
|
||||
DateTime date2 = (DateTime)date;
|
||||
|
||||
return (ulong)(date2.Year & 0xffff) << 0x30
|
||||
| (ulong)(date2.Month & 0xff) << 0x28
|
||||
| (ulong)(date2.Day & 0xff) << 0x20
|
||||
| (ulong)(date2.Hour & 0xff) << 0x18
|
||||
| (ulong)(date2.Minute & 0xff) << 0x10
|
||||
| (ulong)(date2.Second & 0xff) << 0x08;
|
||||
}
|
||||
|
||||
public static DateTime? TimestampToDate(ulong timestamp)
|
||||
{
|
||||
if (timestamp == 0) return null;
|
||||
|
||||
ushort year = (ushort)((timestamp >> 0x30) & 0xffff);
|
||||
byte month = (byte)((timestamp >> 0x28) & 0xff);
|
||||
byte day = (byte)((timestamp >> 0x20) & 0xff);
|
||||
byte hour = (byte)((timestamp >> 0x18) & 0xff);
|
||||
byte minute = (byte)((timestamp >> 0x10) & 0xff);
|
||||
byte second = (byte)((timestamp >> 0x08) & 0xff);
|
||||
//byte fractional = (byte)(timestamp & 0xff); // always 0
|
||||
|
||||
try
|
||||
{
|
||||
return new DateTime(year, month, day, hour, minute, second);
|
||||
}
|
||||
catch (ArgumentOutOfRangeException)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user