月別アーカイブ: 2007年10月

EMOBILE EM・ONE (S01SH) の α化

WindowsMobile6 へのアップグレードのためメーカー送りになっていた
EM・ONE が届きました。予想よりもずっと早い仕上がりでした。

EMOBILE EM・ONE WindowsMobile6 アップグレード申し込み
ZERO3[es] に 小型 Bluetooth アダプタ PTM-UBT3S をつないでみた

5日の申し込みで11日の発送なので、実質8日間で戻ってきたことになります。
最初に電話した申込日から数えてちょうど2週間です。
外側は一緒なのに、中身が変わっただけでなんとなく新機種を購入した
気分です。

変更点は WindowsMobile6.0 へのアップグレードです。
結果として EM・ONE α (S01SH2) 相当となり、S01SH2 のマニュアルや
CD-ROM も付属していました。

ぱっと見てわかるメニューの違いは下記のとおり。

● Today 画面
・JAJAH のリンク
  IP 電話です。
  プリインストールではなく、タッチすることでアプリのダウンロード
  &インストールが行われます。

●設定画面
・S01SH情報
  S01SHバージョン: 2.00

・External GPS
・Windows Update
・暗号化

●プログラム
・3D Box ダウンロード (URLのショートカット)
・Messenger
・Sprite Backup
・Windows Live
・名刺リーダ
・リモートデスクトップモバイル

おそらく Advanced W-ZERO3[es] WS011SH とほぼ同じだと思われます。
これで WindowsMobile6 でのプログラムの動作確認がしやすくなりました。
imekeyset5 の対応もできそうです。

64bit 環境へ移行

昨日の「64bit 開発設定のメモ」
Executable files: に DXSDK の bin\x64 を path を追加しましたが、
よく考えると x86 (32bit) 上で実行する分には不要なものでした。
訂正させていただきます。

実際に Vista x64 をメイン PC にインストールしました。
現在 Windows Vista x86 (32bit) が入っているので 2つ目の HDD に
入れてみます。

HDD 1 – C: Vista x86 (32bit)
HDD 0 – D: Vista x64 (64bit) install 予定

OS が起動した状態から install できなかったので、いったん DVD から
boot します。

インストール予定の HDD 0 側はあらかじめ 100G ほどの空きを作って
おきました。特に HDD を初期化しなくても新規相当で install 可能で、
もとからあったフォルダやファイルなどもそのまま残ります。

install 後、とりあえず Vista x86 と x64 の dual boot となります。
Windows Vista では、どちらで起動してもシステムが入っている方が
C: ドライブに割り当てられます。

x86 (32bit) で起動すると x64 側ドライブ(HDD 0)が D:
x64 (64bit) で起動すると x86 側ドライブ(HDD 1)が D:

システムドライブが固定されるため、それぞれツールなどをインストール
しても混乱せず、混用されないのでこの方が便利です。

アプリケーションは OS 毎に個別のインストールになりますが、
作成したデータなどは共有したいところです。
起動する OS によってフォルダのドライブが異なるため、データは一意に
アクセスしづらくなります。

たとえば x86 で C:\DATA にデータが格納してあった場合、x64 で起動
すると D:\DATA になります。

そこで、両方で共通にアクセスする可能性のあるフォルダは
symbolic link を作りました。
コマンドプロンプトから下記のように実行します。

mklink /d C:\DATA D:\DATA

これで x64 側でも C:\DATA が作られます。実際のデータは D:\DATA に
格納されますが、使ってる分には完全に C:\DATA でアクセスできます。

mklink 実行時に権限が無いといわれることがあります。その場合は
コマンドプロンプトを管理者権限で起動しておきます。スタートメニュー
から起動するとき、右ボタンの「管理者として実行」を選択します。

以前だったらこうなることを想定して、普段から仮想ドライブを作って
おいたりしなければいけないところです。Vista の symbolic link の
方がフォルダ単位で柔軟に対応できるし慣れてるので扱いが楽です。

64bit 環境でも 32bit のアプリケーションがそのまま動作するので、
今のところは特に不具合もなく使えています。普段使ってるツールも
動くし乗り換えてもいいかもしれません。まだ1日しか使ってないけど。

x64 専用アプリに切り替えなくても、たとえばコンパイラの設定も
x86_amd64 (32bit 用 64bit コンパイラ) のままでも動きます。

Program Files も2種類できていました。

C:\Program Files
C:\Program Files (x86)

