悦楽舎は今日で17周年!
ということで15周年、16周年と2度あったことの3度目です。1年振り返りが恒例化してきました(
目次
- 2025年9月、GBA勝手移植「終末の過ごし方(Win)」のBGM制作をお手伝いしました
- 2025紅楼夢、新譜「chiptreading」のMusicROMの話
- 2026例大祭、東方チップチューン合同「幻想郷レトロカーニバル」とGBA音源チップチューンの話
- 2026例大祭、新譜「八雲迷路帖デモ」の話
- あとがき
今回も技術の話を中心に、PCゲーのGBA勝手移植用に作ったGB音源アレンジの聴き比べを入れつつ、進化したMusicROMのサウンドドライバの解説だったり、GBA音源チップチューン作ったけど作曲環境から全部作って地獄だったぜ!って話です、多いな(
それぞれ無関係に見えて連続性があることに気付いたのでだいたい時系列順に進めます
(5/31) 聴き比べの動画は準備中です。
GBA勝手移植のお手伝い
またまたGBA開発wikiのakkera102さん開発のGBA勝手移植「終末の過ごし方 for GBA」のBGMアレンジ制作でお手伝いをしました!
↑ 終末の過ごし方 for GBA ……うーんメガネ! (全員メガネ)
ゲームをGBAで遊ぶには元のゲームデータが必須ですが、今回も音の確認用に使っていたテストROMを公開中です。全曲アレンジしたのでBGMは全部聞けます!
それとサウンドドライバのソース、BGMの生データ(APUログ)やgPSG変換スクリプトも入ってます。サウンド関連のファイルは全て揃ってるのでよかったらどうぞ。
振り返り&聴き比べコーナー
「終末の過ごし方」はBGMが世界観を作り出しているような作品で、BGMは超重要です。ボイスがないのでもはやBGMが最前面です(
そして今回は原曲がFM音源ではなく、楽器もピアノとか、ドラムがない静かな曲が中心で、BPM測定が困難な即興曲も……と振り返るとやべぇ要素ばっかですがV16RISEの完成直前あたりで「全然いけますよー」とか言って引き受けました(
それが5月、仮完成(BGMなし)が7月、リリースが9月。お待たせしてマジすいませんしたァァ!!
まぁベース鳴りっぱなし、重いキックでリズムを取る曲(=自分は作りやすい曲)ばっかやってきて、真逆の静かで退廃的な空気を掴むのに時間かかりました。音が少なくてもチープにならないって難しいです。
(5/31) 公開直前にヘッドホンが壊れてるのに気付いた……流石にマスタリングできなかったので少し待って下さい。ごめん!
WE14 - 作品番号23 即興曲 「混沌」
1日目に流れる曲、つまり、ゲーム内で最初に耳にする曲です。
原曲は、ピアノ即興曲で、BPM不定、鍵盤の強弱で「終末を目前にした世界」の様子を表現してます。
大変そうだから最初に作ろうとして、……色々試行錯誤があって、出来たのはかなり終盤でした。
WE05 - 作品番号12 「過去の意味」
今作のピアノの音はこれでいこうと決めた曲でした。この音はピアノ!ピアノです!(
WE03 - 作品番号08 「哀悼」
空気感で言うと、この曲はしっかり雰囲気を残せました。
WE09 - 作品番号17 「永遠の孤独」
打ち合わせ中に「神秘性」って単語が出たので霧で包んどきました(
WE12 - Op.20 ~why R U crying....?~
教室のスピーカーから流れるからか、原曲がモノラルだったりします。
1日の始まりに流れるので、時を刻む役割なのかも
WE14 - 作品番号22 「悲しい決意」
ドラムもあって空気が動き出す曲、ノリノリになり過ぎないよう抑えて作りました(
WE13 - 作品番号21 「見えない明日」
同じくドラムあり。勢いのある曲でも「壁を壊せない」ような詰まり感がある気がします。
この曲は疑似ディレイ的な鳴らし方を入れてみました。
WE06 - 作品番号13 「君の見る夢」
ここにこの曲を置くといつもの“7曲入りミニアルバム”感が出る!(ぉぃ
テストROMの新機能
どの曲もフル尺が3,4分とかで長いので「途中から再生」は絶対要るだろうなと思って真っ先に付けました。
↑ EoF:は曲の長さ、Start:は開始位置、Vol27は音量設定。この3つが増えました
音が大きいと音割れ、小さいとノイズが入るとか、時々音が変とかあるので耳で音の異常を探す作業中にこれ作っといてよかったーってなりました(
MusicROM・サウンドドライバ(V3)
次はGB用MusicROM「chiptreading」のサウンドドライバ(V3)の話です。少しおさらいから。
勝手移植とMusicROM、どっち用のもいつも会場で見せびらかしている黄ブロスで打ち込んでます。
GBA勝手移植はMusicROM制作ツールを一部流用して、勝手に命名した(VGMの44.1kHzを60/360Tickに変更もした) GB用音楽フォーマット「gPSG」で出力して、それをGBAで再生してます。
つまりGBAのほうが後に作ったドライバで、GBとGBAで共通化できるんじゃね?あ、GBに移植できました!
……って話です(
新しいドライバで変わったこととか
一番大きいのは前作「chiptunism+」(256KB)からROM容量が4倍(1.0MB)になりました7曲しか入ってないのに
というか逆に無圧縮で7曲入れてもまだ512KBを少し超える程度なので、gPSGにする利点のほうが大きいです
chiptreading.map
ROM0: $1629 bytes in 1 bank
ROMX: $7fa2f bytes in 33 banks
SRAM: $2000 bytes in 1 bank
WRAM0: $0226 bytes in 1 bank
WRAMX: $0040 bytes in 1 bank
HRAM: $0053 bytes in 1 bank
↑ 左: chiptreadingのデータマップ、33x16 = 528KB 右: 各gPSGファイルのサイズ一覧
前作のドライバ(V2)は容量削減を徹底していたので頻出パターンをコマンドに置き換えていました。↓
↑ 例えばLSDjで打ち込んだこの1音
APUログ
; songraw
; WE01-OP03_gymnopedia_all_lp0
10,00 ; 初期化
11,80
12,98 ; (INSTのENV$98)
13,4a
14,86
12,18 ; Eコマンド $18
10,00 ; 再送 (これいる?)
11,80
12,18
13,4a
14,86
VGM/gPSG/MusicROM(V3)
; b3 xx yyはGBレジスタ書き
; MusicROM(V3)は、b3を省略
$b3, $10, $00
$b3, $11, $80
$b3, $12, $98
$b3, $13, $4a
$b3, $14, $86
$b3, $12, $18
$b3, $10, $00
$b3, $11, $80
$b3, $12, $18
$b3, $13, $4a
$b3, $14, $86
MusicROM(V2)
; 実際にレジスタに書く値は
; 他と全く同じ
$E5, $4a, $06
; $10-$15を初期化する
$F2, $18 ; $12にxxを単体送信
$FC, $18
; $10-$15の$12だけ指定して再送
; ($12以外はE4実行時の値)
↑ ドライバ(V2)ではコマンドに置き換えることで大幅な容量削減を実現。……恐らくまたどこかで使います(
ちなみにこのコマンドの展開処理は1つ1つ分岐でオーバーヘッドがヒドい状態&4ch同時処理でした、それでも360Tickで動くんだから4MHzは高性能ですごい(小並感)
今作り直したらちゃんとオーバーヘッドが少ない処理にします(
で、gPSGの利点とは、このコマンド変換&展開が不要になり単純な処理に置き換えられることです。
更に、単純になったからできる高速化テクニック……forループ内の処理を、コピーして貼り付ける!
b0_header.asm (遅い)
.lp0
ld a, [hli] ; cmd/adr
cp $FF ; End
jr z, frame_done
ld c, a
ld a, [hli] ; dat
ldh [c], a
jr .lp0
frame_done:
ret
b0_header.asm (早い)
.lp0
ld a, [hli] ; cmd/adr
cp $FF ; End
jr z, frame_done
ld c, a
ld a, [hli] ; dat
ldh [c], a
.1
ld a, [hli] ; cmd/adr
cp $FF ; End
jr z, frame_done
ld c, a
ld a, [hli] ; dat
ldh [c], a
.2
(省略)
jr .lp0
frame_done:
ret
現代の感覚だと「は?何やってんの?」ですが、ループ処理は「カウントを減らす」「0かチェック」「先頭に戻る」の3命令が必要で、これらを減らせた分だけ早くなります。
ドライバ(V3)は12個並べて「先頭に戻る(jr)」を飛ばしまくりました、これがめちゃくちゃ効きます(
あともう一つ、(LSDjと同じ)360Tickから1フレーム7回割り込みの420Tickに変更しました。
1フレーム中に割り込めるチャンスは154(=11x7x2)なので、PCM再生(やkit)と相性がいいのは420のはず……まだ検証してないけど
↑ 「Own the Stage(原曲:東方妖恋談(緋想天))」のCD音源はLSDj(360Tick)録音ですが、MusicROMは420Tickだったりします
というわけで「GBA自作ソフトをGBに移植して全て上手くいきました」!!
ただ、完成はchiptreading初頒布の“秋”ではなく冬コミでした、ね……(遠い目)
秋に頒布したバージョンに入れていた“MusicROMのもと”ことsongrawファイルからMusicROMを出力するツールは公開中です。
そういやこの時に入れたsongrawにも致命的なミスが……実は……もういいか!(
GBAチップチューン作った
で、話がまたGBAに(
GBAのDirectSoundも使ったチップチューンを作って、東方チップチューン合同CD「幻想郷レトロカーニバル」に参加しました!
で……GBA実機で鳴らしたい人間なので、色々悩んだり細かいテストを色々してました……という色々。
1. ステレオPCM再生テスト
何よりまず「GBAは音が悪い」という印象をずーーっと持っていたので音質のテスト。でもガチの周波数特性とか出しても面白くないので、なんとなく学マスの曲を変換して実機で再生&録音。
↑ 左: ボーカルは重なりまくるわ、和楽器は鳴りまくるわ、の「雪解けに」(8bit/64k) 右: 無駄にちゃんと背景作った(
記事公開直前に気付いたけど16bit/44.1kで録音してるから聞いてもらうデータとして適してなくね?(
↑ 左: 聞きたくてついでに変換した「ハッピーミルフィーユ」(8bit/32k) 右: 文字の位置もちゃんと変わる!(
という感じで実機だと、CD(16bit/44.1k) < GBA(8bit/64k) < HiRes(24bit/96k) と言っていいような結果でした。
最大32MBのROM容量を4分の曲に全部使うという無茶が許されるなら、数値通りの音がちゃんと出ます!!今日はこれだけでも覚えて帰ってください
あと学マス曲はリステ濃縮200%スマイルも聞こう!ガチャ画面で鳴り始めて爆笑した、作詞の人はこっちでこの2曲はリステDDだろお前!!ちゃちゃちゃの前に梅昆布が聞こえる!(幻聴) 2ndシングルの自己紹介パートでしかない間奏はあるし、ドンスマの思い出ボムパートに自然に移行できる気がするし、同じ作曲者だから似てるってレベルを遥かに超え……大幅にはみ出していて、これをKiRaReの曲じゃないって認識することがあまりに、あまりにも困難なのでいっそプリズムステージに出場してくれ(意味不明)ギャルゲみたいな親密度コミュとギャルゲの絵柄でVtuberより相性いいぞ、アレは目と耳大渋滞脳に入ってくる情報が何一つ噛み合わなくて新しい価値観のエンタメで面白かったんだけど。ついでに学マスでちぐはぐメロディ作れ!(尊厳破壊)それか生放送でゴリラの(ry
ただGBAのリサンプリング周波数を「8bit 65536Hz」にして65536HzのPCMを再生すると速度がズレます。調査の結果、録音と波形がピッタリ合うのは2Hz低い65534Hzでした。32768Hzで再生なら32767Hzに、16384Hzで再生なら16383.5Hzのデータを流さないといけません。……なんで?知らん。
これも公開直前に気付いたけど動画の波形比較ズレてね?修正前だったっけ(
でも“音質”については、ちゃんと分かったよね?ね?(非公認マスコットキャラクタームーブ)
2. MP2kテスト
市販GBAゲームで使われている公式サウンドドライバ「MP2k」を調べて“らしさ”を理解しようとしました。
これについては資料が充実していて、ゲームROMを読み込んで曲を再生するツールも色々あります。
↑ agbplay-ncを改変しながら実験してました、windowsでの表示バグとかも少し直したり
↑ 名前にsynthって付いてるけどagbplayのコア部分を取り出しただけのプレイヤー
結局ゲームから1曲入りROM出力、agbplayからプレイヤーの最小実装を作り出すところまでは作ったけど、いっそMP2k互換ドライバでも作るか!で始めたにしては、調べていたドライバの細かいバージョン差?曲の抽出失敗?かでなんかダメっぽく、時間かかりそうなのでとりあえず断念。
ちなみに「GBAゲームは音が悪い」のはMP2kがミキシング時に、曲のチャンネル数と同じ回数量子化され、精度が失われているのが原因らしいです → ipatix/gba-hq-mixer
仕組みを画像で上手く伝えるのがめんど難しいのでなんとか理解してください(
MP2kテストの結果がアレで悩んでいると、akkeraさんが急に「作ったよ!」つって投げてくれました。
救世主か??マジデ
↑ 音色は256サンプルの自作波形データ、演奏データはROMに埋め込み済、それを13379Hzでミキシングして再生。ソロ再生も可
結局“らしさ”は13379Hzでミックスした時の劣化なのか、驚くほど“それっぽく”なりました。……13379(=17x787)に何か数値的なこじつけを見出して勝手に納得していたけどド忘れした( とりあえずMP2kの初期値らしい(
GBAチップチューンと制作ツール
方向性は決まりました!とりあえず136_pcm_adsr_test2と131_shuumatsu_bgm_testを合体!!
曲データ再設計の時間はもうなかったので、演奏データの長さ(Tick数)を合わせて、せーの!で同時再生する不安定合体です(
↑ SndがPCMのカウント、VgmがgPSGのカウント。VCNTと背景の緑はCPU使用率(76/228 = 33%)で、ACTがPCM部の同時発音数
上の画像は完成したROMで再生している様子ですが、ほぼいつもの再生画面ですよね。
再生環境は136ベースで拡張しつつ、作曲環境は外側に作りました。というか行き当たりばったりで↓
問題1. pythonで吐き出した波形データを聞くだけにROMビルドが必要……LSDjみたいにすぐ聞きたい!!
↑ snd_engine.py: PC用の音確認コンソールアプリ
音が鳴るだけの黒い窓です(波形編集アプリ、打ち込み用アプリから曲データを飛ばして使う)
問題2. 波形データをリアルタイム編集できて、すぐ音が鳴って、便利なGUIがいい!!
↑ Wave Designer: 波形データのリアルタイム編集アプリ
256サンプルの波形データ(Wave Preset)を視覚的にわかりやすくしたのが右上の表(LSDjならWAVE画面)
エンベロープ(ADSR Preset)の時間変化を視覚的にわかりやすくしたのが右下の表(LSDjならINST画面)
LFO(SSFX Preset)はPitch(LSDjのVやPコマンド、PAN(Oコマンド)、VOL(Eコマンド)辺りの機能
SongDataは演奏データ(テスト用)、Wave9+ADSR20+A4→(2拍休み)→B4→(2拍休み)→C5→(2拍休み)が入ってます。
問題3. 音色は作れたけど……演奏データを本格的に打ち込むのはこの小さい窓じゃ無理!(本当に忘れてた)
今からGBA上にLSDj風のなんかを実装するのは……もっと無理!!
↑ Songdata Editor: 簡易トラッカー(再生位置をトラッキングする機能なし)
右から、2小節のミニマップ(LSDjならSONG画面)、2拍のミニマップ(LSDjならCHAIN画面)、音置くとこ(LSDjならPHRASE画面)です。長年LSDjを使っていた人間はここまでLSDjに依存してしまうんですね、いやー恐ろしい(
あと見ての通り1拍=22Tick固定でBPM変更できません、どれだけヤバかったのか物語ってますね
最後に. GBAっぽい短いリバーブやらパン機能やらをGBAにごちゃごちゃ付けて結局パンは使わなくて完成!
↑ 完成したらSP実機でROMを起動して録音。ハードは違ってもいつも通りです
この開発ラッシュで「GBA上の2つのドライバのdesync」以外に大きなバグが出なかったのは奇跡でした(
↑ 例大祭当日まで毎日蓬屋ふらんさんがみんなの曲を紹介してくれていました
曲はチップチューン合同らしく、GB音源部分をメインにして音が増えていって賑やかに、と「初めてのGBA曲」らしくできました!
ちなみに2曲提出したので普通の(=ドコドコ言う)GB音源のアレンジもあります(今更)
では、改めて……「幻想郷レトロカーニバル」は、サークル「フランソワさんのよもぎ畑」の蓬屋ふらんさん主催の東方チップチューン合同CDです!
前回の「幻想郷レトロミュージカル」から10年半ぶり2回目で……本当にすごいメンバー(語彙力)
様々なハードのチップチューン、そして各アレンジャーの個性が詰まった素敵な4枚組CDになってます!
というか、こんな記事に辿り着いてしまった人は持ってて損ないです!たとえ東方を1ミリも知らなくても!!
つーわけでオススメです!! とりあえずクロスフェード聞け!!
GB用ゲーム「八雲迷路帖 仮ver」
で、最後は今月頒布したGB用ブロック崩し風自作ゲーム開発の話です。
みんなで準備してきたレトロカーニバルの情報解禁の日がついにやってきて「……俺もそろそろ準備しよ」で急に作り出しました(
↓ 左: twitterの告知で使った動画 (※ 音が出ます) 右: ゲーム画面
で、ゲームだから記事が長くなる……と思わせて、毎秒420Tickの処理が安定する強力なエンジン(ドライバ)が既にあるので、新機能実装は実は少ないです。
一枚絵の書き換え機能を小さく使ってブロックを消したり出したり、メニューのカーソル移動機能で霊夢を移動したり、トラック番号の動的タイル書き換え機能で陰陽玉が回ってます。
表示の実装がすぐ終わって余裕を感じつつ、のんきに玉の衝突判定を作り始めたらすぐ地獄になりました(
というのは単純に処理が重い!反射角とか計算しようもんなら崩壊です(表示はラグに対応しているが計算は未対応)
なので、バー(パドル)の反射は比較的軽い某ービィのブロックボール方式にしました。↓
layout.asm
db 9, 2 ; X = 0-7(左側: 0 が最も外側、7 が中央寄り)
db 8, 3
db 7, 4
db 6, 5
db 5, 6
db 4, 7
db 3, 8
db 2, 9
db 2, 9 ; X = 8-15(右側: 8 が中央寄り、15 が最も外側)
db 3, 8
db 4, 7
db 5, 6
db 6, 5
db 7, 4
db 8, 3
db 9, 2
↑ 左: 1px単位だけど一応目盛り書きました 右: 16pxに対応した16段階、Nフレームあたりの玉の移動距離。X軸, Y軸
飛んできた方向は無視でバー(霊夢の持っている札)に当たった位置から反射方向を決めてます。
つまり玉を完全に制御するには1ピクセルの位置調整が必要です……改めて考えるとヤバいな?(
ブロック衝突時の反射も入れるつもりでしたが……「進行方向を変更する」のはブロックの正面or側面判定との組み合わせでえらいことになって間に合いませんでした(
一瞬「これ、場合によっては玉が弾むだけの謎ソフトを頒布か?」とか考えたりしたけど、ブロックを消すだけなら負荷は問題なく、見た目も靈異伝っぽいのでこの仕様にしました、頒布前日に(
で、得点やらステージ変化やら色々追加して、ハイスコアを目指すゲームとして遊べる形になりました!
……間に合ってよかったー!!(
ちなみに「当たってるのにブロックが消えない」ように見えるのは、玉の当たり判定が下にあるからです
↑ 赤い四角が判定位置、こうなってしまったのは一番軽い実装だったからです(
分かれば挙動は理解できるけど、納得できるかは別な感じですいません!というかバグでは?(ぉぃ
あと得点の伸び方には法則があります。……以上、「八雲迷路帖 仮ver」の攻略情報(?)でした(
ハイスコア出したら#八雲迷路帖スコアタに画像上げてね!今なら1つでもブロック消した時点で世界3位です
例大祭行ってない?自家通販やってます!!
あとがき
改めて振り返ってみるとなんか色々進展があった1年だったみたいです(
なんか書き忘れていそうなことがありそうな気がするくらい
とりあえずGB用ゲーム……のデモ版を頒布できて作る作る詐欺にならずに済みました(
で、色々作って研究が進んだ分、次はそろそろ作曲系ツールのパワーアップでもしようかなと。
GBAチップチューンもですが、まだGBで出来るアイデアでやってないアレやコレが色々あります。
GBAのほうは高性能過ぎてどんな音作りでも出来そうで困る……無圧縮PCMは容量がアレだけど(
FM音源 on GBAも少しやってみたくはある
ゲームはタイトルの“八雲迷路帖”らしいステージや曲やボスをこれから追加して完成させるつもりです!
ただ5秒で考えたタイトルなのでタイトル自体は変えるかもしれません(
懸念要素だった初代GBの液晶でも、動く物が少なければ遊べるって確認できたし大丈夫なはずたぶん
……どういう構成(ステージ数とか)でいくかとかはまだふわふわしてます(
はやくこうなりたい(1年ぶり2度目)
どちらかと言うと、わたくし開発するのがとーっても楽しくて、アニメやゲームが疎かになっていますわ~ (現在PLv67)
おしまいですわ
……
思い出した!!
ニンテンドーミュージアムに行ってきました!!
見渡す限り宝の山だったのは言うまでもないし書き始めると止まらんので他のマニアが書いてくれそうな内容は全部割愛!!
64コンコレクターで64コン集めてるけど……これは家に入らんな(
で、お昼を食べようと一旦建物から出て、カービィ見つけて、
すぐ左の傘立てにゲームボーイ付いてて……
数字もついてて……
!!
黄ブロスどうみてもpocketが…… 903 で、とてもびっくりでした(小並感) ……偶然だよな?
おわり