気まぐれな戯れ言 バックナンバー3


気まぐれな戯れ言バックナンバーです。全体の一覧はこちら

00/08/24 2倍拡大編
00/08/20 STGと加算半透明編
00/07/16 クロックアップ編
00/06/21 さらなる新天地?編
00/05/26 新天地キツイね編
00/05/12 クオータニオン編
00/04/26 自己技術診断編
00/04/16 第2種情報処理技術者試験編
00/04/03 CD再生編
00/03/06 フォントからBMP機能追加編
00/03/05 フォントからBMP+周波数編

00/08/24 2倍拡大編[★★★◎◎◎]
SS版怒首領蜂をプレイ・・・うーん、難しい。
アーケードモード難易度ノーマルで1周目で2コンティニュー・・・・。
やはり14インチで横画面プレイは辛い。
その後サターンモード難易度VERY EASYで1周。
1周で蜂に会えるんですねぇ、初回火蜂でノーミス・ノーボム・・・
こりゃいかん。さしあたってアーケードノーマルを1コインクリア目指します。

んで、本題。
以前からMicro Warの拡大をもっとちゃんとしたいと思ってたんだよね。
うちの環境だとStrechBlt使用で20FPSしかでないし。
いざとなったらDirectDrawで320x240で出来るよう別モードも作ろうかなと思うほどに。
(あんまり気が進まないんだけどね。メニューとか使えなくなるし。)

どうもうちのハードは拡大が弱い。
いや、DirectDrawにしても、StretchBltにしてもね。
んで、この際なんでサクッと拡大ルーチンを組んでみようと考える。
以前ミニデモ用に作ったVB・C共通で使えるDIBSectionルーチンがあるのでそれを利用。

んで、やり方。
VB側で256色のDIBSectionを作成。それをDLLに放り込み、2倍化してBitBlt。
っていうかそれだけ。

さしあたって安易にCで組んだけど35FPSしか出ない・・・
こりゃマズイということでアセンブラを使用することに。
次のコードで大体45FPSでました。
っていうかK-6/2 400MHzで45FPSって言うのはマズイよなぁ・・・
っていうか普通もっとハードウェア拡大が速いんじゃない?
さしあたってコード。
void WINAPI DIBSecDouble(DIBSec* Dest,DIBSec* Src){
    //8bitDIB拡大コード
    int a,b;
    byte* db,*sb;
    int w,h,l;

    if(Dest->Width != 2*Src->Width) return;
    if(Dest->Height != 2*Src->Height) return;
    if(Dest->BPP !=8) return;
    if(Src->BPP !=8) return;
    db=(byte*)Dest->hMem;
    sb=(byte*)Src->hMem;
    w=Src->Width;
    h=Dest->Height;
    l=Src->LineLength;

    __asm{
        mov eax,db
        mov ebx,sb
        mov ecx,0
        mov b,0

xyloop: mov dl,[ebx]
        mov dh,dl
        mov [eax],dx
        inc ebx 
        add eax,2
        inc ecx
        cmp ecx,w
        jb  xyloop
        inc b
        mov ecx,b
        and ecx,1
        cmp ecx,1
        jne endsub
        mov ecx,0
        sub ebx,l
endsub: mov edx,b
        cmp edx,h
        jb xyloop
    }
}
うーん。
もっと速く出来ないかなぁ・・・と。
んで、MMX利用を試みる。
そういやぁパック・アンパック系命令が使えないかなぁと考える。
これだと一気に8ピクセル行けるしね。
しかし・・・55FPS。
パック・アンパックって意外と遅いね。
もっと70FPSグらい出て欲しかったんだけど。
んで、コード。
void WINAPI DIBSecDoubleMMX(DIBSec* Dest,DIBSec* Src){
    //8bitDIB拡大コードMMX版
    int a,b;
    byte* db,*sb;
    int w,h,l;

    if(Dest->Width != 2*Src->Width) return;
    if(Dest->Height != 2*Src->Height) return;
    if(Dest->BPP !=8) return;
    if(Src->BPP !=8) return;
    db=(byte*)Dest->hMem;
    sb=(byte*)Src->hMem;
    w=Src->Width;
    h=Dest->Height;
    l=Src->LineLength;

    __asm{
            mov     edx,0
            mov     eax,sb
            mov     ebx,db
            mov     ecx,0
xyloop:     movq    mm0,[eax]
            movq    mm1,mm0
            movq    mm2,mm0
            punpcklbw  mm1,mm0
            punpckhbw  mm2,mm0
            add   eax,8
            add   ecx,8
            movq  [ebx],mm1
            add   ebx,8
            movq  [ebx],mm2
            add   ebx,8
            cmp   ecx,w
            jb    xyloop
            inc edx
            mov ecx,edx
            and ecx,1
            cmp ecx,1
            jne endsub
            sub eax,l
endsub:     mov ecx,0
            cmp edx,h
            jb xyloop
            emms
    }
}

しかし拡大したらしたで画像が粗くてよくないね。
多少狭くても拡大無しぐらいの方がいいのかも。
とにかく本体を完成させなきゃ意味ないな。
弾幕系予定の2の構想をしてもしょうがあるまい。

00/08/20 STGと加算半透明編[★★★◎◎◎]
長かった2週間以上の関西への遠征、そして3日間の合宿を終え、ようやく落ち着きました。
怒首領蜂のSS版を手に入れたので今度学校の部室でやります(^^;)
(いや、やってみたかったけどこれまで見たことなかったのね)

んで、加算・減算半透明。

まずは普通のフェード処理。
これはあるBBSで話題になっていたのでチャレンジ。
要は指定したメモリブロックに一定の値を片っ端から加算・減算するのね。
もちろんVBでやると640*480でも20FPSとかしか出なかったような気が。
もちろん8Bitであれば、パレット操作で速度的には非常に簡単に出来るんだけどね。
16Bitや24Bitではそう行かないと。
16Bitの操作は面倒なのでさしあたって24Bitでチャレンジ。
ってコード自体は簡単なんだけどね。
さしあたってこんな感じ。
//2サーフェス間フェードイン・アウト-MMXアセンブラ
extern "C" VOID WINAPI DIBFadeMMX(byte* DSur,int DPitch,byte* SSur,int SPitch,int LB,int HB,int Fade)
{
    int a;
    byte fval,fv[8],*pfv;
    bool fsgn;

    if(Fade >=0){fval=min(255,Fade);fsgn=TRUE;}
    else{fval=min(255,-Fade);fsgn=FALSE;}

    for(a=0;a<8;a++) fv[a]=fval;
    pfv=&fv[0];

    _asm
    {
        mov a,0
        ;ループ開始
        mov eax,pfv
        movq MM1,[eax]
yloop:  mov ecx,0
        ;ポインタ計算
        ;Destラインスタート位置 ebx= DSur + DPitch*edx
        ;Srcラインスタート位置  eax= SSur + SPitch*edx
        mov eax,DPitch
        mul a
        mov ebx,eax
        add ebx,DSur
        mov eax,SPitch
        mul a
        add eax,SSur
xloop:  movq MM0,[eax]
        cmp fsgn,TRUE
        jne subval
        paddusb MM0,MM1
        jmp putval
subval: psubusb MM0,MM1
        ;置く
putval: movq [ebx],MM0
        add ecx,8
        cmp ecx,LB
        jae ychk
        add eax,8
        add ebx,8
        jmp xloop
ychk:   inc a
        mov edx,a
        cmp edx,HB
        jb yloop
        emms
    }

}