実行するアプリケーションによっていくつかの環境変数が切り替わる
ようになっています。

MSDN 64-Bit Windows WOW64 Implementation Details

たとえば環境変数 ProgramFiles は、64bit アプリでは
C:\Program Files を指していますが 32bit アプリケーションでは
ProgramFiles は C:\Program Files (x86) になっています。

同じように PROCESSOR_ARCHITECTURE も必要に応じて AMD64 や x86
になります。

急に乗り換えたのは Maya plug-in を x64 に対応させるためでした。
そろそろメモリが厳しいということで、グラフィックデザイナーの環境が
64bit に移行しつつあります。

64bit 開発設定のメモ

Windows で x64 用の build 環境を作る時のメモです。

●VisualStudio 2005 IDE

MSDN 方法 : Visual C++ プロジェクトを 64 ビット プラットフォーム用に設定する

構成マネージャで新しい Platform を追加するだけでいいようです。
WindowsCE の CPU 追加と同じような感じ。
その後 Options の Projects and Solutions → VC++ Directories でも
Platform を選択してフォルダなどの確認や追加をします。
32bit 版 Vista で作業しているので、クロス開発用バイナリ x86_amd64 が
選択されていました。
DirectX SDK 用に下記の設定を追加します。必ず一番上にしておきます。

Executable files:
 $(DXSDK_DIR)Utilities\Bin\x64

Inclue files:
 $(DXSDK_DIR)Include

Library files:
 $(DXSDK_DIR)Lib\x64

●コマンドライン用

MSDN 方法 : 64 ビットの Visual C++ ツールセットをコマンド ラインから有効にする

vcvarsall.bat の中を見ると各環境用の個別のファイルを呼び出して
いるだけでした。それぞれ専用の環境変数設定が用意されています。

x86        32bit 用
amd64      64bit 用
x86_amd64  32bit 上で 64bit バイナリの作成 (クロスコンパイル)

環境設定用 bat ファイル

x86       VC\bin\vcvars32.bat
adm64      VC\bin\amd64\vcvarsamd64.bat
x86_adm64  VC\bin\x86_amd64\vcvarsx86_amd64.bat

ひとつの Makefile で各環境用のバイナリを作るなら、これらの設定も
Makefile に記述することになるでしょう。

x64 の場合 lib のそれぞれのパスに lib\amd64 を追加するだけで、
または DirectX SDK のように x86 を x64 に置き換えます。
binary path の場合は上記のようにクロスコンパイルを含めた 3 種類の
構成があります。x86_amd64 では x86 用 bin も必要なので、その前に
x86_amd64 用パスを追加します。

x86
  C:\Program Files\Microsoft Visual Studio 8\VC\bin

amd64
  C:\Program Files\Microsoft Visual Studio 8\VC\bin\amd64

x86_amd64
  C:\Program Files\Microsoft Visual Studio 8\VC\bin\x86_amd64
  C:\Program Files\Microsoft Visual Studio 8\VC\bin

あとはコンパイルオプションの変更など。
ほぼ同じ指定が可能で -arch:SSE2 は不要。

__asm ははじかれたけど、intrin.h は大丈夫そうです。

_T() と TEXT() の違いやソースの文字コード

非常にいまさらな感じで、とっくに常識かもしれませんが、文字列
リテラルに用いる _T() と TEXT() はどこが違うのか気になったので
調べてみました。

Windows で文字や文字列を扱う場合、TCHAR (_TCHAR) 型を良く用います。
これはコンパイル時のオプションによって char と wchar_t に定義内容
が変わります。
TCHAR 型を使用しておくと同一ソースコードでも比較的容易に文字列の
扱いを切り替えることができます。

特に NT 系の API では、文字列として両方受け付けるよう関数が2セット
用意されていて、混在することが可能です。
9x 系の時代は MBCS による表現が用いられていたので、Local かつ
当時から引き継いでいるプログラムなどはそのまま char 型として扱う
ことができます。

逆に WindowsCE は wchar_t しか受け付けないので、CE とのコード共有を
考えると TCHAR 型への対応は重要でした。
ゲーム機でも Dreamcast では WindowsCE を選択できたので、
WindowsCE を使う場合は WCHAR 等の wide 型が用いられました。

TCHAR と同じように文字列定数や文字定数も切り替える必要があります。
その場合に用いられるのが _T() や TEXT() マクロです。この両者は同じ
意味だといわれています。

