One Note Jam

Vodafone 702NKII(Nokia 6680)のディスプレイモード (2005-12-18)

「Vodafone 702NKII」がようやく発売されたとのこと。端末自体は「Nokia 6680」と同じもののようですね。

スペック的には702NK(Nokia 6630)と大差なく、目立った変化はテレビ電話用のサブカメラがついた程度なのかな……と思っていたのですが、開発者的な視点から見るとかなり重大な変更点がひとつ。

702NK(Nokia 6630)702NKII(Nokia 6680)
解像度176×208176×208
色数65,536色(16bpp)262,144色(18bpp)

色数が26万色になっています。これにより、1ピクセルの色データが16ビット内に収まらなくなってしまうわけで、ソフトウェア側から見るとかなり影響が大きい変更点だといえます。Symbian OSのディスプレイモードには「18bpp」というモードはなく、おそらく内部的には1ピクセルを32ビットで扱っているのだろうと推測します(「CCoeEnv::Static()->ScreenDevice()->DisplayMode()」で返ってくる値が「EColor16MU」になっていると予想)。

もちろん、ピクセルデータの内部表現が変わったところで、そのあたりはSymbian OSの表示系まわりで差異を吸収してくれるため、既存ソフトウェアのほとんどは正常に動作するはずです。ただし、ゲーム系アプリケーションなどで、高速な描画を行うためにフレームバッファを「直に」読み書きしているようなプログラムは、正常に動作しなくなる可能性が高いでしょう。

また、ビットマップ貼り付けなどの処理でも、速度面に影響が現れることが予想されます。ビットマップ貼り付け処理では、ビットマップデータのフォーマットとスクリーンデバイスのディスプレイモードとが一致していない場合、内部でフォーマット変換処理が発生するために速度が低下してしまいます。既存ソフトウェアのビットマップリソースのフォーマットは「EColor64K(16bpp)」形式(あるいは「EColor4K(12bpp)」形式)であると思われるので、速度低下は免れないところかと思います。やはり、既存のゲーム系アプリケーションを動かすにはいろいろ厳しいのかも。

と思いきや、「(702NKより)動作が機敏になった」との報告があちこちからあがっているようですね。ちょっと意外です。どういう仕組みで速くなっているんでしょうか?

posted at 2005-12-18 | Permalink

S60用スクリーンキャプチャツール「GetPixels」の開発 (2) (2005-11-27)

現在作成中のスクリーンキャプチャツールですが、開発は遅々として進んでいません。スクリーンキャプチャに必要な機能自体はすでに実装が済んでいるのですが、S60用のGUIの実装に時間がかかっています。ちなみに、アプリケーションの名前は「GetPixels」と命名しました(いかにもプログラマ的なセンスだ……)。

それはさておき、「GetPixels」開発において得たノウハウなどを、この場で書いていこうと思います。

スクリーン表示内容の取得

スクリーンキャプチャツールを作成するにあたり、まず何といっても「現在のスクリーンの表示内容を取得する」ことができないと話になりません。それを実現するためには、「スクリーンデバイス」の機能を使うことで、スクリーンの表示内容にアクセスすることができます。

CWsScreenDevice* device = CCoeEnv::Static()->ScreenDevice();

CWsScreenDeviceクラスには、「GetPixel」とか「GetScanLine」といったAPIが用意されているので、これらを使えば簡単にスクリーンの表示内容を取得できます。その後の料理はお好きなように。

スクリーンキャプチャツール内の実際の実装では、まさにスクリーンキャプチャのために用意されているかのような「CopyScreenToBitmap」というAPIを使っています。ビットマップオブジェクトを引数にして、指定されたビットマップにスクリーンの内容をコピーするというAPIです。使用例は以下のとおり。

CFbsBitmap* bitmap = new(ELeave) CFbsBitmap;
CleanupStack::PushL(bitmap);
User::LeaveIfError(bitmap->Create(device->SizeInPixels(), device->DisplayMode()));

device->CopyScreenToBitmap(bitmap);

// (bitmapを使って各種処理を行う)

CleanupStack::PopAndDestroy(bitmap);

ちなみに、このCopyScreenToBitmapというAPIですが、実行すると指定したビットマップの内容が変化するにもかかわらず、引数の型は「const CFbsBitmap*」とconst修飾されているので注意してください。CFbsBitmapクラス内には実データが含まれていない(実データへの「ポインタ」のみ含まれている)ので、こういう定義でも間違いではないのでしょうが、まぎらわしいものです。

なお、上記のスクリーンデバイス関連の記述は、S60とかUIQといったユーザーインターフェースに関係なく、Synbian OS全般で共通(のはず)です。

posted at 2005-11-27 | Permalink

S60用スクリーンキャプチャアプリケーションの開発 (2005-11-13)

