Android:Common Source Code Project

なんでAndroidでNDK(C++)で開発できるようにしようとしていたかというと…Common Source Code Project のエミュレータを動作させたかったのです!

TAKEDA, toshiya’s HOME PAGE
http://takeda-toshiya.my.coocan.jp/

以前、M5Stack で動かしてみたことがありました。

M5Stack:Common Source Code Project
http://shikarunochi.matrix.jp/?p=3006

Androidは、M5Stackとはメモリ量は桁違いなので、省メモリのための修正を行わなくとも、画面描画&ファイル入出力部分だけ変更すれば、エミュレータ部分のソースは変更なしで使えるはず!

ということで、Native Activityをベースに作り始めました。

ndk-samples/native-activity/
https://github.com/android/ndk-samples/tree/master/native-activity

Javaソース全くなしで、C++だけでAndroidプログラムを作れるとは知らなかった。(とはいえ、内部的には呼び出し用Javaを生成しているっぽい?)

Android Studio、エミュレータ動作&デバッグ実行できるのは強いですね。少々動作は重いですが、printfデバッグすることになると思ってたので、超快適。

CommonSourceCodeのエミュレータロジック部分は、ホント何も触らず、そのままで全然コンパイルエラー出ませんでした。すごい移植性です。

Androidへの移植に関しては、M5Stackの時と同様、たなむさんのページを参考にしました。このページが無ければ、まず、移植に手を付けることが不可能だったと思います。

tanamの日記:Qt 4.8 和製MESS その1
https://tms9918.hatenablog.com/entry/2013/05/19/233702

mainの起動ロジックと、画面描画、ファイル入出力を作成して、一通り完成。今回もまずはSC-3000から挑戦しました。

起動!…エラーは出ずに、動作はしているっぽいのですが、画面が出力されない…。


SC-3000のCongoBongを起動していたので、VRAMをテキストで見えるように、特定の濃さ以上を”1″で、画面の一部分を出力してみたところ

…これ、動いてますよね…!明らかに「g」が出てますよね!エミュレータ自体は動作して、内部的には画面描画できているということ…!

あとは、実画面に描画できればOKなのですが…。うーん、OpenGL全然わかっていないので、僕の書いた画面描画処理がまるでダメのようです。先は長そう。


ちなみに、エミュレータ動作させるときのゲームイメージファイルは、ファイルをエミュレータ画面にファイルをドラッグ&ドロップすると
/sdcard/Download にコピーされるのでそこから読んでます。

ストレージ読み込むには、Manifest ファイルへのpermission追加が必要なのですが、今はそれだけでなくて、Android(エミュレータ)側でのアプリごとの許可設定が必要です。以前のAndroidだと必要なかった部分なので知らないとハマりそう。

/sdcard/Download にコピーされたファイルを、他のところに移動するにはどうすればいいのかわからなかったので、とりあえずはフォルダ決め打ちで作ってます。

エミュレータで他のフォルダに入れたい場合は、ファイラー的なやつをインストールして操作するとか、ADBを使ってPCから入れるとかなのかな?まあそれはのちのちで。


うーん、あとはこれを、ホントの画面に出せれば…。

画像データを画面に出力するの、M5StackのArduinoであれば、drawBmp使って一発なのですが、OpenGLESではそうはいかないようで、いろいろ手順が多いです。サンプルいろいろ見てみたのですが、どの命令が何をやっているのか、そもそもどこで描画されているのかすら全くわからん状況。OpenGL知識が全然ないので読み解くのが大変です。やりたいことはちょっとだけなのに、準備やらなんやら、やることが…多い!

OpenGLについては、ここが順を追っててわかりやすかったです。

独学で 1 ヶ月間 OpenGL を学んで得た基礎知識のまとめ ~ 2D 編 ~
http://tkengo.github.io/blog/2014/12/20/opengl-es-2-2d-knowledge-0/

概要は分かった気がしました。でもそう簡単に画面が表示できるわけではなくw


そしてついに判明!「NDKで2D画面描画するなら、OpenGLのテクスチャに書き込んで表示」って思いこんでいたのですが、別にそんなことなく、OpenGL使わなくても描画可能なのだった!

