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

新型 PSP (PSP-2000) とゲームアーカイブス

新型 PSP (PSP-2000) を入手してしまいました。
といっても結構前です。発売日のすぐ直後に、店頭で売っているのを
見つけたのでついつい。

新型で一番嬉しかったのは、
軽いことでもなく(確かにこれはすごいのですが)、
TVに出力できることでもなく、
読み込みが早いことでもなくて、
方向キーが、最初からちゃんと斜めに入ることです。

以前持っていた PSP は初期型だったので、過去にこんな感じで
苦労していました。
PSP の十字キーが良くなった
PSPで十字キーが斜めに入らない理由

今年になってからは、ゲームアーカイブス のおかげでかなり PSP の
稼働率が上がっています。
Wikipedia ゲームアーカイブス

ゲームアーカイブスでできるのは、PS1 のソフトをダウンロードして
PSP 上で走らせられる、それだけのことです。

思いがけない過去の名作に出会うという、ソフトのよさももちろん
ありますが、むしろ良くできているのはトータルで見た時の使いやすさ
かもしれません。

早い話、今までのゲーム機と比べて非常に便利なのです。

 ・ディスク入れ替え不要で複数のソフトを入れておける
 ・手に入りにくいソフトでも気軽に買える
 ・比較的安価
 ・データダウンロードなのでパッケージやメディアで場所をとらない
 ・メモリカードでソフト本体もセーブデータも一緒に管理できる
 ・PS1 のソフトを常に持ち歩けて、いつでもサスペンドできる
 ・マニュアルもソフト内で読めるので無くさない
 ・PS3 本体でも動くしセーブデータも相互にコピーできる

などなど。
今までのゲームソフトにあった「不便」がかなり無くなっています。
据え置き CD が iPod になったように、ゲームソフトで本当のデジタル
コンテンツらしさを、ようやく実現できたのではないか、とそう感じます。
(そういえば昔、携帯電話のゲームでも同じことを思いました。)

他にも、コンテンツのダウンロード販売として柔軟な点も魅力です。

 ・一度購入すればいつでも再ダウンロードできる
 ・PS3 本体 HDD にソフトが蓄積されるので、いつでも入れ替えできる
 ・メモリカードの内容を PC で簡単にバックアップできる
 ・各ゲームを PC にコピーして保存、入れ替えもできる
  (異なるPSP本体にはコピーできない)

過去に携帯の乗り換えミスで何度もゲームを失ったことを思えば、
柔軟で融通の利くデータ管理は魅力です。

セーブデータの転送も PS3, PSP 間で相互にできるし、PS3 経由で
アダプタを使えば PS1 のメモリーカードとのやり取りもできるし、
自由度は高いです。
ただ、セーブブロックを 1つ1つコピーするのは結構手間がかかり、
どちらが本当に新しいデータなのか たまに わからなくなります。

iTunes + iPod のように、USB でつないで自動でセーブデータを
同期できたらもっと便利になりそうです。もし簡単に同期できるなら、
本当の意味で「外に持ち出して続きをプレイ」が実現しそうですね。

ゲーム本体も、メモリカードの容量が足りなくなったら入れ替える
ことができます。まるでオーディオプレイヤーのように。

これは非常に便利なので、普通のパッケージソフトや新作もぜひ
ダウンロード版を選べるようして欲しいところです。
ゲームは欲しいけれど、パッケージやメディアが場所をとって
たまっていくのはそろそろ避けたいので。CD を購入しても、一度
iTunes に読み込ませたらほとんど触らなくなるのと同じように。

以下、新型への乗換えを行った時のメモです。

●メモリカードの乗り換え

 先に 同じ PSP 本体を使って、より容量の大きいメモリカードに
 乗り換えてみました。
 PC 上でカードの内容をコピーするだけで、ゲームアーカイブスや
 セーブデータを含めて簡単に乗り換え出来ました。

 PSP 自体に USB ストレージ機能があるので、一旦 PC を経由して
 コピーしても大丈夫です。ついでに PC にバックアップも取れます。

 (1) PSP を USB モードにして PC と接続
 (2) PC 上にカードの中身を全部バックアップコピー (PC ← PSP)

 (3) PSP の接続を解除

 (4) PSP のメモリカードを新しいものに入れ替え
 (5) また USB モードで PC に接続
 (6) バックアップコピーを全部書き戻す (PSP ← PC)