久々に(プライベートで)Symbianプログラムを再開。作っているのはS60プラットフォーム向けのスクリーンキャプチャツールです。先日、702NKのスクリーンショットを取る必要が生じたのでその手のアプリケーションを物色してみたのですが、なぜか保存形式がJPEG形式だったり、非圧縮形式で保存できるものはシェアウェアだったりして、なんともままなりません。それがきっかけで、ちょっと自分で作ってみようかと思った次第です。

実は、最近私は業務でSymbianプログラムの開発をやっていて、表示系まわりについてはちょっとだけ知識があります。なので、スクリーンキャプチャを実現するために、Symbianのクラスライブラリのどのクラスを使えばいいのかについてもだいたい見当はついていました。というわけで、スクリーンの表示内容をCFbsBitmap形式にダンプするクラスをさくっと作成。そうなれば、CFbsBitmap::SaveL()メソッドを使って簡単にmbmファイルが出来上がり(mbm形式は、Symbian OS標準の画像形式です)。あとは、SDKのツール"bmconv"を使えばBMPファイルに変換できます。やっぱりスクリーンショットは非圧縮形式でないとねー。

せっかく作ったので、もうちょっとまともなものにして公開しようかと思います。まずは画像の保存形式を標準的なフォーマット(PNGとかBMPとか)に対応させたいところ。画像の各種フォーマットへのエンコードは、ICL(Image Conversion Library)を使えば簡単に実現できそうです。今後の業務でICLに係わる可能性もあるため、これを機に触れておこうかと考えています。

posted at 2005-11-13 | Permalink

ゲームボーイアドバンス用プログラム開発雑感 (2) (2005-11-05)

RAM: 288KBytes・ROM: (最大)32MBytes

ゲームボーイアドバンス(以下GBA)での開発をやってみて、最も厳しいと感じたことの一つは「RAMが少ない」という点です。CPU内部に32KBytes・CPU外部に256KBytesで、合わせて288KBytesというRAMの量は、最近のリッチな環境に慣れた者にとってはかなり手狭に感じます。

代わりに、ROM領域はかなり広大です。市販のGBAゲームでは、ROMカートリッジの容量が8MBytesとか16MBytesといったものもあります(最大で32MBytesまで)。また、GBAではROM領域に配置されたプログラムを直接(= RAM領域に展開せずに)実行できますし、CPUからROM領域のデータを直接アクセスすることもできます。なので、RAM領域は純粋に「読み書き可能なメモリ領域」として使うことになるので、容量が少なくてもさほど問題にはならないわけです(多いに越したことはないのですが)。

余談ですが、このあたりはDoJaなんかの携帯電話向けJavaアプリ開発などと比較すると見事に対称的です。携帯アプリでは「ROM容量(≒jarパッケージの容量)」は厳しく制限されていて、代わりに「RAM容量(≒ヒープとして確保できる領域)」は(端末にもよりますが)比較的多めに取れるようになっています。

RAM: 32KBytes・ROM: 256KBytes

ところが、ブートケーブルを使用して実機動作を行う環境の場合、話が変わってきます。以前の記事(2005-10-23)で触れましたが、「ブートケーブル」とは自作プログラムを実機へ送信して起動するためのハードウェアです。これを使用して「送信」したプログラムがどこに格納されるかというと、当然のごとくGBA内のRAM領域しかありません。具体的には「CPU外部RAM(256KBytes)」に格納されます。

すなわち、ブートケーブル環境で動かせるプログラムは最大でも256KBytesで、さらにRAMとして使用できる領域は内部RAMの32Kbytesということになります。これはさすがに狭い……。

実際のところ、私が作っているようなミニゲーム程度のものであれば、このスペックでもなんとかなります。とはいえ、「狭い」ことからくる心理的影響はなかなか大きく、開発中は何かと節約しがちなコーディングとなってしまいます。

こういった事情を知ると、市販GBAゲームで「1カートリッジプレイ」用のプログラムを作成するのは非常に大変であろうことが推測できます。市販GBAゲームの1カートリッジプレイでは、基本的には「通常版」のゲームをそのまま(あるいは「制限版」を)プレイできるようにする必要があります。256KBytes内にグラフィックやサウンドを収めることの厳しさもさることながら、使えるRAMが32KBytesに制限されるというのはさらに厳しいのではないかと思われます。仕事で開発している人は大変だな……。

posted at 2005-11-05 | Permalink

ゲームボーイアドバンス用プログラム開発雑感 (2005-10-23)

ゲームボーイアドバンス(以下GBA)での開発について、開発環境の概要をさらっと紹介。

開発環境

今回の開発では、開発環境として「DevKit Advance」を使いました。というか、昔GBAの開発を始めたときにインストールしたものが残っていたのでそのまま使っているだけなのですが。

