PCM(YM2612)
概要
メガドライブには、スーパーファミコンやネオジオ等の様なPCM専用のRAMは無く、
CPUからダイレクトにDACへPCMデータをストリーミングする必要があります。
この為、安定した高サンプリングレート再生を実現するには、
一般的にはZ80をPCM再生の為だけに使い、
その他の全ての処理は68000を使います。
またPCMの出力方法としては通常YM2612のDACを利用しますが、
その場合はFM音源の同時発音数が1音減るので、
YM2612のDACを使用せず、PSG音源を代用する事でFM音源の発音数を減らさずに済ませるソフトが存在します。
但しPSG音源を使った場合、PSG音源1chのみでは4bitの制度しか無いので、
綺麗な音を出すには3ch同時発音させる等して精度を高める必要があります。
YM2612のDACを利用したPCM
YM2612のDACを使うには、まずYM2612のレジスタ 0x2B にデータ 0x80
を書き込んでDACを有効にします。
このDACはFM音源6ch目の為のDACを流用しているので、
FM音源の6ch目が無効になります。
以降は望みのサンプリングレートになる様に一定周期でYM2612のレジスタ 0x2A
にPCMデータを書き込む事でPCM再生となります。
Z80 PCMドライバの例
;--------------------------------------------------------------------- ;SOUND DRIVER (C) Minami Youichi 09.23.2008 - 10.04.2008 ; ;使う人居るか知らんけど、このサウンドドライバの使い方: ; このコードを 0xA00000(Z80のRAMエリア)に転送したら、 ; あとは鳴らしたい時に以下のシーケンスを実行すればOK。 ; ; 1. 0xA00010 にPCMスタートアドレスをぶち込む ; 2. 0xA00014 にPCMエンドアドレスをぶち込む ; 3. 0xA00015 に 0x00 をぶち込む ; ; スタートアドレスとエンドアドレスがバンクを跨いでいると死ぬ。 ; なのでバンク(32KBytes単位)を跨がない範囲に揃える必要がある。 ; ; PCMのフォーマットはYM2151のDACデータそのまんま。 ; ;アセンブルの仕方: ; Zilogスタンダードな書き方したつもり。 ; ZASMとかアブソリュートアセンブラでHEXファイル吐かせたら、 ; HEX2BINとかでバイナリ作れば良い。 ; ;--------------------------------------------------------------------- A_SP: EQU 2000h BANK: EQU 6000h YM_REG: EQU 4000h YM_DAT: EQU 4001h ;--------------------------------------------------------------------- ORG 0000h DI ;割り込み禁止 LD SP, A_SP ;スタックポインタ初期化 IM 1 ;割り込みMODE 1 JP INIT ;RESET ;--------------------------------------------------------------------- ORG 0010h NOW1: DEFW 0000h ;PCMデータの終端位置 DEFW 0000h END1: DEFW 0000h ;現在のPCMデータ読み出し位置 DEFW 0000h PLAY1: DEFB 00h ;1=Set Start ;--------------------------------------------------------------------- ORG 0038h VSYNC: RETI ;VSYNC割り込み ;--------------------------------------------------------------------- ORG 0040h INIT: NOP SET1: LD HL, BANK ;バンクセレクト LD A, (NOW1+1) RLCA LD (HL), A ; bit 15 LD A, (NOW1+2) ; LD (HL), A ; bit 16 RRA LD (HL), A ; bit 17 RRA LD (HL), A ; bit 18 RRA LD (HL), A ; bit 19 RRA LD (HL), A ; bit 20 RRA LD (HL), A ; bit 21 XOR A ; 32Mカートリッジまでなら上位2bitは無視可能 LD (HL), A ; bit 22 LD (HL), A ; bit 23 LD A, 2Bh ;FM6無効, PCM有効 LD (YM_REG), A LD A, 80h LD (YM_DAT), A LD A, 2Ah ;PCMデータレジスタを選択 LD (YM_REG), A LD A, 01h ;メインループの準備 LD (PLAY1), A ;再生開始フラグをクリア LD BC, (NOW1) LD DE, (END1) SET 7, B ;15bit目を1にする(ROMアドレスが32K〜63Kなので) SET 7, D ;15bit目を1にする(ROMアドレスが32K〜63Kなので) LD HL, YM_DAT LP1: LD A, (PLAY1) ;13 メインループ AND A ; 4 JP Z, SET1 ;10 PCM1の再生開始フラグが0だったら初期化 LD A, B ; 4 CP D ; 4 JP Z, LP1 ;10 PCMエンドアドレスに到達していたら最初に戻る INC BC ; 6 ADDR_NOW++ LD A, (BC) ; 7 PCMデータをロード LD (HL), A ; 7 YM2151のデータポートに贈る ;計65Clock, 3579540/65= 55.070KHz (111.86Clockで32KHz) NOP ;以下無駄命令で周波数を合わせる NOP NOP NOP NOP NOP NOP NOP NOP JP LP1 ;10 END ;-------------------------------------------------------------