●PSP 本体の乗り換え

 異なる PSP 本体では、同じメモリカードを使うことができませんでした。
 セーブデータなどのデータはそのまま持っていけますが、
 ゲームアーカイブスのゲームは起動しません。

 新しい PSP 本体を使って再認証が必要です。具体的には PS3 から
 コピーしなおすだけでした。

 PS3 で購入したゲームデータは PS3 本体の HDD にも保存されます。
 また一度購入したデータはもう一度ダウンロードすることも出来ます。
 PS3 上で展開したら、PSP をつないで △ボタンから「コピー」を
 選ぶと再認証した後 PSP にゲームを転送します。

 巨大なデータの転送しなおしになるので少々時間はかかりますが、
 再ダウンロードしなくて良い分比較的楽でした。

 機器認証は1アカウントにつき最大5台とのことなので、4回以上乗り換えた
 場合にどうなるかわかりません。
 (もしかして PS3 の分も含まれているのでしょうか?)

なお現在は PS3 が無くても、PC からゲームの購入ができるようになって
います。こちらは試していないので、PC を使った場合の再認証とか
再転送とかその辺についても把握しておりません。
PLAYSTATION Store(PC) ゲームアーカイブス

Direct3D 10 HLSL Effect/FX リソース設定のはまり

●前置き

D3D10/DX10 のレンダリングは、入力と出力に同じものを指定することが
できません。

同じバッファ (Texture) を、RenderTarget と ShaderResource(Texture)
に同時に設定できず、もし設定しても入力側が強制的に 0 (NULL) 相当に
なります。少々厳密すぎる気もしますが、自己レンダリングは動作結果を
保障できないので当たり前といえば当たり前です。

非常にありがたいことに Direct3D10 では、間違って設定しても
DebugLayer が親切に教えてくれます。

ただ判定が厳密すぎるために少々問題になることもあります。

例として、テクスチャへのレンダリングを考えてみます。次のように
読み込み用と書き込み用の View を作成してあるものとします。
iTextureBuffer と iRenderBuffer は、同一の Resource Buffer を
参照していると思ってください。

ID3D10ShaderResourceView*  iTextureBuffer[2]; // テクスチャ
ID3D10RenderTargetView*    iRenderBuffer[2];  // レンダーターゲット

// iTextureBuffer[0] と iRenderBuffer[0] はどちらも Resource[0]
// iTextureBuffer[1] と iRenderBuffer[1] はどちらも Resource[1]

下記の “InputTexture” は Effect(fx) 内で Texture2D 宣言された変数で、
入力するテクスチャを意味しています。登録用インターフェースを
iInputTexture にキャッシュしておきます。

ID3D10EffectShaderResourceVariable* iInputTexture=
    iEffectModel->GetVariableByName( "InputTexture" )
        ->AsShaderResource();

描画時のセットアップを次のようにします。

// list1
// 入力テクスチャの設定
iInputTexture->SetResource( iTextureBuffer[0] ); // ←入力 (A)
iEffectModel->GetTechniqueByName( "Main" )
      ->GetPassByIndex(0)->Apply(0);

// 出力の設定
iDevice->OMSetRenderTargets( 1, &iRenderBuffer[1], NULL ); // ←出力 (B)

Effect の変数に登録したパラメータは Apply() で反映されます。
これで Draw() を発行すると、Resource[0] を読み込んで Resource[1]
を更新することができます。

Resource[1] ← Resource[0]

その直後に、今度は入力と出力を入れ替えてレンダリングします。

Resource[0] ← Resource[1]

// 入力テクスチャの設定
iInputTexture->SetResource( iTextureBuffer[1] );
iEffectModel->GetTechniqueByName( "Main" )->GetPassByIndex(0)
      ->Apply(0); // ←できない, (B)でBusy

// 出力の設定
iDevice->OMSetRenderTargets( 1, &iRenderBuffer[0], NULL );

このとき、Resource[1] は前のレンダリングで RenderTarget として
登録されています。すでに Busy なので、入力テクスチャとして設定する
ことができません。
(ちなみにこれらの衝突は正確には Draw の実行タイミングで検出されます)

衝突を回避するには、先に RenderTarget のステートをクリアしておくか
別のターゲットを登録して参照をはずす必要があります。

// 入力テクスチャの設定
ID3D10RenderTargetView* iRTVNull= NULL;
iDevice->OMSetRenderTargets( 1, &iRTVNull, NULL ); // 参照外しのクリア

iInputTexture->SetResource( iTextureBuffer[1] );
iEffectModel->GetTechniqueByName( "Main" )
      ->GetPassByIndex(0)->Apply(0); // ←できる

// 出力の設定
iDevice->OMSetRenderTargets( 1, &iRenderBuffer[0], NULL );

SetResource と SetRenderTarget の順番を変えても同じで、今度は
入力テクスチャとして参照されているため RenderTarget への登録が
できなくなります。

