OSDN Git Service

44fdf9b7399be03073a188ac9a94ff7d0787ddd0
[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 class csp_state_utils;
16 class CSP_Logger;
17 // ---------------------------------------------------------------------------
18 //      class OPN/OPNA
19 //      OPN/OPNA \82É\97Ç\82­\8e\97\82½\89¹\82ð\90\90¬\82·\82é\89¹\8c¹\83\86\83j\83b\83g
20 //      
21 //      interface:
22 //      bool Init(uint clock, uint rate, bool, const _TCHAR* path);
23 //              \8f\89\8aú\89»\81D\82±\82Ì\83N\83\89\83X\82ð\8eg\97p\82·\82é\91O\82É\82©\82È\82ç\82¸\8cÄ\82ñ\82Å\82¨\82­\82±\82Æ\81D
24 //              OPNA \82Ì\8fê\8d\87\82Í\82±\82Ì\8aÖ\90\94\82Å\83\8a\83Y\83\80\83T\83\93\83v\83\8b\82ð\93Ç\82Ý\8d\9e\82Þ
25 //
26 //              clock:  OPN/OPNA/OPNB \82Ì\83N\83\8d\83b\83N\8eü\94g\90\94(Hz)
27 //
28 //              rate:   \90\90¬\82·\82é PCM \82Ì\95W\96{\8eü\94g\90\94(Hz)
29 //
30 //              path:   \83\8a\83Y\83\80\83T\83\93\83v\83\8b\82Ì\83p\83X(OPNA \82Ì\82Ý\97L\8cø)
31 //                              \8fÈ\97ª\8e\9e\82Í\83J\83\8c\83\93\83g\83f\83B\83\8c\83N\83g\83\8a\82©\82ç\93Ç\82Ý\8d\9e\82Þ
32 //                              \95\8e\9a\97ñ\82Ì\96\96\94ö\82É\82Í '\' \82â '/' \82È\82Ç\82ð\82Â\82¯\82é\82±\82Æ
33 //
34 //              \95Ô\82è\92l  \8f\89\8aú\89»\82É\90¬\8c÷\82·\82ê\82Πtrue
35 //
36 //      bool LoadRhythmSample(const _TCHAR* path)
37 //              (OPNA ONLY)
38 //              Rhythm \83T\83\93\83v\83\8b\82ð\93Ç\82Ý\92¼\82·\81D
39 //              path \82Í Init \82Ì path \82Æ\93¯\82\81D
40 //              
41 //      bool SetRate(uint clock, uint rate, bool)
42 //              \83N\83\8d\83b\83N\82â PCM \83\8c\81[\83g\82ð\95Ï\8dX\82·\82é
43 //              \88ø\90\94\93\99\82Í Init \82ð\8eQ\8fÆ\82Ì\82±\82Æ\81D
44 //      
45 //      void Mix(FM_SAMPLETYPE* dest, int nsamples)
46 //              Stereo PCM \83f\81[\83^\82ð nsamples \95ª\8d\87\90¬\82µ\81C dest \82Å\8en\82Ü\82é\94z\97ñ\82É
47 //              \89Á\82¦\82é(\89Á\8eZ\82·\82é)
48 //              \81Edest \82É\82Í sample*2 \8cÂ\95ª\82Ì\97Ì\88æ\82ª\95K\97v
49 //              \81E\8ai\94[\8c`\8e®\82Í L, R, L, R... \82Æ\82È\82é\81D
50 //              \81E\82 \82­\82Ü\82Å\89Á\8eZ\82È\82Ì\82Å\81C\82 \82ç\82©\82\82ß\94z\97ñ\82ð\83[\83\8d\83N\83\8a\83A\82·\82é\95K\97v\82ª\82 \82é
51 //              \81EFM_SAMPLETYPE \82ª short \8c^\82Ì\8fê\8d\87\83N\83\8a\83b\83s\83\93\83O\82ª\8ds\82í\82ê\82é.
52 //              \81E\82±\82Ì\8aÖ\90\94\82Í\89¹\8c¹\93à\95\94\82Ì\83^\83C\83}\81[\82Æ\82Í\93Æ\97§\82µ\82Ä\82¢\82é\81D
53 //                Timer \82Í Count \82Æ GetNextEvent \82Å\91\80\8dì\82·\82é\95K\97v\82ª\82 \82é\81D
54 //      
55 //      void Reset()
56 //              \89¹\8c¹\82ð\83\8a\83Z\83b\83g(\8f\89\8aú\89»)\82·\82é
57 //
58 //      void SetReg(uint reg, uint data)
59 //              \89¹\8c¹\82Ì\83\8c\83W\83X\83^ reg \82É data \82ð\8f\91\82«\8d\9e\82Þ
60 //      
61 //      uint GetReg(uint reg)
62 //              \89¹\8c¹\82Ì\83\8c\83W\83X\83^ reg \82Ì\93à\97e\82ð\93Ç\82Ý\8fo\82·
63 //              \93Ç\82Ý\8d\9e\82Þ\82±\82Æ\82ª\8fo\97\88\82é\83\8c\83W\83X\83^\82Í PSG, ADPCM \82Ì\88ê\95\94\81CID(0xff) \82Æ\82©
64 //      
65 //      uint ReadStatus()/ReadStatusEx()
66 //              \89¹\8c¹\82Ì\83X\83e\81[\83^\83X\83\8c\83W\83X\83^\82ð\93Ç\82Ý\8fo\82·
67 //              ReadStatusEx \82Í\8ag\92£\83X\83e\81[\83^\83X\83\8c\83W\83X\83^\82Ì\93Ç\82Ý\8fo\82µ(OPNA)
68 //              busy \83t\83\89\83O\82Í\8fí\82É 0
69 //      
70 //      bool ReadIRQ()
71 //              IRQ \8fo\97Í\82ð\93Ç\82Ý\8fo\82·
72 //      
73 //      bool Count(uint32 t)
74 //              \89¹\8c¹\82Ì\83^\83C\83}\81[\82ð t [clock] \90i\82ß\82é\81D
75 //              \89¹\8c¹\82Ì\93à\95\94\8fó\91Ô\82É\95Ï\89»\82ª\82 \82Á\82½\8e\9e(timer \83I\81[\83o\81[\83t\83\8d\81[)
76 //              true \82ð\95Ô\82·
77 //
78 //      uint32 GetNextEvent()
79 //              \89¹\8c¹\82Ì\83^\83C\83}\81[\82Ì\82Ç\82¿\82ç\82©\82ª\83I\81[\83o\81[\83t\83\8d\81[\82·\82é\82Ü\82Å\82É\95K\97v\82È
80 //              \8e\9e\8aÔ[clock]\82ð\95Ô\82·
81 //              \83^\83C\83}\81[\82ª\92â\8e~\82µ\82Ä\82¢\82é\8fê\8d\87\82Í ULONG_MAX \82ð\95Ô\82·\81\82Æ\8ev\82¤
82 //      
83 //      void SetVolumeFM(int db_l, int db_r)/SetVolumePSG(int db_l, int db_r) ...
84 //              \8ae\89¹\8c¹\82Ì\89¹\97Ê\82ð\81{\81|\95û\8cü\82É\92²\90ß\82·\82é\81D\95W\8f\80\92l\82Í 0.
85 //              \92P\88Ê\82Í\96ñ 1/2 dB\81C\97L\8cø\94Í\88Í\82Ì\8fã\8cÀ\82Í 20 (10dB)
86 //
87 namespace FM
88 {
89         //      OPN Base -------------------------------------------------------
90         class DLL_PREFIX OPNBase : public Timer
91         {
92         protected:
93                 int chip_num;
94         public:
95                 OPNBase();
96                 virtual ~OPNBase() {}
97                 
98                 bool    Init(uint c, uint r);
99                 virtual void Reset();
100                 bool    ReadIRQ();
101                 
102                 void    SetVolumeFM(int db_l, int db_r);
103                 void    SetVolumePSG(int db_l, int db_r);
104                 void    SetLPFCutoff(uint freq) {}      // obsolete
105                 
106                 bool is_ay3_891x;
107
108         protected:
109                 void    SetParameter(Channel4* ch, uint addr, uint data);
110                 void    SetPrescaler(uint p);
111                 void    RebuildTimeTable();
112                 void    Intr(bool value);
113                 
114                 void DeclState(void *f);
115                 void SaveState(void *f);
116                 bool LoadState(void *f);
117                 
118                 int             fmvolume_l;
119                 int             fmvolume_r;
120                 
121                 uint    clock;                          // OPN \83N\83\8d\83b\83N
122                 uint    rate;                           // FM \89¹\8c¹\8d\87\90¬\83\8c\81[\83g
123                 uint    psgrate;                        // FMGen  \8fo\97Í\83\8c\81[\83g
124                 uint    status;
125                 bool    interrupt;
126                 Channel4* csmch;
127                 
128
129                 static  uint32 lfotable[8];
130         
131         private:
132                 void    TimerA();
133                 
134         protected:
135                 uint8   prescale;
136                 Chip    chip;
137                 PSG             psg;
138         };
139
140         //      OPN2 Base ------------------------------------------------------
141         class DLL_PREFIX OPNABase : public OPNBase
142         {
143         public:
144                 OPNABase();
145                 ~OPNABase();
146                 
147                 uint    ReadStatus() { return status & 0x03; }
148                 uint    ReadStatusEx();
149                 void    SetChannelMask(uint mask);
150         
151         private:
152                 void    MakeTable2();
153         
154         protected:
155                 bool    Init(uint c, uint r, bool);
156                 bool    SetRate(uint c, uint r, bool);
157
158                 void    Reset();
159                 void    SetReg(uint addr, uint data);
160                 void    SetADPCMBReg(uint reg, uint data);
161                 uint    GetReg(uint addr);      
162                 
163                 void DeclState(void *f);
164                 void SaveState(void *f);
165                 bool LoadState(void *f);
166         
167         protected:
168                 void    FMMix(Sample* buffer, int nsamples);
169                 void    Mix6(Sample* buffer, int nsamples, int activech);
170                 
171                 void    MixSubS(int activech, ISample**);
172                 void    MixSubSL(int activech, ISample**);
173
174                 void    SetStatus(uint bit);
175                 void    ResetStatus(uint bit);
176                 void    UpdateStatus();
177                 void    LFO();
178
179                 void    DecodeADPCMB();
180                 void    ADPCMBMix(Sample* dest, uint count);
181
182                 void    WriteRAM(uint data);
183                 uint    ReadRAM();
184                 int             ReadRAMN();
185                 int             DecodeADPCMBSample(uint);
186                 
187         // FM \89¹\8c¹\8aÖ\8cW
188                 uint8   pan[6];
189                 uint8   fnum2[9];
190                 
191                 uint8   reg22;
192                 uint    reg29;          // OPNA only?
193                 
194                 uint    stmask;
195                 uint    statusnext;
196
197                 uint32  lfocount;
198                 uint32  lfodcount;
199                 
200                 uint    fnum[6];
201                 uint    fnum3[3];
202                 
203         // ADPCM \8aÖ\8cW
204                 uint8*  adpcmbuf;               // ADPCM RAM
205                 uint    adpcmmask;              // \83\81\83\82\83\8a\83A\83h\83\8c\83X\82É\91Î\82·\82é\83r\83b\83g\83}\83X\83N
206                 uint    adpcmnotice;    // ADPCM \8dÄ\90\8fI\97¹\8e\9e\82É\82½\82Â\83r\83b\83g
207                 uint    startaddr;              // Start address
208                 uint    stopaddr;               // Stop address
209                 uint    memaddr;                // \8dÄ\90\92\86\83A\83h\83\8c\83X
210                 uint    limitaddr;              // Limit address/mask
211                 int             adpcmlevel;             // ADPCM \89¹\97Ê
212                 int             adpcmvolume_l;
213                 int             adpcmvolume_r;
214                 int             adpcmvol_l;
215                 int             adpcmvol_r;
216                 uint    deltan;                 // \87\99N
217                 int             adplc;                  // \8eü\94g\90\94\95Ï\8a·\97p\95Ï\90\94
218                 int             adpld;                  // \8eü\94g\90\94\95Ï\8a·\97p\95Ï\90\94\8d·\95ª\92l
219                 uint    adplbase;               // adpld \82Ì\8c³
220                 int             adpcmx;                 // ADPCM \8d\87\90¬\97p x
221                 int             adpcmd;                 // ADPCM \8d\87\90¬\97\87\99
222                 int             adpcmout_l;             // ADPCM \8d\87\90¬\8cã\82Ì\8fo\97Í
223                 int             adpcmout_r;             // ADPCM \8d\87\90¬\8cã\82Ì\8fo\97Í
224                 int             apout0_l;                       // out(t-2)+out(t-1)
225                 int             apout0_r;                       // out(t-2)+out(t-1)
226                 int             apout1_l;                       // out(t-1)+out(t)
227                 int             apout1_r;                       // out(t-1)+out(t)
228
229                 uint    adpcmreadbuf;   // ADPCM \83\8a\81[\83h\97p\83o\83b\83t\83@
230                 bool    adpcmplay;              // ADPCM \8dÄ\90\92\86
231                 int8    granuality;             
232                 bool    adpcmmask_;
233
234                 uint8   control1;               // ADPCM \83R\83\93\83g\83\8d\81[\83\8b\83\8c\83W\83X\83^\82P
235                 uint8   control2;               // ADPCM \83R\83\93\83g\83\8d\81[\83\8b\83\8c\83W\83X\83^\82Q
236                 uint8   adpcmreg[8];    // ADPCM \83\8c\83W\83X\83^\82Ì\88ê\95\94\95ª
237
238                 int             rhythmmask_;
239
240                 Channel4 ch[6];
241
242                 static void     BuildLFOTable();
243                 static int amtable[FM_LFOENTS];
244                 static int pmtable[FM_LFOENTS];
245                 static int32 tltable[FM_TLENTS+FM_TLPOS];
246                 static bool     tablehasmade;
247         };
248
249         //      YM2203(OPN) ----------------------------------------------------
250         class DLL_PREFIX OPN : public OPNBase
251         {
252         public:
253                 OPN();
254                 virtual ~OPN() {}
255                 
256                 bool    Init(uint c, uint r, bool=false, const char* =0);
257                 bool    SetRate(uint c, uint r, bool=false);
258                 
259                 void    Reset();
260                 void    Mix(Sample* buffer, int nsamples);
261                 void    SetReg(uint addr, uint data);
262                 uint    GetReg(uint addr);
263                 uint    ReadStatus() { return status & 0x03; }
264                 uint    ReadStatusEx() { return 0xff; }
265                 
266                 void    SetChannelMask(uint mask);
267                 
268                 int             dbgGetOpOut(int c, int s) { return ch[c].op[s].dbgopout_; }
269                 int             dbgGetPGOut(int c, int s) { return ch[c].op[s].dbgpgout_; }
270                 Channel4* dbgGetCh(int c) { return &ch[c]; }
271                 
272                 void DeclState(void *f);
273                 void SaveState(void *f);
274                 bool LoadState(void *f);
275         
276         private:
277                 void    SetStatus(uint bit);
278                 void    ResetStatus(uint bit);
279                 
280                 uint    fnum[3];
281                 uint    fnum3[3];
282                 uint8   fnum2[6];
283                 
284                 Channel4 ch[3];
285         };
286
287         //      YM2608(OPNA) ---------------------------------------------------
288         class DLL_PREFIX OPNA : public OPNABase
289         {
290         public:
291                 OPNA();
292                 virtual ~OPNA();
293                 
294                 bool    Init(uint c, uint r, bool  = false, const _TCHAR* rhythmpath=0);
295                 bool    LoadRhythmSample(const _TCHAR*);
296         
297                 bool    SetRate(uint c, uint r, bool = false);
298                 void    Mix(Sample* buffer, int nsamples);
299
300                 void    Reset();
301                 void    SetReg(uint addr, uint data);
302                 uint    GetReg(uint addr);
303
304                 void    SetVolumeADPCM(int db_l, int db_r);
305                 void    SetVolumeRhythmTotal(int db_l, int db_r);
306                 void    SetVolumeRhythm(int index, int db_l, int db_r);
307
308                 uint8*  GetADPCMBuffer() { return adpcmbuf; }
309
310                 int             dbgGetOpOut(int c, int s) { return ch[c].op[s].dbgopout_; }
311                 int             dbgGetPGOut(int c, int s) { return ch[c].op[s].dbgpgout_; }
312                 Channel4* dbgGetCh(int c) { return &ch[c]; }
313
314                 void DeclState(void *f);
315                 void SaveState(void *f);
316                 bool LoadState(void *f);
317                 
318         private:
319                 struct Rhythm
320                 {
321                         uint8   pan;            // \82Ï\82ñ
322                         int8    level;          // \82¨\82ñ\82è\82å\82¤
323                         int             volume_l;               // \82¨\82ñ\82è\82å\82¤\82¹\82Á\82Ä\82¢
324                         int             volume_r;               // \82¨\82ñ\82è\82å\82¤\82¹\82Á\82Ä\82¢
325                         int16*  sample;         // \82³\82ñ\82Õ\82é
326                         uint    size;           // \82³\82¢\82¸
327                         uint    pos;            // \82¢\82¿
328                         uint    step;           // \82·\82Ä\82Á\82Õ\82¿
329                         uint    rate;           // \82³\82ñ\82Õ\82é\82Ì\82ê\81[\82Æ
330                 };
331         
332                 void    RhythmMix(Sample* buffer, uint count);
333
334         // \83\8a\83Y\83\80\89¹\8c¹\8aÖ\8cW
335                 Rhythm  rhythm[6];
336                 int8    rhythmtl;               // \83\8a\83Y\83\80\91S\91Ì\82Ì\89¹\97Ê
337                 int             rhythmtvol_l;           
338                 int             rhythmtvol_r;           
339                 uint8   rhythmkey;              // \83\8a\83Y\83\80\82Ì\83L\81[
340         };
341
342         //      YM2610/B(OPNB) ---------------------------------------------------
343         class DLL_PREFIX OPNB : public OPNABase
344         {
345         public:
346                 OPNB();
347                 virtual ~OPNB();
348                 
349                 bool    Init(uint c, uint r, bool = false,
350                                          uint8 *_adpcma = 0, int _adpcma_size = 0,
351                                          uint8 *_adpcmb = 0, int _adpcmb_size = 0);
352         
353                 bool    SetRate(uint c, uint r, bool = false);
354                 void    Mix(Sample* buffer, int nsamples);
355
356                 void    Reset();
357                 void    SetReg(uint addr, uint data);
358                 uint    GetReg(uint addr);
359                 uint    ReadStatusEx();
360
361                 void    SetVolumeADPCMATotal(int db_l, int db_r);
362                 void    SetVolumeADPCMA(int index, int db_l, int db_r);
363                 void    SetVolumeADPCMB(int db_l, int db_r);
364
365 //              void    SetChannelMask(uint mask);
366                 
367         private:
368                 struct ADPCMA
369                 {
370                         uint8   pan;            // \82Ï\82ñ
371                         int8    level;          // \82¨\82ñ\82è\82å\82¤
372                         int             volume_l;               // \82¨\82ñ\82è\82å\82¤\82¹\82Á\82Ä\82¢
373                         int             volume_r;               // \82¨\82ñ\82è\82å\82¤\82¹\82Á\82Ä\82¢
374                         uint    pos;            // \82¢\82¿
375                         uint    step;           // \82·\82Ä\82Á\82Õ\82¿
376
377                         uint    start;          // \8aJ\8en
378                         uint    stop;           // \8fI\97¹
379                         uint    nibble;         // \8e\9f\82Ì 4 bit
380                         int             adpcmx;         // \95Ï\8a·\97p
381                         int             adpcmd;         // \95Ï\8a·\97p
382                 };
383         
384                 int             DecodeADPCMASample(uint);
385                 void    ADPCMAMix(Sample* buffer, uint count);
386                 static void InitADPCMATable();
387                 
388         // ADPCMA \8aÖ\8cW
389                 uint8*  adpcmabuf;              // ADPCMA ROM
390                 int             adpcmasize;
391                 ADPCMA  adpcma[6];
392                 int8    adpcmatl;               // ADPCMA \91S\91Ì\82Ì\89¹\97Ê
393                 int             adpcmatvol_l;           
394                 int             adpcmatvol_r;           
395                 uint8   adpcmakey;              // ADPCMA \82Ì\83L\81[
396                 int             adpcmastep;
397                 uint8   adpcmareg[32];
398  
399                 static int jedi_table[(48+1)*16];
400
401                 Channel4 ch[6];
402         };
403
404         //      YM2612/3438(OPN2) ----------------------------------------------------
405         class OPN2 : public OPNBase
406         {
407         public:
408                 OPN2();
409                 virtual ~OPN2() {}
410                 
411                 bool    Init(uint c, uint r, bool=false, const char* =0);
412                 bool    SetRate(uint c, uint r, bool);
413                 
414                 void    Reset();
415                 void    Mix(Sample* buffer, int nsamples);
416                 void    SetReg(uint addr, uint data);
417                 uint    GetReg(uint addr);
418                 uint    ReadStatus() { return status & 0x03; }
419                 uint    ReadStatusEx() { return 0xff; }
420                 
421                 void    SetChannelMask(uint mask);
422                 
423         private:
424                 void    SetStatus(uint bit);
425                 void    ResetStatus(uint bit);
426                 
427                 uint    fnum[3];
428                 uint    fnum3[3];
429                 uint8   fnum2[6];
430                 
431         // \90ü\8c`\95â\8aÔ\97p\83\8f\81[\83N
432                 int32   mixc, mixc1;
433                 
434                 Channel4 ch[3];
435         };
436 }
437
438 // ---------------------------------------------------------------------------
439
440 inline void FM::OPNBase::RebuildTimeTable()
441 {
442         int p = prescale;
443         prescale = -1;
444         SetPrescaler(p);
445 }
446
447 inline void FM::OPNBase::SetVolumePSG(int db_l, int db_r)
448 {
449         psg.SetVolume(db_l, db_r, is_ay3_891x);
450 }
451
452 #endif // FM_OPNA_H