private const int SIZE_RESERVED = 0x8000; // unpacked box data public override byte[] Write(bool DSV) { for (int i = 0; i < BoxCount; i++) { PokemonList2 boxPL = new PokemonList2(Japanese ? PokemonList2.CapacityType.StoredJP : PokemonList2.CapacityType.Stored, Japanese); int slot = 0; for (int j = 0; j < boxPL.Pokemon.Length; j++) { PK2 boxPK = (PK2) getPKM(getData(getBoxOffset(i) + j*SIZE_STORED, SIZE_STORED)); if (boxPK.Species > 0) boxPL[slot++] = boxPK; } if (i < (Japanese ? 6 : 7)) boxPL.GetBytes().CopyTo(Data, 0x4000 + i * (SIZE_STOREDBOX + 2)); else boxPL.GetBytes().CopyTo(Data, 0x6000 + (i - (Japanese ? 6 : 7)) * (SIZE_STOREDBOX + 2)); if (i == CurrentBox) boxPL.GetBytes().CopyTo(Data, CurrentBoxOffset); } PokemonList2 partyPL = new PokemonList2(PokemonList2.CapacityType.Party, Japanese); int pSlot = 0; for (int i = 0; i < 6; i++) { PK2 partyPK = (PK2)getPKM(getData(getPartyOffset(i), SIZE_STORED)); if (partyPK.Species > 0) partyPL[pSlot++] = partyPK; } partyPL.GetBytes().CopyTo(Data, PartyOffset); setChecksums(); if (Version == GameVersion.C && !Japanese) { Array.Copy(Data, 0x2009, Data, 0x1209, 0xB7A); } if (Version == GameVersion.C && Japanese) { Array.Copy(Data, 0x2009, Data, 0x7209, 0xB32); } if (Version == GameVersion.GS && !Japanese) { Array.Copy(Data, 0x2009, Data, 0x15C7, 0x222F - 0x2009); Array.Copy(Data, 0x222F, Data, 0x3D69, 0x23D9 - 0x222F); Array.Copy(Data, 0x23D9, Data, 0x0C6B, 0x2856 - 0x23D9); Array.Copy(Data, 0x2856, Data, 0x7E39, 0x288A - 0x2856); Array.Copy(Data, 0x288A, Data, 0x10E8, 0x2D69 - 0x288A); } if (Version == GameVersion.GS && Japanese) { Array.Copy(Data, 0x2009, Data, 0x7209, 0xC83); } byte[] outData = new byte[Data.Length - SIZE_RESERVED]; Array.Copy(Data, outData, outData.Length); return outData; }
protected override byte[] Write(bool DSV) { for (int i = 0; i < BoxCount; i++) { PokemonList2 boxPL = new PokemonList2(Japanese ? PokemonList2.CapacityType.StoredJP : PokemonList2.CapacityType.Stored, Japanese); int slot = 0; for (int j = 0; j < boxPL.Pokemon.Length; j++) { PK2 boxPK = (PK2)GetPKM(GetData(GetBoxOffset(i) + j * SIZE_STORED, SIZE_STORED)); if (boxPK.Species > 0) { boxPL[slot++] = boxPK; } } if (i < (Japanese ? 6 : 7)) { boxPL.GetBytes().CopyTo(Data, 0x4000 + i * (SIZE_STOREDBOX + 2)); } else { boxPL.GetBytes().CopyTo(Data, 0x6000 + (i - (Japanese ? 6 : 7)) * (SIZE_STOREDBOX + 2)); } if (i == CurrentBox) { boxPL.GetBytes().CopyTo(Data, Offsets.CurrentBox); } } PokemonList2 partyPL = new PokemonList2(PokemonList2.CapacityType.Party, Japanese); int pSlot = 0; for (int i = 0; i < 6; i++) { PK2 partyPK = (PK2)GetPKM(GetData(GetPartyOffset(i), SIZE_STORED)); if (partyPK.Species > 0) { partyPL[pSlot++] = partyPK; } } partyPL.GetBytes().CopyTo(Data, Offsets.Party); SetChecksums(); if (Japanese) { switch (Version) { case GameVersion.GS: Array.Copy(Data, Offsets.Trainer1, Data, 0x7209, 0xC83); break; case GameVersion.C: Array.Copy(Data, Offsets.Trainer1, Data, 0x7209, 0xADA); break; } } else if (Korean) { // Calculate oddball checksum ushort sum = 0; ushort[][] offsetpairs = { new ushort[] { 0x106B, 0x1533 }, new ushort[] { 0x1534, 0x1A12 }, new ushort[] { 0x1A13, 0x1C38 }, new ushort[] { 0x3DD8, 0x3F79 }, new ushort[] { 0x7E39, 0x7E6A }, }; foreach (ushort[] p in offsetpairs) { for (int i = p[0]; i < p[1]; i++) { sum += Data[i]; } } BitConverter.GetBytes(sum).CopyTo(Data, 0x7E6B); } else { switch (Version) { case GameVersion.GS: Array.Copy(Data, 0x2009, Data, 0x15C7, 0x222F - 0x2009); Array.Copy(Data, 0x222F, Data, 0x3D69, 0x23D9 - 0x222F); Array.Copy(Data, 0x23D9, Data, 0x0C6B, 0x2856 - 0x23D9); Array.Copy(Data, 0x2856, Data, 0x7E39, 0x288A - 0x2856); Array.Copy(Data, 0x288A, Data, 0x10E8, 0x2D69 - 0x288A); break; case GameVersion.C: Array.Copy(Data, 0x2009, Data, 0x1209, 0xB7A); break; } } byte[] outData = new byte[Data.Length - SIZE_RESERVED]; Array.Copy(Data, outData, outData.Length); return(outData); }
private const int SIZE_RESERVED = 0x8000; // unpacked box data protected override byte[] Write(bool DSV) { for (int i = 0; i < BoxCount; i++) { PokemonList2 boxPL = new PokemonList2(Japanese ? PokemonList2.CapacityType.StoredJP : PokemonList2.CapacityType.Stored, Japanese); int slot = 0; for (int j = 0; j < boxPL.Pokemon.Length; j++) { PK2 boxPK = (PK2)GetPKM(GetData(GetBoxOffset(i) + j * SIZE_STORED, SIZE_STORED)); if (boxPK.Species > 0) { boxPL[slot++] = boxPK; } } if (i < (Japanese ? 6 : 7)) { boxPL.GetBytes().CopyTo(Data, 0x4000 + i * (SIZE_STOREDBOX + 2)); } else { boxPL.GetBytes().CopyTo(Data, 0x6000 + (i - (Japanese ? 6 : 7)) * (SIZE_STOREDBOX + 2)); } if (i == CurrentBox) { boxPL.GetBytes().CopyTo(Data, CurrentBoxOffset); } } PokemonList2 partyPL = new PokemonList2(PokemonList2.CapacityType.Party, Japanese); int pSlot = 0; for (int i = 0; i < 6; i++) { PK2 partyPK = (PK2)GetPKM(GetData(GetPartyOffset(i), SIZE_STORED)); if (partyPK.Species > 0) { partyPL[pSlot++] = partyPK; } } partyPL.GetBytes().CopyTo(Data, PartyOffset); SetChecksums(); if (Version == GameVersion.C && !Japanese) { Array.Copy(Data, 0x2009, Data, 0x1209, 0xB7A); } if (Version == GameVersion.C && Japanese) { Array.Copy(Data, 0x2009, Data, 0x7209, 0xADA); } if (Version == GameVersion.GS && !Japanese) { Array.Copy(Data, 0x2009, Data, 0x15C7, 0x222F - 0x2009); Array.Copy(Data, 0x222F, Data, 0x3D69, 0x23D9 - 0x222F); Array.Copy(Data, 0x23D9, Data, 0x0C6B, 0x2856 - 0x23D9); Array.Copy(Data, 0x2856, Data, 0x7E39, 0x288A - 0x2856); Array.Copy(Data, 0x288A, Data, 0x10E8, 0x2D69 - 0x288A); } if (Version == GameVersion.GS && Japanese) { Array.Copy(Data, 0x2009, Data, 0x7209, 0xC83); } byte[] outData = new byte[Data.Length - SIZE_RESERVED]; Array.Copy(Data, outData, outData.Length); return(outData); }
public SAV2(byte[] data = null, GameVersion versionOverride = GameVersion.Any) { Data = data ?? new byte[SaveUtil.SIZE_G2RAW_U]; BAK = (byte[])Data.Clone(); Exportable = !IsRangeEmpty(0, Data.Length); if (data == null) { Version = GameVersion.C; } else if (versionOverride != GameVersion.Any) { Version = versionOverride; } else { Version = SaveUtil.GetIsG2SAV(Data); } if (Version == GameVersion.Invalid) { return; } Japanese = SaveUtil.GetIsG2SAVJ(Data) != GameVersion.Invalid; if (!Japanese) { Korean = SaveUtil.GetIsG2SAVK(Data) != GameVersion.Invalid; } Box = Data.Length; Array.Resize(ref Data, Data.Length + SIZE_RESERVED); Party = GetPartyOffset(0); Personal = Version == GameVersion.GS ? PersonalTable.GS : PersonalTable.C; Offsets = new SAV2Offsets(this); LegalItems = Legal.Pouch_Items_GSC; LegalBalls = Legal.Pouch_Ball_GSC; LegalKeyItems = Version == GameVersion.C ? Legal.Pouch_Key_C : Legal.Pouch_Key_GS; LegalTMHMs = Legal.Pouch_TMHM_GSC; HeldItems = Legal.HeldItems_GSC; // Stash boxes after the save file's end. byte[] TempBox = new byte[SIZE_STOREDBOX]; for (int i = 0; i < BoxCount; i++) { if (i < (Japanese ? 6 : 7)) { Array.Copy(Data, 0x4000 + i * (TempBox.Length + 2), TempBox, 0, TempBox.Length); } else { Array.Copy(Data, 0x6000 + (i - (Japanese ? 6 : 7)) * (TempBox.Length + 2), TempBox, 0, TempBox.Length); } PokemonList2 PL2 = new PokemonList2(TempBox, Japanese ? PokemonList2.CapacityType.StoredJP : PokemonList2.CapacityType.Stored, Japanese); for (int j = 0; j < PL2.Pokemon.Length; j++) { if (j < PL2.Count) { byte[] pkDat = new PokemonList2(PL2[j]).GetBytes(); pkDat.CopyTo(Data, Data.Length - SIZE_RESERVED + i * SIZE_BOX + j * SIZE_STORED); } 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); PokemonList2 curBoxPL = new PokemonList2(TempBox, Japanese ? PokemonList2.CapacityType.StoredJP : PokemonList2.CapacityType.Stored, Japanese); for (int i = 0; i < curBoxPL.Pokemon.Length; i++) { if (i < curBoxPL.Count) { byte[] pkDat = new PokemonList2(curBoxPL[i]).GetBytes(); pkDat.CopyTo(Data, Data.Length - SIZE_RESERVED + CurrentBox * SIZE_BOX + i * SIZE_STORED); } 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)]; Array.Copy(Data, Offsets.Party, TempParty, 0, TempParty.Length); PokemonList2 partyList = new PokemonList2(TempParty, PokemonList2.CapacityType.Party, Japanese); for (int i = 0; i < partyList.Pokemon.Length; i++) { if (i < partyList.Count) { byte[] pkDat = new PokemonList2(partyList[i]).GetBytes(); pkDat.CopyTo(Data, GetPartyOffset(i)); } else { byte[] pkDat = new byte[PokemonList2.GetDataLength(PokemonList2.CapacityType.Single, Japanese)]; pkDat.CopyTo(Data, GetPartyOffset(i)); } } // Daycare currently undocumented for all Gen II games. if (Offsets.Daycare >= 0) { int offset = Offsets.Daycare; DaycareFlags[0] = Data[offset]; offset++; var pk1 = ReadPKMFromOffset(offset); // parent 1 var daycare1 = new PokemonList2(pk1); offset += StringLength * 2 + 0x20; // nick/ot/pkm DaycareFlags[1] = Data[offset]; offset++; byte steps = Data[offset]; offset++; byte BreedMotherOrNonDitto = Data[offset]; offset++; var pk2 = ReadPKMFromOffset(offset); // parent 2 var daycare2 = new PokemonList2(pk2); offset += StringLength * 2 + PKX.SIZE_2STORED; // nick/ot/pkm var pk3 = ReadPKMFromOffset(offset); // egg! pk3.IsEgg = true; var daycare3 = new PokemonList2(pk3); daycare1.GetBytes().CopyTo(Data, GetPartyOffset(7 + (0 * 2))); daycare2.GetBytes().CopyTo(Data, GetPartyOffset(7 + (1 * 2))); daycare3.GetBytes().CopyTo(Data, GetPartyOffset(7 + (2 * 2))); Daycare = Offsets.Daycare; } // Enable Pokedex editing PokeDex = 0; EventFlag = Offsets.EventFlag; if (!Exportable) { ClearBoxes(); } }