当時の定番的な環境の一つですが、バージョンが「Release 5 (Beta 3)」という状態で開発が止まっているように見えるのがちょっと気にかかります。それと、ベースとなっているgccのバージョンも「gcc version 3.2.2 (DevKit Advance R5 Beta 3)」とやや古い。普通に使う分には問題ないとは思いますが。

ハードウェアについての資料

DevKit Advanceには、GBAのハードウェアを制御するためのライブラリは特に含まれていません。ハードウェアの制御を行うには、メモリマップされたレジスタ群を直接アクセスすることになります。そのため、ハードウェアについての詳細な資料は必須です。

GBAのハードウェアは単純明快でわかりやすく、かなり扱いやすいのではないかと思います。なので、ハードウェアのリファレンスマニュアル的資料さえあれば、プログラム開発はじゅうぶん可能でしょう。

エミュレータ

ビルドして生成されたROMイメージはエミュレータにて動作確認します。「VisualBoyAdvance」は、グラフィックビューア・I/Oポートビューア・メモリビューア・逆アセンブル表示などなど、開発に役立つ便利な機能が満載です。

ブートケーブル

せっかくプログラムを作っても、実機で動かせないと面白くありません。コンソールゲーム機プログラム開発に代表されるこの種の「非公式開発」においては、えてして「実機動作」を行うための敷居が非常に高い場合が多いものです。

その点GBAの場合は比較的敷居は低く、「ブートケーブル」なるケーブルを使うことで、自作プログラムを実機へ簡単に送信・起動することができます。GBA本体の改造などは必要ありません。

GBAの市販ゲームソフトには、ROMカートリッジ1つで複数人との対戦プレイができるものがあります。この「1カートリッジプレイ」では、ROMカートリッジが刺さっているGBAが「親機」となり、対戦ケーブル経由でプログラムを「子機」に送信するという形で、子機でプログラムを実行できるようになっています。これを、PCを親機として同様のことを行えば、任意のプログラムをGBAに送信して起動させることが可能になるという仕組みです。これを行うためのケーブルがこの「ブートケーブル」というわけです。

入手方法

問題となるのはブートケーブルの入手方法です。ここ最近は、非ライセンス品の怪しげな周辺機器などもゲームショップで普通に売られていたりしていますが、これくらい特殊な周辺機器となると普通の店では売っていません。

容易に入手するには「Linuxから目覚めるぼくらのゲームボーイ!」という書籍を購入するのがよいでしょう。解説書のほかに、付録としてUSB対応のブートケーブルと、KNOPPIXによる1CD Linux開発環境が入っています。

問題点

ゲームボーイミクロ(以下GBm)ではコネクタの形状が変わっていて、従来GBAのケーブル類は軒並み接続できません。当然、ブートケーブルも使えないわけで、これには困っています。

一応、純正品の変換コネクタは存在するようですが、どうもこれ、両端が「従来GBAオス端子 - GBmメス端子」という形状になっているらしく、これではブートケーブル(従来GBAオス端子)は接続できません。サードパーティから「従来GBAメス端子 - GBmオス端子」の変換コネクタが出てくれればいいのですが……。

posted at 2005-10-23 | Permalink

ゲームボーイアドバンス用プログラム開発はじめました (2005-10-18)

ここのところ非常に忙しく、平日はたいてい終電、休日も出勤するか寝ているかのどちらかという不毛な毎日。Symbian OS上でのプログラミングは正直おなかいっぱいという気分。

そんな中、先月はついつい「ゲームボーイミクロ」を買ってしまいました。おまけに「ファミコンミニ・スーパーマリオブラザーズ」と「Dr.MARIO & パネルでポン」も買ってしまい、すっかり任天堂に踊らされている状態です。忙しい身には電源オンですぐ起動という手軽さがありがたいところ。寝る前のちょっとした時間などにすぐ遊べるのはいいですね。

そんなわけで、8-1がクリアできなかったり11連鎖を出してみたりしているわけですが、ふとゲームボーイアドバンス(以下GBA)上でのプログラム開発をやりたくなりました。GBAプログラムの個人レベルでの開発というのは、初代GBA発売以降から世界中で活発に行われていて、フリーの開発環境や各種資料なども豊富に存在しています。実は私も3年前くらいにちょっと手を出してみたことがあるのですが、短いプログラムを作って動かしてみてひとしきり遊んだ程度です。

ちょうど先週の土日は休みがとれたので、昔に書き散らしたソースコードを整備しながら、ちょっとしたゲームの作成を始めてみました。「まずは習作として単純なゲームを……」と思いつつも「せっかくGBAで作るんだから、GBAの機能を駆使しないとなー」などと矛盾したことを考えながら、今作っているのはこんなゲーム。

GBAゲーム・開発中画面1 GBAゲーム・開発中画面2