一応1サーフェスのみでのフェードも作ったけどね。
んで、テスト。
DirectDrawでは640*480で約60FPS。(←リフレッシュレートかも)
なぜかDIBでは36FPS(^^;)
↑24BitDIBで640*480だからねぇ・・・画面への描画が厳しいのかも。
操作不能画面で良ければ結構使えるレベルかもね。


んで、今度は普通の加算・減算半透明。
実は50%αブレンドからビットシフト処理と透明色処理を除けば(透明色部分にしたければ0にすればいいし)出来るのでコードそのものは速攻で出来た。
(最初引き算の順番を逆にして変な風になったが(^^;))

以前の様に320*240のウインドウに32*32の画像でチャレンジ。
300個の描画時で102FPS。
まぁ実際300個も半透明で書く事はしないからいいかも。
ちなみにこんな感じ。
//8bit、24bit加算ブレンド-MMXアセンブラ
extern "C" VOID WINAPI DIBAddBltMMX(byte* DSur,int DPitch,byte* SSur,int SPitch,int LB,int HB)
{
    int a;
    
    //a-y座標
    //ecx-x座標
    _asm
    {
        mov a,0
        ;ループ開始
yloop:  mov ecx,0
        ;ポインタ計算
        ;Destラインスタート位置 ebx= DSur + DPitch*a
        ;Srcラインスタート位置  eax= SSur + SPitch*a
        mov eax,DPitch
        mul a
        mov ebx,eax
        add ebx,DSur
        mov eax,SPitch
        mul a
        add eax,SSur
xloop:  movq MM0,[eax]
        movq MM1,[ebx]
        paddusb MM1,MM0
        ;置く
        movq [ebx],MM1
        
        ;終了、次のループへ
        add ecx,8
        cmp ecx,LB
        jae ychk
        add eax,8
        add ebx,8
        jmp xloop
ychk:   inc a
        mov ecx,HB
        cmp a,ecx
        jb yloop
        emms
    }
}

あ、減算はpaddusbをpsubusb(←わかりにく・・・)にするだけね。
そろそろ色計算系から座標変換系に移ろうかな・・・回転描画とか。

00/07/16 クロックアップ編
たまにはハードも扱ってみよう。
またも思いつきでクロックアップにチャレンジすることにした。(最近思いつきで動きすぎ)
もっとも、暑い時期には厳しいとは思うが。

最近欲しいと思うハード。
優先順位高−メモリ、CD-R、SCSIボード、HDD。
優先順位中−CPU、グラフィックボード。
優先順位はともかくその気になれば買える−スクロールボタンつきマウス、マウスパッド。
優先順位はともかく宝の持ち腐れ間違い無し−音源、スキャナ、デジカメ、タブレット、キーボード(いや、音楽の。作曲できないけどやってみたい気もある。まぁ撃墜率99%だろうけど)。

んで、CD-R、SCSIボードなんて買わない限りどうしようもない。
メモリ、HDDは余分なものを消すとか、圧縮とか、ラムなんちゃらとかで多少はどうにかなるが、どの道いずれ足りなくなっていく。
その点、CPUは「遅い」と感じる様にはなっても、「足りない」とは感じないだろう。
遅ければ遅いだけ。
逆に1割速度がアップするとすれば、パソコン生活が1割アップする(^^;)わけだ。
まぁK-6/2 500MHzでも一万円足らずで買えるんだけどさ。
実際周波数が増えるとどのぐらい速くなるかってのを体験したいじゃん。
350MHzが500MHzになって実際に約1.5倍速くなるんならいいけどさ。(ま、実際メモリとかそこらへんのことさえなければ純粋に1.5倍ぐらいなるだろうけどね)

んで、2ヶ月ぶりにNiftyを使ってFIBMJ Forumに入り、そことIBM Americaのホームページで情報を得る。
をを、さすがIBMなフォーラム。
幸いAptiva 243のクロックアップではないもののCPU付け替えの記事があった。
ふむふむ。
一応CPUがベースクロック*倍率で動くのは知ってたけど、それって何処で設定するのか知らなかったんだよね。
マザーボードなんだかわかんないし。
そこでIBM America。
さすがに本家(?)だけあり、マザーボードの種類も書いてあれば、クロック設定のジャンパピンの設置もちゃんと書いてある。
パソコンのマニュアルにもこのぐらい突っ込んだ情報を書いて欲しいよな。
ちなみにマザーボードそのものにもベースクロックとかの設定については小さな文字で書いてあったが。(目が疲れる・・・)

どうも一般的には2割増ぐらいまでは行けるっぽいので(Celeronとかはかなりスゴイらしいけどね)さしあたって100*3.5=350となっていたのを100*4=400にチャレンジすることにした。
一応95*4=380という選択肢もあったが、ベースクロックが100であるものをムリに95で動かすのもどうかと思って。
(っつーか400で動けばその方がいいし)
んで、本体を開けてスイッチを見てみる。
あ、ホントにスイッチなんだね(ハードには無知なんで)HDDのマスター・スレーブみたく変なのをつけたり外したりしないといけないのかと思ってたよ。
んで、サクっと3.5から4に変更。(この間5分)

起動時BIOSで確認。
おお!400MHzと出てる!5分でこれはいいのか?
と思ったら。。。
Win98起動時にブルーバック3連発。
さらにその後Win98起動画面の前に文字化け状態でscandiskっぽい画面が・・・

やはり無謀だったか、95*4にするしかないな(っていうか100*3.5に戻すべきだとも思ったが)と思いつつ、最後の賭けと言うことで電圧調整にチャレンジ。
デフォルトで2.2Vだったけど、「電圧を上げると熱くなるけどクロックアップが成功しやすい」と言うことで2.3Vにした。
んで起動!

