調子に乗ってあれこれコード生成してみたが、CPU が thumb モードのままうっか り ARM コードに飛ばしてしまい未定義命令例外が発生してしまい BIOS に飛んで しまい〜なわけだが、それでも他のタスクは普通に動いていたのでちょっと感動 してしまった。メモリダンプを画面に出力するタスクを走らせておけば実機上で ある程度のデバッグが出来るかもしれないなー。
「その場で ARM コード生成」という超絶テクを習得したおいらは PCM ミキサー のループアンロールにこのテクを応用できるんじゃないかと思ったが、ソースを 見直してみたら既にその必要が無い程度(コード生成する分で帳消しになる程度) には最適化されていたのだった。がっくし。
ふとコードサイズが気になって readelf してみたら、libc や libstdc++ から リンクされるコードが結構でかい。libc くらいは共有させたい気がする。そこ で、noMMU な環境でライブラリを共有する機構について調べてた。 とりあえずここら辺かな。 Shared Libraries without an MMU MMU なしプロセッサ用Linuxの 共有ライブラリ機構 ライブラリは GOT (Global Offset Table)経由で参照して、その GOT は DATA セ クションに配置しておいて、その DATA セクションを参照するのはベースレジス タ経由で、そのベースレジスタはローダがセットする……って感じかしら。 理屈は分かるけど、どこからどう実装したものやら……。R_ARM_GOT32 を使うの かしら?
いくらなんでも bf じゃ辛いでしょやっぱ最低でも C じゃないと……と言われ てしまったので TCC のソースを見てる。が、作るべきなのはコンパイラじゃな くてリンカ&ローダのような気がしてきた。MMU が無いので完全リロケータブル を目指さなくちゃいけないのではと思うに至ったわけだ。BREW で静的変数が使え ない(使えなかった)という話を以前よく耳にしたけど、多分根本は一緒なのだ ろう。 uClinux/ARM の MMU-less サポートが参考になりそうな気がして覗いてみたが、 どこから見ればいいのか見当が付かない。ちょっと山が高すぎたかも。 それと、いい加減 arm-elf を脱却して arm-eabi に乗り換えないと……。
セマフォを実装するためにはクリティカルセクションが必要で、要するに割り込 みかプリエンプションを止めなければならないのか。逆に言うと、止めちゃって も良いということか。 タイマ割り込みハンドラでは(タスクの寝ている時間を調べるために)割り込み 回数カウンタをインクリしているので、割り込みを止めるよりは、フラグ立てて コンテキスト☆スイッチだけ禁止する方向でもいいような気がする。VBLANK 割り 込みハンドラ内では割り込みを止めたいので、二段階のロック機構を設けてみる。 これでスプライトダブラが安心して回せるようになった。しっかし、いちいちク リティカルセクションに入っていたら CPU 資源を食ってかなわんなぁ。スプライ トダブラといいつつ、その実スプライトシングラと言えるくらいしか数が出せて いない。 ちなみに ARM7TDMI の TRM によると、セマフォの実装には SWP か SWPB を使え ということらしい。フラグを中身確認せずに立てるだけなら STR でもいいような 気がする。マルチプロセサなら話は変わるんだろうけど、今のところターゲット はシングルプロセサだし。まぁ SWP を使わない理由は無いので使っておくか。 -- モジュールの動的実行とかやってみたかったので b****f*** コンパイラを作って みる。[,.]の4命令に対してリロケーションテーブルを作り、モジュールロード時 に置き換える。ここまではいいとして、入力待ちでビジーループするのはアホら しいので、スリープ状態に突入して入力があったときだけアクティブになるよう な機構が欲しいかもしれない。となると、次はシグナルの実装ということになる のかな。
去年自アンで知った「ダイレクト・プッチン」を今になって実践してみたところ、 口の中全体に柔らかい甘味が押し寄せたと思った次の瞬間、ほのかな甘みだけを 残し、消えて無くなってしまった。もう過去の自分には戻れないだろう。とてつ もない体験をしてしまった。
タイマ割り込みでコンテキスト☆スイッチする機構を作ったものの、main() 関数 の処理を奪いっぱなしのまま回していたので、このままでは同期処理が出来ない ことに気づいた。自分自身をタスクとして割り当てないといけないのではないか? 同期と関連して。タスクが終了する時のことを全く考えていなかった。コンテキ ストを拡張して、関数を抜けるときにポップされる分のスタックをあらかじめ積 んでおき、リンクレジスタから終了処理へと飛ぶように細工する。終了処理から はもう return できないので、空ループでもさせておく。保存された main() の コンテキストを探して戻るようにするべきだろうか? 色々と謎が深まるばかりである。つーか、聞きかじりからの想像で作るのはやっ ぱ無理があるから、そろそろ何かを参考にするにゃん。
そもそもの発端は、読み込みしながらゲームが開始してしまうソフトって何気に 凄くね? スレッドでも使ってるんかね、という話題から、そういや俺スレッド って使ったことないなーと思ったので使ってみることにしたのだが、GBA の非公 式環境にはスレッドなどというものは用意されていないので(探せば RTOS 的な 実装は出てくるけど、見なかったことにして)原始的なプリエンプティブ・マル チタスクの再車輪からスタートすることになったわけだ。(動機が長いよ) まずはガムシャラに実装してみた。1. 割り込みが掛かる 2. コンテキストを TCB (TaskControlBlock) に保存する 3. スタックポインタを巻き戻す 4. TCB を切り替えてコンテキスト復元割り込み復帰処理をせずに回すパターン。スタックがどんどん積まれてしまうの で、スタックポインタを直接操作してみた。アセンブラだぜ!という無駄な満足 感は得られたが、タイマ以外の割り込みにも対応したい等の拡張を施すのは大変 そうだ。 そこで、ちょっと考えて実装を変えてみた。1. 割り込みが掛かる 2. コンテキストを TCB に保存 3. 割り込みがタイマかどうかを調べる ・タイマ割り込みなら TCB を切り替え、TCB の復帰レジスタを書き換える (実際には、あらかじめ書き換えておく) ・他の割り込みなら TCB を切り替えずに処理し、4.に移行する 4. コンテキストを復元 5. 割り込みから復帰これなら他の割り込みが入っても綺麗に流すことが出来る。素晴らしいね。が、 それぞれのタスクのコンテキストを引き継いで処理するため、スタックサイズが 心もとない。他の割り込み用にスタック領域を設けるなど、もう一工夫必要かも。 RTOS 的もしくは POSIX 的なタスクスケジューラを組んでみたい気もしてきたけ ど、とりあえず寝かせておこうかしら。あと、よく分かってないんだけど、多分 mutex とかも必要になるよなぁ。タスク間通信も必要だ。やること一杯あるな。 それと、BIOS に戻るための復帰アドレスをスマートに得る方法がどうしても思い つかなかった。結局、最初のタイマ割り込みで保存した main() 関数のコンテキ ストからタスクのコンテキストにリンクレジスタをコピーしてしまった。おかげ で以降のタスクでも延々と直前からのコピーが発生している。かなり無駄なので なんとかしたいところ。 -- 前回、企業秘密がどうのと書いてしまったけど、このドメインでそんなことを書 くとあらぬ誤解を生んでしまいそうだと気づいたので弁明しておくと、当サイト は実在する企業とは無関係の、ただの個人日記ブログ兼ネタ帳です。一発ネタ多めで。
GBA の例外ベクタは BIOS に割り当てられているので割り込みから SWI まで全 部、一度 BIOS へと飛んでいく仕様になっていて、んでもって割り込みの場合は その先でリンクレジスタを退避してくれちゃってるもんだから、アレが出来ない。 「アレ」が何かはモロバレなような気もしないではないですが、企業秘密なんで 伏せておきます。@ VisualBoyAdvance pseudo-BIOS (IRQ Exception) @ @ 0000-0018: b $0000-0240 @ @ 0000-0240: stmfd sp!, {r0-r3,r12,lr} @ 0000-0244: mov r0, #0x04000000 @ 0000-0248: mov lr, pc @ 0000-024c: ldr pc, [r0, -#0x4] @ @ 0000-0250: ldmfd sp!, {r0-r3,r12,lr} @ 0000-0254: subs pc, lr, #0x4IRQ ハンドラに飛んだ後、BIOS に戻るようリンクレジスタが上書きされちゃって いますなー。(VBA の似非 BIOS コードを貼りましたが、実機も同じ挙動になり ます) なもんで、IRQ ハンドラに飛ぶ前にリンクレジスタをどこかに保存しなおす処理 を間に挟んであげる。ldr r0, =lr_pool add r1, sp, #20 ldr r2, [r1] str r2, [r0] b IRQ_Handlerついでに、その他のコンテキストも保存しちゃってもいいかもしれない。
風邪引いてダウンしてた都合で気づかなかったんですが、正月明け、具体的には 1月8日からスパムが急増したようですなー。例によって、アクセスログから POST メソッドのみを抽出してみた画像ですが、 こんなのが旧年中は1日 100 件近くあったんですが、今年からは 400 件に増や したんだそうですが、まぁ幸いぼくわ天才うぇぶぷろぐらまーなので全部弾いて いますがね。 どうやら referer の頭が http://:// となる新種のスパマーが現れたようです。 こんな分かりやすい特徴を残してどうするの。あと、User-Agent が全て同一な のはどーにかならんのかと、他人事ながら思ったりします。ぼくが天才うぇぶぷ ろぐらまーというよりは、むしろスパマーが(中略)ということのようですね。 残念。ぼくは天才じゃなかった。
何故は分からないけど、ゲーム機のムービーを PC で云々したい場合、今までは キャプチャするか……という発想しか出てこなかった。しかし、レコがあるなら それで録って焼いた DVD を PC に読み込ませればよいという話だわ。PC でのキャ プチャより安定して録れるし、いいかもしれない。 とりあえず作業手順を残しておこうかしら。 DVD-RW からコピーした .vob ファイルを DGIndex で読み込んで、d2v で保存す る。avisynth で適当な .avs ファイルにMPEG2Source("source.d2v") DGBob(order=1,thresh=0)とか書いて bob (60fps化)し、 aviutl や VirtualDub で読み込んでエンコード するだけ。PC で見るだけなら crop した後 resize してもいいかもしれない。 youtube にアップする場合は bob より blend の方が良いのだけど、ノンインタ レースのソースだと少し残念なことになる。まぁ 60fps 化したものをアップし て(youtube 側の再エンコード・fps 調整によって)点滅半透明がものすごく残 念なことになるよりはマシなのかもしれない。 まぁそんなこんなで録った動画がコレ。アップしたのは昨年だけども。 Galaxy Force Neo Classic 16:9 (1/2) Galaxy Force Neo Classic 16:9 (2/2) ううん、眠い画質だなぁ。 折角なので1面だけ、HD画質でもアップしてみた。 http://www.youtube.com/watch?v=GRxGvzbZcas&fmt=22 元のゲームの解像度がせいぜいワイド・プログレなのに HD にして意味あるの? と思われるかもしれないが、意味など無い!と言わざるを得ない。
http://d.hatena.ne.jp/ABA/20090105#p1 少ない行数に収めるためにコンパクト化云々してたり、割と好き勝手にforkされ ている様子を見ていると、そんな気がしてくる。
大掃除をしていたら PS2 メモリカードを読み書きする装置を発掘してしまい、こ れを使って何か面白いことが出来ないかと調べていたら、タイムリーなことに純 正 HDD 付き BB ユニットが某中古ハード取扱店にて 1,500 円で売られているの を入手してしまい、仕方無いので mips-toolchain などを用意してみたら、あれ よこれよと言う間に homebrew 環境が整ってしまった。 PS2 はかなりクセがあって面白そうなのでいずれ手をつけたいとは思うんだけど、 自分のスキルを考えると、まぁたいしたことは出来ないだろうなぁ。マニュアル 目当てに PS2 Linux が欲しいような気もする。
(;´ω`)=3