DxLib 小技3



DxLibFanに戻る


11.Windowモードでバッテンボタンを押してもプロセスが残らないようにする

#include "DxLib.h"


//DxLibのメッセージをフックする
long FAR PASCAL HookDxLibMessage( HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam ){
  switch(message){
    case WM_QUIT:
      exit(1);//注意:exitでもいいが、実は
      //http://www.tietew.jp/cppll/archive/7235 ようにしないと
      //C++のデストラクタは安全ではないらしい
      break;
    case WM_DESTROY:
      //終了する時はこれを呼び出してもらわなきゃ困る。
      PostQuitMessage(0);
      DxLib_End();
      
      break;
  }
  return 0;
}

int WINAPI WinMain( HINSTANCE hInstance, HINSTANCE hPrevInstance,
         LPSTR lpCmdLine, int nCmdShow )
{
  ChangeWindowMode(TRUE);//Window Mode
  SetDrawScreen(DX_SCREEN_BACK);//back buffer write mode

  
  if( DxLib_Init() == -1 )  // DXライブラリ初期化処理
  {
     return -1;// エラーが起きたら直ちに終了
  }
  //注意:DxLib_Initを呼んだ後でないと 登録されない。
  // メッセージをフックするウインドウプロージャを登録する
  SetHookWinProc( HookDxLibMessage ) ;

  int sx,sy,sb;
  GetScreenState(&sx,&sy,&sb);
  //内部は無限ループ。もちろんバッテンボタンを押さないと終了しない。
  for(;;){
    ProcessMessage();
    int color=GetColor(GetRand(255),GetRand(255),GetRand(255));
    //ClsDrawScreen();

    DrawBox(0,0,GetRand(sx),GetRand(sy),color,TRUE);

    ScreenFlip();
  }

  DxLib_End() ;        // DXライブラリ使用の終了処理

  return 0 ;          // ソフトの終了
}


説明:
DxLibの昔のバージョンでは Windowモードでバッテンボタンを押すと自動的にプロセスが残らないようにしていたらしいのですが、 最近になり、ユーザーが任意で終了させるようになりました。
これで終了時の処理等を書けるようになったわけで、私としては非常にうれしいです。
しかし、それを考慮しないでプログラムすると、 ユーザー側にとってはプロセスが残ってしまい、 一回終了させたのに、また起動できないじゃないか! という事態に陥ってしまうと思います。
それを考慮しないソフトが出来てしまうと、なんだかなぁ〜なので、 プロセスの残らないようにするサンプルが必要かな?と思った次第です。
注意
実際はProcessMessage()関数をループ内に入れておいて、-1が帰ったらループを抜けるというやり方が正道との 本家からの教を戴きました。
なので、あまり、私のやり方はDxLibに対してはsmartとは言えないようです。

2003/09/20 一部修正
2003/12/12 注意書き追加
2004/10/23 ソースコードの表示方法を変更

12.偽装化入門

概要:
ファイルの偽装化やパック化の質問が結構掲示板に書き込まれます。
フォルダをパッキングして、ロード時に展開したいというないようでした。
そこで、私は以下のような返信をしました。

フォルダをパッキングするのはあまり良い手法とは私的に言うといえません。 なぜなら、素材の更新,管理に手間取るからです。
また、パッキングしても一部で、それらの解析ツールがあったりするので、 隠蔽するには完全に個人的なファイルフォーマットになり 、他と互換性がなくなり、自分の行うプログラミング量が増えてしまいます。
私としては、そのような方法をとるのではなく、 ファイル自体の偽装化が一番有効だと思われます。
例えば、各リソースファイルのヘッダを偽装化してしまえば、 私はほぼ隠蔽できると考えてますが、 どうでしょうか? (もしかしたら、私の方法って良くない方法??どうか批評を御願いいたします。)