をを!エラーが起きない!
さっそくベンチマークだ!
HDBENCHを起動・・・
さすがにグラフィックやHDDにはそれほど効果が出てないものの、整数演算、浮動小数点演算ともに約2割アップ!(^^)
をを、30FPSのデモが35FPSで動く!500FPSだったMicro Warのタイトルが630FPS(もう無茶苦茶だな。目指すは1000FPS?)もでる!
たった15分でこれはいいのか?
さぁ、みんなもチャレンジしよう(^^;)
失敗しても責任取れないけど。

さしあたって問題点は無いです。
95*4.5=428MHzでもチャレンジしてみようかなぁ・・・

今度メモリを買いに行こうと思うが・・・
128MBのメモリを買うのと、64MBのメモリ+K-6/2 550MHzを買うのはどっちがいいだろ?
いや、メモリスロットが2つしかないから64MBを足してもまだ不足と言う時はヤバイし。

結局128MBのメモリを買った。
うーむ、以前16MB→48MBの時ほど感動が無いなぁ・・・
K-6/2 500MHzの方がよかったか?

00/06/21 さらなる新天地?編[★★◎◎]
なんとなくpLaTeXに手を出そうかなと考える。(メチャクチャ思いつき)

やっぱりWordの数式エディタだと積分記号とかやるときは面倒だし、やはり専門に入ったらTeXは必要らしいということで。
ただ・・・。
本なんか買う余裕はない。

そもそもUnix向けであるTeXはフリーのはずだ、少なくともソフトは手に入る、わからなかったら本を買おう。
と言うことで探してDL。

合計35MBほどしたけど、なかなかサーバーが快適で良かった。
いや、大学のUnixにも入ってるけどさ。

ところでLaTeXってなんて読みます?
ラテックかラテフらしいけどね。
一応自分ははラテフ派です。
ラテックスはなんか嫌だなぁ。

んで、HPを2・30分ほど見て基礎を学ぶ。
まぁRTFとHTMLの中間みたいな?(^^;)

細かいレイアウトとかはわからないが、さしあたって数式が見たいだけなのだ!(^^;)
んで、どうやら1年次の情報処理の教科書に少しだけだがLaTeXを扱ってるページが。
これで基本はわかったな(^^;)

んで、数学の教科書の数式を打ちこんでみる。
\int_0^1x^2dx=\frac{1}{3}とか\overrightarrow{F(x)}=maとか。
おお、数式エディタより速い。

ただ。
dviってWinだとそのまま見られないのかなぁ?
ってdvioutとかいうソフトもあるじゃん。

しかしよくわからんマクロが多すぎ。
やっぱリファレンス本買うべきか?


んで、次SQL。Structerd Query Language。
いや、Perlから利用するんでPostgreSQLとか言うやつなんだけどさ。
mySQLとか言うのが人気でてるらしいね。

Perlは2次元配列が原則的に使えないからテーブルのデータを配列で受け取ることができないんだよね。
しかもgetValueしたものは直じゃなくてprintfでないと取り出せないし。
いや、$dat->getValue(1,1)とかすると$datだけポインタの数値(?)に置き換わっちゃうし。
しかし・・・
Selectもたらたらつながるとわかりづら。
さりげなく2種の知識が役立ってるな。
しかし・・・INNER JOIN使えないのか?


んで、今度はAccess。
クエリーはSQLで書いたほうがラクだ。
いや、先にPostgreSQLやったからなんだけどさ。
だから日本語版Accessなのにフィールドとかはアルファベットにしてある(^^;)
リレーションシップがよくわからん。

「テーブルAにあるIDに対応する文字列をID−文字列対応表のテーブルBから取り出す」って場合selectごりごりじゃなくてinner join使うんだね。
PostgreSQLはouter joinしか使えないしな。
しかし左結合とか右結合って役に立つんかな・・・

コントロール名を日本語にするのやめて欲しいな。
VBAでコード書きづらい。
しかし・・・
VBAでSQLを呼び出すコードを書こうとしたけど・・・うまくいかない。
どうやらテーブル名、フィールド名を[ ]で囲まないと行けないのね。
どういう言う時に囲ってどういうときに囲まないのかわからん。

なんか眠くて支離滅裂だな。

00/05/26 新天地キツイね編[★★◎◎]
アルバイト始めました。
いや、PerlでCGI作成なんだけどさ。
時間がかなり融通利く上になれればほとんど自宅でOKというもの。

ただ、自分は知ってのとおり(?)Perlなんぞほとんど経験が無いから苦労中。(ってまだ1つしか作ってないが)
なんせPerlの基本を知らないからねぇ。
VBになれちゃうとスペルチェックや引数リストが当たり前に思えてきて辛い。
っていうかほぼすべての命令を網羅したリファレンスが欲しい。
以前買った本はちょっと細かいところが載ってないし・・・。
「あ、これmap関数使うとラクだよ」とかあったし。
Content-type: text/htmlのところをLocation: うんちゃらにすると他のページに飛べるなんて知らなかったよ。
大学ではsendmailが使えなかったからよく使い方わからなかったし。
nkf通さなかったら文字化けしたし。

一応「既存のライブラリを使ってもいいけど、できれば自分で中身のわかってるものを作成した方がいいかも」と言われたのでそうしてる。
まだフォームのパース(って俗にそういう関数名つけるのはなぜ?いや、FORM連想配列に全部放り込むヤツね。)と、テンプレート表示(完了時にHTMLファイルをいれるとそれを表示してくれるやつ)しか作ってない。

次回はクッキー関連とかも作ってみるかな。


んで、大学の計算機プログラミングIIの授業。教官が「出席取らないしページ見られるなら家からでもいいよ」とか言うし、朝いちなので家でテレホ時に見た。
今年からJavaメインなのね。
幸いテストなしでレポートだけなんだけど・・・
レポートの提出方式がメールとかではなく講義用ネットニュースグループへの投稿。当然他人の提出ネタがわかる。
まぁ期限より早めに出すと教官が律儀にコメントを書いてくれるんだけどね。

前回の課題では「リストを使ったプログラム」をつくれとのことだったので「井の頭線駅名⇔値段リストプログラム」とかいうのをサクッと作ったんだけど。
Vectorクラスを授業で使ってたからそれを使うのはいいんだけど、IndexOfの内部動作が良くわからん。equalsで比較?うーむ。結局線形探索(単に端から順に調べるだけだが)でやった。結局クラスにequalsメソッドを置いておけば良かったらしいけどね。
いや、javaは構造体が使えないから一応Vectorクラスを2つ置いてやってしまったのだ。
いや、構造体のためだけにクラスを作ると.classファイルも増えてメンドウでしょ?