かつて「マイコンBASICマガジン(通称: ベーマガ)」などの雑誌投稿プログラムで飽きるほど見かけた「キーを押すと上昇・離すと下降・壁に当たらないように進む」というワンキーゲームです。ゲームプログラムを作ったことがある人なら、誰しも一度くらいは作ったことがあるんじゃないかと思います。

GBAらしい唯一のフィーチャーは、自機(?)の上昇・下降の角度に応じて画面全体が傾く(回転する)という点です。以前やはりベーマガで見かけた記憶があるのですが、この手のワンキーゲームで「見た目を3D視点にして新感覚に」というアレンジを施した作品がありました。このゲームもそういう方向性を狙って、目先を変えることで新鮮な感覚を得られないものかと目論んでいたわけですが、実際に動き始めたゲームを見てみると……うーん、試みが成功したとは言い難いかな……。

ま、このゲームはあくまでGBAプログラミングの習作ということで、さっさと完成させて終わりにしましょうかね。暇ができたらまた何か作ってみたいところです。

posted at 2005-10-18 | Permalink

「Rev.」「Dyna-Mo」更新 (2005-08-01)

iアプリ用ゲーム「Rev.」 「Dyna-Mo」を更新しました。

Rev. 新盤面追加

Rev. 新盤面"ROUND" Rev. 新盤面"CLOVER"

「Rev.」の方は新盤面を2つ追加しました。"ROUND"は丸い形をした盤面です。あまり「丸」というような形に見えませんが、外周には「辺」の部分が存在せず、ほとんどの部分が「隅」になっています。もう一つの"CLOVER"は(三つ葉の)クローバーのような形をした盤面です。こちらもやたら「隅」が多い盤面になっています。

Dyna-Mo 新ステージ追加

Dyna-Mo 新ステージ"The Flying Boards" Dyna-Mo 新ステージ"Ripples"

「Dyna-Mo」の方は新ステージを2つ追加しました。動画の内容は、まあスクリーンショットを見ればだいたい想像はつくでしょう。

実は、全7ステージ分の動画を実装するにあたって、まだ1枚も画像ファイルを使用していなかったりします(すべてDoJaのプリミティブな描画メソッドを使用)。上の「地上絵」も、線描画のメソッド(Graphics#drawPolyline)のみで描画しています。(ちなみに頂点数は140個程度)。

posted at 2005-08-01 | Permalink

『Symbian OS C++ 実践開発技法』読書メモ (2005-06-30)

Symbian OSについて日本語で書かれた情報源は非常に少ないわけですが、そんな中『Symbian OS C++ 実践開発技法』という書籍が発売されました。とりあえず、流し読みして気づいたことなどをメモ。

CBaseクラスの定義について(p.6)

e32base.hを見ると、CBaseがコピーコンストラクタと代入演算子をprivate宣言していることが分かる。これは、クラスのクライアントが、間違ってそのクラスのオブジェクトの浅いコピーを作ったり、そのオブジェクトに代入したりするのを防止する手段として、一般に使われているものだ。

このテクニック自体は『Effective C++』にも載っている有名なものですが、大元のCBaseクラスでこれをやっているとは知らなかった。今までわざわざ自前でprivate宣言していました。

書き換え可能な静的データ(p.253)

以前の記事「Symbian C++開発・DLL内のstatic変数(2005-04-01)」に書いたこととほぼ同様の内容。やはり誰もがはまる落とし穴なのでしょうか。

(余談ですが、このサイトのアクセスログを見ると、"ERROR Dll has initialised data"といった検索ワードで検索している方がちらほら見受けられます)

便利なASSERT定義(p.299)

#ifdef _DEBUG
#ifdef ASSERT
#undef ASSERT
#endif
#define __ASSERT_FILE__(s) _LIT(KPanicFileName, s) _LIT(KPanicFileName,s)
#define __ASSERT_PANIC__(l) User::Panic(KPanicFileName().Right(12),l)
#define ASSERT(x) { __ASSERT_FILE__(__FILE__);
        __ASSERT_DEBUG(x, __ASSERT_PANIC__(__LINE__) ); }
#endif

このASSERTを使うと、パニックカテゴリ文字列が「ソースファイル名(の末尾12文字)」で、パニック番号が「(ひっかかったASSERTが存在する)行番号」のパニックを発生します。要は「ソースファイル名と行番号が表示されるASSERT」というわけです。「便利」といっても、他環境での一般的なASSERTでは当たり前のことではありますが……。

なお、上記のコードは本に記述されている内容をそのまま引用したものですが、ASSERTマクロの中身がマルチステートメントになっているのはまずいのではないかという気がします。例えば、以下のようなケースでコンパイルエラーになってしまいそうです。

if (...)
    ASSERT(...);
else
    ...

ちなみに、私の場合はこんな感じのASSERTマクロを使っています。