例えば _T(“initdata.dds”) とか TEXT(“maze.fx”) など、どちらで
記述しても特に差はありません。

_T() の実際の宣言は VC/include の tchar.h にありました。
定義部分だけ抽出すると下記のようになります。

// tchar.h
#ifdef  _UNICODE
#define __T(x)      L ## x
#else
#define __T(x)      x
#endif

#define _T(x)       __T(x)
#define _TEXT(x)    __T(x)

シンボル _UNICODE の定義によって __T() を切り替え、それを _T() と
_TEXT() に定義しなおしています。2段階定義になっているのは、おそらく
マクロ展開のためにプリプロセッサのパスを最低2回通すためでしょう。

 例えば #define DDSFILE “initdata.dds” と定義した場合
 _T(DDSFILE) だと L”initdata.dds” になりますが
 __T(DDSFILE) の場合は LDDSFILE となります。

TEXT() の定義は VC/PlatformSDK/include の winnt.h の中にありました。

// winnt.h
ifdef UNICODE
#define __TEXT(quote) L##quote      // r_winnt
#else
#define __TEXT(quote) quote         // r_winnt
#endif

#define TEXT(quote) __TEXT(quote)   // r_winnt

定義されている意味は同じです。こちらはシンボル UNICODE の定義に
よって __TEXT() の内容が変わり、それをさらに TEXT() に定義
しなおしています。

_TEXT() は tchar.h だけど TEXT() と __TEXT() は winnt.h など、
双方シンボルが衝突しないように微妙に使い分けられているようです。

_T() と TEXT() はそれぞれ定義している場所が違うので、include して
いるヘッダによっては必ずしも両方使えるとは限らないようです。
また UNICODE、_UNICODE の両方を必ず定義するか、または定義しない
ようにしないと定義内容が異なってしまいます。

ヘッダを調べると、一部のヘッダ (OleDlg.h, MSAcm.h, pdh.h) では
UNICODE と _UNICODE の同期を取るコードが含まれていました。

OleDlg.h
// syncronize UNICODE options
#if defined(_UNICODE) && !defined(UNICODE)
        #define UNICODE
#endif
#if defined(UNICODE) && !defined(_UNICODE)
        #define _UNICODE
#endif

ただしこれらのヘッダは必ず include されるとは限らないので、
結局は VisualStudio が挿入するコマンド行シンボル
/D “UNICODE” /D “_UNICODE” に依存しているようです。

ちなみに Windows の wide character は UNICODE の 16bit エンコー
ディングで、MBCS では ShiftJIS が使われていました。
UTF-8 など、UNICODE でも MBCS の可能性があります。
文字まわりはいつも苦労するところですが、個人的にはプログラム中
でも UTF-8 を使うことが結構あります。

プログラム中で扱う文字コードの他に、ソースコードの文字をどうしようか、
といった悩みもあります。以前は OS の言語によってソースを ShiftJIS
とみなしてしまう仕様があって、0x5c(\) の処理でよく問題が
出ていました。

マニュアルを見ると VisualStudio2005 では、BOM さえあれば UTF-8
でも大丈夫そうです。
MSDN コンパイラおよびリンカでの Unicode のサポート

試してみました。テキストエディタでソースを ShiftJIS で開いて

// 表
 Error

とか書いて保存します。UTF-8 で開くと

// [95]\
 Error

となります。文字としては不正ですがとりあえずやってみます。
bom つきで保存するとコンパイルエラーにはならず、行末の \ が
有効となっていることがわかります。(vim で :se bomb )
bom 無しで保存すると ShiftJIS とみなされ、行末の \ が無視
されてコンパイルエラーになります。(vim で :se nobomb )
きちんと UTF-8 を認識しています。

さらに、UTF-8 かつ BOM 付きで実際にコンパイルされた文字コードを
見てみます。

wchar_t* wstr= L"あい";
char*    str= "あい";

ソースコードは 0xe3 0x81 0x82 0xe3 0x81 0x84 で UTF-8 です。

wstr の表示出力は 0x3042 0x3044 0x0000
str の表示出力は 0x82 0xa0 0x82 0xa2 0x00

結局 UTF-16(UCS-2) と ShiftJIS に変換されていました。
UTF-8 そのままは通らないようです。

Direct3D 10 DXGI_FORMAT の機能対応一覧