んで、次の課題。
「木の構造を用いたプログラムを作れ」
Javaなんで、ポインタを直接扱うことが出来ないから木の構造がちょっとやりづらいかなと。
メンドウなんで構造体とかそこらへんは使わないことにして、再帰関数を利用したファイル探索ルーチンを作成。
いや、指定したディレクトリ以下のファイルを列挙するのね。
ファイル名をいれると一応そのファイル名と一致する物だけを取り出して暮れるけど。
ワイルドカードが使いたかったけど使い方がわからなかった。
ここらへんはPerlの方が柔軟っていうか機能ありすぎ。
っていうかFileクラスの構造がわかりにくいぞ。
getAbsoluteメソッドで絶対パスを得られると思ったら得られなかったし。
結局、探索関数にフルパスでディレクトリ名をいれるハメになってしまった。

まぁできたからいいや。

上のリストのプログラムでは、ニュースを見るとかなり力の入ってる人がいたんだよね。
スレッドメッセージがどうとか。
構文解析をやってた人もいたけどそれって木の構造のやるべきだったな。
まぁ大半の人はIndexOfを使った簡単な探索ルーチンとかだけどさ。

んで、ファイル列挙プログラムを投稿。
期限が2週間なんだけど、1週間で提出したら、、、1番乗りだった。
いや、どうでもいいんだけどさ。
ただ、木の構造を表すようなクラスとかは作ってないけどいいのかなぁ・・・
まぁいずれにしても初心者にはキツイ内容だよね。
そろそろ脱落者もでるだろうな(2回目のレポートにして)

余談。
3Dやりたいね。
ひとまず直線をDDAで描画だけはした。
っていうか「だけ」。
テクスチャ付きポリゴンぐらいやれば出来ると思うけど。
光源処理とかはメンドウだなぁ・・・

まぁバイトが17:00〜22:00なんでプログラムをやる時間がかなり制限されてます。
さすがにインターネット常駐しながらアセンブラとか扱うプログラムは避けたいしなぁ・・・
音を使うやつはモデムと同時使用だと不安定だし。


そうそう、日本語でVB7の宣伝が出始めたね。
マルチスレッドが作りやすくなるのはいいかも。
ただゲーム作成にどれほど役立つかは謎だけど(^^;)
所詮ネットワーク用の機能のつもりなんだろうけど>MS

あと、Try-Catch-Finallyはいいかな。
いや、エラー時にファイルを閉じるって言うコードが以外とメンドウなのだ。
いつもOn Error Goto の後のラベル名のネタに困るし(^^;)

あとなんだっけ?Inheritによるクラスの継承だっけ?
個人的にはクラスの使用は余りしてないのでどうでもいいかもしれないけど。
ただオーバーライドが出来るのはいいな。

ランタイムがWin2K同梱の汎用ライブラリに吸収されるとか言ううわさを聞いたがそれはどうなんだか。
まぁVBユーザーは多いし、そのうち普及するだろうけどね。
むしろDirectX7 for VBで作ったゲームが非プログラマ系ユーザーでのDX7普及率がわからない分どれだけ広められるか不安だぞ。
Win98でも平気でDirectX5というパターンも多いしね。
まぁDX5ならDrawPrimitiveが使えるからD3DIM使うなら必要だが。
いや、ExecuteBufferは勘弁(^^;)

っていうかいい加減ポインタを扱わせてくれ。

00/05/12 クオータニオン編[★★◎◎◎]
注:今回三角関数ごりごりでやったけど実は四元数でやればあっさりというオチです。

なんか以前からソフトウェアレンダリングとか挑戦して見たかったんだよね。
いや、どちらかと言えばレイトレーシングとかみたく正確さや再現性で勝負するんじゃなくてデモとかゲームで使える速さ重視のね。

んで、高校時代に行列の知識がないながらもテキトーなワイヤーフレームエンジン(っていうかあれって陰線処理とかすらやってないし。それにファイル形式が・・・ねぇ。一応自分のとこにはポリゴンで辺を指定するタイプのものを作ったので(かなり高速化されたけど)そのうちVB講座に公開するけどさ)を作ったことはあるので、あとはワイヤーフレームからちゃんとしたシェーディングにすると(ってそんな甘いものか?)まともなエンジンになるかと(?)

んで、その一環として手始めに。
今まで良くわからなかったクオータニオンについて。
英語でquaternionでDirectX3、DirectX5 SDK日本語版ではそのままクオータニオンと表現されてたけど、DirectX7では4元数と表されてました。
要はなにをするものかというと、「任意のベクトルを軸として回転させる処理」と言うこと。

実際数学的には複素数をさらにややこしくしたような四元数ということが必要な んだけど、回転がしたいだけならOKかと。

たとえば3Dの飛行機ゲームを作るとする。
左ボタンや右ボタンを押したら常に今向いてる方向から左に旋回、右に旋回しないと行けないわけでしょ?
ところが、通常行列で簡単に表されるのはXYZの各軸での回転のみ。
まぁ前のワイヤーフレームエンジンでもある程度は2回回転計算を行うことでごまかしてたけど、応用性を考えればしっかりとクオータニオンを行列であらわしておいた方がいいかと。

んで、考え方。
回転軸をなんとかXYZ軸のどれかに移す演算を回転するべき点にも施し、その軸の周りで回転させて逆演算で元の位置に戻すと。
んで、今回は取った手段はこんな感じ。
回転軸をXY平面に射影した時、その軸がX軸となす角をθとする(地球で言う経度)
んで、XY平面と回転軸がなす角をφとする(同じく緯度)
ただ、今回は左手系でやってるので一応注意ね。
あと回転はいずれも左回りが正と。
DirectXは時計回りが正らしいしなぁ・・・
2次元なら普通左回りが正なんだろうけど、3次元だと外積とか右ねじがらみのこともあるし、右回りが正の方がいいのかなぁ・・・意見求む。

んで、次の順序で行う。
回転軸をZ軸で−θ回転させてXZ平面上に持っていく。
さらにY軸で−φ回転させてX軸に移す。 こうすれば回転軸がX軸に一致すると。
これを回転したい座標に同様に演算を行えばいいでしょ?
ちなみに、Z軸での回転とY軸での回転は順番逆には出来ないよ。
いや、考えてみればわかるけど、しょっぱなから回転軸がXYZのどれにもならないから。

んで。
X軸で必要な分回転させる。
Y軸でφ回転。
Z軸でθ回転。
これでOKと。

行列で書けば、Z軸でθ回転する行列をP、Y軸でφ回転する行列をQ、X軸で回転させる行列をR、逆行列をInvで表せば・・・
行列は右のものから順にベクトルにかかっていくことを考慮すると。。。
PQRInvQInvPと。
(いや、P,Qは回転する行列だから、逆行列は逆方向に回転する行列でしょ?実際掛ければ単位行列になるし。)

