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 $
10 #include "../../common.h"
15 class csp_state_utils;
17 // ---------------------------------------------------------------------------
19 // OPN/OPNA
\82É
\97Ç
\82
\8e\97\82½
\89¹
\82ð
\90¶
\90¬
\82·
\82é
\89¹
\8c¹
\83\86\83j
\83b
\83g
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Þ
26 // clock: OPN/OPNA/OPNB
\82Ì
\83N
\83\8d\83b
\83N
\8eü
\94g
\90\94(Hz)
28 // rate:
\90¶
\90¬
\82·
\82é PCM
\82Ì
\95W
\96{
\8eü
\94g
\90\94(Hz)
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Æ
34 //
\95Ô
\82è
\92l
\8f\89\8aú
\89»
\82É
\90¬
\8c÷
\82·
\82ê
\82Î true
36 // bool LoadRhythmSample(const _TCHAR* path)
38 // Rhythm
\83T
\83\93\83v
\83\8b\82ð
\93Ç
\82Ý
\92¼
\82·
\81D
39 // path
\82Í Init
\82Ì path
\82Æ
\93¯
\82¶
\81D
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
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
56 //
\89¹
\8c¹
\82ð
\83\8a\83Z
\83b
\83g(
\8f\89\8aú
\89»)
\82·
\82é
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Þ
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©
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
71 // IRQ
\8fo
\97Í
\82ð
\93Ç
\82Ý
\8fo
\82·
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[)
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·
\81c
\82Æ
\8ev
\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)
89 // OPN Base -------------------------------------------------------
90 class DLL_PREFIX OPNBase : public Timer
98 bool Init(uint c, uint r);
102 void SetVolumeFM(int db_l, int db_r);
103 void SetVolumePSG(int db_l, int db_r);
104 void SetLPFCutoff(uint freq) {} // obsolete
109 void SetParameter(Channel4* ch, uint addr, uint data);
110 void SetPrescaler(uint p);
111 void RebuildTimeTable();
112 void Intr(bool value);
114 void DeclState(void *f);
115 void SaveState(void *f);
116 bool LoadState(void *f);
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
129 static uint32 lfotable[8];
140 // OPN2 Base ------------------------------------------------------
141 class DLL_PREFIX OPNABase : public OPNBase
147 uint ReadStatus() { return status & 0x03; }
149 void SetChannelMask(uint mask);
155 bool Init(uint c, uint r, bool);
156 bool SetRate(uint c, uint r, bool);
159 void SetReg(uint addr, uint data);
160 void SetADPCMBReg(uint reg, uint data);
161 uint GetReg(uint addr);
163 void DeclState(void *f);
164 void SaveState(void *f);
165 bool LoadState(void *f);
168 void FMMix(Sample* buffer, int nsamples);
169 void Mix6(Sample* buffer, int nsamples, int activech);
171 void MixSubS(int activech, ISample**);
172 void MixSubSL(int activech, ISample**);
174 void SetStatus(uint bit);
175 void ResetStatus(uint bit);
180 void ADPCMBMix(Sample* dest, uint count);
182 void WriteRAM(uint data);
185 int DecodeADPCMBSample(uint);
187 // FM
\89¹
\8c¹
\8aÖ
\8cW
192 uint reg29; // OPNA only?
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Ê
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¬
\97p
\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)
229 uint adpcmreadbuf; // ADPCM
\83\8a\81[
\83h
\97p
\83o
\83b
\83t
\83@
230 bool adpcmplay; // ADPCM
\8dÄ
\90¶
\92\86
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ª
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;
249 // YM2203(OPN) ----------------------------------------------------
250 class DLL_PREFIX OPN : public OPNBase
256 bool Init(uint c, uint r, bool=false, const char* =0);
257 bool SetRate(uint c, uint r, bool=false);
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; }
266 void SetChannelMask(uint mask);
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]; }
272 void DeclState(void *f);
273 void SaveState(void *f);
274 bool LoadState(void *f);
277 void SetStatus(uint bit);
278 void ResetStatus(uint bit);
287 // YM2608(OPNA) ---------------------------------------------------
288 class DLL_PREFIX OPNA : public OPNABase
294 bool Init(uint c, uint r, bool = false, const _TCHAR* rhythmpath=0);
295 bool LoadRhythmSample(const _TCHAR*);
297 bool SetRate(uint c, uint r, bool = false);
298 void Mix(Sample* buffer, int nsamples);
301 void SetReg(uint addr, uint data);
302 uint GetReg(uint addr);
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);
308 uint8* GetADPCMBuffer() { return adpcmbuf; }
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]; }
314 void DeclState(void *f);
315 void SaveState(void *f);
316 bool LoadState(void *f);
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Æ
332 void RhythmMix(Sample* buffer, uint count);
334 //
\83\8a\83Y
\83\80\89¹
\8c¹
\8aÖ
\8cW
336 int8 rhythmtl; //
\83\8a\83Y
\83\80\91S
\91Ì
\82Ì
\89¹
\97Ê
339 uint8 rhythmkey; //
\83\8a\83Y
\83\80\82Ì
\83L
\81[
342 // YM2610/B(OPNB) ---------------------------------------------------
343 class DLL_PREFIX OPNB : public OPNABase
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);
353 bool SetRate(uint c, uint r, bool = false);
354 void Mix(Sample* buffer, int nsamples);
357 void SetReg(uint addr, uint data);
358 uint GetReg(uint addr);
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);
365 // void SetChannelMask(uint mask);
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¿
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
384 int DecodeADPCMASample(uint);
385 void ADPCMAMix(Sample* buffer, uint count);
386 static void InitADPCMATable();
389 uint8* adpcmabuf; // ADPCMA ROM
392 int8 adpcmatl; // ADPCMA
\91S
\91Ì
\82Ì
\89¹
\97Ê
395 uint8 adpcmakey; // ADPCMA
\82Ì
\83L
\81[
399 static int jedi_table[(48+1)*16];
404 // YM2612/3438(OPN2) ----------------------------------------------------
405 class OPN2 : public OPNBase
411 bool Init(uint c, uint r, bool=false, const char* =0);
412 bool SetRate(uint c, uint r, bool);
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; }
421 void SetChannelMask(uint mask);
424 void SetStatus(uint bit);
425 void ResetStatus(uint bit);
431 //
\90ü
\8c`
\95â
\8aÔ
\97p
\83\8f\81[
\83N
438 // ---------------------------------------------------------------------------
440 inline void FM::OPNBase::RebuildTimeTable()
447 inline void FM::OPNBase::SetVolumePSG(int db_l, int db_r)
449 psg.SetVolume(db_l, db_r, is_ay3_891x);