#define WIDE_LIT(lit)       L ## lit            // 文字列リテラルをワイド文字にする
#define WIDE_MACRO(macro)   WIDE_LIT(macro)     // 文字列マクロをワイド文字にする
#define MY_ASSERT(exp)  __ASSERT_DEBUG(exp, \
    User::Panic(_L("" WIDE_MACRO(__FILE__)).Right(16), static_cast<TInt>(__LINE__)));

ワイド文字がらみでプリプロセッサでいろいろ小細工をしていますが、やっていることは似たようなものです。

posted at 2005-06-30 | Permalink

Series 60開発・エミュレータ上でパニック情報を表示させる (2005-06-08)

パニック情報とは?

702NKでの開発で困っている点として、「パニック発生時にパニック情報が表示されない」ということが挙げられます。Symbian OS上での開発(デバッグ)において、パニック情報は非常に重要なので、これには悩まされています。

パニック(Panic)というのは、復旧不可能なエラーが発生した際にプログラムの動作を即座に停止させるものです。パニックの際には「パニックのカテゴリ(を示す文字列)」と「パニック番号」の2つの情報が得られます。システム側で発生したパニックであれば、これらの情報からパニック発生の原因がある程度わかります。また、アプリケーション側でも明示的にパニックを発生させることができるので、アサーションを行う際などにも使われます。

いずれにしても、パニック情報はエラーの原因を究明する際の足がかりとなる重要な情報です。ですが、前述のとおりパニック情報は表示されず、パニック発生時には以下のような表示になってしまいます。

パニック発生時の画面(パニック情報なし) 表示されるのはパニックが発生したアプリケーション名のみ。

これはエミュレータでの画面ですが、実機ではメッセージの表示すらなく終了してしまいます。

エミュレータ上では解決

そんな中、先日『Symbian OS/C++プログラマのためのNokia Series 60アプリケーション開発ガイド』(長い題名だ)のp.71にこんなことが書かれてあるのを見つけました。

パニック番号やテキストによるコンテクストメッセージの詳細を(中略)表示させるには、ErrRdという空のファイルを、\Epoc32\wins\c\system\bootdataフォルダに作成する必要がある。

さっそく記述に従ってファイルを置いてみたところ、以下のようにパニック情報が表示されるようになりました。

パニック発生時の画面(パニック情報あり) パニックカテゴリ("USER")とパニック番号(130)が表示される。

ちなみに、「USER 130」のパニックは、配列クラス(RArray)に対して範囲外のインデックスを使ってアクセスしようとした際などに発生します(詳しくはSystem panic referenceをご覧ください)。こういった情報があるかないかによって、デバッグの効率が大きく影響されることは想像に難くないと思います。

あとは実機上で……

これでエミュレータ上ではパニック情報がわかるようになったので、あとは実機上でなんとかなればいいのですが……。ちなみに、実機上でも同じようなこと(c:\system\bootdataフォルダに空のファイルErrRdを作成)をやってみたものの、結果は変わらず。何か方法はないものか。

posted at 2005-06-08 | Permalink

Series 60版「Rev.」開発中 (2005-06-01)

Series 60用「Rev.」開発中画面

せっかく購入した702NKですが、ここのところ時間がなくて放置状態です。月々の維持費がかかるおもちゃなので、遊ばせておくのはもったいない(高々月500円程度ではありますが)。

そういうわけで、Symbian OS・Series 60版「Rev.」の開発を再開しました。手始めに、Symbian OSのアプリケーションアーキテクチャに慣れる意味も含めて、画面まわりを手早く実装してみました(スクリーンショットはエミュレータ上のものです)。当初はオフスクリーンバッファを使ってちらつきを防ぐ処理を入れる予定でしたが、スクリーンに直接描画しても実機でほとんどちらつきが見られないので、とりあえずはこのままにしておきます。

盤面の描画以外の部分では、Symbian OSやSeries 60プラットフォームが用意している機能を活用しています。現在のスコアの表示にはナビゲーションペインのラベル表示を流用していますし、勝敗結果の表示にはノート(Windowsにおけるダイアログボックスに相当)を使っています。また、メニューまわりの処理はすべてアプリケーションフレームワーク任せで済ませています。使える部品が揃っていると開発が楽です。

残る最大の難関は、コンピュータの思考ルーチンです。指手を決めるための盤面評価処理は別スレッドで行う必要があるわけですが、マルチスレッドプログラミングとなるとなにかと面倒です。バグを入れ込まないように気をつけないと。

posted at 2005-06-01 | Permalink

動画パズルゲーム「Dyna-Mo」公開 (2005-04-13)

Dyna-Mo タイトル画面

iアプリ用動画パズルゲーム「Dyna-Mo」を公開しました。