ちなみに、左手系であることに注意すると、φは次の様に計算される。
φ=ATan( Sqr(x^2 + y^2) , -z )
-zと負になってしまう。
ちなみに、VBのATanでは引数を1つしか取らないから注意ね。
CとかJavaだとちゃんと2引数で計算してくれるATan2っていう関数があるけど。

んで、具体的な行列表示。
と行きたいけどメンドウだからやめる。
(Z軸でθ回転)(Y軸でφ回転)(X軸で必要な分回転)(Y軸で−φ回転)(Z軸で−θ回転)と。
おのおのの回転は探せばあるでしょ(をい)


・・・ん?
某BBS曰く、「DirectX7SDKのd3dframe\d3dutil.cppにそれ系の関数があるよ」と。
んで、見てみる。
VOID D3DUtil_SetRotationMatrix( D3DMATRIX& mat, D3DVECTOR& vDir, FLOAT fRads )
{
    FLOAT     fCos = cosf( fRads );
    FLOAT     fSin = sinf( fRads );
    D3DVECTOR v    = Normalize( vDir );

    mat._11 = ( v.x * v.x ) * ( 1.0f - fCos ) + fCos;
    mat._12 = ( v.x * v.y ) * ( 1.0f - fCos ) - (v.z * fSin);
    mat._13 = ( v.x * v.z ) * ( 1.0f - fCos ) + (v.y * fSin);

    mat._21 = ( v.y * v.x ) * ( 1.0f - fCos ) + (v.z * fSin);
    mat._22 = ( v.y * v.y ) * ( 1.0f - fCos ) + fCos ;
    mat._23 = ( v.y * v.z ) * ( 1.0f - fCos ) - (v.x * fSin);

    mat._31 = ( v.z * v.x ) * ( 1.0f - fCos ) - (v.y * fSin);
    mat._32 = ( v.z * v.y ) * ( 1.0f - fCos ) + (v.x * fSin);
    mat._33 = ( v.z * v.z ) * ( 1.0f - fCos ) + fCos;

    mat._14 = mat._24 = mat._34 = 0.0f;
    mat._41 = mat._42 = mat._43 = 0.0f;
    mat._44 = 1.0f;
}
・・・・。
一番下の方を見ると4*4行列だけど結局3*3行列で書けそう・・・。
ここまでのの努力(ってほどでもないが)って一体・・・
別ページで四元数についてみると、中身はともかく最終系は上と同じような形。
すっきり過ぎるぞ・・・

あとパースペクティブ コレクトがよくわからないんだよねぇ・・・
素直に線形補間するしかないのか・・・?
いや、1ピクセルごとに割り算したらフォンシェーディングとかわらないじゃん。

00/04/26 自己技術診断編
本サイトも開設して3年になりました。
約7万件のアクセスもあり、こちらとしては非常にうれしいです。

ただ、最近非常に欲求不満な部分があります。
なぜかと言うと・・・最近(パソコン以外においても)新しいものに挑戦する気力がかなり薄れているので。
最近やった新しい分野といえば・・・2種の勉強だけか。

なんか以前のようにDirectXやアセンブラに色々挑戦する気力が起きないんですよね。
やりたい事というかできるようになりたいことは色々あるんですが・・・
まずしょっぱなは3D関連でしょうか。
D3DIMでも自前描画でもいいから最低限ポリゴンにテクスチャを貼れる程度のことはしたいと思うんだけど(これはその気になればソレほど時間はかからないだろうけど)
今はそれほど厳密なレイトレーシングには興味はないです。
むしろ速度重視で何処までやれるかというのが。
まぁライティング・マテリアル・フォグぐらいのものはともかくとして・・・
拡散反射光・ラジオシティ・拡散レイトレーシングなんてワケワカなものはまずやらないでしょう。

他には・・・もっとシステムに突っ込んだプログラムとか。
考えればマルチスレッドすらやったことがないんで。
(ってJavaだとThreadクラスであっさりできるんだけど。)

アルゴリズム面ではゲーム作りの分野ではSLGの戦術処理とか。
数式の解析処理とか。

んで、現在やっているプログラム関連といえば・・・
部活用にリーグ戦の表や日程表をHTMLで出力するプログラムと・・・
Micro Warぐらいか。

どちらもプログラム技術の難易度としては慣れていれば高くはないね。
なんか進歩がない。

せっかく今学期は授業が非常に少ない(先学期の2/3ぐらい)し色々やりたいんだけどね。

んで、自分のプログラミング技術解析。
<VB>
−出来ること−
基本的なコントロールの操作。
簡単な文字列操作。
最低限ゲーム作成に必要な絵・音・BGM等の処理。

−出来ないこと−
ネットワーク・データベース関連。
システム系APIでの処理。
3Dおよび文字列解析。

<C> −出来ること−
単純なVBレベルでのプログラム作成。
普通のAPI型DLL作成。

−出来ないこと−
そもそもランタイムの機能をほとんど知らない。
クラスの構成・名称・活用法を全く知らない。
ヘッダーファイルなどの構成も知らない。
I/O関連・ドライバ関連も無知。

<その他> −出来ること−
アセンブラでちょっとした画像処理。
Javaで最低限のアプレット。

−出来ないこと−
アセンブラの大半の命令の活用法およびアルゴリズム。
Javaの言語セットの大半は知らない。


はぁ・・・。
出来ないことが多すぎる。
まだまだ上級者への道は遠いです。
まだ初心者か初級者を抜けるかどうかぐらいなんだろうな。
少なくとも仕事に使えるレベルではないですね。

00/04/16 第2種情報処理技術者試験編
第2種情報処理技術者試験を受けました。
場所は東京ビッグサイト(東京国際展示場)でした。
・・・遠いぞ。東京の反対側だし。
有楽町線で新木場へ。
新木場で臨海副都心線に乗り換えると・・・
(しかしなんで2駅で\230円?>臨海副都心線)
なんか電車の中は2種の本を読んでる人が結構いました。
チラっと目に入ったのだけで5人以上。

んで、東京ビッグサイト。
うーむ、デカい。
数万人単位で人が来るような施設だしな。
ちなみにその一部で試験をやるんだけど・・・
見た感じ2種が6700人、初級シスアドが2500人いるっぽいです。

さすがにキレイな施設だねぇと思って席につく。
受験生が100人の部屋だった。
別のホールでは300人とかだったんだけど、個人的に少ない方が落ち着くので吉。
さらに後ろの席の方がいいんだけど、後ろから2番目だった。
考えれば入試の席順とかは恵まれてたな・・・。
センター試験→一番後ろ
私大その1→後ろから2列目
私大その2→いや、デカイ教室だけど後ろから1/4ぐらい
国立前期→一番後ろ

やはり後ろの席だと周りの席の動向が見えて落ち着きます>いや、カンニングとかするわけでもないが。