// 出力の設定
iDevice->OMSetRenderTargets( 1, &iRenderBuffer[0], NULL ); // ←できない, (A)でBusy

// 入力テクスチャの設定
iInputTexture->SetResource( iTextureBuffer[1] );
iEffectModel->GetTechniqueByName( "Main" )
      ->GetPassByIndex(0)->Apply(0);

このステート設定順の問題は以前のエントリでも触れました。
Direct3D 10 Streamと同時Resource

また ClearState() を使うとこれらのリソース参照をいっぺんにはずすことができます。
Direct3D 10 ClearState
ただし必要なものまで全部解除されてしまうので効率は悪くなります。

●本題

Effect(fx) を使って描画していると、このリソースの衝突がどうしても
発生してしまうことがあります。C/C++ のプログラムコード上は正しくても
うまくいかず、それだけでは原因がわからないのです。

// list2
iInputTexture->SetResource( iTextureBuffer[0] ); // (C)
iEffectModel->GetTechniqueByName( "Update" )
      ->GetPassByIndex(0)->Apply(0);

 ~描画など

// 入力テクスチャの設定
iInputTexture->SetResource( iTextureBuffer[1] ); // (D)
iEffectModel->GetTechniqueByName( "Main" )
      ->GetPassByIndex(0)->Apply(0);

// 出力の設定
iDevice->OMSetRenderTargets( 1, &iRenderBuffer[0], NULL ); // (E)

list2 の (C) で Resource[0] を入力テクスチャとして参照し、一旦描画
しています。その後 (D) でテクスチャを変更して、別の Technique を使って
描画しようとしています。

InputTexture は iTextureBuffer[1] (Resource[1]) で置換されているし
Apply() もしているので、(E) のタイミングでは Resource[0] はフリーに
なったように見えます。

ところがシェーダーによっては (E) の SetRenderTarget() で衝突してしまう
可能性があります。

重要なのは描画に使っている Technique が異なっているということです。

ID3D10Effect 上では同一の変数&インターフェースとしてリソース登録が
できるものの、書き換えられる場所はシェーダーによって違うからです。

(1) シェーダーリソースの登録は、VS, GS, PS それぞれ別管理となっている

“Update” のシェーダーでは、InputTexture を VS と PS の両方で参照
しているかもしれません。Core API での Resource 登録は VS, GS, PS
それぞれ別なので、下記のように専用の登録 API があります。

ID3D10Device::VSSetShaderResources()
ID3D10Device::GSSetShaderResources()
ID3D10Device::PSSetShaderResources()

“Main” のシェーダーで、もし InputTexture の読み込みを PS だけで
行っているとしたら、(D) の Apply() で上書きされるのは
PSSetShaderResources() だけなのです。
そのため VSSetShaderResources() の参照が残ったままとなります。

(2) シェーダーによって、各リソース参照するスロット番号が異なっている。

“Update” の PixelShader が 2枚のテクスチャを参照しているとします。
このとき InputTexture が 0 と 1 のどちらのスロットに割り当てられる
のか予測できません。(Reflection を見るとわかる)

例えば “Update” では InputTexture は Slot 1 に割り当てられており、
“Main” の PixelShader では Slot 0 だとすると、
やはり (D) の Apply() では Slot 1 の参照は上書きされずに残って
しまうのです。

HLSL コンパイラは最適化によって、各シェーダーが本当に必要としている
リソースしかバインドしません。ID3D10Effect のステート管理も最小限の
更新だけで済むように最適化が行われているので、内部の動作をある程度
把握しておかないと、このような はまり に遭遇してしまうことになります。

個別に呼び出すとシェーダー単体は問題なく動作するし、C/C++ のコードも
問題が無いので原因がなかなか見つからないかもしれません。

注意点

 ・同じ Effect/Fx でも Technique や Pass が異なっていると違うシェーダー
  であること

 ・シェーダー(Technique/Pass)ごとに Apply() しないと、厳密には各種リソース
  のステートが上書きされないこと

よくあるのはこんなケースです。

 1. 本来はシェーダーでテクスチャを参照している

 2. デバッグのために一時的に Shader を書き換えて、固定値を出力して
  動きを確認しようとする。
  (例えば PS で強制的に return float4(1,0,0,1); とするなど)

 3. このときテクスチャの参照が外れたので、Effect は Resource 設定の
  上書きを行わずに前のステートが残ってしまう。

 4. 固定値を返すように書き換えただけなのに、突然関係ないシェーダーの
  描画で衝突検出が発生して驚く

