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 #if defined(_USE_AGAR) || defined(_USE_SDL) || defined(_USE_QT)
19 // ---------------------------------------------------------------------------
21 // OPN/OPNA
\82É
\97Ç
\82
\8e\97\82½
\89¹
\82ð
\90¶
\90¬
\82·
\82é
\89¹
\8c¹
\83\86\83j
\83b
\83g
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Þ
28 // clock: OPN/OPNA/OPNB
\82Ì
\83N
\83\8d\83b
\83N
\8eü
\94g
\90\94(Hz)
30 // rate:
\90¶
\90¬
\82·
\82é PCM
\82Ì
\95W
\96{
\8eü
\94g
\90\94(Hz)
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Æ
36 //
\95Ô
\82è
\92l
\8f\89\8aú
\89»
\82É
\90¬
\8c÷
\82·
\82ê
\82Î true
38 // bool LoadRhythmSample(const _TCHAR* path)
40 // Rhythm
\83T
\83\93\83v
\83\8b\82ð
\93Ç
\82Ý
\92¼
\82·
\81D
41 // path
\82Í Init
\82Ì path
\82Æ
\93¯
\82¶
\81D
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
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
58 //
\89¹
\8c¹
\82ð
\83\8a\83Z
\83b
\83g(
\8f\89\8aú
\89»)
\82·
\82é
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Þ
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©
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
73 // IRQ
\8fo
\97Í
\82ð
\93Ç
\82Ý
\8fo
\82·
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[)
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·
\81c
\82Æ
\8ev
\82¤
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)
91 // OPN Base -------------------------------------------------------
92 class OPNBase : public Timer
98 bool Init(uint c, uint r);
102 void SetVolumeFM(int db);
103 void SetVolumePSG(int db);
104 void SetLPFCutoff(uint freq) {} // obsolete
107 void SetParameter(Channel4* ch, uint addr, uint data);
108 void SetPrescaler(uint p);
109 void RebuildTimeTable();
110 void Intr(bool value);
112 void SaveState(void *f);
113 bool LoadState(void *f);
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
125 static uint32 lfotable[8];
136 // OPN2 Base ------------------------------------------------------
137 class OPNABase : public OPNBase
143 uint ReadStatus() { return status & 0x03; }
145 void SetChannelMask(uint mask);
151 bool Init(uint c, uint r, bool);
152 bool SetRate(uint c, uint r, bool);
155 void SetReg(uint addr, uint data);
156 void SetADPCMBReg(uint reg, uint data);
157 uint GetReg(uint addr);
159 void SaveState(void *f);
160 bool LoadState(void *f);
163 void FMMix(Sample* buffer, int nsamples);
164 void Mix6(Sample* buffer, int nsamples, int activech);
166 void MixSubS(int activech, ISample**);
167 void MixSubSL(int activech, ISample**);
169 void SetStatus(uint bit);
170 void ResetStatus(uint bit);
175 void ADPCMBMix(Sample* dest, uint count);
177 void WriteRAM(uint data);
180 int DecodeADPCMBSample(uint);
182 // FM
\89¹
\8c¹
\8aÖ
\8cW
187 uint reg29; // OPNA only?
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Ê
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¬
\97p
\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)
219 uint adpcmreadbuf; // ADPCM
\83\8a\81[
\83h
\97p
\83o
\83b
\83t
\83@
220 bool adpcmplay; // ADPCM
\8dÄ
\90¶
\92\86
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ª
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;
239 // YM2203(OPN) ----------------------------------------------------
240 class OPN : public OPNBase
246 bool Init(uint c, uint r, bool=false, const char* =0);
247 bool SetRate(uint c, uint r, bool=false);
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; }
256 void SetChannelMask(uint mask);
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]; }
262 void SaveState(void *f);
263 bool LoadState(void *f);
266 void SetStatus(uint bit);
267 void ResetStatus(uint bit);
276 // YM2608(OPNA) ---------------------------------------------------
277 class OPNA : public OPNABase
283 bool Init(uint c, uint r, bool = false, const _TCHAR* rhythmpath=0);
284 bool LoadRhythmSample(const _TCHAR*);
286 bool SetRate(uint c, uint r, bool = false);
287 void Mix(Sample* buffer, int nsamples);
290 void SetReg(uint addr, uint data);
291 uint GetReg(uint addr);
293 void SetVolumeADPCM(int db);
294 void SetVolumeRhythmTotal(int db);
295 void SetVolumeRhythm(int index, int db);
297 uint8* GetADPCMBuffer() { return adpcmbuf; }
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]; }
303 void SaveState(void *f);
304 bool LoadState(void *f);
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Æ
319 void RhythmMix(Sample* buffer, uint count);
321 //
\83\8a\83Y
\83\80\89¹
\8c¹
\8aÖ
\8cW
323 int8 rhythmtl; //
\83\8a\83Y
\83\80\91S
\91Ì
\82Ì
\89¹
\97Ê
325 uint8 rhythmkey; //
\83\8a\83Y
\83\80\82Ì
\83L
\81[
328 // YM2610/B(OPNB) ---------------------------------------------------
329 class OPNB : public OPNABase
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);
339 bool SetRate(uint c, uint r, bool = false);
340 void Mix(Sample* buffer, int nsamples);
343 void SetReg(uint addr, uint data);
344 uint GetReg(uint addr);
347 void SetVolumeADPCMATotal(int db);
348 void SetVolumeADPCMA(int index, int db);
349 void SetVolumeADPCMB(int db);
351 // void SetChannelMask(uint mask);
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¿
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
369 int DecodeADPCMASample(uint);
370 void ADPCMAMix(Sample* buffer, uint count);
371 static void InitADPCMATable();
374 uint8* adpcmabuf; // ADPCMA ROM
377 int8 adpcmatl; // ADPCMA
\91S
\91Ì
\82Ì
\89¹
\97Ê
379 uint8 adpcmakey; // ADPCMA
\82Ì
\83L
\81[
383 static int jedi_table[(48+1)*16];
388 // YM2612/3438(OPN2) ----------------------------------------------------
389 class OPN2 : public OPNBase
395 bool Init(uint c, uint r, bool=false, const char* =0);
396 bool SetRate(uint c, uint r, bool);
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; }
405 void SetChannelMask(uint mask);
408 void SetStatus(uint bit);
409 void ResetStatus(uint bit);
415 //
\90ü
\8c`
\95â
\8aÔ
\97p
\83\8f\81[
\83N
422 // ---------------------------------------------------------------------------
424 inline void FM::OPNBase::RebuildTimeTable()
431 inline void FM::OPNBase::SetVolumePSG(int db)