・・・。
・・・・。
・・・・・・・・・。
電卓忘れた(^^;)

まぁともかく試験開始。
センター試験を受けてただけあってマークシート自体にはかなり慣れてるので一気に飛ばす。
1巡目45分。
いや、計算問題はかなり適当なんだけど。
っていうか定率法での償却なんちゃら計算。
0.361だかを何回も掛ける計算。
手でやると面倒だ・・・。

まぁその後見なおししたら10個近く訂正入ったけどさ。

しかし意外と途中退室する人が多い。
合格率が2割を切ると言うことならそれほど自信のある人間は少ないはずだが・・・
んで、午後に突入。

しょっぱなの部屋探索はいいとして・・・
アルゴリズム第2問。
うおお、これって白黒DIBじゃん( ̄ー ̄)
ここらへんの処理はDIBSectionで経験済みなのでさっさと解答。

んで、選択問題。
しょっぱなのマルチプログラミングの問題は「タイムスライス」「ラウンドロビン」の意味がよくわからなかったので避ける。
んで、英単語の問題に入る。
うーむ、2分探索法か・・・まぁどうにかやる。

んで、オブジェクト表現のわけわからん問題。
一応やるも自信がなかったので避ける。
んで、ハフマン符号圧縮の問題。
計算が面倒ながらも問題的にやりやすかったのでやる。
ああ、電卓があればこの問題は半分の時間でできたのに。

んで、プログラム。
一応Cを見ると。。。
あ、アナログ時計描画?(^^;)
アセンブラを見ると異常にメンドくさそうに見えたので、C選択(^^;)

んでもう一問。
一応Cを見ると・・・
筆算風乗算?これもVBでやったことある(^^;)
ただ、符号処理や小数点が面倒だったのでアセンブラへ。
おお、過去問よりラクだということで選択。

ラスト。マイコン設計を選ぶ。
実はこの分野は問題集をやってないんだけど・・・
CASLでかなりどうにかなる分野ではあるんでやることにした。
いや、他のが異様にめんどうに見えたんで。


んで、自宅について自己採点・・・
いや、インターネットで色々見つかるのね。
午前は問題数も多いし1問あたりの配点も低いので1つのページしかチェックしてないけど・・・
いちおう70/80=88%でした。
午後。
問4・14が解答によってばらつきが・・・
一応幅をみると85〜92というところでしょうか。
一応問題集をみると145点で多分大丈夫とあったのでどうにかなるかと。

一応(一応が多いな)使った参考書を。

第2種情報処理技術者試験 直前整理特大号 12春−午前(技術評論社)
願書付きなのがうれしい。
基本的にこれで勉強しました。
午前の過去問が2回分あります。
残念ながら過去問は解答だけで解説は載ってないのね。
2種を受けるきっかけになった本。
試験会場でも3人ほど見かけた本です。

2000年版2種情報 実戦問題(オーム社出版局)
値段の割に厚いです。
まぁ他の本で勉強して問題だけ解いていけば、一気に終わります。
問題といいつつ解説がかなり多いです。
午後も含め過去問が1回分ついてます。
なかなかいいかもね。(ただ、マイコン設計は扱ってないです)

新カリキュラム対応 第2種情報処理完全合格教本「午後」(新星出版社)
午後用の本。
ただ、アルゴリズムは結構多くが自分はVB等で作成経験済みだったり、ネットワーク・データベースも上の本の少し詳しい版だというぐらいでした。
内部設計・プログラム設計は上の午前の本に比べるとだいぶ詳しかったんですが、過去問をやってからマイコン設計で行くことを決めたのでソレほど役に立ちませんでした。(プログラム・マイコン設計は載ってない)
プログラム未経験者だったら流れ図が豊富なのでいいかも。

午後の勉強はあまりしてません。
午前の応用である程度はどうにかなるので。
アルゴリズムは実際にプログラムを組んだことのある人ならかなりいけるでしょう。
CASLは特に勉強せずです。(上の実戦問題の本の問題を7問ほどやったけど)
だって問題のほうにCASLのアセンブラの仕様が書いてあるし(^^;)
Intel系アセンブラに比べればまだスマートかと。

しかし午後はやったことのあるプログラムが結構でたな。
DIB操作もどき、アナログ時計、人間風乗算・・・

結果は6月だそうです。

00/04/03 CD再生編[★★◎◎]
なんか最近VN(ビジュアルノベル)系ゲームをやったのね。
いや、どちらかと言えばアクションとかシューティングとか見たく直接的に実力が現れるゲームの方が好きなんだけどさ。

んで、ふと思った。
「そういやCDの再生方法って知らないよなぁ」
んで、GameToolsのモジュールの1つとしても使えるかなと思って、調べることに。
って言ってもこの類はmciSendStringでいいことはわかってるんだけどさ。
まぁいいやということで、
Call mciSendString("play cdaudio from 3 to 5","",0,0)
とでもすればできるだろうと思ったが・・・
うーむ。
再生はされたが・・・
トラック3〜5が再生されているとは思えない。
っていうか思いっきり曲の途中から聞こえる(^^;)

んで、オンラインで手に入れたプログラムのサンプルから"mciSendString"を総チェックしたら・・・
ほとんどmidi関連だったんだけど、1つだけCD関連がヒット。
かのelライブラリだった。

んで、内容をチェック。
どうやら音データ自体は1つに並んでいるとして、各トラックの開始位置を元にして
Call mciSendString("play cdaudio from 00:00:00 to 00:00:00","",0,0)
の形で再生するだけらしいね。
んで、"status cdaudio length track"+CStr(i)とか"status cdaudio position track"+CStr(i)でトラックの開始位置のテーブルを作成して、演奏に成功。

んで、次は一時停止の実装。
elライブラリでは、なぜか現在位置を取得して演奏を止め、演奏を再開するときにはその位置から普通に"play cdaudio"してた。
ただ、持ってる古いWin32APIヘルプ(どちらかと言うとWin95より初期のNTのなのでWin95のインターフェイスとかのようなAPIは載ってない)を見ると・・・
CDオーディオはpauseとresumeのコマンドも使えるとか書いてあるじゃん。
んで、試してみる。
あり?
pauseはうまく行くんだけど、resumeがうまく行かない。
んで、調べてみると返り値が274。
ってことは・・・APIビューアーで定数の項を見てみると・・・
MCIERR_UNSUPPORTED_FUCTION = (MCIERR_BASE + 18)
・・・。
サポートされてないってか。

んで、elと同じ方法で実装。
ひとまず最低限の機能を実装。

ってなわけでGameToolsの一部として今回アップロードすることにしました。
でも今後ビジュアルノベルのプログラムなんて作らなそうだな。
コレ系のプログラムはフリーウェアでも色々出てるし。
相当プログラムでないと書けないエフェクトが欲しかったりしない限りはね。

