/// <summary> /// Creates an instance of <see cref="PKM"/> from the given data. /// </summary> /// <param name="data">Raw data of the Pokemon file.</param> /// <param name="prefer">Optional identifier for the preferred generation. Usually the generation of the destination save file.</param> /// <returns>An instance of <see cref="PKM"/> created from the given <paramref name="data"/>, or null if <paramref name="data"/> is invalid.</returns> public static PKM?GetPKMfromBytes(byte[] data, int prefer = 7) { int format = GetPKMDataFormat(data); switch (format) { case 1: var list1 = new PokeList1(data); return(list1[0]); case 2: if (data.Length == PokeCrypto.SIZE_2STADIUM) { return(new SK2(data)); } var list2 = new PokeList2(data); return(list2[0]); case 3: return(data.Length switch { PokeCrypto.SIZE_3CSTORED => new CK3(data), PokeCrypto.SIZE_3XSTORED => new XK3(data), _ => new PK3(data) });
private const int SIZE_RESERVED = 0x8000; // unpacked box data protected override byte[] GetFinalData() { var capacity = Japanese ? PokeListType.StoredJP : PokeListType.Stored; for (int i = 0; i < BoxCount; i++) { var boxPL = new PokeList1(capacity, Japanese); int slot = 0; for (int j = 0; j < boxPL.Pokemon.Length; j++) { PK1 boxPK = (PK1)GetPKM(GetData(GetBoxOffset(i) + (j * SIZE_STORED), SIZE_STORED)); if (boxPK.Species > 0) { boxPL[slot++] = boxPK; } } // copy to box location var boxdata = boxPL.Write(); int ofs = GetBoxRawDataOffset(i); SetData(boxdata, ofs); // copy to active loc if current box if (i == CurrentBox) { SetData(boxdata, Offsets.CurrentBox); } } var partyPL = new PokeList1(PokeListType.Party, Japanese); int pSlot = 0; for (int i = 0; i < 6; i++) { PK1 partyPK = (PK1)GetPKM(GetData(GetPartyOffset(i), SIZE_STORED)); if (partyPK.Species > 0) { partyPL[pSlot++] = partyPK; } } partyPL.Write().CopyTo(Data, Offsets.Party); // 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[] dc = new byte[1 + (2 * StringLength) + PKX.SIZE_1STORED]; dc[0] = rawDC[0]; Array.Copy(rawDC, 2 + 1 + PKX.SIZE_1PARTY + StringLength, dc, 1, StringLength); Array.Copy(rawDC, 2 + 1 + PKX.SIZE_1PARTY, dc, 1 + StringLength, StringLength); Array.Copy(rawDC, 2 + 1, dc, 1 + (2 * StringLength), PKX.SIZE_1STORED); dc.CopyTo(Data, Offsets.Daycare); SetChecksums(); byte[] outData = new byte[Data.Length - SIZE_RESERVED]; Array.Copy(Data, outData, outData.Length); return(outData); }
/// <summary> /// Creates an instance of <see cref="PKM"/> from the given data. /// </summary> /// <param name="data">Raw data of the Pokemon file.</param> /// <param name="ident">Optional identifier for the Pokemon. Usually the full path of the source file.</param> /// <param name="prefer">Optional identifier for the preferred generation. Usually the generation of the destination save file.</param> /// <returns>An instance of <see cref="PKM"/> created from the given <paramref name="data"/>, or null if <paramref name="data"/> is invalid.</returns> public static PKM GetPKMfromBytes(byte[] data, string ident = null, int prefer = 7) { int format = GetPKMDataFormat(data); switch (format) { case 1: var PL1 = new PokeList1(data); if (ident != null) { PL1[0].Identifier = ident; } return(PL1[0]); case 2: var PL2 = new PokeList2(data); if (ident != null) { PL2[0].Identifier = ident; } return(PL2[0]); case 3: switch (data.Length) { case PKX.SIZE_3CSTORED: return(new CK3(data, ident)); case PKX.SIZE_3XSTORED: return(new XK3(data, ident)); default: return(new PK3(data, ident)); } case 4: var pk = new PK4(data, ident); if (!pk.Valid || pk.Sanity != 0) { var bk = new BK4(data, ident); if (bk.Valid) { return(bk); } } return(pk); case 5: return(new PK5(data, ident)); case 6: var pkx = new PK6(data, ident); return(CheckPKMFormat7(pkx, prefer)); default: return(null); } }
/// <summary> /// Creates an instance of <see cref="PKM"/> from the given data. /// </summary> /// <param name="data">Raw data of the Pokemon file.</param> /// <param name="prefer">Optional identifier for the preferred generation. Usually the generation of the destination save file.</param> /// <returns>An instance of <see cref="PKM"/> created from the given <paramref name="data"/>, or null if <paramref name="data"/> is invalid.</returns> public static PKM?GetPKMfromBytes(byte[] data, int prefer = 7) { int format = GetPKMDataFormat(data); switch (format) { case 1: var PL1 = new PokeList1(data); return(PL1[0]); case 2: var PL2 = new PokeList2(data); return(PL2[0]); case 3: return(data.Length switch { PokeCrypto.SIZE_3CSTORED => new CK3(data), PokeCrypto.SIZE_3XSTORED => new XK3(data), _ => new PK3(data) });
private void Initialize(GameVersion versionOverride) { // see if RBY can be differentiated if (Starter != 0 && versionOverride != GameVersion.Any) { Version = Yellow ? GameVersion.YW : GameVersion.RB; } Box = Data.Length; Array.Resize(ref Data, Data.Length + SIZE_RESERVED); Party = GetPartyOffset(0); // Stash boxes after the save file's end. int stored = SIZE_STOREDBOX; int baseDest = Data.Length - SIZE_RESERVED; var capacity = Japanese ? PokeListType.StoredJP : PokeListType.Stored; for (int i = 0; i < BoxCount; i++) { int ofs = GetBoxRawDataOffset(i); var box = GetData(ofs, stored); var boxDest = baseDest + (i * SIZE_BOX); var boxPL = new PokeList1(box, capacity, Japanese); for (int j = 0; j < boxPL.Pokemon.Length; j++) { var dest = boxDest + (j * SIZE_STORED); var pkDat = (j < boxPL.Count) ? new PokeList1(boxPL[j]).Write() : new byte[PokeList1.GetDataLength(PokeListType.Single, Japanese)]; pkDat.CopyTo(Data, dest); } } var current = GetData(Offsets.CurrentBox, SIZE_STOREDBOX); var curBoxPL = new PokeList1(current, capacity, Japanese); for (int i = 0; i < curBoxPL.Pokemon.Length; i++) { var dest = Data.Length - SIZE_RESERVED + (CurrentBox * SIZE_BOX) + (i * SIZE_STORED); var pkDat = i < curBoxPL.Count ? new PokeList1(curBoxPL[i]).Write() : new byte[PokeList1.GetDataLength(PokeListType.Single, Japanese)]; pkDat.CopyTo(Data, dest); } var party = GetData(Offsets.Party, SIZE_STOREDPARTY); var partyPL = new PokeList1(party, PokeListType.Party, Japanese); for (int i = 0; i < partyPL.Pokemon.Length; i++) { var dest = GetPartyOffset(i); var pkDat = i < partyPL.Count ? new PokeList1(partyPL[i]).Write() : new byte[PokeList1.GetDataLength(PokeListType.Single, Japanese)]; pkDat.CopyTo(Data, dest); } byte[] rawDC = new byte[0x38]; Array.Copy(Data, Offsets.Daycare, rawDC, 0, rawDC.Length); byte[] TempDaycare = new byte[PokeList1.GetDataLength(PokeListType.Single, Japanese)]; TempDaycare[0] = rawDC[0]; 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 + (2 * StringLength), TempDaycare, 2 + 1, PKX.SIZE_1STORED); PokeList1 daycareList = new PokeList1(TempDaycare, PokeListType.Single, Japanese); daycareList.Write().CopyTo(Data, GetPartyOffset(7)); DaycareOffset = GetPartyOffset(7); EventFlag = Offsets.EventFlag; // Enable Pokedex editing PokeDex = 0; }
public SAV1(byte[] data = null, GameVersion versionOverride = GameVersion.Any) { Data = data ?? new byte[SaveUtil.SIZE_G1RAW]; BAK = (byte[])Data.Clone(); Exportable = !IsRangeEmpty(0, Data.Length); if (versionOverride != GameVersion.Any) { Version = versionOverride; } else if (data == null) { Version = GameVersion.RBY; } else { Version = SaveUtil.GetIsG1SAV(Data); } if (Version == GameVersion.Invalid) { return; } Japanese = SaveUtil.GetIsG1SAVJ(Data); Offsets = Japanese ? SAV1Offsets.JPN : SAV1Offsets.INT; // see if RBY can be differentiated if (Starter != 0 && versionOverride != GameVersion.Any) { Version = Yellow ? GameVersion.YW : GameVersion.RB; } Box = Data.Length; Array.Resize(ref Data, Data.Length + SIZE_RESERVED); Party = GetPartyOffset(0); Personal = Version == GameVersion.Y ? PersonalTable.Y : PersonalTable.RB; // Stash boxes after the save file's end. int stored = SIZE_STOREDBOX; int baseDest = Data.Length - SIZE_RESERVED; var capacity = Japanese ? PokeListType.StoredJP : PokeListType.Stored; for (int i = 0; i < BoxCount; i++) { int ofs = GetBoxRawDataOffset(i); var box = GetData(ofs, stored); var boxDest = baseDest + (i * SIZE_BOX); var boxPL = new PokeList1(box, capacity, Japanese); for (int j = 0; j < boxPL.Pokemon.Length; j++) { var dest = boxDest + (j * SIZE_STORED); var pkDat = (j < boxPL.Count) ? new PokeList1(boxPL[j]).Write() : new byte[PokeList1.GetDataLength(PokeListType.Single, Japanese)]; pkDat.CopyTo(Data, dest); } } var current = GetData(Offsets.CurrentBox, SIZE_STOREDBOX); var curBoxPL = new PokeList1(current, capacity, Japanese); for (int i = 0; i < curBoxPL.Pokemon.Length; i++) { var dest = Data.Length - SIZE_RESERVED + (CurrentBox * SIZE_BOX) + (i * SIZE_STORED); var pkDat = i < curBoxPL.Count ? new PokeList1(curBoxPL[i]).Write() : new byte[PokeList1.GetDataLength(PokeListType.Single, Japanese)]; pkDat.CopyTo(Data, dest); } var party = GetData(Offsets.Party, SIZE_STOREDPARTY); var partyPL = new PokeList1(party, PokeListType.Party, Japanese); for (int i = 0; i < partyPL.Pokemon.Length; i++) { var dest = GetPartyOffset(i); var pkDat = i < partyPL.Count ? new PokeList1(partyPL[i]).Write() : new byte[PokeList1.GetDataLength(PokeListType.Single, Japanese)]; pkDat.CopyTo(Data, dest); } byte[] rawDC = new byte[0x38]; Array.Copy(Data, Offsets.Daycare, rawDC, 0, rawDC.Length); byte[] TempDaycare = new byte[PokeList1.GetDataLength(PokeListType.Single, Japanese)]; TempDaycare[0] = rawDC[0]; 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 + (2 * StringLength), TempDaycare, 2 + 1, PKX.SIZE_1STORED); PokeList1 daycareList = new PokeList1(TempDaycare, PokeListType.Single, Japanese); daycareList.Write().CopyTo(Data, GetPartyOffset(7)); Daycare = GetPartyOffset(7); EventFlag = Offsets.EventFlag; // Enable Pokedex editing PokeDex = 0; if (!Exportable) { ClearBoxes(); } }