ようやく子守が終わりだ。
モジュレーションとポルタメントを実装。 050829mdrv.zip あと、エンベロープがリリースに入ったチャネルを空きとみなすことで発音 数を稼ぐことにした。あっという間に発音数オーバーしてしまうようなので。 リリースが切れるとピアノ曲がショボくなってしまうので、特別になんらか の措置が必要かもしれない。元々ショボいから構わないっつう話もあるけど。
ミキサは-marmで書いているんだが、この部分の動作速度が実機とエミュで 違いすぎる。エミュが速すぎるので実機に持っていくとガックリくるね。 BoycottAdvance > VisualBoyAdvance > Mappy ≒ 実機 の順に速いようだ。 BAの名前を書きながら思い出したけど、ウェブではやっぱり、ブラウザです ぐ遊べるゲームのほうが強いね。以前自アン+でお皿マンゲームを公開した ときに、ブラウザから BoycottAdvance ONLINEで直接遊べるようにしていた んだけど意外と反応があった。ダウンロード版の方は誰も落とさないんだも んなー。遊ぶまでのプロセスが「ZIP を落とす→解凍する→エミュを探す→ 解凍する→遊ぶ」と、長くてダルいのかもしれない。俺だってダルいよ。
SMFコンバータにチャネル振り分け機能を付けようとしたが、どうしてもGBA の音源ドライバを移植する必要があり(発音がオフになったチャネルを空き とするだけでは、エンベロープのリリースに対応出来ない → エンベロー プがオフになった瞬間を知る必要がある → 音色もコンバータに通知する 必要がある)なんか色々と面倒になったので結局ドライバ側で振り分けるこ とにした。 負荷が気になって、どうしても演奏データをポリのまま使う方向へは手が動 かなかったんだけど、案ずるより生むが易しだなあ。ずっと悩んでた俺がア ホみたいだ。
実は、スーファミとかAGBとかの一番美味しくて使い手のある機能はウイン ドウなんじゃないかと思い始めた。スーファミソフトで言うと、FF6のアル テマとかFE4の魔法とか、あと忘れちゃいけないのが、ゼルダの伝説のカン テラなどがウインドウ機能で表現されている。 なんで突然こんなことを言い出すのかというと、ガンスパヒー(もっとマシ な略しかたは無いのかよ)公式のムービーを観て、セブンフォースの変形エ フェクトにインパクトを受けたのです。 http://sega.jp/segachan/ch2/gunstar_pr1.html スプライトをウィンドウモードに設定して、BGを透過するようにした上で、 BGの方でそれっぽくパレットアニメさせてるんだろうなあ。
自動ゲイン調整というか手抜きなコンプレッサというか、そんな機能をつけ てみたところ、音量がボコボコするぞ!駄目だこりゃ。うまいこと処理出来 ればクリップしなくて済むかと思ったんだが、やっぱり真面目にクリップす るかあ。
久しぶりにソースを弄ったらプチノイズの問題が解決したのでプチ小躍りし てしまったよ。サンプリング周波数を替えるときに I/Oレジスタを触る順番 を間違えてた。 本来は、素直にこう書かなきゃいけないところをCODE_IN_IWRAM void PDRV_Switch(s8 *buf) { // DMA書き換え REG_DMA1CNT = 0; REG_DMA1SAD = (u32 *)buf; REG_DMA1CNT = DMA_DEST_FIX | DMA_SRC_INC | DMA_REPEAT | DMA_16BIT | DMA_FIFO | DMA_ENABLE; // タイマ書き換え if (pdrvw.old_rateNum != pdrvw.rateNum) { REG_TM0CNT = 0; REG_TM0D = RateTable[pdrvw.rateNum].count; REG_TM0CNT = TIMER_PRESCALER_1CLK | TIMER_ENABLE; pdrvw.old_rateNum = pdrvw.rateNum; } }こう書いてたわけだ。 DMAが止まっている間にDirectSound(ダイレクトにサウンドを流し込むから DirectSoundって名づけたそうだよって京都の某I社の人が昔ゆってたよ(^^;) から転送要求が発生してプチノイズが鳴っておった。俺の馬鹿め。 まあ、これでピッチや負荷によって動的にサンプリング周波数を変える機構 が完成したわけだ。めでたい。CODE_IN_IWRAM void PDRV_Switch(s8 *buf) { // とりあえずDMAを止めておいて…… REG_DMA1CNT = 0; // すかさずタイマ書き換え if (pdrvw.old_rateNum != pdrvw.rateNum) { REG_TM0CNT = 0; REG_TM0D = RateTable[pdrvw.rateNum].count; REG_TM0CNT = TIMER_PRESCALER_1CLK | TIMER_ENABLE; pdrvw.old_rateNum = pdrvw.rateNum; } // そしてDMA再開 REG_DMA1SAD = (u32 *)buf; REG_DMA1CNT = DMA_DEST_FIX | DMA_SRC_INC | DMA_REPEAT | DMA_16BIT | DMA_FIFO | DMA_ENABLE; }
Windows版の超連射68Kをやっているのだが、なんかムズい!妙にムズい!と 思ったのだが、55fps前提で作られたものを60fpsでそのまま動かしてるから 全ての動作が1.06倍速いのだな。もしモニタのリフレッシュレートが75Hzで 固定だったら、75fpsで動くのかしら。 こういう場合、VSYNCで回して12フレームに一度ウェイトを掛けるか、タイ マで回してティアリング覚悟で画面更新するかのどっちかしか無いのかな… …とか考えたけど俺には関係ない話だった。 そういえば翼神はどういう手法をとっているのだろうかなあ。
コンパイラなんか作らなくても、gcc/gasのマクロを使ってそれなりにデータ が作れることに気が付いた。それなりどころか、例えばループジャンプ命令 があるとして、ジャンプ先のアドレスを直接埋め込めたりする分、有利かも しれない。 ということはMMLも……。
弾幕生成部分をスクリプトで書けるようにした。したというかしてるところ であり、記述はバイナリ直打ちでやってる。早いとこコンパイラを書かない とキツくて死んじゃうヨ。 この変更により敵プログラム本体は移動だけ記述すればよくなったので、大 分スッキリした。移動もスクリプト化しちゃえばもっとスッキリするんだろ うが、まあそのうち。 『弾幕タスク(子)→敵砲台タスク(子)→敵機タスク(親)』と、子供が いっぱい増えてきたのでそろそろ真面目に管理しないとバグの温床になりそ うだ。
昨日置いたソースのドキュメントを書くのが面倒なので、簡単なサンプルを 作りました。 050804spr_sample.lzh 8x8, 16x16, 32x32, 64x64 16x8, 32x8, 32x16, 64x32 8x16, 8x32, 16x32, 32x64 の順にスプライトを表示するので、VisualBoyAdvanceの Tile Viewer や OAM Viewer でPCGとOAMの動作を確認して下さい。 コンパイルするにはDevkitARM r13 と、perlがインストールされている必要 があります。あと多分、MSYS も必要。適当に書き換えれば DevkitAdvance とかでも使えると思います。
今のところ、同じ優先順位のスプライトが重なる場合、後から生成したスプ ライトが前に生成したスプライトの下に隠れるような仕様にしていて。 で、鞭のように伸びる弾を作ってみて思ったのだけど、速い弾が遅い弾の下 に隠れるってことになるので、あまり良くないような気がする。 ところで↑のスクリーンショットに出てる緑色の物体ですが、エメラルドに 見えますかねえ?本家のエメラルドも、動いてると「なんだかよく分からな い緑色の物体」だったような気がしないでもないですが。↑は、動いてると ピーマンに見えます。
現状のスプライト管理システムは仮スプライトのポインタを渡してくるため、 オブジェを一括削除するときとか用にいわゆるデストラクタを書かなくては ならないので面倒くさい。仮スプライトバッファのポインタを保持したまま オブジェが消滅すると……。なので、ポインタを保持しなくてもいいように 作り直すことに決めた。決めたんだけど、昨日の夜決めて、起きたら思った んだけど、窓をバンバン思ったんだけど、ゲームシステムの都合で1INT内で 同じスプライトを二回操作する場面があるので、ポインタ経由でスプライト を管理したほうが都合がいいことに気付いた。 それはともかく、スプライト管理システムとかPCG管理システムとかのソース を置いておくので、スプライトをバンバン使う必要がある人は使えばいいと 思うよ。大域変数バンバンだったりしてみっともないので、誰か書き直して くれれば喜びます。 050803spr.lzh