しかし今回は比較的レベルの低い(いや、下のアセンブラとかのヘビーな話題に比べるとさ)事を書いたな。
ゲーム作成においてはかなり必須(音の再生という意味ではね。そりゃsndPlaySoundより難しいよ。)な事項だしね。
あと3D関連ができれば最低限のゲームの知識がつくんだがなぁ(ってシミュレーションとかの得点評価とかのアルゴリズム関連はわかんないけど(ってどうでもいいけど括弧が多いな。))

00/03/06 フォントからBMP機能追加編[★★★◎◎◎]
んで、昨日のやつに機能追加。
影および縁取り。

まずは影から。
これは簡単。
位置をずらして2つ描画するだけ。
ただ、上になるフォントが1色ならそれでいいんだけど、上のフォントがテクスチャ付きの画像だとそうもいかない。
よって次のようにすることでどうにかやった。
(別の方法はいろいろあるけどね。白地に黒で字を書いてマスクにしてスプライト処理をするとか)
PictureBox1は上の文字を書き、テクスチャを貼る。(一応やり方を書いておくと、白で文字を書いて絵柄をSRCANDで重ねるだけ)
PictureBox2は下の文字を書いた後、上の文字を黒(背景色)で書くことで影の差分を作成。
SRCPAINTでOR結合になるようにBitBltする。
これでOK。

しかしここらへん変数の再定義とか、数値の再計算が面倒なため、別関数にせず一つに突っ込んでしまったので異常にやりづらい。

んで、縁取り。
これが結構難問。
今回はDIBSectionを利用することにした。
いや、すべてのピクセルにおいて半径数ピクセルの部分をすべてチェックするから、GetPixel・SetPixelなんてやってられないしね。

んで、手順。
上の字を書く。
DIBSectionにコピー。
(あとの作業はあまりここで使った変数を利用する必要が無いため、別関数にした)

まずアンチエイリアスを消す。
(通常フォントを描画するとアンチエイリエスがかかる場合がある。縁取りをすると薄くなった部分の周りに縁取りするのはカッコ悪いのでそれを解除する。ただ黒でない部分をすべて文字の描画色にするだけだけど。ちなみに、通常のBMP生成モードだとアンチエイリアスがかかった状態でテクスチャが貼られてしまうが、中心部より明るくなることは無いしそれほど重要でもないだろう。)
んで、各ピクセル(ただし、文字の色でないピクセル)に対し、半径数ピクセル分(これはユーザーに指定させる)の内部に文字の色があれば縁になるとする。
ちなみに、円形にチェックするので、横幅(っていうかスキャンライン)は毎回CosやSin、Sqrで計算するより、テーブルにしておくべきでしょう。
この場合縁取り幅は10までにしてあるし。
(当然縁取り幅の2乗で処理速度がかかるしね)

アルゴリズムはこれでいいんだけどなぜかうまく行かない・・・
途中経過を描画させてもなにも描画しない・・・なぜ?


ん? そう言えばDIBSectionにBitBltしてもメモリデータを取り出してないじゃん(^^;)
最近C++でDIBSectionがらみやってるとDIBSectionのデータそのものにポインタが当たってるからそこらへん意識しなくていいだけど・・・
VBだと一応別にBYTEの配列を準備してあるしなぁ・・・
で、取りだし&送りルーチンを入れたら・・・
ふむ、うまく行った。
んで、こんな感じ。

(この画像はそのうち消します・・・いや、サイズの都合でね)
1色+影。Westminsterフォント。
(削除)

テクスチャ+縁取り。なんちゃら特太ゴシック。
(削除)

まあそのうちミニソフトで出すけど、今欲しいぜっていうゲーム作者の人とかは連絡を。
(ミニミニソフトで現在は公開しています)

00/03/05 フォントからBMP+周波数編[★★★◎◎]
今回は豪華2本だて(をい)

とあるところで話題になった、フォントからBMP作成の話。
ゲームを作るときはフォントを使ってTextOutやDrawTextするのもいいんだけど、DirectDrawを使ってるとGetDCしてCreateFontしてSelectObjectしてSetTextColorしてSetBkModeしてSetBkColorしてDrawTextしてSelectObjectしてDeleteObjectしてReleaseDCしてと非常に面倒な手順が必要なわけね。
(しかし本当に長いな)
速度的にもGetDCとかはあまり早くない(ちょっと使う程度ではFPSは60をきったりしないけど、他の処理に比べると遅い)ので、特にシューティングゲームなど、アルファベットと数字、あと少しの記号でいい場合、文字をBMPで用意することが結構あるのね。
(Micro Warでもそうだけど)

んで、当然プログラムを組むことを考えると等間隔で文字が並んでる方がいい。
横幅の小さいiやjも、大きなSやWも同じでなければならないと。
いや、等幅フォントを使えばいいんだけどさ。
まぁ非等幅フォントでも同じ大きさに出来るようにしてみたいなあと。

手順は簡単。
1文字ずつサイズを取得して真中に配置する。
ただ・・・VBの仕様に関する問題が次々と。

まず苦労したのが・・・コモンダイアログ。
OCXは避けたいので(いくらなんでもこのダイアログの普及率はランタイムとほぼ同じだろうけど)コードで書くことに。
コモンダイアログをラクに使うクラスとかあったけど、Pack for Winのどこにあったか忘れたし、最小限の仕様な訳だからあまりメソッドとか増やしてもしょうがない。
ということで自分で書くことに。
ファイル関連のダイアログは以前作ったものをもってくればよかったんだけど・・・
フォントとカラーはやったこと無いしな・・・
カラー選択は簡単に出来た。
なぜかフォントのダイアログが出ない・・・
なんでかと思ったら選択フォントをスクリーンフォントにするって言うフラグを立て忘れてた。
まぁこのフォントダイアログはLOGFONTを返してくれるから直にCreateFontDirectにもって行けていいんだよね。

ただこまるのが・・・
API名がChooseColorにChooseFont、それに渡す構造体の名前もCHOOSECOLORとCHOOSEFONT・・・
大文字小文字を分けるCならいいけど、VBだとダメだっていうのに(^^;)
ちょっと考えて欲しいなぁ・・・>M$
しょうがなく構造体名を少し略したけどさ。
まぁここらへんはいいほう。

んで、今度はフォントサイズ計算。
いや、入力された文字で一番大きなサイズを必要とする文字を計算するんだけどさ。
これはDrawTextにDT_CALCRECTフラグだけでいいんだけど。
(とはいえ、まったく余白が無くなるわけでもない)
これは以外と簡単にできたんで・・・

