mirror of
https://github.com/kwsch/pk3DS.git
synced 2026-10-03 06:16:55 -05:00
1329 lines
45 KiB
C#
1329 lines
45 KiB
C#
using System;
|
|
using System.Drawing;
|
|
using System.IO;
|
|
using System.Linq;
|
|
|
|
namespace pk3DS
|
|
{
|
|
public class RNG
|
|
{
|
|
public static uint Forward32(uint seed, int ctr)
|
|
{
|
|
for (int i = 0; i < ctr; i++)
|
|
{
|
|
seed *= 0x41C64E6D;
|
|
seed += 0x00006073;
|
|
}
|
|
return seed;
|
|
}
|
|
}
|
|
public class PersonalInfo
|
|
{
|
|
public byte HP, ATK, DEF, SPE, SPA, SPD;
|
|
public int BST;
|
|
private ushort EVs;
|
|
public int EV_HP, EV_ATK, EV_DEF, EV_SPE, EV_SPA, EV_SPD;
|
|
public byte[] Types = new byte[2];
|
|
public byte CatchRate, EvoStage;
|
|
public ushort[] Items = new ushort[3];
|
|
public byte Gender, HatchCycles, BaseFriendship, EXPGrowth;
|
|
public byte[] EggGroups = new byte[2];
|
|
public byte[] Abilities = new byte[3];
|
|
public ushort FormStats, FormeSprite, BaseEXP;
|
|
public byte FormeCount, Color;
|
|
public float Height, Weight;
|
|
public bool[] TMHM;
|
|
public bool[] Tutors;
|
|
public bool[][] ORASTutors = new bool[4][];
|
|
public byte EscapeRate;
|
|
public PersonalInfo(byte[] data)
|
|
{
|
|
using (BinaryReader br = new BinaryReader(new MemoryStream(data)))
|
|
{
|
|
HP = br.ReadByte(); ATK = br.ReadByte(); DEF = br.ReadByte();
|
|
SPE = br.ReadByte(); SPA = br.ReadByte(); SPD = br.ReadByte();
|
|
BST = HP + ATK + DEF + SPE + SPA + SPD;
|
|
|
|
Types = new[] { br.ReadByte(), br.ReadByte() };
|
|
CatchRate = br.ReadByte();
|
|
EvoStage = br.ReadByte();
|
|
|
|
EVs = br.ReadUInt16();
|
|
EV_HP = ((EVs >> 0) & 0x3);
|
|
EV_ATK = ((EVs >> 2) & 0x3);
|
|
EV_DEF = ((EVs >> 4) & 0x3);
|
|
EV_SPE = ((EVs >> 6) & 0x3);
|
|
EV_SPA = ((EVs >> 8) & 0x3);
|
|
EV_SPD = ((EVs >> 10) & 0x3);
|
|
|
|
Items = new[] { br.ReadUInt16(), br.ReadUInt16(), br.ReadUInt16() };
|
|
Gender = br.ReadByte();
|
|
HatchCycles = br.ReadByte();
|
|
BaseFriendship = br.ReadByte();
|
|
|
|
EXPGrowth = br.ReadByte();
|
|
EggGroups = new[] { br.ReadByte(), br.ReadByte() };
|
|
Abilities = new[] { br.ReadByte(), br.ReadByte(), br.ReadByte() };
|
|
EscapeRate = br.ReadByte();
|
|
FormStats = br.ReadUInt16();
|
|
|
|
FormeSprite = br.ReadUInt16();
|
|
FormeCount = br.ReadByte();
|
|
Color = br.ReadByte();
|
|
BaseEXP = br.ReadUInt16();
|
|
|
|
Height = br.ReadUInt16();
|
|
Weight = br.ReadUInt16();
|
|
|
|
byte[] TMHMData = br.ReadBytes(0x10);
|
|
TMHM = new bool[8 * TMHMData.Length];
|
|
for (int j = 0; j < TMHM.Length; j++)
|
|
TMHM[j] = ((TMHMData[j / 8] >> (j % 8)) & 0x1) == 1; //Bitflags for TMHM
|
|
|
|
byte[] TutorData = br.ReadBytes(8);
|
|
Tutors = new bool[8 * TutorData.Length];
|
|
for (int j = 0; j < Tutors.Length; j++)
|
|
Tutors[j] = ((TutorData[j / 8] >> (j % 8)) & 0x1) == 1; //Bitflags for Tutors
|
|
|
|
if (br.BaseStream.Length - br.BaseStream.Position == 0x10) // ORAS
|
|
{
|
|
byte[][] ORASTutorData =
|
|
{
|
|
br.ReadBytes(2), // 15
|
|
br.ReadBytes(3), // 17
|
|
br.ReadBytes(2), // 16
|
|
br.ReadBytes(2), // 15
|
|
};
|
|
for (int i = 0; i < 4; i++)
|
|
{
|
|
ORASTutors[i] = new bool[8 * ORASTutorData[i].Length];
|
|
for (int b = 0; b < 8 * ORASTutorData[i].Length; b++)
|
|
ORASTutors[i][b] = ((ORASTutorData[i][b / 8] >> (b % 8)) & 0x1) == 1;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
public byte[] Write()
|
|
{
|
|
using (MemoryStream ms = new MemoryStream())
|
|
using (BinaryWriter bw = new BinaryWriter(ms))
|
|
{
|
|
bw.Write(HP);
|
|
bw.Write(ATK);
|
|
bw.Write(DEF);
|
|
bw.Write(SPE);
|
|
bw.Write(SPA);
|
|
bw.Write(SPD);
|
|
foreach (byte Type in Types) bw.Write(Type);
|
|
bw.Write(CatchRate);
|
|
bw.Write(EvoStage);
|
|
EVs = (ushort)(EVs & 0x80 | ((EV_HP & 3) << 0) | ((EV_ATK & 3) << 2) | ((EV_DEF & 3) << 4) | ((EV_SPE & 3) << 6) | ((EV_SPA & 3) << 8) | ((EV_SPD & 3) << 10));
|
|
bw.Write(EVs);
|
|
foreach (ushort Item in Items) bw.Write(Item);
|
|
bw.Write(Gender);
|
|
bw.Write(HatchCycles);
|
|
bw.Write(BaseFriendship);
|
|
bw.Write(EXPGrowth);
|
|
foreach (byte EggGroup in EggGroups) bw.Write(EggGroup);
|
|
foreach (byte Ability in Abilities) bw.Write(Ability);
|
|
bw.Write(EscapeRate);
|
|
bw.Write(FormStats);
|
|
bw.Write(FormeSprite);
|
|
bw.Write(FormeCount);
|
|
bw.Write(Color);
|
|
bw.Write(BaseEXP);
|
|
bw.Write(BitConverter.GetBytes(Convert.ToUInt16(Height)));
|
|
bw.Write(BitConverter.GetBytes(Convert.ToUInt16(Weight)));
|
|
|
|
byte[] TMHMData = new byte[0x10];
|
|
for (int i = 0; i < TMHM.Length; i++)
|
|
TMHMData[i / 8] |= (byte)(TMHM[i] ? (1 << (i % 8)) : 0);
|
|
bw.Write(TMHMData);
|
|
|
|
byte[] TutorData = new byte[8];
|
|
for (int i = 0; i < Tutors.Length; i++)
|
|
TutorData[i / 8] |= (byte)(Tutors[i] ? (1 << (i % 8)) : 0);
|
|
bw.Write(TutorData);
|
|
|
|
while (bw.BaseStream.Length != 0x40) bw.Write((byte)0);
|
|
|
|
if (ORASTutors[0] != null) // ORAS Data
|
|
{
|
|
byte[][] ORASTutorData =
|
|
{
|
|
new byte[2], // 15
|
|
new byte[3], // 17
|
|
new byte[2], // 16
|
|
new byte[2], // 15
|
|
};
|
|
for (int i = 0; i < 4; i++)
|
|
for (int b = 0; b < ORASTutors[i].Length; b++)
|
|
ORASTutorData[i][b / 8] |= (byte)(ORASTutors[i][b] ? (1 << b % 8) : 0);
|
|
|
|
foreach (byte[] ORASTutor in ORASTutorData) bw.Write(ORASTutor);
|
|
|
|
while (bw.BaseStream.Length != 0x50) bw.Write((byte)0);
|
|
}
|
|
return ms.ToArray();
|
|
}
|
|
}
|
|
}
|
|
public class Trainer
|
|
{
|
|
public bool isORAS;
|
|
public int Format, Class;
|
|
public bool Item, Moves;
|
|
public byte BattleType, NumPokemon, AI;
|
|
public ushort[] Items = new ushort[4];
|
|
public byte u1, u2, u3;
|
|
public ushort uORAS;
|
|
public bool Healer;
|
|
public byte Money;
|
|
public ushort Prize;
|
|
public Pokemon[] Team;
|
|
public Trainer(byte[] trData, byte[] trPoke, bool ORAS)
|
|
{
|
|
using (BinaryReader br = new BinaryReader(new MemoryStream(trData)))
|
|
{
|
|
isORAS = ORAS;
|
|
Format = ORAS ? br.ReadUInt16() : br.ReadByte();
|
|
Class = ORAS ? br.ReadUInt16() : br.ReadByte();
|
|
if (ORAS) uORAS = br.ReadUInt16();
|
|
Item = ((Format >> 1) & 1) == 1;
|
|
Moves = (Format & 1) == 1;
|
|
BattleType = br.ReadByte();
|
|
NumPokemon = br.ReadByte();
|
|
for (int i = 0; i < 4; i++)
|
|
Items[i] = br.ReadUInt16();
|
|
AI = br.ReadByte();
|
|
u1 = br.ReadByte();
|
|
u2 = br.ReadByte();
|
|
u3 = br.ReadByte();
|
|
Healer = br.ReadByte() != 0;
|
|
Money = br.ReadByte();
|
|
Prize = br.ReadUInt16();
|
|
|
|
// Fetch Team
|
|
Team = new Pokemon[NumPokemon];
|
|
byte[][] TeamData = new byte[NumPokemon][];
|
|
int dataLen = trPoke.Length / NumPokemon;
|
|
for (int i = 0; i < TeamData.Length; i++)
|
|
TeamData[i] = trPoke.Skip(i * dataLen).Take(dataLen).ToArray();
|
|
for (int i = 0; i < NumPokemon; i++)
|
|
Team[i] = new Pokemon(TeamData[i], Item, Moves);
|
|
}
|
|
}
|
|
public byte[] Write()
|
|
{
|
|
using (MemoryStream ms = new MemoryStream())
|
|
using (BinaryWriter bw = new BinaryWriter(ms))
|
|
{
|
|
Format = Convert.ToByte(Moves) + (Convert.ToByte(Item) << 1);
|
|
if (isORAS)
|
|
{ bw.Write((ushort)Format); bw.Write((ushort)Class); bw.Write((ushort)0); }
|
|
else
|
|
{ bw.Write((byte)Format); bw.Write((byte)Class); }
|
|
|
|
bw.Write(BattleType);
|
|
bw.Write(NumPokemon);
|
|
bw.Write(Items[0]);
|
|
bw.Write(Items[1]);
|
|
bw.Write(Items[2]);
|
|
bw.Write(Items[3]);
|
|
|
|
bw.Write(AI);
|
|
bw.Write(u1);
|
|
bw.Write(u2);
|
|
bw.Write(u3);
|
|
bw.Write(Convert.ToByte(Healer));
|
|
bw.Write(Money);
|
|
bw.Write(Prize);
|
|
|
|
return ms.ToArray();
|
|
}
|
|
}
|
|
public byte[] WriteTeam()
|
|
{
|
|
return Team.Aggregate(new byte[0], (i, pkm) => i.Concat(pkm.Write(Item, Moves)).ToArray());
|
|
}
|
|
|
|
public class Pokemon
|
|
{
|
|
public byte IVs;
|
|
public byte PID;
|
|
public ushort Level;
|
|
public ushort Species;
|
|
public ushort Form;
|
|
public int Ability;
|
|
public int Gender;
|
|
public int uBit;
|
|
public ushort Item;
|
|
public ushort[] Moves = new ushort[4];
|
|
|
|
public Pokemon(byte[] data, bool HasItem, bool HasMoves)
|
|
{
|
|
using (BinaryReader br = new BinaryReader(new MemoryStream(data)))
|
|
{
|
|
IVs = br.ReadByte();
|
|
PID = br.ReadByte();
|
|
Level = br.ReadUInt16();
|
|
Species = br.ReadUInt16();
|
|
Form = br.ReadUInt16();
|
|
|
|
Ability = PID >> 4;
|
|
Gender = PID & 3;
|
|
uBit = (PID >> 3) & 1;
|
|
|
|
if (HasItem)
|
|
Item = br.ReadUInt16();
|
|
if (HasMoves)
|
|
for (int i = 0; i < 4; i++)
|
|
Moves[i] = br.ReadUInt16();
|
|
}
|
|
}
|
|
public byte[] Write(bool HasItem, bool HasMoves)
|
|
{
|
|
using (MemoryStream ms = new MemoryStream())
|
|
using (BinaryWriter bw = new BinaryWriter(ms))
|
|
{
|
|
bw.Write(IVs);
|
|
PID = (byte)(((Ability & 0xF) << 4) | ((uBit & 1) << 3) | (Gender & 0x7));
|
|
bw.Write(PID);
|
|
bw.Write(Level);
|
|
bw.Write(Species);
|
|
bw.Write(Form);
|
|
|
|
if (HasItem)
|
|
bw.Write(Item);
|
|
if (HasMoves)
|
|
foreach (ushort Move in Moves)
|
|
bw.Write(Move);
|
|
return ms.ToArray();
|
|
}
|
|
}
|
|
}
|
|
}
|
|
public class Move
|
|
{
|
|
public byte Type, Quality, Category, Power, Accuracy, PP, Priority, InflictPercent,
|
|
HitMin, HitMax, TurnMin, TurnMax, CritStage, Flinch, Recoil, Targeting,
|
|
Stat1, Stat2, Stat3,
|
|
Stat1Stage, Stat2Stage, Stat3Stage,
|
|
Stat1Percent, Stat2Percent, Stat3Percent;
|
|
|
|
public Heal Healing;
|
|
public ushort Inflict, Effect;
|
|
public byte _0xB, _0x1E, _0x1F, _0x20, _0x21;
|
|
public Move(byte[] data)
|
|
{
|
|
Type = data[0];
|
|
Quality = data[1];
|
|
Category = data[2];
|
|
Power = data[3];
|
|
Accuracy = data[4];
|
|
PP = data[5];
|
|
Priority = data[6];
|
|
HitMin = (byte)(data[7] & 0xF);
|
|
HitMax = (byte)(data[7] >> 4);
|
|
Inflict = BitConverter.ToUInt16(data, 0x8);
|
|
InflictPercent = data[0xA];
|
|
_0xB = data[0xB];
|
|
TurnMin = data[0xC];
|
|
TurnMax = data[0xD];
|
|
CritStage = data[0xE];
|
|
Flinch = data[0xF];
|
|
Effect = BitConverter.ToUInt16(data, 0x10);
|
|
Recoil = data[0x12];
|
|
Healing = new Heal(data[0x13]);
|
|
Targeting = data[0x14];
|
|
Stat1 = data[0x15];
|
|
Stat2 = data[0x16];
|
|
Stat3 = data[0x17];
|
|
Stat1Stage = data[0x18];
|
|
Stat2Stage = data[0x19];
|
|
Stat3Stage = data[0x1A];
|
|
Stat1Percent = data[0x1B];
|
|
Stat2Percent = data[0x1C];
|
|
Stat3Percent = data[0x1D];
|
|
_0x1E = data[0x1E];
|
|
_0x1F = data[0x1F];
|
|
_0x20 = data[0x20];
|
|
_0x21 = data[0x21];
|
|
}
|
|
public byte[] Write()
|
|
{
|
|
using (MemoryStream ms = new MemoryStream())
|
|
using (BinaryWriter bw = new BinaryWriter(ms))
|
|
{
|
|
bw.Write(Type);
|
|
bw.Write(Quality);
|
|
bw.Write(Category);
|
|
bw.Write(Power);
|
|
bw.Write(Accuracy);
|
|
bw.Write(PP);
|
|
bw.Write(Priority);
|
|
bw.Write((byte)(HitMin | (HitMax << 4)));
|
|
bw.Write(Inflict);
|
|
bw.Write(InflictPercent);
|
|
bw.Write(_0xB);
|
|
bw.Write(TurnMin);
|
|
bw.Write(TurnMax);
|
|
bw.Write(CritStage);
|
|
bw.Write(Flinch);
|
|
bw.Write(Effect);
|
|
bw.Write(Recoil);
|
|
bw.Write(Healing.Write());
|
|
bw.Write(Targeting);
|
|
bw.Write(Stat1);
|
|
bw.Write(Stat2);
|
|
bw.Write(Stat3);
|
|
bw.Write(Stat1Stage);
|
|
bw.Write(Stat2Stage);
|
|
bw.Write(Stat3Stage);
|
|
bw.Write(Stat1Percent);
|
|
bw.Write(Stat2Percent);
|
|
bw.Write(Stat3Percent);
|
|
bw.Write(_0x1E);
|
|
bw.Write(_0x1F);
|
|
bw.Write(_0x20);
|
|
bw.Write(_0x21);
|
|
return ms.ToArray();
|
|
}
|
|
}
|
|
public class Heal
|
|
{
|
|
public byte Val;
|
|
public bool Full, Half, Quarter, Value;
|
|
public Heal(byte val)
|
|
{
|
|
Val = val;
|
|
Full = Val == 0xFF;
|
|
Half = Val == 0xFE;
|
|
Quarter = Val == 0xFD;
|
|
Value = (Val < 0xFD);
|
|
}
|
|
public byte Write()
|
|
{
|
|
if (Value)
|
|
return Val;
|
|
if (Full)
|
|
return 0xFF;
|
|
if (Half)
|
|
return 0xFE;
|
|
if (Quarter)
|
|
return 0xFD;
|
|
return Val;
|
|
}
|
|
}
|
|
}
|
|
public class Item
|
|
{
|
|
public ushort Price;
|
|
public int BuyPrice;
|
|
public int SellPrice;
|
|
public byte HeldEffect, HeldArgument, NaturalGiftEffect, FlingEffect, FlingPower, NaturalGiftPower;
|
|
public byte NaturalGiftType, u8Flags;
|
|
public byte KeyFlags;
|
|
public byte UseEffect;
|
|
public byte _0xB; // Battle Type
|
|
public byte _0xC; // 0 or 1
|
|
public byte _0xD; // Classification (0-3 Battle, 4 Balls, 5 Mail)
|
|
public byte Consumable;
|
|
public byte SortIndex;
|
|
public byte CureInflict; // Bitflags
|
|
public byte FieldEffect; // Revive 1, Sacred Ash 3, Rare Candy 5, EvoStone 8
|
|
public int BoostATK,
|
|
BoostDEF, BoostSPA,
|
|
BoostSPD, BoostSPE,
|
|
BoostACC, BoostCRIT, BoostPP;
|
|
public ushort FunctionFlags;
|
|
|
|
public ushort FieldBoost; // 0x15-0x16
|
|
public byte EVHP, EVATK, EVDEF, EVSPE, EVSPA, EVSPD;
|
|
public Heal Healing;
|
|
public byte PPGain, Friendship1, Friendship2, Friendship3;
|
|
public byte _0x23, _0x24;
|
|
|
|
public Item(byte[] data)
|
|
{
|
|
using (BinaryReader br = new BinaryReader(new MemoryStream(data)))
|
|
{
|
|
Price = br.ReadUInt16();
|
|
BuyPrice = Price*10;
|
|
SellPrice = Price*5;
|
|
|
|
HeldEffect = br.ReadByte();
|
|
HeldArgument = br.ReadByte();
|
|
NaturalGiftEffect = br.ReadByte();
|
|
FlingEffect = br.ReadByte();
|
|
FlingPower = br.ReadByte();
|
|
NaturalGiftPower = br.ReadByte();
|
|
NaturalGiftType = br.ReadByte();
|
|
u8Flags = (byte)(NaturalGiftType >> 5);
|
|
NaturalGiftType &= 0x1F;
|
|
KeyFlags = br.ReadByte();
|
|
UseEffect = br.ReadByte();
|
|
_0xB = br.ReadByte();
|
|
_0xC = br.ReadByte();
|
|
_0xD = br.ReadByte();
|
|
Consumable = br.ReadByte();
|
|
SortIndex = br.ReadByte();
|
|
CureInflict = br.ReadByte();
|
|
|
|
FieldEffect = br.ReadByte();
|
|
BoostATK = FieldEffect >> 4;
|
|
FieldEffect &= 0xF;
|
|
BoostDEF = br.ReadByte();
|
|
BoostSPA = BoostDEF >> 4;
|
|
BoostDEF &= 0xF;
|
|
BoostSPD = br.ReadByte();
|
|
BoostSPE = BoostSPD >> 4;
|
|
BoostSPD &= 0xF;
|
|
BoostACC = br.ReadByte();
|
|
BoostCRIT = (BoostACC >> 4) & 0x3;
|
|
BoostPP = (BoostACC >> 6);
|
|
BoostACC &= 0xF;
|
|
|
|
FunctionFlags = br.ReadUInt16();
|
|
|
|
EVHP = br.ReadByte();
|
|
EVATK = br.ReadByte();
|
|
EVDEF = br.ReadByte();
|
|
EVSPE = br.ReadByte();
|
|
EVSPA = br.ReadByte();
|
|
EVSPD = br.ReadByte();
|
|
|
|
Healing = new Heal(br.ReadByte());
|
|
PPGain = br.ReadByte();
|
|
Friendship1 = br.ReadByte();
|
|
Friendship2 = br.ReadByte();
|
|
Friendship3 = br.ReadByte();
|
|
_0x23 = br.ReadByte();
|
|
_0x24 = br.ReadByte();
|
|
}
|
|
}
|
|
public byte[] Write()
|
|
{
|
|
using (MemoryStream ms = new MemoryStream())
|
|
using (BinaryWriter bw = new BinaryWriter(ms))
|
|
{
|
|
bw.Write(Price);
|
|
bw.Write(HeldEffect);
|
|
bw.Write(HeldArgument);
|
|
bw.Write(NaturalGiftEffect);
|
|
bw.Write(FlingEffect);
|
|
bw.Write(FlingPower);
|
|
bw.Write(NaturalGiftPower);
|
|
bw.Write((byte)(NaturalGiftType | (u8Flags << 5)));
|
|
bw.Write(KeyFlags);
|
|
bw.Write(UseEffect);
|
|
bw.Write(_0xB);
|
|
bw.Write(_0xC);
|
|
bw.Write(_0xD);
|
|
bw.Write(Consumable);
|
|
bw.Write(SortIndex);
|
|
bw.Write(CureInflict);
|
|
|
|
bw.Write((byte)(FieldEffect | (BoostATK << 4)));
|
|
bw.Write((byte)(BoostDEF | (BoostSPA << 4)));
|
|
bw.Write((byte)(BoostSPD | (BoostSPE << 4)));
|
|
bw.Write((byte)(BoostACC | (BoostCRIT << 4) | (BoostPP << 6)));
|
|
|
|
bw.Write(FunctionFlags);
|
|
|
|
bw.Write(EVHP);
|
|
bw.Write(EVATK);
|
|
bw.Write(EVDEF);
|
|
bw.Write(EVSPE);
|
|
bw.Write(EVSPA);
|
|
bw.Write(EVSPD);
|
|
bw.Write(Healing.Write());
|
|
bw.Write(PPGain);
|
|
bw.Write(Friendship1);
|
|
bw.Write(Friendship2);
|
|
bw.Write(Friendship3);
|
|
|
|
bw.Write(_0x23);
|
|
bw.Write(_0x24);
|
|
|
|
return ms.ToArray();
|
|
}
|
|
}
|
|
public class Heal
|
|
{
|
|
public byte Val;
|
|
public bool Full, Half, Quarter, Value;
|
|
public Heal(byte val)
|
|
{
|
|
Val = val;
|
|
Full = Val == 0xFF;
|
|
Half = Val == 0xFE;
|
|
Quarter = Val == 0xFD;
|
|
Value = (Val < 0xFD);
|
|
}
|
|
public byte Write()
|
|
{
|
|
if (Value)
|
|
return Val;
|
|
if (Full)
|
|
return 0xFF;
|
|
if (Half)
|
|
return 0xFE;
|
|
if (Quarter)
|
|
return 0xFD;
|
|
return Val;
|
|
}
|
|
}
|
|
}
|
|
public class Maison
|
|
{
|
|
public class Trainer
|
|
{
|
|
public ushort Class;
|
|
public ushort Count;
|
|
public ushort[] Choices;
|
|
|
|
public Trainer() { }
|
|
public Trainer(byte[] data)
|
|
{
|
|
Class = BitConverter.ToUInt16(data, 0);
|
|
Count = BitConverter.ToUInt16(data, 0);
|
|
Choices = new ushort[Count];
|
|
for (int i = 0; i < Count; i++)
|
|
Choices[i] = BitConverter.ToUInt16(data, 4 + 2 * i);
|
|
}
|
|
public byte[] Write()
|
|
{
|
|
using (var ms = new MemoryStream())
|
|
using (var bw = new BinaryWriter(ms))
|
|
{
|
|
bw.Write(Class);
|
|
bw.Write(Count);
|
|
foreach (ushort Choice in Choices)
|
|
bw.Write(Choice);
|
|
return ms.ToArray();
|
|
}
|
|
}
|
|
}
|
|
public class Pokemon
|
|
{
|
|
public ushort Species, Item;
|
|
public byte EVs, Nature;
|
|
public ushort[] Moves;
|
|
public bool HP, ATK, DEF, SPE, SPA, SPD;
|
|
|
|
private byte _u1, _u2;
|
|
|
|
public Pokemon(byte[] data)
|
|
{
|
|
Species = BitConverter.ToUInt16(data, 0);
|
|
Moves = new[]
|
|
{
|
|
BitConverter.ToUInt16(data, 2),
|
|
BitConverter.ToUInt16(data, 4),
|
|
BitConverter.ToUInt16(data, 6),
|
|
BitConverter.ToUInt16(data, 8)
|
|
};
|
|
EVs = data[0xA];
|
|
HP = (EVs >> 0 & 1) == 1;
|
|
ATK = (EVs >> 1 & 1) == 1;
|
|
DEF = (EVs >> 2 & 1) == 1;
|
|
SPE = (EVs >> 3 & 1) == 1;
|
|
SPA = (EVs >> 4 & 1) == 1;
|
|
SPD = (EVs >> 5 & 1) == 1;
|
|
Nature = data[0xB];
|
|
Item = BitConverter.ToUInt16(data, 0xC);
|
|
_u1 = data[0xE];
|
|
_u2 = data[0xF];
|
|
}
|
|
public byte[] Write()
|
|
{
|
|
using (var ms = new MemoryStream())
|
|
using (var bw = new BinaryWriter(ms))
|
|
{
|
|
bw.Write(Species);
|
|
foreach (ushort Move in Moves)
|
|
bw.Write(Move);
|
|
|
|
EVs &= 0xC0;
|
|
EVs |= (byte)(HP ? 1 << 0 : 0);
|
|
EVs |= (byte)(ATK ? 1 << 1 : 0);
|
|
EVs |= (byte)(DEF ? 1 << 1 : 0);
|
|
EVs |= (byte)(SPE ? 1 << 1 : 0);
|
|
EVs |= (byte)(SPA ? 1 << 1 : 0);
|
|
EVs |= (byte)(SPD ? 1 << 1 : 0);
|
|
bw.Write(EVs);
|
|
|
|
bw.Write(Nature);
|
|
bw.Write(Item);
|
|
bw.Write(_u1);
|
|
bw.Write(_u2);
|
|
return ms.ToArray();
|
|
}
|
|
}
|
|
}
|
|
}
|
|
public class Learnset
|
|
{
|
|
public int Count;
|
|
public short[] Moves;
|
|
public short[] Levels;
|
|
public Learnset(byte[] data)
|
|
{
|
|
if (data.Length < 4 || data.Length % 4 != 0) return; // Detect invalid files, weakly.
|
|
Count = (data.Length / 4) - 1;
|
|
Moves = new short[Count];
|
|
Levels = new short[Count];
|
|
using (BinaryReader br = new BinaryReader(new MemoryStream(data)))
|
|
{
|
|
for (int i = 0; i < Count; i++)
|
|
{
|
|
Moves[i] = br.ReadInt16();
|
|
Levels[i] = br.ReadInt16();
|
|
}
|
|
}
|
|
}
|
|
public byte[] Write()
|
|
{
|
|
using (MemoryStream ms = new MemoryStream())
|
|
using (BinaryWriter bw = new BinaryWriter(ms))
|
|
{
|
|
for (int i = 0; i < Count; i++)
|
|
{
|
|
bw.Write(Moves[i]);
|
|
bw.Write(Levels[i]);
|
|
}
|
|
bw.Write(-1);
|
|
return ms.ToArray();
|
|
}
|
|
}
|
|
}
|
|
public class EggMoves
|
|
{
|
|
public ushort Count;
|
|
public ushort[] Moves;
|
|
|
|
public EggMoves(byte[] data)
|
|
{
|
|
if (data.Length < 2 || data.Length % 2 != 0) return; // Detect invalid files, weakly.
|
|
using (BinaryReader br = new BinaryReader(new MemoryStream(data)))
|
|
{
|
|
Count = br.ReadUInt16();
|
|
Moves = new ushort[Count];
|
|
for (int i = 0; i < Count; i++)
|
|
Moves[i] = br.ReadUInt16();
|
|
}
|
|
}
|
|
public byte[] Write()
|
|
{
|
|
Count = (ushort)Moves.Length;
|
|
if (Count == 0) return new byte[0];
|
|
using (MemoryStream ms = new MemoryStream())
|
|
using (BinaryWriter bw = new BinaryWriter(ms))
|
|
{
|
|
bw.Write(Count);
|
|
for (int i = 0; i < Count; i++)
|
|
bw.Write(Moves[i]);
|
|
|
|
return ms.ToArray();
|
|
}
|
|
}
|
|
}
|
|
public class Evolutions
|
|
{
|
|
public ushort[] Method, Criteria, Species;
|
|
public Evolutions(byte[] data)
|
|
{
|
|
if (data.Length < 0x30 || data.Length % 6 != 0) return;
|
|
Method = new ushort[data.Length / 6];
|
|
Criteria = new ushort[data.Length / 6];
|
|
Species = new ushort[data.Length / 6];
|
|
using (BinaryReader br = new BinaryReader(new MemoryStream(data)))
|
|
for (int i = 0; i < Species.Length; i++)
|
|
{
|
|
Method[i] = br.ReadUInt16();
|
|
Criteria[i] = br.ReadUInt16();
|
|
Species[i] = br.ReadUInt16();
|
|
}
|
|
}
|
|
public byte[] Write()
|
|
{
|
|
using (MemoryStream ms = new MemoryStream())
|
|
using (BinaryWriter bw = new BinaryWriter(ms))
|
|
{
|
|
for (int i = 0; i < Species.Length; i++)
|
|
{
|
|
bw.Write(Method[i]);
|
|
bw.Write(Criteria[i]);
|
|
bw.Write(Species[i]);
|
|
}
|
|
return ms.ToArray();
|
|
}
|
|
}
|
|
}
|
|
public class Gift
|
|
{
|
|
// All
|
|
public byte[] Data;
|
|
public bool ORAS;
|
|
|
|
public ushort Species;
|
|
public ushort u2;
|
|
public byte Form;
|
|
public byte Level;
|
|
public byte Gender;
|
|
public short Nature;
|
|
public byte u9, uA, uB;
|
|
public int HeldItem;
|
|
public byte Ability;
|
|
// ORAS
|
|
public byte u11;
|
|
public short MetLocation;
|
|
public ushort Move;
|
|
// All
|
|
public sbyte[] IVs = new sbyte[6];
|
|
// ORAS
|
|
public byte[] ContestStats;
|
|
public byte u22;
|
|
// All
|
|
public byte uLast;
|
|
|
|
public Gift(byte[] data, bool oras)
|
|
{
|
|
Data = data;
|
|
ORAS = oras;
|
|
using (BinaryReader br = new BinaryReader(new MemoryStream(Data)))
|
|
{
|
|
Species = br.ReadUInt16();
|
|
u2 = br.ReadUInt16();
|
|
Form = br.ReadByte();
|
|
Level = br.ReadByte();
|
|
Gender = br.ReadByte();
|
|
Nature = br.ReadInt16();
|
|
u9 = br.ReadByte();
|
|
uA = br.ReadByte();
|
|
uB = br.ReadByte();
|
|
HeldItem = br.ReadInt32();
|
|
Ability = br.ReadByte();
|
|
|
|
if (ORAS)
|
|
{
|
|
u11 = br.ReadByte();
|
|
MetLocation = br.ReadInt16();
|
|
Move = br.ReadUInt16();
|
|
}
|
|
|
|
for (int i = 0; i < 6; i++)
|
|
IVs[i] = br.ReadSByte();
|
|
|
|
if (ORAS)
|
|
{
|
|
ContestStats = br.ReadBytes(6);
|
|
u22 = br.ReadByte();
|
|
}
|
|
|
|
uLast = br.ReadByte();
|
|
}
|
|
}
|
|
public byte[] Write()
|
|
{
|
|
using (MemoryStream ms = new MemoryStream())
|
|
using (BinaryWriter bw = new BinaryWriter(ms))
|
|
{
|
|
bw.Write(Species);
|
|
bw.Write(u2);
|
|
bw.Write(Form);
|
|
bw.Write(Level);
|
|
bw.Write(Gender);
|
|
bw.Write(Nature);
|
|
bw.Write(u9);
|
|
bw.Write(uA);
|
|
bw.Write(uB);
|
|
bw.Write(HeldItem);
|
|
bw.Write(Ability);
|
|
|
|
if (ORAS)
|
|
{
|
|
bw.Write(u11);
|
|
bw.Write(MetLocation);
|
|
bw.Write(Move);
|
|
}
|
|
|
|
for (int i = 0; i < 6; i++)
|
|
bw.Write(IVs[i]);
|
|
|
|
if (ORAS)
|
|
{
|
|
bw.Write(ContestStats);
|
|
bw.Write(u22);
|
|
}
|
|
|
|
bw.Write(uLast);
|
|
|
|
return ms.ToArray();
|
|
}
|
|
}
|
|
}
|
|
public class MegaEvolutions
|
|
{
|
|
public ushort[] Form, Method, Argument, u6;
|
|
public MegaEvolutions(byte[] data)
|
|
{
|
|
if (data.Length < 0x10 || data.Length % 8 != 0) return;
|
|
Form = new ushort[data.Length / 8];
|
|
Method = new ushort[data.Length / 8];
|
|
Argument = new ushort[data.Length / 8];
|
|
u6 = new ushort[data.Length / 8];
|
|
using (BinaryReader br = new BinaryReader(new MemoryStream(data)))
|
|
for (int i = 0; i < Form.Length; i++)
|
|
{
|
|
Form[i] = br.ReadUInt16();
|
|
Method[i] = br.ReadUInt16();
|
|
Argument[i] = br.ReadUInt16();
|
|
u6[i] = br.ReadUInt16();
|
|
}
|
|
}
|
|
public byte[] Write()
|
|
{
|
|
using (MemoryStream ms = new MemoryStream())
|
|
using (BinaryWriter bw = new BinaryWriter(ms))
|
|
{
|
|
for (int i = 0; i < Form.Length; i++)
|
|
{
|
|
if (Method[i] == 0)
|
|
{ Form[i] = Argument[i] = 0; } // No method to evolve, clear information.
|
|
bw.Write(Form[i]);
|
|
bw.Write(Method[i]);
|
|
bw.Write(Argument[i]);
|
|
bw.Write(u6[i]);
|
|
}
|
|
return ms.ToArray();
|
|
}
|
|
}
|
|
}
|
|
public class MapMatrix
|
|
{
|
|
public uint u0;
|
|
public ushort uL;
|
|
public ushort Width, Height;
|
|
private int Area;
|
|
public ushort[] EntryList;
|
|
public Entry[] Entries;
|
|
public MapMatrix(byte[] data)
|
|
{
|
|
using (BinaryReader br = new BinaryReader(new MemoryStream(data)))
|
|
{
|
|
u0 = br.ReadUInt32();
|
|
Width = br.ReadUInt16();
|
|
Height = br.ReadUInt16();
|
|
Area = Width*Height;
|
|
Entries = new Entry[Area];
|
|
EntryList = new ushort[Area];
|
|
for (int i = 0; i < Area; i++)
|
|
EntryList[i] = br.ReadUInt16();
|
|
|
|
if (br.BaseStream.Position != br.BaseStream.Length)
|
|
uL = br.ReadUInt16();
|
|
}
|
|
}
|
|
public byte[] Write()
|
|
{
|
|
using (MemoryStream ms = new MemoryStream())
|
|
using (BinaryWriter bw = new BinaryWriter(ms))
|
|
{
|
|
bw.Write(u0);
|
|
bw.Write(Width);
|
|
bw.Write(Height);
|
|
foreach (ushort Entry in EntryList) bw.Write(Entry);
|
|
bw.Write(uL);
|
|
return ms.ToArray();
|
|
}
|
|
}
|
|
|
|
public Image Preview(int Scale, int ColorShift)
|
|
{
|
|
// Require the entries to be defined in order to continue.
|
|
if (Entries.Any(entry => entry == null))
|
|
{
|
|
// Do nothing; images are instead created with the standard dimensions and returned.
|
|
}
|
|
|
|
// Fetch Singular Images first
|
|
Image[] EntryImages = new Image[Area];
|
|
for (int i = 0; i < Area; i++)
|
|
EntryImages[i] = (Entries[i] == null)
|
|
? new Bitmap(40 * Scale, 40 * Scale)
|
|
: Entries[i].Preview(Scale, ColorShift);
|
|
|
|
// Combine all images into one.
|
|
Bitmap img = new Bitmap(EntryImages[0].Width * Width, EntryImages[0].Height * Height);
|
|
|
|
using (Graphics g = Graphics.FromImage(img))
|
|
for (int i = 0; i < Area; i++)
|
|
{
|
|
g.DrawImage(EntryImages[i], new Point((i * EntryImages[0].Width) % (img.Width), EntryImages[0].Height * ((i / Width))));
|
|
}
|
|
return img;
|
|
}
|
|
|
|
public class Entry
|
|
{
|
|
public ushort Width, Height;
|
|
private int Area;
|
|
public uint[] Tiles; // Certain bits?
|
|
public Entry(byte[] data)
|
|
{
|
|
using (BinaryReader br = new BinaryReader(new MemoryStream(data)))
|
|
{
|
|
Width = br.ReadUInt16();
|
|
Height = br.ReadUInt16();
|
|
Area = Width*Height;
|
|
Tiles = new uint[Area];
|
|
for (int i = 0; i < Area; i++)
|
|
Tiles[i] = br.ReadUInt32();
|
|
}
|
|
}
|
|
public byte[] Write()
|
|
{
|
|
using (MemoryStream ms = new MemoryStream())
|
|
using (BinaryWriter bw = new BinaryWriter(ms))
|
|
{
|
|
bw.Write(Width);
|
|
bw.Write(Height);
|
|
foreach (uint Tile in Tiles) bw.Write(Tile);
|
|
return ms.ToArray();
|
|
}
|
|
}
|
|
public Image Preview(int s, int ColorShift)
|
|
{
|
|
Bitmap img = new Bitmap(Width*s, Height*s);
|
|
for (int i = 0; i < Area; i++)
|
|
{
|
|
Color c = Tiles[i] == 0x01000021
|
|
? Color.Black
|
|
: Color.FromArgb((int) (RNG.Forward32(Tiles[i], ColorShift) | 0xFF000000));
|
|
try
|
|
{
|
|
for (int x = 0; x < s; x++)
|
|
for (int y = 0; y < s; y++)
|
|
{
|
|
img.SetPixel(
|
|
x + (i * s) % (img.Width),
|
|
y + ((i/Width)*s),
|
|
c);
|
|
}
|
|
}
|
|
catch { }
|
|
}
|
|
return img;
|
|
}
|
|
}
|
|
}
|
|
public class ZoneData
|
|
{
|
|
public ushort u00, u02, MapMatrix, TextFile, u08; // Changing
|
|
public ushort u0A, u0C, u0E, u10, u12, u14, u16; // Constant
|
|
|
|
public ushort u18, u1A, OverworldLocation, u1E;
|
|
public byte OLFlags; // Part of OverworldLocation
|
|
public byte u20, u21; // uses 3 bits, uses 7 bits
|
|
public ushort u22, u24; // Zero
|
|
public short u26; // -1 thru ~25
|
|
|
|
public ushort u28, u2A; // 2 bytes float?
|
|
public short u2C, u2E, u30, u32, u34, u36;
|
|
|
|
public ZoneData(byte[] data)
|
|
{
|
|
if (data.Length != 0x36)
|
|
return;
|
|
using (BinaryReader br = new BinaryReader(new MemoryStream(data)))
|
|
{
|
|
u00 = br.ReadUInt16();
|
|
u02 = br.ReadUInt16();
|
|
MapMatrix = br.ReadUInt16();
|
|
TextFile = br.ReadUInt16();
|
|
u08 = br.ReadUInt16();
|
|
|
|
u0A = br.ReadUInt16();
|
|
u0C = br.ReadUInt16();
|
|
u0E = br.ReadUInt16();
|
|
u10 = br.ReadUInt16();
|
|
u12 = br.ReadUInt16();
|
|
u14 = br.ReadUInt16();
|
|
|
|
u18 = br.ReadUInt16();
|
|
u1A = br.ReadUInt16();
|
|
OverworldLocation = br.ReadUInt16();
|
|
OLFlags = (byte)(OverworldLocation >> 9);
|
|
OverworldLocation &= 0x1FF;
|
|
|
|
u20 = br.ReadByte();
|
|
u21 = br.ReadByte();
|
|
|
|
u22 = br.ReadUInt16();
|
|
u24 = br.ReadUInt16();
|
|
u26 = br.ReadInt16();
|
|
u28 = br.ReadUInt16();
|
|
u2A = br.ReadUInt16();
|
|
|
|
u2C = br.ReadInt16();
|
|
u2E = br.ReadInt16();
|
|
u30 = br.ReadInt16();
|
|
u32 = br.ReadInt16();
|
|
u34 = br.ReadInt16();
|
|
u36 = br.ReadInt16();
|
|
}
|
|
}
|
|
public byte[] Write()
|
|
{
|
|
using (MemoryStream ms = new MemoryStream())
|
|
using (BinaryWriter bw = new BinaryWriter(ms))
|
|
{
|
|
bw.Write(u00); bw.Write(u02); bw.Write(MapMatrix); bw.Write(TextFile);
|
|
bw.Write(u08); bw.Write(u0A); bw.Write(u0C); bw.Write(u0E);
|
|
bw.Write(u10); bw.Write(u12); bw.Write(u14); bw.Write(u16);
|
|
|
|
bw.Write(u18); bw.Write(u1A);
|
|
bw.Write((ushort)(OverworldLocation << (OLFlags << 9)));
|
|
bw.Write(u1E); bw.Write(u20); bw.Write(u21);
|
|
bw.Write(u22); bw.Write(u22); bw.Write(u24);
|
|
bw.Write(u26); bw.Write(u28); bw.Write(u2A);
|
|
|
|
bw.Write(u2C); bw.Write(u2E); bw.Write(u30);
|
|
bw.Write(u32); bw.Write(u34); bw.Write(u36);
|
|
return ms.ToArray();
|
|
}
|
|
}
|
|
}
|
|
public class Zone
|
|
{
|
|
public ZoneInfo Info;
|
|
public ZoneEntities Entities;
|
|
public ZoneScript MapScript;
|
|
public ZoneEncounters Encounters;
|
|
public ZoneUnknown File5;
|
|
|
|
public Zone(byte[][] Zone)
|
|
{
|
|
// A ZO is comprised of 4-5 files.
|
|
|
|
// Array 0 is [Map Info]
|
|
Info = new ZoneInfo(Zone[0]);
|
|
// Array 1 is [Overworld Entities & their Scripts]
|
|
Entities = new ZoneEntities(Zone[1]);
|
|
// Array 2 is [Map Script]
|
|
MapScript = new ZoneScript(Zone[2]);
|
|
// Array 3 is [Wild Encounters]
|
|
Encounters = new ZoneEncounters(Zone[3]);
|
|
// Array 4 is [???] - May not be present in all.
|
|
if (Zone.Length <= 4)
|
|
return;
|
|
File5 = new ZoneUnknown(Zone[4]);
|
|
}
|
|
|
|
public byte[][] Write()
|
|
{
|
|
byte[][] Zone = new byte[(File5 != null) ? 5 : 4][];
|
|
Zone[0] = Info.Write();
|
|
Zone[1] = Entities.Write();
|
|
Zone[2] = MapScript.Write();
|
|
Zone[3] = Encounters.Write();
|
|
if (Zone.Length <= 4)
|
|
return Zone;
|
|
|
|
Zone[4] = File5.Write();
|
|
return Zone;
|
|
}
|
|
|
|
public class ZoneInfo
|
|
{
|
|
public byte[] InfoData; // File details unknown.
|
|
public ZoneInfo(byte[] data)
|
|
{
|
|
InfoData = data;
|
|
}
|
|
public byte[] Write()
|
|
{
|
|
return InfoData;
|
|
}
|
|
}
|
|
public class ZoneEntities
|
|
{
|
|
public byte[] Data; // File details unknown.
|
|
|
|
public UInt32 Length;
|
|
public EntityFurniture[] Furniture;
|
|
public EntityNPC[] NPCs;
|
|
public EntityWarp[] Warps;
|
|
public EntityTrigger[] Triggers;
|
|
public Byte[] ScriptData;
|
|
public ZoneEntities(byte[] data)
|
|
{
|
|
Data = data;
|
|
|
|
using (BinaryReader br = new BinaryReader(new MemoryStream(data)))
|
|
{
|
|
Length = br.ReadUInt32();
|
|
Furniture = new EntityFurniture[br.ReadByte()];
|
|
NPCs = new EntityNPC[br.ReadByte()];
|
|
Warps = new EntityWarp[br.ReadByte()];
|
|
Triggers = new EntityTrigger[br.ReadByte()];
|
|
for (int i = 0; i < Furniture.Length; i++)
|
|
Furniture[i] = new EntityFurniture(br.ReadBytes(Furniture.Length));
|
|
for (int i = 0; i < NPCs.Length; i++)
|
|
NPCs[i] = new EntityNPC(br.ReadBytes(NPCs.Length));
|
|
for (int i = 0; i < Warps.Length; i++)
|
|
Warps[i] = new EntityWarp(br.ReadBytes(Warps.Length));
|
|
for (int i = 0; i < Triggers.Length; i++)
|
|
Triggers[i] = new EntityTrigger(br.ReadBytes(Triggers.Length));
|
|
ScriptData = br.ReadBytes((int)(br.BaseStream.Length - br.BaseStream.Position));
|
|
}
|
|
}
|
|
public byte[] Write()
|
|
{
|
|
return Data;
|
|
}
|
|
|
|
// Entity Classes
|
|
public class EntityFurniture
|
|
{
|
|
internal static readonly byte Length = 0x14;
|
|
public byte[] Raw;
|
|
public EntityFurniture(byte[] data)
|
|
{
|
|
Raw = data;
|
|
}
|
|
public byte[] Write()
|
|
{
|
|
return Raw;
|
|
}
|
|
}
|
|
public class EntityNPC
|
|
{
|
|
internal static readonly byte Length = 0x30;
|
|
public ushort ID;
|
|
public byte[] Raw;
|
|
public EntityNPC(byte[] data)
|
|
{
|
|
Raw = data;
|
|
ID = BitConverter.ToUInt16(data, 0x4);
|
|
}
|
|
public byte[] Write()
|
|
{
|
|
return Raw;
|
|
}
|
|
}
|
|
public class EntityWarp
|
|
{
|
|
internal static readonly byte Length = 0x18;
|
|
public byte[] Raw;
|
|
public ushort DestinationMap;
|
|
public ushort DestinationTileIndex;
|
|
public EntityWarp(byte[] data)
|
|
{
|
|
Raw = data;
|
|
|
|
DestinationMap = BitConverter.ToUInt16(data, 0x4);
|
|
DestinationTileIndex = BitConverter.ToUInt16(data, 0x6);
|
|
}
|
|
public byte[] Write()
|
|
{
|
|
return Raw;
|
|
}
|
|
}
|
|
public class EntityTrigger
|
|
{
|
|
internal static readonly byte Length = 0x18;
|
|
public byte[] Raw;
|
|
public EntityTrigger(byte[] data)
|
|
{
|
|
Raw = data;
|
|
}
|
|
public byte[] Write()
|
|
{
|
|
return Raw;
|
|
}
|
|
}
|
|
}
|
|
public class ZoneScript
|
|
{
|
|
public byte[] Data; // File details unknown.
|
|
public ZoneScript(byte[] data)
|
|
{
|
|
Data = data;
|
|
}
|
|
public byte[] Write()
|
|
{
|
|
return Data;
|
|
}
|
|
}
|
|
public class ZoneEncounters
|
|
{
|
|
public byte[] Data; // File details unknown.
|
|
public byte[] Header;
|
|
public EncounterSet[] Encounters;
|
|
public ZoneEncounters(byte[] data)
|
|
{
|
|
Data = data;
|
|
|
|
using (BinaryReader br = new BinaryReader(new MemoryStream(data)))
|
|
{
|
|
Header = br.ReadBytes(0x10);
|
|
Encounters = new EncounterSet[(int)(br.BaseStream.Length - br.BaseStream.Position)/4];
|
|
for (int i = 0; i < Encounters.Length; i++)
|
|
Encounters[i] = new EncounterSet(br.ReadBytes(4));
|
|
}
|
|
}
|
|
public byte[] Write()
|
|
{
|
|
byte[] data = Header; // Start with the header data, then concat every encounter in afterwards.
|
|
return Encounters.Aggregate(data, (current, t) => current.Concat(t.Write()).ToArray());
|
|
}
|
|
|
|
public class EncounterSet
|
|
{
|
|
public int Species;
|
|
public int Form;
|
|
public byte LevelMin, LevelMax;
|
|
|
|
public EncounterSet(byte[] data)
|
|
{
|
|
using (BinaryReader br = new BinaryReader(new MemoryStream(data)))
|
|
{
|
|
ushort SpecForm = br.ReadUInt16();
|
|
Species = SpecForm & 0x7FF;
|
|
Form = SpecForm >> 11;
|
|
LevelMin = br.ReadByte();
|
|
LevelMax = br.ReadByte();
|
|
}
|
|
}
|
|
public byte[] Write()
|
|
{
|
|
using (MemoryStream ms = new MemoryStream())
|
|
using (BinaryWriter bw = new BinaryWriter(ms))
|
|
{
|
|
bw.Write((ushort)(Species | (Form << 11)));
|
|
bw.Write(LevelMin);
|
|
bw.Write(LevelMax);
|
|
return ms.ToArray();
|
|
}
|
|
}
|
|
}
|
|
}
|
|
public class ZoneUnknown
|
|
{
|
|
public byte[] FileData; // File details unknown.
|
|
public ZoneUnknown(byte[] data)
|
|
{
|
|
FileData = data;
|
|
}
|
|
|
|
public byte[] Write()
|
|
{
|
|
return FileData;
|
|
}
|
|
}
|
|
}
|
|
}
|