1
Name:
Anonymous
2011-12-02 10:51
Following lines were found in Nintendo DS SDK.
// If the 8th bit of the data length storage byte is 0, it not an encoding data sequence.
u4 RLDstCount; // Expansion data size in bytes
u4 RLSrcCount; // Size of data that is targeted for expansion in bytes--after processing
if ( srcp[ RLSrcCount ] & 0x80 ) // decoding process (run length encoded)
{
length = srcp[ RLSrcCount++ ] & 0x7f; // store data length (three geta are worn, so consider it actually +3)
// Data expansion control function (Because it auto expands, it will not run if at the end there is no header for raw data expansion.)
u8 *startp; // Points to the beginning of data that is the compression target for one process loop.
pCompList = compList; // Points to the array that holds the compression sequence.
// Process to add a NULL header (pseudo header for data before it is compressed)
tmp = srcp[i] & 0x0f; HuffTable[tmp].Freq++; // The concern is the encoding floor
// search target data must be data from before two byte.
//
// offset is stored as 12-bit so less than 4096
9
Name:
Anonymous
2011-12-02 11:10
dbg_printf( stderr, "nitroCompress raw\n" );
RawWrite(pReadBuf, dataSize, dstp);
if ( pCompBuf[0] != NULL ) {
free( (void *)pCompBuf[0] );
pCompBuf[0] = NULL;
}
if (pCompBuf[1] != NULL) {
free( pCompBuf[1] );
pCompBuf[1] = NULL;
}
return dataSize;
}
}
// One more loop
pReadBuf = pCompBuf[ compBufNo ];
compBufNo ^= 0x01;
dataSize = nextDataSize;
pCompList++;
}
}
//===========================================================================
// Copy compression data
//===========================================================================
STATIC u32 RawWrite(u8 *srcp, u32 size, u8 *dstp)
{
u32 i;
dbg_printf( stderr, "RawWrite\tsize=%d\n\n",size );
for ( i = 0; i < size - 1; i++ ) {
*dstp = *srcp;
dstp++;
srcp++;
}
*dstp = *srcp;
return size;
}
//===========================================================================
// Difference filter
//===========================================================================
STATIC u32 DiffFiltWrite( u8 *srcp, u32 size, u8 *dstp, u8 diffBitSize )
{
u32 DiffCount; // Compression data size in bytes
u32 i;
u16 *src16p = (u16 *)srcp;
u16 *dst16p = (u16 *)dstp;
dbg_printf_dif( stderr, "DiffFiltWrite\tsize=%d\tdiffBitSize=%d\n", size, diffBitSize );
*(u32 *)dstp = size << 8 | ( DIFF_CODE_HEADER | diffBitSize / 8 ); // data header
DiffCount = 4;
if (diffBitSize == 8)
{
#ifdef DEBUG_PRINT_DIFFFILT
for ( i = 0; i < 16; i++ ) {
dbg_printf_dif(stderr, "srcp[%d] = %x\n",i,srcp[i] );
}
#endif
dstp[DiffCount] = srcp[0]; // top table only without diffs
DiffCount++;
for ( i = 1; i < size; i++, DiffCount++ )
{
dbg_printf_dif( stderr, "dstp[%x] = srcp[%d]-srcp[%d] = %x - %x = %x\n",
DiffCount, i, i - 1, srcp[i] , srcp[i-1], srcp[i] - srcp[i-1] );
dstp[DiffCount] = srcp[i] - srcp[ i - 1 ]; // diff data storage
}
}
else // 16-bit size
{
dst16p[DiffCount/2] = src16p[0];
DiffCount += 2;
for ( i = 1; i < size / 2; i++, DiffCount += 2 ) {
dst16p[DiffCount/2] = src16p[i] - src16p[i-1];
}
}
// 4-byte border alignment
// 0 data for alignment is not included in the data size.
i = 0;
while ((DiffCount+i) & 0x3) {
dstp[DiffCount+i] = 0;
i++;
}
return DiffCount;
}
//===========================================================================
// Run length encoding (bytes)
//===========================================================================
STATIC u32 RLCompWrite (u8 *srcp, u32 size, u8 *dstp)
{
u32 RLDstCount; // Compression data size in bytes
u32 RLSrcCount; // Size of data that is the targeted for compression, after processing is complete (bytes)
u8 RLCompFlag; // For run length encoding use 1
u8 runLength; // Run length
u8 rawDataLength; // Length of data that is not run
u32 i;
u8 *startp; // Points to the beginning of data that is the compression target for one process loop.
dbg_printf_rl( stderr, "RLCompWrite\tsize=%d\n", size );
// data header (size is after extraction)
*(u32 *)dstp = size << 8 | RL_CODE_HEADER; // data header
RLDstCount = 4;
RLSrcCount = 0;
rawDataLength = 0;
RLCompFlag = 0;
while ( RLSrcCount < size )
{
startp = &srcp[ RLSrcCount ]; // Setting the compression target data
for ( i = 0; i < 128; i++ ) // Data sized 0-127 can be expressed as 7-bit
{
// Reached the end of the compression target data.
if ( RLSrcCount + rawDataLength >= size ) {
rawDataLength = (u8)(size - RLSrcCount);
break;
}
if ( RLSrcCount + rawDataLength + 2 < size ) {
if ( startp[ i ] == startp[ i + 1 ] &&
startp[i] == startp[i+2] )
{
RLCompFlag = 1;
break;
}
}
rawDataLength++;
}
// Store data that will not be encoded.
// If the 8th bit of the data length storage byte is 0, it not an encoding data sequence.
// Data length is the number -1. Therefore 0-127 becomes 1-128.
if ( rawDataLength ) {
dstp[ RLDstCount++ ] = rawDataLength - 1; // "Data length -1" storage (7 bits)
for ( i = 0; i < rawDataLength; i++ ) {
dstp[ RLDstCount++ ] = srcp[ RLSrcCount++ ];
}
rawDataLength = 0;
}
// Run length encoding
if ( RLCompFlag )
{
runLength = 3;
for ( i = 3; i < 128 + 2; i++ ) {
// Reached the end of the data for compression
if ( RLSrcCount + runLength >= size ) {
runLength = (u8)( size - RLSrcCount );
break;
}
// If there is a pause in the run
if ( srcp[ RLSrcCount ] != srcp[ RLSrcCount + runLength ] ) {
break;
}
// Continuing the run
runLength++;
}
// If the 8th bit of the data length storage byte is 1, it is an encoded data sequence.
dstp[ RLDstCount++ ] = 0x80 | ( runLength - 3 ); // Add 3 from the bottom and store 3-130
dstp[ RLDstCount++ ] = srcp[ RLSrcCount ];
RLSrcCount += runLength;
RLCompFlag = 0;
}
}
// 4-byte border alignment
// 0 data for alignment is not included in the data size
i = 0;
while ( ( RLDstCount+i ) & 0x3 ) {
dstp[RLDstCount+i] = 0;
i++;
}
return RLDstCount;
}
10
Name:
Anonymous
2011-12-02 11:11
//===========================================================================
// LZ77 compression
//===========================================================================
STATIC u32 LZCompWrite( u8 *srcp, u32 size, u8 *dstp, u8 lzSearchOffset )
{
u32 LZDstCount; // Compression data size in bytes
u32 LZSrcCount; // Size of data that is the target of compression, after processing is complete (bytes)
u8 LZCompFlags; // Flag sequence that indicates whether compression or not.
u8 *LZCompFlagsp; // Points to the memory region that stores LZCompFlags
u8 *compressingDataHeadp; // Beginning address of the current data region that is targeted for compression.
u8 *searchp; // Beginning address of the matching data search region
u16 tmpOffset; // Offset to the matching data (mid-search data)
u8 tmpLength; // Matching data length (mid-search data)
u16 lastOffset; // Offset to matching data (longest matching data at that time)
u8 lastLength; // Matching data length (longest matching data at that time)
u8 i;
dbg_printf_lz( stderr, "LZCompWrite\tsize=%d\tlzSearchOffset=%d\n", size, lzSearchOffset );
*(u32 *)dstp = size << 8 | LZ_CODE_HEADER; // data header
LZDstCount = 4;
LZSrcCount = 0;
while ( LZSrcCount < size )
{
LZCompFlags = 0;
LZCompFlagsp = &dstp[ LZDstCount++ ]; // storage target of flag series
// flag series is stored as 8-bit data, so 8-time loop
for ( i = 0; i < 8; i++ )
{
LZCompFlags <<= 1; // the first time (i=0) carries no special significance
lastOffset = 0;
lastLength = 0;
compressingDataHeadp = &srcp[ LZSrcCount ];
// VRAM is two-byte access so (since there are cases where data is read from VRAM)
// search target data must be data from before two byte.
//
// offset is stored as 12-bit so less than 4096
for ( tmpOffset = lzSearchOffset; tmpOffset <= LZSrcCount && tmpOffset <= 4096; tmpOffset++ )
{
if ( LZSrcCount >= size ) {
break;
}
searchp = &srcp[ LZSrcCount - tmpOffset ]; // search data region setting
if (*searchp == *compressingDataHeadp) // matching data found
{
// data length is stored with four bits, so less than 18 (put on the 3 clog)
for ( tmpLength = 1; tmpLength <= 16 + 2; tmpLength++ ) {
if ( searchp[ tmpLength ] != compressingDataHeadp[ tmpLength ] ) {
break;
}
}
if ( tmpLength > 16 + 2 ) {
tmpLength = 18; // so it doesn't become 19
}
if ( LZSrcCount + tmpLength >= size ) {
tmpLength = (u8)(size - LZSrcCount);
}
// update the longest matching data
if ( tmpLength >= 3 && tmpLength > lastLength ) {
lastOffset = tmpOffset;
lastLength = tmpLength;
LZCompFlags |= 0x01;
}
}
}
// storage of LZCompFlags one compressed data
if ( LZSrcCount < size ) {
if ( (LZCompFlags & 0x01) == 0 ) { // no compression
dstp[ LZDstCount++ ] = srcp[ LZSrcCount++ ];
} else {
// offset is separated into top four bits and bottom eight bits and stored
dstp[ LZDstCount++ ] = (lastLength - 3) << 4 | (lastOffset - 1) >> 8;
dstp[ LZDstCount++ ] = (lastOffset - 1) & 0xff;
LZSrcCount += lastLength;
}
}
} // 8-time loop ends
*LZCompFlagsp = LZCompFlags; // store flag series
}
// four byte boundary alignment
// don't include data 0 for alignment in data size
i = 0;
while ( (LZDstCount + i) & 0x3 ) {
dstp[ LZDstCount + i ] = 0;
i++;
}
return LZDstCount;
}