OSDN Git Service

[VM][FMTOWNS][MEMORY] Fix setup around memory banks by I/O 0404h and 0480h.
[csp-qt/common_source_project-fm7.git] / source / src / vm / fmgen / opna.h
1 // ---------------------------------------------------------------------------
2 //      OPN/A/B interface with ADPCM support
3 //      Copyright (C) cisc 1998, 2003.
4 // ---------------------------------------------------------------------------
5 //      $Id: opna.h,v 1.33 2003/06/12 13:14:37 cisc Exp $
6
7 #ifndef FM_OPNA_H
8 #define FM_OPNA_H
9
10 #include "../../common.h"
11 #include "fmgen.h"
12 #include "fmtimer.h"
13 #include "psg.h"
14
15 // ---------------------------------------------------------------------------
16 //      class OPN/OPNA
17 //      OPN/OPNA に良く似た音を生成する音源ユニット
18 //
19 //      interface:
20 //      bool Init(uint clock, uint rate, bool, const _TCHAR* path);
21 //              初期化.このクラスを使用する前にかならず呼んでおくこと.
22 //              OPNA の場合はこの関数でリズムサンプルを読み込む
23 //
24 //              clock:  OPN/OPNA/OPNB のクロック周波数(Hz)
25 //
26 //              rate:   生成する PCM の標本周波数(Hz)
27 //
28 //              path:   リズムサンプルのパス(OPNA のみ有効)
29 //                              省略時はカレントディレクトリから読み込む
30 //                              文字列の末尾には '\' や '/' などをつけること
31 //
32 //              返り値       初期化に成功すれば true
33 //
34 //      bool LoadRhythmSample(const _TCHAR* path)
35 //              (OPNA ONLY)
36 //              Rhythm サンプルを読み直す.
37 //              path は Init の path と同じ.
38 //
39 //      bool SetRate(uint clock, uint rate, bool)
40 //              クロックや PCM レートを変更する
41 //              引数等は Init を参照のこと.
42 //
43 //      void Mix(FM_SAMPLETYPE* dest, int nsamples)
44 //              Stereo PCM データを nsamples 分合成し, dest で始まる配列に
45 //              加える(加算する)
46 //              ・dest には sample*2 個分の領域が必要
47 //              ・格納形式は L, R, L, R... となる.
48 //              ・あくまで加算なので,あらかじめ配列をゼロクリアする必要がある
49 //              ・FM_SAMPLETYPE が short 型の場合クリッピングが行われる.
50 //              ・この関数は音源内部のタイマーとは独立している.
51 //                Timer は Count と GetNextEvent で操作する必要がある.
52 //
53 //      void Reset()
54 //              音源をリセット(初期化)する
55 //
56 //      void SetReg(uint reg, uint data)
57 //              音源のレジスタ reg に data を書き込む
58 //
59 //      uint GetReg(uint reg)
60 //              音源のレジスタ reg の内容を読み出す
61 //              読み込むことが出来るレジスタは PSG, ADPCM の一部,ID(0xff) とか
62 //
63 //      uint ReadStatus()/ReadStatusEx()
64 //              音源のステータスレジスタを読み出す
65 //              ReadStatusEx は拡張ステータスレジスタの読み出し(OPNA)
66 //              busy フラグは常に 0
67 //
68 //      bool ReadIRQ()
69 //              IRQ 出力を読み出す
70 //
71 //      bool Count(uint32 t)
72 //              音源のタイマーを t [clock] 進める.
73 //              音源の内部状態に変化があった時(timer オーバーフロー)
74 //              true を返す
75 //
76 //      uint32 GetNextEvent()
77 //              音源のタイマーのどちらかがオーバーフローするまでに必要な
78 //              時間[clock]を返す
79 //              タイマーが停止している場合は ULONG_MAX を返す… と思う
80 //
81 //      void SetVolumeFM(int db_l, int db_r)/SetVolumePSG(int db_l, int db_r) ...
82 //              各音源の音量を+−方向に調節する.標準値は 0.
83 //              単位は約 1/2 dB,有効範囲の上限は 20 (10dB)
84 //
85 class CSP_Logger;
86 namespace FM
87 {
88         //      OPN Base -------------------------------------------------------
89         class DLL_PREFIX OPNBase : public Timer
90         {
91         protected:
92                 int chip_num;
93         public:
94                 OPNBase();
95                 virtual ~OPNBase() {}
96
97                 bool    Init(uint c, uint r);
98                 virtual void Reset();
99                 bool    ReadIRQ();
100
101                 void    SetVolumeFM(int db_l, int db_r);
102                 void    SetVolumePSG(int db_l, int db_r);
103                 void    SetLPFCutoff(uint freq) {}      // obsolete
104                 uint    GetPrescaler() { return prescale; }
105                 bool    is_ay3_891x;
106
107         protected:
108                 void    SetParameter(Channel4* ch, uint addr, uint data);
109                 virtual void    SetPrescaler(uint p);
110                 void    RebuildTimeTable();
111                 void    Intr(bool value);
112
113                 bool ProcessState(void *f, bool loading);
114
115                 int             fmvolume_l;
116                 int             fmvolume_r;
117
118                 uint    clock;                          // OPN クロック
119                 uint    rate;                           // FM 音源合成レート
120                 uint    psgrate;                        // FMGen  出力レート
121                 uint    status;
122                 bool    interrupt;
123                 Channel4* csmch;
124
125
126                 __DECL_ALIGNED(16) static  uint32 lfotable[8];
127         private:
128                 void    TimerA();
129
130         protected:
131                 uint8   prescale;
132                 Chip    chip;
133                 PSG             psg;
134         };
135
136         //      OPNA Base ------------------------------------------------------
137         class DLL_PREFIX OPNABase : public OPNBase
138         {
139         public:
140                 OPNABase();
141                 ~OPNABase();
142
143                 uint    ReadStatus() { return status & 0x03; }
144                 uint    ReadStatusEx();
145                 void    SetChannelMask(uint mask);
146
147         private:
148                 void    MakeTable2();
149
150         protected:
151                 bool    Init(uint c, uint r, bool);
152                 bool    SetRate(uint c, uint r, bool);
153
154                 void    Reset();
155                 void    SetReg(uint addr, uint data);
156                 void    SetADPCMBReg(uint reg, uint data);
157                 uint    GetReg(uint addr);
158
159                 bool ProcessState(void *f, bool loading);
160
161         protected:
162                 void    FMMix(Sample* buffer, int nsamples);
163                 void    Mix6(Sample* buffer, int nsamples, int activech);
164
165                 void    MixSubS(int activech, ISample**);
166                 void    MixSubSL(int activech, ISample**);
167
168                 void    SetStatus(uint bit);
169                 void    ResetStatus(uint bit);
170                 void    UpdateStatus();
171                 void    LFO();
172
173                 void    DecodeADPCMB();
174                 void    ADPCMBMix(Sample* dest, uint count);
175
176                 void    WriteRAM(uint data);
177                 uint    ReadRAM();
178                 int             ReadRAMN();
179                 int             DecodeADPCMBSample(uint);
180
181         // FM 音源関係
182                 __DECL_ALIGNED(16) uint8        pan[6];
183                 __DECL_ALIGNED(16) uint8        fnum2[9];
184
185                 uint8   reg22;
186                 uint    reg29;          // OPNA only?
187
188                 uint    stmask;
189                 uint    statusnext;
190
191                 uint32  lfocount;
192                 uint32  lfodcount;
193
194                 __DECL_ALIGNED(16) uint fnum[6];
195                 __DECL_ALIGNED(16) uint fnum3[3];
196
197         // ADPCM 関係
198                 uint8*  adpcmbuf;               // ADPCM RAM
199                 uint    adpcmmask;              // メモリアドレスに対するビットマスク
200                 uint    adpcmnotice;    // ADPCM 再生終了時にたつビット
201                 uint    startaddr;              // Start address
202                 uint    stopaddr;               // Stop address
203                 uint    memaddr;                // 再生中アドレス
204                 uint    limitaddr;              // Limit address/mask
205                 int             adpcmlevel;             // ADPCM 音量
206                 int             adpcmvolume_l;
207                 int             adpcmvolume_r;
208                 int             adpcmvol_l;
209                 int             adpcmvol_r;
210                 uint    deltan;                 // N
211                 int             adplc;                  // 周波数変換用変数
212                 int             adpld;                  // 周波数変換用変数差分値
213                 uint    adplbase;               // adpld の元
214                 int             adpcmx;                 // ADPCM 合成用 x
215                 int             adpcmd;                 // ADPCM 合成用
216                 int             adpcmout_l;             // ADPCM 合成後の出力
217                 int             adpcmout_r;             // ADPCM 合成後の出力
218                 int             apout0_l;                       // out(t-2)+out(t-1)
219                 int             apout0_r;                       // out(t-2)+out(t-1)
220                 int             apout1_l;                       // out(t-1)+out(t)
221                 int             apout1_r;                       // out(t-1)+out(t)
222
223                 uint    adpcmreadbuf;   // ADPCM リード用バッファ
224                 bool    adpcmplay;              // ADPCM 再生中
225                 int8    granuality;
226                 bool    adpcmmask_;
227
228                 uint8   control1;               // ADPCM コントロールレジスタ1
229                 uint8   control2;               // ADPCM コントロールレジスタ2
230                 __DECL_ALIGNED(16) uint8        adpcmreg[8];    // ADPCM レジスタの一部分
231
232                 int             rhythmmask_;
233
234                 __DECL_ALIGNED(16) Channel4 ch[6];
235
236                 static void     BuildLFOTable();
237                 __DECL_ALIGNED(16) static int amtable[FM_LFOENTS];
238                 __DECL_ALIGNED(16) static int pmtable[FM_LFOENTS];
239                 __DECL_ALIGNED(16) static int32 tltable[FM_TLENTS+FM_TLPOS];
240                 static bool     tablehasmade;
241         };
242
243         //      OPN2 Base ------------------------------------------------------
244         class DLL_PREFIX OPN2Base : public OPNBase
245         {
246         public:
247                 OPN2Base();
248                 ~OPN2Base();
249
250                 uint    ReadStatus() { return status & 0x7f; }
251                 uint    ReadStatusEx()  { return 0xff; }
252                 void    SetChannelMask(uint mask);
253
254         private:
255                 void    MakeTable2();
256
257         protected:
258                 bool    Init(uint c, uint r, bool);
259                 bool    SetRate(uint c, uint r, bool);
260                 virtual void SetPrescaler(uint p);
261
262                 void    Reset();
263                 void    SetReg(uint addr, uint data);
264                 uint    GetReg(uint addr);
265
266                 bool ProcessState(void *f, bool loading);
267
268         protected:
269                 void    FMMix(Sample* buffer, int nsamples);
270                 void    Mix6(Sample* buffer, int nsamples, int activech);
271
272                 void    MixSubS(int activech, ISample**);
273                 void    MixSubSL(int activech, ISample**);
274
275                 void    SetStatus(uint bit);
276                 void    ResetStatus(uint bit);
277                 void    UpdateStatus();
278                 void    LFO();
279
280         // FM 音源関係
281                 __DECL_ALIGNED(16) uint8        pan[6];
282                 __DECL_ALIGNED(16) uint8        fnum2[9];
283
284                 uint8   reg22;
285                 uint    reg29;          // OPNA only?
286
287                 uint    stmask;
288
289                 uint32  lfocount;
290                 uint32  lfodcount;
291
292                 __DECL_ALIGNED(16) uint fnum[6];
293                 __DECL_ALIGNED(16) uint fnum3[3];
294
295                 __DECL_ALIGNED(16) Channel4 ch[6];
296                 int32   dac_data;
297                 bool    dac_enabled;
298
299                 static void     BuildLFOTable();
300                 __DECL_ALIGNED(16) static int amtable[FM_LFOENTS];
301                 __DECL_ALIGNED(16) static int pmtable[FM_LFOENTS];
302                 __DECL_ALIGNED(16) static int32 tltable[FM_TLENTS+FM_TLPOS];
303                 static bool     tablehasmade;
304         };
305         //      YM2203(OPN) ----------------------------------------------------
306         class DLL_PREFIX OPN : public OPNBase
307         {
308         public:
309                 OPN();
310                 virtual ~OPN() {}
311
312                 bool    Init(uint c, uint r, bool=false, const char* =0);
313                 bool    SetRate(uint c, uint r, bool=false);
314
315                 void    Reset();
316                 void    Mix(Sample* buffer, int nsamples);
317                 void    SetReg(uint addr, uint data);
318                 uint    GetReg(uint addr);
319                 uint    ReadStatus() { return status & 0x03; }
320                 uint    ReadStatusEx() { return 0xff; }
321
322                 void    SetChannelMask(uint mask);
323
324                 int             dbgGetOpOut(int c, int s) { return ch[c].op[s].dbgopout_; }
325                 int             dbgGetPGOut(int c, int s) { return ch[c].op[s].dbgpgout_; }
326                 Channel4* dbgGetCh(int c) { return &ch[c]; }
327
328                 bool ProcessState(void *f, bool loading);
329
330         private:
331                 void    SetStatus(uint bit);
332                 void    ResetStatus(uint bit);
333
334                 __DECL_ALIGNED(16) uint fnum[3];
335                 __DECL_ALIGNED(16) uint fnum3[3];
336                 __DECL_ALIGNED(16) uint8        fnum2[6];
337
338                 __DECL_ALIGNED(16) Channel4 ch[3];
339         };
340
341         //      YM2608(OPNA) ---------------------------------------------------
342         class DLL_PREFIX OPNA : public OPNABase
343         {
344         public:
345                 OPNA();
346                 virtual ~OPNA();
347
348                 bool    Init(uint c, uint r, bool  = false, const _TCHAR* rhythmpath=0);
349                 bool    LoadRhythmSample(const _TCHAR*);
350
351                 bool    SetRate(uint c, uint r, bool = false);
352                 void    Mix(Sample* buffer, int nsamples);
353
354                 void    Reset();
355                 void    SetReg(uint addr, uint data);
356                 uint    GetReg(uint addr);
357
358                 void    SetVolumeADPCM(int db_l, int db_r);
359                 void    SetVolumeRhythmTotal(int db_l, int db_r);
360                 void    SetVolumeRhythm(int index, int db_l, int db_r);
361
362                 uint8*  GetADPCMBuffer() { return adpcmbuf; }
363
364                 int             dbgGetOpOut(int c, int s) { return ch[c].op[s].dbgopout_; }
365                 int             dbgGetPGOut(int c, int s) { return ch[c].op[s].dbgpgout_; }
366                 Channel4* dbgGetCh(int c) { return &ch[c]; }
367
368                 bool ProcessState(void *f, bool loading);
369
370         private:
371                 struct Rhythm
372                 {
373                         uint8   pan;            // ぱん
374                         int8    level;          // おんりょう
375                         int             volume_l;               // おんりょうせってい
376                         int             volume_r;               // おんりょうせってい
377                         int16*  sample;         // さんぷる
378                         uint    size;           // さいず
379                         uint    pos;            // いち
380                         uint    step;           // すてっぷち
381                         uint    rate;           // さんぷるのれーと
382                 };
383
384                 void    RhythmMix(Sample* buffer, uint count);
385
386         // リズム音源関係
387                 __DECL_ALIGNED(16) Rhythm       rhythm[6];
388                 int8    rhythmtl;               // リズム全体の音量
389                 int             rhythmtvol_l;
390                 int             rhythmtvol_r;
391                 uint8   rhythmkey;              // リズムのキー
392         };
393
394         //      YM2610/B(OPNB) ---------------------------------------------------
395         class DLL_PREFIX OPNB : public OPNABase
396         {
397         public:
398                 OPNB();
399                 virtual ~OPNB();
400
401                 bool    Init(uint c, uint r, bool = false,
402                                          uint8 *_adpcma = 0, int _adpcma_size = 0,
403                                          uint8 *_adpcmb = 0, int _adpcmb_size = 0);
404
405                 bool    SetRate(uint c, uint r, bool = false);
406                 void    Mix(Sample* buffer, int nsamples);
407
408                 void    Reset();
409                 void    SetReg(uint addr, uint data);
410                 uint    GetReg(uint addr);
411                 uint    ReadStatusEx();
412
413                 void    SetVolumeADPCMATotal(int db_l, int db_r);
414                 void    SetVolumeADPCMA(int index, int db_l, int db_r);
415                 void    SetVolumeADPCMB(int db_l, int db_r);
416
417 //              void    SetChannelMask(uint mask);
418
419         private:
420                 struct ADPCMA
421                 {
422                         uint8   pan;            // ぱん
423                         int8    level;          // おんりょう
424                         int             volume_l;               // おんりょうせってい
425                         int             volume_r;               // おんりょうせってい
426                         uint    pos;            // いち
427                         uint    step;           // すてっぷち
428
429                         uint    start;          // 開始
430                         uint    stop;           // 終了
431                         uint    nibble;         // 次の 4 bit
432                         int             adpcmx;         // 変換用
433                         int             adpcmd;         // 変換用
434                 };
435
436                 int             DecodeADPCMASample(uint);
437                 void    ADPCMAMix(Sample* buffer, uint count);
438                 static void InitADPCMATable();
439
440         // ADPCMA 関係
441                 uint8*  adpcmabuf;              // ADPCMA ROM
442                 int             adpcmasize;
443                 __DECL_ALIGNED(16) ADPCMA       adpcma[6];
444                 int8    adpcmatl;               // ADPCMA 全体の音量
445                 int             adpcmatvol_l;
446                 int             adpcmatvol_r;
447                 uint8   adpcmakey;              // ADPCMA のキー
448                 int             adpcmastep;
449                 __DECL_ALIGNED(16) uint8        adpcmareg[32];
450
451                 __DECL_ALIGNED(16) static int jedi_table[(48+1)*16];
452
453                 __DECL_ALIGNED(16) Channel4 ch[6];
454         };
455
456         //      YM2612/3438(OPN2) ----------------------------------------------------
457         class DLL_PREFIX OPN2 : public OPN2Base
458         {
459         public:
460                 OPN2();
461                 virtual ~OPN2();
462
463                 bool    Init(uint c, uint r, bool=false, const char* =0);
464                 bool    SetRate(uint c, uint r, bool);
465
466                 void    Reset();
467                 void    Mix(Sample* buffer, int nsamples);
468                 void    SetReg(uint addr, uint data);
469                 uint    GetReg(uint addr);
470                 uint    ReadStatus() { return status & 0x03; }
471                 uint    ReadStatusEx() { return 0xff; }
472
473                 bool ProcessState(void *f, bool loading);
474
475         private:
476                 //void  SetStatus(uint bit);
477                 //void  ResetStatus(uint bit);
478         // 線形補間用ワーク
479                 int32   mixc, mixc1;
480         };
481 }
482
483 // ---------------------------------------------------------------------------
484
485 inline void FM::OPNBase::RebuildTimeTable()
486 {
487         int p = prescale;
488         prescale = -1;
489         SetPrescaler(p);
490 }
491
492 inline void FM::OPNBase::SetVolumePSG(int db_l, int db_r)
493 {
494         psg.SetVolume(db_l, db_r, is_ay3_891x);
495 }
496
497 #endif // FM_OPNA_H