以前の記事(2005-03-06)でちょっと紹介してから早1か月。「動画でジグソーパズルゲーム」のゲームの枠組みは簡単にできあがったのですが、表示する動画のネタを考えるのにえんえんと苦労していました。ようやく5種類ほど動画を用意できたので、ひとまず公開することにしました。

実機での動作確認をまったく行っていないので、まともに動作するのかどうか心配だったりします。ゲームの性質上、描画処理の負担が大きいので、なるべく描画性能の高い端末でプレイすることをお勧めします。

スクリーンショット

Dyna-Mo プレイ画面1 ゲーム開始直後です。

Dyna-Mo プレイ画面2 徐々にピースをそろえていって……。

Dyna-Mo プレイ画面3 完成!

posted at 2005-04-13 | Permalink

Symbian C++開発・DLL内のstatic変数 (2005-04-01)

「DLLは書き込み可能なstaticデータを持たない」

702NKを購入したので、さっそく実機で自作プログラムを動かしてみたいところです。なので、以前iアプリのJavaで作った「Rev.」をSymbian OSに移植してみることにします。 以前の記事(2005-02-22)に書きましたが、ゲームのコア部分はすでにSymbian C++で実装していて、表示回りはコンソールアプリケーションとして実装するところまではできています。

しかしここで問題発生。エミュレータ向けのビルドは正常に完了し、エミュレータ上では正常動作するのですが、実機向けのビルドが成功しません。以下のようなエラーメッセージが出てしまいます。

ERROR: Dll 'REVENGINE.DLL' has initialised data.

("RevEngine.dll"は、ゲームのコア部分を独立させたDLLです)

これはすなわち「DLLは書き込み可能なstaticデータを持たない(『Symbian OS C++プログラミング』p.41)」という制限にひっかかったということです。というわけで、プログラム内で静的変数を使っていないかチェックしてみますが、それらしい箇所は見つかりません。静的データ領域はたくさんありますが、どれも"static const"で宣言しているので定数領域に配置されるはずなのです。ところが、mapファイルを見てみると、dataセクションにもbssセクションにも領域がちょっとずつ割り当てられている模様。おかしいなあ。

constの落とし穴

あちこち調べたところ、どうも以下のコードがまずかったようです。

static const TPatternBits* table[] =
    {
    &KPatternBitsSquare,
//  (中略)
    };

ポインタ変数に対してconstを指定する場合、"const"を記述する位置によって意味がまったく変わってきます。上記のコードだと、「ポインタ変数の指す先がconst(ポインタ変数自体は非const)」という意味になってしまいます。ポインタ変数自体をconstにするためには、以下のように"*"の右側に"const"を記述しなくてはなりません。

static const TPatternBits* const table[] =
    {
    &KPatternBitsSquare,
//  (中略)
    };

ところが、この問題を修正してもまだビルドに成功しません。仕方がないので、mapファイルを見ながら怪しげなテーブルを部分的にコメントアウトしてビルドを繰り返したところ、ようやくもう一つの原因を発見できました。

static const TPoint KInitPointsSquare[] =
    {
    TPoint(11, 5),
    TPoint(13, 5),
    TPoint(13, 6),
    TPoint(11, 6),
    };

要するに、コンパイル時に値が確定しない(実行時にコンストラクタが動作したときに初めて値が確定する)ため、定数領域に確保されないわけです。(ちなみに、"TPoint"というのはSymbianで用意している座標クラスです)

これらの問題を修正して、ようやくビルドが成功するようになりました。やれやれ。

エミュレータの落とし穴

それにしても、エミュレータ用と実機用とで実行バイナリが異なるというのは頭の痛いところです。エミュレータ向けのビルドを行うとWindows用のバイナリが生成されるわけですが、WindowsのDLLでは書き込み可能な静的領域うんぬんといった制限はないわけで、正常にビルドが完了してしまいます。そして、(実機環境ではビルドすらできないようなプログラムでも)エミュレータ上では何の問題もなく動作してしまうわけです。

まあ、今回は実機用のビルド時に問題が発覚したのでまだましなのですが、エミュレータと実機との違いによる落とし穴には、今後も幾度となくはまりそうです。

後日談

一連の問題が収束した後で、こんな文書を見つけました。

How can I find the "uninitialised data" in my DLL?

まさに今回の問題にそのまま当てはまる話です。最初からこれを読んでおけばよかった。英語だからといってスルーしていてはいけませんね。

というわけで、Symbian開発関連の(英語の)ウェブサイトをいろいろ回っていると、「.mmpファイルに"EPOCALLOWDLLDATA"の指定を追加すれば、DLL内の書き込み可能staticデータが使えるようになる」という情報を拾いました。調べてみると、こんな文書が見つかりました。

Symbian OS support for writeable static data in DLLs (PDF)

と思いきや、この機能をサポートしているのはSymbian OS v8.0bとv8.1bのみとのこと。702NK(Nokia 6630)のOSのバージョンはv8.0aなんですね……。

