//********************************************************************************************
/**
 * @file		smpl_d2pack.cpp
 * @brief		D2Cパックデータ作成
 *
 *	このファイルの詳細説明
 *
 * @date		2013/03/19	takedan	新規作成.
 */
//********************************************************************************************

#define	SW_MODULE_SMPL_D2PACK						///< この機能を切り離したい時はコメントアウト.
#ifdef	SW_MODULE_SMPL_D2PACK

#ifdef _UNICODE

#ifndef _STOOLS_H
#include <system/win32/env.h>
#endif

//********************************************************************************************
/**
 * @class		SMPL_D2PACK
 * @brief		D2Cパックデータ作成スクリプトコマンドクラス.
 */
//********************************************************************************************
class SMPL_D2PACK
{
	BOOL		m_bInitialized;
	BOOL		m_bImplemented;
	BOOL		m_bFullInit;
	
	void		Initialize();
	
	enum{	enBuffSize = 1024*1024	};
	
	struct StFIleInfo
	{
		UInt32	m_uCrcName;
		UInt32	m_uOffset;
		UInt32	m_uSize;
	};
	enum{	HEADER_SIZE = (8)	};		//!< StHeader の m_stFiles を除いたサイズ.
	struct StHeader
	{
		Char		m_sId[ 4 ];
		Int16		m_iEntry;
		Int16		m_iRefEntry;
		
		StFIleInfo	m_stFiles[ 256 ];	//!< 最大値. 256個のデータ長があるわけではない.
	};
	
	struct StPacFile
	{
		TCHAR		m_sPath[ T_MAXPATH ];
		Char		m_sTexName[ T_MAXNAME ];
		Int32		m_iSize;
	};
	
public:
	virtual int		Func( LPCTSTR _sParamString );
	virtual void	Quit( BOOL _bExit );
	
	SMPL_D2PACK();
	virtual ~SMPL_D2PACK();
	
};

//********************************************************************************************
/**
 * @brief		D2Cパックデータ作成コンストラクタ.
 */
//********************************************************************************************
SMPL_D2PACK::SMPL_D2PACK()
	: m_bFullInit( FALSE )
	, m_bInitialized( FALSE )
	, m_bImplemented( FALSE )
{
	
}

//********************************************************************************************
/**
 * @brief		D2Cパックデータ作成デストラクタ.
 */
//********************************************************************************************
SMPL_D2PACK::~SMPL_D2PACK()
{
	
}


//==============================================================================================================================================
/**
	初期化と開放.
		1ファイルに1つの処理でコンプリートするような場合は修正する必要ありません
		注釈となっている Message_printf を有効にして sample.swb を実行すると動きがよく分かると思います。
*/
//==============================================================================================================================================

//********************************************************************************************
/**
 * @brief		D2Cパックデータ作成スクリプトコマンドの初期化.
 *				(特に必要ないなら変更の必要なし)
 *
 * @return		なし (none)
 */
//********************************************************************************************
void	SMPL_D2PACK::Initialize()
{
	if( m_bInitialized == TRUE )	return;
	m_bInitialized = TRUE;	//	初期済みフラグ
	
	if( m_bFullInit == FALSE )
	{
		m_bFullInit = TRUE;
		//	全体を通して一度しか行わない初期化
		
		//Message_printf( TEXT("全体の初期化") );
		
	}
	
	//	初期化処理
	//	１つのバッチに同じスクリプトが２度指定されていたならここには２度来る
	//Message_printf( TEXT("初期化") );
	
}

//********************************************************************************************
/**
 * @brief		D2Cパックデータ作成スクリプトコマンドの終了.
 *				(特に必要ないなら変更の必要なし)
 *
 * @param[in]	BOOL	_bExit	.
 *
 * @return		なし (none)
 */
