/// <summary> /// Decrypts the given buffer. The buffer must be 64 bytes long. /// </summary> /// <param name="buffer"></param> public void Decrypt64(RandomAccess buffer) { if (buffer == null) { throw new ArgumentNullException(nameof(buffer)); } if (buffer.Length != 64) { throw new ArgumentException($"The given buffer was not 64 bytes ({buffer.Length}).", nameof(buffer)); } for (int i = 0x0F; i >= 0; i--) { int positionA = i; int keyA = GetWord(positionA); int positionB = keyA & 0x0F; int data1 = buffer.JumpAbsolute(positionA * 4).LongLE(); data1 -= keyA; int data2 = buffer.JumpAbsolute(positionB * 4).LongLE(); data2 -= keyA; int opAnd1 = data1 & keyA; int opNotA = ~keyA; int opAnd2 = data2 & opNotA; int opOr1 = opAnd1 | opAnd2; buffer.JumpAbsolute(positionA * 4).WriteLongLE(opOr1); int opAnd3 = data2 & keyA; int opAnd4 = data1 & opNotA; int opOr2 = opAnd3 | opAnd4; buffer.JumpAbsolute(positionB * 4).WriteLongLE(opOr2); } }
public void LEReadWriteTest() { var ra = new RandomAccess(new byte[] { 1, 2, 3, 4 }); int value = ra.LongLE(); ra.JumpAbsolute(0); ra.WriteLongLE(value); ra.JumpAbsolute(0); int value2 = ra.LongLE(); Assert.AreEqual(value, value2); }
public void ShouldSkipPartiallyOverwrittenBlock() { var rx = new RandomAccess(new byte[4 * 256]); rx.WriteLongLE(0); rx.WriteLongLE(0x300); rx.JumpAbsolute(0x100); // Inside the previous block! rx.WriteLongLE(0x100); rx.WriteLongLE(0x200); rx.JumpAbsolute(0); var block = new TpsBlock(rx, 0, 0x300, false); Assert.AreEqual(1, block.Pages.Count); Assert.AreEqual(0x100, block.Pages[0].Address); Assert.AreEqual(0x200, block.Pages[0].Size); }
public void ShouldReadTwoBlocksWithGap() { var rx = new RandomAccess(new byte[4 * 256]); rx.WriteLongLE(0); rx.WriteLongLE(0x100); rx.JumpAbsolute(0x200); rx.WriteLongLE(0x200); rx.WriteLongLE(0x100); rx.JumpAbsolute(0); var block = new TpsBlock(rx, 0, 0x300, false); Assert.AreEqual(2, block.Pages.Count); Assert.AreEqual(0x100, block.Pages[0].Size); Assert.AreEqual(0x100, block.Pages[1].Size); }
/// <summary> /// Encrypts the given buffer. The buffer must be 64 bytes long. /// </summary> /// <param name="buffer">The buffer to encrypt.</param> public void Encrypt64(RandomAccess buffer) { if (buffer == null) { throw new ArgumentNullException(nameof(buffer)); } if (buffer.Length != 64) { throw new ArgumentException($"The given buffer was not 64 bytes ({buffer.Length}).", nameof(buffer)); } for (int i = 0; i < 0x10; i++) { int positionA = i; int keyA = GetWord(i); int positionB = keyA & 0x0F; int data2 = buffer.JumpAbsolute(positionA * 4).LongLE(); int data1 = buffer.JumpAbsolute(positionB * 4).LongLE(); int opAnd1 = keyA & data2; int opNotA = ~keyA; int opAnd2 = opNotA & data1; int opOr1 = opAnd1 | opAnd2; int sum1 = keyA + opOr1; buffer.JumpAbsolute(positionA * 4).WriteLongLE(sum1); int opAnd3 = keyA & data1; int opAnd4 = opNotA & data2; int opOr2 = opAnd3 | opAnd4; int sum2 = opOr2 + keyA; buffer.JumpAbsolute(positionB * 4).WriteLongLE(sum2); } }
public TpsBlock(RandomAccess rx, int start, int end, bool ignorePageErrors) { Data = rx ?? throw new ArgumentNullException(nameof(rx)); Start = start; End = end; _pages = new List <TpsPage>(); Data.PushPosition(); Data.JumpAbsolute(Start); try { // Some blocks are 0 in length and should be skipped while (Data.Position < End) { if (IsCompletePage()) { try { var page = new TpsPage(Data); _pages.Add(page); } catch (RunLengthEncodingException ex) { if (ignorePageErrors) { Debug.WriteLine($"Ignored RLE error: {ex.ToString()}"); } else { throw; } } } else { Data.JumpRelative(0x100); } NavigateToNextPage(); } } finally { Data.PopPosition(); } }