PC-9801-86をI/Oポート経由で叩く

ヤフオクでPC-9801-86を手に入れたので、PC-286VGにさして遊んだときの記録です。

誰得? -> 俺得。

基本

I/O 0x188でレジスタ番号を指定
I/O 0x18Aでデータを読み書き

ex. Reg07<-0x37

OUT &h188,&h07
OUT &h18A,&h37

ノイズ

Reg06h(ノイズ周期) 適当に設定(たとえば0x1F)
Reg08h(音量) (レベルはSSGと共有) 0x0Fにするとテスト的にはよい
Reg07h(出力設定) 0x37に設定すると音が出る!(注意: ビットを0にすると出力)

リズム

注意: OPNAモードに切り替えないと鳴りません!

OUT &hA460, (INP(&hA460) and &hFC) or 1
Reg11h(音量) 0x3F(最大)に設定
Reg18h~1Dh(各音量) 0xDF(L+R、0dB)に設定
Reg10h(NoteON) 0x3Fにすると全部鳴ります。これは1にしたやつが書き込んだ瞬間鳴る。

SSG

Reg01h/00h(4+8あわせて12bit) 周波数(出力したい音の)を変換した値をいれる。
 値=1/(Hz/8000000*64) (マスタークロックは8MHzのようです。)
  (f tone=ΦM/(64*値); ΦM=マスタークロック から変形)
Reg08h(音量) ノイズの項を参照(&~0x10にしておくように; エンベロープジェネレータを無効にする)
Reg07h(出力) 0x3Eとすれば鳴る(Tone A ON) (注意: ノイズの項でも書いたけど、ビットを0にすると出力)

エンベロープジェネレータであそぶ

とりあえず音を鳴らしておく
Reg0Ch/0Bh(8+8で16bit) 周波数(EGの)を変換した値をいれる。
 値=1/(Hz/8000000*1024)
  (f EG = ΦM / (1024 * 値); ΦM=マスタークロック から変換)
Reg0Dh(エンベロープ波形) 適当に設定。(pdf資料の31ページにある))
Reg08h(音量) 忘れずに0x10をandして、EGを有効にしておく
これで音量がエンベロープに従って出力されているはず。

FM

初期化

Reg29h 00hにする(CH4~6を使うときは80h、IRQ欲しいときは適宜ビットたてる)

CH1で440Hzのサイン波を鳴らす

4つのオペレータを並列接続にして、S1をサイン波、それ以外を音出さないようにすれば出る。それを実践。

まずはチャンネル/オペレータ設定

RegB0h 07hにする(CH1: Algorithm=7(4op並列)、Feedback=0)
RegA4h 24hにする(CH1: Block=4(octave)、Fnumber2=4(110b))
RegA0h 0Ehにする(CH1: Fnumber1=0Eh(00001110h))
 FnumberについてはPDF資料のp25を参考にしました。
 RegA4h/A0hはこの順番に書かないといけないらしい。(PDF資料より)
Reg30h 01hにする(CH1S1: detune=0 multiple=1)
Reg50h 08hにする(CH1S1: ks=0 AttackRate=15(Attack最速=NoteONで、すぐに最大音量になる))
Reg54h 00hにする(CH1S2: ks=0 AttackRate=0(Envelope無効))
Reg58h 00hにする(CH1S3: ks=0 AttackRate=0(Envelope無効))
Reg5Ch 00hにする(CH1S4: ks=0 AttackRate=0(Envelope無効))
 CH1のS2,3,4については、この段階で音が鳴らなくなっているので、ほかのパラメータは設定しなくてもよい。
Reg60h 00hにする(CH1S1: am=off DecayRate=0(最大音量のままキープ))
Reg80h 00hにする(CH1S1: SustainLevel=0(Decayなし、でもDR=0なので無意味)(注意: SLは減衰量を表すので、0がDecay無効となる) ReleaseRate=0)
Reg70h 00hにする(CH1S1: SustainRate=0(SLのままサステイン、でもDR=0なので無意味))
Reg40h 00hにする(CH1S1: TotalLevel=0(注意: 減衰量を表すので、0が最大)
Reg22h 00hにする(CH1: LFO=off FQ.CONT=0 つまりLFO無効)
RegB4h C0hにする(CH1: L/Rの出力ON、AMS=0 PMS=0)

実際に音を出す。

Reg28h 00hにする(S1234=off CH=1) = Note OFF)(これをやらないと前にNote ONだった場合次のNote ONで何も起きない)
Reg28h F0hにする(S1234=on CH=1) = Note ON(ここで鳴る、DR SL SRが1以上なら自然に減衰していく)
ちょっと待ってから…
Reg28h 00hにする(S1234=off CH=1) = Note OFF(明示的にOFF。RRが小さいほど遅く音が減衰するのがわかる)

PCM

PCMはOPNAのADPCMではなく、別につけられた(俗にいう?)86系PCMです。なので、Port188hは使わず、独自のI/Oポートを叩きます。

再生

PortA466h A0hを書く(音量最大) (注意 下位ニブルは0になるほど音量が大きくなる)
PortA468h(1度目) 08hを書く(FIFOをリセットする)
PortA46Ah F2hを書く(量子化ビット数はお好みで)
PortA46Ch データをひたすら書く!!(繰り返しWriteする)
PortA66Eh (注意 ポート番号はA66Ehです。A46Ehではありません!) 00hを書く。(出力有効化)
PortA468h(2度目) 87hなどを書く(FIFO ON、サンプリング周波数はお好みで。)
 これを書いたときに音が鳴るはず。

FIFOバッファはループで再生されるようです。もっと長く再生したいときはFIFO割り込みを有効にし、PortA46Ahで割り込みタイミングを有効にし、割り込みが入ったらFIFOバッファを書く、といったルーチンが必要になるとおもいます。[未検証]

…なんかうまく音が鳴らせない。変な音は出るけど、目的の音が出ない…

録音

まだできてないよ!!

参考文献

I/Oポート
http://www.webtech.co.jp/company/doc/undocumented_mem/io_sound.txt
YM2608データシート(日本語)
http://www.x68000.de/files/sheets/ym2608.pdf

ツッコミ欄

つくるのわすれてた…

お名前:
  • HTML
  • PDF
RSS2.0 RSS1.0 Atom1.0