forked from Guillem96/argon-nx
-
Notifications
You must be signed in to change notification settings - Fork 4
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
36 changed files
with
19,784 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,98 @@ | ||
/* | ||
* Copyright (c) 2018 rajkosto | ||
* Copyright (c) 2018 SciresM | ||
* | ||
* This program is free software; you can redistribute it and/or modify it | ||
* under the terms and conditions of the GNU General Public License, | ||
* version 2, as published by the Free Software Foundation. | ||
* | ||
* This program is distributed in the hope it will be useful, but WITHOUT | ||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or | ||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for | ||
* more details. | ||
* | ||
* You should have received a copy of the GNU General Public License | ||
* along with this program. If not, see <http://www.gnu.org/licenses/>. | ||
*/ | ||
|
||
#include <stdlib.h> | ||
#include <string.h> | ||
|
||
#include "blz.h" | ||
|
||
const blz_footer *blz_get_footer(const unsigned char *compData, unsigned int compDataLen, blz_footer *outFooter) | ||
{ | ||
if (compDataLen < sizeof(blz_footer)) | ||
return NULL; | ||
|
||
const blz_footer *srcFooter = (const blz_footer*)&compData[compDataLen - sizeof(blz_footer)]; | ||
if (outFooter != NULL) | ||
memcpy(outFooter, srcFooter, sizeof(blz_footer)); // Must be a memcpy because no umaligned accesses on ARMv4. | ||
|
||
return srcFooter; | ||
} | ||
|
||
// From https://github.com/SciresM/hactool/blob/master/kip.c which is exactly how kernel does it, thanks SciresM! | ||
int blz_uncompress_inplace(unsigned char *dataBuf, unsigned int compSize, const blz_footer *footer) | ||
{ | ||
u32 addl_size = footer->addl_size; | ||
u32 header_size = footer->header_size; | ||
u32 cmp_and_hdr_size = footer->cmp_and_hdr_size; | ||
|
||
unsigned char* cmp_start = &dataBuf[compSize] - cmp_and_hdr_size; | ||
u32 cmp_ofs = cmp_and_hdr_size - header_size; | ||
u32 out_ofs = cmp_and_hdr_size + addl_size; | ||
|
||
while (out_ofs) | ||
{ | ||
unsigned char control = cmp_start[--cmp_ofs]; | ||
for (unsigned int i=0; i<8; i++) | ||
{ | ||
if (control & 0x80) | ||
{ | ||
if (cmp_ofs < 2) | ||
return 0; // Out of bounds. | ||
|
||
cmp_ofs -= 2; | ||
u16 seg_val = ((unsigned int)(cmp_start[cmp_ofs + 1]) << 8) | cmp_start[cmp_ofs]; | ||
u32 seg_size = ((seg_val >> 12) & 0xF) + 3; | ||
u32 seg_ofs = (seg_val & 0x0FFF) + 3; | ||
if (out_ofs < seg_size) // Kernel restricts segment copy to stay in bounds. | ||
seg_size = out_ofs; | ||
|
||
out_ofs -= seg_size; | ||
|
||
for (unsigned int j = 0; j < seg_size; j++) | ||
cmp_start[out_ofs + j] = cmp_start[out_ofs + j + seg_ofs]; | ||
} | ||
else | ||
{ | ||
// Copy directly. | ||
if (cmp_ofs < 1) | ||
return 0; //out of bounds | ||
|
||
cmp_start[--out_ofs] = cmp_start[--cmp_ofs]; | ||
} | ||
control <<= 1; | ||
if (out_ofs == 0) // Blz works backwards, so if it reaches byte 0, it's done. | ||
return 1; | ||
} | ||
} | ||
|
||
return 1; | ||
} | ||
|
||
int blz_uncompress_srcdest(const unsigned char *compData, unsigned int compDataLen, unsigned char *dstData, unsigned int dstSize) | ||
{ | ||
blz_footer footer; | ||
const blz_footer *compFooterPtr = blz_get_footer(compData, compDataLen, &footer); | ||
if (compFooterPtr == NULL) | ||
return 0; | ||
|
||
// Decompression must be done in-place, so need to copy the relevant compressed data first. | ||
unsigned int numCompBytes = (const unsigned char*)(compFooterPtr)-compData; | ||
memcpy(dstData, compData, numCompBytes); | ||
memset(&dstData[numCompBytes], 0, dstSize - numCompBytes); | ||
|
||
return blz_uncompress_inplace(dstData, compDataLen, &footer); | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,36 @@ | ||
/* | ||
* Copyright (c) 2018 rajkosto | ||
* | ||
* This program is free software; you can redistribute it and/or modify it | ||
* under the terms and conditions of the GNU General Public License, | ||
* version 2, as published by the Free Software Foundation. | ||
* | ||
* This program is distributed in the hope it will be useful, but WITHOUT | ||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or | ||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for | ||
* more details. | ||
* | ||
* You should have received a copy of the GNU General Public License | ||
* along with this program. If not, see <http://www.gnu.org/licenses/>. | ||
*/ | ||
|
||
#ifndef _BLZ_H_ | ||
#define _BLZ_H_ | ||
|
||
#include <utils/types.h> | ||
|
||
typedef struct _blz_footer | ||
{ | ||
u32 cmp_and_hdr_size; | ||
u32 header_size; | ||
u32 addl_size; | ||
} blz_footer; | ||
|
||
// Returns pointer to footer in compData if present, additionally copies it to outFooter if not NULL. | ||
const blz_footer *blz_get_footer(const unsigned char *compData, unsigned int compDataLen, blz_footer *outFooter); | ||
// Returns 0 on failure. | ||
int blz_uncompress_inplace(unsigned char *dataBuf, unsigned int compSize, const blz_footer *footer); | ||
// Returns 0 on failure. | ||
int blz_uncompress_srcdest(const unsigned char *compData, unsigned int compDataLen, unsigned char *dstData, unsigned int dstSize); | ||
|
||
#endif |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,181 @@ | ||
/************************************************************************* | ||
* Name: lz.c | ||
* Author: Marcus Geelnard | ||
* Description: LZ77 coder/decoder implementation. | ||
* Reentrant: Yes | ||
* | ||
* The LZ77 compression scheme is a substitutional compression scheme | ||
* proposed by Abraham Lempel and Jakob Ziv in 1977. It is very simple in | ||
* its design, and uses no fancy bit level compression. | ||
* | ||
* This is my first attempt at an implementation of a LZ77 code/decoder. | ||
* | ||
* The principle of the LZ77 compression algorithm is to store repeated | ||
* occurrences of strings as references to previous occurrences of the same | ||
* string. The point is that the reference consumes less space than the | ||
* string itself, provided that the string is long enough (in this | ||
* implementation, the string has to be at least 4 bytes long, since the | ||
* minimum coded reference is 3 bytes long). Also note that the term | ||
* "string" refers to any kind of byte sequence (it does not have to be | ||
* an ASCII string, for instance). | ||
* | ||
* The coder uses a brute force approach to finding string matches in the | ||
* history buffer (or "sliding window", if you wish), which is very, very | ||
* slow. I recon the complexity is somewhere between O(n^2) and O(n^3), | ||
* depending on the input data. | ||
* | ||
* There is also a faster implementation that uses a large working buffer | ||
* in which a "jump table" is stored, which is used to quickly find | ||
* possible string matches (see the source code for LZ_CompressFast() for | ||
* more information). The faster method is an order of magnitude faster, | ||
* but still quite slow compared to other compression methods. | ||
* | ||
* The upside is that decompression is very fast, and the compression ratio | ||
* is often very good. | ||
* | ||
* The reference to a string is coded as a (length,offset) pair, where the | ||
* length indicates the length of the string, and the offset gives the | ||
* offset from the current data position. To distinguish between string | ||
* references and literal strings (uncompressed bytes), a string reference | ||
* is preceded by a marker byte, which is chosen as the least common byte | ||
* symbol in the input data stream (this marker byte is stored in the | ||
* output stream as the first byte). | ||
* | ||
* Occurrences of the marker byte in the stream are encoded as the marker | ||
* byte followed by a zero byte, which means that occurrences of the marker | ||
* byte have to be coded with two bytes. | ||
* | ||
* The lengths and offsets are coded in a variable length fashion, allowing | ||
* values of any magnitude (up to 4294967295 in this implementation). | ||
* | ||
* With this compression scheme, the worst case compression result is | ||
* (257/256)*insize + 1. | ||
* | ||
*------------------------------------------------------------------------- | ||
* Copyright (c) 2003-2006 Marcus Geelnard | ||
* | ||
* This software is provided 'as-is', without any express or implied | ||
* warranty. In no event will the authors be held liable for any damages | ||
* arising from the use of this software. | ||
* | ||
* Permission is granted to anyone to use this software for any purpose, | ||
* including commercial applications, and to alter it and redistribute it | ||
* freely, subject to the following restrictions: | ||
* | ||
* 1. The origin of this software must not be misrepresented; you must not | ||
* claim that you wrote the original software. If you use this software | ||
* in a product, an acknowledgment in the product documentation would | ||
* be appreciated but is not required. | ||
* | ||
* 2. Altered source versions must be plainly marked as such, and must not | ||
* be misrepresented as being the original software. | ||
* | ||
* 3. This notice may not be removed or altered from any source | ||
* distribution. | ||
* | ||
* Marcus Geelnard | ||
* marcus.geelnard at home.se | ||
*************************************************************************/ | ||
|
||
|
||
/************************************************************************* | ||
* INTERNAL FUNCTIONS * | ||
*************************************************************************/ | ||
|
||
|
||
/************************************************************************* | ||
* _LZ_ReadVarSize() - Read unsigned integer with variable number of | ||
* bytes depending on value. | ||
*************************************************************************/ | ||
|
||
static int _LZ_ReadVarSize( unsigned int * x, const unsigned char * buf ) | ||
{ | ||
unsigned int y, b, num_bytes; | ||
|
||
/* Read complete value (stop when byte contains zero in 8:th bit) */ | ||
y = 0; | ||
num_bytes = 0; | ||
do | ||
{ | ||
b = (unsigned int) (*buf ++); | ||
y = (y << 7) | (b & 0x0000007f); | ||
++ num_bytes; | ||
} | ||
while( b & 0x00000080 ); | ||
|
||
/* Store value in x */ | ||
*x = y; | ||
|
||
/* Return number of bytes read */ | ||
return num_bytes; | ||
} | ||
|
||
|
||
|
||
/************************************************************************* | ||
* PUBLIC FUNCTIONS * | ||
*************************************************************************/ | ||
|
||
|
||
/************************************************************************* | ||
* LZ_Uncompress() - Uncompress a block of data using an LZ77 decoder. | ||
* in - Input (compressed) buffer. | ||
* out - Output (uncompressed) buffer. This buffer must be large | ||
* enough to hold the uncompressed data. | ||
* insize - Number of input bytes. | ||
*************************************************************************/ | ||
|
||
unsigned int LZ_Uncompress( const unsigned char *in, unsigned char *out, | ||
unsigned int insize ) | ||
{ | ||
unsigned char marker, symbol; | ||
unsigned int i, inpos, outpos, length, offset; | ||
|
||
/* Do we have anything to uncompress? */ | ||
if( insize < 1 ) | ||
{ | ||
return 0; | ||
} | ||
|
||
/* Get marker symbol from input stream */ | ||
marker = in[ 0 ]; | ||
inpos = 1; | ||
|
||
/* Main decompression loop */ | ||
outpos = 0; | ||
do | ||
{ | ||
symbol = in[ inpos ++ ]; | ||
if( symbol == marker ) | ||
{ | ||
/* We had a marker byte */ | ||
if( in[ inpos ] == 0 ) | ||
{ | ||
/* It was a single occurrence of the marker byte */ | ||
out[ outpos ++ ] = marker; | ||
++ inpos; | ||
} | ||
else | ||
{ | ||
/* Extract true length and offset */ | ||
inpos += _LZ_ReadVarSize( &length, &in[ inpos ] ); | ||
inpos += _LZ_ReadVarSize( &offset, &in[ inpos ] ); | ||
|
||
/* Copy corresponding data from history window */ | ||
for( i = 0; i < length; ++ i ) | ||
{ | ||
out[ outpos ] = out[ outpos - offset ]; | ||
++ outpos; | ||
} | ||
} | ||
} | ||
else | ||
{ | ||
/* No marker, plain copy */ | ||
out[ outpos ++ ] = symbol; | ||
} | ||
} | ||
while( inpos < insize ); | ||
|
||
return outpos; | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,52 @@ | ||
/************************************************************************* | ||
* Name: lz.h | ||
* Author: Marcus Geelnard | ||
* Description: LZ77 coder/decoder interface. | ||
* Reentrant: Yes | ||
*------------------------------------------------------------------------- | ||
* Copyright (c) 2003-2006 Marcus Geelnard | ||
* | ||
* This software is provided 'as-is', without any express or implied | ||
* warranty. In no event will the authors be held liable for any damages | ||
* arising from the use of this software. | ||
* | ||
* Permission is granted to anyone to use this software for any purpose, | ||
* including commercial applications, and to alter it and redistribute it | ||
* freely, subject to the following restrictions: | ||
* | ||
* 1. The origin of this software must not be misrepresented; you must not | ||
* claim that you wrote the original software. If you use this software | ||
* in a product, an acknowledgment in the product documentation would | ||
* be appreciated but is not required. | ||
* | ||
* 2. Altered source versions must be plainly marked as such, and must not | ||
* be misrepresented as being the original software. | ||
* | ||
* 3. This notice may not be removed or altered from any source | ||
* distribution. | ||
* | ||
* Marcus Geelnard | ||
* marcus.geelnard at home.se | ||
*************************************************************************/ | ||
|
||
#ifndef _lz_h_ | ||
#define _lz_h_ | ||
|
||
#ifdef __cplusplus | ||
extern "C" { | ||
#endif | ||
|
||
|
||
/************************************************************************* | ||
* Function prototypes | ||
*************************************************************************/ | ||
|
||
unsigned int LZ_Uncompress( const unsigned char *in, unsigned char *out, | ||
unsigned int insize ); | ||
|
||
|
||
#ifdef __cplusplus | ||
} | ||
#endif | ||
|
||
#endif /* _lz_h_ */ |
Oops, something went wrong.