固定小数点を1:8:7で取るとき (0,240) (240,240) ┏━━━━━━━━━━━━┓ ┃ ┌──────┐ ┃ ┃ │ │ ┃ ┃ │ │ ┃ ┃ │ │ ┃ ┃ │ │ ┃ ┃ │ │ ┃ ┃ │ │ ┃ ┃ │ │ ┃ ┃ │ │ ┃ ┃ └──────┘ ┃ ┗━━━━━━━━━━━━┛ (0,0) (240,0) こういう風に座標を取っちゃ駄目だ。右側に16ドットしか余裕が無い。 1:9:6にするか、中央を(0,0)にするかしたほうがいいな。あー。
シューティングの当たり判定は、縦シューなら縦軸を横シューなら横軸 を先に判定すると比較が少なくて良いのだな。特に、弾が膨大にあると 顕著。まあ考えてみれば当然か。 空間を分割して登録、比較するようにすれば多分もっと稼げるけどそこ までするほど困ってないと言うか、登録するためのテーブルを用意する ほどメモリがあるわけではないというか、メモリはあるんだけど、最終 的にリプレイを保存したいのでERAMは余っていればいるほど良いという か、よくよく計算してみると毎フレ1バイトをRLEで圧縮という条件でも 約30分のリプレイが収まらないかもというか。
みんなポーズ機能はどうやって実装してるんだろうか。大雑把に書くと 「タスクを止める」か「タスクが止まる」かなんだけど。まあどっちで やってもいいんだけど、止まっているキャラクタを描画したい&動いて いるキャラもいるとかメニュー画面を出したいとか、という条件で…… えーと、前者の場合タスクは描画命令を出せない。だから、キャラクタ の描画はどこかで肩代わりしてやるとか。後者の場合それぞれのタスク にポーズ時の挙動を記述するのが面倒だが描画命令は出せるっつーか。 そもそも描画を命令する必要があるという設計がいかんのかもしんない。 でもタスクのリストを一からなめてどうこうってのもなんかヤじゃない。 virtual void draw(void) = 0;をオーバーライドして…みたいなさあ。 オブジェクト指向でなんでも解決できると思ったら大間違いなんだぞ。俺が。 唐突に結論を出すが、俺は明日死ぬ。
曲コンバータも音源ドライバもほぼ完成し、意気揚々と実行してみたら まともに曲が鳴らない。しばらくハマったがどうやら outb(port, var) の引数 port には変数が使えないようだ。 void outb(u8 port, u8 value) { asm push dx asm push ax asm mov dx, port asm mov al, value asm out dx, al asm pop ax asm pop dx } こんなの。アセンブリを吐かせると push bp mov bp,sp push dx push ax mov dx,[bp+4] mov al,[bp+6] out dx,al pop ax pop dx pop bp ret こんな感じ。使えそうな気がするんだけど使えない。定数ならOKで変数 が駄目な理由はなぜかしら。仕方ないのでアレをアレしたら、まともに 鳴るようになった。 絵・音・割り込みが使えるようになったので一通りのことが出来るよう になったかな。満足したので、これにてWonderSwan編は終了。もし続き をやるとしたら以降はmixiの方に書きます。
一通りの鳴らし方が分かったのでシーケンスの作成だ。MMLコンパイラを 改造しようかと思ったが、MMLを打つのが激しく面倒なのでやっぱり例の SMFコンバータを75Hz仕様にすることに。 MIDIメッセージ一つに4バイトも使うと、あっというまに容量をオーバー してしまうので最大2バイトに圧縮。データ的にはMMLをコンパイルして 作るものと変わらんようなアレになった。エンベロープ仕様は取り合え ずADSRでいいか。
WSCampは周波数を弄ると再発音するが、これは再発音しないほうが正解 のような気がする。ソースがあれば直すんだけどなあ。おかしなLPFの せいで音が不自然に丸いのもどうにかしたい。 OSwanはソフトスウィープしても再発音せずに鳴っとるね。ただしこちら はノイズチャネルを波形メモリ音源と併用したときの挙動や、ハードの 再生限界値を超えたときの挙動(最高/最低の周波数を入れて消音する というテクニックがある)が大分怪しいな。まあこちらは修正可能だけ ど。
つーかスワン楽しすぎる。自分で割り込みが作れたもんだから嬉しくて ついつい弄ってしまう。GBAでもまるきり同じことが出来るのに。この 感覚は久しぶりだなあ。 勿論GBAもちゃんと進めてます。スワンに掛かりっきりなわけではない。 割り込みが一段落したので、今度は音を出してみようかと思う。基本的 には周波数と音量を指定するだけなので、鳴らすこと自体は楽勝なよう に思える。しかし音色はどこで変えるのだ?謎なのだ。 ……どうやらI/Oの$8Fで波形メモリのベースアドレスを変えるらしい。 $8Fに書いた内容を6ビット左にシフトした値がベースアドレスとなり、 そこから順に16バイトずつ(1バイト2要素で)32要素の波形を書いてい くようだ。 うーん、割り込みベクタからスプライト・BGテーブルから波形メモリ に至るまで、なんでもかんでもIRAMに置いてあるのは、なんだかなあ。 CPUがCISCだから仕方ないんだろうけど。 00FF:FFFF +------------+ | | | CODE | | | 0040:0000 +------------+ | ? | 0002:0000 +------------+ | SRAM | 0001:0000 +------------+ | IRAM | 0000:0000 +------------+ 現状、IRAMとCODE(の最初のバンク)しか使えておらず、しかもIRAMの 先頭64バイトは割り込みベクタに、末尾512バイトはグラフィック用に 使用している。 SRAM領域がメモリとして使えれば大分楽になるし、コードセグメントも 弄れれば尚いいんだけど……まあ本腰を入れるわけではないからいいか。
やっと安定した。VBLANK割り込みでスプライトを表示しつつ、HBLANK割 り込みでBGをウネウネとスクロールさせてます。 ワンダースワンのHBLANK割り込みはnライン間隔で発行させられるので 色々と面白いことが出来そうである。8ライン間隔で割り込ませれば簡 単にスプライトダブラが作れそうじゃない?(GBAの場合、VCOUNT割り 込みを一々設定しなおさなければならないので少なからずロスがある) 問題は、スプライトダブラ分のスプライト領域を確保できるほどメモリ があるわけではないということか。
分からないまま放っておくのは精神衛生に悪いので、再挑戦した。が、 うっかり風邪をひいてしまい、体力と気力が尽きかけているので簡潔に 書く。 callback.asm つまるところVBLANK割り込みでスプライト更新関数を呼ぶことには成功 した。 しかしタイミングか何かの問題で(原因わっからん)数百回呼ぶとハン グアップするのだ。HBLANK割り込みをさせようものなら、あっというま にハングしてしまうー。 なので、今日はここまで。
ws_test3.zip (ソース込み) 作れそうな気がしたんだけどうまくいかない。つーかCSとかDSとか無理。 分からんものは分からんのだ。しばらく寝かせることにしてGBAに帰るよ。 ソースの231行目
のコメントを外せば一応実験出来ます。/* if (!irq) { IRQ_SetHandler(IRQ_VBLANK_BEGIN, Vblank_Handler); irq = 1; }*/
まずは手元にある資料でなんとかしようと思い、80386/486プログラミン グガイドを読み直し、割り込みベクタはIDT(InterruptDescriptorTable) を設定すれば良いことが分かった。そのためにSIDT命令が用意されてい るが、この命令は8086には無いようだ。つーか、当たり前だがこの本で 8086の勉強をしようとしちゃ駄目だよ。(;´Д`) 仕方ないのでCygneのソースを読んだ。となっており、呼び出し側 (main.cpp) は nec_int((wsIO[0xb0]+n)*4); で呼んでいた。nに入る値は 0: シリアル送信 1: キー押下 2: RTCアラーム 3: シリアル受信 4: 描画ライン検出 5: 垂直同期タイマ 6: 垂直同期 7: 水平同期タイマ (あれ?0除算フォールトとかは潰されてる?) wstech24.txtによると、I/Oポートの$B0はInterrupt Baseとなっている ので、ここが0x00なら0000:0000から割り込みベクタが開始するようだ。void nec_int(DWORD wektor) { DWORD dest_seg, dest_off; if(I.IF) { i_pushf(); I.TF = I.IF = 0; dest_off = ReadWord(wektor); dest_seg = ReadWord(wektor+2); PUSH(I.sregs[CS]); PUSH(I.ip); I.ip = (WORD)dest_off; I.sregs[CS] = (WORD)dest_seg; } } (nec.cpp)
ws_test2.zip rep movswなんてものがあるじゃないの。というわけで高速化し、処理落 ちしなくなった。DMAが使えるといいんだけど、まだ使い方がよく分から ないので保留。 Aボタン 表示数変更 Bボタン 回転 Yボタン グラフィックの変更 手探りでアレコレ試すのは楽しいな。楽しいんだけど、真剣に作ろうと するなら、タイルの管理やメモリの節約で地獄を見ることになるんだろ うな。 WonderMagicはゲームバンクでまだ買えるらしい? http://gamebank-web.com/ec/store.asp?code_syosai=432180 しかし販売終了品のページにも載っているし、本当に買えるのか謎だ。 http://gamebank-web.com/ec/store.asp?kind=zzz&gazou=syousai
ws_test.zip 情報があんまり無くて、ここまでたどり着くのに結構苦労した……それは さておき。スワンのスプライトは8x8が128個だったのか。 CPUパワーが潤沢なら144ライン÷8ドット×32個(1ラインの最大表示数 が32個なので)で、最大576個まで表示できる計算になるが、ごらんの通 り256個の点滅表示でも既に処理落ちしてるのでスプライトダブラを作る のはかなり難しそうだ。 というか、割り込みの作り方が分からないよ。割り込みベクタはどこに あるのかしら。
同じ場所をグルグルとループしている気がしてきた。まあいいけどさあ。
GWの間ずっと考えてた。面倒くさいので結論だけ書くと、巨大スプライト をその場で複合スプライトにコンバートしてスプライトダブラで表示する しかない(というか、その場でやると明らかに効率が悪いのであらかじめ 分割しておく)。でないと、どうしても優先度が破綻してしまう。 現状16x16サイズのスプライトを704個まで出すことが出来るけど、むしろ 352個までしか出せない代わりに32x32サイズのスプライトを使えるように すると、案外バランスがよかったりするのかも。複合スプライトは作り直 しになるけど……。
アンダーディフィートのFM音源アレンジにはしてやられた。 しかし個人的には「このパートはこの音色の方がいいはず」と思うところ が少なからずあったし、大きなお友達のみんなもそう思っただろうことは 想像に難くない。 そういうわけで、みんなでFM音源にアレンジしよーぜ。 ほぼオッケーであろう耳コピ素材を置いとくので VOPMなりFM7なり、携帯のMA-n系音源なりで鳴らして遊ぼうぜ。 UnderDefeat - Can't come back (SMF) んで、これが携帯の音源で素直に鳴らしてみた例。 UnderDefeat - Can't come back (mp3) パートを使いすぎているのでFM8パート+PCM2パートくらいに落とし込み たいところではある。 (10:30追記) mp3を2loopにしたものと差し替えた。