File Annotation

Not logged in
13b7203622 2011-02-23        kinaba: 
13b7203622 2011-02-23        kinaba: #include "stdafx.h"
13b7203622 2011-02-23        kinaba: #include "ArcCpt.h"
13b7203622 2011-02-23        kinaba: #include "NoahApp.h"
13b7203622 2011-02-23        kinaba: 
13b7203622 2011-02-23        kinaba: //--- CArchiver --------------------------------------------------
13b7203622 2011-02-23        kinaba: 
13b7203622 2011-02-23        kinaba: bool CArcCpt::v_check( const kiPath& aname )
13b7203622 2011-02-23        kinaba: {
13b7203622 2011-02-23        kinaba: 	bool ans = ( cpt.open( aname ) && read_main_hdr() && check_index_crc() );
13b7203622 2011-02-23        kinaba: 	cpt.close();
13b7203622 2011-02-23        kinaba: 	return ans;
13b7203622 2011-02-23        kinaba: }
13b7203622 2011-02-23        kinaba: 
13b7203622 2011-02-23        kinaba: bool CArcCpt::v_list( const arcname& aname, aflArray& files )
13b7203622 2011-02-23        kinaba: {
13b7203622 2011-02-23        kinaba: 	::SetCurrentDirectory( aname.basedir );
13b7203622 2011-02-23        kinaba: 
13b7203622 2011-02-23        kinaba: 	bool ans = ( cpt.open( aname.lname ) && read_main_hdr() && operation_for_each( true, &files ) );
13b7203622 2011-02-23        kinaba: 	cpt.close();
13b7203622 2011-02-23        kinaba: 	return ans;
13b7203622 2011-02-23        kinaba: }
13b7203622 2011-02-23        kinaba: 
13b7203622 2011-02-23        kinaba: int CArcCpt::v_melt( const arcname& aname, const kiPath& ddir, const aflArray* files )
13b7203622 2011-02-23        kinaba: {
13b7203622 2011-02-23        kinaba: 	::SetCurrentDirectory( aname.basedir );
13b7203622 2011-02-23        kinaba: 	if( !cpt.open( aname.lname ) )
13b7203622 2011-02-23        kinaba: 		return 0xffff;
13b7203622 2011-02-23        kinaba: 
13b7203622 2011-02-23        kinaba: 	::SetCurrentDirectory( ddir );
13b7203622 2011-02-23        kinaba: 	bool ans = ( read_main_hdr() && operation_for_each( false, const_cast<aflArray*>(files) ) );
13b7203622 2011-02-23        kinaba: 	cpt.close();
13b7203622 2011-02-23        kinaba: 	return ans ? 0 : 0x8020;
13b7203622 2011-02-23        kinaba: }
13b7203622 2011-02-23        kinaba: 
13b7203622 2011-02-23        kinaba: int CArcCpt::v_contents( const kiPath& aname, kiPath& dname )
13b7203622 2011-02-23        kinaba: {
13b7203622 2011-02-23        kinaba: 	int ans=aUnknown;
13b7203622 2011-02-23        kinaba: 	if( cpt.open( aname ) && read_main_hdr() )
13b7203622 2011-02-23        kinaba: 	{
13b7203622 2011-02-23        kinaba: 		if( cpt.read( tmp, 7 ) )
13b7203622 2011-02-23        kinaba: 		{
13b7203622 2011-02-23        kinaba: 			WORD EntryNum = (tmp[4]<<8)  + tmp[5];
13b7203622 2011-02-23        kinaba: 			if( EntryNum == 1 )
13b7203622 2011-02-23        kinaba: 				ans = aSingleFile;
13b7203622 2011-02-23        kinaba: 			else
13b7203622 2011-02-23        kinaba: 			{
13b7203622 2011-02-23        kinaba: 				cpt.read( tmp, tmp[6] );
13b7203622 2011-02-23        kinaba: 				tmp[0] = cpt.getc();
13b7203622 2011-02-23        kinaba: 				if( tmp[0] & 0x80 ) // Folder
13b7203622 2011-02-23        kinaba: 				{
13b7203622 2011-02-23        kinaba: 					unsigned long size = (tmp[0]&0x3f) + 2;
13b7203622 2011-02-23        kinaba: 					if( size == cpt.read( tmp+1, size ) )
13b7203622 2011-02-23        kinaba: 						if( EntryNum == 1 + (tmp[size-1]<<8) + tmp[size] )
13b7203622 2011-02-23        kinaba: 						{
13b7203622 2011-02-23        kinaba: 							dname = "";
13b7203622 2011-02-23        kinaba: 							tmp[ 1+tmp[0] ] = '\0';
13b7203622 2011-02-23        kinaba: 							for( char* pp=(char*)tmp+1; *pp; pp=kiStr::next(pp) )
13b7203622 2011-02-23        kinaba: 							{
13b7203622 2011-02-23        kinaba: 								if( kiStr::isLeadByte(*pp) )
13b7203622 2011-02-23        kinaba: 									dname += *pp, dname += *(pp+1);
13b7203622 2011-02-23        kinaba: 								else if( *pp<' ' || *pp>'~' )
13b7203622 2011-02-23        kinaba: 									dname += '_';
13b7203622 2011-02-23        kinaba: 								else switch( *pp )
13b7203622 2011-02-23        kinaba: 								{
13b7203622 2011-02-23        kinaba: 									case '\\': case '/': case ':': case '*':
13b7203622 2011-02-23        kinaba: 									case '?': case '\"': case '<': case '>': case '|':
13b7203622 2011-02-23        kinaba: 										dname += '_';
13b7203622 2011-02-23        kinaba: 									default:
13b7203622 2011-02-23        kinaba: 										dname += *pp;
13b7203622 2011-02-23        kinaba: 								}
13b7203622 2011-02-23        kinaba: 							}
13b7203622 2011-02-23        kinaba: 
13b7203622 2011-02-23        kinaba: 							ans = aSingleDir;
13b7203622 2011-02-23        kinaba: 						}
13b7203622 2011-02-23        kinaba: 				}
13b7203622 2011-02-23        kinaba: 			}
13b7203622 2011-02-23        kinaba: 		}
13b7203622 2011-02-23        kinaba: 	}
13b7203622 2011-02-23        kinaba: 	cpt.close();
13b7203622 2011-02-23        kinaba: 	return ans;
13b7203622 2011-02-23        kinaba: }
13b7203622 2011-02-23        kinaba: 
13b7203622 2011-02-23        kinaba: //--- CRC ----------------------------------------------------------
13b7203622 2011-02-23        kinaba: 
13b7203622 2011-02-23        kinaba: static unsigned long crctbl[256] = { 1 };
13b7203622 2011-02-23        kinaba: 
13b7203622 2011-02-23        kinaba: static void init_crc_table()
13b7203622 2011-02-23        kinaba: {
13b7203622 2011-02-23        kinaba: 	if( crctbl[0]==1 ) // uninitialized
13b7203622 2011-02-23        kinaba: 		for( unsigned long c,n=0; n!=256; n++ )
13b7203622 2011-02-23        kinaba: 		{
13b7203622 2011-02-23        kinaba: 			c = n;
13b7203622 2011-02-23        kinaba: 			for( unsigned long k=8; k; k-- )
13b7203622 2011-02-23        kinaba: 				c = (c&1) ? ((0xedb88320L)^(c>>1)) : (c>>1);
13b7203622 2011-02-23        kinaba: 			crctbl[n] = c;
13b7203622 2011-02-23        kinaba: 		}
13b7203622 2011-02-23        kinaba: }
13b7203622 2011-02-23        kinaba: 
13b7203622 2011-02-23        kinaba: static unsigned long crc( unsigned long c, unsigned char* cp,int cnt )
13b7203622 2011-02-23        kinaba: {
13b7203622 2011-02-23        kinaba: 	while( cnt-- )
13b7203622 2011-02-23        kinaba: 		c = (c>>8)^crctbl[(c&0xff)^*cp++];
13b7203622 2011-02-23        kinaba: 	return c;
13b7203622 2011-02-23        kinaba: }
13b7203622 2011-02-23        kinaba: 
13b7203622 2011-02-23        kinaba: //--- cpt ----------------------------------------------------------
13b7203622 2011-02-23        kinaba: 
13b7203622 2011-02-23        kinaba: bool CArcCpt::read_main_hdr()
13b7203622 2011-02-23        kinaba: {
13b7203622 2011-02-23        kinaba: 	//-- 先頭のバイトは MagicNumber : 0x01 なはず。
13b7203622 2011-02-23        kinaba: 	m_nMacBinOffset = 0;
13b7203622 2011-02-23        kinaba: 	if( 8 != cpt.read( tmp, 8 ) )
13b7203622 2011-02-23        kinaba: 		return false;
13b7203622 2011-02-23        kinaba: 	if( tmp[0] != 1 )
13b7203622 2011-02-23        kinaba: 	{
13b7203622 2011-02-23        kinaba: 		if(  0  != tmp[0]
13b7203622 2011-02-23        kinaba: 		 || 120 != cpt.read( tmp, 120 )
13b7203622 2011-02-23        kinaba: 		 ||  8  != cpt.read( tmp,  8  )
13b7203622 2011-02-23        kinaba: 		 || tmp[0] != 1 ) // MacBinスキップ
13b7203622 2011-02-23        kinaba: 			return false;
13b7203622 2011-02-23        kinaba: 		m_nMacBinOffset = 128;
13b7203622 2011-02-23        kinaba: 	}
13b7203622 2011-02-23        kinaba: 
13b7203622 2011-02-23        kinaba: 	//-- indexまで跳ぶ
13b7203622 2011-02-23        kinaba: 	cpt.seek( (tmp[4]<<24) + (tmp[5]<<16) + (tmp[6]<<8) + (tmp[7]) - 8 );
13b7203622 2011-02-23        kinaba: 	return true;
13b7203622 2011-02-23        kinaba: }
13b7203622 2011-02-23        kinaba: 
13b7203622 2011-02-23        kinaba: bool CArcCpt::check_index_crc()
13b7203622 2011-02-23        kinaba: {
13b7203622 2011-02-23        kinaba: 	bool folder;
13b7203622 2011-02-23        kinaba: 	unsigned int size;
13b7203622 2011-02-23        kinaba: 
13b7203622 2011-02-23        kinaba: 	//-- CRC(DWORD), EntryNum(WORD), CommentLen(BYTE)
13b7203622 2011-02-23        kinaba: 	if( !cpt.read( tmp, 7 ) )
13b7203622 2011-02-23        kinaba: 		return false;
13b7203622 2011-02-23        kinaba: 
13b7203622 2011-02-23        kinaba: 	init_crc_table();
13b7203622 2011-02-23        kinaba: 
13b7203622 2011-02-23        kinaba: 	DWORD     CRC = (tmp[0]<<24) + (tmp[1]<<16) + (tmp[2]<<8) + tmp[3];
13b7203622 2011-02-23        kinaba: 	WORD EntryNum = (tmp[4]<<8)  + tmp[5];
13b7203622 2011-02-23        kinaba: 	if( tmp[6] != cpt.read( tmp+7, tmp[6] ) )
13b7203622 2011-02-23        kinaba: 		return false;
13b7203622 2011-02-23        kinaba: 	DWORD chk_crc = crc( 0xffffffff, tmp+4, 3+tmp[6] );
13b7203622 2011-02-23        kinaba: 
13b7203622 2011-02-23        kinaba: 	//-- 全ヘッダを走査してCRC計算
13b7203622 2011-02-23        kinaba: 	for( WORD i=0; i!=EntryNum; i++ )
13b7203622 2011-02-23        kinaba: 	{
13b7203622 2011-02-23        kinaba: 		tmp[0] = cpt.getc();
13b7203622 2011-02-23        kinaba: 
13b7203622 2011-02-23        kinaba: 		if( tmp[0] & 0x80 )	folder = true,  size = (tmp[0]&0x3f) + 2;
13b7203622 2011-02-23        kinaba: 		else				folder = false, size = (tmp[0]) + 45;
13b7203622 2011-02-23        kinaba: 		if( size != cpt.read( tmp+1, size ) ) return false;
13b7203622 2011-02-23        kinaba: 
13b7203622 2011-02-23        kinaba: 		chk_crc = crc( chk_crc, tmp, 1+size );
13b7203622 2011-02-23        kinaba:     }
13b7203622 2011-02-23        kinaba: 
13b7203622 2011-02-23        kinaba: 	return CRC == chk_crc;
13b7203622 2011-02-23        kinaba: }
13b7203622 2011-02-23        kinaba: 
13b7203622 2011-02-23        kinaba: bool CArcCpt::operation_for_each( bool o_list, aflArray* files )
13b7203622 2011-02-23        kinaba: {
13b7203622 2011-02-23        kinaba: 	//-- Entry数を得る
13b7203622 2011-02-23        kinaba: 	if( !cpt.read( tmp, 7 ) )
13b7203622 2011-02-23        kinaba: 		return false;
13b7203622 2011-02-23        kinaba: 	WORD EntryNum = (tmp[4]<<8)  + tmp[5];
13b7203622 2011-02-23        kinaba: 	cpt.read( tmp, tmp[6] );
13b7203622 2011-02-23        kinaba: 
13b7203622 2011-02-23        kinaba: 	//-- ダイアログ準備
13b7203622 2011-02-23        kinaba: 	pdlg = files ? NULL : new CArcProgressDlg( EntryNum );
13b7203622 2011-02-23        kinaba: 
13b7203622 2011-02-23        kinaba: 	//-- 操作
13b7203622 2011-02-23        kinaba: 	kiPath path;
13b7203622 2011-02-23        kinaba: 	m_nIndexPos = cpt.tell();
13b7203622 2011-02-23        kinaba: 	bool ans = recurse( o_list, files, path, 0, EntryNum );
13b7203622 2011-02-23        kinaba: 	delete pdlg;
13b7203622 2011-02-23        kinaba: 	return ans;
13b7203622 2011-02-23        kinaba: }
13b7203622 2011-02-23        kinaba: 
13b7203622 2011-02-23        kinaba: bool CArcCpt::recurse( bool o_list, aflArray* files, kiPath& path, int base, int num )
13b7203622 2011-02-23        kinaba: {
13b7203622 2011-02-23        kinaba: 	bool folder;
13b7203622 2011-02-23        kinaba: 	unsigned int size;
13b7203622 2011-02-23        kinaba: 	kiPath pthtmp;
13b7203622 2011-02-23        kinaba: 
13b7203622 2011-02-23        kinaba: 	for( int i=0; i<num; i++ )
13b7203622 2011-02-23        kinaba: 	{
13b7203622 2011-02-23        kinaba: 		cpt.seekTo( m_nIndexPos );
13b7203622 2011-02-23        kinaba: 
13b7203622 2011-02-23        kinaba: 	//-- tmpへindex読み込み
13b7203622 2011-02-23        kinaba: 
13b7203622 2011-02-23        kinaba: 		tmp[0] = cpt.getc();
13b7203622 2011-02-23        kinaba: 		if( tmp[0] & 0x80 )	folder = true,  size = (tmp[0]&0x3f) + 2;
13b7203622 2011-02-23        kinaba: 		else				folder = false, size = (tmp[0]) + 45;
13b7203622 2011-02-23        kinaba: 		if( size != cpt.read( tmp+1, size ) ) return false;
13b7203622 2011-02-23        kinaba: 		m_nIndexPos = cpt.tell(); // 次のIndexの位置を記憶
13b7203622 2011-02-23        kinaba: 
13b7203622 2011-02-23        kinaba: 	//-- ヘッダ解析
13b7203622 2011-02-23        kinaba: 
13b7203622 2011-02-23        kinaba: 		//   0: filename_len (BYTE)
13b7203622 2011-02-23        kinaba: 		// 1-n: filename     (with no '\0')
13b7203622 2011-02-23        kinaba: 		char filename[MAX_PATH];
13b7203622 2011-02-23        kinaba: 		ki_memcpy( filename, tmp+1, tmp[0] );
13b7203622 2011-02-23        kinaba: 		filename[ *tmp ] = '\0';
13b7203622 2011-02-23        kinaba: 		for( char* pp=filename; *pp; pp=kiStr::next(pp) )
13b7203622 2011-02-23        kinaba: 		{
13b7203622 2011-02-23        kinaba: 			if( kiStr::isLeadByte(*pp) )
13b7203622 2011-02-23        kinaba: 				continue;
13b7203622 2011-02-23        kinaba: 			if( *pp<' ' || *pp>'~' )
13b7203622 2011-02-23        kinaba: 				*pp = '_';
13b7203622 2011-02-23        kinaba: 			else switch( *pp )
13b7203622 2011-02-23        kinaba: 			{
13b7203622 2011-02-23        kinaba: 				case '\\': case '/': case ':': case '*':
13b7203622 2011-02-23        kinaba: 				case '?': case '\"': case '<': case '>': case '|':
13b7203622 2011-02-23        kinaba: 					*pp = '_';
13b7203622 2011-02-23        kinaba: 			}
13b7203622 2011-02-23        kinaba: 		}
13b7203622 2011-02-23        kinaba: 		// filenameが2個以上の.のみからなっていたら_に書き換え
13b7203622 2011-02-23        kinaba: 		{
13b7203622 2011-02-23        kinaba: 			int dots = 0;
13b7203622 2011-02-23        kinaba: 			char* pp;
13b7203622 2011-02-23        kinaba: 			for( pp=filename; *pp; pp=kiStr::next(pp) )
13b7203622 2011-02-23        kinaba: 				if( *pp == '.' ) { ++dots; }
13b7203622 2011-02-23        kinaba: 				else { dots=-1; break; }
13b7203622 2011-02-23        kinaba: 			if( dots >= 2 )
13b7203622 2011-02-23        kinaba: 				for( pp=filename; *pp; ++pp )
13b7203622 2011-02-23        kinaba: 					*pp = '_';
13b7203622 2011-02-23        kinaba: 		}
13b7203622 2011-02-23        kinaba: 
13b7203622 2011-02-23        kinaba: 	//-- ダイアログ処理
13b7203622 2011-02-23        kinaba: 
13b7203622 2011-02-23        kinaba: 		pthtmp = path, pthtmp += filename;
13b7203622 2011-02-23        kinaba: 
13b7203622 2011-02-23        kinaba: 		if( pdlg )
13b7203622 2011-02-23        kinaba: 		{
13b7203622 2011-02-23        kinaba: 			pdlg->change( pthtmp, base+i+1 );
13b7203622 2011-02-23        kinaba: 			if( !pdlg->msgloop() )
13b7203622 2011-02-23        kinaba: 				return false;
13b7203622 2011-02-23        kinaba: 		}
13b7203622 2011-02-23        kinaba: 
13b7203622 2011-02-23        kinaba: 	//-- フォルダ処理
13b7203622 2011-02-23        kinaba: 
13b7203622 2011-02-23        kinaba: 		if( folder )
13b7203622 2011-02-23        kinaba: 		{
13b7203622 2011-02-23        kinaba: 			unsigned long fldlen = (tmp[size-1]<<8) + tmp[size];
13b7203622 2011-02-23        kinaba: 			pthtmp += '\\';
13b7203622 2011-02-23        kinaba: 
13b7203622 2011-02-23        kinaba: 			if( o_list )
13b7203622 2011-02-23        kinaba: 			{
13b7203622 2011-02-23        kinaba: 				files->forcelen( base+i+1 );
13b7203622 2011-02-23        kinaba: 				ki_strcpy( (*files)[base+i].inf.szFileName, pthtmp );
13b7203622 2011-02-23        kinaba: 				(*files)[base+i].isfile = false;
13b7203622 2011-02-23        kinaba: 			}
13b7203622 2011-02-23        kinaba: 
13b7203622 2011-02-23        kinaba: 			if( !recurse( o_list, files, pthtmp, base+i+1, fldlen ) )
13b7203622 2011-02-23        kinaba: 				return false;
13b7203622 2011-02-23        kinaba: 			i += fldlen;
13b7203622 2011-02-23        kinaba: 		}
13b7203622 2011-02-23        kinaba: 
13b7203622 2011-02-23        kinaba: 	//-- ファイル処理
13b7203622 2011-02-23        kinaba: 
13b7203622 2011-02-23        kinaba: 		else
13b7203622 2011-02-23        kinaba: 		{
13b7203622 2011-02-23        kinaba: 			const unsigned char* hdr = tmp + (size+1) - 80;
13b7203622 2011-02-23        kinaba: 
13b7203622 2011-02-23        kinaba: 			unsigned long rsrcSkip; bool lzhFlag;
13b7203622 2011-02-23        kinaba: 			if( (hdr[68]<<24) + (hdr[69]<<16) + (hdr[70]<<8) + hdr[71] != 0 )
13b7203622 2011-02-23        kinaba: 			{
13b7203622 2011-02-23        kinaba: 				// もし dataForkが存在するならば
13b7203622 2011-02-23        kinaba: 				dataULen = (hdr[68]<<24) + (hdr[69]<<16) + (hdr[70]<<8) + hdr[71];
13b7203622 2011-02-23        kinaba: 				dataCLen = (hdr[76]<<24) + (hdr[77]<<16) + (hdr[78]<<8) + hdr[79];
13b7203622 2011-02-23        kinaba: 				rsrcSkip = (hdr[72]<<24) + (hdr[73]<<16) + (hdr[74]<<8) + hdr[75];
13b7203622 2011-02-23        kinaba: 				lzhFlag  = (hdr[63]&4) !=0;
13b7203622 2011-02-23        kinaba: 			}
13b7203622 2011-02-23        kinaba: 			else
13b7203622 2011-02-23        kinaba: 			{
13b7203622 2011-02-23        kinaba: 				// dataForkが存在しないならば
13b7203622 2011-02-23        kinaba: 				dataULen = (hdr[64]<<24) + (hdr[65]<<16) + (hdr[66]<<8) + hdr[67];
13b7203622 2011-02-23        kinaba: 				dataCLen = (hdr[72]<<24) + (hdr[73]<<16) + (hdr[74]<<8) + hdr[75];
13b7203622 2011-02-23        kinaba: 				rsrcSkip = 0;
13b7203622 2011-02-23        kinaba: 				lzhFlag  = (hdr[63]&2) !=0;
13b7203622 2011-02-23        kinaba: 			}
13b7203622 2011-02-23        kinaba: 
13b7203622 2011-02-23        kinaba: 			if( o_list ) // リストへ加える
13b7203622 2011-02-23        kinaba: 			{
13b7203622 2011-02-23        kinaba: 				files->forcelen( base+i+1 );
13b7203622 2011-02-23        kinaba: 				ki_strcpy( (*files)[base+i].inf.szFileName, pthtmp );
13b7203622 2011-02-23        kinaba: 				ki_strcpy( (*files)[base+i].inf.szMode, lzhFlag ? "rle+lzh" : "rle" );
13b7203622 2011-02-23        kinaba: 				(*files)[base+i].inf.dwCompressedSize = dataCLen;
13b7203622 2011-02-23        kinaba: 				(*files)[base+i].inf.dwOriginalSize = dataULen;
13b7203622 2011-02-23        kinaba: 				(*files)[base+i].isfile = true;
13b7203622 2011-02-23        kinaba: 			}
13b7203622 2011-02-23        kinaba: 			else if( !files || (*files)[base+i].selected )
13b7203622 2011-02-23        kinaba: 			{
13b7203622 2011-02-23        kinaba: 				if( !(hdr[63] & 1) )
13b7203622 2011-02-23        kinaba: 				{
13b7203622 2011-02-23        kinaba: 					pthtmp.mkdir();
13b7203622 2011-02-23        kinaba: 					cpt.seekTo( (hdr[36]<<24) + (hdr[37]<<16) + (hdr[38]<<8) + hdr[39] +
13b7203622 2011-02-23        kinaba: 								rsrcSkip + m_nMacBinOffset ); // filepos + rsrcCLen + (0 | 128)
13b7203622 2011-02-23        kinaba: 					if( out.open( pthtmp, false ) )
13b7203622 2011-02-23        kinaba: 					{
13b7203622 2011-02-23        kinaba: 						cptmelt( lzhFlag );
13b7203622 2011-02-23        kinaba: 						out.close();
13b7203622 2011-02-23        kinaba: 					}
13b7203622 2011-02-23        kinaba: 				}
13b7203622 2011-02-23        kinaba: 			}
13b7203622 2011-02-23        kinaba: 		}
13b7203622 2011-02-23        kinaba:     }
13b7203622 2011-02-23        kinaba: 
13b7203622 2011-02-23        kinaba: 	return true;
13b7203622 2011-02-23        kinaba: }
13b7203622 2011-02-23        kinaba: 
13b7203622 2011-02-23        kinaba: //-- 解凍処理 ------------------------------------------------
13b7203622 2011-02-23        kinaba: 
13b7203622 2011-02-23        kinaba: #define	ESC1		0x81
13b7203622 2011-02-23        kinaba: #define	ESC2		0x82
13b7203622 2011-02-23        kinaba: #define NONESEEN	0
13b7203622 2011-02-23        kinaba: #define ESC1SEEN	1
13b7203622 2011-02-23        kinaba: #define ESC2SEEN	2
13b7203622 2011-02-23        kinaba: 
13b7203622 2011-02-23        kinaba: void CArcCpt::cptmelt( bool isRL )
13b7203622 2011-02-23        kinaba: {
13b7203622 2011-02-23        kinaba: 	cpt_outstat = NONESEEN;
13b7203622 2011-02-23        kinaba: 	cpt_LZptr = 0;
13b7203622 2011-02-23        kinaba: 	cpt_blocksize = 0x1fff0;
13b7203622 2011-02-23        kinaba: 
13b7203622 2011-02-23        kinaba: 	if( isRL )
13b7203622 2011-02-23        kinaba: 		cpt_rle_lzh();
13b7203622 2011-02-23        kinaba: 	else
13b7203622 2011-02-23        kinaba: 		while( dataCLen-- )
13b7203622 2011-02-23        kinaba: 			cpt_outch( cpt.getc() );
13b7203622 2011-02-23        kinaba: }
13b7203622 2011-02-23        kinaba: 
13b7203622 2011-02-23        kinaba: void CArcCpt::cpt_outch(unsigned char ch)
13b7203622 2011-02-23        kinaba: {
13b7203622 2011-02-23        kinaba: 	cpt_LZbuff[ cpt_LZptr++ & (CIRCSIZE-1) ] = ch;
13b7203622 2011-02-23        kinaba: 
13b7203622 2011-02-23        kinaba: 	switch( cpt_outstat )
13b7203622 2011-02-23        kinaba: 	{
13b7203622 2011-02-23        kinaba: 	case NONESEEN:
13b7203622 2011-02-23        kinaba: 		if( ch==ESC1 )
13b7203622 2011-02-23        kinaba: 			cpt_outstat = ESC1SEEN;
13b7203622 2011-02-23        kinaba: 		else
13b7203622 2011-02-23        kinaba: 			dataULen--,out.putc( cpt_savechar=ch );
13b7203622 2011-02-23        kinaba: 		break;
13b7203622 2011-02-23        kinaba: 
13b7203622 2011-02-23        kinaba: 	case ESC1SEEN:
13b7203622 2011-02-23        kinaba: 		if( ch==ESC2 )
13b7203622 2011-02-23        kinaba: 			cpt_outstat = ESC2SEEN;
13b7203622 2011-02-23        kinaba: 		else
13b7203622 2011-02-23        kinaba: 		{
13b7203622 2011-02-23        kinaba: 			dataULen--,out.putc( cpt_savechar=ESC1 );
13b7203622 2011-02-23        kinaba: 			if( ch!=ESC1 )
13b7203622 2011-02-23        kinaba: 			{
13b7203622 2011-02-23        kinaba: 				cpt_outstat = NONESEEN;
13b7203622 2011-02-23        kinaba: 				dataULen--,out.putc( cpt_savechar=ch );
13b7203622 2011-02-23        kinaba: 			}
13b7203622 2011-02-23        kinaba: 		}
13b7203622 2011-02-23        kinaba: 		break;
13b7203622 2011-02-23        kinaba: 
13b7203622 2011-02-23        kinaba: 	case ESC2SEEN:
13b7203622 2011-02-23        kinaba: 		cpt_outstat = NONESEEN;
13b7203622 2011-02-23        kinaba: 		if( ch!=0 )
13b7203622 2011-02-23        kinaba: 			while( --ch )
13b7203622 2011-02-23        kinaba: 				dataULen--,out.putc(cpt_savechar);
13b7203622 2011-02-23        kinaba: 		else
13b7203622 2011-02-23        kinaba: 		{
13b7203622 2011-02-23        kinaba: 			dataULen--,out.putc( ESC1 );
13b7203622 2011-02-23        kinaba: 			dataULen--,out.putc( cpt_savechar=ESC2 );
13b7203622 2011-02-23        kinaba: 		}
13b7203622 2011-02-23        kinaba:     }
13b7203622 2011-02-23        kinaba: }
13b7203622 2011-02-23        kinaba: 
13b7203622 2011-02-23        kinaba: void CArcCpt::cpt_rle_lzh()
13b7203622 2011-02-23        kinaba: {
13b7203622 2011-02-23        kinaba: 	int block_count;
13b7203622 2011-02-23        kinaba: 	unsigned int bptr;
13b7203622 2011-02-23        kinaba: 	int Huffchar, LZlength, LZoffs;
13b7203622 2011-02-23        kinaba: 
13b7203622 2011-02-23        kinaba: 	cpt_LZbuff[CIRCSIZE - 3] = 0;
13b7203622 2011-02-23        kinaba: 	cpt_LZbuff[CIRCSIZE - 2] = 0;
13b7203622 2011-02-23        kinaba: 	cpt_LZbuff[CIRCSIZE - 1] = 0;
13b7203622 2011-02-23        kinaba: 	cpt_LZptr = 0;
13b7203622 2011-02-23        kinaba: 
13b7203622 2011-02-23        kinaba: 	while( dataULen!=0 )
13b7203622 2011-02-23        kinaba: 	{
13b7203622 2011-02-23        kinaba: 		cpt_readHuff(256,cpt_Hufftree);
13b7203622 2011-02-23        kinaba: 		cpt_readHuff( 64,cpt_LZlength);
13b7203622 2011-02-23        kinaba: 		cpt_readHuff(128,cpt_LZoffs  );
13b7203622 2011-02-23        kinaba: 		block_count = 0;
13b7203622 2011-02-23        kinaba: 		cpt_newbits = (cpt.getc()<<8);
13b7203622 2011-02-23        kinaba: 		cpt_newbits = cpt_newbits | cpt.getc();
13b7203622 2011-02-23        kinaba: 		cpt_newbits = cpt_newbits << 16;
13b7203622 2011-02-23        kinaba: 		cpt_bitsavail = 16;
13b7203622 2011-02-23        kinaba: 		while( block_count<cpt_blocksize && dataULen!=0 )
13b7203622 2011-02-23        kinaba: 		{
13b7203622 2011-02-23        kinaba: 			if( cpt_getbit() )
13b7203622 2011-02-23        kinaba: 			{
13b7203622 2011-02-23        kinaba: 				Huffchar = gethuffbyte(cpt_Hufftree);
13b7203622 2011-02-23        kinaba: 				cpt_outch((unsigned char)Huffchar);
13b7203622 2011-02-23        kinaba: 				block_count += 2;
13b7203622 2011-02-23        kinaba: 			}
13b7203622 2011-02-23        kinaba: 			else
13b7203622 2011-02-23        kinaba: 			{
13b7203622 2011-02-23        kinaba: 				LZlength = gethuffbyte(cpt_LZlength);
13b7203622 2011-02-23        kinaba: 				LZoffs = gethuffbyte(cpt_LZoffs);
13b7203622 2011-02-23        kinaba: 				LZoffs = (LZoffs << 6) | cpt_get6bits();
13b7203622 2011-02-23        kinaba: 				bptr = cpt_LZptr - LZoffs;
13b7203622 2011-02-23        kinaba: 				while( LZlength-->0 )
13b7203622 2011-02-23        kinaba: 					cpt_outch(cpt_LZbuff[bptr++&(CIRCSIZE-1)]);
13b7203622 2011-02-23        kinaba: 				block_count += 3;
13b7203622 2011-02-23        kinaba: 			}
13b7203622 2011-02-23        kinaba: 		}
13b7203622 2011-02-23        kinaba: 	}
13b7203622 2011-02-23        kinaba: }
13b7203622 2011-02-23        kinaba: 
13b7203622 2011-02-23        kinaba: int CArcCpt::gethuffbyte(node* l_nodelist)
13b7203622 2011-02-23        kinaba: {
13b7203622 2011-02-23        kinaba: 	register node *np;
13b7203622 2011-02-23        kinaba: 	np = l_nodelist;
13b7203622 2011-02-23        kinaba: 	while(np->flag == 0)
13b7203622 2011-02-23        kinaba: 		np = cpt_getbit() ? np->one : np->zero;
13b7203622 2011-02-23        kinaba: 	return np->byte;
13b7203622 2011-02-23        kinaba: }
13b7203622 2011-02-23        kinaba: 
13b7203622 2011-02-23        kinaba: void CArcCpt::cpt_readHuff(int size,node* Hufftree)
13b7203622 2011-02-23        kinaba: {
13b7203622 2011-02-23        kinaba: 	sf_entry tree_entry[256 + SLACK];
13b7203622 2011-02-23        kinaba: 	int tree_entries;
13b7203622 2011-02-23        kinaba: 	int tree_MaxLength;
13b7203622 2011-02-23        kinaba: 	int treeBytes, i, len;
13b7203622 2011-02-23        kinaba: 	sf_entry *ejm1;
13b7203622 2011-02-23        kinaba: 	int j;
13b7203622 2011-02-23        kinaba: 	sf_entry *entry;
13b7203622 2011-02-23        kinaba:     sf_entry tmp;
13b7203622 2011-02-23        kinaba:     int entries;
13b7203622 2011-02-23        kinaba:     unsigned a, b;
13b7203622 2011-02-23        kinaba: 	int codelen, lvlstart, next, parents;
13b7203622 2011-02-23        kinaba: 	int tree_count[32];
13b7203622 2011-02-23        kinaba: 
13b7203622 2011-02-23        kinaba: 	treeBytes = cpt.getc();
13b7203622 2011-02-23        kinaba: 	if( size<treeBytes*2 )
13b7203622 2011-02-23        kinaba: 		return;
13b7203622 2011-02-23        kinaba: 	for( i=0; i!=32; i++ )
13b7203622 2011-02-23        kinaba: 		tree_count[i] = 0;
13b7203622 2011-02-23        kinaba: 	i = 0;
13b7203622 2011-02-23        kinaba: 	tree_MaxLength = 0;
13b7203622 2011-02-23        kinaba: 	tree_entries = 0;
13b7203622 2011-02-23        kinaba: 	while( treeBytes-->0 )
13b7203622 2011-02-23        kinaba: 	{
13b7203622 2011-02-23        kinaba: 		int c=cpt.getc();
13b7203622 2011-02-23        kinaba: 		len = c >> 4;
13b7203622 2011-02-23        kinaba: 
13b7203622 2011-02-23        kinaba: 		if(len != 0)
13b7203622 2011-02-23        kinaba: 		{
13b7203622 2011-02-23        kinaba: 			if(len > tree_MaxLength)
13b7203622 2011-02-23        kinaba: 				tree_MaxLength = len;
13b7203622 2011-02-23        kinaba: 			tree_count[len]++;
13b7203622 2011-02-23        kinaba: 			tree_entry[tree_entries].Value = i;
13b7203622 2011-02-23        kinaba: 			tree_entry[tree_entries++].BitLength = len;
13b7203622 2011-02-23        kinaba: 		}
13b7203622 2011-02-23        kinaba: 		i++;
13b7203622 2011-02-23        kinaba: 		len = c & 0x0f;
13b7203622 2011-02-23        kinaba: 		if(len != 0)
13b7203622 2011-02-23        kinaba: 		{
13b7203622 2011-02-23        kinaba: 			if(len > tree_MaxLength)
13b7203622 2011-02-23        kinaba: 				tree_MaxLength = len;
13b7203622 2011-02-23        kinaba: 			tree_count[len]++;
13b7203622 2011-02-23        kinaba: 			tree_entry[tree_entries].Value = i;
13b7203622 2011-02-23        kinaba: 			tree_entry[tree_entries++].BitLength = len;
13b7203622 2011-02-23        kinaba: 		}
13b7203622 2011-02-23        kinaba: 		i++;
13b7203622 2011-02-23        kinaba: 	}
13b7203622 2011-02-23        kinaba: 
13b7203622 2011-02-23        kinaba: 	j = 0;
13b7203622 2011-02-23        kinaba:     for( i=0; i<=tree_MaxLength; i++ )
13b7203622 2011-02-23        kinaba: 		j = (j << 1) + tree_count[i];
13b7203622 2011-02-23        kinaba: 	j = (1 <<tree_MaxLength) - j;
13b7203622 2011-02-23        kinaba: 	for( i=0; i<j; i++ )
13b7203622 2011-02-23        kinaba: 	{
13b7203622 2011-02-23        kinaba: 		tree_entry[tree_entries].Value = size;
13b7203622 2011-02-23        kinaba: 		tree_entry[tree_entries++].BitLength = tree_MaxLength;
13b7203622 2011-02-23        kinaba: 	}
13b7203622 2011-02-23        kinaba: 
13b7203622 2011-02-23        kinaba: 	entry = &(tree_entry[0]);
13b7203622 2011-02-23        kinaba: 	entries = tree_entries;
13b7203622 2011-02-23        kinaba:     for( i=0; ++i<entries; )
13b7203622 2011-02-23        kinaba: 	{
13b7203622 2011-02-23        kinaba: 		tmp = entry[i];
13b7203622 2011-02-23        kinaba: 		b = tmp.BitLength;
13b7203622 2011-02-23        kinaba: 		j = i;
13b7203622 2011-02-23        kinaba: 		while((j > 0) && ((a = (ejm1 = &(entry[j - 1]))->BitLength) >= b))
13b7203622 2011-02-23        kinaba: 		{
13b7203622 2011-02-23        kinaba: 			if((a == b) && (ejm1->Value <= tmp.Value))
13b7203622 2011-02-23        kinaba: 				break;
13b7203622 2011-02-23        kinaba: 			*(ejm1 + 1) = *ejm1;
13b7203622 2011-02-23        kinaba: 			--j;
13b7203622 2011-02-23        kinaba: 		}
13b7203622 2011-02-23        kinaba: 		entry[j] = tmp;
13b7203622 2011-02-23        kinaba: 	}
13b7203622 2011-02-23        kinaba: 
13b7203622 2011-02-23        kinaba:     i = tree_entries - 1;
13b7203622 2011-02-23        kinaba:     lvlstart = next = size * 2 + SLACK - 1;
13b7203622 2011-02-23        kinaba:     for(codelen = tree_MaxLength; codelen >= 1; --codelen)
13b7203622 2011-02-23        kinaba: 	{
13b7203622 2011-02-23        kinaba: 		while((i >= 0) && (tree_entry[i].BitLength == codelen))
13b7203622 2011-02-23        kinaba: 		{
13b7203622 2011-02-23        kinaba: 			Hufftree[next].byte = tree_entry[i].Value;
13b7203622 2011-02-23        kinaba: 			Hufftree[next].flag = 1;
13b7203622 2011-02-23        kinaba: 			next--;
13b7203622 2011-02-23        kinaba: 			i--;
13b7203622 2011-02-23        kinaba: 		}
13b7203622 2011-02-23        kinaba: 		parents = next;
13b7203622 2011-02-23        kinaba: 		if(codelen > 1)
13b7203622 2011-02-23        kinaba: 		{
13b7203622 2011-02-23        kinaba: 			for(j = lvlstart; j > parents + 1; j-= 2)
13b7203622 2011-02-23        kinaba: 			{
13b7203622 2011-02-23        kinaba: 				Hufftree[next].one = &(Hufftree[j]);
13b7203622 2011-02-23        kinaba: 				Hufftree[next].zero = &(Hufftree[j - 1]);
13b7203622 2011-02-23        kinaba: 				Hufftree[next].flag = 0;
13b7203622 2011-02-23        kinaba: 				next--;
13b7203622 2011-02-23        kinaba: 			}
13b7203622 2011-02-23        kinaba: 		}
13b7203622 2011-02-23        kinaba: 		lvlstart = parents;
13b7203622 2011-02-23        kinaba: 	}
13b7203622 2011-02-23        kinaba: 	Hufftree[0].one = &(Hufftree[next + 2]);
13b7203622 2011-02-23        kinaba: 	Hufftree[0].zero = &(Hufftree[next + 1]);
13b7203622 2011-02-23        kinaba: 	Hufftree[0].flag = 0;
13b7203622 2011-02-23        kinaba: }
13b7203622 2011-02-23        kinaba: 
13b7203622 2011-02-23        kinaba: int CArcCpt::cpt_get6bits()
13b7203622 2011-02-23        kinaba: {
13b7203622 2011-02-23        kinaba: 	int cn,b=(cpt_newbits >> 26) & 0x3f;
13b7203622 2011-02-23        kinaba: 	cpt_bitsavail -= 6;
13b7203622 2011-02-23        kinaba: 	cpt_newbits <<= 6;
13b7203622 2011-02-23        kinaba: 	if(cpt_bitsavail < 16)
13b7203622 2011-02-23        kinaba: 	{
13b7203622 2011-02-23        kinaba: 		cn = (cpt.getc() << 8);
13b7203622 2011-02-23        kinaba: 		cn |= cpt.getc();
13b7203622 2011-02-23        kinaba: 		cpt_newbits |= (cn << (16 - cpt_bitsavail));
13b7203622 2011-02-23        kinaba: 		cpt_bitsavail += 16;
13b7203622 2011-02-23        kinaba: 	}
13b7203622 2011-02-23        kinaba: 	return b;
13b7203622 2011-02-23        kinaba: }
13b7203622 2011-02-23        kinaba: 
13b7203622 2011-02-23        kinaba: int CArcCpt::cpt_getbit()
13b7203622 2011-02-23        kinaba: {
13b7203622 2011-02-23        kinaba: 	int b = (cpt_newbits >> 31) & 1;
13b7203622 2011-02-23        kinaba: 	cpt_bitsavail--;
13b7203622 2011-02-23        kinaba: 	if( cpt_bitsavail<16 )
13b7203622 2011-02-23        kinaba: 	{
13b7203622 2011-02-23        kinaba: 		cpt_newbits |= (cpt.getc() << 8);
13b7203622 2011-02-23        kinaba: 		cpt_newbits |= cpt.getc();
13b7203622 2011-02-23        kinaba: 		cpt_bitsavail += 16;
13b7203622 2011-02-23        kinaba: 	}
13b7203622 2011-02-23        kinaba: 	cpt_newbits <<= 1;
13b7203622 2011-02-23        kinaba: 	return b;
13b7203622 2011-02-23        kinaba: }