mirror of
https://github.com/rvtr/TwlIPL_commit-99.git
synced 2025-10-31 06:21:11 -04:00
294 lines
8.4 KiB
C
294 lines
8.4 KiB
C
/*---------------------------------------------------------------------------*
|
||
Project: TwlFirm - tools - makegcdfirm
|
||
File: compress.c
|
||
|
||
Copyright 2007 Nintendo. All rights reserved.
|
||
|
||
These coded instructions, statements, and computer programs contain
|
||
proprietary information of Nintendo of America Inc. and/or Nintendo
|
||
Company Ltd., and are protected by Federal copyright law. They may
|
||
not be disclosed to third parties or copied or duplicated in any form,
|
||
in whole or in part, without the prior written consent of Nintendo.
|
||
|
||
$Date:: 2007-09-06$
|
||
$Rev$
|
||
$Author$
|
||
*---------------------------------------------------------------------------*/
|
||
#include <stdio.h>
|
||
#include <stdlib.h> // atoi()
|
||
#include <string.h> // strcmp()
|
||
#include <ctype.h> // isprint()
|
||
#include <unistd.h> // chdir()
|
||
#include <tchar.h>
|
||
#include <limits.h> // UCHAR_MAX
|
||
#include <time.h>
|
||
#include <sys/stat.h> // stat()
|
||
#include "elf.h"
|
||
#include "misc.h"
|
||
#include "defval.h"
|
||
#include "format_rom.h"
|
||
#include "format_nlist.h"
|
||
#include "makegcdfirm.h"
|
||
|
||
//#define ADD_HEADER
|
||
|
||
#define DIFF_CODE_HEADER (0x80)
|
||
#define RL_CODE_HEADER (0x30)
|
||
#define LZ_CODE_HEADER (0x10)
|
||
#define HUFF_CODE_HEADER (0x20)
|
||
#define CODE_HEADER_MASK (0xF0)
|
||
|
||
//===========================================================================
|
||
// LZ77ˆ³<CB86>k
|
||
//===========================================================================
|
||
static u8 SearchLZ(const u8 *nextp, u32 remainSize, u16 *offset);
|
||
|
||
static u16 windowPos;
|
||
static u16 windowLen;
|
||
|
||
static s16 LZOffsetTable[4096];
|
||
static s16 LZByteTable[256];
|
||
static s16 LZEndTable[256];
|
||
|
||
|
||
static void LZInitTable(void)
|
||
{
|
||
u16 i;
|
||
|
||
for (i = 0; i < 256; i++)
|
||
{
|
||
LZByteTable[i] = -1;
|
||
LZEndTable[i] = -1;
|
||
}
|
||
windowPos = 0;
|
||
windowLen = 0;
|
||
}
|
||
|
||
static void SlideByte(const u8 *srcp)
|
||
{
|
||
s16 offset;
|
||
u8 in_data = *srcp;
|
||
u16 insert_offset;
|
||
|
||
if (windowLen == 4096)
|
||
{
|
||
u8 out_data = *(srcp - 4096);
|
||
if ((LZByteTable[out_data] = LZOffsetTable[LZByteTable[out_data]]) == -1)
|
||
{
|
||
LZEndTable[out_data] = -1;
|
||
}
|
||
insert_offset = windowPos;
|
||
}
|
||
else
|
||
{
|
||
insert_offset = windowLen;
|
||
}
|
||
|
||
offset = LZEndTable[in_data];
|
||
if (offset == -1)
|
||
{
|
||
LZByteTable[in_data] = insert_offset;
|
||
}
|
||
else
|
||
{
|
||
LZOffsetTable[offset] = insert_offset;
|
||
}
|
||
LZEndTable[in_data] = insert_offset;
|
||
LZOffsetTable[insert_offset] = -1;
|
||
|
||
if (windowLen == 4096)
|
||
{
|
||
windowPos = (u16)((windowPos + 1) % 0x1000);
|
||
}
|
||
else
|
||
{
|
||
windowLen++;
|
||
}
|
||
}
|
||
|
||
static void LZSlide(const u8 *srcp, u32 n)
|
||
{
|
||
u32 i;
|
||
|
||
for (i = 0; i < n; i++)
|
||
{
|
||
SlideByte(srcp++);
|
||
}
|
||
}
|
||
|
||
/*---------------------------------------------------------------------------*
|
||
Name: MI_CompressLZ
|
||
|
||
Description: LZ77ˆ³<CB86>k‚ð<E2809A>s‚È‚¤ŠÖ<C5A0>”
|
||
|
||
Arguments: srcp ˆ³<CB86>kŒ³ƒf<C692>[ƒ^‚ւ̃|ƒCƒ“ƒ^
|
||
size ˆ³<CB86>kŒ³ƒf<C692>[ƒ^ƒTƒCƒY
|
||
dstp ˆ³<CB86>k<EFBFBD>æƒf<C692>[ƒ^‚ւ̃|ƒCƒ“ƒ^
|
||
ˆ³<CB86>kŒ³ƒf<C692>[ƒ^‚æ‚è‚à‘å‚«‚¢ƒTƒCƒY‚̃oƒbƒtƒ@‚ª•K—v‚Å‚·<E2809A>B
|
||
|
||
Returns: ˆ³<CB86>kŒã‚̃f<C692>[ƒ^ƒTƒCƒY<C692>B
|
||
ˆ³<CB86>kŒã‚̃f<C692>[ƒ^‚ªˆ³<CB86>k‘O‚æ‚è‚à‘å‚«‚‚È‚é<E2809A>ê<EFBFBD>‡‚ɂ͈³<CB86>k‚ð’†’f‚µ0‚ð•Ô‚µ‚Ü‚·<E2809A>B
|
||
*---------------------------------------------------------------------------*/
|
||
u32 LZCompWrite(u8 *srcp, u32 size, u8 *dstp, int boundary)
|
||
{
|
||
u32 LZDstCount; // ˆ³<CB86>kƒf<C692>[ƒ^‚̃oƒCƒg<C692>”
|
||
u8 LZCompFlags; // ˆ³<CB86>k‚Ì—L–³‚ðŽ¦‚·ƒtƒ‰ƒOŒn—ñ
|
||
u8 *LZCompFlagsp; // LZCompFlags ‚ðŠi”[‚·‚éƒ<C3A9>ƒ‚ƒŠ—̈æ‚ðƒ|ƒCƒ“ƒg
|
||
u16 lastOffset; // ˆê’vƒf<C692>[ƒ^‚܂ł̃IƒtƒZƒbƒg (‚»‚ÌŽž“_‚Å‚Ì<E2809A>Å’·ˆê’vƒf<C692>[ƒ^)
|
||
u8 lastLength; // ˆê’vƒf<C692>[ƒ^’· (‚»‚ÌŽž“_‚Å‚Ì<E2809A>Å’·ˆê’vƒf<C692>[ƒ^)
|
||
u8 i;
|
||
u32 dstMax;
|
||
|
||
#ifdef ADD_HEADER
|
||
*(u32 *)dstp = size << 8 | LZ_CODE_HEADER; // ƒf<C692>[ƒ^<5E>Eƒwƒbƒ_
|
||
dstp += 4;
|
||
#endif
|
||
LZDstCount = 4;
|
||
dstMax = size;
|
||
LZInitTable();
|
||
|
||
while (size > 0)
|
||
{
|
||
LZCompFlags = 0;
|
||
LZCompFlagsp = dstp++; // ƒtƒ‰ƒOŒn—ñ‚ÌŠi”[<5B>æ
|
||
LZDstCount++;
|
||
|
||
// ƒtƒ‰ƒOŒn—ñ‚ª8ƒrƒbƒgƒf<C692>[ƒ^‚Æ‚µ‚ÄŠi”[‚³‚ê‚邽‚ß<E2809A>A8‰ñƒ‹<C692>[ƒv
|
||
for (i = 0; i < 8; i++)
|
||
{
|
||
LZCompFlags <<= 1; // <20>‰‰ñ (i=0) ‚Í“Á‚ɈӖ¡‚͂Ȃ¢
|
||
if (size <= 0)
|
||
{
|
||
// <20>I’[‚É—ˆ‚½<E2809A>ê<EFBFBD>‡‚̓tƒ‰ƒO‚ð<E2809A>ÅŒã‚܂ŃVƒtƒg‚³‚¹‚Ä‚©‚ç<E2809A>I—¹
|
||
continue;
|
||
}
|
||
|
||
if ((lastLength = SearchLZ(srcp, size, &lastOffset)))
|
||
{
|
||
// ˆ³<CB86>k‰Â”\‚È<E2809A>ê<EFBFBD>‡‚̓tƒ‰ƒO‚ð—§‚Ä‚é
|
||
LZCompFlags |= 0x1;
|
||
|
||
// ƒIƒtƒZƒbƒg‚Í<E2809A>ãˆÊ4ƒrƒbƒg‚ƉºˆÊ8ƒrƒbƒg‚É•ª‚¯‚ÄŠi”[
|
||
*dstp++ = (u8)((lastLength - 3) << 4 | (lastOffset - 1) >> 8);
|
||
*dstp++ = (u8)((lastOffset - 1) & 0xff);
|
||
LZDstCount += 2;
|
||
LZSlide(srcp, lastLength);
|
||
srcp += lastLength;
|
||
size -= lastLength;
|
||
}
|
||
else
|
||
{
|
||
// ˆ³<CB86>k‚È‚µ
|
||
LZSlide(srcp, 1);
|
||
*dstp++ = *srcp++;
|
||
size--;
|
||
LZDstCount++;
|
||
}
|
||
} // 8‰ñƒ‹<C692>[ƒv<C692>I—¹
|
||
*LZCompFlagsp = LZCompFlags; // ƒtƒ‰ƒOŒn—ñ‚ðŠi”[
|
||
}
|
||
|
||
// 16ƒoƒCƒg‹«ŠEƒAƒ‰ƒCƒ“ƒ<E2809C>ƒ“ƒg
|
||
// ƒAƒ‰ƒCƒ“ƒ<E2809C>ƒ“ƒg—pƒf<C692>[ƒ^0 ‚̓f<C692>[ƒ^ƒTƒCƒY‚Ɋ܂߂é
|
||
i = 0;
|
||
while (LZDstCount & (boundary - 1))
|
||
// while ((LZDstCount + i) & 0x3)
|
||
{
|
||
*dstp++ = 0;
|
||
LZDstCount++;
|
||
i++;
|
||
}
|
||
|
||
return LZDstCount;
|
||
}
|
||
|
||
//--------------------------------------------------------
|
||
// LZ77ˆ³<CB86>k‚ŃXƒ‰ƒCƒh‘‹‚Ì’†‚©‚ç<E2809A>Å’·ˆê’v—ñ‚ðŒŸ<C592>õ‚µ‚Ü‚·<E2809A>B
|
||
// Arguments: startp ƒf<C692>[ƒ^‚ÌŠJŽnˆÊ’u‚ðŽ¦‚·ƒ|ƒCƒ“ƒ^
|
||
// nextp ŒŸ<C592>õ‚ðŠJŽn‚·‚éƒf<C692>[ƒ^‚̃|ƒCƒ“ƒ^
|
||
// remainSize Žc‚èƒf<C692>[ƒ^ƒTƒCƒY
|
||
// offset ˆê’v‚µ‚½ƒIƒtƒZƒbƒg‚ðŠi”[‚·‚é—̈æ‚ւ̃|ƒCƒ“ƒ^
|
||
// Return : ˆê’v—ñ‚ªŒ©‚‚©‚Á‚½<E2809A>ê<EFBFBD>‡‚Í TRUE
|
||
// Œ©‚‚©‚ç‚È‚©‚Á‚½<E2809A>ê<EFBFBD>‡‚Í FALSE
|
||
//--------------------------------------------------------
|
||
static u8 SearchLZ(const u8 *nextp, u32 remainSize, u16 *offset)
|
||
{
|
||
const u8 *searchp;
|
||
const u8 *headp, *searchHeadp;
|
||
u16 maxOffset;
|
||
u8 maxLength = 2;
|
||
u8 tmpLength;
|
||
s32 w_offset;
|
||
|
||
if (remainSize < 3)
|
||
{
|
||
return 0;
|
||
}
|
||
|
||
w_offset = LZByteTable[*nextp];
|
||
|
||
while (w_offset != -1)
|
||
{
|
||
if (w_offset < windowPos)
|
||
{
|
||
searchp = nextp - windowPos + w_offset;
|
||
}
|
||
else
|
||
{
|
||
searchp = nextp - windowLen - windowPos + w_offset;
|
||
}
|
||
|
||
/* –³‚‚Ä‚à—Ç‚¢‚ª<E2809A>A‹Í‚©‚É<E2809A>‚‘¬‰»‚·‚é */
|
||
if (*(searchp + 1) != *(nextp + 1) || *(searchp + 2) != *(nextp + 2))
|
||
{
|
||
w_offset = LZOffsetTable[w_offset];
|
||
continue;
|
||
}
|
||
|
||
if (nextp - searchp < 2)
|
||
{
|
||
// VRAM‚Í2ƒoƒCƒgƒAƒNƒZƒX‚Ȃ̂Š(VRAM‚©‚çƒf<C692>[ƒ^‚ð“Ç‚Ý<E2809A>o‚·<E2809A>ê<EFBFBD>‡‚ª‚ ‚邽‚ß)<29>A
|
||
// ŒŸ<C592>õ‘Î<E28098>Ûƒf<C692>[ƒ^‚Í2ƒoƒCƒg‘O‚©‚ç‚̃f<C692>[ƒ^‚É‚µ‚È‚¯‚ê‚΂Ȃç‚È‚¢<E2809A>B
|
||
//
|
||
// ƒIƒtƒZƒbƒg‚Í12ƒrƒbƒg‚ÅŠi”[‚³‚ê‚邽‚ß<E2809A>A4096ˆÈ‰º
|
||
break;
|
||
}
|
||
tmpLength = 3;
|
||
searchHeadp = searchp + 3;
|
||
headp = nextp + 3;
|
||
|
||
while (((u32)(headp - nextp) < remainSize) && (*headp == *searchHeadp))
|
||
{
|
||
headp++;
|
||
searchHeadp++;
|
||
tmpLength++;
|
||
|
||
// ƒf<C692>[ƒ^’·‚Í4ƒrƒbƒg‚ÅŠi”[‚³‚ê‚邽‚ß<E2809A>A18ˆÈ‰º (3‚̉º‘Ê‚ð‚Í‚©‚¹‚é)
|
||
if (tmpLength == (0xF + 3))
|
||
{
|
||
break;
|
||
}
|
||
}
|
||
if (tmpLength > maxLength)
|
||
{
|
||
// <20>ő咷ƒIƒtƒZƒbƒg‚ð<E2809A>X<EFBFBD>V
|
||
maxLength = tmpLength;
|
||
maxOffset = (u16)(nextp - searchp);
|
||
if (maxLength == (0xF + 3))
|
||
{
|
||
// ˆê’v’·‚ª<E2809A>Å‘å‚Ȃ̂Å<E2809A>AŒŸ<C592>õ‚ð<E2809A>I—¹‚·‚é<E2809A>B
|
||
break;
|
||
}
|
||
}
|
||
w_offset = LZOffsetTable[w_offset];
|
||
}
|
||
|
||
if (maxLength < 3)
|
||
{
|
||
return 0;
|
||
}
|
||
*offset = maxOffset;
|
||
return maxLength;
|
||
}
|
||
|