public Signature(Span <byte> bytes) { if (bytes.Length != 65) { throw new ArgumentException(); } bytes.Slice(0, 64).CopyTo(Bytes.AsSpan()); V = bytes[64]; }
public Signature(ReadOnlySpan <byte> bytes, int recoveryId) { if (bytes.Length != 64) { throw new ArgumentException(); } bytes.CopyTo(Bytes.AsSpan()); V = (ulong)recoveryId + VOffset; }
private void WriteBytes(MemoryHolder address, int offset, Bytes bytes) { SimpleType st = (SimpleType)_type; Debug.Assert(st._type == SimpleTypeKind.Char && bytes.Count <= _length); address.WriteSpan(offset, bytes.AsSpan()); if (bytes.Count < _length) { address.WriteByte(checked (offset + bytes.Count), 0); } }
public Signature(ReadOnlySpan <byte> r, ReadOnlySpan <byte> s, ulong v) { if (v < VOffset) { throw new ArgumentException(nameof(v)); } r.CopyTo(Bytes.AsSpan().Slice(32 - r.Length, r.Length)); s.CopyTo(Bytes.AsSpan().Slice(64 - s.Length, s.Length)); V = v; }
public Signature(Span <byte> r, Span <byte> s, int v) { if (v < 27) { throw new ArgumentException(nameof(v)); } r.CopyTo(Bytes.AsSpan().Slice(32 - r.Length, r.Length)); s.CopyTo(Bytes.AsSpan().Slice(64 - s.Length, s.Length)); V = v; }
public Signature(UInt256 r, UInt256 s, ulong v) { if (v < VOffset) { throw new ArgumentException(nameof(v)); } r.ToBigEndian(Bytes.AsSpan().Slice(0, 32)); s.ToBigEndian(Bytes.AsSpan().Slice(32, 32)); V = v; }
public GameSave(string fileName) { Bytes = File.ReadAllBytes(FileName = fileName); IsRemaster = BitConverter.ToInt32(Bytes, 8) == 0; if (IsRemaster && !Path.GetFileNameWithoutExtension(fileName).StartsWith("svd_fmt_5_")) { throw new NotSupportedException("Save file is not a user save and changing them can lead to the game infinite looping. The editor only supports saves that start with svd_fmt_5."); } _header = new GameSaveHeader(this); Body = Bytes.AsSpan(BodyStart, BodyDataLength).ToArray(); IsCompressed = Encoding.Default.GetString(Body, 0, 4) == "zlib"; if (IsCompressed) { throw new NotSupportedException("Save file uses compression."); } _originalBodyLength = Body.Length; Stash = Stash.TryCreateStash(this); ReadOnlySpan <byte> data = Body; _bagOffset = GetBagOffset(data); _dataLengthOffsets = new[] { data.IndexOf(new byte[5] { 0x0C, 0xAE, 0x32, 0x00, 0x00 }) + 5, // unknown length 1 data.IndexOf(new byte[5] { 0xF7, 0x5D, 0x3C, 0x00, 0x0A }) + 5, // unknown length 2 data.IndexOf(new byte[5] { 0x23, 0xCC, 0x58, 0x00, 0x03 }) + 5, // type section length }; _itemContainer = new Container(this, data.IndexOf(new byte[5] { 0xD3, 0x34, 0x43, 0x00, 0x00 }), 0x00_24_D5_68_00_00_00_0Bul); _itemBuffsContainer = new Container(this, data.IndexOf(new byte[5] { 0xBB, 0xD5, 0x43, 0x00, 0x00 }), 0x00_28_60_84_00_00_00_0Bul); _itemSocketsContainer = new Container(this, data.IndexOf(new byte[5] { 0x93, 0xCC, 0x80, 0x00, 0x00 }), 0x00_59_36_38_00_00_00_0Bul); var itemLocs = _itemContainer.ToDictionary(x => x.id, x => (x.offset, x.dataLength)); var itemBuffsLocs = _itemBuffsContainer.ToDictionary(x => x.id, x => (x.offset, x.dataLength)); var itemSocketsLocs = _itemSocketsContainer.ToDictionary(x => x.id, x => (x.offset, x.dataLength)); int dataLength, playerActor = 0; var candidates = new List <(int id, int typeIdOffset, QuestItemDefinition?questItemDef)>(); for (int ixOfActor = _dataLengthOffsets[^ 1] + 4; BitConverter.ToInt32(Body, ixOfActor) == 0x00_75_2D_06; ixOfActor += dataLength)
public void GetRange() { var key = "TestGetRange_null"; cli.Set(key, Null); Assert.Equal("", cli.GetRange(key, 10, 20)); key = "TestGetRange_string"; cli.Set(key, "abcdefg"); Assert.Equal("cde", cli.GetRange(key, 2, 4)); Assert.Equal("abcdefg", cli.GetRange(key, 0, -1)); key = "TestGetRange_bytes"; cli.Set(key, Bytes); Assert.Equal(Bytes.AsSpan(2, 3).ToArray(), cli.GetRange <byte[]>(key, 2, 4)); Assert.Equal(Bytes, cli.GetRange <byte[]>(key, 0, -1)); }
public Item(GameSave gameSave, int typeIdOffset, int offset, int dataLength, int itemBuffsOffset, int itemBuffsLength, int itemGemsOffset, int itemGemsLength) { (_gameSave, TypeIdOffset, ItemOffset) = (gameSave, typeIdOffset, offset); _levelShiftOffset = (byte)(8 * gameSave.Body[TypeIdOffset + 10]); Bytes = _gameSave.Body.AsSpan(offset, dataLength).ToArray(); ItemSockets = new(gameSave, itemGemsOffset, itemGemsLength); ItemBuffs = new(gameSave, this, itemBuffsOffset, itemBuffsLength); var span = Bytes.AsSpan(Offsets.BuffCount); foreach (var(buffId, _) in BuffDuration.ReadList(ref span)) { PlayerBuffs.Add(Amalur.GetBuff(buffId)); } if (HasCustomName) { ItemName = _gameSave.Encoding.GetString(Bytes, Offsets.Name, NameLength); } }
public StashItem(GameSave gameSave, int offset, int dataLength, Gem[] gems) { ItemOffset = offset; Bytes = gameSave.Body.AsSpan(offset, dataLength).ToArray(); var span = Bytes.AsSpan(Offsets.BuffCount); foreach (var(buffId, _) in BuffDuration.ReadList(ref span)) { PlayerBuffs.Add(Amalur.GetBuff(buffId)); } if (HasCustomName) { ItemName = gameSave.Encoding.GetString(Bytes, Offsets.Name, NameLength); } Gems = gems; // socket section is either FF // or 20 02, followed by int32 count, and int32 handle per gem. int socketsStart = gems.Length == 0 ? Bytes.Length - 1 : gems[0].ItemOffset - offset - (4 * (1 + gems.Length)) - 2; ItemBuffs = Bytes[Offsets.HasItemBuffs] == 0x14 ? new ItemBuffMemory(this, socketsStart) : Definition.ItemBuffs; }
public GameSave(string fileName) { Bytes = File.ReadAllBytes(FileName = fileName); IsRemaster = BitConverter.ToInt32(Bytes, 8) == 0; SaveType = IsRemaster switch { true when Path.GetExtension(fileName) is "" => SaveType.Switch, true => SaveType.Remaster, false => SaveType.Original, }; var pattern = SaveType == SaveType.Switch ? SwitchFilePattern : RemasterFilePattern; if (IsRemaster && Path.GetExtension(fileName) != ".bin" && !Path.GetFileNameWithoutExtension(fileName).StartsWith(pattern)) { throw new NotSupportedException($"Save file is not a user save and changing them can lead to the game infinite looping. The editor only supports saves that start with {pattern}."); } _header = new(this); Buffs = FilterToApplicable(Amalur.Buffs.Values, _header.IsFateswornAware); ItemDefinitions = FilterToApplicable(Amalur.ItemDefinitions.Values, _header.IsFateswornAware); if (BitConverter.ToInt32(Bytes, BodyStart) == CompressedFlag) { Body = new byte[BitConverter.ToInt32(Bytes, BodyStart + 4)]; if (Body.Length != _header.BodyDataLength) { throw new NotSupportedException($"Save file appears corrupted. The header states that the body should have {_header.BodyDataLength} bytes, but the decompressed size is {Body.Length}"); } var bundleInfoStart = BodyStart + 12; var bundleInfoSize = BitConverter.ToInt32(Bytes, bundleInfoStart - 4); using var bundleInfoData = new ZLibStream(new MemoryStream(Bytes, bundleInfoStart, bundleInfoSize), CompressionMode.Decompress); var endOfBundle = bundleInfoData.ReadAll(Body); var gameStateStart = bundleInfoStart + bundleInfoSize + 4; var gameStateSize = BitConverter.ToInt32(Bytes, gameStateStart - 4); using var gameStateData = new ZLibStream(new MemoryStream(Bytes, gameStateStart, gameStateSize), CompressionMode.Decompress); gameStateData.ReadAll(Body.AsSpan(endOfBundle, Body.Length - endOfBundle)); } else { Body = Bytes.AsSpan(BodyStart, BodyDataLength).ToArray(); } _originalBodyLength = Body.Length; Stash = Stash.TryCreateStash(this); ReadOnlySpan <byte> data = Body; _bagOffset = GetBagOffset(data); _gameStateStartOffset = data.IndexOf(new byte[5] { 0xF7, 0x5D, 0x3C, 0x00, 0x0A }); var typeSectionOffset = data.IndexOf(new byte[5] { 0x23, 0xCC, 0x58, 0x00, 0x06 }) is int ix and > -1 ? ix : data.IndexOf(new byte[5] { 0x23, 0xCC, 0x58, 0x00, 0x04 }) is int pix and > -1 ? pix : data.IndexOf(new byte[5] { 0x23, 0xCC, 0x58, 0x00, 0x03 }); _dataLengthOffsets = new[] { _gameStateStartOffset + 5, // gameStateSize data.IndexOf(new byte[5] { 0x0C, 0xAE, 0x32, 0x00, 0x00 }) + 5, // unknown length 1 typeSectionOffset + 5, // type section length }; _itemContainer = new(this, data.IndexOf(new byte[5] { 0xD3, 0x34, 0x43, 0x00, 0x00 }), 0x00_24_D5_68_00_00_00_0Bul); _itemBuffsContainer = new(this, data.IndexOf(new byte[5] { 0xBB, 0xD5, 0x43, 0x00, 0x00 }), 0x00_28_60_84_00_00_00_0Bul); _itemSocketsContainer = new(this, data.IndexOf(new byte[5] { 0x93, 0xCC, 0x80, 0x00, 0x00 }), 0x00_59_36_38_00_00_00_0Bul); var itemLocs = _itemContainer.ToDictionary(x => x.id, x => (x.offset, x.dataLength)); var itemBuffsLocs = _itemBuffsContainer.ToDictionary(x => x.id, x => (x.offset, x.dataLength)); var itemSocketsLocs = _itemSocketsContainer.ToDictionary(x => x.id, x => (x.offset, x.dataLength)); int dataLength, playerActor = 0; var candidates = new List <(int id, int typeIdOffset, QuestItemDefinition?questItemDef)>(); for (int ixOfActor = _dataLengthOffsets[^ 1] + 4; BitConverter.ToInt32(Body, ixOfActor) == 0x00_75_2D_06; ixOfActor += dataLength)