//********************************************************************************************
void	SMPL_D2PACK::Quit(BOOL _bExit)
{
	//	ここにはスクリプトを使っていなくても来るので注意
	
	if( m_bImplemented == FALSE )	return;		///<変換処理が実行されていないなら帰還.
	m_bImplemented = FALSE;
	m_bInitialized = FALSE;
	
	///	終了処理.
	//Message_printf( TEXT("終了") );
	
	if( _bExit == TRUE )
	{
		//	次のスクリプトは存在しない、完全な終了
		//	１つのバッチに同じスクリプトに別パラメータを渡しての処理で
		//	逐一結果を出さず、全体で統合して結果を出したい場合などはここで
		
		//Message_printf( TEXT("全体の終了") );
	}
	
}







//==============================================================================================================================================
//	変換処理部分
//==============================================================================================================================================

#define	SMPL_D2PACK_OUTAREA		2	///< 変換後の容量は仮に元の倍取っている　内容によって変更して下さい.

//********************************************************************************************
/**
 * @brief	D2Cパックデータ作成変換フィルターサンプル　機能:無変換
 *			テキストデータを取り扱うサンプル.
 *			関数内は patol.lib を使用したサンプルになっているが、中身は完全に別物に変えても問題ありません.
 *
 *			
 *
 * @param[in]	LPCTSTR	_sParamString	引数文字列  ターゲットファイル名 + スクリプトで指定する引数.
 *
 * @return		int	TRUE:成 / FALSE:否(デフォルト)
 */