いったん、さよなら、OpenGL!概要が学べたのでまあOK!いつの日か、また、再挑戦したいと思います。


NDKでの2D画面描画は、NativePlasmaサンプルに答えがありました。

ndk-samples/native-plasma/
https://github.com/android/ndk-samples/tree/master/native-plasma

これ、Plasma描画のロジックが複雑に見えて、最初に見たとき「難しそうだなー」と避けてしまっていたのでした。しかしそこはSampleの本質ではなかった。

ANativeWindow_setBuffersGeometryでANativeWindow_Bufferを生成して、生成したバッファを buffer->bits で取得。あとはここに書き込めばOK!

出たー!!!感動!!!!Dot by Dot なので画面小さいー!

エミュレータ何度も移植してますが、やはり最初に画面が出た時には感動です!!!!!

この方式だと、拡大を自分で行う必要ありますね。実画面の縦横サイズが取得可能なので、それにあわせてうまいこと拡大してやればやればよさそう。画面のドット小さいので適当な拡大処理でも問題なさそうです。

ひとまず、縦横4倍で拡大。

バッチリじゃないか!…なんか変だ!上下逆だ!

気を取り直してもう一度。

今度こそバッチリ!

なぜか、スタートボタンが押されて、ゲームが開始になってる…?キー状態の初期化漏れでなんかキー入力イベントが発生してるのかな…。今の段階ではまあヨシ!


実機でも動きました!すばらしーい!


これですね、エミュレータ側のソースには、ほぼ手を入れてないんですよね。

つまり、SC-3000用のCMakeLists.txtを、MZ-700用に書き直して、ちょっとソース修正すれば…

MZ-700も、すぐ動く!


イベントの取得もすでにサンプルで実装されてて、画面タッチやキー入力の拾い方もわかりました。

実機AndroidにBluetoothキーボードを接続してイベント確認してみると、KeyDown/KeyUPとキーコードが取得できてます…!これ、コードを変換してエミュレータに渡してあげれば、キー入力可能ですね。

エミュレータ側とAndroid側でキーコード体系が違ってるので、根性でチェックしました。

とはいえ「0~9」とか「A~Z」はコード上で順番に並んでるので、そこまでの根性は必要なかったですw

結局最後は公式ページで答え合わせなのですがw 最初からこれがあることに気が付いていれば…。

Android Developers NDK リファレンス Input
https://developer.android.com/ndk/reference/group/input?hl=ja

日本語キーボードで調整したので、英語キーボードだと変になるかも?

エミュレート元となるホビーPCは、JISっぽい配列のことが多いので、キーボードの記号表示に関わらず、日本語キーボードの並びにしておくのが良いかなー、と思いました。

同時押しの必要なシフトキーやCtrlキーはちょっと特別扱いしてあげる必要ありますね。

LEVEL-2 BASICを起動してプログラム入力もできました!シフトキーやカーソルキーも使えます。

ESCキーはAndroidのほうが先に拾ってしまうので使えないです。STOPキーとかBREAKキーに割り当てようと思ってたのでちょっと悩みますね。割り込みする方法もありそうな気はする。

ソフトウェアキーボードにも対応したいところなのですが、NDKからどうやって連携すればよいのやらまだわからないです。あと、SHIFTのKeyDown/KeyUpは取得できなさそうな予感ありますね。カーソルキーも足りないし。ちゃんと対応するなら。ソフトウェアキーボード自作するしかないかも。

USBキーボードでも入力可能でした。USB接続の小型キーボードとかあればいいのにな。


まだ、ファイル選択とか全然作ってなくて固定ファイル読み込みになってるので、そのあたり作っていきたいと思います。ファイル選択ダイアログも、NDKからAndroid標準のやつ呼び出したいなーと思ってるのですが、そんなことがそもそもできるかどうか怪しいですね…。


動作速度はSC-3000/MZ-700の実機レベル出てると思います。とはいえ、まだ、バックグラウンドに行ったらリセットかかったりするので普通には使えないですw

ソースの公開はもうちょっと整理してからの予定ですー。