"v8.0a"と"v8.0b"なんて、いかにもマイナーバージョンアップのような感じなのに、そんなに大きい変更があるものなのか? と思って調べてみたところ、どうやら"a"と"b"とでカーネルが違うのだそうで。

Symbian OS Version 8.0 functional description (日本語版)

結論としては、「702NK(Nokia 6630)用アプリケーションを作るのであれば、DLL内の書き込み可能staticデータはやっぱり不可」ということになるようです。

posted at 2005-04-01 | Permalink

Vodafone 702NK 購入 (2005-03-27)

先日「Vodafone 702NK」をついつい買ってしまいました。以前の記事(2005-02-22)で「Symbianプログラムの動作環境として1台ほしい」と書いたものの、「これだけのためにVodafone回線の新規契約をするのも……」と思って二の足を踏んでいました。しかし、Vodafoneには「グローバルコールプラン」という「海外のみで使用するならば月額基本使用料567円」の格安料金プランがあると知り、これはまさに私の目的にうってつけだと思い、購入した次第です。ちなみに、このグローバルコールプランの新規受付は3月末にて終了するとのことで、これに背中を押されて購入に踏み切ったようなものです。

購入した702NKはプログラム開発中心に使っていくことになると思います。そういうわけで、今後このサイトではSymbian開発・Series 60開発についての技術的Tipsなどについても書いていく予定です。また、MIDPのJavaプログラムも作ってみたいと思っています。

posted at 2005-03-27 | Permalink

動画ジグソーパズルゲーム開発中 (2005-03-06)

動画ジグソーパズルゲーム・開発中画面

現在、iアプリでこんな感じのジグソーパズルゲームを作っています。普通のジグソーパズルと異なるのは、絵がリアルタイムで動くという点です。DoJaのAPIリファレンスを眺めていて、ちょっとひらめいたのでなんとなく作ってみたところ、ゲームの根幹となる部分はあっさりできてしまいました。せっかくなので適当に作りこんで公開しようと考えた次第です。

「動画でジグソーパズル」というアイディアをもとにしたゲームは昔からけっこうあるようです。私が知っているのは、『きね子』というファミコン(ディスクシステム)のゲームです。残念ながら実際にプレイしたことはないのですが、いかにもビデオゲームならではのアイディアだなあと感心した覚えがあります。

それはさておき、現在作りこみの最中なわけですが、残作業のうちでもっとも大きいタスクが「動画の作成」だったりします。動画といっても、iモーションみたいな「本物の動画」を使うわけではなく、プログラムでちまちま描画してアニメーション表示を行うわけです。

というわけで、その動画のネタを考えるのに苦労しています。なにせ私は絵を描くのが苦手。よって、必然的に「線描画」とか「矩形描画」とかの単純なグラフィック描画によるアニメーションばかりになってしまいます(ラインアートとか)。この手のゲームでは、絵の良し悪しがゲームの出来を左右するので、もうちょっと見栄えのする絵を用意したいところなのですが……。

冒頭のスクリーンショット内の動画は、ブロック崩しをモチーフにしたものです。これにしても、見事に矩形と線だけで構成されていて、単調な画面であることは否めません。このゲームの場合は、スクリーンショットよりも動いている画面の方が重要だ! と強弁してみても、しょせんブロック崩しなのでそれほどダイナミックな動きはありません。もうちょっと気のきいた動画ネタを用意したいところなのですが……。

まあ、動画ネタは後からでも追加できるので、さっさと仕上げて近いうちに公開したいなと思っています。

posted at 2005-03-06 | Permalink

Vodafone 702NK (2005-02-22)

ちょっと今さらな感じはありますが、昨年末に発売された端末「Vodafone 702NK」はなかなか面白そうです。この端末、基本的にはNokiaのSymbian OS搭載端末「Nokia 6630」と同じものだそうで、ユーザーが自由にネイティブアプリケーションをインストールできる点が(ごく一部の人たちの間で)人気を呼んでいるようです。Symbian OS搭載端末にもいろいろありますが、702NK(Nokia 6630)は「Series 60」というユーザーインターフェースを採用しています。Nokiaの端末ではすでにさまざまな機種でSeries 60を搭載しているため、アプリケーションも豊富に出回っています。残念ながら、702NKにはSymbianの認証を受けたアプリケーションしかインストールできないようなロックがかけられているらしいのですが、回避策もあるとのこと。

開発者側として面白そうな点は、ネイティブアプリケーション開発用のSDKも無償で提供されていることです。制限だらけのiアプリなどとは比べ物にならないほどいろんなことができそうです(その分、ウィルスだのトロイの木馬だのも開発されてしまうわけですが)。