//********************************************************************************************
int		SMPL_D2PACK::Func( LPCTSTR _sParamString )
{
	CSwbParam	cParam( _sParamString );							///< パラメータ処理.
	
	TCHAR		cDrive[_MAX_DRIVE], cDir[_MAX_DIR], cName[_MAX_PATH], cExt[_MAX_EXT], cListName[T_MAXPATH];
	TCHAR		cWork[ 256 ];
	TCHAR		*pMem = NULL;
	Char		*pOut = NULL;
	int			ii, iOffset, iSourceLength;
	LPCTSTR		szFileName, szOutName;
	StHeader	*pHeader;
	StPacFile	stPacFiles[ 256 ];
	Int32		iPacEntry = 0;
	Char		cRefStr[1024] = "";
	Int32		iRefLength = 0;
	
	
	szFileName = cParam.GetPath();
	szOutName  = cParam.GetOutPath();
	
	
	/// 機能の初期化.
	Initialize();
	
	/// 元データ読み込み(関数内部でpMemに領域を確保している).
	iSourceLength = MEM_TextRead( &pMem, szFileName );							///< UNICODEの場合 UTF16に変換されて読まれます.
	if( iSourceLength == 0 )
	{
		/** エラーメッセージの表示　処理はMessage_printfと同じ、Message_errorを使用すると自動終了しなくなります */
		Message_error( TEXT("file not found:%s"), szFileName );
		return FALSE;						///< ファイルがない.
	}
	
	m_bImplemented = TRUE;					///< 実行済みフラグon. これをonにしないとQuit()が実行されない.
	
	/// 変換後のデータバッファを確保	元データがあまりに小さい場合があるので最低1KBは確保.
	mem_alloc( Char, pOut, enBuffSize );
	
	pHeader = (StHeader*)pOut;
	
	
	//! ヘッダーセット.
	memcpy( pHeader->m_sId, "D2C", 4 );
	pHeader->m_iEntry = 0;
	pHeader->m_iRefEntry = 0;
	
	
	{
		//! パックファイル情報列挙.
		TCHAR	*pp = pMem;
		
		Message_printf( TEXT("\r\n%s(%d)"), szFileName, stPacFiles[ iPacEntry ].m_iSize );
		{
			CTOSJIS	cJis( TEXT("D2DATA") );
			memcpy( stPacFiles[ iPacEntry ].m_sTexName, cJis.Get(), strlen(cJis.Get())+1 );
			
			FILE_split( szFileName, NULL, NULL, cName, cExt );
			FILE_split( szFileName, cDrive, cDir, NULL, NULL );
			
			FILE_merge( cListName, cDrive, cDir, cName, TEXT(".txt") );
			
			FILE_merge( stPacFiles[ iPacEntry ].m_sPath, cDrive, cDir, cName, TEXT(".d2b") );
			stPacFiles[ iPacEntry ].m_iSize = FILE_GetFileSize( stPacFiles[ iPacEntry ].m_sPath );
			
			if( stPacFiles[ iPacEntry ].m_iSize == 0 )
			{
				Message_error( TEXT("not found:%s"), stPacFiles[ iPacEntry ].m_sPath );
				return FALSE;
			}
		//	Message_printf( TEXT("%s(%d)"), stPacFiles[ iPacEntry ].m_sTexName, stPacFiles[ iPacEntry ].m_iSize );
			iPacEntry++;
		}
		
		while( 1 )
		{
			pp = STRING_str( pp, TEXT("<tex_param") );
			if( !pp )	break;
			pp = STRING_str( pp, TEXT("fname=\"") );
			if( !pp )	break;
			pp += STRING_len( TEXT("fname=\"") );
			ii = 0;
			while( *pp != '"' )	cWork[ ii++ ] = *pp++;
			cWork[ ii ] = '\0';
			
			for( ii=0 ; ii<iPacEntry ; ii++ )
			{
				CTOUTF16	cUtf( stPacFiles[ ii ].m_sTexName );
				if( 0 == STRING_cmp( cUtf.Get(), cWork ) )	break;
			}
			
			if( ii >= iPacEntry )
			{
				FILE_printf( cListName, TEXT("%s\r\n"), cWork );
				
			//	STRING_cpy( stPacFiles[ iPacEntry ].m_sTexName, cWork );
				CTOSJIS	cJis(cWork);
				memcpy( stPacFiles[ iPacEntry ].m_sTexName, cJis.Get(), strlen(cJis.Get())+1 );
				
				FILE_split( cWork, NULL, NULL, cName, cExt );
				FILE_split( szFileName, cDrive, cDir, NULL, NULL );
				
				FILE_merge( stPacFiles[ iPacEntry ].m_sPath, cDrive, cDir, cName, TEXT(".gim") );
				if( FILE_GetFileSize( stPacFiles[ iPacEntry ].m_sPath ) == 0 )
				{
					catyen( cDir );
					STRING_cat( cDir, TEXT("gim") );
					FILE_merge( stPacFiles[ iPacEntry ].m_sPath, cDrive, cDir, cName, TEXT(".gim") );
				}
				stPacFiles[ iPacEntry ].m_iSize = FILE_GetFileSize( stPacFiles[ iPacEntry ].m_sPath );
				if( 0 == stPacFiles[ iPacEntry ].m_iSize )
				{
					Message_error( TEXT("not found:%s"), stPacFiles[ iPacEntry ].m_sPath );
				}
			//	Message_printf( TEXT("%s(%d)"), stPacFiles[ iPacEntry ].m_sTexName, stPacFiles[ iPacEntry ].m_iSize );
				iPacEntry++;
			}
		}
	}
	{
		//! リファレンス名列挙.
		TCHAR	*pp = pMem;
		while( 1 )
		{
			pp = STRING_str( pp, TEXT("<Reference") );
			if( !pp )	break;
			pp = STRING_str( pp, TEXT("<data name=\"") );
			if( !pp )	break;
			pp += STRING_len( TEXT("<data name=\"") );
			ii = 0;
			while( *pp != '"' )	cWork[ ii++ ] = *pp++;
			cWork[ ii ] = '\0';
			
		//	if( STRING_cmp( cWork, TEXT("n_all") ) == 0 )	continue;
			if( cWork[ 0 ] != '@' )	continue;
			TCHAR	*pPtr = &cWork[ 1 ];
			
			CTOSJIS	cJis(pPtr);
			BUF_copy( &cRefStr[ iRefLength ], cJis.Get(), STRING_len(pPtr) );
			iRefLength += STRING_len( pPtr ) + 1;
			pHeader->m_iRefEntry++;
		}
		if(0<iRefLength)	iRefLength += 4 - (iRefLength % 4);
	}
	
	iOffset = (HEADER_SIZE + sizeof(StFIleInfo) * iPacEntry) + iRefLength;
	for( ii=0 ; ii<iPacEntry ; ii++ )
	{
		CTOUTF16	cUtf( stPacFiles[ ii ].m_sTexName );
		pHeader->m_stFiles[ ii ].m_uCrcName = STRING_crc32( cUtf.Get() );
		pHeader->m_stFiles[ ii ].m_uOffset = iOffset;
		pHeader->m_stFiles[ ii ].m_uSize = stPacFiles[ ii ].m_iSize;
		Message_printf( TEXT("%-24s 0x%08X,0x%08X,0x%08X"), cUtf.Get(), pHeader->m_stFiles[ ii ].m_uCrcName, pHeader->m_stFiles[ ii ].m_uOffset, pHeader->m_stFiles[ ii ].m_uSize );
		
		iOffset += ((stPacFiles[ ii ].m_iSize + 3)/4)*4;
	}
	
	pHeader->m_iEntry = iPacEntry;
	//! リファレンス部分をコピー.
	if(0<iRefLength)	BUF_copy( pOut + HEADER_SIZE + sizeof(StFIleInfo)*iPacEntry, cRefStr, iRefLength );
	
	iOffset = (HEADER_SIZE + sizeof(StFIleInfo) * iPacEntry) + iRefLength;
	for( ii=0 ; ii<iPacEntry ; ii++ )
	{
		Char	*pTex = NULL;
		Int32	iLength = MEM_TargetRead( &pTex, stPacFiles[ ii ].m_sPath );
		
		if( iOffset+iLength >= enBuffSize )
		{
			del_alloc( pTex );
			del_alloc( pMem );
			del_alloc( pOut );
			Message_error( TEXT("buff over:%s"), stPacFiles[ ii ].m_sPath );
			return FALSE;
		}
		
		BUF_copy( pOut + iOffset, pTex, iLength );
		iOffset += ((iLength + 3)/4)*4;
		del_alloc( pTex );
	}
	
	
	/// 変換された pOut(iOffset) を出力　　出力ファイル名はバッチで指定、特に指定されていなければ元と同じファイル名.
	{
		TCHAR	cTemp[ T_MAXPATH ], szTemp[ T_MAXPATH ];
		TCHAR	cFolder[][16] = {
			TEXT("scene"),
			TEXT("play"),
			TEXT("ui"),
		};
		Int32	iFolderIndex = 0;
		
		FILE_GetCurrentDirectory( cTemp, T_MAXPATH );
		//if( STRING_str( cTemp, TEXT("play") ) != NULL )		iFolderIndex = 1;
		//else if( STRING_str( cTemp, TEXT("ui") ) != NULL )	iFolderIndex = 2;
		
		FILE_split( szOutName, NULL, NULL, cName, NULL );
	//	ENV_GetStr( cTemp, T_MAXPATH, TEXT("ROCK_ROOT") );
	//	STRING_printf( szTemp, T_MAXPATH, TEXT("%s\\discRoot\\psp\\%s\\graphics\\%s.d2c"), cTemp, cFolder[ iFolderIndex ], cName );
	
	//	STRING_printf( szTemp, T_MAXPATH, TEXT("%s\\resource\\psp\\%s\\graphics\\d2c\\%s.d2c"), cTemp, cFolder[ iFolderIndex ], cName );
		
		// 2013/7/8 修正 abe shunta.
		STRING_printf( szTemp, T_MAXPATH, TEXT("%s\\d2c\\%s.d2c"), cTemp, cName );

		FILE_TargetWrite( szTemp, pOut, iOffset );
	}
	
	
	/// メモリを開放.
	del_alloc( pMem );
	del_alloc( pOut );
	
	return TRUE;
}
#else
class SMPL_D2PACK
{
public:
	virtual int		Func( LPCTSTR _sParamString ){return 0;}
	virtual void	Quit( BOOL _bExit ){}
	
	SMPL_D2PACK(){}
	virtual ~SMPL_D2PACK(){}
};
#endif	// _UNICODE


SMPL_D2PACK	*pC_smpl_d2pack = NULL;

#endif	// SW_MODULE_SMPL_D2PACK