DXGI_FORMAT_R11G11B10_FLOAT は RenderTarget として使えましたが、
DXGI_FORMAT_R9G9B9E5_SHAREDEXP はレンダリングできませんでした。
Direct3D 10 DXGI_FORMAT_R11G11B10_FLOAT の実験(2)
Direct3D 10 DXGI_FORMAT_R11G11B10_FLOAT の実験

また Direct3D10/DirectX10 では Pixel 形式も頂点形式もインデックスも
統合されています。BC1 (DXT1) は画像圧縮用フォーマットなので、
これは頂点形式に使えるのでしょうか。

フォーマット Type 毎に対応している機能や、どの用途に使えるのか
ID3D10Device::CheckFormatSupport() で調べることができます。

各フォーマットの機能一覧を作成してみました。

Direct3D 10.0 DXGI_FORMAT 機能対応一覧

表の BF は CreateBuffer() で作成できるかどうか、
1D ~ 3D はそれぞれ CreateTexture1D() ~ 3D() で作成できるかどうか、
Texture として使えるかどうかを意味しています。

BF = ID3D10Buffer
1D = ID3DTexture1D
2D = ID3DTexture2D
3D = ID3DTexture3D

VB, IB, SO は、VertexBuffer, IndexBuffer, StreamOutput や
InputLayout の定義に使えるかどうかです。これを見ると、やはり
BC1~BC5 (DXT) や、R8G8_B8G8/G8R8_G8B8 (YUV) などの圧縮形式は
画像以外に使えないことがわかります。

R9G9B9E5_SHAREDEXP はだめですが、R11G11B10_FLOAT は頂点でも
使用できるようです。

IndexBuffer に使えるのは
R32_UINT (32bit), R16_UINT (16bit) しかありませんでした。

VB = InputLayout (VertexBuffer)
IB = IndexBuffer
SO = StreamOutput

SL, SS, SC は、シェーダー中のリソースアクセス手段を示しています。
SL は Sampler を使わないで直接 Load() 命令が使えるかどうか、
SS は Sampler 経由の Sample() 命令が使えるかどうかです。

同じように SC は SampleCmp() 系命令に対応しています。わかりやすく
言えば、SC が付いたフォーマットはハードウエアシャドウマップ
(NVIDIA ShadowMap) に使えるということです。

SL = Load()
SS = Sample() / SampleGrad() / SampleLevel()
SC = SampleCmp() / SampleCmpLevelZero()

MI は MipMap です。ほとんどすべてのフォーマットが使用可能に
なっています。MA は Mipmap の自動生成対応かどうか。

MI = MipMap
MA = MipMap 自動生成

RT が付いたものは RenderTarget に使えます。整数形式を含めて
レンダリング可能な形式は結構多いようです。ただし Blend 可能な
なのは BL が付いたものだけです。Blend 対応フォーマットはそれほど
多くありませんが、32bit FLOAT もしっかり blend 対応になっている
など D3D9 世代と比べたらかなりの贅沢さです。

DS は DepthStencil 用フォーマットです。DepthStencil はまだまだ
特殊なフォーマットであることがわかります。

MT が付いたものはさらに MultiSample 対応になります。
DI (Display) は単なる RenderTarget ではなく、FrontBuffer として
使用可能なフォーマットを意味しているようです。

RT = RenderTarget
BL = Blend 対応
DS = DepthStencil
MT = MultiSample RenderTarget
DI = Display

その他の機能シンボルの意味は下記のとおりです。

CL = CPU で Lock (Map)できる
CW = 他の format に cast できる
MR = MultiSample Resolution 対応
ML = Multisample テクスチャを Load() 可能

表を見ていると 1bit 形式の DXGI_FORMAT_R1_UNORM はかなり特殊な
フォーマットであることがわかります。2D Texture にしか使えず
Mipmap もありません。RenderTarget もだめ。

またこのフォーマット機能表を確認しておくと、Direct3D 10.1 の
機能拡張の意味が見えてきます。
まず block-compressed (BC?) texture へのレンダリングができる
ようになるとのこと。

さらに Blend 対応の拡張があります。10.0 だと下記のものだけですが、
これが DirectX 10.1 ではすべての UNORM、SNORM で使えるように
なるそうです。

R32G32B32A32_FLOAT
R32G32_FLOAT
R32_FLOAT
R16G16B16A16_FLOAT
R16G16_FLOAT
R16_FLOAT
R11G11B10_FLOAT
R10G10B10A2_UNORM
R8G8B8A8_UNORM
R8G8B8A8_UNORM_SRGB
R8G8_UNORM
R8_UNORM
A8_UNORM