Effect(fx) を使って、高レベルな API の理解だけで済ませてしまおう・・
として、思わぬはまりに遭遇することがあります。D3D10 ではある程度
Effect 内部動作や ID3D10Device 関連のステート設定についてもきちんと
把握しておく必要があるかもしれません。

em1key Bluetooth keyboard RBK-2000BTII の設定 その3

以前こちらのエントリで、Bluetooth keyboard RBK-2000BT2 用の
カスタマイズファイル(em1key用)を公開しました。
em1key Bluetooth keyboard RBK-2000BTII の設定 その2

ところがこの設定を使ってカーソルキーのカスタマイズを有効にする
([↑] 位置を [/?] にする)と、ZERO3 や EM・ONE 内蔵キーボードの
カーソルキーも影響を受けます。[↑]が入れ替わってしまいます。

em1key 側の問題なので、カーソルキー部分も内蔵キーボードと外部
キーボードの分離判定を行うように修正してみました。
WindowsMobile 版のみです。

em1key v1.27

これでカーソルキー部分の入れ替えを行っても、本体内蔵のカーソル
キーは影響を受けなくなりました。設定ファイルの変更はありません。

しばらく使っていて気がついたのですが、RBK-2000BT2 では [Fn] との
併用で次のキー操作も使えるようです。

[F11]       [Fn] + [-_]     ファンクションキー
[F12]       [Fn] + [=+]     ファンクションキー
[PageUp]    [Fn] + [↑]
[PageDown]  [Fn] + [↓]
[Home]      [Fn] + [←]
[End]       [Fn] + [→]

またメーカーサイトでは、リュウド純正のキー変更ツール
「Windows Mobile版RBK-2000BTIIサポートソフト Ver.1.0」
が公開されています。
Rboard for Keitai ソフトウエア・ダウンロード
WindowsMobile 上でキーボードの刻印どおりにキー入力できるように
するためのもので、ASCII(英語)配列キーボードになります。

マニュアルを一通り読んでみました。組み込まれている機能を
考えると、一般的な Keyboard Hook を使っているようにみえます。
実際に起動してみるとやはり em1key と共存できませんでした。
[Fn] キーのカスタマイズなどキーボード特有の特殊なことはして
いないので、おそらく asciipatchwm とほぼ同等の置き換えではない
でしょうか。
[Fn]+[←]/[→] のソフトキーへの置き換えは、もともと [Home]/[End]
が割り当てられていたので、それを置換しているだけだと思われます。

逆にキーボードを選ばず動作する可能性があるので、もしかしたらこれも
一般的な ASCII(英語)配列キーボード用の配列補正ツールとして使えるかも
しれません。

関連エントリ
Bluetooth キーボード Rboard for Keitai RBK-2000BT2
em1key Bluetooth keyboard RBK-2000BTII の日本語カスタマイズ例
em1key Bluetooth keyboard RBK-2000BTII の設定 その2

EMOBILE EM・ONE WindowsMobile6 アップグレード申し込み

EM・ONE (S01SH) の WindowsMobile6 アップグレードを申し込んでみました。

イー・モバイル、「EM・ONE α」にIP電話機能
EM・ONE向けのWM6アップグレード受付、10月5日開始
最新OS、Microsoft(R) Windows Mobile(R) 6への「EM・ONE」有償アップグレードサービスを提供開始 Microsoft(R) Windows Mobile(R) 5.0搭載機向け

手順はまず電話での申し込みです。

(1) カスタマーセンターへ電話
  自動応答だけど該当するものが無いのでオペレータ呼び出しへ

(2) 申し込み。一通り説明を受ける

(3) 書類の到着を待つ

(4) 届いた書類に記入して捺印。本体とともに郵送

  ・初期化されるので必要なデータはバックアップをとっておく。
  ・製品が入っていた黒い箱に入れて送る。
  ・郵送するものは本体のみ。下記のものは送らない。はずしておく。
    ・スタイラス
    ・バッテリー
    ・バッテリーのふた
    ・SIMカード(EM chip)
    ・miniSDカード
    ・ストラップ

(5) アップグレードが完了して届くのを待つ
  2週間ほどかかる予定

現在(3)の段階です。
料金は 9980円で送料込み。

以前 iPAQ h3630 を PocketPC 2002 にアップグレードしたときも
CD-ROM の送付だけで 7000円以上しました。
GENIO e550 はメーカーに送って RAM 増設込みを選んだので
2万円近くかかってます。当時の記録を見てみると、GENIO は
意外にも早くて 1週間くらいで返ってきたようです。

Direct3D 10 Shader4.0 ジオメトリシェーダーで QUADLIST の描画

描画するプリミティブの形状は通常 IASetPrimitiveTopology() で
指定します。D3D10/DX10 では次の 9種類が定義されています。

