最近はraspberrypiをいじくりまくってた。
*
そのかいあって、常にxlink kaiを動かすraspberrypiがほぼできた。
私の作ったプログラムにより、raspberrypi側の無線LANアダプタを自分で操作しなくても、MACアドレスに対応したPSPのネットワークに自動接続できる。
また、起動時にメモリ上にSquashFSのrootfsを配置する形にした。
これにより、起動後はSDカードを取り外しても動作し続けることができる。
raspberrypiにSDカードは完全には差さらず、出っ張るためうっかり触って抜けてしまったり、カードやスロットなどが破損したりということが起きかねない。
それに、マウントした状態で取り外したり、電源コードを抜いたりすると、ファイルシステムが破損する可能性だってある。
実際、それでSDカードのファイルシステムの再構築が必要になったことが何度かある。
そもそもraspberrypiに電源スイッチなどないし、普通に終了するためには何らかの方法でログインし、shutdownコマンドを叩かなければならない。
それが電源コードを抜いて電源を落としても多分大丈夫になった、というのは大きい。
*
私の作ったプログラムはもう少し修正する必要がある。
周囲のアドホックネットワークの検索処理を実行する間隔が短すぎて、他の通信に悪影響が出てしまっている。
しかし、どうスリープしたものか。固定時間か、一定間隔毎に処理するように計算してスリープするか。
昨日、いつにも増してやる気が出ん、だるいと思ったら微熱が出ていた。
*
それでも、なんとかパッケージ情報に記述したゲームについての情報を取り出す処理は追加できた。
月曜には、ゲームのロード処理をメイン関数に追加したいところ。
明日はraspberrypiをいじくるとしよう。
ショートカットファイルからゲームの参照情報を取り出すのはできた。
*
まぁ、記述内容がベースシステムの参照情報とほぼ同じだから、処理をコピーして少し修正して作ったんだけど。
次はパッケージ情報にゲームについての情報を追加して、それを取り出す処理かな。
こっちも、ベースシステムの情報と大体似たような感じだから、処理をコピー、修正して作れば楽だろうな。
その取り出した情報を使ってゲームをロードし、ベースシステムの実行時に引数として渡す、というところまで明日中にできればいいんだが。
というわけで、0.5.0できた。
*
ベースシステムの起動までできたところで0.5.0とした。
この次はゲームの生成、破棄とゲームの制御となるわけだが、どうするかちょっと考え中。
昨日の日記書いてた時には、ゲームの生成や破棄はベースシステム内でやろうかと考えたりしていたのだが、それはあまり望ましくない気がする。
ゲームの生成や破棄は、色々な実装方法が思い付くような処理ではない。
簡単に言えば、newとdeleteなわけだ。
ならば、わざわざベースシステム側にそれを任せることもない気がする。
そうすれば、ベースシステム側が設定ファイルを解析したり、モジュールをロードしたりする必要はなくなる。
*
どちらにせよ、まずはショートカットファイルからゲームについての情報を取り出す処理を追加するところからだろうか。
どこに記述したところで、その処理自体は変わらないだろうし。
モジュールのロード、ロードしたモジュールからの関数取得も完了。
*
これを使ってベースシステムの起動をするわけだが、それにはダミーのベースシステムを作る方が先か。
中身空っぽでいいから、これはさっとできるだろうな。
次はどうするべきかな。
ベースシステムの実行の次、となるとゲームの起動だろうか。
それをするとなると、ベースシステムから設定ファイルを読んだりモジュールをロードしたりする必要があるだろうから、ライブラリを作る必要がありそうだなぁ。
*
3連休中、raspberrypiをいじくっていた。
とりあえずの成果として、比較的簡単にraspberrypi用のgentooのrootfsを生成できるようになった。
私は出来合いのカーネルとか使いたくないので、というよりカーネルの機能を増やしたい時とかに備えてカーネルは時前でビルドしたいので、その辺は自分でやる必要があるけど。
で、raspberrypi版のxlink kaiとかあったんで、xlink kaiを使うためだけのraspberrypiを作れないか画策中。
xlink kaiは昔windows版を使っていたことがあったが、PSPとパソコンをアドホックで接続するために、わざわざパソコン側で操作が必要になるのが面倒だった。
なので、その辺の操作を自動化してみたい。
しかし、アドホック接続についての情報がうまく見つからない。
特定のPSPを示す識別子みたいのってないのかな。
とりあえずテストプログラムのビルドルールを分離させた、のだけど。
*
今のままでは、configure時にテストプログラムについてもビルドするよって指定しないとビルドしてくれない。
確か前は、そういう風になってしまうのを嫌ってテストプログラムのビルド処理を分けなかったんだった気がする。
実際面倒だし、テストプログラムが増えるたびにconfigureコマンドのオプション指定が増えることになる。さすがに嫌だ。
*
依存関係を定義できるようにするべきかもしれない。
このプログラムをビルドする場合、他のプログラムもビルドする、みたいな指定。
そういう仕組みを作れば、あるプログラムに関連するテストプログラムの自動的なビルドも可能になる。
いかんいかん。典型的な三日坊主じゃないか。
*
微妙に詰まっている。
モジュールロード機能のテストコードを作ったので、そのテストを通そうとしたところで困った。
テストでモジュールをロードする必要があるので、そのためのダミーモジュールを作る、それはいい。
しかし、現状ではテストコードにライブラリやらなんやらを関連付けることができない。
なので、どう変えるべきか考え中。
よく考えたら、テストプログラムの在り方がおかしい気がする。
なんらかのプログラムに付随するものとしてるから、テストに対して他の何かを関連付けられないのだ。
最初からテストプログラムも独立したプログラムとして扱えば、こんなことにはならないはずだ。
不要にビルド処理を複雑にしてしまっている雰囲気がする。
改善しなければ。
0.4.0できた。
*
パッケージ情報ファイルとショートカットファイルの内容から、取得できる範囲の情報を取得、表示するところまでやって0.4.0とした。
取得した情報を使えばベースシステムの起動までできるはずだが、そのためには起動するベースシステムも中身からっぽでいいから作らないといかん。
ベースシステムの起動まで作ったら、次はどうしようか。
ベースシステムの中身を詰めていくべきかな。
パッケージ設定ファイルの処理とかもないわけではないけど、これ以上同じような作業はきついものがある。
それに前にも書いた通り、パッケージ設定ファイルは今のところ無くても問題ないのだ。
これ以上モチベーションを落としたくないし。
やはりそう簡単にはやる気は戻らんらしい。
*
リファクタリングしたり、パッケージ情報ファイルを解析したデータからデータを取得する関数を追加したりしてたら、今日中に0.4.0を作りきれなかった。
でもまぁ、パッケージ情報ファイルから名前に対応したベースシステム情報を取得する関数の処理を実装したら、あとはメインの処理を追加して、デバッグ出力を追加すれば完成だろうか。
道筋は見えているので、起きたらさくさくっと完成させたい。
前回から1ヶ月程度か。結構さぼってしまった。
*
作業はしてたんだけど、やはり牛歩。
やる気が出なかったのは、退屈な作業というか、前のバージョンで追加したのと同じような作業をやることになったからだろうな。
前はショートカットファイルの解析で、今回はパッケージ情報ファイルの解析。
必要なことではあるのだが、なんとも退屈な作業だった。
*
パッケージ情報ファイルの解析処理はなんとかできたので、それを使って得られた情報を出力して、それを0.4.0とすることにしよう。
明日にはパパッと作ってしまって、さっさと次に進みたいところ。
ベースシステムの情報は取得できるようになったわけだし、次はいよいよベースシステムの起動に入れるか。
機能を実装したと仮定した処理を記述していっているのだが、つまずいている。
*
パッケージ情報ファイルを読み込む、これはいい。
読み込んだパッケージ情報ファイルからベースシステムの情報を取り出す、これもいい。
この次がしっくりこない。
手順としては、まずモジュールをロードするんだろうけど。
モジュールをロードして、ロードしたモジュールからベースシステムの関数を取り出し、取り出した関数を実行する。
急に処理のレイヤーが低くなるから違和感を覚えるのかしら。
*
ベースシステムの情報を取り出すのではなく、パッケージ情報ファイルの内容とベースシステム名を引数にベースシステムを実行する、の方がいいのかなぁ。
だったら、パッケージのパスとベースシステム名を引数にベースシステムを実行する、の方がよりいいかもしれない。
後のことを考慮すればもっとまとまるだろうか?
パッケージ設定ファイルを読むようにした場合だ。
パッケージ設定ファイルを読み、使用するパッケージのパッケージ情報ファイルを読み、使用するモジュールを列挙、ロードし、ベースシステムを含むモジュールからベースシステムの関数を取り出し、実行。
関数をどう、とかなると低レイヤーすぎるから、ベースシステムの実行として1つの処理にまとめるべきだろうな。
可変長の引数を取り、それを共有ライブラリから取り出した関数ポインタの引数に渡して呼び出す、みたいなことできればいいんだけどそんな簡単にできるだろうか。
0.3.0できた。
*
設定ファイル要素の集合体からショートカットファイルを表す構造体を生成する処理を追加した。
こういう構成の設定ファイルがショートカットファイル、というのを定めたことになる。
とはいえ、ベースシステム実行に必要な要素だけが記述された、暫定的なものだけど。
具体的には、ベースシステムが含まれるパッケージのパスと、ベースシステム名、この2つ。
この2つの情報が記載されたファイルをショートカットファイルとする。
*
次は、その2つの情報を使い、ベースシステムを実行する処理を作ろう。
それを0.4.0とする。
昨日、方針を固めたのはいいのだが。
*
実際に作業を進めようとしたものの、なんだかやりにくい。
どうにも、処理が不完全な感じがある。
ショートカットファイルの読み込み、解析を行なっているものの、最終的に生成しているのがショートカットファイルを表す構造体でないのが分かりにくい原因か。
現状、設定ファイル要素の集合体としてしか扱っていない。
データを取り出すにも、例えばマップにキーに対応するデータが存在するか、とかから始めないといけない。
ショートカットファイルとして正しいのかどうかのチェックを行なっていないから、そのようなめんどうなことになるのだ。
設定ファイルとして文法が正しいか、の次にショートカットファイルとして正しい構成になっているか、のチェックが必要だ。
そうすれば、データを取り出す際にいちいちデータの存在チェックとかやらんで済む。
*
どうしよう、それを0.3.0として作るか?
機能として完全に分離させた方がよさそうだし、そうするかなぁ。
考えて考えて、ようやく方針が固まった。
*
次は、ベースシステムを実行する処理を作る。
ベースシステムとゲームの構成についても変更する。
前のプロジェクトでは、ベースシステムは生成・破棄するもの、ゲームは実行するものという扱いだったが、これは逆にする。
ベースシステムは実行するもの、ゲームは生成・破棄するもの。
ゲームは完全に動作を制御したいのだ。
だから実行する、つまり制御を完全に移す形にするのは適切ではない。
ベースシステムは制御できる形にしたところで、じゃあそれを誰が制御するんだよって話になる。
起動プログラム?そんなめんどうなことはさせたくない。
よって制御を完全に移す形にする。
*
というわけでベースシステムのライブラリをロード、関数を取り出し呼び出す、ということをすることになるが、まずはできるだけ規模を小さくする。
ライブラリを扱うということはパッケージを扱うことになるのだが、本来想定している処理の流れは以下の通りだ。
・パッケージ設定ファイルを読み込み、利用するパッケージ、モジュールを特定
・利用するパッケージのパッケージ情報ファイルを読み込み、ベースシステム実行関数が含まれるモジュールや、モジュールの実体(ファイル名)などを把握
・利用するモジュールを全てロード、ベースシステム実行関数が含まれるモジュールから関数を取り出し呼び出す
こんな感じだが、まずは最初のパッケージ設定ファイルの読み込みを行なわないことにする。
単にモジュールを読み込んで関数を取り出し呼び出すだけなら、パッケージ情報ファイルを読めばできるのだ。
パッケージ設定ファイルは、モジュールの利用する・しないの判断や、依存パッケージの指定、パッケージとセーブデータの関連付け、パッケージやモジュールへのパラメータの設定などなど、より高度なことを行うために必要となるが、最低限の動作では必要ない。
よって、0.3.0ではパッケージ情報ファイルを読み込み、ベースシステムを実行するところまで作る。
*
パッケージ設定ファイルを使う前提で考えていたから、どう進めるべきか決まらなかった感じがある。
もし無理矢理その方向で進めていたら、またしても泥沼の展開だっただろうな。
こんなに長く考えたのだから、それを避けられればいいのだが。
連休を利用して、マシンの環境を構築し直していた。
*
今までは、64bitと32bitの環境を完全に分けて構築していた。
64bit環境で32bitプログラムを動かすために、エミュレーションライブラリを使う必要があるのを嫌ったためだ。
しかしながら、今年の3月頃だったか、エミュレーションライブラリの使用は非推奨になった。
64bit環境で32bitプログラムを動かすために必要となるライブラリも、ソースからビルドできるようになったからだ。
わざわざ環境を作り直すのはめんどうなのでやってこなかったが、2つの環境を扱うのも色々めんどうがある。
例えばパッケージの更新は2環境にそれぞれ実行しなければならないし、設定ファイルなんかも2箇所に置くことになるし、そもそも2環境作ると容量結構取るし。
そんなわけで環境を作り直した。
*
今のところ、問題なく動いているようだ。
skypeなんかは、前は32bit環境で動かしていたため、32bit環境に移行→skype起動、などとするスクリプトとか用意してたんだけど、そんな必要もなくなった。
32bit環境に移行する必要がなくなったからか、前より起動が速くなった気がする。
*
後は、raidをマシンの外に出したいけれど、これをやるとなるとまためんどうそうだなぁ。
封印してある玄箱T4を使おうと思っているが、これを普通に使おうとすると、4つ入るハードディスクのうち、どれか1つの中に環境を構築しないといけないとかいう残念なやつだし。
それを避けるには、外部に環境を作りNFSでマウントして使う、とかしないといけないんだけど、これまためんどい。
ちょうど使ってないraspberrypiもあることだし、それを使おうと考えているが、結局そっちの環境構築も必要になるわけだし。
やるなら次の土日だろうけど、土日で完了できるだろうか。
いや、まず無理だな。できてraspberrypiの環境構築くらいなものだろう。
*
ちなみに環境というのはどれもGentooだ。Gentoo Linux。
柔軟で扱いやすくていい。
しかし、パッケージをソースからビルドする形なので時間がかかりがちなのが難点。
昨日のうちに、0.2.0は完成した。
*
のだが、次はどうするべきか決めかねている。
ベースシステム情報が得られているのだから、ベースシステムの構築・起動をするべきだろうか。
しかし、ベースシステムとゲームをどう連携させるかまだ決まってないしなぁ。
最低限決まっているのはベースシステムを起動した後にゲームを起動させるという順番くらいなものだろうか。
とりあえずをそれをやってしまうべきか?
中身はほぼ空でも。
*
しかし、それはまた行き当たりばったりな感じがするし。
もうちょい考えをまとめるべきだろうなぁ。
ゲームはどこでロードするのか?
今作っている起動プログラムか?もしくはベースシステム内の処理か?
前者の場合、ゲームをロードする必要がある時には起動プログラム側に制御を戻さなければならなくて、なんだか奇妙だ。
後者の場合、起動プログラムからベースシステムをロードして動かし、ベースシステムからゲームをロードして動かす、という流れになって、見た目きれいな感じがする。
しかしながら、ゲームのロードには設定ファイルの読み込みが必要になるものの、そもそもベースシステムからして設定ファイルの読み込みを行なった上でロードするのだ。
設定ファイルの読み込み処理は、普通に考えたら起動プログラム部分に配置することになる。
それをどうやってベースシステムから呼び出すのか?
案はないわけではないが。
モジュールの設定という概念を追加して対応する、というのが今考えている案。
それにより起動プログラム内の関数名を指定し、モジュールロード時に関数を取得、という感じだ。
そんな関数が用意されているかは謎だ。
*
うーん、設定ファイル形式の解析処理はできているわけだから、解析を行なった次の段階、設定ファイルを読み込みデータを取得するための関数を実装すべきだろうか。
だとして、その目的はどうするべきか?
これまでは、それぞれファイルの内容を出力するためにファイル読み込み処理を追加したし、読み込んだファイルから意味あるデータを取得するために解析処理を追加した。
目的を持たない機能追加はその実用性に疑問が残る。
次にやる事を考えれば、ベースシステムの構築なわけで、つまりモジュールのロードや、ロードしたモジュールからの関数取得か。
それらの処理を行なうための入力データとして、ファイルから読み込んだデータを構造体にまとめる、という感じになるか。
*
ということで、目的はベースシステムの構築、もといベースシステムの生成・破棄関数の呼び出しか。
それに付随して、モジュールのロードや、設定ファイルの形式を定めていったりする必要がある。
まずは、すごい簡単なベースシステム生成・破棄関数を持ったライブラリを作るところから始めるべきか?
その辺ができてこないと、設定ファイルにどう記述していいか分からないしなぁ。
ちょっと不調。データ取得関数を一通り追加したところまで。
*
多分、これで設定ファイルに関する関数は一通りできたはず。
あとはこれらを使ってメイン処理を組み立てる。
明日には0.2.0を仕上げたい。
マップ要素まで完了した。
*
後は、解析したデータからのデータ取得関数とか追加しながらメイン処理を組み立てて、0.2.0の完成といったところか。
次はどうするべきか。
設定ファイルからベースシステムについての情報とゲームについての情報を得られるわけだから、ベースシステムの生成だろうか。
ベースシステムはどこで作ろうか。
暫定的なものはcandymakerで作ってしまおうか。
それが、とりあえずはコンパクトでいい気もする。
リスト要素はできたが、マップ要素はまだ。
*
来週には持ち越したくないなぁ。
明日中にマップ要素を完成させて、来週からは作った処理を使って読み込んだショートカットファイルの内容を解析したいところ。
リスト要素の解析は完成には至らなかった。
*
しかしもう少しだ。
残件は複数の要素を含むリストの場合の処理。
要素が単一の場合については完了している。
なので、30分、あるいは1時間もあれば十分できるんじゃないかな。
ソースファイルを要素毎に分けたりしたので、作り切れなかったんだろうか。
ならば、明日中にリスト要素の完成に加えて、マップ要素も完成させてしまいたいところだが。
マップ要素の処理はリスト要素と似ているので、案外早く片付きそうな気がする。
設定ファイルの文字列要素の解析処理はできた。
*
想定よりも時間がかかってしまった感じがある。
しかし、これから追加する予定のリスト、マップ要素でも共通して利用することになる処理も含んでいるので、案外こんなものかもしれない。
明日はリスト要素の対応。
ちゃっちゃと片付けてしまいところだが、現状の文字列要素の処理を別ファイルに分離したりとかそういう作業が必要になってくるので、意外と面倒かも。
*
今回作った文字列要素解析処理のソースはおよそ300行。
全てが文字列要素についての処理というわけではなく、要素共通の処理も含まれているが。
それに比べて、前回のプロジェクトで作ったソースは文字列要素についてのファイルがおよそ150行、要素共通のファイルがおよそ550行。
前回のプロジェクトの要素共通のファイルでかすぎない?と思って中を見てみたら、デバッグ出力に結構行数使ってた。
そういや前回のは、動作確認のために読み込んだデータの内容を1つ1つ出力してたな。
今回はその辺のチェックがテストコードで済むので、こんなでかいデバッグ出力処理はいらないだろう。
というわけで、テストファーストで作るのを試している。
*
前に作ったソースを流用する予定だったけど、テスト駆動開発の練習も兼ねてほぼ1から作っている。
最初にごく単純な処理を実装するために、まずテストを書く。
アサートを先に書き、そのアサートに至るための処理を書いてテストコードとする。
次にそれを失敗するコードを書き、そのテストコードがテストで実行されることを確認する。
次に、テストを通すことだけを目的とした、固定値を返すような不完全な仮実装を行ない、テストが通ることを確認する。
仮実装では不完全ということを示すために、別の入力を行なった場合のテストを書く。
本実装をして、両方のテストが通ることを確認し、完了。
最後の方はなんか違うような気がするけど。
確か、テストは1つで、不完全な仮実装でテストを通し、後はテストが通ることで処理が正しいことを確認する、みたいな感じだったような。
テストを2つ書くのは三点測量とかいう、なんか不安な時にやる方法とかだったような。
でもこっちの方がより納得できるんだよなぁ。
仮実装でもテストが通るというのが気に食わない。
で、仕様を追加する場合も同じ手順で進めていく。
*
その結果、前に書いた時とは処理方法が変わった。
まだ前に書いた機能には達していないので変わりそう、が正しいが。
単純、コンパクトな実装でテストを通すようにしているためか、前に書いたのより見やすく、分かりやすくなっている気がする。
前はテストとか書いてなかったから、処理ありきで書いていたため、頭の中にある処理をそのまま書き出していたからごちゃごちゃしていた。
今回はテスト、つまり結果が先に来て、その結果にするためにどうするか、という考え方に加えて、機能を細かく1つずつ実装していっているので、ごちゃごちゃしてない感じがある。
これなら、機能を増やしていっても見やすい、分かりやすいコードが書けそうだ。
*
初日ということもあってかあまり進んでいないが、大体分かってきたので明日からはもっと進められればいいのだが。
CppUnit?知らない子ですね。
*
Google Testに切り替えた。
他にもBoost.Testとかあったらしい。
完全に調査不足である。
Google Testに決めたのは、出力に色が付くのでテストの成否が一目で分かるというのが一番の理由。
その結果、CppUnitをより扱いやすくするために書いたコードは全て不要になった。
悲しい。
*
元々、CppUnitはJUnitをC++用に書き直したようなものだからか、クラスありきな書き方が気に入らなかった。
Google Testなら、クラスを作らずにテストを書けるし、必要に応じてクラスを使ったテストも書くことができていい感じっぽい。
昨日は久々に朝方まで作業してしまった。
*
その甲斐もあって、CppUnitを利用した自動テスト実行環境は大体整った感ある。
wafの自動テストサポートも使い、ビルド成功時にテストプログラムが自動的に実行されて、テストが通ったか通らんかったか表示されるようにした。
ただ、テストの通った通らないはテストプログラム単位なので、テストが通らなかった時にどのテストが通らなかったのかは表示されない。
なので、その場合は自分でテストプログラムを実行してどのテストが通らなかったのか確認する必要がある。
そこが少し面倒だが、かといって全テストの出力を表示すると量が多すぎるか。
*
テストコードのファイル数が増えれば増えるほど、テスト対象コードの全く同じコンパイル処理の回数が増えると思われる。
ビルド時間の増大が懸念されるが、全く同じということはコンパイルキャッシュなるものを使えば時間短縮できるんだろうか。
*
もうちょい整えたらテストファーストで作業を開始するつもりだけど、それは月曜からにしようかなぁ。
タグとか初めて使った。
*
使い方これでいいのかよく分からんけど。
とりあえずリポジトリを作っておいた。
読んだファイルの内容を処理するところまでやろうかとも思ったけど、とりあえずファイルを読み込んでその内容を出力するだけ。
それでバージョン0.1.0ということにした。
次は読んだ内容を処理し、データを抽出して出力する。
それを0.2.0ということにしよう。
基本的には、処理内容は今までに作ったやつから持ってくればいいと思う。
でも今回は、自動テストを作ってから作る、テストファーストというやつをやってみよう。
そのためにCppUnitをインストールしたのだ。
超久しぶり。
*
正直詰まってる感じある。
思うに、やはり行き当たりばったりすぎるのだろう。
筋道が立たずにところどころ肥大化しつつあるような、どうしようもない進め方になってしまっている。
こんなことしても進んで戻ってを繰り返すことになりそうでさすがに躊躇しているのだが、1から作り直すべきかもしれない。
一体何回目になるのだ。4回?5回?
経験はどんどん蓄積されているわけなのだから、それをうまく利用できればいいのだけれど。
*
まずは単純なものを作らなくては。いつもここが抜けている気がする。
色々考えた結果、とりあえずベースファイルとかいらん。
環境に1つの設定ファイルなんぞ見るとかそんなんもっと後でいい。今はいらん。
コマンドライン引数から設定ファイルのパスを受け取り、そのファイルの内容を処理する。これだ。
いっそそのファイルのパスも固定してしまえばもっと単純になるかもしれないが、さすがに実用性がなさすぎる気がする。
*
ここまで書いといて今更だが、作ろうとしてるプログラムの大まかな流れは、
・ベースシステムという機能集合体を生成
・ベースシステムを利用して動作するゲームをロード
・ゲームを動かす
という感じになる。
前述のコマンドライン引数で渡す設定ファイルのパスというのは、ゲームについての情報が書かれているファイルだ。
現状では、ベースシステムについての情報は何一つ書かれていない。
これまでの想定としては、ベースシステムについての情報は環境に1つの設定ファイルに記述しておく形だった。
しかしよく考えると、それだと使用するベースシステムが固定的になりすぎる気がする。
別のベースシステムの上でゲームを動かしたいなーとかなった時に面倒だ。
なので、コマンドライン引数で渡す設定ファイルの中に、ベースシステムについての情報も書いておくべきかななどと思った。
そもそもコマンドライン引数で渡す設定ファイルはショートカットファイルという名前だ。
それ1つ読めば、とりあえずゲームが起動するところまでできるべきファイルなのだ。
ならば、ショートカットファイルにはベースシステムの情報とゲームの情報、どちらも記述するべきだろう。
後々既定のベースシステムとか作る場合には、ベースシステムの情報の記述は必須ではないとかにすればよかろう。
*
そこからまた展開させようとすると、どんどん肥大化していく悪寒がする。
なのでとりあえず決まったそこまで作ろう。
まずコマンドライン引数でショートカットファイルパスを受け取る。
次にそのファイルを読む。
最後に読んだ内容を出力する。
これだ。これで行こう。
ここまで作ったらまた書く。
パッケージ設定に対応するパッケージ情報と、依存パッケージ設定の読み込み処理まで作った。
*
次は、その読み込んだ設定ファイル群からベースシステム情報を取得する処理と、その構築に必要なモジュール群の列挙処理か。
それを終えて初めてモジュールマネージャに取りかかれるな。
設定ファイル、JSONじゃない方がいいかもしれない。
*
思いの他扱いやすいし見づらくもないので大体問題はないんだけど、JSONの仕様には存在しない要素がほしい。
具体的に言うと集合がほしい。
現時点では、やろうとするとリストとして記述し、JSONを読み込んでデータを取り出した後に、重複するデータは削除するなどすればできるけど、なんだか回りくどい。
JSONを読み込んだ時点で、重複するデータは削除するようにしてしまいたいところ。
[]はリストで、{}はオブジェクトだから、適当なところで()だろうか。
pythonと同じような感じになりそうだな。
ただこれをやるとなると、JSONの比較処理も追加しなければならないな。
*
JSON読み込み処理は現時点ではかなり限定的でJSONとは呼び難いのだけど、この機能を追加するとJSONの定義から完全に外れることになる。
だからどうだということも、特にないが。
設定ディレクトリ内にあるコンフィグディレクトリってなんだろうな。
*
パッケージのモジュールの使用許可やセーブデータディレクトリとの関連付けなどを記述した設定ファイルなんだけど、パッケージ設定とは呼びにくい。
パッケージディレクトリに配置されている各パッケージ内にも設定ファイルが存在するからだ。
現時点では、後者を読み込む時にPackageConfigという構造体にデータをつっこんでいる。
しかし、このファイルは基本的にユーザーが変更することはないため、設定というよりは情報が記述されているだけのファイル、と考えるべきかもしれない。
そう考えると、PackageConfigではなくPackageInfo、パッケージ情報ファイルと呼ぶべきかもしれない。
そうすれば、モジュールの使用許可などを記述したファイルのことをパッケージ設定ファイルと呼べるし。
今まで脳内ではコンフィグ設定ファイルとか呼んでいたが、コンフィグと設定って同じ意味だし、構造体にしようとするとConfigConfigになっちゃうしで困っていたが、これでどうにかなりそうだ。
*
前の記事に書いた作業については昨日のうちに終わらせておいた。
思うに、ソースコードが読みにくい。
*
情報を表すデータと、情報を参照するための情報を表すデータがほぼ同じ名前で定義されているため分かりにくい。
前者をXXとしたら、後者はXXRefという感じに命名するようにしようかなぁ。
デバッグ出力も、後者もXXとほぼ同じ出力になっちゃってるから分かりにくいし。
*
モジュールマネージャに取りかかる前に、まずはそこらのリファクタリングからだな。
牛歩、牛歩。
*
ようやくモジュールマネージャに取りかかれそう。
パッケージ設定ファイルからベースシステムの設定を取得するところまではできたので、ベースシステムを生成するために生成関数と破棄関数の取得を行なわねばならない。
関数の取得の前にはモジュールのロードを行なわなければならないし、つまりいよいよモジュールマネージャというわけである。
*
基本データ型の定義を変えるべきかもしれない。
現時点では、typedefを使ってintをfg::Intと定義したりしてるのだけど、モジュールがエクスポートするシンボルのことを考慮すると、これはあまりよくない気がする。
fg::Intはシンボルとしてはintと同じように扱われてしまう。
これはあまり都合がよくない。
fg::Intはfg::Intとして扱われていた方が都合がいいのだ。
主に、シンボル名のマングリングとかそこらの処理のために。
それをやるためには、fg::Intをtypedefではなくクラスとして定義すればいいのだろうけど、ソースコード上での扱いは今までのから変更したくはない。
演算子のオーバーロードを駆使することで達成できるのかなぁ。不安だ。
このところ、raspberrypiをいじくっていた。ちょうど日記が途切れた辺りから。
*
raspbmcをつっこんでみたり、openelecをつっこんでみたり。
raspberrypiでradiko使ってラジオが聴けるようになったり、インターネットラジオ聴けるようになったり、youtube見れるようになったり、天気予報確認できるようになったりなど。
テレビにHDMIでつなげばテレビのリモコンで操作できるようになったりしておもしろい。
*
で、bindとdhcpを動かしてるraspberrypiにこれらの機能をつっこめないか、と思って色々試していたのだが、結局今動いているようなgentooにxbmcをインストールするのが一番手っ取り早そう、という結論に達した。
raspbmcはなぜか無線LANがうまくつながらんし、openelecはbindとdhcpを追加するのがかなりめんどそうだし。
*
しかしながら、gentooをまた構築するのもそれはそれでめんどうだったり。
いい加減dropmakerの方進めたくなってきたし、休みの日とかに気が向いたらちょっとずつ進めてみようかと。
って明日祝日?明日はやらん。どうもraspberrypiに関わると頭が痛くなりやすい気がする。
モチベーションが下がっているが、ちょっとずつ進んでいる。
*
パッケージ設定ファイルも、大部分は処理できている。
例によって、暫定的な実装であるため穴だらけだが、そのうちなんとかする予定。
進みが遅くなっている。
*
パス型の扱いを少し変えたり、パッケージ設定を読み込む際の処理で、今まで書いた処理を共通関数化して使えるようにしてから処理したりなど。
パッケージ設定ファイルを見てて思ったのは、これまた割と適当に決めた感じがあるなぁということ。
でもまぁ、とりあえず全部読み込んで型に落とし込む。
そうしないと始まらん。
パス型を文字列に変換する暫定的な処理ができた。
*
しかし、本当に暫定的だ。
機能も少ない。循環参照エラーの検出ができないため、設定ファイルでまずい記述をすると無限ループが発生する可能性もある。
その辺の問題は後々解決していくとしよう。めんどいので。
*
とりあえずパス型を文字列に変換し、ファイルを読み込むところまではできたが、読み込んだものの処理はまだ実装していない。
その辺は明日やる。
パッケージ設定の読み込み処理を作っているところ。
*
ファイルをJSONとして読み込む処理とかは、ベース設定の読み込みでも使っているので使い回せるが、パスの扱いは今回が初になるため、そこで少し手間取っている。
具体的にはパス型を文字列型に変換し、ファイルオープンなどに使えるようにする処理なのだが、今回作成するものは限定的な機能を持ったものでいいだろう。
とにかく、パッケージ設定のパスを文字列にできればいいのだ。そのために全機能は必要ない。
後々きちんと全機能作らなければならないだろうけど、今それをやると間違いなくだれる。
今回作らない機能についても、大体どのように実装すればいいのかはイメージできているので多分大丈夫。多分。
ひとまず、ベースシステム生成、破棄関数取得までの流れは作った。
*
ベースシステムの生成、破棄に関わるモジュール群生成までの流れも作ってしまいたいところだったが、これにはモジュールローダの設計が大きく関わってくる。
そして、今のところモジュールローダは中身が空っぽの状態だ。
よってまだ書けない。書くのはモジュールローダの設計をまとめて、というかモジュールローダを作ってからだな。
*
やはり今週中は無理だったな。来週中ならいけるかしら。
来週の作業手順は、とりあえず流れを作ってあるベースシステム生成、破棄関数取得までの部分の実装を作るところからだろう。
それを終えたら、モジュールローダを作るのとベースシステムの生成、破棄に関わるモジュール群生成を並行して行なう感じだろうか。
大体後者が主導になると思うが。部品を先に作ってしまって、実際に使う場面でやっぱりびみょう、使い物にならんとかなったら目も当てられん。
というわけで、サイトをgithub pagesに移行した。
*
何日か前に書いたような気がしたけど書いてなかったので、経緯を書いておこう。
gaeのツールが動かんくなった。
どうもpythonのバージョンとうまく噛み合っていないらしく、バグ報告も上がっているようだけどツールのバージョンアップが来ない。
現状やってることと言えば静的ページの公開だけだし、記事書いた後にコミットとは別にアップロードコマンド打つのもめんどうなので、github pagesに移行した。
github pagesなら独自ドメイン使用時にサブドメイン付けなくていいし、サブドメインからリダイレクトさせることもできるので、URLをtekuto.netにできていい感じ。
今までのwww.tekuto.netにアクセスすれば、tekuto.netにリダイレクトしてくれる。
今週中に終わらせられれば、とか昨日書いたけど早速今日、諸事情により作業できなかった。
*
明日から本気出す。
でもさすがに明日1日で終わらせるのは無理だろうなぁ。
ベース設定ファイルからベースシステムとシェルについての情報を読み込む処理を書いた。
*
Baroqueのサントラ流しながら作業すると集中できていいな。
歌が入ってるタイプの曲は、作業中の私にはあまり向かないようだ。
気が散りやすいというか、ヘッドホンで聞きながら作業すると頭痛くなったりする。
*
さて、ベース設定ファイルに記述する内容はひとまず全て読み込む処理を書いたので、次はそれを元にベースシステムを生成するための情報を生成する処理か。
まずはどこからだろうか。ベースシステム情報に記述してある、パスに対応した設定ファイルを読み込む処理からかな。
その設定ファイルには、対応するパッケージについて、そのパッケージのパスや、対応するセーブデータのパス、使用を許可するモジュールのリストなどが含まれている。
ので、その設定ファイルを読んだら次はパッケージの設定ファイルを読み込んで、とかそういう流れになるんだろうな。
なかなか負荷の高そうな内容だ。今週中に終わらせられればいいのだが。
パス型の定義変更に対応完了。
*
昨日に済ませておきたかったところだけど、ちょうどその直前できりがよかったため、昨日の作業はそこで切り上げてしまった。
で、今日その辺をさくっと終わらせた。
次はベースシステムやシェルについての情報をベース設定ファイルから読み込む処理と、ベース設定ファイルの情報を元に、色々設定ファイルとか読み込んで、ベースシステム生成に必要な情報を構築する処理かな。
ベースシステムについての情報が記述されてるんならそれでいいじゃないかと思うかもしれないが、記述されているのは設定ファイルのパスとベースシステム名だけなので、具体的にどのモジュールをロードし、なんて関数を呼び出して生成し、破棄するか、といった情報は他の設定ファイルを読まないと分からない。
なので、その辺どうにかする処理を書く、といった感じだ。
やはりきちんと毎日書かんとだめだな。すっかり習慣がなくなってる。
*
昨日の作業としては、設定ファイルの記述を修正したり、パス型の読み込み処理を独立させたりなど。
パス型の定義を変えてあるため、現時点の処理では対応できないので、使う場面になったら修正することになるだろう。
今日はベースシステム構築のためにコンフィグマネージャから情報を取得する処理とか書くつもりなので、前述の修正はやることになるかも。
できるだけ忘れずに書いていくことにする。
*
早速忘れかけていた上に、ツールがちゃんと動作するようになるまでネット上に上げられんけども。
さて、結局設定ファイルの扱いについては、いっそのこと全ての設定ファイルを1箇所で管理した方が分かりやすいのでは、ということで話が進んでいる。
設定ファイル間で関連性があるものも結構あるわけだし、管理オブジェクトに対し、情報を要求すれば必要に応じて設定ファイルを読み込んで情報を生成して返す、みたいな。
一度読み込んだ設定ファイルはキャッシュしておいたり、もし要求があればキャッシュを削除したりなども考えているけど、前者はともかく後者は後回しだろうな。
いや、前者も別に必須ではないな。
もやもやは晴れつつあるし、ペース上げていきたいところだが。
過去ログは年単位で分ければいいのでは、という声が一部でささやかれている。
*
進みはスローペース。もっとさくさくやりたいところだが。
ベース設定の一部を読み取る処理はできた。
一部というのはパスの別名定義。パスに名前を付けて管理する形を取るので、そう呼んでいる。
これにより、それぞれのデータのパスを指定できるようになった。
最終的には、ベースシステムの構築→シェルの起動→ゲームの起動となるわけだが、それまでにどういう処理が必要になるだろうか。
ベースシステムの構築やシェル、ゲームの起動のためには、やはりモジュールのロードが不可欠。
よって、モジュールマネージャの生成が必要になるだろう。
モジュールのロードには、パッケージディレクトリとコンフィグディレクトリに置かれているファイルの読み込みが必要になってくるはずだ。
しかしその処理はモジュールマネージャ内で行うべきだろうか?難しいところだ。
それを含めてしまうと、モジュールマネージャが肥大化してしまう気がする。
とはいえ、どこかでは設定ファイル間の関連付けを解決する処理をやらねばならない。
いっそ、モジュールマネージャではなく設定ファイルマネージャと考えるべきだろうか。
モジュールのロードとかは、それとは別にモジュールローダというか、モジュールロードマネージャというか、そんな感じの機能を別に作り、そこでやらせる。
パッケージディレクトリの設定ファイルと、コンフィグディレクトリの設定ファイル読み込み処理については、別々の機能に分けることはできないだろうな。
パッケージに含まれるモジュール一覧とその詳細情報は前者に書かれているが、どのモジュールの読み込みが許可されているかどうかは後者に書かれている。
あるモジュールを読み込むだけなら、後者の設定ファイルを読んだ後に前者の設定ファイルを読めばいいだけだが、モジュールによっては依存モジュールが存在する。
依存モジュールについては、また後者の設定ファイルから読み直す必要がある。
これを別々の機能に分けるとなると、循環参照になってしまって気持ちの悪いことになりそうな感じがある。
*
書いてたら、ちょっともやもやが晴れた気がする。
完全にクリアになったわけではないのだが。