mirror of
https://github.com/Thealexbarney/LibHac.git
synced 2024-11-14 10:49:41 +01:00
Switched to Ryujinx's implementation of LZ4
Fixed stream handling in Nso.cs
This commit is contained in:
parent
73b472befa
commit
e694833e0c
3 changed files with 103 additions and 13 deletions
|
@ -27,7 +27,6 @@
|
|||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="lz4net" Version="1.0.15.93" />
|
||||
<PackageReference Include="System.Numerics.Vectors" Version="4.5.0" Condition=" '$(TargetFramework)' == 'net46' " />
|
||||
</ItemGroup>
|
||||
|
||||
|
|
78
libhac/Lz4.cs
Normal file
78
libhac/Lz4.cs
Normal file
|
@ -0,0 +1,78 @@
|
|||
using System;
|
||||
|
||||
namespace Ryujinx.HLE.Loaders.Compression
|
||||
{
|
||||
static class Lz4
|
||||
{
|
||||
public static byte[] Decompress(byte[] Cmp, int DecLength)
|
||||
{
|
||||
byte[] Dec = new byte[DecLength];
|
||||
|
||||
int CmpPos = 0;
|
||||
int DecPos = 0;
|
||||
|
||||
int GetLength(int Length)
|
||||
{
|
||||
byte Sum;
|
||||
|
||||
if (Length == 0xf)
|
||||
{
|
||||
do
|
||||
{
|
||||
Length += (Sum = Cmp[CmpPos++]);
|
||||
}
|
||||
while (Sum == 0xff);
|
||||
}
|
||||
|
||||
return Length;
|
||||
}
|
||||
|
||||
do
|
||||
{
|
||||
byte Token = Cmp[CmpPos++];
|
||||
|
||||
int EncCount = (Token >> 0) & 0xf;
|
||||
int LitCount = (Token >> 4) & 0xf;
|
||||
|
||||
//Copy literal chunck
|
||||
LitCount = GetLength(LitCount);
|
||||
|
||||
Buffer.BlockCopy(Cmp, CmpPos, Dec, DecPos, LitCount);
|
||||
|
||||
CmpPos += LitCount;
|
||||
DecPos += LitCount;
|
||||
|
||||
if (CmpPos >= Cmp.Length)
|
||||
{
|
||||
break;
|
||||
}
|
||||
|
||||
//Copy compressed chunck
|
||||
int Back = Cmp[CmpPos++] << 0 |
|
||||
Cmp[CmpPos++] << 8;
|
||||
|
||||
EncCount = GetLength(EncCount) + 4;
|
||||
|
||||
int EncPos = DecPos - Back;
|
||||
|
||||
if (EncCount <= Back)
|
||||
{
|
||||
Buffer.BlockCopy(Dec, EncPos, Dec, DecPos, EncCount);
|
||||
|
||||
DecPos += EncCount;
|
||||
}
|
||||
else
|
||||
{
|
||||
while (EncCount-- > 0)
|
||||
{
|
||||
Dec[DecPos++] = Dec[EncPos++];
|
||||
}
|
||||
}
|
||||
}
|
||||
while (CmpPos < Cmp.Length &&
|
||||
DecPos < Dec.Length);
|
||||
|
||||
return Dec;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,5 +1,5 @@
|
|||
using LibHac.Streams;
|
||||
using LZ4;
|
||||
using Ryujinx.HLE.Loaders.Compression;
|
||||
using System;
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
|
@ -15,19 +15,20 @@ namespace LibHac
|
|||
public uint BssSize;
|
||||
public byte[] BuildID = new byte[0x20];
|
||||
|
||||
private BinaryReader reader;
|
||||
private SharedStreamSource StreamSource;
|
||||
|
||||
public Nso(Stream stream)
|
||||
{
|
||||
reader = new BinaryReader(stream);
|
||||
StreamSource = new SharedStreamSource(stream);
|
||||
BinaryReader reader = new BinaryReader(StreamSource.CreateStream());
|
||||
if (reader.ReadAscii(4) != "NSO0")
|
||||
throw new InvalidDataException("NSO magic is incorrect!");
|
||||
reader.ReadUInt32(); // Version
|
||||
reader.ReadUInt32(); // Reserved/Unused
|
||||
BitArray flags = new BitArray(new int[] { (int) reader.ReadUInt32() });
|
||||
NsoSection textSection = new NsoSection(stream);
|
||||
NsoSection rodataSection = new NsoSection(stream);
|
||||
NsoSection dataSection = new NsoSection(stream);
|
||||
NsoSection textSection = new NsoSection(StreamSource);
|
||||
NsoSection rodataSection = new NsoSection(StreamSource);
|
||||
NsoSection dataSection = new NsoSection(StreamSource);
|
||||
textSection.IsCompressed = flags[0];
|
||||
textSection.CheckHash = flags[3];
|
||||
rodataSection.IsCompressed = flags[1];
|
||||
|
@ -56,26 +57,31 @@ namespace LibHac
|
|||
reader.Read(dataSection.Hash, 0, 0x20);
|
||||
|
||||
Sections = new NsoSection[] {textSection, rodataSection, dataSection };
|
||||
reader.Close();
|
||||
}
|
||||
|
||||
public void ReadSegmentHeader(NsoSection section)
|
||||
{
|
||||
BinaryReader reader = new BinaryReader(StreamSource.CreateStream());
|
||||
section.FileOffset = reader.ReadUInt32();
|
||||
section.MemoryOffset = reader.ReadUInt32();
|
||||
section.DecompressedSize = reader.ReadUInt32();
|
||||
section.DecompressedSize = reader.ReadUInt32();
|
||||
reader.Close();
|
||||
}
|
||||
|
||||
public RodataRelativeExtent ReadRodataRelativeExtent()
|
||||
{
|
||||
BinaryReader reader = new BinaryReader(StreamSource.CreateStream());
|
||||
RodataRelativeExtent extent = new RodataRelativeExtent();
|
||||
extent.RegionRodataOffset = reader.ReadUInt32();
|
||||
extent.RegionSize = reader.ReadUInt32();
|
||||
reader.Close();
|
||||
return extent;
|
||||
}
|
||||
|
||||
public class NsoSection
|
||||
{
|
||||
private Stream Stream;
|
||||
private readonly SharedStreamSource StreamSource;
|
||||
|
||||
public bool IsCompressed,
|
||||
CheckHash;
|
||||
|
@ -85,19 +91,26 @@ namespace LibHac
|
|||
CompressedSize;
|
||||
public byte[] Hash = new byte[0x20];
|
||||
|
||||
public NsoSection(Stream stream)
|
||||
public NsoSection(SharedStreamSource streamSource)
|
||||
{
|
||||
Stream = stream;
|
||||
StreamSource = streamSource;
|
||||
}
|
||||
|
||||
public Stream OpenCompressedStream()
|
||||
{
|
||||
return new SubStream(Stream, FileOffset, CompressedSize);
|
||||
return StreamSource.CreateStream(FileOffset, CompressedSize);
|
||||
}
|
||||
|
||||
public Stream OpenDecompressedStream()
|
||||
{
|
||||
return new LZ4Stream(OpenCompressedStream(), LZ4StreamMode.Decompress);
|
||||
return new MemoryStream(Decompress());
|
||||
}
|
||||
|
||||
public byte[] Decompress()
|
||||
{
|
||||
byte[] compressed = new byte[CompressedSize];
|
||||
OpenCompressedStream().Read(compressed, 0, (int) CompressedSize);
|
||||
return Lz4.Decompress(compressed, (int) DecompressedSize);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in a new issue