// LZSS解凍ソフト // include --------- #include #include #include // define ---------- // 各型とバイト数の関係( 環境によって変わりますが・・・ ) // int : 4バイト(0〜4,294,967,295) // short : 2バイト(0〜65,535) // char : 1バイト(0〜255) // data type ------- // 圧縮データの情報構造体 struct LZSS_ENCODE_INFO { int OriginalSize ; // 圧縮前のデータのサイズ(バイト数) int PressSize ; // 圧縮後のデータのサイズ(この構造体のサイズも含む) int EncodeCode ; // 圧縮情報の開始を示す数値 } ; // proto type ------ // 圧縮データを解凍する // // 戻り値:解凍後のサイズ -1 はエラー Dest に NULL を入れると解凍データ格納に必要なサイズが返る int LZSS_Decode( void *Press, void *Dest ) ; // code ------------ // メイン関数 // argc:引数の数( 最初の1個は exe ファイルのパスなので0個になることはない ) // argv:引数の文字列配列へのポインタ( 最初の文字列は exe ファイルのパス文字列 ) int main( int argc, char **argv ) { void *buf, *dest_buf ; int size, dest_size ; // ソフトのタイトルを出力 printf( "LZSS Decode Soft\n\n" ) ; // ファイル名の指定がなかったらヘルプを表示 if( argc != 2 ) { printf( " LzssDecode.exe FilePath\n" ) ; return 0 ; } // ファイルを丸ごと読み込む { FILE *fp ; // ファイルを開く fp = fopen( argv[1], "rb" ) ; if( fp == NULL ) { printf( " File open Error!!\n" ) ; return 0 ; } // ファイルサイズを調べる { // ファイルポインタをファイルの末尾に fseek( fp, 0L, SEEK_END ) ; // ファイルの末尾で現在のファイルポインタアドレスを取得すればそれはファイルのサイズ size = ftell( fp ) ; // ファイルポインタをファイルの先頭に戻す fseek( fp, 0L, SEEK_SET ) ; } // ファイルを丸ごと読み込む為のメモリを確保する buf = malloc( size ) ; if( buf == NULL ) { printf( " Memory alloc Error!!\n" ) ; return 0 ; } // ファイルを丸ごと読み込む fread( buf, size, 1, fp ) ; // ファイルを閉じる fclose( fp ) ; } // 圧縮したデータを解凍する { // 解凍した時のデータのサイズを取得する dest_size = LZSS_Decode( buf, NULL ) ; // 解凍したデータを格納するためのメモリを確保する dest_buf = malloc( dest_size ) ; if( dest_buf == NULL ) { printf( " Memory alloc Error!!\n" ) ; return 0 ; } // 解凍したデータを確保したメモリ領域に保存する LZSS_Decode( buf, dest_buf ) ; // 圧縮データを解放する free( buf ) ; } // 解凍したデータをファイルに保存する { FILE *fp ; char FileName[256] ; // 拡張子を『dec』に変更して保存する { char *LastPeriod ; // 元のファイルのファイルパスをコピーする strcpy( FileName, argv[1] ) ; // 最後の『.』のアドレスを取得する LastPeriod = strrchr( FileName, '.' ) ; // ピリオドがなかった場合は拡張子が無いと判断して『.dec』を末尾に追加する if( LastPeriod == NULL ) { strcat( FileName, ".dec" ) ; } else { // あった場合はピリオドの後の文字列を『dec』にしてしまう strcpy( LastPeriod + 1, "dec" ) ; } } // 解凍データを保存するファイルを開く fp = fopen( FileName, "wb" ) ; // 解凍データを丸ごと書き込み fwrite( dest_buf, dest_size, 1, fp ) ; // ファイルを閉じる fclose( fp ) ; // 解凍データを解放する free( dest_buf ) ; } // 終了 return 0 ; } // 圧縮データを解凍する // // 戻り値:解凍後のサイズ -1 はエラー Dest に NULL を入れると解凍データ格納に必要なサイズが返る int LZSS_Decode( void *Press, void *Dest ) { int PressSize, PressSizeCounter, DestSizeCounter ; unsigned char *PressPoint, *DestPoint ; LZSS_ENCODE_INFO EncodeInfo ; // void 型のポインタではアドレスの操作が出来ないので unsigned char 型のポインタにする PressPoint = ( unsigned char * )Press ; DestPoint = ( unsigned char * )Dest ; // 圧縮データの情報を取得する memcpy( &EncodeInfo, Press, sizeof( LZSS_ENCODE_INFO ) ) ; // Dest が NULL の場合は 解凍後のデータのサイズを返す if( Dest == NULL ) return EncodeInfo.OriginalSize ; // 圧縮データ本体のサイズを取得する PressSize = EncodeInfo.PressSize - sizeof( LZSS_ENCODE_INFO ) ; // 解凍処理 { int Index, EqualNum ; unsigned char *PressData ; // 圧縮データ本体の先頭アドレスをセット // (圧縮データ本体は元のサイズ、圧縮後のサイズ、圧縮情報の開始を示す数値を // 格納するデータ領域の後にある) PressData = PressPoint + sizeof( LZSS_ENCODE_INFO ) ; // 解凍したデータを格納するアドレスの初期化 DestSizeCounter = 0 ; // 解凍する圧縮データの参照アドレスの初期化 PressSizeCounter = 0 ; // 全ての圧縮データを解凍するまでループ while( PressSizeCounter < PressSize ) { // 圧縮情報の開始を示す数値かどうかで処理を分岐 if( PressData[PressSizeCounter] == EncodeInfo.EncodeCode ) { PressSizeCounter ++ ; // 2バイト連続で圧縮情報の開始を示す数値だった場合、開始を示す // 数値そのものを示しているのでそのまま出力する if( PressData[PressSizeCounter] == EncodeInfo.EncodeCode ) { DestPoint[DestSizeCounter] = ( unsigned char )EncodeInfo.EncodeCode ; DestSizeCounter ++ ; PressSizeCounter ++ ; } else { // 普通に圧縮情報を示す数値だった場合 // 『何バイト前から?』の数値を得る { Index = PressData[PressSizeCounter] ; PressSizeCounter ++ ; // 『何バイト前から?』の数値が圧縮情報を示す数値より // 大きい値の場合は−1する(詳しくはエンコードプログラムを参照してください) if( Index > EncodeInfo.EncodeCode ) Index -- ; } // 『何バイト同じか?』の数値を得る EqualNum = PressData[PressSizeCounter] ; PressSizeCounter ++ ; // 指定のバイト数分だけ前のアドレスから、指定の // バイト数分だけコピー memcpy( &DestPoint[DestSizeCounter], &DestPoint[DestSizeCounter - Index], EqualNum ) ; DestSizeCounter += EqualNum ; } } else { // 普通に数値を出力 DestPoint[DestSizeCounter] = PressData[PressSizeCounter] ; DestSizeCounter ++ ; PressSizeCounter ++ ; } } } // 解凍後のサイズを返す return EncodeInfo.OriginalSize ; }