ちなみに、APIを見てるとGetTextExtentPoint32とかいう描画領域取得関数があってDrawTextとどっちにしようか迷ったんだけど・・・
なんか2バイト文字を入れてもGetTextExtentPoint32はうまく行かなかったんでやめた(^^;)
1バイト文字の結果は同じだったし。

んで。
よし、描画だ!と思ったんだけど・・・

わかりやすく20Ptぐらいのフォントで書くと・・・
あれ?
なぜか普通のMS-Pゴシック 9Ptになる。
ただ、フォントサイズ計算時にはちゃんと大きなフォントになる。
なぜ?
どこかでVB側に干渉されてるのか?
確かにCreateFontDirectしてSelectObjectしてもVBのプロパティでFontNameをみると変更されてない・・・
VB側でテーブルか何かで保持されてるらしい。
しょうがないんでDrawTextする直前に毎回SelectObjectしたらどうにかなった。

んで、次はテクスチャ実装。
これは基本的には黒地に白でフォントを書いておけば、後は絵柄をSRCANDでBitBltすればOKなんだけど・・・
1文字当たりのセルサイズ(とでも言えばいいのかな?)より絵のサイズが小さい場合が問題。
セルサイズが絵の整数倍ならいいんだけどそれ意外だとね。
クリッピングしてもいいんだけど。
一応別PictureBoxでクリッピングの手間を省こうかなと。
どっちにしても必要なのがLoadPictureした絵のサイズ取得。
んで、別PictureBoxにタイル状に描画してるんだけど・・・
うまく行かない・・・なぜか1つだけあるのみ。
なんでだろ?
BitBltでもPaintPictureでもRenderメソッドでも・・・
んで、Renderで気づいた。
「座標はミリメートル単位」
なぬぅ?
んで、Picture.Widthを見てみると(PictureBoxじゃなくてPictureオブジェクトのプロパティね)・・・
やはりミリメートル(^^;)
なんでんなもんをデフォルトで使うんだ>M$
と言うわけで、AutoResizeプロパティがTrueなのを利用してPictureBoxのWidth、Heightから計算。
かろうじてクリア。

んで、最後、保存。
これはSavePictureでいいかなぁと思ってたんだけど・・・
(いや、元BMPが256色だったら256色で出力したいなとも思ったけどひとまずいいかなぁと(手抜き))

しかぁし、甘かった(^^;)
いや、基本的にはいいんだけど・・・
いったんプレビューとかででかいPictureBoxにしてしまうと、一番デカイサイズの画像領域が確保されてしまうらしく、あとで小さい物にしてもSavePictureした時にでかいものが出来てしまうと。
しかもその領域にはでかい物を作ったときの画像の残骸が・・・
うーむ、これはPictureBoxのWidthやHeightを変えてもムダだし・・・
かといってPictureオブジェクトのWidthやHeightは直接書き換えは不可能(っていうかそもそもミリメートル単位だからやりづらいんだけどさ)

んで、無意味に(?)Indexプロパティを利用して保存時に動的にPictureBoxをロードし、保存し終わったらまたUnloadすることで、毎回保存したいサイズのPictureBoxを利用できると。
なんとかうまくいった・・・

いや、ここらへんはちょっと解決策が思い浮かばなくてねぇ・・・
以前のデモで使ったDIBSectionモジュールを使おうかなと思ったんだけど。

んで、ひとまず簡易的な物ができた。
ホントは影と縁取り機能をつけたかったんだけどね・・・
これをつけるとなるとやっぱりDIBSectionいるかもね。
影は何ピクセルか斜めにずらして描画すればいいんだけど・・・
縁取りがよくわからない・・・
半径何ピクセルかの部分に文字があれば色をつけるって言うのでいいのかな?
ただ、この場合「半径何ピクセル」ってのが、円でやるのか正方形でやるのかひし形(っていうか正方形が斜めになっただけかもしれないけど)

まぁ気が向いたらつくろ。


んで、もうひとつやったのは・・・CPUの周波数測定。
いや、なんとなくね。
アセンブラのRDTSC命令でタイムスタンプが得られるって言うんで。

せっかくなんで以前のデモスケルトンを利用。
初期化時にTextOutで描画しておけばいいと。

しかし、またCPUIDのごとくに・・・コンパイル不可能。
「newlineはアセンブラの構文エラー」だと。
だけど前回の経験を生かして(?)__emit擬似命令でどうにかする。

RDTSCは64bit数値を返す(EDX:EAXの形式ね)んでちょっと扱いづらいけど・・・
幸いVCには__int64とか言う64bit数値が扱えたんで。

時間差はtimeGetTimeでms単位で得ると・・・
RDTSCから得られるタイム差*1000/時間差で周波数が得られるんでMHzにするために1024*1024で割ればいいと。
んで、最初得られた数値*1000/時間差>>20にしてみる。
すると・・・
334MHz?
ありゃ?
と思い、M=2^20でなくM=10^6としてみる。
小数第2位まで得られるようにちょっとルーチンを加えると・・・
350.69MHz・・・まぁこんなもんか。
でもMをどっちに取るかで3%も違うのか・・・結構サギかも(をい)
んで、こんな感じ。

    __int64 a,b,*aa,*bb;
    // __int64 t;
    int i,j;
    double d;
    char ts[100];

    DIBSecCreate(&MainDIB,24,320,240,NULL);
    FillMemory(MainDIB.hMem,320*240*3,0xCF);
    aa=&a;
    bb=&b;
    i=timeGetTime();
    __asm{
        mov ebx,aa
        __emit 0x0F
        __emit 0x31
        mov [ebx],eax
        mov [ebx+4],edx
    }
    Sleep(3000);
    j=timeGetTime();
    __asm{
        mov ebx,bb
        __emit 0x0F
        __emit 0x31
        mov [ebx],eax
        mov [ebx+4],edx
    }
    d=(b-a)/(j-i);
    //K=1024、M=1024*1024の場合
    //っていうか普通ってK=1000、M=1000*1000だったのね
    //t=((b-a)*1000/(j-i))>>20;
    wsprintf(&ts[0],"%d.%d MHz\0",(int)d/1000,(int)(d/10)%100);
    TextOut(MainDIB.hdc,0,0,&ts[0],lstrlen(&ts[0]));
    wsprintf(&ts[0],"MMX - %d",(int)CheckMMX());
    TextOut(MainDIB.hdc,0,15,&ts[0],lstrlen(&ts[0]));

しかし文字列関連はさすがにVBの方がやりやすいね。
どこぞにありそうなStringクラスのソースを持ってくるとかMFCからCStringだけ持ってくるとかしたいかも。
でも数値→文字は結局sprintf系かな。
まぁいいや、ひとまず。


一覧へ戻る