D3D10_PRIMITIVE_TOPOLOGY_POINTLIST  // 点
D3D10_PRIMITIVE_TOPOLOGY_LINELIST   // 線
D3D10_PRIMITIVE_TOPOLOGY_LINESTRIP  // 連続線
D3D10_PRIMITIVE_TOPOLOGY_TRIANGLELIST  // 三角形
D3D10_PRIMITIVE_TOPOLOGY_TRIANGLESTRIP // 連続三角形
D3D10_PRIMITIVE_TOPOLOGY_LINELIST_ADJ
D3D10_PRIMITIVE_TOPOLOGY_LINESTRIP_ADJ
D3D10_PRIMITIVE_TOPOLOGY_TRIANGLELIST_ADJ
D3D10_PRIMITIVE_TOPOLOGY_TRIANGLESTRIP_ADJ

ところがジオメトリシェーダーを使っている場合、
IASetPrimitiveTopology() の設定値は実際に描画する
プリミティブ形状と連動していません。

というのは、GeometryShader の出力プリミティブの種類はシェーダー
側で再定義されるからです。

PointSprite がその良い例で、入力 Topology は PointList でも
実際に描画される形状は TriangleStrip の板ポリゴンになっています。

つまりジオメトリシェーダーを使う場合の IASetPrimitiveTopology()
の設定値は、

・頂点ストリームを一度に読み進める量
・GeometryShader へ同時に入力されるパラメータ数

の決定にだけ使われると考えられます。

そこでジオメトリシェーダーへの入力頂点数にだけ注目してまとめると
次のようになります。

同時 1 頂点 POINTLIST
同時 2 頂点 LINELIST
同時 3 頂点 TRIANGLELIST
同時 4 頂点 LINELIST_ADJ
同時 6 頂点 TRIANGLELIST_ADJ

同時 5頂点が無いのが残念ですが、ほぼ 1~6 頂点までの汎用的な入力
頂点数として流用することが可能です。この考え方を使って
4頂点プリミティブや 6頂点プリミティブを定義することができます。

実際に 4角ポリゴン でモデルを作って描画してみました。
いわゆる QUADLIST 相当です。(D3DPT_QUADLIST ?)

ss07

いつものように、実行ファイル、ソース、シェーダー込みでダウンロード
できます。

モデルデータ側は四角形のあつまりなので、index list は 4つで
1ポリゴンとなります。

// torus.inc
static unsigned short _Index[]= {
    0, 1, 2, 3,	// 四角ポリゴン1
    4, 0, 3, 5,	// 四角ポリゴン2
    6, 4, 5, 7,	// 四角ポリゴン3
    8, 6, 7, 9,	// 四角ポリゴン4
      :

描画命令の発行は 同時4頂点入力の LINELIST_ADJ を使います。

// 描画 (ss07.cpp)
iDevice->IASetPrimitiveTopology( D3D10_PRIMITIVE_TOPOLOGY_LINELIST_ADJ );
iDevice->IASetInputLayout( iInputLayout );
UINT	vsize= sizeof(VertexType);
UINT	voffset= 0;
iDevice->IASetVertexBuffers( 0, 1, &iVertexBuffer, &vsize, &voffset );
iDevice->IASetIndexBuffer( iIndexBuffer, DXGI_FORMAT_R16_UINT, 0 );

iEffectModel->GetTechniqueByName( "Main" )->GetPassByIndex( 0 )->Apply( 0 );
iDevice->DrawIndexedInstanced( IndexCount, 16, 0, 0, 0 );

無駄に凝ったことをしているので DrawIndexedInstance() になってますが、
LINELIST_ADJ 以外はごく普通の描画コードです。
DrawIndexed~() に渡す値もそのまま頂点数 (Index) の個数になっています。
もし1枚だけ描くなら 4頂点です。

// 1枚だけ描く場合
iDevice->DrawIndexed( 4, 0, 0 );

VertexShader も PixelShader も通常の描画と全く同じものです。
ジオメトリシェーダーは次のとおりです。

typedef VS_OUTPUT   GS_OUTPUT;

[maxvertexcount(4)]
void GS_Main( lineadj GS_OUTPUT In[4],
		inout TriangleStream gsstream )
{
    gsstream.Append( In[0] );
    gsstream.Append( In[1] );
    gsstream.Append( In[3] );
    gsstream.Append( In[2] );
    gsstream.RestartStrip();
}

lineadj で 4頂点入力、TriangleStrip で四角形を描画します。
これで QUADLIST の描画が可能となります。

ファイルはこちらです。
wheelhandle_ss07t.zip