ryujinx/Ryujinx.HLE/Loaders/Compression/BackwardsLz.cs
gdkchan 00579927e4
Better process implementation (#491)
* Initial implementation of KProcess

* Some improvements to the memory manager, implement back guest stack trace printing

* Better GetInfo implementation, improve checking in some places with information from process capabilities

* Allow the cpu to read/write from the correct memory locations for accesses crossing a page boundary

* Change long -> ulong for address/size on memory related methods to avoid unnecessary casts

* Attempt at implementing ldr:ro with new KProcess

* Allow BSS with size 0 on ldr:ro

* Add checking for memory block slab heap usage, return errors if full, exit gracefully

* Use KMemoryBlockSize const from KMemoryManager

* Allow all methods to read from non-contiguous locations

* Fix for TransactParcelAuto

* Address PR feedback, additionally fix some small issues related to the KIP loader and implement SVCs GetProcessId, GetProcessList, GetSystemInfo, CreatePort and ManageNamedPort

* Fix wrong check for source pages count from page list on MapPhysicalMemory

* Fix some issues with UnloadNro on ldr:ro
2018-11-28 20:18:09 -02:00

105 lines
2.9 KiB
C#

using System;
using System.IO;
namespace Ryujinx.HLE.Loaders.Compression
{
static class BackwardsLz
{
private class BackwardsReader
{
private Stream BaseStream;
public BackwardsReader(Stream BaseStream)
{
this.BaseStream = BaseStream;
}
public byte ReadByte()
{
BaseStream.Seek(-1, SeekOrigin.Current);
byte Value = (byte)BaseStream.ReadByte();
BaseStream.Seek(-1, SeekOrigin.Current);
return Value;
}
public short ReadInt16()
{
return (short)((ReadByte() << 8) | (ReadByte() << 0));
}
public int ReadInt32()
{
return ((ReadByte() << 24) |
(ReadByte() << 16) |
(ReadByte() << 8) |
(ReadByte() << 0));
}
}
public static byte[] Decompress(Stream Input, int DecompressedLength)
{
long End = Input.Position;
BackwardsReader Reader = new BackwardsReader(Input);
int AdditionalDecLength = Reader.ReadInt32();
int StartOffset = Reader.ReadInt32();
int CompressedLength = Reader.ReadInt32();
Input.Seek(12 - StartOffset, SeekOrigin.Current);
byte[] Dec = new byte[DecompressedLength];
int DecompressedLengthUnpadded = CompressedLength + AdditionalDecLength;
int DecompressionStart = DecompressedLength - DecompressedLengthUnpadded;
int DecPos = Dec.Length;
byte Mask = 0;
byte Header = 0;
while (DecPos > DecompressionStart)
{
if ((Mask >>= 1) == 0)
{
Header = Reader.ReadByte();
Mask = 0x80;
}
if ((Header & Mask) == 0)
{
Dec[--DecPos] = Reader.ReadByte();
}
else
{
ushort Pair = (ushort)Reader.ReadInt16();
int Length = (Pair >> 12) + 3;
int Position = (Pair & 0xfff) + 3;
DecPos -= Length;
if (Length <= Position)
{
int SrcPos = DecPos + Position;
Buffer.BlockCopy(Dec, SrcPos, Dec, DecPos, Length);
}
else
{
for (int Offset = 0; Offset < Length; Offset++)
{
Dec[DecPos + Offset] = Dec[DecPos + Position + Offset];
}
}
}
}
return Dec;
}
}
}