
#include	"stdafx.h"
#include	"ExtractBase.h"
#include	"Image.h"
#include	"Tga.h"

//////////////////////////////////////////////////////////////////////////////////////////
//	僨僐乕僪

BOOL	CTga::Decode(
	CArcFile*			pclArc,							// 傾乕僇僀僽
	const void*			pvSrc,							// TGA僨乕僞
	DWORD				dwSrcSize,						// TGA僨乕僞僒僀僘
	const YCString&		rfclsFileLastName				// 僼傽僀儖柤偺枛旜
	)
{
	const BYTE*			pbtSrc = (const BYTE*) pvSrc;
	const STGAHeader*	psttgahSrc = (STGAHeader*) pvSrc;

	pbtSrc += sizeof(STGAHeader);
	dwSrcSize -= sizeof(STGAHeader);

	// 夝搥

	YCMemory<BYTE>		clmbtSrc2;

	switch( psttgahSrc->btImageType )
	{
	case	9:
	case	10:
		// RLE埑弅

		DWORD				dwSrcSize2 = ((psttgahSrc->wWidth * (psttgahSrc->btDepth >> 3) + 3) & 0xFFFFFFFC) * psttgahSrc->wHeight;

		clmbtSrc2.resize( dwSrcSize2 );

		DecompRLE( &clmbtSrc2[0], dwSrcSize2, pbtSrc, dwSrcSize, psttgahSrc->btDepth );

		pbtSrc = &clmbtSrc2[0];
		dwSrcSize = dwSrcSize2;

		break;
	}

	CImage				clImage;

	if( psttgahSrc->btDepth == 0 )
	{
		clImage.Init( pclArc, psttgahSrc->wWidth, psttgahSrc->wHeight, 32, NULL, 0, rfclsFileLastName );
		clImage.WriteReverse( pbtSrc, dwSrcSize );
		clImage.Close();
	}
	else
	{
		clImage.Init( pclArc, psttgahSrc->wWidth, psttgahSrc->wHeight, psttgahSrc->btDepth, NULL, 0, rfclsFileLastName );
		clImage.Write( pbtSrc, dwSrcSize );
		clImage.Close();
	}

	return	TRUE;
}

//////////////////////////////////////////////////////////////////////////////////////////
//	埑弅TGA偺夝搥

BOOL	CTga::Decomp(
	void*				pvDst,							// 奿擺愭
	DWORD				dwDstSize,						// 奿擺愭僒僀僘
	const void*			pvSrc,							// 埑弅TGA
	DWORD				dwSrcSize						// 埑弅TGA僒僀僘
	)
{
	BYTE*				pbtDst = (BYTE*) pvDst;
	const BYTE*			pbtSrc = (const BYTE*) pvSrc;
	const STGAHeader*	psttgahSrc = (STGAHeader*) pvSrc;

	pbtSrc += sizeof(STGAHeader);
	dwSrcSize -= sizeof(STGAHeader);

	// 夝搥

	switch( psttgahSrc->btDepth )
	{
	case	9:
	case	10:
		// RLE

		DecompRLE( pbtDst, dwDstSize, pbtSrc, dwSrcSize, psttgahSrc->btDepth );
		break;

	default:
		// 柍埑弅

		memcpy( pbtDst, pbtSrc, dwSrcSize );
	}

	return	TRUE;
}

//////////////////////////////////////////////////////////////////////////////////////////
//	RLE夝搥

BOOL	CTga::DecompRLE(
	void*				pvDst,							// 奿擺愭
	DWORD				dwDstSize,						// 奿擺愭僒僀僘
	const void*			pvSrc,							// 埑弅僨乕僞
	DWORD				dwSrcSize,						// 埑弅僨乕僞僒僀僘
	BYTE				wBpp							// 價僢僩悢
	)
{
	const BYTE*			pbtSrc = (const BYTE*) pvSrc;
	BYTE*				pbtDst = (BYTE*) pvDst;
	DWORD				dwSrcPtr = 0;
	DWORD				dwDstPtr = 0;
	WORD				wByteCount = (wBpp >> 3);

	while( (dwSrcPtr < dwSrcSize) && (dwDstPtr < dwDstSize) )
	{
		DWORD				dwLength = pbtSrc[dwSrcPtr++];

		if( dwLength & 0x80 )
		{
			dwLength = (dwLength & 0x7F) + 1;

			for( DWORD i = 0 ; i < dwLength ; i++ )
			{
				memcpy( &pbtDst[dwDstPtr], &pbtSrc[dwSrcPtr], wByteCount );

				dwDstPtr += wByteCount;
			}

			dwSrcPtr += wByteCount;
		}
		else
		{
			dwLength++;

			dwLength *= wByteCount;

			memcpy( &pbtDst[dwDstPtr], &pbtSrc[dwSrcPtr], dwLength );

			dwSrcPtr += dwLength;
			dwDstPtr += dwLength;
		}

		if( memcmp( &pbtSrc[dwSrcPtr + 8], "TRUEVISION-XFILE", 16 ) == 0 )
		{
			// 廔抂

			break;
		}
	}

	return	TRUE;
}
