Ticket #9010: dosbox_adlib_v5.patch

File dosbox_adlib_v5.patch, 142.8 KB (added by lordhoto, 15 years ago)

Patch against trunk r40187.

Line 
1Index: sound/module.mk
2===================================================================
3--- sound/module.mk (revision 40184)
4+++ sound/module.mk (working copy)
5@@ -30,6 +30,9 @@
6 mods/rjp1.o \
7 mods/soundfx.o \
8 softsynth/adlib.o \
9+ softsynth/adlib/dbopl.o \
10+ softsynth/adlib/dosbox.o \
11+ softsynth/adlib/mame.o \
12 softsynth/ym2612.o \
13 softsynth/fluidsynth.o \
14 softsynth/mt32.o \
15Index: sound/fmopl.h
16===================================================================
17--- sound/fmopl.h 2009-04-28 18:36:54.319782168 +0200
18+++ sound/fmopl.h 2009-04-28 18:38:31.171943036 +0200
19@@ -8,166 +8,64 @@
20 * modify it under the terms of the GNU General Public License
21 * as published by the Free Software Foundation; either version 2
22 * of the License, or (at your option) any later version.
23-
24+ *
25 * This program is distributed in the hope that it will be useful,
26 * but WITHOUT ANY WARRANTY; without even the implied warranty of
27 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
28 * GNU General Public License for more details.
29-
30+ *
31 * You should have received a copy of the GNU General Public License
32 * along with this program; if not, write to the Free Software
33 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
34 *
35- * $URL: https://scummvm.svn.sourceforge.net/svnroot/scummvm/scummvm/trunk/sound/fmopl.h $
36- * $Id: fmopl.h 38211 2009-02-15 10:07:50Z sev $
37- *
38- * LGPL licensed version of MAMEs fmopl (V0.37a modified) by
39- * Tatsuyuki Satoh. Included from LGPL'ed AdPlug.
40+ * $URL$
41+ * $Id$
42 */
43
44-
45 #ifndef SOUND_FMOPL_H
46 #define SOUND_FMOPL_H
47
48 #include "common/scummsys.h"
49-#include "common/util.h"
50
51-enum {
52- FMOPL_ENV_BITS_HQ = 16,
53- FMOPL_ENV_BITS_MQ = 8,
54- FMOPL_ENV_BITS_LQ = 8,
55- FMOPL_EG_ENT_HQ = 4096,
56- FMOPL_EG_ENT_MQ = 1024,
57- FMOPL_EG_ENT_LQ = 128
58-};
59+namespace AdLib {
60+
61+// TODO: Documentation
62+class AdLib {
63+public:
64+ virtual ~AdLib() {}
65
66+ enum kOplType {
67+ kOpl2 = 0
68+ };
69
70-typedef void (*OPL_TIMERHANDLER)(int channel,double interval_Sec);
71-typedef void (*OPL_IRQHANDLER)(int param,int irq);
72-typedef void (*OPL_UPDATEHANDLER)(int param,int min_interval_us);
73-
74-#define OPL_TYPE_WAVESEL 0x01 /* waveform select */
75-
76-/* Saving is necessary for member of the 'R' mark for suspend/resume */
77-/* ---------- OPL one of slot ---------- */
78-typedef struct fm_opl_slot {
79- int TL; /* total level :TL << 8 */
80- int TLL; /* adjusted now TL */
81- uint8 KSR; /* key scale rate :(shift down bit) */
82- int *AR; /* attack rate :&AR_TABLE[AR<<2] */
83- int *DR; /* decay rate :&DR_TABLE[DR<<2] */
84- int SL; /* sustain level :SL_TABLE[SL] */
85- int *RR; /* release rate :&DR_TABLE[RR<<2] */
86- uint8 ksl; /* keyscale level :(shift down bits) */
87- uint8 ksr; /* key scale rate :kcode>>KSR */
88- uint mul; /* multiple :ML_TABLE[ML] */
89- uint Cnt; /* frequency count */
90- uint Incr; /* frequency step */
91-
92- /* envelope generator state */
93- uint8 eg_typ;/* envelope type flag */
94- uint8 evm; /* envelope phase */
95- int evc; /* envelope counter */
96- int eve; /* envelope counter end point */
97- int evs; /* envelope counter step */
98- int evsa; /* envelope step for AR :AR[ksr] */
99- int evsd; /* envelope step for DR :DR[ksr] */
100- int evsr; /* envelope step for RR :RR[ksr] */
101-
102- /* LFO */
103- uint8 ams; /* ams flag */
104- uint8 vib; /* vibrate flag */
105- /* wave selector */
106- int **wavetable;
107-} OPL_SLOT;
108-
109-/* ---------- OPL one of channel ---------- */
110-typedef struct fm_opl_channel {
111- OPL_SLOT SLOT[2];
112- uint8 CON; /* connection type */
113- uint8 FB; /* feed back :(shift down bit)*/
114- int *connect1; /* slot1 output pointer */
115- int *connect2; /* slot2 output pointer */
116- int op1_out[2]; /* slot1 output for selfeedback */
117-
118- /* phase generator state */
119- uint block_fnum; /* block+fnum */
120- uint8 kcode; /* key code : KeyScaleCode */
121- uint fc; /* Freq. Increment base */
122- uint ksl_base; /* KeyScaleLevel Base step */
123- uint8 keyon; /* key on/off flag */
124-} OPL_CH;
125-
126-/* OPL state */
127-typedef struct fm_opl_f {
128- uint8 type; /* chip type */
129- int clock; /* master clock (Hz) */
130- int rate; /* sampling rate (Hz) */
131- double freqbase; /* frequency base */
132- double TimerBase; /* Timer base time (==sampling time) */
133- uint8 address; /* address register */
134- uint8 status; /* status flag */
135- uint8 statusmask; /* status mask */
136- uint mode; /* Reg.08 : CSM , notesel,etc. */
137-
138- /* Timer */
139- int T[2]; /* timer counter */
140- uint8 st[2]; /* timer enable */
141-
142- /* FM channel slots */
143- OPL_CH *P_CH; /* pointer of CH */
144- int max_ch; /* maximum channel */
145-
146- /* Rythm sention */
147- uint8 rythm; /* Rythm mode , key flag */
148-
149- /* time tables */
150- int AR_TABLE[76]; /* atttack rate tables */
151- int DR_TABLE[76]; /* decay rate tables */
152- uint FN_TABLE[1024];/* fnumber -> increment counter */
153-
154- /* LFO */
155- int *ams_table;
156- int *vib_table;
157- int amsCnt;
158- int amsIncr;
159- int vibCnt;
160- int vibIncr;
161-
162- /* wave selector enable flag */
163- uint8 wavesel;
164-
165- /* external event callback handler */
166- OPL_TIMERHANDLER TimerHandler; /* TIMER handler */
167- int TimerParam; /* TIMER parameter */
168- OPL_IRQHANDLER IRQHandler; /* IRQ handler */
169- int IRQParam; /* IRQ parameter */
170- OPL_UPDATEHANDLER UpdateHandler; /* stream update handler */
171- int UpdateParam; /* stream update parameter */
172-
173- Common::RandomSource rnd;
174-} FM_OPL;
175-
176-/* ---------- Generic interface section ---------- */
177-#define OPL_TYPE_YM3526 (0)
178-#define OPL_TYPE_YM3812 (OPL_TYPE_WAVESEL)
179+ virtual void init(int rate, kOplType type = kOpl2) = 0;
180+ virtual void reset() = 0;
181
182-void OPLBuildTables(int ENV_BITS_PARAM, int EG_ENT_PARAM);
183+ virtual void write(int a, int v) = 0;
184+ virtual byte read(int a) = 0;
185+
186+ virtual void writeReg(int r, int v) = 0;
187+
188+ virtual void readBuffer(int16 *buffer, int length) = 0;
189+
190+ static AdLib *createInstance();
191+};
192+
193+} // end of namespace AdLib
194+
195+// Legacy API
196+typedef AdLib::AdLib FM_OPL;
197
198-FM_OPL *OPLCreate(int type, int clock, int rate);
199 void OPLDestroy(FM_OPL *OPL);
200-void OPLSetTimerHandler(FM_OPL *OPL, OPL_TIMERHANDLER TimerHandler, int channelOffset);
201-void OPLSetIRQHandler(FM_OPL *OPL, OPL_IRQHANDLER IRQHandler, int param);
202-void OPLSetUpdateHandler(FM_OPL *OPL, OPL_UPDATEHANDLER UpdateHandler, int param);
203
204 void OPLResetChip(FM_OPL *OPL);
205-int OPLWrite(FM_OPL *OPL, int a, int v);
206+void OPLWrite(FM_OPL *OPL, int a, int v);
207 unsigned char OPLRead(FM_OPL *OPL, int a);
208-int OPLTimerOver(FM_OPL *OPL, int c);
209 void OPLWriteReg(FM_OPL *OPL, int r, int v);
210-void YM3812UpdateOne(FM_OPL *OPL, int16 *buffer, int length, int interleave = 0);
211+void YM3812UpdateOne(FM_OPL *OPL, int16 *buffer, int length);
212
213 // Factory method
214 FM_OPL *makeAdlibOPL(int rate);
215
216 #endif
217+
218Index: sound/fmopl.cpp
219===================================================================
220--- sound/fmopl.cpp 2009-04-28 18:38:05.947781895 +0200
221+++ sound/fmopl.cpp 2009-04-28 18:38:21.552408141 +0200
222@@ -8,1184 +8,63 @@
223 * modify it under the terms of the GNU General Public License
224 * as published by the Free Software Foundation; either version 2
225 * of the License, or (at your option) any later version.
226-
227+ *
228 * This program is distributed in the hope that it will be useful,
229 * but WITHOUT ANY WARRANTY; without even the implied warranty of
230 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
231 * GNU General Public License for more details.
232-
233+ *
234 * You should have received a copy of the GNU General Public License
235 * along with this program; if not, write to the Free Software
236 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
237 *
238- * $URL: https://scummvm.svn.sourceforge.net/svnroot/scummvm/scummvm/trunk/sound/fmopl.cpp $
239- * $Id: fmopl.cpp 38211 2009-02-15 10:07:50Z sev $
240- *
241- * LGPL licensed version of MAMEs fmopl (V0.37a modified) by
242- * Tatsuyuki Satoh. Included from LGPL'ed AdPlug.
243+ * $URL$
244+ * $Id$
245 */
246
247-#include <stdio.h>
248-#include <stdlib.h>
249-#include <string.h>
250-#include <stdarg.h>
251-#include <math.h>
252-
253 #include "sound/fmopl.h"
254
255-#if defined (_WIN32_WCE) || defined (__SYMBIAN32__) || defined(PALMOS_MODE) || defined(__GP32__) || defined(GP2X) || defined (__MAEMO__) || defined(__DS__) || defined (__MINT__)
256-#include "common/config-manager.h"
257-#endif
258-
259-/* -------------------- preliminary define section --------------------- */
260-/* attack/decay rate time rate */
261-#define OPL_ARRATE 141280 /* RATE 4 = 2826.24ms @ 3.6MHz */
262-#define OPL_DRRATE 1956000 /* RATE 4 = 39280.64ms @ 3.6MHz */
263-
264-#define FREQ_BITS 24 /* frequency turn */
265-
266-/* counter bits = 20 , octerve 7 */
267-#define FREQ_RATE (1<<(FREQ_BITS-20))
268-#define TL_BITS (FREQ_BITS+2)
269-
270-/* final output shift , limit minimum and maximum */
271-#define OPL_OUTSB (TL_BITS+3-16) /* OPL output final shift 16bit */
272-#define OPL_MAXOUT (0x7fff<<OPL_OUTSB)
273-#define OPL_MINOUT (-0x8000<<OPL_OUTSB)
274-
275-/* -------------------- quality selection --------------------- */
276-
277-/* sinwave entries */
278-/* used static memory = SIN_ENT * 4 (byte) */
279-#ifdef __DS__
280-#include "dsmain.h"
281-#define SIN_ENT_SHIFT 8
282-#else
283-#define SIN_ENT_SHIFT 11
284-#endif
285-#define SIN_ENT (1<<SIN_ENT_SHIFT)
286-
287-/* output level entries (envelope,sinwave) */
288-/* envelope counter lower bits */
289-int ENV_BITS;
290-/* envelope output entries */
291-int EG_ENT;
292-
293-/* used dynamic memory = EG_ENT*4*4(byte)or EG_ENT*6*4(byte) */
294-/* used static memory = EG_ENT*4 (byte) */
295-int EG_OFF; /* OFF */
296-int EG_DED;
297-int EG_DST; /* DECAY START */
298-int EG_AED;
299-#define EG_AST 0 /* ATTACK START */
300-
301-#define EG_STEP (96.0/EG_ENT) /* OPL is 0.1875 dB step */
302-
303-/* LFO table entries */
304-#define VIB_ENT 512
305-#define VIB_SHIFT (32-9)
306-#define AMS_ENT 512
307-#define AMS_SHIFT (32-9)
308-
309-#define VIB_RATE_SHIFT 8
310-#define VIB_RATE (1<<VIB_RATE_SHIFT)
311-
312-/* -------------------- local defines , macros --------------------- */
313-
314-/* register number to channel number , slot offset */
315-#define SLOT1 0
316-#define SLOT2 1
317-
318-/* envelope phase */
319-#define ENV_MOD_RR 0x00
320-#define ENV_MOD_DR 0x01
321-#define ENV_MOD_AR 0x02
322-
323-/* -------------------- tables --------------------- */
324-static const int slot_array[32] = {
325- 0, 2, 4, 1, 3, 5,-1,-1,
326- 6, 8,10, 7, 9,11,-1,-1,
327- 12,14,16,13,15,17,-1,-1,
328- -1,-1,-1,-1,-1,-1,-1,-1
329-};
330-
331-static uint KSL_TABLE[8 * 16];
332-
333-static const double KSL_TABLE_SEED[8 * 16] = {
334- /* OCT 0 */
335- 0.000, 0.000, 0.000, 0.000,
336- 0.000, 0.000, 0.000, 0.000,
337- 0.000, 0.000, 0.000, 0.000,
338- 0.000, 0.000, 0.000, 0.000,
339- /* OCT 1 */
340- 0.000, 0.000, 0.000, 0.000,
341- 0.000, 0.000, 0.000, 0.000,
342- 0.000, 0.750, 1.125, 1.500,
343- 1.875, 2.250, 2.625, 3.000,
344- /* OCT 2 */
345- 0.000, 0.000, 0.000, 0.000,
346- 0.000, 1.125, 1.875, 2.625,
347- 3.000, 3.750, 4.125, 4.500,
348- 4.875, 5.250, 5.625, 6.000,
349- /* OCT 3 */
350- 0.000, 0.000, 0.000, 1.875,
351- 3.000, 4.125, 4.875, 5.625,
352- 6.000, 6.750, 7.125, 7.500,
353- 7.875, 8.250, 8.625, 9.000,
354- /* OCT 4 */
355- 0.000, 0.000, 3.000, 4.875,
356- 6.000, 7.125, 7.875, 8.625,
357- 9.000, 9.750, 10.125, 10.500,
358- 10.875, 11.250, 11.625, 12.000,
359- /* OCT 5 */
360- 0.000, 3.000, 6.000, 7.875,
361- 9.000, 10.125, 10.875, 11.625,
362- 12.000, 12.750, 13.125, 13.500,
363- 13.875, 14.250, 14.625, 15.000,
364- /* OCT 6 */
365- 0.000, 6.000, 9.000, 10.875,
366- 12.000, 13.125, 13.875, 14.625,
367- 15.000, 15.750, 16.125, 16.500,
368- 16.875, 17.250, 17.625, 18.000,
369- /* OCT 7 */
370- 0.000, 9.000, 12.000, 13.875,
371- 15.000, 16.125, 16.875, 17.625,
372- 18.000, 18.750, 19.125, 19.500,
373- 19.875, 20.250, 20.625, 21.000
374-};
375-
376-/* sustain level table (3db per step) */
377-/* 0 - 15: 0, 3, 6, 9,12,15,18,21,24,27,30,33,36,39,42,93 (dB)*/
378-
379-static int SL_TABLE[16];
380-
381-static const uint SL_TABLE_SEED[16] = {
382- 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 31
383-};
384-
385-#define TL_MAX (EG_ENT * 2) /* limit(tl + ksr + envelope) + sinwave */
386-/* TotalLevel : 48 24 12 6 3 1.5 0.75 (dB) */
387-/* TL_TABLE[ 0 to TL_MAX ] : plus section */
388-/* TL_TABLE[ TL_MAX to TL_MAX+TL_MAX-1 ] : minus section */
389-static int *TL_TABLE;
390-
391-/* pointers to TL_TABLE with sinwave output offset */
392-static int **SIN_TABLE;
393-
394-/* LFO table */
395-static int *AMS_TABLE;
396-static int *VIB_TABLE;
397-
398-/* envelope output curve table */
399-/* attack + decay + OFF */
400-//static int ENV_CURVE[2*EG_ENT+1];
401-//static int ENV_CURVE[2 * 4096 + 1]; // to keep it static ...
402-static int *ENV_CURVE;
403-
404-
405-/* multiple table */
406-#define ML(a) (int)(a * 2)
407-static const uint MUL_TABLE[16]= {
408-/* 1/2, 1, 2, 3, 4, 5, 6, 7, 8, 9,10,11,12,13,14,15 */
409- ML(0.50), ML(1.00), ML(2.00), ML(3.00), ML(4.00), ML(5.00), ML(6.00), ML(7.00),
410- ML(8.00), ML(9.00), ML(10.00), ML(10.00),ML(12.00),ML(12.00),ML(15.00),ML(15.00)
411-};
412-#undef ML
413-
414-/* dummy attack / decay rate ( when rate == 0 ) */
415-static int RATE_0[16]=
416-{0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0};
417-
418-/* -------------------- static state --------------------- */
419-
420-/* lock level of common table */
421-static int num_lock = 0;
422-
423-/* work table */
424-static void *cur_chip = NULL; /* current chip point */
425-/* currenct chip state */
426-/* static OPLSAMPLE *bufL,*bufR; */
427-static OPL_CH *S_CH;
428-static OPL_CH *E_CH;
429-OPL_SLOT *SLOT7_1, *SLOT7_2, *SLOT8_1, *SLOT8_2;
430-
431-static int outd[1];
432-static int ams;
433-static int vib;
434-int *ams_table;
435-int *vib_table;
436-static int amsIncr;
437-static int vibIncr;
438-static int feedback2; /* connect for SLOT 2 */
439-
440-/* --------------------- rebuild tables ------------------- */
441-
442-#define SC_KSL(mydb) ((uint) (mydb / (EG_STEP / 2)))
443-#define SC_SL(db) (int)(db * ((3 / EG_STEP) * (1 << ENV_BITS))) + EG_DST
444-
445-void OPLBuildTables(int ENV_BITS_PARAM, int EG_ENT_PARAM) {
446- int i;
447-
448- ENV_BITS = ENV_BITS_PARAM;
449- EG_ENT = EG_ENT_PARAM;
450- EG_OFF = ((2 * EG_ENT)<<ENV_BITS); /* OFF */
451- EG_DED = EG_OFF;
452- EG_DST = (EG_ENT << ENV_BITS); /* DECAY START */
453- EG_AED = EG_DST;
454- //EG_STEP = (96.0/EG_ENT);
455-
456- for (i = 0; i < ARRAYSIZE(KSL_TABLE_SEED); i++)
457- KSL_TABLE[i] = SC_KSL(KSL_TABLE_SEED[i]);
458-
459- for (i = 0; i < ARRAYSIZE(SL_TABLE_SEED); i++)
460- SL_TABLE[i] = SC_SL(SL_TABLE_SEED[i]);
461-}
462-
463-#undef SC_KSL
464-#undef SC_SL
465-
466-/* --------------------- subroutines --------------------- */
467-
468-/* status set and IRQ handling */
469-inline void OPL_STATUS_SET(FM_OPL *OPL, int flag) {
470- /* set status flag */
471- OPL->status |= flag;
472- if(!(OPL->status & 0x80)) {
473- if(OPL->status & OPL->statusmask) { /* IRQ on */
474- OPL->status |= 0x80;
475- /* callback user interrupt handler (IRQ is OFF to ON) */
476- if(OPL->IRQHandler)
477- (OPL->IRQHandler)(OPL->IRQParam,1);
478- }
479- }
480-}
481-
482-/* status reset and IRQ handling */
483-inline void OPL_STATUS_RESET(FM_OPL *OPL, int flag) {
484- /* reset status flag */
485- OPL->status &= ~flag;
486- if((OPL->status & 0x80)) {
487- if (!(OPL->status & OPL->statusmask)) {
488- OPL->status &= 0x7f;
489- /* callback user interrupt handler (IRQ is ON to OFF) */
490- if(OPL->IRQHandler) (OPL->IRQHandler)(OPL->IRQParam,0);
491- }
492- }
493-}
494-
495-/* IRQ mask set */
496-inline void OPL_STATUSMASK_SET(FM_OPL *OPL, int flag) {
497- OPL->statusmask = flag;
498- /* IRQ handling check */
499- OPL_STATUS_SET(OPL,0);
500- OPL_STATUS_RESET(OPL,0);
501-}
502-
503-/* ----- key on ----- */
504-inline void OPL_KEYON(OPL_SLOT *SLOT) {
505- /* sin wave restart */
506- SLOT->Cnt = 0;
507- /* set attack */
508- SLOT->evm = ENV_MOD_AR;
509- SLOT->evs = SLOT->evsa;
510- SLOT->evc = EG_AST;
511- SLOT->eve = EG_AED;
512-}
513-
514-/* ----- key off ----- */
515-inline void OPL_KEYOFF(OPL_SLOT *SLOT) {
516- if( SLOT->evm > ENV_MOD_RR) {
517- /* set envelope counter from envleope output */
518-
519- // WORKAROUND: The Kyra engine does something very strange when
520- // starting a new song. For each channel:
521- //
522- // * The release rate is set to "fastest".
523- // * Any note is keyed off.
524- // * A very low-frequency note is keyed on.
525- //
526- // Usually, what happens next is that the real notes is keyed
527- // on immediately, in which case there's no problem.
528- //
529- // However, if the note is again keyed off (because the channel
530- // begins on a rest rather than a note), the envelope counter
531- // was moved from the very lowest point on the attack curve to
532- // the very highest point on the release curve.
533- //
534- // Again, this might not be a problem, if the release rate is
535- // still set to "fastest". But in many cases, it had already
536- // been increased. And, possibly because of inaccuracies in the
537- // envelope generator, that would cause the note to "fade out"
538- // for quite a long time.
539- //
540- // What we really need is a way to find the correct starting
541- // point for the envelope counter, and that may be what the
542- // commented-out line below is meant to do. For now, simply
543- // handle the pathological case.
544-
545- if (SLOT->evm == ENV_MOD_AR && SLOT->evc == EG_AST)
546- SLOT->evc = EG_DED;
547- else if( !(SLOT->evc & EG_DST) )
548- //SLOT->evc = (ENV_CURVE[SLOT->evc>>ENV_BITS]<<ENV_BITS) + EG_DST;
549- SLOT->evc = EG_DST;
550- SLOT->eve = EG_DED;
551- SLOT->evs = SLOT->evsr;
552- SLOT->evm = ENV_MOD_RR;
553- }
554-}
555-
556-/* ---------- calcrate Envelope Generator & Phase Generator ---------- */
557-
558-/* return : envelope output */
559-inline uint OPL_CALC_SLOT(OPL_SLOT *SLOT) {
560- /* calcrate envelope generator */
561- if((SLOT->evc += SLOT->evs) >= SLOT->eve) {
562- switch( SLOT->evm ) {
563- case ENV_MOD_AR: /* ATTACK -> DECAY1 */
564- /* next DR */
565- SLOT->evm = ENV_MOD_DR;
566- SLOT->evc = EG_DST;
567- SLOT->eve = SLOT->SL;
568- SLOT->evs = SLOT->evsd;
569- break;
570- case ENV_MOD_DR: /* DECAY -> SL or RR */
571- SLOT->evc = SLOT->SL;
572- SLOT->eve = EG_DED;
573- if(SLOT->eg_typ) {
574- SLOT->evs = 0;
575- } else {
576- SLOT->evm = ENV_MOD_RR;
577- SLOT->evs = SLOT->evsr;
578- }
579- break;
580- case ENV_MOD_RR: /* RR -> OFF */
581- SLOT->evc = EG_OFF;
582- SLOT->eve = EG_OFF + 1;
583- SLOT->evs = 0;
584- break;
585- }
586- }
587- /* calcrate envelope */
588- return SLOT->TLL + ENV_CURVE[SLOT->evc>>ENV_BITS] + (SLOT->ams ? ams : 0);
589-}
590-
591-/* set algorythm connection */
592-static void set_algorythm(OPL_CH *CH) {
593- int *carrier = &outd[0];
594- CH->connect1 = CH->CON ? carrier : &feedback2;
595- CH->connect2 = carrier;
596-}
597-
598-/* ---------- frequency counter for operater update ---------- */
599-inline void CALC_FCSLOT(OPL_CH *CH, OPL_SLOT *SLOT) {
600- int ksr;
601-
602- /* frequency step counter */
603- SLOT->Incr = CH->fc * SLOT->mul;
604- ksr = CH->kcode >> SLOT->KSR;
605-
606- if( SLOT->ksr != ksr ) {
607- SLOT->ksr = ksr;
608- /* attack , decay rate recalcration */
609- SLOT->evsa = SLOT->AR[ksr];
610- SLOT->evsd = SLOT->DR[ksr];
611- SLOT->evsr = SLOT->RR[ksr];
612- }
613- SLOT->TLL = SLOT->TL + (CH->ksl_base>>SLOT->ksl);
614-}
615-
616-/* set multi,am,vib,EG-TYP,KSR,mul */
617-inline void set_mul(FM_OPL *OPL, int slot, int v) {
618- OPL_CH *CH = &OPL->P_CH[slot>>1];
619- OPL_SLOT *SLOT = &CH->SLOT[slot & 1];
620-
621- SLOT->mul = MUL_TABLE[v & 0x0f];
622- SLOT->KSR = (v & 0x10) ? 0 : 2;
623- SLOT->eg_typ = (v & 0x20) >> 5;
624- SLOT->vib = (v & 0x40);
625- SLOT->ams = (v & 0x80);
626- CALC_FCSLOT(CH, SLOT);
627-}
628-
629-/* set ksl & tl */
630-inline void set_ksl_tl(FM_OPL *OPL, int slot, int v) {
631- OPL_CH *CH = &OPL->P_CH[slot>>1];
632- OPL_SLOT *SLOT = &CH->SLOT[slot & 1];
633- int ksl = v >> 6; /* 0 / 1.5 / 3 / 6 db/OCT */
634-
635- SLOT->ksl = ksl ? 3-ksl : 31;
636- SLOT->TL = (int)((v & 0x3f) * (0.75 / EG_STEP)); /* 0.75db step */
637-
638- if(!(OPL->mode & 0x80)) { /* not CSM latch total level */
639- SLOT->TLL = SLOT->TL + (CH->ksl_base >> SLOT->ksl);
640- }
641-}
642-
643-/* set attack rate & decay rate */
644-inline void set_ar_dr(FM_OPL *OPL, int slot, int v) {
645- OPL_CH *CH = &OPL->P_CH[slot>>1];
646- OPL_SLOT *SLOT = &CH->SLOT[slot & 1];
647- int ar = v >> 4;
648- int dr = v & 0x0f;
649-
650- SLOT->AR = ar ? &OPL->AR_TABLE[ar << 2] : RATE_0;
651- SLOT->evsa = SLOT->AR[SLOT->ksr];
652- if(SLOT->evm == ENV_MOD_AR)
653- SLOT->evs = SLOT->evsa;
654-
655- SLOT->DR = dr ? &OPL->DR_TABLE[dr<<2] : RATE_0;
656- SLOT->evsd = SLOT->DR[SLOT->ksr];
657- if(SLOT->evm == ENV_MOD_DR)
658- SLOT->evs = SLOT->evsd;
659-}
660+#include "sound/softsynth/adlib/dosbox.h"
661+#include "sound/softsynth/adlib/mame.h"
662
663-/* set sustain level & release rate */
664-inline void set_sl_rr(FM_OPL *OPL, int slot, int v) {
665- OPL_CH *CH = &OPL->P_CH[slot>>1];
666- OPL_SLOT *SLOT = &CH->SLOT[slot & 1];
667- int sl = v >> 4;
668- int rr = v & 0x0f;
669+namespace AdLib {
670
671- SLOT->SL = SL_TABLE[sl];
672- if(SLOT->evm == ENV_MOD_DR)
673- SLOT->eve = SLOT->SL;
674- SLOT->RR = &OPL->DR_TABLE[rr<<2];
675- SLOT->evsr = SLOT->RR[SLOT->ksr];
676- if(SLOT->evm == ENV_MOD_RR)
677- SLOT->evs = SLOT->evsr;
678+AdLib *AdLib::createInstance() {
679+// return new MAME::AdLib_MAME();
680+ return new DOSBox::AdLib_DOSBox();
681 }
682
683-/* operator output calcrator */
684-
685-#define OP_OUT(slot,env,con) slot->wavetable[((slot->Cnt + con)>>(24-SIN_ENT_SHIFT)) & (SIN_ENT-1)][env]
686-/* ---------- calcrate one of channel ---------- */
687-inline void OPL_CALC_CH(OPL_CH *CH) {
688- uint env_out;
689- OPL_SLOT *SLOT;
690-
691- feedback2 = 0;
692- /* SLOT 1 */
693- SLOT = &CH->SLOT[SLOT1];
694- env_out=OPL_CALC_SLOT(SLOT);
695- if(env_out < (uint)(EG_ENT - 1)) {
696- /* PG */
697- if(SLOT->vib)
698- SLOT->Cnt += (SLOT->Incr * vib) >> VIB_RATE_SHIFT;
699- else
700- SLOT->Cnt += SLOT->Incr;
701- /* connection */
702- if(CH->FB) {
703- int feedback1 = (CH->op1_out[0] + CH->op1_out[1]) >> CH->FB;
704- CH->op1_out[1] = CH->op1_out[0];
705- *CH->connect1 += CH->op1_out[0] = OP_OUT(SLOT, env_out, feedback1);
706- } else {
707- *CH->connect1 += OP_OUT(SLOT, env_out, 0);
708- }
709- } else {
710- CH->op1_out[1] = CH->op1_out[0];
711- CH->op1_out[0] = 0;
712- }
713- /* SLOT 2 */
714- SLOT = &CH->SLOT[SLOT2];
715- env_out=OPL_CALC_SLOT(SLOT);
716- if(env_out < (uint)(EG_ENT - 1)) {
717- /* PG */
718- if(SLOT->vib)
719- SLOT->Cnt += (SLOT->Incr * vib) >> VIB_RATE_SHIFT;
720- else
721- SLOT->Cnt += SLOT->Incr;
722- /* connection */
723- outd[0] += OP_OUT(SLOT, env_out, feedback2);
724- }
725-}
726-
727-/* ---------- calcrate rythm block ---------- */
728-#define WHITE_NOISE_db 6.0
729-inline void OPL_CALC_RH(FM_OPL *OPL, OPL_CH *CH) {
730- uint env_tam, env_sd, env_top, env_hh;
731- // This code used to do int(OPL->rnd.getRandomBit() * (WHITE_NOISE_db / EG_STEP)),
732- // but EG_STEP = 96.0/EG_ENT, and WHITE_NOISE_db=6.0. So, that's equivalent to
733- // int(OPL->rnd.getRandomBit() * EG_ENT/16). We know that EG_ENT is 4096, or 1024,
734- // or 128, so we can safely avoid any FP ops.
735- int whitenoise = OPL->rnd.getRandomBit() * (EG_ENT>>4);
736-
737- int tone8;
738-
739- OPL_SLOT *SLOT;
740- int env_out;
741-
742- /* BD : same as FM serial mode and output level is large */
743- feedback2 = 0;
744- /* SLOT 1 */
745- SLOT = &CH[6].SLOT[SLOT1];
746- env_out = OPL_CALC_SLOT(SLOT);
747- if(env_out < EG_ENT-1) {
748- /* PG */
749- if(SLOT->vib)
750- SLOT->Cnt += (SLOT->Incr * vib) >> VIB_RATE_SHIFT;
751- else
752- SLOT->Cnt += SLOT->Incr;
753- /* connection */
754- if(CH[6].FB) {
755- int feedback1 = (CH[6].op1_out[0] + CH[6].op1_out[1]) >> CH[6].FB;
756- CH[6].op1_out[1] = CH[6].op1_out[0];
757- feedback2 = CH[6].op1_out[0] = OP_OUT(SLOT, env_out, feedback1);
758- }
759- else {
760- feedback2 = OP_OUT(SLOT, env_out, 0);
761- }
762- } else {
763- feedback2 = 0;
764- CH[6].op1_out[1] = CH[6].op1_out[0];
765- CH[6].op1_out[0] = 0;
766- }
767- /* SLOT 2 */
768- SLOT = &CH[6].SLOT[SLOT2];
769- env_out = OPL_CALC_SLOT(SLOT);
770- if(env_out < EG_ENT-1) {
771- /* PG */
772- if(SLOT->vib)
773- SLOT->Cnt += (SLOT->Incr * vib) >> VIB_RATE_SHIFT;
774- else
775- SLOT->Cnt += SLOT->Incr;
776- /* connection */
777- outd[0] += OP_OUT(SLOT, env_out, feedback2) * 2;
778- }
779-
780- // SD (17) = mul14[fnum7] + white noise
781- // TAM (15) = mul15[fnum8]
782- // TOP (18) = fnum6(mul18[fnum8]+whitenoise)
783- // HH (14) = fnum7(mul18[fnum8]+whitenoise) + white noise
784- env_sd = OPL_CALC_SLOT(SLOT7_2) + whitenoise;
785- env_tam =OPL_CALC_SLOT(SLOT8_1);
786- env_top = OPL_CALC_SLOT(SLOT8_2);
787- env_hh = OPL_CALC_SLOT(SLOT7_1) + whitenoise;
788-
789- /* PG */
790- if(SLOT7_1->vib)
791- SLOT7_1->Cnt += (SLOT7_1->Incr * vib) >> (VIB_RATE_SHIFT-1);
792- else
793- SLOT7_1->Cnt += 2 * SLOT7_1->Incr;
794- if(SLOT7_2->vib)
795- SLOT7_2->Cnt += (CH[7].fc * vib) >> (VIB_RATE_SHIFT-3);
796- else
797- SLOT7_2->Cnt += (CH[7].fc * 8);
798- if(SLOT8_1->vib)
799- SLOT8_1->Cnt += (SLOT8_1->Incr * vib) >> VIB_RATE_SHIFT;
800- else
801- SLOT8_1->Cnt += SLOT8_1->Incr;
802- if(SLOT8_2->vib)
803- SLOT8_2->Cnt += ((CH[8].fc * 3) * vib) >> (VIB_RATE_SHIFT-4);
804- else
805- SLOT8_2->Cnt += (CH[8].fc * 48);
806-
807- tone8 = OP_OUT(SLOT8_2,whitenoise,0 );
808-
809- /* SD */
810- if(env_sd < (uint)(EG_ENT - 1))
811- outd[0] += OP_OUT(SLOT7_1, env_sd, 0) * 8;
812- /* TAM */
813- if(env_tam < (uint)(EG_ENT - 1))
814- outd[0] += OP_OUT(SLOT8_1, env_tam, 0) * 2;
815- /* TOP-CY */
816- if(env_top < (uint)(EG_ENT - 1))
817- outd[0] += OP_OUT(SLOT7_2, env_top, tone8) * 2;
818- /* HH */
819- if(env_hh < (uint)(EG_ENT-1))
820- outd[0] += OP_OUT(SLOT7_2, env_hh, tone8) * 2;
821-}
822-
823-/* ----------- initialize time tabls ----------- */
824-static void init_timetables(FM_OPL *OPL, int ARRATE, int DRRATE) {
825- int i;
826- double rate;
827-
828- /* make attack rate & decay rate tables */
829- for (i = 0; i < 4; i++)
830- OPL->AR_TABLE[i] = OPL->DR_TABLE[i] = 0;
831- for (i = 4; i <= 60; i++) {
832- rate = OPL->freqbase; /* frequency rate */
833- if(i < 60)
834- rate *= 1.0 + (i & 3) * 0.25; /* b0-1 : x1 , x1.25 , x1.5 , x1.75 */
835- rate *= 1 << ((i >> 2) - 1); /* b2-5 : shift bit */
836- rate *= (double)(EG_ENT << ENV_BITS);
837- OPL->AR_TABLE[i] = (int)(rate / ARRATE);
838- OPL->DR_TABLE[i] = (int)(rate / DRRATE);
839- }
840- for (i = 60; i < 76; i++) {
841- OPL->AR_TABLE[i] = EG_AED-1;
842- OPL->DR_TABLE[i] = OPL->DR_TABLE[60];
843- }
844-}
845-
846-/* ---------- generic table initialize ---------- */
847-static int OPLOpenTable(void) {
848- int s,t;
849- double rate;
850- int i,j;
851- double pom;
852-
853-#ifdef __DS__
854- DS::fastRamReset();
855-
856- TL_TABLE = (int *) DS::fastRamAlloc(TL_MAX * 2 * sizeof(int *));
857- SIN_TABLE = (int **) DS::fastRamAlloc(SIN_ENT * 4 * sizeof(int *));
858-#else
859-
860- /* allocate dynamic tables */
861- if((TL_TABLE = (int *)malloc(TL_MAX * 2 * sizeof(int))) == NULL)
862- return 0;
863-
864- if((SIN_TABLE = (int **)malloc(SIN_ENT * 4 * sizeof(int *))) == NULL) {
865- free(TL_TABLE);
866- return 0;
867- }
868-#endif
869-
870- if((AMS_TABLE = (int *)malloc(AMS_ENT * 2 * sizeof(int))) == NULL) {
871- free(TL_TABLE);
872- free(SIN_TABLE);
873- return 0;
874- }
875-
876- if((VIB_TABLE = (int *)malloc(VIB_ENT * 2 * sizeof(int))) == NULL) {
877- free(TL_TABLE);
878- free(SIN_TABLE);
879- free(AMS_TABLE);
880- return 0;
881- }
882- /* make total level table */
883- for (t = 0; t < EG_ENT - 1 ; t++) {
884- rate = ((1 << TL_BITS) - 1) / pow(10.0, EG_STEP * t / 20); /* dB -> voltage */
885- TL_TABLE[ t] = (int)rate;
886- TL_TABLE[TL_MAX + t] = -TL_TABLE[t];
887- }
888- /* fill volume off area */
889- for (t = EG_ENT - 1; t < TL_MAX; t++) {
890- TL_TABLE[t] = TL_TABLE[TL_MAX + t] = 0;
891- }
892-
893- /* make sinwave table (total level offet) */
894- /* degree 0 = degree 180 = off */
895- SIN_TABLE[0] = SIN_TABLE[SIN_ENT /2 ] = &TL_TABLE[EG_ENT - 1];
896- for (s = 1;s <= SIN_ENT / 4; s++) {
897- pom = sin(2 * PI * s / SIN_ENT); /* sin */
898- pom = 20 * log10(1 / pom); /* decibel */
899- j = int(pom / EG_STEP); /* TL_TABLE steps */
900-
901- /* degree 0 - 90 , degree 180 - 90 : plus section */
902- SIN_TABLE[ s] = SIN_TABLE[SIN_ENT / 2 - s] = &TL_TABLE[j];
903- /* degree 180 - 270 , degree 360 - 270 : minus section */
904- SIN_TABLE[SIN_ENT / 2 + s] = SIN_TABLE[SIN_ENT - s] = &TL_TABLE[TL_MAX + j];
905- }
906- for (s = 0;s < SIN_ENT; s++) {
907- SIN_TABLE[SIN_ENT * 1 + s] = s < (SIN_ENT / 2) ? SIN_TABLE[s] : &TL_TABLE[EG_ENT];
908- SIN_TABLE[SIN_ENT * 2 + s] = SIN_TABLE[s % (SIN_ENT / 2)];
909- SIN_TABLE[SIN_ENT * 3 + s] = (s / (SIN_ENT / 4)) & 1 ? &TL_TABLE[EG_ENT] : SIN_TABLE[SIN_ENT * 2 + s];
910- }
911-
912-
913- ENV_CURVE = (int *)malloc(sizeof(int) * (2*EG_ENT+1));
914-
915- /* envelope counter -> envelope output table */
916- for (i=0; i < EG_ENT; i++) {
917- /* ATTACK curve */
918- pom = pow(((double)(EG_ENT - 1 - i) / EG_ENT), 8) * EG_ENT;
919- /* if( pom >= EG_ENT ) pom = EG_ENT-1; */
920- ENV_CURVE[i] = (int)pom;
921- /* DECAY ,RELEASE curve */
922- ENV_CURVE[(EG_DST >> ENV_BITS) + i]= i;
923- }
924- /* off */
925- ENV_CURVE[EG_OFF >> ENV_BITS]= EG_ENT - 1;
926- /* make LFO ams table */
927- for (i=0; i < AMS_ENT; i++) {
928- pom = (1.0 + sin(2 * PI * i / AMS_ENT)) / 2; /* sin */
929- AMS_TABLE[i] = (int)((1.0 / EG_STEP) * pom); /* 1dB */
930- AMS_TABLE[AMS_ENT + i] = (int)((4.8 / EG_STEP) * pom); /* 4.8dB */
931- }
932- /* make LFO vibrate table */
933- for (i=0; i < VIB_ENT; i++) {
934- /* 100cent = 1seminote = 6% ?? */
935- pom = (double)VIB_RATE * 0.06 * sin(2 * PI * i / VIB_ENT); /* +-100sect step */
936- VIB_TABLE[i] = (int)(VIB_RATE + (pom * 0.07)); /* +- 7cent */
937- VIB_TABLE[VIB_ENT + i] = (int)(VIB_RATE + (pom * 0.14)); /* +-14cent */
938- }
939- return 1;
940-}
941-
942-static void OPLCloseTable(void) {
943- free(TL_TABLE);
944- free(SIN_TABLE);
945- free(AMS_TABLE);
946- free(VIB_TABLE);
947- free(ENV_CURVE);
948-}
949-
950-/* CSM Key Controll */
951-inline void CSMKeyControll(OPL_CH *CH) {
952- OPL_SLOT *slot1 = &CH->SLOT[SLOT1];
953- OPL_SLOT *slot2 = &CH->SLOT[SLOT2];
954- /* all key off */
955- OPL_KEYOFF(slot1);
956- OPL_KEYOFF(slot2);
957- /* total level latch */
958- slot1->TLL = slot1->TL + (CH->ksl_base>>slot1->ksl);
959- slot1->TLL = slot1->TL + (CH->ksl_base>>slot1->ksl);
960- /* key on */
961- CH->op1_out[0] = CH->op1_out[1] = 0;
962- OPL_KEYON(slot1);
963- OPL_KEYON(slot2);
964-}
965+} // end of namespace AdLib
966
967-/* ---------- opl initialize ---------- */
968-static void OPL_initalize(FM_OPL *OPL) {
969- int fn;
970-
971- /* frequency base */
972- OPL->freqbase = (OPL->rate) ? ((double)OPL->clock / OPL->rate) / 72 : 0;
973- /* Timer base time */
974- OPL->TimerBase = 1.0/((double)OPL->clock / 72.0 );
975- /* make time tables */
976- init_timetables(OPL, OPL_ARRATE, OPL_DRRATE);
977- /* make fnumber -> increment counter table */
978- for( fn=0; fn < 1024; fn++) {
979- OPL->FN_TABLE[fn] = (uint)(OPL->freqbase * fn * FREQ_RATE * (1<<7) / 2);
980- }
981- /* LFO freq.table */
982- OPL->amsIncr = (int)(OPL->rate ? (double)AMS_ENT * (1 << AMS_SHIFT) / OPL->rate * 3.7 * ((double)OPL->clock/3600000) : 0);
983- OPL->vibIncr = (int)(OPL->rate ? (double)VIB_ENT * (1 << VIB_SHIFT) / OPL->rate * 6.4 * ((double)OPL->clock/3600000) : 0);
984-}
985-
986-/* ---------- write a OPL registers ---------- */
987-void OPLWriteReg(FM_OPL *OPL, int r, int v) {
988- OPL_CH *CH;
989- int slot;
990- uint block_fnum;
991-
992- switch(r & 0xe0) {
993- case 0x00: /* 00-1f:controll */
994- switch(r & 0x1f) {
995- case 0x01:
996- /* wave selector enable */
997- if(OPL->type&OPL_TYPE_WAVESEL) {
998- OPL->wavesel = v & 0x20;
999- if(!OPL->wavesel) {
1000- /* preset compatible mode */
1001- int c;
1002- for(c=0; c<OPL->max_ch; c++) {
1003- OPL->P_CH[c].SLOT[SLOT1].wavetable = &SIN_TABLE[0];
1004- OPL->P_CH[c].SLOT[SLOT2].wavetable = &SIN_TABLE[0];
1005- }
1006- }
1007- }
1008- return;
1009- case 0x02: /* Timer 1 */
1010- OPL->T[0] = (256-v) * 4;
1011- break;
1012- case 0x03: /* Timer 2 */
1013- OPL->T[1] = (256-v) * 16;
1014- return;
1015- case 0x04: /* IRQ clear / mask and Timer enable */
1016- if(v & 0x80) { /* IRQ flag clear */
1017- OPL_STATUS_RESET(OPL, 0x7f);
1018- } else { /* set IRQ mask ,timer enable*/
1019- uint8 st1 = v & 1;
1020- uint8 st2 = (v >> 1) & 1;
1021- /* IRQRST,T1MSK,t2MSK,EOSMSK,BRMSK,x,ST2,ST1 */
1022- OPL_STATUS_RESET(OPL, v & 0x78);
1023- OPL_STATUSMASK_SET(OPL,((~v) & 0x78) | 0x01);
1024- /* timer 2 */
1025- if(OPL->st[1] != st2) {
1026- double interval = st2 ? (double)OPL->T[1] * OPL->TimerBase : 0.0;
1027- OPL->st[1] = st2;
1028- if (OPL->TimerHandler) (OPL->TimerHandler)(OPL->TimerParam + 1, interval);
1029- }
1030- /* timer 1 */
1031- if(OPL->st[0] != st1) {
1032- double interval = st1 ? (double)OPL->T[0] * OPL->TimerBase : 0.0;
1033- OPL->st[0] = st1;
1034- if (OPL->TimerHandler) (OPL->TimerHandler)(OPL->TimerParam + 0, interval);
1035- }
1036- }
1037- return;
1038- }
1039- break;
1040- case 0x20: /* am,vib,ksr,eg type,mul */
1041- slot = slot_array[r&0x1f];
1042- if(slot == -1)
1043- return;
1044- set_mul(OPL,slot,v);
1045- return;
1046- case 0x40:
1047- slot = slot_array[r&0x1f];
1048- if(slot == -1)
1049- return;
1050- set_ksl_tl(OPL,slot,v);
1051- return;
1052- case 0x60:
1053- slot = slot_array[r&0x1f];
1054- if(slot == -1)
1055- return;
1056- set_ar_dr(OPL,slot,v);
1057- return;
1058- case 0x80:
1059- slot = slot_array[r&0x1f];
1060- if(slot == -1)
1061- return;
1062- set_sl_rr(OPL,slot,v);
1063- return;
1064- case 0xa0:
1065- switch(r) {
1066- case 0xbd:
1067- /* amsep,vibdep,r,bd,sd,tom,tc,hh */
1068- {
1069- uint8 rkey = OPL->rythm ^ v;
1070- OPL->ams_table = &AMS_TABLE[v & 0x80 ? AMS_ENT : 0];
1071- OPL->vib_table = &VIB_TABLE[v & 0x40 ? VIB_ENT : 0];
1072- OPL->rythm = v & 0x3f;
1073- if(OPL->rythm & 0x20) {
1074- /* BD key on/off */
1075- if(rkey & 0x10) {
1076- if(v & 0x10) {
1077- OPL->P_CH[6].op1_out[0] = OPL->P_CH[6].op1_out[1] = 0;
1078- OPL_KEYON(&OPL->P_CH[6].SLOT[SLOT1]);
1079- OPL_KEYON(&OPL->P_CH[6].SLOT[SLOT2]);
1080- } else {
1081- OPL_KEYOFF(&OPL->P_CH[6].SLOT[SLOT1]);
1082- OPL_KEYOFF(&OPL->P_CH[6].SLOT[SLOT2]);
1083- }
1084- }
1085- /* SD key on/off */
1086- if(rkey & 0x08) {
1087- if(v & 0x08)
1088- OPL_KEYON(&OPL->P_CH[7].SLOT[SLOT2]);
1089- else
1090- OPL_KEYOFF(&OPL->P_CH[7].SLOT[SLOT2]);
1091- }/* TAM key on/off */
1092- if(rkey & 0x04) {
1093- if(v & 0x04)
1094- OPL_KEYON(&OPL->P_CH[8].SLOT[SLOT1]);
1095- else
1096- OPL_KEYOFF(&OPL->P_CH[8].SLOT[SLOT1]);
1097- }
1098- /* TOP-CY key on/off */
1099- if(rkey & 0x02) {
1100- if(v & 0x02)
1101- OPL_KEYON(&OPL->P_CH[8].SLOT[SLOT2]);
1102- else
1103- OPL_KEYOFF(&OPL->P_CH[8].SLOT[SLOT2]);
1104- }
1105- /* HH key on/off */
1106- if(rkey & 0x01) {
1107- if(v & 0x01)
1108- OPL_KEYON(&OPL->P_CH[7].SLOT[SLOT1]);
1109- else
1110- OPL_KEYOFF(&OPL->P_CH[7].SLOT[SLOT1]);
1111- }
1112- }
1113- }
1114- return;
1115-
1116- default:
1117- break;
1118- }
1119- /* keyon,block,fnum */
1120- if((r & 0x0f) > 8)
1121- return;
1122- CH = &OPL->P_CH[r & 0x0f];
1123- if(!(r&0x10)) { /* a0-a8 */
1124- block_fnum = (CH->block_fnum & 0x1f00) | v;
1125- } else { /* b0-b8 */
1126- int keyon = (v >> 5) & 1;
1127- block_fnum = ((v & 0x1f) << 8) | (CH->block_fnum & 0xff);
1128- if(CH->keyon != keyon) {
1129- if((CH->keyon=keyon)) {
1130- CH->op1_out[0] = CH->op1_out[1] = 0;
1131- OPL_KEYON(&CH->SLOT[SLOT1]);
1132- OPL_KEYON(&CH->SLOT[SLOT2]);
1133- } else {
1134- OPL_KEYOFF(&CH->SLOT[SLOT1]);
1135- OPL_KEYOFF(&CH->SLOT[SLOT2]);
1136- }
1137- }
1138- }
1139- /* update */
1140- if(CH->block_fnum != block_fnum) {
1141- int blockRv = 7 - (block_fnum >> 10);
1142- int fnum = block_fnum & 0x3ff;
1143- CH->block_fnum = block_fnum;
1144- CH->ksl_base = KSL_TABLE[block_fnum >> 6];
1145- CH->fc = OPL->FN_TABLE[fnum] >> blockRv;
1146- CH->kcode = CH->block_fnum >> 9;
1147- if((OPL->mode & 0x40) && CH->block_fnum & 0x100)
1148- CH->kcode |=1;
1149- CALC_FCSLOT(CH,&CH->SLOT[SLOT1]);
1150- CALC_FCSLOT(CH,&CH->SLOT[SLOT2]);
1151- }
1152- return;
1153- case 0xc0:
1154- /* FB,C */
1155- if((r & 0x0f) > 8)
1156- return;
1157- CH = &OPL->P_CH[r&0x0f];
1158- {
1159- int feedback = (v >> 1) & 7;
1160- CH->FB = feedback ? (8 + 1) - feedback : 0;
1161- CH->CON = v & 1;
1162- set_algorythm(CH);
1163- }
1164- return;
1165- case 0xe0: /* wave type */
1166- slot = slot_array[r & 0x1f];
1167- if(slot == -1)
1168- return;
1169- CH = &OPL->P_CH[slot>>1];
1170- if(OPL->wavesel) {
1171- CH->SLOT[slot&1].wavetable = &SIN_TABLE[(v & 0x03) * SIN_ENT];
1172- }
1173- return;
1174- }
1175-}
1176-
1177-/* lock/unlock for common table */
1178-static int OPL_LockTable(void) {
1179- num_lock++;
1180- if(num_lock>1)
1181- return 0;
1182- /* first time */
1183- cur_chip = NULL;
1184- /* allocate total level table (128kb space) */
1185- if(!OPLOpenTable()) {
1186- num_lock--;
1187- return -1;
1188- }
1189- return 0;
1190-}
1191-
1192-static void OPL_UnLockTable(void) {
1193- if(num_lock)
1194- num_lock--;
1195- if(num_lock)
1196- return;
1197- /* last time */
1198- cur_chip = NULL;
1199- OPLCloseTable();
1200-}
1201-
1202-/*******************************************************************************/
1203-/* YM3812 local section */
1204-/*******************************************************************************/
1205-
1206-/* ---------- update one of chip ----------- */
1207-void YM3812UpdateOne(FM_OPL *OPL, int16 *buffer, int length, int interleave) {
1208- int i;
1209- int data;
1210- int16 *buf = buffer;
1211- uint amsCnt = OPL->amsCnt;
1212- uint vibCnt = OPL->vibCnt;
1213- uint8 rythm = OPL->rythm & 0x20;
1214- OPL_CH *CH, *R_CH;
1215-
1216-
1217- if((void *)OPL != cur_chip) {
1218- cur_chip = (void *)OPL;
1219- /* channel pointers */
1220- S_CH = OPL->P_CH;
1221- E_CH = &S_CH[9];
1222- /* rythm slot */
1223- SLOT7_1 = &S_CH[7].SLOT[SLOT1];
1224- SLOT7_2 = &S_CH[7].SLOT[SLOT2];
1225- SLOT8_1 = &S_CH[8].SLOT[SLOT1];
1226- SLOT8_2 = &S_CH[8].SLOT[SLOT2];
1227- /* LFO state */
1228- amsIncr = OPL->amsIncr;
1229- vibIncr = OPL->vibIncr;
1230- ams_table = OPL->ams_table;
1231- vib_table = OPL->vib_table;
1232- }
1233- R_CH = rythm ? &S_CH[6] : E_CH;
1234- for(i = 0; i < length; i++) {
1235- /* channel A channel B channel C */
1236- /* LFO */
1237- ams = ams_table[(amsCnt += amsIncr) >> AMS_SHIFT];
1238- vib = vib_table[(vibCnt += vibIncr) >> VIB_SHIFT];
1239- outd[0] = 0;
1240- /* FM part */
1241- for(CH=S_CH; CH < R_CH; CH++)
1242- OPL_CALC_CH(CH);
1243- /* Rythn part */
1244- if(rythm)
1245- OPL_CALC_RH(OPL, S_CH);
1246- /* limit check */
1247- data = CLIP(outd[0], OPL_MINOUT, OPL_MAXOUT);
1248- /* store to sound buffer */
1249- buf[i << interleave] = data >> OPL_OUTSB;
1250- }
1251-
1252- OPL->amsCnt = amsCnt;
1253- OPL->vibCnt = vibCnt;
1254-}
1255-
1256-/* ---------- reset a chip ---------- */
1257-void OPLResetChip(FM_OPL *OPL) {
1258- int c,s;
1259- int i;
1260-
1261- /* reset chip */
1262- OPL->mode = 0; /* normal mode */
1263- OPL_STATUS_RESET(OPL, 0x7f);
1264- /* reset with register write */
1265- OPLWriteReg(OPL, 0x01,0); /* wabesel disable */
1266- OPLWriteReg(OPL, 0x02,0); /* Timer1 */
1267- OPLWriteReg(OPL, 0x03,0); /* Timer2 */
1268- OPLWriteReg(OPL, 0x04,0); /* IRQ mask clear */
1269- for(i = 0xff; i >= 0x20; i--)
1270- OPLWriteReg(OPL,i,0);
1271- /* reset OPerator parameter */
1272- for(c = 0; c < OPL->max_ch ;c++ ) {
1273- OPL_CH *CH = &OPL->P_CH[c];
1274- /* OPL->P_CH[c].PAN = OPN_CENTER; */
1275- for(s = 0; s < 2; s++ ) {
1276- /* wave table */
1277- CH->SLOT[s].wavetable = &SIN_TABLE[0];
1278- /* CH->SLOT[s].evm = ENV_MOD_RR; */
1279- CH->SLOT[s].evc = EG_OFF;
1280- CH->SLOT[s].eve = EG_OFF + 1;
1281- CH->SLOT[s].evs = 0;
1282- }
1283- }
1284-}
1285-
1286-/* ---------- Create a virtual YM3812 ---------- */
1287-/* 'rate' is sampling rate and 'bufsiz' is the size of the */
1288-FM_OPL *OPLCreate(int type, int clock, int rate) {
1289- char *ptr;
1290- FM_OPL *OPL;
1291- int state_size;
1292- int max_ch = 9; /* normaly 9 channels */
1293-
1294- if( OPL_LockTable() == -1)
1295- return NULL;
1296- /* allocate OPL state space */
1297- state_size = sizeof(FM_OPL);
1298- state_size += sizeof(OPL_CH) * max_ch;
1299-
1300- /* allocate memory block */
1301- ptr = (char *)calloc(state_size, 1);
1302- if(ptr == NULL)
1303- return NULL;
1304-
1305- /* clear */
1306- memset(ptr, 0, state_size);
1307- OPL = (FM_OPL *)ptr; ptr += sizeof(FM_OPL);
1308- OPL->P_CH = (OPL_CH *)ptr; ptr += sizeof(OPL_CH) * max_ch;
1309-
1310- /* set channel state pointer */
1311- OPL->type = type;
1312- OPL->clock = clock;
1313- OPL->rate = rate;
1314- OPL->max_ch = max_ch;
1315-
1316- /* init grobal tables */
1317- OPL_initalize(OPL);
1318-
1319- /* reset chip */
1320- OPLResetChip(OPL);
1321- return OPL;
1322-}
1323-
1324-/* ---------- Destroy one of vietual YM3812 ---------- */
1325 void OPLDestroy(FM_OPL *OPL) {
1326- OPL_UnLockTable();
1327- free(OPL);
1328-}
1329-
1330-/* ---------- Option handlers ---------- */
1331-void OPLSetTimerHandler(FM_OPL *OPL, OPL_TIMERHANDLER TimerHandler,int channelOffset) {
1332- OPL->TimerHandler = TimerHandler;
1333- OPL->TimerParam = channelOffset;
1334+ delete OPL;
1335 }
1336
1337-void OPLSetIRQHandler(FM_OPL *OPL, OPL_IRQHANDLER IRQHandler, int param) {
1338- OPL->IRQHandler = IRQHandler;
1339- OPL->IRQParam = param;
1340+void OPLResetChip(FM_OPL *OPL) {
1341+ OPL->reset();
1342 }
1343
1344-void OPLSetUpdateHandler(FM_OPL *OPL, OPL_UPDATEHANDLER UpdateHandler,int param) {
1345- OPL->UpdateHandler = UpdateHandler;
1346- OPL->UpdateParam = param;
1347+void OPLWrite(FM_OPL *OPL, int a, int v) {
1348+ OPL->write(a, v);
1349 }
1350
1351-/* ---------- YM3812 I/O interface ---------- */
1352-int OPLWrite(FM_OPL *OPL,int a,int v) {
1353- if(!(a & 1)) { /* address port */
1354- OPL->address = v & 0xff;
1355- } else { /* data port */
1356- if(OPL->UpdateHandler)
1357- OPL->UpdateHandler(OPL->UpdateParam,0);
1358- OPLWriteReg(OPL, OPL->address,v);
1359- }
1360- return OPL->status >> 7;
1361+unsigned char OPLRead(FM_OPL *OPL, int a) {
1362+ return OPL->read(a);
1363 }
1364
1365-unsigned char OPLRead(FM_OPL *OPL,int a) {
1366- if(!(a & 1)) { /* status port */
1367- return OPL->status & (OPL->statusmask | 0x80);
1368- }
1369- /* data port */
1370- switch(OPL->address) {
1371- case 0x05: /* KeyBoard IN */
1372- warning("OPL:read unmapped KEYBOARD port\n");
1373- return 0;
1374- case 0x19: /* I/O DATA */
1375- warning("OPL:read unmapped I/O port\n");
1376- return 0;
1377- case 0x1a: /* PCM-DATA */
1378- return 0;
1379- default:
1380- break;
1381- }
1382- return 0;
1383+void OPLWriteReg(FM_OPL *OPL, int r, int v) {
1384+ OPL->writeReg(r, v);
1385 }
1386
1387-int OPLTimerOver(FM_OPL *OPL, int c) {
1388- if(c) { /* Timer B */
1389- OPL_STATUS_SET(OPL, 0x20);
1390- } else { /* Timer A */
1391- OPL_STATUS_SET(OPL, 0x40);
1392- /* CSM mode key,TL controll */
1393- if(OPL->mode & 0x80) { /* CSM mode total level latch and auto key on */
1394- int ch;
1395- if(OPL->UpdateHandler)
1396- OPL->UpdateHandler(OPL->UpdateParam,0);
1397- for(ch = 0; ch < 9; ch++)
1398- CSMKeyControll(&OPL->P_CH[ch]);
1399- }
1400- }
1401- /* reload timer */
1402- if (OPL->TimerHandler)
1403- (OPL->TimerHandler)(OPL->TimerParam + c, (double)OPL->T[c] * OPL->TimerBase);
1404- return OPL->status >> 7;
1405+void YM3812UpdateOne(FM_OPL *OPL, int16 *buffer, int length) {
1406+ OPL->readBuffer(buffer, length);
1407 }
1408
1409+// Factory method
1410 FM_OPL *makeAdlibOPL(int rate) {
1411- // We need to emulate one YM3812 chip
1412- int env_bits = FMOPL_ENV_BITS_HQ;
1413- int eg_ent = FMOPL_EG_ENT_HQ;
1414-#if defined (_WIN32_WCE) || defined(__SYMBIAN32__) || defined(PALMOS_MODE) || defined(__GP32__) || defined (GP2X) || defined(__MAEMO__) || defined(__DS__) || defined (__MINT__)
1415- if (ConfMan.hasKey("FM_high_quality") && ConfMan.getBool("FM_high_quality")) {
1416- env_bits = FMOPL_ENV_BITS_HQ;
1417- eg_ent = FMOPL_EG_ENT_HQ;
1418- } else if (ConfMan.hasKey("FM_medium_quality") && ConfMan.getBool("FM_medium_quality")) {
1419- env_bits = FMOPL_ENV_BITS_MQ;
1420- eg_ent = FMOPL_EG_ENT_MQ;
1421- } else {
1422- env_bits = FMOPL_ENV_BITS_LQ;
1423- eg_ent = FMOPL_EG_ENT_LQ;
1424- }
1425-#endif
1426-
1427- OPLBuildTables(env_bits, eg_ent);
1428- return OPLCreate(OPL_TYPE_YM3812, 3579545, rate);
1429+ FM_OPL *opl = AdLib::AdLib::createInstance();
1430+ if (opl)
1431+ opl->init(rate);
1432+ return opl;
1433 }
1434+
1435Index: sound/softsynth/adlib/dosbox.cpp
1436===================================================================
1437--- sound/softsynth/adlib/dosbox.cpp (revision 0)
1438+++ sound/softsynth/adlib/dosbox.cpp (revision 0)
1439@@ -0,0 +1,284 @@
1440+/* ScummVM - Graphic Adventure Engine
1441+ *
1442+ * ScummVM is the legal property of its developers, whose names
1443+ * are too numerous to list here. Please refer to the COPYRIGHT
1444+ * file distributed with this source distribution.
1445+ *
1446+ * This program is free software; you can redistribute it and/or
1447+ * modify it under the terms of the GNU General Public License
1448+ * as published by the Free Software Foundation; either version 2
1449+ * of the License, or (at your option) any later version.
1450+ *
1451+ * This program is distributed in the hope that it will be useful,
1452+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
1453+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
1454+ * GNU General Public License for more details.
1455+ *
1456+ * You should have received a copy of the GNU General Public License
1457+ * along with this program; if not, write to the Free Software
1458+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
1459+ *
1460+ * $URL$
1461+ * $Id$
1462+ */
1463+
1464+/*
1465+ * Based on AdLib emulation code of DOSBox
1466+ * Copyright (C) 2002-2009 The DOSBox Team
1467+ * Licensed under GPLv2+
1468+ * http://www.dosbox.com
1469+ */
1470+
1471+#ifndef DISABLE_DOSBOX_ADLIB
1472+
1473+#include "dosbox.h"
1474+#include "dbopl.h"
1475+
1476+#include "common/system.h"
1477+
1478+#include <math.h>
1479+#include <string.h>
1480+
1481+namespace AdLib {
1482+namespace DOSBox {
1483+
1484+Timer::Timer() {
1485+ masked = false;
1486+ overflow = false;
1487+ enabled = false;
1488+ counter = 0;
1489+ delay = 0;
1490+}
1491+
1492+void Timer::update(double time) {
1493+ if (!enabled || !delay)
1494+ return;
1495+ double deltaStart = time - startTime;
1496+ // Only set the overflow flag when not masked
1497+ if (deltaStart >= 0 && !masked)
1498+ overflow = 1;
1499+}
1500+
1501+void Timer::reset(double time) {
1502+ overflow = false;
1503+ if (!delay || !enabled)
1504+ return;
1505+ double delta = (time - startTime);
1506+ double rem = fmod(delta, delay);
1507+ double next = delay - rem;
1508+ startTime = time + next;
1509+}
1510+
1511+void Timer::stop() {
1512+ enabled = false;
1513+}
1514+
1515+void Timer::start(double time, int scale) {
1516+ //Don't enable again
1517+ if (enabled)
1518+ return;
1519+ enabled = true;
1520+ delay = 0.001 * (256 - counter) * scale;
1521+ startTime = time + delay;
1522+}
1523+
1524+bool Chip::write(uint32 reg, uint8 val) {
1525+ switch (reg) {
1526+ case 0x02:
1527+ timer[0].counter = val;
1528+ return true;
1529+ case 0x03:
1530+ timer[1].counter = val;
1531+ return true;
1532+ case 0x04:
1533+ // TODO: I couldn't get behind the PIC_FullIndex logic, but I would guess
1534+ // it should be like this...
1535+ double time = g_system->getMillis() / 1000.0;
1536+
1537+ if (val & 0x80) {
1538+ timer[0].reset(time);
1539+ timer[1].reset(time);
1540+ } else {
1541+ timer[0].update(time);
1542+ timer[1].update(time);
1543+
1544+ if (val & 0x1)
1545+ timer[0].start(time, 80);
1546+ else
1547+ timer[0].stop();
1548+
1549+ timer[0].masked = (val & 0x40) > 0;
1550+
1551+ if (timer[0].masked)
1552+ timer[0].overflow = false;
1553+
1554+ if (val & 0x2)
1555+ timer[1].start(time, 320);
1556+ else
1557+ timer[1].stop();
1558+
1559+ timer[1].masked = (val & 0x20) > 0;
1560+
1561+ if (timer[1].masked)
1562+ timer[1].overflow = false;
1563+ }
1564+ return true;
1565+ }
1566+ return false;
1567+}
1568+
1569+uint8 Chip::read() {
1570+ // TODO: I couldn't get behind the PIC_FullIndex logic, but I would guess
1571+ // it should be like this...
1572+ double time = g_system->getMillis() / 1000.0;
1573+
1574+ timer[0].update(time);
1575+ timer[1].update(time);
1576+
1577+ uint8 ret = 0;
1578+ //Overflow won't be set if a channel is masked
1579+ if (timer[0].overflow) {
1580+ ret |= 0x40;
1581+ ret |= 0x80;
1582+ }
1583+ if (timer[1].overflow) {
1584+ ret |= 0x20;
1585+ ret |= 0x80;
1586+ }
1587+ return ret;
1588+}
1589+
1590+AdLib_DOSBox::AdLib_DOSBox() : _type(kOpl2), _rate(0), _handler(0) {
1591+}
1592+
1593+AdLib_DOSBox::~AdLib_DOSBox() {
1594+ free();
1595+}
1596+
1597+void AdLib_DOSBox::free() {
1598+ delete _handler;
1599+ _handler = 0;
1600+}
1601+
1602+void AdLib_DOSBox::init(int rate, kOplType type) {
1603+ free();
1604+
1605+ _reg.dual[0] = 0;
1606+ _reg.dual[1] = 0;
1607+ _reg.normal = 0;
1608+
1609+ memset(_chip, 0, sizeof(_chip));
1610+ _type = type;
1611+
1612+ switch (_type) {
1613+ case kOpl2:
1614+ _handler = new DBOPL::Handler();
1615+ break;
1616+ }
1617+
1618+ _handler->init(rate);
1619+ _rate = rate;
1620+}
1621+
1622+void AdLib_DOSBox::reset() {
1623+ // TODO: Find a nicer way to reset the emulator
1624+ init(_rate, _type);
1625+}
1626+
1627+void AdLib_DOSBox::write(int port, int val) {
1628+ if (port&1) {
1629+ switch (_type) {
1630+ case kOpl2:
1631+ //case kOpl3:
1632+ if (!_chip[0].write(_reg.normal, val))
1633+ _handler->writeReg(_reg.normal, val);
1634+ break;
1635+ /*case kDualOpl2:
1636+ // Not a 0x??8 port, then write to a specific port
1637+ if (!(port & 0x8)) {
1638+ byte index = (port & 2) >> 1;
1639+ dualWrite(index, _reg.dual[index], val);
1640+ } else {
1641+ //Write to both ports
1642+ dualWrite(0, _reg.dual[0], val);
1643+ dualWrite(1, _reg.dual[1], val);
1644+ }
1645+ break;*/
1646+ }
1647+ } else {
1648+ // Ask the handler to write the address
1649+ // Make sure to clip them in the right range
1650+ switch (_type) {
1651+ case kOpl2:
1652+ _reg.normal = _handler->writeAddr(port, val) & 0xff;
1653+ break;
1654+ /*case kOpl3:
1655+ _reg.normal = _handler->writeAddr(port, val) & 0x1ff;
1656+ break;
1657+ case kDualOpl2:
1658+ // Not a 0x?88 port, when write to a specific side
1659+ if (!(port & 0x8)) {
1660+ byte index = (port & 2) >> 1;
1661+ _reg.dual[index] = val & 0xff;
1662+ } else {
1663+ _reg.dual[0] = val & 0xff;
1664+ _reg.dual[1] = val & 0xff;
1665+ }
1666+ break;*/
1667+ }
1668+ }
1669+}
1670+
1671+byte AdLib_DOSBox::read(int port) {
1672+ switch (_type) {
1673+ case kOpl2:
1674+ if (!(port & 1))
1675+ //Make sure the low bits are 6 on opl2
1676+ return _chip[0].read() | 0x6;
1677+ break;
1678+ /*case kOpl3:
1679+ if (!(port & 1))
1680+ return _chip[0].read();
1681+ break;
1682+ case kDualOpl2:
1683+ // Only return for the lower ports
1684+ if (port & 1)
1685+ return 0xff;
1686+ // Make sure the low bits are 6 on opl2
1687+ return _chip[(port >> 1) & 1].read() | 0x6;*/
1688+ }
1689+ return 0;
1690+}
1691+
1692+void AdLib_DOSBox::writeReg(int r, int v) {
1693+ byte tempReg = 0;
1694+ switch (_type) {
1695+ case kOpl2:
1696+ //case kOpl3:
1697+ // We can't use _handler->writeReg here directly, since it would miss timer changes.
1698+
1699+ // Backup old setup register
1700+ tempReg = _reg.normal;
1701+
1702+ // We need to set the register we want to write to via port 0x388
1703+ write(0x388, r);
1704+ // Do the real writing to the register
1705+ write(0x389, v);
1706+ // Restore the old register
1707+ write(0x388, tempReg);
1708+ break;
1709+
1710+ //case kDualOpl2:
1711+ // error("Can't use AdLib_DOSBox::writeReg on Dual OPL2");
1712+ // break;
1713+ };
1714+}
1715+
1716+void AdLib_DOSBox::readBuffer(int16 *buffer, int length) {
1717+ _handler->generate(buffer, length);
1718+}
1719+
1720+} // end of namespace DOSBox
1721+} // end of namespace AdLib
1722+
1723+#endif // !DISABLE_DOSBOX_ADLIB
1724Index: sound/softsynth/adlib/mame.cpp
1725===================================================================
1726--- sound/softsynth/adlib/mame.cpp (revision 0)
1727+++ sound/softsynth/adlib/mame.cpp (revision 0)
1728@@ -0,0 +1,1230 @@
1729+/* ScummVM - Graphic Adventure Engine
1730+ *
1731+ * ScummVM is the legal property of its developers, whose names
1732+ * are too numerous to list here. Please refer to the COPYRIGHT
1733+ * file distributed with this source distribution.
1734+ *
1735+ * This program is free software; you can redistribute it and/or
1736+ * modify it under the terms of the GNU General Public License
1737+ * as published by the Free Software Foundation; either version 2
1738+ * of the License, or (at your option) any later version.
1739+
1740+ * This program is distributed in the hope that it will be useful,
1741+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
1742+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
1743+ * GNU General Public License for more details.
1744+
1745+ * You should have received a copy of the GNU General Public License
1746+ * along with this program; if not, write to the Free Software
1747+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
1748+ *
1749+ * $URL: https://scummvm.svn.sourceforge.net/svnroot/scummvm/scummvm/trunk/sound/fmopl.cpp $
1750+ * $Id: fmopl.cpp 38211 2009-02-15 10:07:50Z sev $
1751+ *
1752+ * LGPL licensed version of MAMEs fmopl (V0.37a modified) by
1753+ * Tatsuyuki Satoh. Included from LGPL'ed AdPlug.
1754+ */
1755+
1756+#include <stdio.h>
1757+#include <stdlib.h>
1758+#include <string.h>
1759+#include <stdarg.h>
1760+#include <math.h>
1761+
1762+#include "mame.h"
1763+
1764+#if defined (_WIN32_WCE) || defined (__SYMBIAN32__) || defined(PALMOS_MODE) || defined(__GP32__) || defined(GP2X) || defined (__MAEMO__) || defined(__DS__) || defined (__MINT__)
1765+#include "common/config-manager.h"
1766+#endif
1767+
1768+namespace AdLib {
1769+namespace MAME {
1770+
1771+AdLib_MAME::~AdLib_MAME() {
1772+ MAME::OPLDestroy(_opl);
1773+ _opl = 0;
1774+}
1775+
1776+void AdLib_MAME::init(int rate, kOplType type) {
1777+ if (_opl)
1778+ MAME::OPLDestroy(_opl);
1779+
1780+ _opl = MAME::makeAdlibOPL(rate);
1781+}
1782+
1783+void AdLib_MAME::reset() {
1784+ MAME::OPLResetChip(_opl);
1785+}
1786+
1787+void AdLib_MAME::write(int a, int v) {
1788+ MAME::OPLWrite(_opl, a, v);
1789+}
1790+
1791+byte AdLib_MAME::read(int a) {
1792+ return MAME::OPLRead(_opl, a);
1793+}
1794+
1795+void AdLib_MAME::writeReg(int r, int v) {
1796+ MAME::OPLWriteReg(_opl, r, v);
1797+}
1798+
1799+void AdLib_MAME::readBuffer(int16 *buffer, int length) {
1800+ MAME::YM3812UpdateOne(_opl, buffer, length);
1801+}
1802+
1803+/* -------------------- preliminary define section --------------------- */
1804+/* attack/decay rate time rate */
1805+#define OPL_ARRATE 141280 /* RATE 4 = 2826.24ms @ 3.6MHz */
1806+#define OPL_DRRATE 1956000 /* RATE 4 = 39280.64ms @ 3.6MHz */
1807+
1808+#define FREQ_BITS 24 /* frequency turn */
1809+
1810+/* counter bits = 20 , octerve 7 */
1811+#define FREQ_RATE (1<<(FREQ_BITS-20))
1812+#define TL_BITS (FREQ_BITS+2)
1813+
1814+/* final output shift , limit minimum and maximum */
1815+#define OPL_OUTSB (TL_BITS+3-16) /* OPL output final shift 16bit */
1816+#define OPL_MAXOUT (0x7fff<<OPL_OUTSB)
1817+#define OPL_MINOUT (-0x8000<<OPL_OUTSB)
1818+
1819+/* -------------------- quality selection --------------------- */
1820+
1821+/* sinwave entries */
1822+/* used static memory = SIN_ENT * 4 (byte) */
1823+#ifdef __DS__
1824+#include "dsmain.h"
1825+#define SIN_ENT_SHIFT 8
1826+#else
1827+#define SIN_ENT_SHIFT 11
1828+#endif
1829+#define SIN_ENT (1<<SIN_ENT_SHIFT)
1830+
1831+/* output level entries (envelope,sinwave) */
1832+/* envelope counter lower bits */
1833+int ENV_BITS;
1834+/* envelope output entries */
1835+int EG_ENT;
1836+
1837+/* used dynamic memory = EG_ENT*4*4(byte)or EG_ENT*6*4(byte) */
1838+/* used static memory = EG_ENT*4 (byte) */
1839+int EG_OFF; /* OFF */
1840+int EG_DED;
1841+int EG_DST; /* DECAY START */
1842+int EG_AED;
1843+#define EG_AST 0 /* ATTACK START */
1844+
1845+#define EG_STEP (96.0/EG_ENT) /* OPL is 0.1875 dB step */
1846+
1847+/* LFO table entries */
1848+#define VIB_ENT 512
1849+#define VIB_SHIFT (32-9)
1850+#define AMS_ENT 512
1851+#define AMS_SHIFT (32-9)
1852+
1853+#define VIB_RATE_SHIFT 8
1854+#define VIB_RATE (1<<VIB_RATE_SHIFT)
1855+
1856+/* -------------------- local defines , macros --------------------- */
1857+
1858+/* register number to channel number , slot offset */
1859+#define SLOT1 0
1860+#define SLOT2 1
1861+
1862+/* envelope phase */
1863+#define ENV_MOD_RR 0x00
1864+#define ENV_MOD_DR 0x01
1865+#define ENV_MOD_AR 0x02
1866+
1867+/* -------------------- tables --------------------- */
1868+static const int slot_array[32] = {
1869+ 0, 2, 4, 1, 3, 5,-1,-1,
1870+ 6, 8,10, 7, 9,11,-1,-1,
1871+ 12,14,16,13,15,17,-1,-1,
1872+ -1,-1,-1,-1,-1,-1,-1,-1
1873+};
1874+
1875+static uint KSL_TABLE[8 * 16];
1876+
1877+static const double KSL_TABLE_SEED[8 * 16] = {
1878+ /* OCT 0 */
1879+ 0.000, 0.000, 0.000, 0.000,
1880+ 0.000, 0.000, 0.000, 0.000,
1881+ 0.000, 0.000, 0.000, 0.000,
1882+ 0.000, 0.000, 0.000, 0.000,
1883+ /* OCT 1 */
1884+ 0.000, 0.000, 0.000, 0.000,
1885+ 0.000, 0.000, 0.000, 0.000,
1886+ 0.000, 0.750, 1.125, 1.500,
1887+ 1.875, 2.250, 2.625, 3.000,
1888+ /* OCT 2 */
1889+ 0.000, 0.000, 0.000, 0.000,
1890+ 0.000, 1.125, 1.875, 2.625,
1891+ 3.000, 3.750, 4.125, 4.500,
1892+ 4.875, 5.250, 5.625, 6.000,
1893+ /* OCT 3 */
1894+ 0.000, 0.000, 0.000, 1.875,
1895+ 3.000, 4.125, 4.875, 5.625,
1896+ 6.000, 6.750, 7.125, 7.500,
1897+ 7.875, 8.250, 8.625, 9.000,
1898+ /* OCT 4 */
1899+ 0.000, 0.000, 3.000, 4.875,
1900+ 6.000, 7.125, 7.875, 8.625,
1901+ 9.000, 9.750, 10.125, 10.500,
1902+ 10.875, 11.250, 11.625, 12.000,
1903+ /* OCT 5 */
1904+ 0.000, 3.000, 6.000, 7.875,
1905+ 9.000, 10.125, 10.875, 11.625,
1906+ 12.000, 12.750, 13.125, 13.500,
1907+ 13.875, 14.250, 14.625, 15.000,
1908+ /* OCT 6 */
1909+ 0.000, 6.000, 9.000, 10.875,
1910+ 12.000, 13.125, 13.875, 14.625,
1911+ 15.000, 15.750, 16.125, 16.500,
1912+ 16.875, 17.250, 17.625, 18.000,
1913+ /* OCT 7 */
1914+ 0.000, 9.000, 12.000, 13.875,
1915+ 15.000, 16.125, 16.875, 17.625,
1916+ 18.000, 18.750, 19.125, 19.500,
1917+ 19.875, 20.250, 20.625, 21.000
1918+};
1919+
1920+/* sustain level table (3db per step) */
1921+/* 0 - 15: 0, 3, 6, 9,12,15,18,21,24,27,30,33,36,39,42,93 (dB)*/
1922+
1923+static int SL_TABLE[16];
1924+
1925+static const uint SL_TABLE_SEED[16] = {
1926+ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 31
1927+};
1928+
1929+#define TL_MAX (EG_ENT * 2) /* limit(tl + ksr + envelope) + sinwave */
1930+/* TotalLevel : 48 24 12 6 3 1.5 0.75 (dB) */
1931+/* TL_TABLE[ 0 to TL_MAX ] : plus section */
1932+/* TL_TABLE[ TL_MAX to TL_MAX+TL_MAX-1 ] : minus section */
1933+static int *TL_TABLE;
1934+
1935+/* pointers to TL_TABLE with sinwave output offset */
1936+static int **SIN_TABLE;
1937+
1938+/* LFO table */
1939+static int *AMS_TABLE;
1940+static int *VIB_TABLE;
1941+
1942+/* envelope output curve table */
1943+/* attack + decay + OFF */
1944+//static int ENV_CURVE[2*EG_ENT+1];
1945+//static int ENV_CURVE[2 * 4096 + 1]; // to keep it static ...
1946+static int *ENV_CURVE;
1947+
1948+
1949+/* multiple table */
1950+#define ML(a) (int)(a * 2)
1951+static const uint MUL_TABLE[16]= {
1952+/* 1/2, 1, 2, 3, 4, 5, 6, 7, 8, 9,10,11,12,13,14,15 */
1953+ ML(0.50), ML(1.00), ML(2.00), ML(3.00), ML(4.00), ML(5.00), ML(6.00), ML(7.00),
1954+ ML(8.00), ML(9.00), ML(10.00), ML(10.00),ML(12.00),ML(12.00),ML(15.00),ML(15.00)
1955+};
1956+#undef ML
1957+
1958+/* dummy attack / decay rate ( when rate == 0 ) */
1959+static int RATE_0[16]=
1960+{0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0};
1961+
1962+/* -------------------- static state --------------------- */
1963+
1964+/* lock level of common table */
1965+static int num_lock = 0;
1966+
1967+/* work table */
1968+static void *cur_chip = NULL; /* current chip point */
1969+/* currenct chip state */
1970+/* static OPLSAMPLE *bufL,*bufR; */
1971+static OPL_CH *S_CH;
1972+static OPL_CH *E_CH;
1973+OPL_SLOT *SLOT7_1, *SLOT7_2, *SLOT8_1, *SLOT8_2;
1974+
1975+static int outd[1];
1976+static int ams;
1977+static int vib;
1978+int *ams_table;
1979+int *vib_table;
1980+static int amsIncr;
1981+static int vibIncr;
1982+static int feedback2; /* connect for SLOT 2 */
1983+
1984+/* --------------------- rebuild tables ------------------- */
1985+
1986+#define SC_KSL(mydb) ((uint) (mydb / (EG_STEP / 2)))
1987+#define SC_SL(db) (int)(db * ((3 / EG_STEP) * (1 << ENV_BITS))) + EG_DST
1988+
1989+void OPLBuildTables(int ENV_BITS_PARAM, int EG_ENT_PARAM) {
1990+ int i;
1991+
1992+ ENV_BITS = ENV_BITS_PARAM;
1993+ EG_ENT = EG_ENT_PARAM;
1994+ EG_OFF = ((2 * EG_ENT)<<ENV_BITS); /* OFF */
1995+ EG_DED = EG_OFF;
1996+ EG_DST = (EG_ENT << ENV_BITS); /* DECAY START */
1997+ EG_AED = EG_DST;
1998+ //EG_STEP = (96.0/EG_ENT);
1999+
2000+ for (i = 0; i < ARRAYSIZE(KSL_TABLE_SEED); i++)
2001+ KSL_TABLE[i] = SC_KSL(KSL_TABLE_SEED[i]);
2002+
2003+ for (i = 0; i < ARRAYSIZE(SL_TABLE_SEED); i++)
2004+ SL_TABLE[i] = SC_SL(SL_TABLE_SEED[i]);
2005+}
2006+
2007+#undef SC_KSL
2008+#undef SC_SL
2009+
2010+/* --------------------- subroutines --------------------- */
2011+
2012+/* status set and IRQ handling */
2013+inline void OPL_STATUS_SET(FM_OPL *OPL, int flag) {
2014+ /* set status flag */
2015+ OPL->status |= flag;
2016+ if(!(OPL->status & 0x80)) {
2017+ if(OPL->status & OPL->statusmask) { /* IRQ on */
2018+ OPL->status |= 0x80;
2019+ /* callback user interrupt handler (IRQ is OFF to ON) */
2020+ if(OPL->IRQHandler)
2021+ (OPL->IRQHandler)(OPL->IRQParam,1);
2022+ }
2023+ }
2024+}
2025+
2026+/* status reset and IRQ handling */
2027+inline void OPL_STATUS_RESET(FM_OPL *OPL, int flag) {
2028+ /* reset status flag */
2029+ OPL->status &= ~flag;
2030+ if((OPL->status & 0x80)) {
2031+ if (!(OPL->status & OPL->statusmask)) {
2032+ OPL->status &= 0x7f;
2033+ /* callback user interrupt handler (IRQ is ON to OFF) */
2034+ if(OPL->IRQHandler) (OPL->IRQHandler)(OPL->IRQParam,0);
2035+ }
2036+ }
2037+}
2038+
2039+/* IRQ mask set */
2040+inline void OPL_STATUSMASK_SET(FM_OPL *OPL, int flag) {
2041+ OPL->statusmask = flag;
2042+ /* IRQ handling check */
2043+ OPL_STATUS_SET(OPL,0);
2044+ OPL_STATUS_RESET(OPL,0);
2045+}
2046+
2047+/* ----- key on ----- */
2048+inline void OPL_KEYON(OPL_SLOT *SLOT) {
2049+ /* sin wave restart */
2050+ SLOT->Cnt = 0;
2051+ /* set attack */
2052+ SLOT->evm = ENV_MOD_AR;
2053+ SLOT->evs = SLOT->evsa;
2054+ SLOT->evc = EG_AST;
2055+ SLOT->eve = EG_AED;
2056+}
2057+
2058+/* ----- key off ----- */
2059+inline void OPL_KEYOFF(OPL_SLOT *SLOT) {
2060+ if( SLOT->evm > ENV_MOD_RR) {
2061+ /* set envelope counter from envleope output */
2062+
2063+ // WORKAROUND: The Kyra engine does something very strange when
2064+ // starting a new song. For each channel:
2065+ //
2066+ // * The release rate is set to "fastest".
2067+ // * Any note is keyed off.
2068+ // * A very low-frequency note is keyed on.
2069+ //
2070+ // Usually, what happens next is that the real notes is keyed
2071+ // on immediately, in which case there's no problem.
2072+ //
2073+ // However, if the note is again keyed off (because the channel
2074+ // begins on a rest rather than a note), the envelope counter
2075+ // was moved from the very lowest point on the attack curve to
2076+ // the very highest point on the release curve.
2077+ //
2078+ // Again, this might not be a problem, if the release rate is
2079+ // still set to "fastest". But in many cases, it had already
2080+ // been increased. And, possibly because of inaccuracies in the
2081+ // envelope generator, that would cause the note to "fade out"
2082+ // for quite a long time.
2083+ //
2084+ // What we really need is a way to find the correct starting
2085+ // point for the envelope counter, and that may be what the
2086+ // commented-out line below is meant to do. For now, simply
2087+ // handle the pathological case.
2088+
2089+ if (SLOT->evm == ENV_MOD_AR && SLOT->evc == EG_AST)
2090+ SLOT->evc = EG_DED;
2091+ else if( !(SLOT->evc & EG_DST) )
2092+ //SLOT->evc = (ENV_CURVE[SLOT->evc>>ENV_BITS]<<ENV_BITS) + EG_DST;
2093+ SLOT->evc = EG_DST;
2094+ SLOT->eve = EG_DED;
2095+ SLOT->evs = SLOT->evsr;
2096+ SLOT->evm = ENV_MOD_RR;
2097+ }
2098+}
2099+
2100+/* ---------- calcrate Envelope Generator & Phase Generator ---------- */
2101+
2102+/* return : envelope output */
2103+inline uint OPL_CALC_SLOT(OPL_SLOT *SLOT) {
2104+ /* calcrate envelope generator */
2105+ if((SLOT->evc += SLOT->evs) >= SLOT->eve) {
2106+ switch( SLOT->evm ) {
2107+ case ENV_MOD_AR: /* ATTACK -> DECAY1 */
2108+ /* next DR */
2109+ SLOT->evm = ENV_MOD_DR;
2110+ SLOT->evc = EG_DST;
2111+ SLOT->eve = SLOT->SL;
2112+ SLOT->evs = SLOT->evsd;
2113+ break;
2114+ case ENV_MOD_DR: /* DECAY -> SL or RR */
2115+ SLOT->evc = SLOT->SL;
2116+ SLOT->eve = EG_DED;
2117+ if(SLOT->eg_typ) {
2118+ SLOT->evs = 0;
2119+ } else {
2120+ SLOT->evm = ENV_MOD_RR;
2121+ SLOT->evs = SLOT->evsr;
2122+ }
2123+ break;
2124+ case ENV_MOD_RR: /* RR -> OFF */
2125+ SLOT->evc = EG_OFF;
2126+ SLOT->eve = EG_OFF + 1;
2127+ SLOT->evs = 0;
2128+ break;
2129+ }
2130+ }
2131+ /* calcrate envelope */
2132+ return SLOT->TLL + ENV_CURVE[SLOT->evc>>ENV_BITS] + (SLOT->ams ? ams : 0);
2133+}
2134+
2135+/* set algorythm connection */
2136+static void set_algorythm(OPL_CH *CH) {
2137+ int *carrier = &outd[0];
2138+ CH->connect1 = CH->CON ? carrier : &feedback2;
2139+ CH->connect2 = carrier;
2140+}
2141+
2142+/* ---------- frequency counter for operater update ---------- */
2143+inline void CALC_FCSLOT(OPL_CH *CH, OPL_SLOT *SLOT) {
2144+ int ksr;
2145+
2146+ /* frequency step counter */
2147+ SLOT->Incr = CH->fc * SLOT->mul;
2148+ ksr = CH->kcode >> SLOT->KSR;
2149+
2150+ if( SLOT->ksr != ksr ) {
2151+ SLOT->ksr = ksr;
2152+ /* attack , decay rate recalcration */
2153+ SLOT->evsa = SLOT->AR[ksr];
2154+ SLOT->evsd = SLOT->DR[ksr];
2155+ SLOT->evsr = SLOT->RR[ksr];
2156+ }
2157+ SLOT->TLL = SLOT->TL + (CH->ksl_base>>SLOT->ksl);
2158+}
2159+
2160+/* set multi,am,vib,EG-TYP,KSR,mul */
2161+inline void set_mul(FM_OPL *OPL, int slot, int v) {
2162+ OPL_CH *CH = &OPL->P_CH[slot>>1];
2163+ OPL_SLOT *SLOT = &CH->SLOT[slot & 1];
2164+
2165+ SLOT->mul = MUL_TABLE[v & 0x0f];
2166+ SLOT->KSR = (v & 0x10) ? 0 : 2;
2167+ SLOT->eg_typ = (v & 0x20) >> 5;
2168+ SLOT->vib = (v & 0x40);
2169+ SLOT->ams = (v & 0x80);
2170+ CALC_FCSLOT(CH, SLOT);
2171+}
2172+
2173+/* set ksl & tl */
2174+inline void set_ksl_tl(FM_OPL *OPL, int slot, int v) {
2175+ OPL_CH *CH = &OPL->P_CH[slot>>1];
2176+ OPL_SLOT *SLOT = &CH->SLOT[slot & 1];
2177+ int ksl = v >> 6; /* 0 / 1.5 / 3 / 6 db/OCT */
2178+
2179+ SLOT->ksl = ksl ? 3-ksl : 31;
2180+ SLOT->TL = (int)((v & 0x3f) * (0.75 / EG_STEP)); /* 0.75db step */
2181+
2182+ if(!(OPL->mode & 0x80)) { /* not CSM latch total level */
2183+ SLOT->TLL = SLOT->TL + (CH->ksl_base >> SLOT->ksl);
2184+ }
2185+}
2186+
2187+/* set attack rate & decay rate */
2188+inline void set_ar_dr(FM_OPL *OPL, int slot, int v) {
2189+ OPL_CH *CH = &OPL->P_CH[slot>>1];
2190+ OPL_SLOT *SLOT = &CH->SLOT[slot & 1];
2191+ int ar = v >> 4;
2192+ int dr = v & 0x0f;
2193+
2194+ SLOT->AR = ar ? &OPL->AR_TABLE[ar << 2] : RATE_0;
2195+ SLOT->evsa = SLOT->AR[SLOT->ksr];
2196+ if(SLOT->evm == ENV_MOD_AR)
2197+ SLOT->evs = SLOT->evsa;
2198+
2199+ SLOT->DR = dr ? &OPL->DR_TABLE[dr<<2] : RATE_0;
2200+ SLOT->evsd = SLOT->DR[SLOT->ksr];
2201+ if(SLOT->evm == ENV_MOD_DR)
2202+ SLOT->evs = SLOT->evsd;
2203+}
2204+
2205+/* set sustain level & release rate */
2206+inline void set_sl_rr(FM_OPL *OPL, int slot, int v) {
2207+ OPL_CH *CH = &OPL->P_CH[slot>>1];
2208+ OPL_SLOT *SLOT = &CH->SLOT[slot & 1];
2209+ int sl = v >> 4;
2210+ int rr = v & 0x0f;
2211+
2212+ SLOT->SL = SL_TABLE[sl];
2213+ if(SLOT->evm == ENV_MOD_DR)
2214+ SLOT->eve = SLOT->SL;
2215+ SLOT->RR = &OPL->DR_TABLE[rr<<2];
2216+ SLOT->evsr = SLOT->RR[SLOT->ksr];
2217+ if(SLOT->evm == ENV_MOD_RR)
2218+ SLOT->evs = SLOT->evsr;
2219+}
2220+
2221+/* operator output calcrator */
2222+
2223+#define OP_OUT(slot,env,con) slot->wavetable[((slot->Cnt + con)>>(24-SIN_ENT_SHIFT)) & (SIN_ENT-1)][env]
2224+/* ---------- calcrate one of channel ---------- */
2225+inline void OPL_CALC_CH(OPL_CH *CH) {
2226+ uint env_out;
2227+ OPL_SLOT *SLOT;
2228+
2229+ feedback2 = 0;
2230+ /* SLOT 1 */
2231+ SLOT = &CH->SLOT[SLOT1];
2232+ env_out=OPL_CALC_SLOT(SLOT);
2233+ if(env_out < (uint)(EG_ENT - 1)) {
2234+ /* PG */
2235+ if(SLOT->vib)
2236+ SLOT->Cnt += (SLOT->Incr * vib) >> VIB_RATE_SHIFT;
2237+ else
2238+ SLOT->Cnt += SLOT->Incr;
2239+ /* connection */
2240+ if(CH->FB) {
2241+ int feedback1 = (CH->op1_out[0] + CH->op1_out[1]) >> CH->FB;
2242+ CH->op1_out[1] = CH->op1_out[0];
2243+ *CH->connect1 += CH->op1_out[0] = OP_OUT(SLOT, env_out, feedback1);
2244+ } else {
2245+ *CH->connect1 += OP_OUT(SLOT, env_out, 0);
2246+ }
2247+ } else {
2248+ CH->op1_out[1] = CH->op1_out[0];
2249+ CH->op1_out[0] = 0;
2250+ }
2251+ /* SLOT 2 */
2252+ SLOT = &CH->SLOT[SLOT2];
2253+ env_out=OPL_CALC_SLOT(SLOT);
2254+ if(env_out < (uint)(EG_ENT - 1)) {
2255+ /* PG */
2256+ if(SLOT->vib)
2257+ SLOT->Cnt += (SLOT->Incr * vib) >> VIB_RATE_SHIFT;
2258+ else
2259+ SLOT->Cnt += SLOT->Incr;
2260+ /* connection */
2261+ outd[0] += OP_OUT(SLOT, env_out, feedback2);
2262+ }
2263+}
2264+
2265+/* ---------- calcrate rythm block ---------- */
2266+#define WHITE_NOISE_db 6.0
2267+inline void OPL_CALC_RH(FM_OPL *OPL, OPL_CH *CH) {
2268+ uint env_tam, env_sd, env_top, env_hh;
2269+ // This code used to do int(OPL->rnd.getRandomBit() * (WHITE_NOISE_db / EG_STEP)),
2270+ // but EG_STEP = 96.0/EG_ENT, and WHITE_NOISE_db=6.0. So, that's equivalent to
2271+ // int(OPL->rnd.getRandomBit() * EG_ENT/16). We know that EG_ENT is 4096, or 1024,
2272+ // or 128, so we can safely avoid any FP ops.
2273+ int whitenoise = OPL->rnd.getRandomBit() * (EG_ENT>>4);
2274+
2275+ int tone8;
2276+
2277+ OPL_SLOT *SLOT;
2278+ int env_out;
2279+
2280+ /* BD : same as FM serial mode and output level is large */
2281+ feedback2 = 0;
2282+ /* SLOT 1 */
2283+ SLOT = &CH[6].SLOT[SLOT1];
2284+ env_out = OPL_CALC_SLOT(SLOT);
2285+ if(env_out < EG_ENT-1) {
2286+ /* PG */
2287+ if(SLOT->vib)
2288+ SLOT->Cnt += (SLOT->Incr * vib) >> VIB_RATE_SHIFT;
2289+ else
2290+ SLOT->Cnt += SLOT->Incr;
2291+ /* connection */
2292+ if(CH[6].FB) {
2293+ int feedback1 = (CH[6].op1_out[0] + CH[6].op1_out[1]) >> CH[6].FB;
2294+ CH[6].op1_out[1] = CH[6].op1_out[0];
2295+ feedback2 = CH[6].op1_out[0] = OP_OUT(SLOT, env_out, feedback1);
2296+ }
2297+ else {
2298+ feedback2 = OP_OUT(SLOT, env_out, 0);
2299+ }
2300+ } else {
2301+ feedback2 = 0;
2302+ CH[6].op1_out[1] = CH[6].op1_out[0];
2303+ CH[6].op1_out[0] = 0;
2304+ }
2305+ /* SLOT 2 */
2306+ SLOT = &CH[6].SLOT[SLOT2];
2307+ env_out = OPL_CALC_SLOT(SLOT);
2308+ if(env_out < EG_ENT-1) {
2309+ /* PG */
2310+ if(SLOT->vib)
2311+ SLOT->Cnt += (SLOT->Incr * vib) >> VIB_RATE_SHIFT;
2312+ else
2313+ SLOT->Cnt += SLOT->Incr;
2314+ /* connection */
2315+ outd[0] += OP_OUT(SLOT, env_out, feedback2) * 2;
2316+ }
2317+
2318+ // SD (17) = mul14[fnum7] + white noise
2319+ // TAM (15) = mul15[fnum8]
2320+ // TOP (18) = fnum6(mul18[fnum8]+whitenoise)
2321+ // HH (14) = fnum7(mul18[fnum8]+whitenoise) + white noise
2322+ env_sd = OPL_CALC_SLOT(SLOT7_2) + whitenoise;
2323+ env_tam =OPL_CALC_SLOT(SLOT8_1);
2324+ env_top = OPL_CALC_SLOT(SLOT8_2);
2325+ env_hh = OPL_CALC_SLOT(SLOT7_1) + whitenoise;
2326+
2327+ /* PG */
2328+ if(SLOT7_1->vib)
2329+ SLOT7_1->Cnt += (SLOT7_1->Incr * vib) >> (VIB_RATE_SHIFT-1);
2330+ else
2331+ SLOT7_1->Cnt += 2 * SLOT7_1->Incr;
2332+ if(SLOT7_2->vib)
2333+ SLOT7_2->Cnt += (CH[7].fc * vib) >> (VIB_RATE_SHIFT-3);
2334+ else
2335+ SLOT7_2->Cnt += (CH[7].fc * 8);
2336+ if(SLOT8_1->vib)
2337+ SLOT8_1->Cnt += (SLOT8_1->Incr * vib) >> VIB_RATE_SHIFT;
2338+ else
2339+ SLOT8_1->Cnt += SLOT8_1->Incr;
2340+ if(SLOT8_2->vib)
2341+ SLOT8_2->Cnt += ((CH[8].fc * 3) * vib) >> (VIB_RATE_SHIFT-4);
2342+ else
2343+ SLOT8_2->Cnt += (CH[8].fc * 48);
2344+
2345+ tone8 = OP_OUT(SLOT8_2,whitenoise,0 );
2346+
2347+ /* SD */
2348+ if(env_sd < (uint)(EG_ENT - 1))
2349+ outd[0] += OP_OUT(SLOT7_1, env_sd, 0) * 8;
2350+ /* TAM */
2351+ if(env_tam < (uint)(EG_ENT - 1))
2352+ outd[0] += OP_OUT(SLOT8_1, env_tam, 0) * 2;
2353+ /* TOP-CY */
2354+ if(env_top < (uint)(EG_ENT - 1))
2355+ outd[0] += OP_OUT(SLOT7_2, env_top, tone8) * 2;
2356+ /* HH */
2357+ if(env_hh < (uint)(EG_ENT-1))
2358+ outd[0] += OP_OUT(SLOT7_2, env_hh, tone8) * 2;
2359+}
2360+
2361+/* ----------- initialize time tabls ----------- */
2362+static void init_timetables(FM_OPL *OPL, int ARRATE, int DRRATE) {
2363+ int i;
2364+ double rate;
2365+
2366+ /* make attack rate & decay rate tables */
2367+ for (i = 0; i < 4; i++)
2368+ OPL->AR_TABLE[i] = OPL->DR_TABLE[i] = 0;
2369+ for (i = 4; i <= 60; i++) {
2370+ rate = OPL->freqbase; /* frequency rate */
2371+ if(i < 60)
2372+ rate *= 1.0 + (i & 3) * 0.25; /* b0-1 : x1 , x1.25 , x1.5 , x1.75 */
2373+ rate *= 1 << ((i >> 2) - 1); /* b2-5 : shift bit */
2374+ rate *= (double)(EG_ENT << ENV_BITS);
2375+ OPL->AR_TABLE[i] = (int)(rate / ARRATE);
2376+ OPL->DR_TABLE[i] = (int)(rate / DRRATE);
2377+ }
2378+ for (i = 60; i < 76; i++) {
2379+ OPL->AR_TABLE[i] = EG_AED-1;
2380+ OPL->DR_TABLE[i] = OPL->DR_TABLE[60];
2381+ }
2382+}
2383+
2384+/* ---------- generic table initialize ---------- */
2385+static int OPLOpenTable(void) {
2386+ int s,t;
2387+ double rate;
2388+ int i,j;
2389+ double pom;
2390+
2391+#ifdef __DS__
2392+ DS::fastRamReset();
2393+
2394+ TL_TABLE = (int *) DS::fastRamAlloc(TL_MAX * 2 * sizeof(int *));
2395+ SIN_TABLE = (int **) DS::fastRamAlloc(SIN_ENT * 4 * sizeof(int *));
2396+#else
2397+
2398+ /* allocate dynamic tables */
2399+ if((TL_TABLE = (int *)malloc(TL_MAX * 2 * sizeof(int))) == NULL)
2400+ return 0;
2401+
2402+ if((SIN_TABLE = (int **)malloc(SIN_ENT * 4 * sizeof(int *))) == NULL) {
2403+ free(TL_TABLE);
2404+ return 0;
2405+ }
2406+#endif
2407+
2408+ if((AMS_TABLE = (int *)malloc(AMS_ENT * 2 * sizeof(int))) == NULL) {
2409+ free(TL_TABLE);
2410+ free(SIN_TABLE);
2411+ return 0;
2412+ }
2413+
2414+ if((VIB_TABLE = (int *)malloc(VIB_ENT * 2 * sizeof(int))) == NULL) {
2415+ free(TL_TABLE);
2416+ free(SIN_TABLE);
2417+ free(AMS_TABLE);
2418+ return 0;
2419+ }
2420+ /* make total level table */
2421+ for (t = 0; t < EG_ENT - 1 ; t++) {
2422+ rate = ((1 << TL_BITS) - 1) / pow(10.0, EG_STEP * t / 20); /* dB -> voltage */
2423+ TL_TABLE[ t] = (int)rate;
2424+ TL_TABLE[TL_MAX + t] = -TL_TABLE[t];
2425+ }
2426+ /* fill volume off area */
2427+ for (t = EG_ENT - 1; t < TL_MAX; t++) {
2428+ TL_TABLE[t] = TL_TABLE[TL_MAX + t] = 0;
2429+ }
2430+
2431+ /* make sinwave table (total level offet) */
2432+ /* degree 0 = degree 180 = off */
2433+ SIN_TABLE[0] = SIN_TABLE[SIN_ENT /2 ] = &TL_TABLE[EG_ENT - 1];
2434+ for (s = 1;s <= SIN_ENT / 4; s++) {
2435+ pom = sin(2 * PI * s / SIN_ENT); /* sin */
2436+ pom = 20 * log10(1 / pom); /* decibel */
2437+ j = int(pom / EG_STEP); /* TL_TABLE steps */
2438+
2439+ /* degree 0 - 90 , degree 180 - 90 : plus section */
2440+ SIN_TABLE[ s] = SIN_TABLE[SIN_ENT / 2 - s] = &TL_TABLE[j];
2441+ /* degree 180 - 270 , degree 360 - 270 : minus section */
2442+ SIN_TABLE[SIN_ENT / 2 + s] = SIN_TABLE[SIN_ENT - s] = &TL_TABLE[TL_MAX + j];
2443+ }
2444+ for (s = 0;s < SIN_ENT; s++) {
2445+ SIN_TABLE[SIN_ENT * 1 + s] = s < (SIN_ENT / 2) ? SIN_TABLE[s] : &TL_TABLE[EG_ENT];
2446+ SIN_TABLE[SIN_ENT * 2 + s] = SIN_TABLE[s % (SIN_ENT / 2)];
2447+ SIN_TABLE[SIN_ENT * 3 + s] = (s / (SIN_ENT / 4)) & 1 ? &TL_TABLE[EG_ENT] : SIN_TABLE[SIN_ENT * 2 + s];
2448+ }
2449+
2450+
2451+ ENV_CURVE = (int *)malloc(sizeof(int) * (2*EG_ENT+1));
2452+
2453+ /* envelope counter -> envelope output table */
2454+ for (i=0; i < EG_ENT; i++) {
2455+ /* ATTACK curve */
2456+ pom = pow(((double)(EG_ENT - 1 - i) / EG_ENT), 8) * EG_ENT;
2457+ /* if( pom >= EG_ENT ) pom = EG_ENT-1; */
2458+ ENV_CURVE[i] = (int)pom;
2459+ /* DECAY ,RELEASE curve */
2460+ ENV_CURVE[(EG_DST >> ENV_BITS) + i]= i;
2461+ }
2462+ /* off */
2463+ ENV_CURVE[EG_OFF >> ENV_BITS]= EG_ENT - 1;
2464+ /* make LFO ams table */
2465+ for (i=0; i < AMS_ENT; i++) {
2466+ pom = (1.0 + sin(2 * PI * i / AMS_ENT)) / 2; /* sin */
2467+ AMS_TABLE[i] = (int)((1.0 / EG_STEP) * pom); /* 1dB */
2468+ AMS_TABLE[AMS_ENT + i] = (int)((4.8 / EG_STEP) * pom); /* 4.8dB */
2469+ }
2470+ /* make LFO vibrate table */
2471+ for (i=0; i < VIB_ENT; i++) {
2472+ /* 100cent = 1seminote = 6% ?? */
2473+ pom = (double)VIB_RATE * 0.06 * sin(2 * PI * i / VIB_ENT); /* +-100sect step */
2474+ VIB_TABLE[i] = (int)(VIB_RATE + (pom * 0.07)); /* +- 7cent */
2475+ VIB_TABLE[VIB_ENT + i] = (int)(VIB_RATE + (pom * 0.14)); /* +-14cent */
2476+ }
2477+ return 1;
2478+}
2479+
2480+static void OPLCloseTable(void) {
2481+ free(TL_TABLE);
2482+ free(SIN_TABLE);
2483+ free(AMS_TABLE);
2484+ free(VIB_TABLE);
2485+ free(ENV_CURVE);
2486+}
2487+
2488+/* CSM Key Controll */
2489+inline void CSMKeyControll(OPL_CH *CH) {
2490+ OPL_SLOT *slot1 = &CH->SLOT[SLOT1];
2491+ OPL_SLOT *slot2 = &CH->SLOT[SLOT2];
2492+ /* all key off */
2493+ OPL_KEYOFF(slot1);
2494+ OPL_KEYOFF(slot2);
2495+ /* total level latch */
2496+ slot1->TLL = slot1->TL + (CH->ksl_base>>slot1->ksl);
2497+ slot1->TLL = slot1->TL + (CH->ksl_base>>slot1->ksl);
2498+ /* key on */
2499+ CH->op1_out[0] = CH->op1_out[1] = 0;
2500+ OPL_KEYON(slot1);
2501+ OPL_KEYON(slot2);
2502+}
2503+
2504+/* ---------- opl initialize ---------- */
2505+static void OPL_initalize(FM_OPL *OPL) {
2506+ int fn;
2507+
2508+ /* frequency base */
2509+ OPL->freqbase = (OPL->rate) ? ((double)OPL->clock / OPL->rate) / 72 : 0;
2510+ /* Timer base time */
2511+ OPL->TimerBase = 1.0/((double)OPL->clock / 72.0 );
2512+ /* make time tables */
2513+ init_timetables(OPL, OPL_ARRATE, OPL_DRRATE);
2514+ /* make fnumber -> increment counter table */
2515+ for( fn=0; fn < 1024; fn++) {
2516+ OPL->FN_TABLE[fn] = (uint)(OPL->freqbase * fn * FREQ_RATE * (1<<7) / 2);
2517+ }
2518+ /* LFO freq.table */
2519+ OPL->amsIncr = (int)(OPL->rate ? (double)AMS_ENT * (1 << AMS_SHIFT) / OPL->rate * 3.7 * ((double)OPL->clock/3600000) : 0);
2520+ OPL->vibIncr = (int)(OPL->rate ? (double)VIB_ENT * (1 << VIB_SHIFT) / OPL->rate * 6.4 * ((double)OPL->clock/3600000) : 0);
2521+}
2522+
2523+/* ---------- write a OPL registers ---------- */
2524+void OPLWriteReg(FM_OPL *OPL, int r, int v) {
2525+ OPL_CH *CH;
2526+ int slot;
2527+ uint block_fnum;
2528+
2529+ switch(r & 0xe0) {
2530+ case 0x00: /* 00-1f:controll */
2531+ switch(r & 0x1f) {
2532+ case 0x01:
2533+ /* wave selector enable */
2534+ if(OPL->type&OPL_TYPE_WAVESEL) {
2535+ OPL->wavesel = v & 0x20;
2536+ if(!OPL->wavesel) {
2537+ /* preset compatible mode */
2538+ int c;
2539+ for(c=0; c<OPL->max_ch; c++) {
2540+ OPL->P_CH[c].SLOT[SLOT1].wavetable = &SIN_TABLE[0];
2541+ OPL->P_CH[c].SLOT[SLOT2].wavetable = &SIN_TABLE[0];
2542+ }
2543+ }
2544+ }
2545+ return;
2546+ case 0x02: /* Timer 1 */
2547+ OPL->T[0] = (256-v) * 4;
2548+ break;
2549+ case 0x03: /* Timer 2 */
2550+ OPL->T[1] = (256-v) * 16;
2551+ return;
2552+ case 0x04: /* IRQ clear / mask and Timer enable */
2553+ if(v & 0x80) { /* IRQ flag clear */
2554+ OPL_STATUS_RESET(OPL, 0x7f);
2555+ } else { /* set IRQ mask ,timer enable*/
2556+ uint8 st1 = v & 1;
2557+ uint8 st2 = (v >> 1) & 1;
2558+ /* IRQRST,T1MSK,t2MSK,EOSMSK,BRMSK,x,ST2,ST1 */
2559+ OPL_STATUS_RESET(OPL, v & 0x78);
2560+ OPL_STATUSMASK_SET(OPL,((~v) & 0x78) | 0x01);
2561+ /* timer 2 */
2562+ if(OPL->st[1] != st2) {
2563+ double interval = st2 ? (double)OPL->T[1] * OPL->TimerBase : 0.0;
2564+ OPL->st[1] = st2;
2565+ if (OPL->TimerHandler) (OPL->TimerHandler)(OPL->TimerParam + 1, interval);
2566+ }
2567+ /* timer 1 */
2568+ if(OPL->st[0] != st1) {
2569+ double interval = st1 ? (double)OPL->T[0] * OPL->TimerBase : 0.0;
2570+ OPL->st[0] = st1;
2571+ if (OPL->TimerHandler) (OPL->TimerHandler)(OPL->TimerParam + 0, interval);
2572+ }
2573+ }
2574+ return;
2575+ }
2576+ break;
2577+ case 0x20: /* am,vib,ksr,eg type,mul */
2578+ slot = slot_array[r&0x1f];
2579+ if(slot == -1)
2580+ return;
2581+ set_mul(OPL,slot,v);
2582+ return;
2583+ case 0x40:
2584+ slot = slot_array[r&0x1f];
2585+ if(slot == -1)
2586+ return;
2587+ set_ksl_tl(OPL,slot,v);
2588+ return;
2589+ case 0x60:
2590+ slot = slot_array[r&0x1f];
2591+ if(slot == -1)
2592+ return;
2593+ set_ar_dr(OPL,slot,v);
2594+ return;
2595+ case 0x80:
2596+ slot = slot_array[r&0x1f];
2597+ if(slot == -1)
2598+ return;
2599+ set_sl_rr(OPL,slot,v);
2600+ return;
2601+ case 0xa0:
2602+ switch(r) {
2603+ case 0xbd:
2604+ /* amsep,vibdep,r,bd,sd,tom,tc,hh */
2605+ {
2606+ uint8 rkey = OPL->rythm ^ v;
2607+ OPL->ams_table = &AMS_TABLE[v & 0x80 ? AMS_ENT : 0];
2608+ OPL->vib_table = &VIB_TABLE[v & 0x40 ? VIB_ENT : 0];
2609+ OPL->rythm = v & 0x3f;
2610+ if(OPL->rythm & 0x20) {
2611+ /* BD key on/off */
2612+ if(rkey & 0x10) {
2613+ if(v & 0x10) {
2614+ OPL->P_CH[6].op1_out[0] = OPL->P_CH[6].op1_out[1] = 0;
2615+ OPL_KEYON(&OPL->P_CH[6].SLOT[SLOT1]);
2616+ OPL_KEYON(&OPL->P_CH[6].SLOT[SLOT2]);
2617+ } else {
2618+ OPL_KEYOFF(&OPL->P_CH[6].SLOT[SLOT1]);
2619+ OPL_KEYOFF(&OPL->P_CH[6].SLOT[SLOT2]);
2620+ }
2621+ }
2622+ /* SD key on/off */
2623+ if(rkey & 0x08) {
2624+ if(v & 0x08)
2625+ OPL_KEYON(&OPL->P_CH[7].SLOT[SLOT2]);
2626+ else
2627+ OPL_KEYOFF(&OPL->P_CH[7].SLOT[SLOT2]);
2628+ }/* TAM key on/off */
2629+ if(rkey & 0x04) {
2630+ if(v & 0x04)
2631+ OPL_KEYON(&OPL->P_CH[8].SLOT[SLOT1]);
2632+ else
2633+ OPL_KEYOFF(&OPL->P_CH[8].SLOT[SLOT1]);
2634+ }
2635+ /* TOP-CY key on/off */
2636+ if(rkey & 0x02) {
2637+ if(v & 0x02)
2638+ OPL_KEYON(&OPL->P_CH[8].SLOT[SLOT2]);
2639+ else
2640+ OPL_KEYOFF(&OPL->P_CH[8].SLOT[SLOT2]);
2641+ }
2642+ /* HH key on/off */
2643+ if(rkey & 0x01) {
2644+ if(v & 0x01)
2645+ OPL_KEYON(&OPL->P_CH[7].SLOT[SLOT1]);
2646+ else
2647+ OPL_KEYOFF(&OPL->P_CH[7].SLOT[SLOT1]);
2648+ }
2649+ }
2650+ }
2651+ return;
2652+
2653+ default:
2654+ break;
2655+ }
2656+ /* keyon,block,fnum */
2657+ if((r & 0x0f) > 8)
2658+ return;
2659+ CH = &OPL->P_CH[r & 0x0f];
2660+ if(!(r&0x10)) { /* a0-a8 */
2661+ block_fnum = (CH->block_fnum & 0x1f00) | v;
2662+ } else { /* b0-b8 */
2663+ int keyon = (v >> 5) & 1;
2664+ block_fnum = ((v & 0x1f) << 8) | (CH->block_fnum & 0xff);
2665+ if(CH->keyon != keyon) {
2666+ if((CH->keyon=keyon)) {
2667+ CH->op1_out[0] = CH->op1_out[1] = 0;
2668+ OPL_KEYON(&CH->SLOT[SLOT1]);
2669+ OPL_KEYON(&CH->SLOT[SLOT2]);
2670+ } else {
2671+ OPL_KEYOFF(&CH->SLOT[SLOT1]);
2672+ OPL_KEYOFF(&CH->SLOT[SLOT2]);
2673+ }
2674+ }
2675+ }
2676+ /* update */
2677+ if(CH->block_fnum != block_fnum) {
2678+ int blockRv = 7 - (block_fnum >> 10);
2679+ int fnum = block_fnum & 0x3ff;
2680+ CH->block_fnum = block_fnum;
2681+ CH->ksl_base = KSL_TABLE[block_fnum >> 6];
2682+ CH->fc = OPL->FN_TABLE[fnum] >> blockRv;
2683+ CH->kcode = CH->block_fnum >> 9;
2684+ if((OPL->mode & 0x40) && CH->block_fnum & 0x100)
2685+ CH->kcode |=1;
2686+ CALC_FCSLOT(CH,&CH->SLOT[SLOT1]);
2687+ CALC_FCSLOT(CH,&CH->SLOT[SLOT2]);
2688+ }
2689+ return;
2690+ case 0xc0:
2691+ /* FB,C */
2692+ if((r & 0x0f) > 8)
2693+ return;
2694+ CH = &OPL->P_CH[r&0x0f];
2695+ {
2696+ int feedback = (v >> 1) & 7;
2697+ CH->FB = feedback ? (8 + 1) - feedback : 0;
2698+ CH->CON = v & 1;
2699+ set_algorythm(CH);
2700+ }
2701+ return;
2702+ case 0xe0: /* wave type */
2703+ slot = slot_array[r & 0x1f];
2704+ if(slot == -1)
2705+ return;
2706+ CH = &OPL->P_CH[slot>>1];
2707+ if(OPL->wavesel) {
2708+ CH->SLOT[slot&1].wavetable = &SIN_TABLE[(v & 0x03) * SIN_ENT];
2709+ }
2710+ return;
2711+ }
2712+}
2713+
2714+/* lock/unlock for common table */
2715+static int OPL_LockTable(void) {
2716+ num_lock++;
2717+ if(num_lock>1)
2718+ return 0;
2719+ /* first time */
2720+ cur_chip = NULL;
2721+ /* allocate total level table (128kb space) */
2722+ if(!OPLOpenTable()) {
2723+ num_lock--;
2724+ return -1;
2725+ }
2726+ return 0;
2727+}
2728+
2729+static void OPL_UnLockTable(void) {
2730+ if(num_lock)
2731+ num_lock--;
2732+ if(num_lock)
2733+ return;
2734+ /* last time */
2735+ cur_chip = NULL;
2736+ OPLCloseTable();
2737+}
2738+
2739+/*******************************************************************************/
2740+/* YM3812 local section */
2741+/*******************************************************************************/
2742+
2743+/* ---------- update one of chip ----------- */
2744+void YM3812UpdateOne(FM_OPL *OPL, int16 *buffer, int length, int interleave) {
2745+ int i;
2746+ int data;
2747+ int16 *buf = buffer;
2748+ uint amsCnt = OPL->amsCnt;
2749+ uint vibCnt = OPL->vibCnt;
2750+ uint8 rythm = OPL->rythm & 0x20;
2751+ OPL_CH *CH, *R_CH;
2752+
2753+
2754+ if((void *)OPL != cur_chip) {
2755+ cur_chip = (void *)OPL;
2756+ /* channel pointers */
2757+ S_CH = OPL->P_CH;
2758+ E_CH = &S_CH[9];
2759+ /* rythm slot */
2760+ SLOT7_1 = &S_CH[7].SLOT[SLOT1];
2761+ SLOT7_2 = &S_CH[7].SLOT[SLOT2];
2762+ SLOT8_1 = &S_CH[8].SLOT[SLOT1];
2763+ SLOT8_2 = &S_CH[8].SLOT[SLOT2];
2764+ /* LFO state */
2765+ amsIncr = OPL->amsIncr;
2766+ vibIncr = OPL->vibIncr;
2767+ ams_table = OPL->ams_table;
2768+ vib_table = OPL->vib_table;
2769+ }
2770+ R_CH = rythm ? &S_CH[6] : E_CH;
2771+ for(i = 0; i < length; i++) {
2772+ /* channel A channel B channel C */
2773+ /* LFO */
2774+ ams = ams_table[(amsCnt += amsIncr) >> AMS_SHIFT];
2775+ vib = vib_table[(vibCnt += vibIncr) >> VIB_SHIFT];
2776+ outd[0] = 0;
2777+ /* FM part */
2778+ for(CH=S_CH; CH < R_CH; CH++)
2779+ OPL_CALC_CH(CH);
2780+ /* Rythn part */
2781+ if(rythm)
2782+ OPL_CALC_RH(OPL, S_CH);
2783+ /* limit check */
2784+ data = CLIP(outd[0], OPL_MINOUT, OPL_MAXOUT);
2785+ /* store to sound buffer */
2786+ buf[i << interleave] = data >> OPL_OUTSB;
2787+ }
2788+
2789+ OPL->amsCnt = amsCnt;
2790+ OPL->vibCnt = vibCnt;
2791+}
2792+
2793+/* ---------- reset a chip ---------- */
2794+void OPLResetChip(FM_OPL *OPL) {
2795+ int c,s;
2796+ int i;
2797+
2798+ /* reset chip */
2799+ OPL->mode = 0; /* normal mode */
2800+ OPL_STATUS_RESET(OPL, 0x7f);
2801+ /* reset with register write */
2802+ OPLWriteReg(OPL, 0x01,0); /* wabesel disable */
2803+ OPLWriteReg(OPL, 0x02,0); /* Timer1 */
2804+ OPLWriteReg(OPL, 0x03,0); /* Timer2 */
2805+ OPLWriteReg(OPL, 0x04,0); /* IRQ mask clear */
2806+ for(i = 0xff; i >= 0x20; i--)
2807+ OPLWriteReg(OPL,i,0);
2808+ /* reset OPerator parameter */
2809+ for(c = 0; c < OPL->max_ch ;c++ ) {
2810+ OPL_CH *CH = &OPL->P_CH[c];
2811+ /* OPL->P_CH[c].PAN = OPN_CENTER; */
2812+ for(s = 0; s < 2; s++ ) {
2813+ /* wave table */
2814+ CH->SLOT[s].wavetable = &SIN_TABLE[0];
2815+ /* CH->SLOT[s].evm = ENV_MOD_RR; */
2816+ CH->SLOT[s].evc = EG_OFF;
2817+ CH->SLOT[s].eve = EG_OFF + 1;
2818+ CH->SLOT[s].evs = 0;
2819+ }
2820+ }
2821+}
2822+
2823+/* ---------- Create a virtual YM3812 ---------- */
2824+/* 'rate' is sampling rate and 'bufsiz' is the size of the */
2825+FM_OPL *OPLCreate(int type, int clock, int rate) {
2826+ char *ptr;
2827+ FM_OPL *OPL;
2828+ int state_size;
2829+ int max_ch = 9; /* normaly 9 channels */
2830+
2831+ if( OPL_LockTable() == -1)
2832+ return NULL;
2833+ /* allocate OPL state space */
2834+ state_size = sizeof(FM_OPL);
2835+ state_size += sizeof(OPL_CH) * max_ch;
2836+
2837+ /* allocate memory block */
2838+ ptr = (char *)calloc(state_size, 1);
2839+ if(ptr == NULL)
2840+ return NULL;
2841+
2842+ /* clear */
2843+ memset(ptr, 0, state_size);
2844+ OPL = (FM_OPL *)ptr; ptr += sizeof(FM_OPL);
2845+ OPL->P_CH = (OPL_CH *)ptr; ptr += sizeof(OPL_CH) * max_ch;
2846+
2847+ /* set channel state pointer */
2848+ OPL->type = type;
2849+ OPL->clock = clock;
2850+ OPL->rate = rate;
2851+ OPL->max_ch = max_ch;
2852+
2853+ /* init grobal tables */
2854+ OPL_initalize(OPL);
2855+
2856+ /* reset chip */
2857+ OPLResetChip(OPL);
2858+ return OPL;
2859+}
2860+
2861+/* ---------- Destroy one of vietual YM3812 ---------- */
2862+void OPLDestroy(FM_OPL *OPL) {
2863+ OPL_UnLockTable();
2864+ free(OPL);
2865+}
2866+
2867+/* ---------- Option handlers ---------- */
2868+void OPLSetTimerHandler(FM_OPL *OPL, OPL_TIMERHANDLER TimerHandler,int channelOffset) {
2869+ OPL->TimerHandler = TimerHandler;
2870+ OPL->TimerParam = channelOffset;
2871+}
2872+
2873+void OPLSetIRQHandler(FM_OPL *OPL, OPL_IRQHANDLER IRQHandler, int param) {
2874+ OPL->IRQHandler = IRQHandler;
2875+ OPL->IRQParam = param;
2876+}
2877+
2878+void OPLSetUpdateHandler(FM_OPL *OPL, OPL_UPDATEHANDLER UpdateHandler,int param) {
2879+ OPL->UpdateHandler = UpdateHandler;
2880+ OPL->UpdateParam = param;
2881+}
2882+
2883+/* ---------- YM3812 I/O interface ---------- */
2884+int OPLWrite(FM_OPL *OPL,int a,int v) {
2885+ if(!(a & 1)) { /* address port */
2886+ OPL->address = v & 0xff;
2887+ } else { /* data port */
2888+ if(OPL->UpdateHandler)
2889+ OPL->UpdateHandler(OPL->UpdateParam,0);
2890+ OPLWriteReg(OPL, OPL->address,v);
2891+ }
2892+ return OPL->status >> 7;
2893+}
2894+
2895+unsigned char OPLRead(FM_OPL *OPL,int a) {
2896+ if(!(a & 1)) { /* status port */
2897+ return OPL->status & (OPL->statusmask | 0x80);
2898+ }
2899+ /* data port */
2900+ switch(OPL->address) {
2901+ case 0x05: /* KeyBoard IN */
2902+ warning("OPL:read unmapped KEYBOARD port\n");
2903+ return 0;
2904+ case 0x19: /* I/O DATA */
2905+ warning("OPL:read unmapped I/O port\n");
2906+ return 0;
2907+ case 0x1a: /* PCM-DATA */
2908+ return 0;
2909+ default:
2910+ break;
2911+ }
2912+ return 0;
2913+}
2914+
2915+int OPLTimerOver(FM_OPL *OPL, int c) {
2916+ if(c) { /* Timer B */
2917+ OPL_STATUS_SET(OPL, 0x20);
2918+ } else { /* Timer A */
2919+ OPL_STATUS_SET(OPL, 0x40);
2920+ /* CSM mode key,TL controll */
2921+ if(OPL->mode & 0x80) { /* CSM mode total level latch and auto key on */
2922+ int ch;
2923+ if(OPL->UpdateHandler)
2924+ OPL->UpdateHandler(OPL->UpdateParam,0);
2925+ for(ch = 0; ch < 9; ch++)
2926+ CSMKeyControll(&OPL->P_CH[ch]);
2927+ }
2928+ }
2929+ /* reload timer */
2930+ if (OPL->TimerHandler)
2931+ (OPL->TimerHandler)(OPL->TimerParam + c, (double)OPL->T[c] * OPL->TimerBase);
2932+ return OPL->status >> 7;
2933+}
2934+
2935+FM_OPL *makeAdlibOPL(int rate) {
2936+ // We need to emulate one YM3812 chip
2937+ int env_bits = FMOPL_ENV_BITS_HQ;
2938+ int eg_ent = FMOPL_EG_ENT_HQ;
2939+#if defined (_WIN32_WCE) || defined(__SYMBIAN32__) || defined(PALMOS_MODE) || defined(__GP32__) || defined (GP2X) || defined(__MAEMO__) || defined(__DS__) || defined (__MINT__)
2940+ if (ConfMan.hasKey("FM_high_quality") && ConfMan.getBool("FM_high_quality")) {
2941+ env_bits = FMOPL_ENV_BITS_HQ;
2942+ eg_ent = FMOPL_EG_ENT_HQ;
2943+ } else if (ConfMan.hasKey("FM_medium_quality") && ConfMan.getBool("FM_medium_quality")) {
2944+ env_bits = FMOPL_ENV_BITS_MQ;
2945+ eg_ent = FMOPL_EG_ENT_MQ;
2946+ } else {
2947+ env_bits = FMOPL_ENV_BITS_LQ;
2948+ eg_ent = FMOPL_EG_ENT_LQ;
2949+ }
2950+#endif
2951+
2952+ OPLBuildTables(env_bits, eg_ent);
2953+ return OPLCreate(OPL_TYPE_YM3812, 3579545, rate);
2954+}
2955+
2956+} // end of namespace MAME
2957+} // end of namespace AdLib
2958+
2959Index: sound/softsynth/adlib/dbopl.cpp
2960===================================================================
2961--- sound/softsynth/adlib/dbopl.cpp (revision 0)
2962+++ sound/softsynth/adlib/dbopl.cpp (revision 0)
2963@@ -0,0 +1,1468 @@
2964+/*
2965+ * Copyright (C) 2002-2009 The DOSBox Team
2966+ *
2967+ * This program is free software; you can redistribute it and/or modify
2968+ * it under the terms of the GNU General Public License as published by
2969+ * the Free Software Foundation; either version 2 of the License, or
2970+ * (at your option) any later version.
2971+ *
2972+ * This program is distributed in the hope that it will be useful,
2973+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
2974+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
2975+ * GNU General Public License for more details.
2976+ *
2977+ * You should have received a copy of the GNU General Public License
2978+ * along with this program; if not, write to the Free Software
2979+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
2980+ */
2981+
2982+/*
2983+ DOSBox implementation of a combined Yamaha YMF262 and Yamaha YM3812 emulator.
2984+ Enabling the opl3 bit will switch the emulator to stereo opl3 output instead of regular mono opl2
2985+ Except for the table generation it's all integer math
2986+ Can choose different types of generators, using muls and bigger tables, try different ones for slower platforms
2987+ The generation was based on the MAME implementation but tried to have it use less memory and be faster in general
2988+ MAME uses much bigger envelope tables and this will be the biggest cause of it sounding different at times
2989+
2990+ //TODO Don't delay first operator 1 sample in opl3 mode
2991+ //TODO Maybe not use class method pointers but a regular function pointers with operator as first parameter
2992+ //TODO Fix panning for the Percussion channels, would any opl3 player use it and actually really change it though?
2993+ //TODO don't use variables in work structure for tremolo and vibrato but give the variables as parameters to GetSample
2994+ //TODO Since the vibrato takes 1024 samples it's easier to run the emulator in same vibrato chunks, vibrato would be costfree
2995+
2996+ //DUNNO Keyon in 4op, switch to 2op without keyoff.
2997+*/
2998+
2999+#ifndef DISABLE_DOSBOX_ADLIB
3000+
3001+#include "dbopl.h"
3002+#include <stddef.h> // for ptrdiff_t
3003+
3004+#ifndef PI
3005+#define PI 3.14159265358979323846
3006+#endif
3007+
3008+#ifndef INLINE
3009+#define INLINE
3010+#endif
3011+
3012+#define OFFS(type,item) (((ptrdiff_t)(&((type*)42)->type::item))-42)
3013+
3014+namespace AdLib {
3015+namespace DOSBox {
3016+namespace DBOPL {
3017+
3018+#define MAX_SAMPLES 256
3019+#define OPLRATE ((double)(14318180.0 / 288.0))
3020+
3021+//Only need 4 valid bits at the top for vibrato
3022+#define VIBRATO_SH ( 32 - 4 )
3023+//Need 6 bits of accuracy
3024+#define TREMOLO_SH ( 32 - 6 )
3025+#define TREMOLO_TABLE 52
3026+
3027+//Wave bits available in the top of the 32bit range
3028+//Original adlib uses 10.10, we use 12.20
3029+//Have to keep some bits in the top to allow for freqmul 0.5
3030+#define WAVE_BITS 12
3031+#define WAVE_SH ( 32 - WAVE_BITS )
3032+#define WAVE_MASK ( ( 1 << WAVE_SH ) - 1 )
3033+
3034+//Maximum amount of attenuation bits
3035+//Envelope goes to 511, 9 bits
3036+#if (DBOPL_WAVE == WAVE_TABLEMUL )
3037+//Uses the value directly
3038+#define ENV_BITS ( 9 )
3039+#else
3040+//Add 3 bits here for more accuracy and would have to be shifted up either way
3041+#define ENV_BITS ( 9 )
3042+#endif
3043+//Limits of the envelope with those bits and when the envelope goes silent
3044+#define ENV_MIN 0
3045+#define ENV_EXTRA ( ENV_BITS - 9 )
3046+#define ENV_MAX ( 511 << ENV_EXTRA )
3047+#define ENV_LIMIT ( ( 12 * 256) >> ( 3 - ENV_EXTRA ) )
3048+#define ENV_SILENT( _X_ ) ( (_X_) >= ENV_LIMIT )
3049+
3050+//Attack/decay/release rate counter shift
3051+#define RATE_SH 24
3052+#define RATE_MASK ( ( 1 << RATE_SH ) - 1 )
3053+//Has to fit within 16bit lookuptable
3054+#define MUL_SH 16
3055+
3056+//Check some ranges
3057+#if ENV_EXTRA > 3
3058+#error Too many envelope bits
3059+#endif
3060+
3061+
3062+//How much to substract from the base value for the final attenuation
3063+static const Bit8u KslCreateTable[16] = {
3064+ //0 will always be be lower than 7 * 8
3065+ 64, 32, 24, 19,
3066+ 16, 12, 11, 10,
3067+ 8, 6, 5, 4,
3068+ 3, 2, 1, 0,
3069+};
3070+
3071+#define M(_X_) ((Bit8u)( (_X_) * 2))
3072+static const Bit8u FreqCreateTable[16] = {
3073+ M(0.5), M(1 ), M(2 ), M(3 ), M(4 ), M(5 ), M(6 ), M(7 ),
3074+ M(8 ), M(9 ), M(10), M(10), M(12), M(12), M(15), M(15)
3075+};
3076+#undef M
3077+
3078+//We're not including the highest attack rate, that gets a special value
3079+static const Bit8u AttackSamplesTable[13] = {
3080+ 69, 55, 46, 40,
3081+ 35, 29, 23, 20,
3082+ 19, 15, 11, 10,
3083+ 9
3084+};
3085+//On a real opl these values take 8 samples to reach and are based upon larger tables
3086+static const Bit8u EnvelopeIncreaseTable[13] = {
3087+ 4, 5, 6, 7,
3088+ 8, 10, 12, 14,
3089+ 16, 20, 24, 28,
3090+ 32,
3091+};
3092+
3093+#if ( DBOPL_WAVE == WAVE_HANDLER ) || ( DBOPL_WAVE == WAVE_TABLELOG )
3094+static Bit16u ExpTable[ 256 ];
3095+#endif
3096+
3097+#if ( DBOPL_WAVE == WAVE_HANDLER )
3098+//PI table used by WAVEHANDLER
3099+static Bit16u SinTable[ 512 ];
3100+#endif
3101+
3102+#if ( DBOPL_WAVE > WAVE_HANDLER )
3103+//Layout of the waveform table in 512 entry intervals
3104+//With overlapping waves we reduce the table to half it's size
3105+
3106+// | |//\\|____|WAV7|//__|/\ |____|/\/\|
3107+// |\\//| | |WAV7| | \/| | |
3108+// |06 |0126|17 |7 |3 |4 |4 5 |5 |
3109+
3110+//6 is just 0 shifted and masked
3111+
3112+static Bit16s WaveTable[ 8 * 512 ];
3113+//Distance into WaveTable the wave starts
3114+static const Bit16u WaveBaseTable[8] = {
3115+ 0x000, 0x200, 0x200, 0x800,
3116+ 0xa00, 0xc00, 0x100, 0x400,
3117+
3118+};
3119+//Mask the counter with this
3120+static const Bit16u WaveMaskTable[8] = {
3121+ 1023, 1023, 511, 511,
3122+ 1023, 1023, 512, 1023,
3123+};
3124+
3125+//Where to start the counter on at keyon
3126+static const Bit16u WaveStartTable[8] = {
3127+ 512, 0, 0, 0,
3128+ 0, 512, 512, 256,
3129+};
3130+#endif
3131+
3132+#if ( DBOPL_WAVE == WAVE_TABLEMUL )
3133+static Bit16u MulTable[ 384 ];
3134+#endif
3135+
3136+static Bit8u KslTable[ 8 * 16 ];
3137+static Bit8u TremoloTable[ TREMOLO_TABLE ];
3138+//Start of a channel behind the chip struct start
3139+static Bit16u ChanOffsetTable[32];
3140+//Start of an operator behind the chip struct start
3141+static Bit16u OpOffsetTable[64];
3142+
3143+//The lower bits are the shift of the operator vibrato value
3144+//The highest bit is right shifted to generate -1 or 0 for negation
3145+//So taking the highest input value of 7 this gives 3, 7, 3, 0, -3, -7, -3, 0
3146+static const Bit8s VibratoTable[ 8 ] = {
3147+ 1 - 0x00, 0 - 0x00, 1 - 0x00, 30 - 0x00,
3148+ 1 - 0x80, 0 - 0x80, 1 - 0x80, 30 - 0x80
3149+};
3150+
3151+//Shift strength for the ksl value determined by ksl strength
3152+static const Bit8u KslShiftTable[4] = {
3153+ 31,1,2,0
3154+};
3155+
3156+//Generate a table index and table shift value using input value from a selected rate
3157+static void EnvelopeSelect( Bit8u val, Bit8u& index, Bit8u& shift ) {
3158+ if ( val < 13 * 4 ) { //Rate 0 - 12
3159+ shift = 12 - ( val >> 2 );
3160+ index = val & 3;
3161+ } else if ( val < 15 * 4 ) { //rate 13 - 14
3162+ shift = 0;
3163+ index = val - 12 * 4;
3164+ } else { //rate 15 and up
3165+ shift = 0;
3166+ index = 12;
3167+ }
3168+}
3169+
3170+#if ( DBOPL_WAVE == WAVE_HANDLER )
3171+/*
3172+ Generate the different waveforms out of the sine/exponetial table using handlers
3173+*/
3174+static inline Bits MakeVolume( Bitu wave, Bitu volume ) {
3175+ Bitu total = wave + volume;
3176+ Bitu index = total & 0xff;
3177+ Bitu sig = ExpTable[ index ];
3178+ Bitu exp = total >> 8;
3179+#if 0
3180+ //Check if we overflow the 31 shift limit
3181+ if ( exp >= 32 ) {
3182+ LOG_MSG( "WTF %d %d", total, exp );
3183+ }
3184+#endif
3185+ return (sig >> exp);
3186+};
3187+
3188+static Bits DB_FASTCALL WaveForm0( Bitu i, Bitu volume ) {
3189+ Bits neg = 0 - (( i >> 9) & 1);//Create ~0 or 0
3190+ Bitu wave = SinTable[i & 511];
3191+ return (MakeVolume( wave, volume ) ^ neg) - neg;
3192+}
3193+static Bits DB_FASTCALL WaveForm1( Bitu i, Bitu volume ) {
3194+ Bit32u wave = SinTable[i & 511];
3195+ wave |= ( ( (i ^ 512 ) & 512) - 1) >> ( 32 - 12 );
3196+ return MakeVolume( wave, volume );
3197+}
3198+static Bits DB_FASTCALL WaveForm2( Bitu i, Bitu volume ) {
3199+ Bitu wave = SinTable[i & 511];
3200+ return MakeVolume( wave, volume );
3201+}
3202+static Bits DB_FASTCALL WaveForm3( Bitu i, Bitu volume ) {
3203+ Bitu wave = SinTable[i & 255];
3204+ wave |= ( ( (i ^ 256 ) & 256) - 1) >> ( 32 - 12 );
3205+ return MakeVolume( wave, volume );
3206+}
3207+static Bits DB_FASTCALL WaveForm4( Bitu i, Bitu volume ) {
3208+ //Twice as fast
3209+ i <<= 1;
3210+ Bits neg = 0 - (( i >> 9) & 1);//Create ~0 or 0
3211+ Bitu wave = SinTable[i & 511];
3212+ wave |= ( ( (i ^ 512 ) & 512) - 1) >> ( 32 - 12 );
3213+ return (MakeVolume( wave, volume ) ^ neg) - neg;
3214+}
3215+static Bits DB_FASTCALL WaveForm5( Bitu i, Bitu volume ) {
3216+ //Twice as fast
3217+ i <<= 1;
3218+ Bitu wave = SinTable[i & 511];
3219+ wave |= ( ( (i ^ 512 ) & 512) - 1) >> ( 32 - 12 );
3220+ return MakeVolume( wave, volume );
3221+}
3222+static Bits DB_FASTCALL WaveForm6( Bitu i, Bitu volume ) {
3223+ Bits neg = 0 - (( i >> 9) & 1);//Create ~0 or 0
3224+ return (MakeVolume( 0, volume ) ^ neg) - neg;
3225+}
3226+static Bits DB_FASTCALL WaveForm7( Bitu i, Bitu volume ) {
3227+ //Negative is reversed here
3228+ Bits neg = (( i >> 9) & 1) - 1;
3229+ Bitu wave = (i << 3);
3230+ //When negative the volume also runs backwards
3231+ wave = ((wave ^ neg) - neg) & 4095;
3232+ return (MakeVolume( wave, volume ) ^ neg) - neg;
3233+}
3234+
3235+static const WaveHandler WaveHandlerTable[8] = {
3236+ WaveForm0, WaveForm1, WaveForm2, WaveForm3,
3237+ WaveForm4, WaveForm5, WaveForm6, WaveForm7
3238+};
3239+
3240+#endif
3241+
3242+//Structto hold the data everything well yeh works with
3243+static struct {
3244+ Bitu samples;
3245+ Bits vibrato;
3246+ Bits tremolo;
3247+ inline void SetVibrato( Bit8s vib ) {
3248+ vibrato = vib;
3249+ vibrato &= ~0x80;
3250+ }
3251+ Bit32s output[MAX_SAMPLES * 2];
3252+ //Could intermix the vib/trem table for slightly better cache hits
3253+ Bit8s vibTable[MAX_SAMPLES];
3254+ Bit8s tremTable[MAX_SAMPLES];
3255+} Work;
3256+
3257+/*
3258+ Operator
3259+*/
3260+
3261+//We zero out when rate == 0
3262+inline void Operator::UpdateAttack( const Chip* chip ) {
3263+ Bit8u rate = reg60 >> 4;
3264+ if ( rate ) {
3265+ Bit8u val = (rate << 2) + ksr;
3266+ attackAdd = chip->attackRates[ val ];
3267+ rateZero &= ~(1 << ATTACK);
3268+ } else {
3269+ attackAdd = 0;
3270+ rateZero |= (1 << ATTACK);
3271+ }
3272+}
3273+inline void Operator::UpdateDecay( const Chip* chip ) {
3274+ Bit8u rate = reg60 & 0xf;
3275+ if ( rate ) {
3276+ Bit8u val = (rate << 2) + ksr;
3277+ decayAdd = chip->linearRates[ val ];
3278+ rateZero &= ~(1 << DECAY);
3279+ } else {
3280+ decayAdd = 0;
3281+ rateZero |= (1 << DECAY);
3282+ }
3283+}
3284+inline void Operator::UpdateRelease( const Chip* chip ) {
3285+ Bit8u rate = reg80 & 0xf;
3286+ if ( rate ) {
3287+ Bit8u val = (rate << 2) + ksr;
3288+ releaseAdd = chip->linearRates[ val ];
3289+ rateZero &= ~(1 << RELEASE);
3290+ if ( !(reg20 & MASK_SUSTAIN ) ) {
3291+ rateZero &= ~( 1 << SUSTAIN );
3292+ }
3293+ } else {
3294+ rateZero |= (1 << RELEASE);
3295+ releaseAdd = 0;
3296+ if ( !(reg20 & MASK_SUSTAIN ) ) {
3297+ rateZero |= ( 1 << SUSTAIN );
3298+ }
3299+ }
3300+}
3301+
3302+inline void Operator::UpdateAttenuation( ) {
3303+ Bit8u kslBase = (chanData >> SHIFT_KSLBASE) & 0xff;
3304+ Bit32u tl = reg40 & 0x3f;
3305+ Bit8u kslShift = KslShiftTable[ reg40 >> 6 ];
3306+ //Make sure the attenuation goes to the right bits
3307+ totalLevel = tl << ( ENV_BITS - 7 ); //Total level goes 2 bits below max
3308+ totalLevel += ( kslBase << ENV_EXTRA ) >> kslShift;
3309+}
3310+
3311+void Operator::UpdateFrequency( ) {
3312+ Bit32u freq = chanData & (( 1 << 10 ) - 1);
3313+ Bit32u block = (chanData >> 10) & 0xff;
3314+
3315+ waveAdd = (freq << block) * freqMul;
3316+ if ( reg20 & MASK_VIBRATO ) {
3317+ vibStrength = (Bit8u)(freq >> 7);
3318+ vibrato = ( vibStrength << block ) * freqMul;
3319+ } else {
3320+ vibStrength = 0;
3321+ vibrato = 0;
3322+ }
3323+}
3324+
3325+void Operator::UpdateRates( const Chip* chip ) {
3326+ //Mame seems to reverse this where enabling ksr actually lowers
3327+ //the rate, but pdf manuals says otherwise?
3328+ Bit8u newKsr = (chanData >> SHIFT_KEYCODE) & 0xff;
3329+ if ( !( reg20 & MASK_KSR ) ) {
3330+ newKsr >>= 2;
3331+ }
3332+ if ( ksr == newKsr )
3333+ return;
3334+ ksr = newKsr;
3335+ UpdateAttack( chip );
3336+ UpdateDecay( chip );
3337+ UpdateRelease( chip );
3338+}
3339+
3340+INLINE Bit32s Operator::RateForward( Bit32u add ) {
3341+ rateIndex += add;
3342+ Bit32s ret = rateIndex >> RATE_SH;
3343+ rateIndex = rateIndex & RATE_MASK;
3344+ return ret;
3345+}
3346+
3347+template< Operator::State yes>
3348+Bits Operator::TemplateVolume( ) {
3349+ Bit32s vol = activeLevel;
3350+ Bit32s change;
3351+ switch ( yes ) {
3352+ case OFF:
3353+ return ENV_MAX;
3354+ case ATTACK:
3355+ change = RateForward( attackAdd );
3356+ if ( !change )
3357+ return vol;
3358+ vol += ( (~vol) * change ) >> 3;
3359+ if ( vol < ENV_MIN ) {
3360+ activeLevel = ENV_MIN;
3361+ rateIndex = 0;
3362+ SetState( DECAY );
3363+ return ENV_MIN;
3364+ }
3365+ break;
3366+ case DECAY:
3367+ vol += RateForward( decayAdd );
3368+ if ( vol >= sustainLevel ) {
3369+ //Check if we didn't overshoot max attenuation, then just go off
3370+ if ( vol >= ENV_MAX ) {
3371+ activeLevel = ENV_MAX;
3372+ SetState( OFF );
3373+ return ENV_MAX;
3374+ }
3375+ //Continue as sustain
3376+ rateIndex = 0;
3377+ SetState( SUSTAIN );
3378+ }
3379+ break;
3380+ case SUSTAIN:
3381+ if ( reg20 & MASK_SUSTAIN ) {
3382+ return vol;
3383+ }
3384+ //In sustain phase, but not sustaining, do regular release
3385+ case RELEASE:
3386+ vol += RateForward( releaseAdd );;
3387+ if ( vol >= ENV_MAX ) {
3388+ activeLevel = ENV_MAX;
3389+ SetState( OFF );
3390+ return ENV_MAX;
3391+ }
3392+ break;
3393+ }
3394+ activeLevel = vol;
3395+ return vol;
3396+}
3397+
3398+static const VolumeHandler VolumeHandlerTable[5] = {
3399+ &Operator::TemplateVolume< Operator::OFF >,
3400+ &Operator::TemplateVolume< Operator::RELEASE >,
3401+ &Operator::TemplateVolume< Operator::SUSTAIN >,
3402+ &Operator::TemplateVolume< Operator::DECAY >,
3403+ &Operator::TemplateVolume< Operator::ATTACK >
3404+};
3405+
3406+INLINE Bitu Operator::ForwardVolume() {
3407+ return totalLevel + (this->*volHandler)()
3408+#if defined ( DBOPL_TREMOLO )
3409+ + (Work.tremolo & tremoloMask)
3410+#endif
3411+ ;
3412+}
3413+
3414+
3415+INLINE Bitu Operator::ForwardWave() {
3416+#if defined ( DBOPL_VIBRATO )
3417+ if ( vibStrength >> (Bit8u)(Work.vibrato) ) {
3418+ Bit32s add = vibrato >> (Bit8u)(Work.vibrato);
3419+ //Sign extend over the shift value
3420+ Bit32s neg = Work.vibrato >> 16;
3421+ //Negate the add with -1 or 0
3422+ add = ( add ^ neg ) - neg;
3423+ waveIndex += add + waveAdd;
3424+ return waveIndex >> WAVE_SH;
3425+ }
3426+#endif
3427+ waveIndex += waveAdd;
3428+ return waveIndex >> WAVE_SH;
3429+}
3430+
3431+
3432+void Operator::Write20( const Chip* chip, Bit8u val ) {
3433+ Bit8u change = (reg20 ^ val );
3434+ if ( !change )
3435+ return;
3436+ reg20 = val;
3437+ //Shift the tremolo bit over the entire register, saved a branch, YES!
3438+ tremoloMask = (Bit8s)(val) >> 7;
3439+ tremoloMask &= ~(( 1 << ENV_EXTRA ) -1);
3440+ //Update specific features based on changes
3441+ if ( change & MASK_KSR ) {
3442+ UpdateRates( chip );
3443+ }
3444+ //With sustain enable the volume doesn't change
3445+ if ( reg20 & MASK_SUSTAIN || ( !releaseAdd ) ) {
3446+ rateZero |= ( 1 << SUSTAIN );
3447+ } else {
3448+ rateZero &= ~( 1 << SUSTAIN );
3449+ }
3450+ //Frequency multiplier or vibrato changed
3451+ if ( change & (0xf | MASK_VIBRATO) ) {
3452+ freqMul = chip->freqMul[ val & 0xf ];
3453+ UpdateFrequency();
3454+ }
3455+}
3456+
3457+void Operator::Write40( const Chip* chip, Bit8u val ) {
3458+ if (!(reg40 ^ val ))
3459+ return;
3460+ reg40 = val;
3461+ UpdateAttenuation( );
3462+}
3463+
3464+void Operator::Write60( const Chip* chip, Bit8u val ) {
3465+ Bit8u change = reg60 ^ val;
3466+ reg60 = val;
3467+ if ( change & 0x0f ) {
3468+ UpdateDecay( chip );
3469+ }
3470+ if ( change & 0xf0 ) {
3471+ UpdateAttack( chip );
3472+ }
3473+}
3474+
3475+void Operator::Write80( const Chip* chip, Bit8u val ) {
3476+ Bit8u change = (reg80 ^ val );
3477+ if ( !change )
3478+ return;
3479+ reg80 = val;
3480+ Bit8u sustain = val >> 4;
3481+ //Turn 0xf into 0x1f
3482+ sustain |= ( sustain + 1) & 0x10;
3483+ sustainLevel = sustain << ( ENV_BITS - 5 );
3484+ if ( change & 0x0f ) {
3485+ UpdateRelease( chip );
3486+ }
3487+}
3488+
3489+void Operator::WriteE0( const Chip* chip, Bit8u val ) {
3490+ if ( !(regE0 ^ val) )
3491+ return;
3492+ //in opl3 mode you can always selet 7 waveforms regardless of waveformselect
3493+ Bit8u waveForm = val & ( ( 0x3 & chip->waveFormMask ) | (0x7 & chip->opl3Active ) );
3494+ regE0 = val;
3495+#if ( DBOPL_WAVE == WAVE_HANDLER )
3496+ waveHandler = WaveHandlerTable[ waveForm ];
3497+#else
3498+ waveBase = WaveTable + WaveBaseTable[ waveForm ];
3499+ waveStart = WaveStartTable[ waveForm ] << WAVE_SH;
3500+ waveMask = WaveMaskTable[ waveForm ];
3501+#endif
3502+}
3503+
3504+INLINE void Operator::SetState( Bit8u s ) {
3505+ state = s;
3506+ volHandler = VolumeHandlerTable[ s ];
3507+}
3508+
3509+INLINE bool Operator::Silent() const {
3510+ if ( !ENV_SILENT( totalLevel + activeLevel ) )
3511+ return false;
3512+ if ( !(rateZero & ( 1 << state ) ) )
3513+ return false;
3514+ return true;
3515+}
3516+
3517+void Operator::KeyOn( Bit8u mask ) {
3518+ if ( !keyOn ) {
3519+ //Restart the frequency generator
3520+#if ( DBOPL_WAVE > WAVE_HANDLER )
3521+ waveIndex = waveStart;
3522+#else
3523+ waveIndex = 0;
3524+#endif
3525+ rateIndex = 0;
3526+ SetState( ATTACK );
3527+ }
3528+ keyOn |= mask;
3529+}
3530+
3531+void Operator::KeyOff( Bit8u mask ) {
3532+ keyOn &= ~mask;
3533+ if ( !keyOn ) {
3534+ if ( state != OFF ) {
3535+ SetState( RELEASE );
3536+ }
3537+ }
3538+}
3539+
3540+INLINE Bits Operator::GetWave( Bitu index, Bitu vol ) {
3541+#if ( DBOPL_WAVE == WAVE_HANDLER )
3542+ return waveHandler( index, vol << ( 3 - ENV_EXTRA ) );
3543+#elif ( DBOPL_WAVE == WAVE_TABLEMUL )
3544+ return (waveBase[ index & waveMask ] * MulTable[ vol >> ENV_EXTRA ]) >> MUL_SH;
3545+#elif ( DBOPL_WAVE == WAVE_TABLELOG )
3546+ Bit32s wave = waveBase[ index & waveMask ];
3547+ Bit32u total = ( wave & 0x7fff ) + vol << ( 3 - ENV_EXTRA );
3548+ Bit32s sig = ExpTable[ total & 0xff ];
3549+ Bit32u exp = total >> 8;
3550+ Bit32s neg = wave >> 16;
3551+ return ((sig ^ neg) - neg) >> exp;
3552+#else
3553+#error "No valid wave routine"
3554+#endif
3555+}
3556+
3557+Bits INLINE Operator::GetSample( Bits modulation ) {
3558+ Bitu vol = ForwardVolume();
3559+ if ( ENV_SILENT( vol ) ) {
3560+ //Simply forward the wave
3561+ waveIndex += waveAdd;
3562+ return 0;
3563+ } else {
3564+ Bitu index = ForwardWave();
3565+ index += modulation;
3566+ return GetWave( index, vol );
3567+ }
3568+}
3569+
3570+Operator::Operator() {
3571+ chanData = 0;
3572+ freqMul = 0;
3573+ waveIndex = 0;
3574+ waveAdd = 0;
3575+ keyOn = 0;
3576+ ksr = 0;
3577+ reg20 = 0;
3578+ reg40 = 0;
3579+ reg60 = 0;
3580+ reg80 = 0;
3581+ regE0 = 0;
3582+ SetState( OFF );
3583+ rateZero = (1 << OFF);
3584+ sustainLevel = ENV_MAX;
3585+ activeLevel = ENV_MAX;
3586+ totalLevel = ENV_MAX;
3587+}
3588+
3589+/*
3590+ Channel
3591+*/
3592+
3593+Channel::Channel() {
3594+ old[0] = old[1] = 0;
3595+ chanData = 0;
3596+ regB0 = 0;
3597+ regC0 = 0;
3598+ maskLeft = -1;
3599+ maskRight = -1;
3600+ feedback = 31;
3601+ fourMask = 0;
3602+ synthHandler = &Channel::BlockTemplate< sm2FM >;
3603+}
3604+
3605+void Channel::SetChanData( const Chip* chip, Bit32u data ) {
3606+ Bit32u change = chanData ^ data;
3607+ chanData = data;
3608+ Op( 0 )->chanData = data;
3609+ Op( 1 )->chanData = data;
3610+ //Since a frequency update triggered this, always update frequency
3611+ Op( 0 )->UpdateFrequency();
3612+ Op( 1 )->UpdateFrequency();
3613+ if ( change & ( 0xff << SHIFT_KSLBASE ) ) {
3614+ Op( 0 )->UpdateAttenuation();
3615+ Op( 1 )->UpdateAttenuation();
3616+ }
3617+ if ( change & ( 0xff << SHIFT_KEYCODE ) ) {
3618+ Op( 0 )->UpdateRates( chip );
3619+ Op( 1 )->UpdateRates( chip );
3620+ }
3621+}
3622+
3623+void Channel::UpdateFrequency( const Chip* chip, Bit8u fourOp ) {
3624+ //Extrace the frequency bits
3625+ Bit32u data = chanData & 0xffff;
3626+ Bit32u kslBase = KslTable[ data >> 6 ];
3627+ Bit32u keyCode = ( data & 0x1c00) >> 9;
3628+ if ( chip->reg08 & 0x40 ) {
3629+ keyCode |= ( data & 0x100)>>8; /* notesel == 1 */
3630+ } else {
3631+ keyCode |= ( data & 0x200)>>9; /* notesel == 0 */
3632+ }
3633+ //Add the keycode and ksl into the highest bits of chanData
3634+ data |= (keyCode << SHIFT_KEYCODE) | ( kslBase << SHIFT_KSLBASE );
3635+ ( this + 0 )->SetChanData( chip, data );
3636+ if ( fourOp & 0x3f ) {
3637+ ( this + 1 )->SetChanData( chip, data );
3638+ }
3639+}
3640+
3641+void Channel::WriteA0( const Chip* chip, Bit8u val ) {
3642+ Bit8u fourOp = chip->reg104 & chip->opl3Active & fourMask;
3643+ //Don't handle writes to silent fourop channels
3644+ if ( fourOp > 0x80 )
3645+ return;
3646+ Bit32u change = (chanData ^ val ) & 0xff;
3647+ if ( change ) {
3648+ chanData ^= change;
3649+ UpdateFrequency( chip, fourOp );
3650+ }
3651+}
3652+
3653+void Channel::WriteB0( const Chip* chip, Bit8u val ) {
3654+ Bit8u fourOp = chip->reg104 & chip->opl3Active & fourMask;
3655+ //Don't handle writes to silent fourop channels
3656+ if ( fourOp > 0x80 )
3657+ return;
3658+ Bitu change = (chanData ^ ( val << 8 ) ) & 0x1f00;
3659+ if ( change ) {
3660+ chanData ^= change;
3661+ UpdateFrequency( chip, fourOp );
3662+ }
3663+ //Check for a change in the keyon/off state
3664+ if ( !(( val ^ regB0) & 0x20))
3665+ return;
3666+ regB0 = val;
3667+ if ( val & 0x20 ) {
3668+ Op(0)->KeyOn( 0x1 );
3669+ Op(1)->KeyOn( 0x1 );
3670+ if ( fourOp & 0x3f ) {
3671+ ( this + 1 )->Op(0)->KeyOn( 1 );
3672+ ( this + 1 )->Op(1)->KeyOn( 1 );
3673+ }
3674+ } else {
3675+ Op(0)->KeyOff( 0x1 );
3676+ Op(1)->KeyOff( 0x1 );
3677+ if ( fourOp & 0x3f ) {
3678+ ( this + 1 )->Op(0)->KeyOff( 1 );
3679+ ( this + 1 )->Op(1)->KeyOff( 1 );
3680+ }
3681+ }
3682+}
3683+
3684+void Channel::WriteC0( const Chip* chip, Bit8u val ) {
3685+ Bit8u change = val ^ regC0;
3686+ if ( !change )
3687+ return;
3688+ regC0 = val;
3689+ feedback = ( val >> 1 ) & 7;
3690+ if ( feedback ) {
3691+ //We shift the input to the right 10 bit wave index value
3692+ feedback = 9 - feedback;
3693+ } else {
3694+ feedback = 31;
3695+ }
3696+ //Select the new synth mode
3697+ if ( chip->opl3Active ) {
3698+ //4-op mode enabled for this channel
3699+ if ( (chip->reg104 & fourMask) & 0x3f ) {
3700+ Channel* chan0, *chan1;
3701+ //Check if it's the 2nd channel in a 4-op
3702+ if ( !(fourMask & 0x80 ) ) {
3703+ chan0 = this;
3704+ chan1 = this + 1;
3705+ } else {
3706+ chan0 = this - 1;
3707+ chan1 = this;
3708+ }
3709+
3710+ Bit8u synth = ( (chan0->regC0 & 1) << 0 )| (( chan1->regC0 & 1) << 1 );
3711+ switch ( synth ) {
3712+ case 0:
3713+ chan0->synthHandler = &Channel::BlockTemplate< sm3FMFM >;
3714+ break;
3715+ case 1:
3716+ chan0->synthHandler = &Channel::BlockTemplate< sm3AMFM >;
3717+ break;
3718+ case 2:
3719+ chan0->synthHandler = &Channel::BlockTemplate< sm3FMAM >;
3720+ break;
3721+ case 3:
3722+ chan0->synthHandler = &Channel::BlockTemplate< sm3AMAM >;
3723+ break;
3724+ }
3725+ //Disable updating percussion channels
3726+ } else if ((fourMask & 0x40) && ( chip->regBD & 0x20) ) {
3727+
3728+ //Regular dual op, am or fm
3729+ } else if ( val & 1 ) {
3730+ synthHandler = &Channel::BlockTemplate< sm3AM >;
3731+ } else {
3732+ synthHandler = &Channel::BlockTemplate< sm3FM >;
3733+ }
3734+ maskLeft = ( val & 0x10 ) ? -1 : 0;
3735+ maskRight = ( val & 0x20 ) ? -1 : 0;
3736+ //opl2 active
3737+ } else {
3738+ //Disable updating percussion channels
3739+ if ( (fourMask & 0x40) && ( chip->regBD & 0x20 ) ) {
3740+
3741+ //Regular dual op, am or fm
3742+ } else if ( val & 1 ) {
3743+ synthHandler = &Channel::BlockTemplate< sm2AM >;
3744+ } else {
3745+ synthHandler = &Channel::BlockTemplate< sm2FM >;
3746+ }
3747+ }
3748+}
3749+
3750+void Channel::ResetC0( const Chip* chip ) {
3751+ Bit8u val = regC0;
3752+ regC0 ^= 0xff;
3753+ WriteC0( chip, val );
3754+}
3755+
3756+template< bool opl3Mode>
3757+void Channel::GeneratePercussion( Bit32s* output ) {
3758+ Channel* chan = this;
3759+
3760+ //BassDrum
3761+ Bit32s mod = (Bit32u)((old[0] + old[1])) >> feedback;
3762+ old[0] = old[1];
3763+ old[1] = Op(0)->GetSample( mod );
3764+
3765+ //When bassdrum is in AM mode first operator is ignoed
3766+ if ( chan->regC0 & 1 ) {
3767+ mod = 0;
3768+ } else {
3769+ mod = old[0];
3770+ }
3771+ Bit32s sample = Op(1)->GetSample( mod );
3772+
3773+ Operator* op2 = ( this + 1 )->Op(0);
3774+ Operator* op4 = ( this + 2 )->Op(0);
3775+
3776+ //Precalculate stuff used by other oupts
3777+ Bit32u noiseBit = rand() & 0x2;
3778+ Bit32u c2 = op2->ForwardWave();
3779+ //(bit 7 ^ bit 2) | bit 3 -> combined in bit 1
3780+ Bit32u phaseBit = ( (c2 >> 6) ^ ( c2 >> 1 ) ) | ( c2 >> 2 );
3781+ Bit32u c4 = op4->ForwardWave();
3782+ //bit 5 ^ bit 3 to bit 1
3783+ Bit32u gateBit = ( c4 >> 4 ) ^ ( c4 >> 3 );
3784+ phaseBit = (phaseBit | gateBit) & 0x2;
3785+
3786+ //Hi-Hat
3787+ Bit32u hhVol = op2->ForwardVolume();
3788+ if ( !ENV_SILENT( hhVol ) ) {
3789+ /* when phase & 0x200 is set and noise=1 then phase = 0x200|0xd0 */
3790+ /* when phase & 0x200 is set and noise=0 then phase = 0x200|(0xd0>>2), ie no change */
3791+ Bit32u hhIndex = ( phaseBit << 8 ) | ( 0xd0 >> ( phaseBit ^ noiseBit ) );
3792+ sample += op2->GetWave( hhIndex, hhVol );
3793+ }
3794+ //Snare Drum
3795+ Operator* op3 = ( this + 1 )->Op(1);
3796+ Bit32u sdVol = op3->ForwardVolume();
3797+ if ( !ENV_SILENT( sdVol ) ) {
3798+ Bit32u sdBits = 0x100 + (c2 & 0x100);
3799+ Bit32u sdIndex = sdBits ^ ( noiseBit << 7 );
3800+ sample += op3->GetWave( sdIndex, sdVol );
3801+ }
3802+ //Tom-tom
3803+ sample += op4->GetSample( 0 );
3804+ //Top-Cymbal
3805+ Operator* op5 = ( this + 2 )->Op(1);
3806+ Bit32u tcVol = op5->ForwardVolume();
3807+ if ( !ENV_SILENT( tcVol ) ) {
3808+ Bit32u tcIndex = (1 + phaseBit) << 8;
3809+ sample += op5->GetWave( tcIndex, tcVol );
3810+ }
3811+ sample <<= 1;
3812+ if ( opl3Mode ) {
3813+ output[0] += sample;
3814+ output[1] += sample;
3815+ } else {
3816+ output[0] += sample;
3817+ }
3818+}
3819+
3820+template<SynthMode mode>
3821+Channel* Channel::BlockTemplate( ) {
3822+ switch( mode ) {
3823+ case sm2AM:
3824+ case sm3AM:
3825+ if ( Op(0)->Silent() && Op(1)->Silent() ) {
3826+ old[0] = old[1] = 0;
3827+ return (this + 1);
3828+ }
3829+ break;
3830+ case sm2FM:
3831+ case sm3FM:
3832+ if ( Op(1)->Silent() ) {
3833+ old[0] = old[1] = 0;
3834+ return (this + 1);
3835+ }
3836+ break;
3837+ case sm3FMFM:
3838+ if ( Op(3)->Silent() ) {
3839+ old[0] = old[1] = 0;
3840+ return (this + 2);
3841+ }
3842+ break;
3843+ case sm3AMFM:
3844+ if ( Op(0)->Silent() && Op(3)->Silent() ) {
3845+ old[0] = old[1] = 0;
3846+ return (this + 2);
3847+ }
3848+ break;
3849+ case sm3FMAM:
3850+ if ( Op(1)->Silent() && Op(3)->Silent() ) {
3851+ old[0] = old[1] = 0;
3852+ return (this + 2);
3853+ }
3854+ break;
3855+ case sm3AMAM:
3856+ if ( Op(0)->Silent() && Op(2)->Silent() && Op(3)->Silent() ) {
3857+ old[0] = old[1] = 0;
3858+ return (this + 2);
3859+ }
3860+ break;
3861+ // TODO: Check this
3862+ default:
3863+ break;
3864+ }
3865+ for ( Bitu i = 0; i < Work.samples; i++ ) {
3866+ Work.vibrato = Work.vibTable[i];
3867+ Work.tremolo = Work.tremTable[i];
3868+
3869+ //Early out for percussion handlers
3870+ if ( mode == sm2Percussion ) {
3871+ GeneratePercussion<false>( Work.output + i );
3872+ continue; //Prevent some unitialized value bitching
3873+ } else if ( mode == sm3Percussion ) {
3874+ GeneratePercussion<true>( Work.output + i * 2 );
3875+ continue; //Prevent some unitialized value bitching
3876+ }
3877+
3878+ //Do unsigned shift so we can shift out all bits but still stay in 10 bit range otherwise
3879+ Bit32s mod = (Bit32u)((old[0] + old[1])) >> feedback;
3880+ old[0] = old[1];
3881+ old[1] = Op(0)->GetSample( mod );
3882+ Bit32s sample;
3883+ Bit32s out0 = old[0];
3884+ if ( mode == sm2AM || mode == sm3AM ) {
3885+ sample = out0 + Op(1)->GetSample( 0 );
3886+ } else if ( mode == sm2FM || mode == sm3FM ) {
3887+ sample = Op(1)->GetSample( out0 );
3888+ } else if ( mode == sm3FMFM ) {
3889+ Bits next = Op(1)->GetSample( out0 );
3890+ next = Op(2)->GetSample( next );
3891+ sample = Op(3)->GetSample( next );
3892+ } else if ( mode == sm3AMFM ) {
3893+ sample = out0;
3894+ Bits next = Op(1)->GetSample( 0 );
3895+ next = Op(2)->GetSample( next );
3896+ sample += Op(3)->GetSample( next );
3897+ } else if ( mode == sm3FMAM ) {
3898+ sample = Op(1)->GetSample( out0 );
3899+ Bits next = Op(2)->GetSample( 0 );
3900+ sample += Op(3)->GetSample( next );
3901+ } else if ( mode == sm3AMAM ) {
3902+ sample = out0;
3903+ Bits next = Op(1)->GetSample( 0 );
3904+ sample += Op(2)->GetSample( next );
3905+ sample += Op(3)->GetSample( 0 );
3906+ }
3907+ switch( mode ) {
3908+ case sm2AM:
3909+ case sm2FM:
3910+ Work.output[ i ] += sample;
3911+ break;
3912+ case sm3AM:
3913+ case sm3FM:
3914+ case sm3FMFM:
3915+ case sm3AMFM:
3916+ case sm3FMAM:
3917+ case sm3AMAM:
3918+ Work.output[ i * 2 + 0 ] += sample & maskLeft;
3919+ Work.output[ i * 2 + 1 ] += sample & maskRight;
3920+ break;
3921+ // TODO: Check this
3922+ default:
3923+ break;
3924+ }
3925+ }
3926+ switch( mode ) {
3927+ case sm2AM:
3928+ case sm2FM:
3929+ case sm3AM:
3930+ case sm3FM:
3931+ return ( this + 1 );
3932+ case sm3FMFM:
3933+ case sm3AMFM:
3934+ case sm3FMAM:
3935+ case sm3AMAM:
3936+ return( this + 2 );
3937+ case sm2Percussion:
3938+ case sm3Percussion:
3939+ return( this + 3 );
3940+ }
3941+ return 0;
3942+}
3943+
3944+/*
3945+ Chip
3946+*/
3947+
3948+Chip::Chip() {
3949+ reg08 = 0;
3950+ reg04 = 0;
3951+ regBD = 0;
3952+ reg104 = 0;
3953+ opl3Active = 0;
3954+}
3955+
3956+
3957+Bit8u Chip::ForwardTremolo( ) {
3958+ tremoloCounter += tremoloAdd;
3959+ if ( tremoloCounter >= (uint)(TREMOLO_TABLE << TREMOLO_SH) ) {
3960+ tremoloCounter -= TREMOLO_TABLE << TREMOLO_SH;
3961+ }
3962+ Bitu index = tremoloCounter >> TREMOLO_SH;
3963+ return TremoloTable[ index ] >> tremoloShift;
3964+}
3965+
3966+Bit8s Chip::ForwardVibrato( ) {
3967+ vibratoCounter += vibratoAdd;
3968+ Bitu index = vibratoCounter >> VIBRATO_SH;
3969+ //Vibrato shift, basically makes the shift greater reducing the actual final value
3970+ return VibratoTable[index & 7] + vibratoShift;
3971+}
3972+
3973+void Chip::WriteBD( Bit8u val ) {
3974+ Bit8u change = regBD ^ val;
3975+ if ( !change )
3976+ return;
3977+ regBD = val;
3978+ //TODO could do this with shift and xor?
3979+ vibratoShift = (val & 0x40) ? 0x00 : 0x01;
3980+ tremoloShift = (val & 0x80) ? 0x00 : 0x02;
3981+ if ( val & 0x20 ) {
3982+ //Drum was just enabled, make sure channel 6 has the right synth
3983+ if ( change & 0x20 ) {
3984+ if ( opl3Active ) {
3985+ chan[6].synthHandler = &Channel::BlockTemplate< sm3Percussion >;
3986+ } else {
3987+ chan[6].synthHandler = &Channel::BlockTemplate< sm2Percussion >;
3988+ }
3989+ }
3990+ //Bass Drum
3991+ if ( val & 0x10 ) {
3992+ chan[6].op[0].KeyOn( 0x2 );
3993+ chan[6].op[1].KeyOn( 0x2 );
3994+ } else {
3995+ chan[6].op[0].KeyOff( 0x2 );
3996+ chan[6].op[1].KeyOff( 0x2 );
3997+ }
3998+ //Hi-Hat
3999+ if ( val & 0x1 ) {
4000+ chan[7].op[0].KeyOn( 0x2 );
4001+ } else {
4002+ chan[7].op[0].KeyOff( 0x2 );
4003+ }
4004+ //Snare
4005+ if ( val & 0x8 ) {
4006+ chan[7].op[1].KeyOn( 0x2 );
4007+ } else {
4008+ chan[7].op[1].KeyOff( 0x2 );
4009+ }
4010+ //Tom-Tom
4011+ if ( val & 0x4 ) {
4012+ chan[8].op[0].KeyOn( 0x2 );
4013+ } else {
4014+ chan[8].op[0].KeyOff( 0x2 );
4015+ }
4016+ //Top Cymbal
4017+ if ( val & 0x2 ) {
4018+ chan[8].op[1].KeyOn( 0x2 );
4019+ } else {
4020+ chan[8].op[1].KeyOff( 0x2 );
4021+ }
4022+ //Toggle keyoffs when we turn off the percussion
4023+ } else if ( change & 0x20 ) {
4024+ //Trigger a reset to setup the original synth handler
4025+ chan[6].ResetC0( this );
4026+ chan[6].op[0].KeyOff( 0x2 );
4027+ chan[6].op[1].KeyOff( 0x2 );
4028+ chan[7].op[0].KeyOff( 0x2 );
4029+ chan[7].op[1].KeyOff( 0x2 );
4030+ chan[8].op[0].KeyOff( 0x2 );
4031+ chan[8].op[1].KeyOff( 0x2 );
4032+ }
4033+}
4034+
4035+
4036+#define REGOP( _FUNC_ ) \
4037+ index = ( ( reg >> 3) & 0x20 ) | ( reg & 0x1f ); \
4038+ if ( OpOffsetTable[ index ] ) { \
4039+ Operator* regOp = (Operator*)( ((char *)this ) + OpOffsetTable[ index ] ); \
4040+ regOp->_FUNC_( this, val ); \
4041+ }
4042+
4043+#define REGCHAN( _FUNC_ ) \
4044+ index = ( ( reg >> 4) & 0x10 ) | ( reg & 0xf ); \
4045+ if ( ChanOffsetTable[ index ] ) { \
4046+ Channel* regChan = (Channel*)( ((char *)this ) + ChanOffsetTable[ index ] ); \
4047+ regChan->_FUNC_( this, val ); \
4048+ }
4049+
4050+void Chip::WriteReg( Bit32u reg, Bit8u val ) {
4051+ Bitu index;
4052+ switch ( (reg & 0xf0) >> 4 ) {
4053+ case 0x00 >> 4:
4054+ if ( reg == 0x01 ) {
4055+ waveFormMask = ( val & 0x20 ) ? 0x7 : 0x0;
4056+ } else if ( reg == 0x104 ) {
4057+ //Only detect changes in lowest 6 bits
4058+ if ( !((reg104 ^ val) & 0x3f) )
4059+ return;
4060+ //Always keep the highest bit enabled, for checking > 0x80
4061+ reg104 = 0x80 | ( val & 0x3f );
4062+ } else if ( reg == 0x105 ) {
4063+ //MAME says the real opl3 doesn't reset anything on opl3 disable/enable till the next write in another register
4064+ if ( !((opl3Active ^ val) & 1 ) )
4065+ return;
4066+ opl3Active = ( val & 1 ) ? 0xff : 0;
4067+ //Update the 0xc0 register for all channels to signal the switch to mono/stereo handlers
4068+ for ( int i = 0; i < 18;i++ ) {
4069+ chan[i].ResetC0( this );
4070+ }
4071+ } else if ( reg == 0x08 ) {
4072+ reg08 = val;
4073+ }
4074+ case 0x10 >> 4:
4075+ break;
4076+ case 0x20 >> 4:
4077+ case 0x30 >> 4:
4078+ REGOP( Write20 );
4079+ break;
4080+ case 0x40 >> 4:
4081+ case 0x50 >> 4:
4082+ REGOP( Write40 );
4083+ break;
4084+ case 0x60 >> 4:
4085+ case 0x70 >> 4:
4086+ REGOP( Write60 );
4087+ break;
4088+ case 0x80 >> 4:
4089+ case 0x90 >> 4:
4090+ REGOP( Write80 );
4091+ break;
4092+ case 0xa0 >> 4:
4093+ REGCHAN( WriteA0 );
4094+ break;
4095+ case 0xb0 >> 4:
4096+ if ( reg == 0xbd ) {
4097+ WriteBD( val );
4098+ } else {
4099+ REGCHAN( WriteB0 );
4100+ }
4101+ break;
4102+ case 0xc0 >> 4:
4103+ REGCHAN( WriteC0 );
4104+ case 0xd0 >> 4:
4105+ break;
4106+ case 0xe0 >> 4:
4107+ case 0xf0 >> 4:
4108+ REGOP( WriteE0 );
4109+ break;
4110+ }
4111+}
4112+
4113+
4114+Bit32u Chip::WriteAddr( Bit32u port, Bit8u val ) {
4115+ switch ( port & 3 ) {
4116+ case 0:
4117+ return val;
4118+ case 2:
4119+ if ( opl3Active || (val == 0x05) )
4120+ return 0x100 | val;
4121+ else
4122+ return val;
4123+ }
4124+ return 0;
4125+}
4126+
4127+void Chip::GenerateBlock2( Bitu samples ) {
4128+ Work.samples = samples;
4129+ for ( Bitu i = 0; i < Work.samples; i++ ) {
4130+ Work.vibTable[i] = ForwardVibrato();
4131+ Work.tremTable[i] = ForwardTremolo();
4132+ Work.output[i] = 0;
4133+ }
4134+ int count = 0;
4135+ for( Channel* ch = chan; ch < chan + 9; ) {
4136+ count++;
4137+ ch = (ch->*(ch->synthHandler))();
4138+ }
4139+}
4140+
4141+void Chip::GenerateBlock3( Bitu samples ) {
4142+ Work.samples = samples;
4143+ for ( Bitu i = 0; i < Work.samples; i++ ) {
4144+ Work.vibTable[i] = ForwardVibrato();
4145+ Work.tremTable[i] = ForwardTremolo();
4146+ Work.output[i*2 + 0] = 0;
4147+ Work.output[i*2 + 1] = 0;
4148+ }
4149+ int count = 0;
4150+ for( Channel* ch = chan; ch < chan + 18; ) {
4151+ count++;
4152+ ch = (ch->*(ch->synthHandler))();
4153+ }
4154+}
4155+
4156+void Chip::Setup( Bit32u rate ) {
4157+ //Vibrato forwards every 1024 samples
4158+ vibratoAdd = (Bit32u)((double)rate * (double)( 1 << (VIBRATO_SH - 10) ) / OPLRATE);
4159+ vibratoCounter = 0;
4160+ //tremolo forwards every 64 samples
4161+ //We use a 52 entry table, real is 210, so repeat each sample an extra 4 times
4162+ tremoloAdd = (Bit32u)((double)rate * (double)( 1 << (TREMOLO_SH - 6 - 2) ) / OPLRATE);
4163+ tremoloCounter = 0;
4164+ //10 bits of frequency counter
4165+ //With higher octave this gets shifted up
4166+ //-1 since the freqCreateTable = *2
4167+ double scale = (OPLRATE * (double)( 1 << ( WAVE_SH - 10 - 1))) / rate;
4168+ for ( int i = 0; i < 16; i++ ) {
4169+ //Use rounding with 0.5
4170+ freqMul[i] = (Bit32u)( 0.5 + scale * FreqCreateTable[ i ] );
4171+ }
4172+
4173+ scale = OPLRATE / rate;
4174+ //-3 since the real envelope takes 8 steps to reach the single value we supply
4175+ for ( Bit8u i = 0; i < 76; i++ ) {
4176+ Bit8u index, shift;
4177+ EnvelopeSelect( i, index, shift );
4178+ linearRates[i] = (Bit32u)( scale * (EnvelopeIncreaseTable[ index ] << ( RATE_SH + ENV_EXTRA - shift - 3 )));
4179+ }
4180+ //Generate the best matching attack rate
4181+ for ( Bit8u i = 0; i < 62; i++ ) {
4182+ Bit8u index, shift;
4183+ EnvelopeSelect( i, index, shift );
4184+ //Original amount of samples the attack would take
4185+ Bit32s original = (Bit32u)( (AttackSamplesTable[ index ] << shift) / scale);
4186+
4187+ Bit32s guessAdd = (Bit32u)( scale * (EnvelopeIncreaseTable[ index ] << ( RATE_SH - shift - 3 )));
4188+ Bit32s bestAdd;
4189+ Bit32u bestDiff = 1 << 30;
4190+ for( Bit32u passes = 0; passes < 16; passes ++ ) {
4191+ Bit32s volume = ENV_MAX;
4192+ Bit32s samples = 0;
4193+ Bit32u count = 0;
4194+ while ( volume > 0 && samples < original * 2 ) {
4195+ count += guessAdd;
4196+ Bit32s change = count >> RATE_SH;
4197+ count &= RATE_MASK;
4198+ if ( change ) {
4199+ volume += ( ~volume * change ) >> 3;
4200+ }
4201+ samples++;
4202+
4203+ }
4204+ Bit32s diff = original - samples;
4205+ Bit32u lDiff = labs( diff );
4206+ //Init last on first pass
4207+ if ( lDiff < bestDiff ) {
4208+ bestDiff = lDiff;
4209+ bestAdd = guessAdd;
4210+ if ( !bestDiff )
4211+ break;
4212+ }
4213+ //Below our target
4214+ if ( diff < 0 ) {
4215+ //Better than the last time
4216+ Bit32s mul = ((original - diff) << 12) / original;
4217+ guessAdd = ((guessAdd * mul) >> 12);
4218+ guessAdd++;
4219+ } else if ( diff > 0 ) {
4220+ Bit32s mul = ((original - diff) << 12) / original;
4221+ guessAdd = (guessAdd * mul) >> 12;
4222+ guessAdd--;
4223+ }
4224+ }
4225+ attackRates[i] = bestAdd;
4226+ }
4227+ for ( Bit8u i = 62; i < 76; i++ ) {
4228+ //This should provide instant volume maximizing
4229+ attackRates[i] = 8 << RATE_SH;
4230+ }
4231+ //Setup the channels with the correct four op flags
4232+ //Channels are accessed through a table so they appear linear here
4233+ chan[ 0].fourMask = 0x00 | ( 1 << 0 );
4234+ chan[ 1].fourMask = 0x80 | ( 1 << 0 );
4235+ chan[ 2].fourMask = 0x00 | ( 1 << 1 );
4236+ chan[ 3].fourMask = 0x80 | ( 1 << 1 );
4237+ chan[ 4].fourMask = 0x00 | ( 1 << 2 );
4238+ chan[ 5].fourMask = 0x80 | ( 1 << 2 );
4239+
4240+ chan[ 9].fourMask = 0x00 | ( 1 << 3 );
4241+ chan[10].fourMask = 0x80 | ( 1 << 3 );
4242+ chan[11].fourMask = 0x00 | ( 1 << 4 );
4243+ chan[12].fourMask = 0x80 | ( 1 << 4 );
4244+ chan[13].fourMask = 0x00 | ( 1 << 5 );
4245+ chan[14].fourMask = 0x80 | ( 1 << 5 );
4246+
4247+ //mark the percussion channels
4248+ chan[ 6].fourMask = 0x40;
4249+ chan[ 7].fourMask = 0x40;
4250+ chan[ 8].fourMask = 0x40;
4251+
4252+ //Clear Everything in opl3 mode
4253+ WriteReg( 0x105, 0x1 );
4254+ for ( int i = 0; i < 512; i++ ) {
4255+ if ( i == 0x105 )
4256+ continue;
4257+ WriteReg( i, 0xff );
4258+ WriteReg( i, 0x0 );
4259+ }
4260+ WriteReg( 0x105, 0x0 );
4261+ //Clear everything in opl2 mode
4262+ for ( int i = 0; i < 255; i++ ) {
4263+ WriteReg( i, 0xff );
4264+ WriteReg( i, 0x0 );
4265+ }
4266+}
4267+
4268+static bool doneTables = false;
4269+void InitTables( void ) {
4270+ if ( doneTables )
4271+ return;
4272+ doneTables = true;
4273+#if ( DBOPL_WAVE == WAVE_HANDLER ) || ( DBOPL_WAVE == WAVE_TABLELOG )
4274+ //Exponential volume table, same as the real adlib
4275+ for ( int i = 0; i < 256; i++ ) {
4276+ //Save them in reverse
4277+ ExpTable[i] = (int)( 0.5 + ( pow(2.0, ( 255 - i) * ( 1.0 /256 ) )-1) * 1024 );
4278+ ExpTable[i] += 1024; //or remove the -1 oh well :)
4279+ //Preshift to the left once so the final volume can shift to the right
4280+ ExpTable[i] *= 2;
4281+ }
4282+#endif
4283+#if ( DBOPL_WAVE == WAVE_HANDLER )
4284+ //Add 0.5 for the trunc rounding of the integer cast
4285+ //Do a PI sinetable instead of the original 0.5 PI
4286+ for ( int i = 0; i < 512; i++ ) {
4287+ SinTable[i] = (Bit16s)( 0.5 - log10( sin( (i + 0.5) * (PI / 512.0) ) ) / log10(2.0)*256 );
4288+ }
4289+#endif
4290+#if ( DBOPL_WAVE == WAVE_TABLEMUL )
4291+ //Multiplication based tables
4292+ for ( int i = 0; i < 384; i++ ) {
4293+ int s = i * 8;
4294+ //TODO maybe keep some of the precision errors of the original table?
4295+ double val = ( 0.5 + ( pow(2, -1 + ( 255 - s) * ( 1.0 /256 ) )) * ( 1 << MUL_SH ));
4296+ MulTable[i] = (Bit16u)(val);
4297+ }
4298+
4299+ //Sine Wave Base
4300+ for ( int i = 0; i < 512; i++ ) {
4301+ WaveTable[ 0x0200 + i ] = (Bit16s)(sin( (i + 0.5) * (PI / 512.0) ) * 4084);
4302+ WaveTable[ 0x0000 + i ] = -WaveTable[ 0x200 + i ];
4303+ }
4304+ //Exponential wave
4305+ for ( int i = 0; i < 256; i++ ) {
4306+ WaveTable[ 0x700 + i ] = (Bit16s)( 0.5 + ( pow(2, -1 + ( 255 - i * 8) * ( 1.0 /256 ) ) ) * 4085 );
4307+ WaveTable[ 0x6ff - i ] = -WaveTable[ 0x700 + i ];
4308+ }
4309+#endif
4310+#if ( DBOPL_WAVE == WAVE_TABLELOG )
4311+ //Sine Wave Base
4312+ for ( int i = 0; i < 512; i++ ) {
4313+ WaveTable[ 0x0200 + i ] = (Bit16s)( 0.5 - log10( sin( (i + 0.5) * (PI / 512.0) ) ) / log10(2.0)*256 );
4314+ WaveTable[ 0x0000 + i ] = ((Bit16s)0x8000) | WaveTable[ 0x200 + i];
4315+ }
4316+ //Exponential wave
4317+ for ( int i = 0; i < 256; i++ ) {
4318+ WaveTable[ 0x700 + i ] = i * 8;
4319+ WaveTable[ 0x6ff - i ] = ((Bit16s)0x8000) | i * 8;
4320+ }
4321+#endif
4322+
4323+ // | |//\\|____|WAV7|//__|/\ |____|/\/\|
4324+ // |\\//| | |WAV7| | \/| | |
4325+ // |06 |0126|27 |7 |3 |4 |4 5 |5 |
4326+
4327+#if (( DBOPL_WAVE == WAVE_TABLELOG ) || ( DBOPL_WAVE == WAVE_TABLEMUL ))
4328+ for ( int i = 0; i < 256; i++ ) {
4329+ //Fill silence gaps
4330+ WaveTable[ 0x400 + i ] = WaveTable[0];
4331+ WaveTable[ 0x500 + i ] = WaveTable[0];
4332+ WaveTable[ 0x900 + i ] = WaveTable[0];
4333+ WaveTable[ 0xc00 + i ] = WaveTable[0];
4334+ WaveTable[ 0xd00 + i ] = WaveTable[0];
4335+ //Replicate sines in other pieces
4336+ WaveTable[ 0x800 + i ] = WaveTable[ 0x200 + i ];
4337+ //double speed sines
4338+ WaveTable[ 0xa00 + i ] = WaveTable[ 0x200 + i * 2 ];
4339+ WaveTable[ 0xb00 + i ] = WaveTable[ 0x000 + i * 2 ];
4340+ WaveTable[ 0xe00 + i ] = WaveTable[ 0x200 + i * 2 ];
4341+ WaveTable[ 0xf00 + i ] = WaveTable[ 0x200 + i * 2 ];
4342+ }
4343+#endif
4344+
4345+ //Create the ksl table
4346+ for ( int oct = 0; oct < 8; oct++ ) {
4347+ int base = oct * 8;
4348+ for ( int i = 0; i < 16; i++ ) {
4349+ int val = base - KslCreateTable[i];
4350+ if ( val < 0 )
4351+ val = 0;
4352+ //*4 for the final range to match attenuation range
4353+ KslTable[ oct * 16 + i ] = val * 4;
4354+ }
4355+ }
4356+ //Create the Tremolo table, just increase and decrease a triangle wave
4357+ for ( Bit8u i = 0; i < TREMOLO_TABLE / 2; i++ ) {
4358+ Bit8u val = i << ENV_EXTRA;
4359+ TremoloTable[i] = val;
4360+ TremoloTable[TREMOLO_TABLE - 1 - i] = val;
4361+ }
4362+ //Create a table with offsets of the channels from the start of the chip
4363+ for ( Bitu i = 0; i < 32; i++ ) {
4364+ Bitu index = i & 0xf;
4365+ if ( index >= 9 ) {
4366+ ChanOffsetTable[i] = 0;
4367+ continue;
4368+ }
4369+ //Make sure the four op channels follow eachother
4370+ if ( index < 6 ) {
4371+ index = (index % 3) * 2 + ( index / 3 );
4372+ }
4373+ //Add back the bits for highest ones
4374+ if ( i >= 16 )
4375+ index += 9;
4376+ ChanOffsetTable[i] = OFFS(Chip, chan) + index * sizeof(Channel);
4377+ }
4378+ //Same for operators
4379+ for ( Bitu i = 0; i < 64; i++ ) {
4380+ if ( i % 8 >= 6 || ( (i / 8) % 4 == 3 ) ) {
4381+ OpOffsetTable[i] = 0;
4382+ continue;
4383+ }
4384+ Bitu chNum = (i / 8) * 3 + (i % 8) % 3;
4385+ //Make sure we use 16 and up for the 2nd range to match the chanoffset gap
4386+ if ( chNum >= 12 )
4387+ chNum += 16 - 12;
4388+ Bitu opNum = ( i % 8 ) / 3;
4389+ OpOffsetTable[i] = ChanOffsetTable[ chNum ] + OFFS(Channel, op) + opNum * sizeof(Operator);
4390+ }
4391+}
4392+
4393+Bit32u Handler::writeAddr( Bit32u port, Bit8u val ) {
4394+ return chip.WriteAddr( port, val );
4395+
4396+}
4397+void Handler::writeReg( Bit32u addr, Bit8u val ) {
4398+ chip.WriteReg( addr, val );
4399+}
4400+
4401+void Handler::generate( Bit16s *chan, Bitu samples ) {
4402+ // Opl3 is stereo thus we half the number of samples here.
4403+
4404+ while (samples > 0) {
4405+ Bitu todo = samples > MAX_SAMPLES ? MAX_SAMPLES : samples;
4406+ samples -= todo;
4407+ if ( !chip.opl3Active ) {
4408+ chip.GenerateBlock2( todo );
4409+ for (uint i = 0; i < todo; ++i)
4410+ chan[i] = Work.output[i];
4411+ chan += todo;
4412+ } else {
4413+ chip.GenerateBlock3( samples );
4414+ for (uint i = 0; i < (todo << 1); ++i)
4415+ chan[i] = Work.output[i];
4416+ chan += (todo << 1);
4417+ }
4418+ }
4419+}
4420+
4421+void Handler::init( Bitu rate ) {
4422+ InitTables();
4423+ chip.Setup( rate );
4424+}
4425+
4426+} // end of namespace DBOPL
4427+} // end of namespace DOSBox
4428+} // end of namespace AdLib
4429+
4430+#endif
4431+
4432Index: sound/softsynth/adlib/dosbox.h
4433===================================================================
4434--- sound/softsynth/adlib/dosbox.h (revision 0)
4435+++ sound/softsynth/adlib/dosbox.h (revision 0)
4436@@ -0,0 +1,120 @@
4437+/* ScummVM - Graphic Adventure Engine
4438+ *
4439+ * ScummVM is the legal property of its developers, whose names
4440+ * are too numerous to list here. Please refer to the COPYRIGHT
4441+ * file distributed with this source distribution.
4442+ *
4443+ * This program is free software; you can redistribute it and/or
4444+ * modify it under the terms of the GNU General Public License
4445+ * as published by the Free Software Foundation; either version 2
4446+ * of the License, or (at your option) any later version.
4447+ *
4448+ * This program is distributed in the hope that it will be useful,
4449+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
4450+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
4451+ * GNU General Public License for more details.
4452+ *
4453+ * You should have received a copy of the GNU General Public License
4454+ * along with this program; if not, write to the Free Software
4455+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
4456+ *
4457+ * $URL$
4458+ * $Id$
4459+ */
4460+
4461+/*
4462+ * Based on AdLib emulation code of DOSBox
4463+ * Copyright (C) 2002-2009 The DOSBox Team
4464+ * Licensed under GPLv2+
4465+ * http://www.dosbox.com
4466+ */
4467+
4468+#ifndef SOUND_SOFTSYNTH_ADLIB_DOSBOX_H
4469+#define SOUND_SOFTSYNTH_ADLIB_DOSBOX_H
4470+
4471+#ifndef DISABLE_DOSBOX_ADLIB
4472+
4473+#include "sound/fmopl.h"
4474+
4475+namespace AdLib {
4476+namespace DOSBox {
4477+
4478+class Handler;
4479+
4480+struct Timer {
4481+ double startTime;
4482+ double delay;
4483+ bool enabled, overflow, masked;
4484+ uint8 counter;
4485+
4486+ Timer();
4487+
4488+ //Call update before making any further changes
4489+ void update(double time);
4490+
4491+ //On a reset make sure the start is in sync with the next cycle
4492+ void reset(double time);
4493+
4494+ void stop();
4495+
4496+ void start(double time, int scale);
4497+};
4498+
4499+struct Chip {
4500+ //Last selected register
4501+ Timer timer[2];
4502+ //Check for it being a write to the timer
4503+ bool write(uint32 addr, uint8 val);
4504+ //Read the current timer state, will use current double
4505+ uint8 read();
4506+};
4507+
4508+class Handler {
4509+public:
4510+ virtual ~Handler() {}
4511+
4512+ // Write an address to a chip, returns the address the chip sets
4513+ virtual uint32 writeAddr(uint32 port, uint8 val) = 0;
4514+ // Write to a specific register in the chip
4515+ virtual void writeReg(uint32 addr, uint8 val) = 0;
4516+ // Generate a certain amount of samples
4517+ virtual void generate(int16 *chan, uint samples) = 0;
4518+ // Initialize at a specific sample rate and mode
4519+ virtual void init(uint rate) = 0;
4520+};
4521+
4522+class AdLib_DOSBox : public AdLib {
4523+private:
4524+ kOplType _type;
4525+ uint _rate;
4526+
4527+ Handler *_handler;
4528+ Chip _chip[2];
4529+ union {
4530+ uint16 normal;
4531+ uint8 dual[2];
4532+ } _reg;
4533+
4534+ void free();
4535+public:
4536+ AdLib_DOSBox();
4537+ ~AdLib_DOSBox();
4538+
4539+ void init(int rate, kOplType type);
4540+ void reset();
4541+
4542+ void write(int a, int v);
4543+ byte read(int a);
4544+
4545+ void writeReg(int r, int v);
4546+
4547+ void readBuffer(int16 *buffer, int length);
4548+};
4549+
4550+} // end of namespace DOSBox
4551+} // end of namespace AdLib
4552+
4553+#endif // !DISABLE_DOSBOX_ADLIB
4554+
4555+#endif
4556+
4557Index: sound/softsynth/adlib/mame.h
4558===================================================================
4559--- sound/softsynth/adlib/mame.h (revision 0)
4560+++ sound/softsynth/adlib/mame.h (revision 0)
4561@@ -0,0 +1,200 @@
4562+/* ScummVM - Graphic Adventure Engine
4563+ *
4564+ * ScummVM is the legal property of its developers, whose names
4565+ * are too numerous to list here. Please refer to the COPYRIGHT
4566+ * file distributed with this source distribution.
4567+ *
4568+ * This program is free software; you can redistribute it and/or
4569+ * modify it under the terms of the GNU General Public License
4570+ * as published by the Free Software Foundation; either version 2
4571+ * of the License, or (at your option) any later version.
4572+
4573+ * This program is distributed in the hope that it will be useful,
4574+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
4575+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
4576+ * GNU General Public License for more details.
4577+
4578+ * You should have received a copy of the GNU General Public License
4579+ * along with this program; if not, write to the Free Software
4580+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
4581+ *
4582+ * $URL: https://scummvm.svn.sourceforge.net/svnroot/scummvm/scummvm/trunk/sound/fmopl.h $
4583+ * $Id: fmopl.h 38211 2009-02-15 10:07:50Z sev $
4584+ *
4585+ * LGPL licensed version of MAMEs fmopl (V0.37a modified) by
4586+ * Tatsuyuki Satoh. Included from LGPL'ed AdPlug.
4587+ */
4588+
4589+
4590+#ifndef SOUND_SOFTSYNTH_ADLIB_MAME_H
4591+#define SOUND_SOFTSYNTH_ADLIB_MAME_H
4592+
4593+#include "common/scummsys.h"
4594+#include "common/util.h"
4595+
4596+#include "sound/fmopl.h"
4597+
4598+namespace AdLib {
4599+namespace MAME {
4600+
4601+enum {
4602+ FMOPL_ENV_BITS_HQ = 16,
4603+ FMOPL_ENV_BITS_MQ = 8,
4604+ FMOPL_ENV_BITS_LQ = 8,
4605+ FMOPL_EG_ENT_HQ = 4096,
4606+ FMOPL_EG_ENT_MQ = 1024,
4607+ FMOPL_EG_ENT_LQ = 128
4608+};
4609+
4610+
4611+typedef void (*OPL_TIMERHANDLER)(int channel,double interval_Sec);
4612+typedef void (*OPL_IRQHANDLER)(int param,int irq);
4613+typedef void (*OPL_UPDATEHANDLER)(int param,int min_interval_us);
4614+
4615+#define OPL_TYPE_WAVESEL 0x01 /* waveform select */
4616+
4617+/* Saving is necessary for member of the 'R' mark for suspend/resume */
4618+/* ---------- OPL one of slot ---------- */
4619+typedef struct fm_opl_slot {
4620+ int TL; /* total level :TL << 8 */
4621+ int TLL; /* adjusted now TL */
4622+ uint8 KSR; /* key scale rate :(shift down bit) */
4623+ int *AR; /* attack rate :&AR_TABLE[AR<<2] */
4624+ int *DR; /* decay rate :&DR_TABLE[DR<<2] */
4625+ int SL; /* sustain level :SL_TABLE[SL] */
4626+ int *RR; /* release rate :&DR_TABLE[RR<<2] */
4627+ uint8 ksl; /* keyscale level :(shift down bits) */
4628+ uint8 ksr; /* key scale rate :kcode>>KSR */
4629+ uint mul; /* multiple :ML_TABLE[ML] */
4630+ uint Cnt; /* frequency count */
4631+ uint Incr; /* frequency step */
4632+
4633+ /* envelope generator state */
4634+ uint8 eg_typ;/* envelope type flag */
4635+ uint8 evm; /* envelope phase */
4636+ int evc; /* envelope counter */
4637+ int eve; /* envelope counter end point */
4638+ int evs; /* envelope counter step */
4639+ int evsa; /* envelope step for AR :AR[ksr] */
4640+ int evsd; /* envelope step for DR :DR[ksr] */
4641+ int evsr; /* envelope step for RR :RR[ksr] */
4642+
4643+ /* LFO */
4644+ uint8 ams; /* ams flag */
4645+ uint8 vib; /* vibrate flag */
4646+ /* wave selector */
4647+ int **wavetable;
4648+} OPL_SLOT;
4649+
4650+/* ---------- OPL one of channel ---------- */
4651+typedef struct fm_opl_channel {
4652+ OPL_SLOT SLOT[2];
4653+ uint8 CON; /* connection type */
4654+ uint8 FB; /* feed back :(shift down bit)*/
4655+ int *connect1; /* slot1 output pointer */
4656+ int *connect2; /* slot2 output pointer */
4657+ int op1_out[2]; /* slot1 output for selfeedback */
4658+
4659+ /* phase generator state */
4660+ uint block_fnum; /* block+fnum */
4661+ uint8 kcode; /* key code : KeyScaleCode */
4662+ uint fc; /* Freq. Increment base */
4663+ uint ksl_base; /* KeyScaleLevel Base step */
4664+ uint8 keyon; /* key on/off flag */
4665+} OPL_CH;
4666+
4667+/* OPL state */
4668+typedef struct fm_opl_f {
4669+ uint8 type; /* chip type */
4670+ int clock; /* master clock (Hz) */
4671+ int rate; /* sampling rate (Hz) */
4672+ double freqbase; /* frequency base */
4673+ double TimerBase; /* Timer base time (==sampling time) */
4674+ uint8 address; /* address register */
4675+ uint8 status; /* status flag */
4676+ uint8 statusmask; /* status mask */
4677+ uint mode; /* Reg.08 : CSM , notesel,etc. */
4678+
4679+ /* Timer */
4680+ int T[2]; /* timer counter */
4681+ uint8 st[2]; /* timer enable */
4682+
4683+ /* FM channel slots */
4684+ OPL_CH *P_CH; /* pointer of CH */
4685+ int max_ch; /* maximum channel */
4686+
4687+ /* Rythm sention */
4688+ uint8 rythm; /* Rythm mode , key flag */
4689+
4690+ /* time tables */
4691+ int AR_TABLE[76]; /* atttack rate tables */
4692+ int DR_TABLE[76]; /* decay rate tables */
4693+ uint FN_TABLE[1024];/* fnumber -> increment counter */
4694+
4695+ /* LFO */
4696+ int *ams_table;
4697+ int *vib_table;
4698+ int amsCnt;
4699+ int amsIncr;
4700+ int vibCnt;
4701+ int vibIncr;
4702+
4703+ /* wave selector enable flag */
4704+ uint8 wavesel;
4705+
4706+ /* external event callback handler */
4707+ OPL_TIMERHANDLER TimerHandler; /* TIMER handler */
4708+ int TimerParam; /* TIMER parameter */
4709+ OPL_IRQHANDLER IRQHandler; /* IRQ handler */
4710+ int IRQParam; /* IRQ parameter */
4711+ OPL_UPDATEHANDLER UpdateHandler; /* stream update handler */
4712+ int UpdateParam; /* stream update parameter */
4713+
4714+ Common::RandomSource rnd;
4715+} FM_OPL;
4716+
4717+/* ---------- Generic interface section ---------- */
4718+#define OPL_TYPE_YM3526 (0)
4719+#define OPL_TYPE_YM3812 (OPL_TYPE_WAVESEL)
4720+
4721+void OPLBuildTables(int ENV_BITS_PARAM, int EG_ENT_PARAM);
4722+
4723+FM_OPL *OPLCreate(int type, int clock, int rate);
4724+void OPLDestroy(FM_OPL *OPL);
4725+void OPLSetTimerHandler(FM_OPL *OPL, OPL_TIMERHANDLER TimerHandler, int channelOffset);
4726+void OPLSetIRQHandler(FM_OPL *OPL, OPL_IRQHANDLER IRQHandler, int param);
4727+void OPLSetUpdateHandler(FM_OPL *OPL, OPL_UPDATEHANDLER UpdateHandler, int param);
4728+
4729+void OPLResetChip(FM_OPL *OPL);
4730+int OPLWrite(FM_OPL *OPL, int a, int v);
4731+unsigned char OPLRead(FM_OPL *OPL, int a);
4732+int OPLTimerOver(FM_OPL *OPL, int c);
4733+void OPLWriteReg(FM_OPL *OPL, int r, int v);
4734+void YM3812UpdateOne(FM_OPL *OPL, int16 *buffer, int length, int interleave = 0);
4735+
4736+// Factory method
4737+FM_OPL *makeAdlibOPL(int rate);
4738+
4739+// AdLib API implementation
4740+class AdLib_MAME : public AdLib {
4741+private:
4742+ FM_OPL *_opl;
4743+public:
4744+ AdLib_MAME() : _opl(0) {}
4745+ ~AdLib_MAME();
4746+
4747+ void init(int rate, kOplType type);
4748+ void reset();
4749+
4750+ void write(int a, int v);
4751+ byte read(int a);
4752+
4753+ void writeReg(int r, int v);
4754+
4755+ void readBuffer(int16 *buffer, int length);
4756+};
4757+
4758+} // end of namespace MAME
4759+} // end of namespace AdLib
4760+
4761+#endif
4762Index: sound/softsynth/adlib/dbopl.h
4763===================================================================
4764--- sound/softsynth/adlib/dbopl.h (revision 0)
4765+++ sound/softsynth/adlib/dbopl.h (revision 0)
4766@@ -0,0 +1,284 @@
4767+/* ScummVM - Graphic Adventure Engine
4768+ *
4769+ * ScummVM is the legal property of its developers, whose names
4770+ * are too numerous to list here. Please refer to the COPYRIGHT
4771+ * file distributed with this source distribution.
4772+ *
4773+ * This program is free software; you can redistribute it and/or
4774+ * modify it under the terms of the GNU General Public License
4775+ * as published by the Free Software Foundation; either version 2
4776+ * of the License, or (at your option) any later version.
4777+ *
4778+ * This program is distributed in the hope that it will be useful,
4779+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
4780+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
4781+ * GNU General Public License for more details.
4782+ *
4783+ * You should have received a copy of the GNU General Public License
4784+ * along with this program; if not, write to the Free Software
4785+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
4786+ *
4787+ * $URL$
4788+ * $Id$
4789+ */
4790+
4791+/*
4792+ * Based on AdLib emulation code of DOSBox
4793+ * Copyright (C) 2002-2009 The DOSBox Team
4794+ * Licensed under GPLv2+
4795+ * http://www.dosbox.com
4796+ */
4797+
4798+#ifndef DISABLE_DOSBOX_ADLIB
4799+
4800+#ifndef SOUND_SOFTSYNTH_ADLIB_DBOPL_H
4801+#define SOUND_SOFTSYNTH_ADLIB_DBOPL_H
4802+
4803+#include "common/scummsys.h"
4804+#include "dosbox.h"
4805+
4806+//Use 8 handlers based on a small logatirmic wavetabe and an exponential table for volume
4807+#define WAVE_HANDLER 10
4808+//Use a logarithmic wavetable with an exponential table for volume
4809+#define WAVE_TABLELOG 11
4810+//Use a linear wavetable with a multiply table for volume
4811+#define WAVE_TABLEMUL 12
4812+
4813+//Select the type of wave generator routine
4814+#define DBOPL_WAVE WAVE_TABLEMUL
4815+//Enable vibrato in the output
4816+#define DBOPL_VIBRATO
4817+//Enable tremolo in the output
4818+#define DBOPL_TREMOLO
4819+
4820+namespace AdLib {
4821+namespace DOSBox {
4822+namespace DBOPL {
4823+
4824+// Define types required by DOSBox code
4825+typedef int Bits;
4826+typedef uint Bitu;
4827+typedef int8 Bit8s;
4828+typedef uint8 Bit8u;
4829+typedef int16 Bit16s;
4830+typedef uint16 Bit16u;
4831+typedef int32 Bit32s;
4832+typedef uint32 Bit32u;
4833+
4834+struct Chip;
4835+struct Operator;
4836+struct Channel;
4837+
4838+#if (DBOPL_WAVE == WAVE_HANDLER)
4839+typedef Bits ( DB_FASTCALL *WaveHandler) ( Bitu i, Bitu volume );
4840+#endif
4841+
4842+typedef Bits ( DBOPL::Operator::*VolumeHandler) ( );
4843+typedef Channel* ( DBOPL::Channel::*SynthHandler) ( );
4844+
4845+//Different synth modes that can generate blocks of data
4846+enum SynthMode {
4847+ smNone,
4848+ sm2AM,
4849+ sm2FM,
4850+ sm2Percussion,
4851+ sm3AM,
4852+ sm3FM,
4853+ sm3FMFM,
4854+ sm3AMFM,
4855+ sm3FMAM,
4856+ sm3AMAM,
4857+ sm3Percussion
4858+};
4859+
4860+//Shifts for the values contained in chandata variable
4861+enum {
4862+ SHIFT_KSLBASE = 16,
4863+ SHIFT_KEYCODE = 24
4864+};
4865+
4866+struct Operator {
4867+public:
4868+ //Masks for operator 20 values
4869+ enum {
4870+ MASK_KSR = 0x10,
4871+ MASK_SUSTAIN = 0x20,
4872+ MASK_VIBRATO = 0x40,
4873+ MASK_TREMOLO = 0x80
4874+ };
4875+
4876+ enum State {
4877+ OFF,
4878+ RELEASE,
4879+ SUSTAIN,
4880+ DECAY,
4881+ ATTACK
4882+ };
4883+
4884+ VolumeHandler volHandler;
4885+
4886+#if (DBOPL_WAVE == WAVE_HANDLER)
4887+ WaveHandler waveHandler; //Routine that generate a wave
4888+#else
4889+ Bit16s* waveBase;
4890+ Bit32u waveMask;
4891+ Bit32u waveStart;
4892+#endif
4893+ Bit32u waveIndex; //WAVE_BITS shifted counter of the frequency index
4894+ Bit32u waveAdd;
4895+
4896+ Bit32u chanData; //Frequency/octave and derived data coming from whatever channel controls this
4897+ Bit32u freqMul; //Scale channel frequency with this, TODO maybe remove?
4898+ Bit32u vibrato; //Scaled up vibrato strength
4899+ Bit32s sustainLevel; //When stopping at sustain level stop here
4900+ Bit32s totalLevel; //totalLeve is added to every generated volume
4901+ Bit32s activeLevel; //The currently active volume
4902+
4903+ Bit32u attackAdd; //Timers for the different states of the envelope
4904+ Bit32u decayAdd;
4905+ Bit32u releaseAdd;
4906+ Bit32u rateIndex; //Current position of the evenlope
4907+
4908+ Bit8u rateZero; //Bits for the different states of the envelope having no changes
4909+ Bit8u keyOn; //Bitmask of different values that can generate keyon
4910+ //Registers, also used to check for changes
4911+ Bit8u reg20, reg40, reg60, reg80, regE0;
4912+ //Active part of the envelope we're in
4913+ Bit8u state;
4914+ //0xff when tremolo is enabled
4915+ Bit8u tremoloMask;
4916+ //Strength of the vibrato
4917+ Bit8u vibStrength;
4918+ //Keep track of the calculated KSR so we can check for changes
4919+ Bit8u ksr;
4920+private:
4921+ void SetState( Bit8u s );
4922+ void UpdateAttack( const Chip* chip );
4923+ void UpdateRelease( const Chip* chip );
4924+ void UpdateDecay( const Chip* chip );
4925+public:
4926+ void UpdateAttenuation();
4927+ void UpdateRates( const Chip* chip );
4928+ void UpdateFrequency( );
4929+
4930+ void Write20( const Chip* chip, Bit8u val );
4931+ void Write40( const Chip* chip, Bit8u val );
4932+ void Write60( const Chip* chip, Bit8u val );
4933+ void Write80( const Chip* chip, Bit8u val );
4934+ void WriteE0( const Chip* chip, Bit8u val );
4935+
4936+ bool Silent() const;
4937+ void KeyOn( Bit8u mask);
4938+ void KeyOff( Bit8u mask);
4939+
4940+ template< State state>
4941+ Bits TemplateVolume( );
4942+
4943+ Bit32s RateForward( Bit32u add );
4944+ Bitu ForwardWave();
4945+ Bitu ForwardVolume();
4946+
4947+ Bits GetSample( Bits modulation );
4948+ Bits GetWave( Bitu index, Bitu vol );
4949+public:
4950+ Operator();
4951+};
4952+
4953+struct Channel {
4954+ Operator op[2];
4955+ inline Operator* Op( Bitu index ) {
4956+ return &( ( this + (index >> 1) )->op[ index & 1 ]);
4957+ }
4958+ SynthHandler synthHandler;
4959+ Bit32u chanData; //Frequency/octave and derived values
4960+ Bit32s old[2]; //Old data for feedback
4961+
4962+ Bit8u feedback; //Feedback shift
4963+ Bit8u regB0; //Register values to check for changes
4964+ Bit8u regC0;
4965+ //This should correspond with reg104, bit 6 indicates a Percussion channel, bit 7 indicates a silent channel
4966+ Bit8u fourMask;
4967+ Bit8s maskLeft; //Sign extended values for both channel's panning
4968+ Bit8s maskRight;
4969+
4970+ //Forward the channel data to the operators of the channel
4971+ void SetChanData( const Chip* chip, Bit32u data );
4972+ //Change in the chandata, check for new values and if we have to forward to operators
4973+ void UpdateFrequency( const Chip* chip, Bit8u fourOp );
4974+ void WriteA0( const Chip* chip, Bit8u val );
4975+ void WriteB0( const Chip* chip, Bit8u val );
4976+ void WriteC0( const Chip* chip, Bit8u val );
4977+ void ResetC0( const Chip* chip );
4978+
4979+ //call this for the first channel
4980+ template< bool opl3Mode >
4981+ void GeneratePercussion( Bit32s* output );
4982+
4983+ //Generate blocks of data in specific modes
4984+ template<SynthMode mode>
4985+ Channel* BlockTemplate( );
4986+ Channel();
4987+};
4988+
4989+struct Chip {
4990+ //This is used as the base counter for vibrato and tremolo
4991+ Bit32u tremoloCounter;
4992+ Bit32u tremoloAdd;
4993+ Bit32u vibratoCounter;
4994+ Bit32u vibratoAdd;
4995+
4996+ //Frequency scales for the different multiplications
4997+ Bit32u freqMul[16];
4998+ //Rates for decay and release for rate of this chip
4999+ Bit32u linearRates[76];
5000+ //Best match attack rates for the rate of this chip
5001+ Bit32u attackRates[76];
5002+
5003+ //18 channels with 2 operators each
5004+ Channel chan[18];
5005+
5006+ Bit8u reg104;
5007+ Bit8u reg08;
5008+ Bit8u reg04;
5009+ Bit8u regBD;
5010+ Bit8u vibratoShift;
5011+ Bit8u tremoloShift;
5012+ //Mask for allowed wave forms
5013+ Bit8u waveFormMask;
5014+ //0 or -1 when enabled
5015+ Bit8s opl3Active;
5016+
5017+ Bit8u ForwardTremolo();
5018+ Bit8s ForwardVibrato();
5019+
5020+ void WriteBD( Bit8u val );
5021+ void WriteReg(Bit32u reg, Bit8u val );
5022+
5023+ Bit32u WriteAddr( Bit32u port, Bit8u val );
5024+
5025+ void GenerateBlock2( Bitu samples );
5026+ void GenerateBlock3( Bitu samples );
5027+
5028+ void Generate( Bit32u samples );
5029+ void Setup( Bit32u r );
5030+
5031+ Chip();
5032+};
5033+
5034+struct Handler : public DOSBox::Handler {
5035+ DBOPL::Chip chip;
5036+
5037+ virtual Bit32u writeAddr( Bit32u port, Bit8u val );
5038+ virtual void writeReg( Bit32u addr, Bit8u val );
5039+ virtual void generate( Bit16s *chan, Bitu samples );
5040+ virtual void init( Bitu rate );
5041+};
5042+
5043+} // end of namespace DBOPL
5044+} // end of namespace DOSBox
5045+} // end of namespace AdLib
5046+
5047+#endif
5048+
5049+#endif
5050+
5051Index: engines/sci/sfx/softseq/opl2.cpp
5052===================================================================
5053--- engines/sci/sfx/softseq/opl2.cpp (revision 40184)
5054+++ engines/sci/sfx/softseq/opl2.cpp (working copy)
5055@@ -42,6 +42,8 @@
5056
5057 ***************************************************************************/
5058
5059+#include "common/util.h"
5060+
5061 #include "sci/tools.h"
5062 #include "sci/sfx/iterator.h"
5063 #include "../softseq.h"
5064@@ -79,9 +81,6 @@
5065 #define ADLIB_LEFT 0
5066 #define ADLIB_RIGHT 1
5067
5068-/* #define OPL_INTERNAL_FREQ 3600000 */
5069-#define OPL_INTERNAL_FREQ 3579545
5070-
5071 static int ready = 0;
5072 static int pcmout_stereo = STEREO;
5073
5074@@ -157,21 +156,21 @@
5075
5076 /* more shamelessly lifted from xmp and adplug. And altered. :) */
5077
5078-static int opl_write_L(int a, int v) {
5079+static void opl_write_L(int a, int v) {
5080 adlib_reg_L[a] = v;
5081 OPLWrite(ym3812_L, 0x388, a);
5082- return OPLWrite(ym3812_L, 0x389, v);
5083+ OPLWrite(ym3812_L, 0x389, v);
5084 }
5085
5086-static int opl_write_R(int a, int v) {
5087+static void opl_write_R(int a, int v) {
5088 adlib_reg_R[a] = v;
5089 OPLWrite(ym3812_R, 0x388, a);
5090- return OPLWrite(ym3812_R, 0x389, v);
5091+ OPLWrite(ym3812_R, 0x389, v);
5092 }
5093
5094-static int opl_write(int a, int v) {
5095+static void opl_write(int a, int v) {
5096 opl_write_L(a, v);
5097- return opl_write_R(a, v);
5098+ opl_write_R(a, v);
5099 }
5100
5101 /*
5102@@ -472,16 +471,13 @@
5103 We assume 16-bit stereo frames (ie 4 bytes)
5104 */
5105 static void opl2_poll(sfx_softseq_t *self, byte *dest, int count) {
5106- int16 *buffer = (int16 *) dest;
5107- int16 *ptr = buffer;
5108+ int16 *ptr = (int16 *)dest;
5109
5110- if (!ready) {
5111+ if (!ready)
5112 error("synth_mixer(): !ready \n");
5113- }
5114
5115- if (!buffer) {
5116+ if (!ptr)
5117 error("synth_mixer(): !buffer \n");
5118- }
5119
5120 #if 0
5121 {
5122@@ -509,10 +505,24 @@
5123 #endif
5124
5125 if (pcmout_stereo) {
5126- YM3812UpdateOne(ym3812_L, ptr, count, 1);
5127- YM3812UpdateOne(ym3812_R, ptr + 1, count, 1);
5128+ int16 buffer[512];
5129+
5130+ while (count > 0) {
5131+ int process = count > ARRAYSIZE(buffer) ? ARRAYSIZE(buffer) : count;
5132+ count -= process;
5133+
5134+ YM3812UpdateOne(ym3812_L, buffer, process);
5135+ for (int i = 0; i < process; ++i)
5136+ ptr[(i << 1) + 0] = buffer[i];
5137+
5138+ YM3812UpdateOne(ym3812_R, buffer, process);
5139+ for (int i = 0; i < process; ++i)
5140+ ptr[(i << 1) + 1] = buffer[i];
5141+
5142+ ptr += (count << 1);
5143+ }
5144 } else {
5145- YM3812UpdateOne(ym3812_L, ptr, count, 0);
5146+ YM3812UpdateOne(ym3812_L, ptr, count);
5147 }
5148 }
5149
5150@@ -533,10 +543,7 @@
5151 for (i = 48; i < 96; i++)
5152 make_sbi((adlib_def *)(data_ptr + 2 + (28 * i)), adlib_sbi[i]);
5153
5154- OPLBuildTables(FMOPL_ENV_BITS_HQ, FMOPL_EG_ENT_HQ);
5155-
5156- if (!(ym3812_L = OPLCreate(OPL_TYPE_YM3812, OPL_INTERNAL_FREQ, SAMPLE_RATE)) ||
5157- !(ym3812_R = OPLCreate(OPL_TYPE_YM3812, OPL_INTERNAL_FREQ, SAMPLE_RATE))) {
5158+ if (!(ym3812_L = makeAdlibOPL(SAMPLE_RATE)) || !(ym3812_R = makeAdlibOPL(SAMPLE_RATE))) {
5159 sciprintf("[sfx:seq:opl2] Failure: Emulator init failed!\n");
5160 return SFX_ERROR;
5161 }
5162@@ -549,12 +556,10 @@
5163
5164
5165 static void opl2_exit(sfx_softseq_t *self) {
5166- FM_OPL *opl = ym3812_L;
5167+ OPLDestroy(ym3812_L);
5168 ym3812_L = NULL;
5169- OPLDestroy(opl);
5170- opl = ym3812_R;
5171+ OPLDestroy(ym3812_R);
5172 ym3812_R = NULL;
5173- OPLDestroy(opl);
5174
5175 // XXX deregister with pcm layer.
5176 }