という事で、以下のようなサンプルをちと作ってみました。
(といいますか・・・dKingyoUtility2からのコピペですが・・・ヘッダ暗号化はこのために作りました。
ビットマップの偽装化、複合化Onlyですが 結構実用には耐えると思っていたりします。(私の考え方でいいのかなぁ?)
DxLibの掲示板に以下のようなソースがありましたが、私としては次のような問題が挙げられます。
// グラフィックの変換関数
int BMPtoGRP( char *FileName )
{
  void *FileImage ;
  FILE *fp ;
  int FileSize ;
  char FName[256] ;
  int i ;

  // ファイルを開く
  {
    // 拡張子の追加
    strcpy( FName, FileName ) ;
    strcat( FName, ".bmp" ) ;
    if( ( fp = fopen( FName, "rb" ) ) == NULL )
    return -1 ;
  }

  // ファイルのサイズを取得する
  fseek( fp, 0, SEEK_END ) ;
  FileSize = ftell( fp ) ;
  fseek( fp, 0, SEEK_SET ) ;

  // メモリの確保
  if( ( FileImage = malloc( FileSize ) ) == NULL )
  return -1 ;

  // ファイルの読みこみ
  fread( FileImage, FileSize, 1, fp ) ;

  // ファイルを閉じる
  fclose( fp ) ;

  // 書き出しファイルを開く
  {
    // 拡張子の追加
    strcpy( FName, FileName ) ;
    strcat( FName, ".GRP" ) ;
    if( ( fp = fopen( FName, "wb" ) ) == NULL )
    return -1 ;
  }

  // ファイルデータをNOT演算を掛ける
  {
    unsigned char *Image = ( unsigned char * )FileImage ;
    for( i = 0 ; i < FileSize ; i ++ )
    {
      //!d金魚の考察 @
      //ここがワンタイムパッドと変わらない。
      //実際、BMP画像は1MB越すこともざらなので、
      //1MBものメモリコピーが発生することは実用上問題ありだと思います。
      Image[i] = ~Image[i] ;
    }
  }

  // ファイルを書き出す
  fwrite( FileImage, FileSize, 1, fp ) ;

  // ファイルを閉じる
  fclose( fp ) ;
  free(FileImage);

  // 終了
  return 0 ;
}


// 偽装BMPファイルロード 
int GRPLoad( char *FileName )
{
  void *FileImage ;
  FILE *fp ;
  int FileSize ,i;
  int GHandle;
  char FName[256] ;

  // ファイルを開く
  {
    // 拡張子の追加
    strcpy( FName, FileName ) ;
    strcat( FName, ".GRP" ) ;
    if( ( fp = fopen( FName, "rb" ) ) == NULL )
    return -1 ;
  }

  // ファイルのサイズを取得する
  fseek( fp, 0, SEEK_END ) ;
  FileSize = ftell( fp ) ;
  fseek( fp, 0, SEEK_SET ) ;

  // メモリの確保
  if( ( FileImage = malloc( FileSize ) ) == NULL )
    return -1 ;

  // ファイルの読みこみ
  fread( FileImage, FileSize, 1, fp ) ;

  // ファイルを閉じる
  fclose( fp ) ;

  // グラフィックデータにNOT演算を掛けてもとのBMPデータに変換
  {
    unsigned char *Image = ( unsigned char * )FileImage ;
    for( i = 0 ; i < FileSize ; i ++ )
    {
      //@と同じ
      Image[i] = ~Image[i] ;
    }
  }

  // グラフィックを作成する
  GHandle = CreateGraphFromMem( FileImage, FileSize) ;
  free(FileImage);
  return GHandle;
}
問題点:
  1. 実際、BMP画像は1MB越すこともざらなので、 1MBものメモリコピーが発生することは実用上問題ありだと思います。
  2. ワンタイムパッド(といいますか、ワンタイムパッドは唯一絶対に破られない暗号化アルゴリズムらしいです。) と同じコピー量ながら、NOT演算なので、バイナリを解析されてしまうと、結構簡単に破られると思います。(私のヴァーナム暗号??っぽいものもバイナリを解析されると破られやすいそうですが・・・
やっぱり、二つ目はともかく、一つ目の問題は非常につらいでしょう。
なので、私はヘッダのみを書き変えることにしました。
すると書き換えするメモリの量は100Byte以内で済みます。
1MBの画像全部のメモリの書き換えと比較してみると、 私のほうは10000分の1の書き換えで済んでいます。
ということで、以下のソースを使うのはどうですか?
BSD Licenceです。面倒なので、BSDLか、NYSLで。
こちらにソースがあります。
説明:
え、処理の内容を説明しろ!?・・・
もう眠いので勘弁してください。○Oo。.(T¬T)/~~~ バーナム暗号?だと思います。
多分、バイナリを解析する人なら、すぐに解析されるけど、ツール仕込みの素人にはわからない・・・はず・・・
キーの隠し場所が課題だね。
ワンタイムパッドにすれば絶対大丈夫だと思うよ!?(一生複合化できないって・・・。
ちなみに、d金魚はこの暗号化を使うのですか?
理論上はまったく同じ(ストリーム暗号)ですが私は今のところ別にRewriteしたものを使っています。
あとは、各人で上記のソースをいじくり回して下さいよ(笑)
関連
ちなみに、暗号化基礎

2003/09/20 一部の文を訂正
2004/05/17 一部の文を訂正
2004/06/24 一部の文を訂正
2004/10/23 ソースコードを別ファイルに分離



13.Softwareモードで最速の設定

何故、Softwareモードにするかというと、トラブルがある人向けの環境にも対応させるためです。
しかし、ソフトウェアモードは遅いのですが、いろいろ設定をいじれば少し速くなるそうです。 で、以下のようにすれば最速になります。
DxLibで画像がうまく表示されない人 専用の環境設定です。
(DxLib Extension Library(またはDxLib Setup <- これは開発停止中)を使えば この画像のような(これは開発中の画像) ダイアログで設定できるようになります。
SetUse3DFlag( FALSE ) ;//3D機能を使用しない
SetUseVramFlag( TRUE ) ;//VRAMを使用する
SetBasicBlendFlag( TRUE );//ブレンドのクオリティを下げる。
DxLib_Init();//DxLibを初期化
SetDrawScreen(DX_SCREEN_BACK);//描画先をバックバッファに指定

/*
どうしても遅い場合だけ
コメントアウトを外してください。
(しかし、これを外すと環境によっては動かない場合もあるので注意)
*/
//SetWaitVSyncFlag(FALSE);


2004/10/31:SetWaitVSyncFlag()を付けた。


14.圧縮入門 (メッチャしょぼいけど

概要:
圧縮ってどうしてますか?
UNLHA32やUNZIP32とか使ってますか?
それらは、圧縮効率は良いですが、展開速度としてはゲームに使うのであればちと、難でしょう。
なので、ここでは連長圧縮(Run Length Compress)の方がいいかな〜(実際、速度は遅いのですが・・・)
こんばんは コラム
2.85MBの画像をこのクラスで操作したら、以下のような感じでした。
単位:msec (CPU:Athlon 2000 XP)
圧縮:time = 50
解凍:time = 40

ん〜〜。ちと遅いかな?このCPUでこんなスコアでは・・・
yaneSDK3rdにはLZSS法による圧縮ルーチン。があるそうです。
これを使うしかないような気も・・・

追記:2004/05/17
dkutil_cライブラリにLZSS圧縮機構をつけました。 BSD Licenceです。どうぞ
追記:2004/10/23
dkutil_cライブラリにRLE (PackBits形式) 圧縮機構をつけました。BSD Licenceです。 もうすぐで発表されるdkutil 0.20に収録されると思います。
追記:2005/02/07
http://d.hatena.ne.jp/studiokingyo/20041224#p2
にNYSLのRLE (PackBits形式) 圧縮機構を掲載しました。

とまぁ、作ってみましたので、バリバリコピペしてください。(以下のソースはBSD Licenceです。
詳しい処理の概要を知りたい方はこんな感じで調べてください。

関連,参考資料:
処理の速度比較とか(製作中
Kojif Homepage 圧縮研究所
DO++ block sorting
奥村晴彦氏のHP
データ圧縮のリンク集
M.Hiroi’s Home Page
圧縮基礎 (DxLib Fan 内)







2004/05/17 注意:圧縮効率に多少問題あり・・・^^;


更新履歴:
2004/06/24 一部の文章を変更,追記


DxLibFanに戻る DxLibのダウンロードは以下から
Dxライブラリ置き場
DxLib Copyright(C) 山田 巧

The program using DxLib.
The text of this page.
SEO [PR] 爆速!無料ブログ 無料ホームページ開設 無料ライブ放送