個人的に、Symbianプログラミングの勉強のために、実機で自作プログラムを動作できる環境がないものかと思っていただけに、ちょっと興味があります。ただ、これだけのためにVodafone回線の新規契約をするのもなあ……。端末自体の値段は(型番を見てもわかるように)ローエンドの位置づけなので安価ではあるのですが。

まあ、買うか買わないかはさておき、開発環境をインストールするのは無料です。手始めに、以前iアプリのJavaで作った「Rev.」をSymbian OS向けにポーティングしてみることにします。もっとも、まだSeries 60プラットフォームのGUIまわりはよくわからないので、とりあえず表示回りはコンソールアプリケーションにして、内部のエンジン部分だけSymbian C++で実装しています。

エミュレータ上でのスクリーンショットを載せたいところですが、日本語版Windowsの環境ではエミュレータ上でコンソールアプリケーションの文字が正常に表示できないらしく、表示が乱れてしまっています。何か回避策はないものか。

posted at 2005-02-22 | Permalink

AH-K3001Vの待受画面にメモを表示 (2005-01-20)

今時の機種なら簡単にできそうなことですが……

タイトルのとおり、AH-K3001Vの待受画面上にちょっとしたメモを常時表示したいと思っているわけです。PCのデスクトップ上に「付箋紙」風のメモを表示するようなプログラムがありますが、それの待受画面版みたいな感じでしょうか。

Javaプログラムが動く端末ならば、いわゆる「待受アプリ」で実現できるでしょう。また、端末自体にそういった機能を持っている機種もありそうです。しかし、AH-K3001Vにはどちらもありません。でも、どうにかして実現できないものか。

力技で解決

で、考えたのが、「壁紙画像の上にメモ文字列を描画した画像を作成する」という方法です。もちろん、こんなことはAH-K3001Vでは不可能なので、Webサーバにやらせます。Webサーバ側にベースとなる壁紙画像を用意しておき、さらにメモ文字列を受け取るCGIプログラムも置いておきます。そして、AH-K3001VのOperaからそのCGIにアクセスしてメモ文字列をPOSTして、そのタイミングで壁紙画像へメモ文字列を書き込むという算段です。

メモ文字列をやりとりするCGIプログラムは簡単に作れますが、画像に文字列を描画するのはどうすればいいでしょうか? ここは安易にImageMagickを実行することにしました。ImageMagickには大量のオプションが用意されていて、様々な画像操作が可能です。せっかくなので、単に文字列を描画するだけではなくて、ちょっときれいに仕上げてみることにします。今回は、以下のようなオプションを指定してみました。

convert base.png -region 224x160+8+32 -colorize 50/40/30 -raise 2x2
 -fill white -pointsize 14 -font kotori.ttf -draw @cmd.txt wall.png

base.pngはベースとなる壁紙画像で、wall.pngが生成される壁紙画像です。今回は文字列描画用のフォントとして「ことり文字フォント」を使わせてもらいました(kotori.ttf)。

なお、cmd.txtには、"-draw"オプションで描画を行うためのコマンド文字列をあらかじめ格納しておきます。

text 2,0 "
[予定]
2005-01-21: 飲み会
2005-01-24: 納品
[メモ]
・終電の時刻は23:53"

見てのとおり単純なコマンド文字列なので、CGIプログラムで取得したメモ文字列から簡単に変換できるでしょう(ただし、cmd.txtはUTF-8エンコーディングにしておかないと、和文を正常に表示できないので注意が必要です)。

実際の描画例を見てみましょう。

画像. ベースとなる壁紙画像 こんな画像から……(base.png)。

画像. メモ文字列を描画した壁紙画像 こんな画像が生成されます(wall.png)。

あとは、生成された画像をダウンロードして壁紙に設定すればOKです。これで待受画面へのメモ表示を実現することができました。

使いづらい……

しかしながら、このシステムを実際に使ってみるといろいろと問題点が出てきました。一番の問題点は、壁紙画像をダウンロードして保存する際に、AH-K3001Vでは「上書き」ができないことです。当初の目論見では、「wall.pngを壁紙に設定している状態で新しいwall.pngをダウンロードして上書きすれば、待受画面も更新されるだろう」と思っていました。しかし、上書きができないということにより、保存した後に壁紙の設定を再度行わなくてはならないわけで、この作業はかなり面倒です。

また、上書きができないということは、以前の壁紙ファイルがずっと残っていくことを意味します。AH-K3001Vのデータフォルダの容量はかなり少ない(1MBytes程度)ので、こまめに消していく必要があります。これもまた作業の面倒さに拍車がかかる要因となっています。

というわけで、せっかく仕組みを作ったものの、現在はお蔵入り状態になってしまっています。気軽にメモ内容の更新ができないようでは、やはり更新がおっくうになってしまいますね。

posted at 2005-01-20 | Permalink

© 2004-2008 ENDO