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: }