OSDN Git Service

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