1 /* ScummVM - Graphic Adventure Engine
2 *
3 * ScummVM is the legal property of its developers, whose names
4 * are too numerous to list here. Please refer to the COPYRIGHT
5 * file distributed with this source distribution.
6 *
7 * This program is free software; you can redistribute it and/or
8 * modify it under the terms of the GNU General Public License
9 * as published by the Free Software Foundation; either version 2
10 * of the License, or (at your option) any later version.
11 *
12 * This program is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 * GNU General Public License for more details.
16 *
17 * You should have received a copy of the GNU General Public License
18 * along with this program; if not, write to the Free Software
19 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
20 *
21 * LGPL licensed version of MAMEs fmopl (V0.37a modified) by
22 * Tatsuyuki Satoh. Included from LGPL'ed AdPlug.
23 *
24 */
25
26 #include <stdio.h>
27 #include <stdlib.h>
28 #include <string.h>
29 #include <stdarg.h>
30 #include <math.h>
31
32 #include "mame.h"
33
34 #include "audio/mixer.h"
35 #include "common/system.h"
36 #include "common/textconsole.h"
37 #include "common/util.h"
38
39 #if defined(_WIN32_WCE) || defined(__SYMBIAN32__) || defined(__GP32__) || defined(GP2X) || defined(__MAEMO__) || defined(__DS__) || defined(__MINT__) || defined(__N64__)
40 #include "common/config-manager.h"
41 #endif
42
43 #if defined(__DS__)
44 #include "dsmain.h"
45 #endif
46
47 namespace OPL {
48 namespace MAME {
49
~OPL()50 OPL::~OPL() {
51 stop();
52 MAME::OPLDestroy(_opl);
53 _opl = 0;
54 }
55
init()56 bool OPL::init() {
57 if (_opl) {
58 stopCallbacks();
59 MAME::OPLDestroy(_opl);
60 }
61
62 _opl = MAME::makeAdLibOPL(g_system->getMixer()->getOutputRate());
63
64 return (_opl != 0);
65 }
66
reset()67 void OPL::reset() {
68 MAME::OPLResetChip(_opl);
69 }
70
write(int a,int v)71 void OPL::write(int a, int v) {
72 MAME::OPLWrite(_opl, a, v);
73 }
74
read(int a)75 byte OPL::read(int a) {
76 return MAME::OPLRead(_opl, a);
77 }
78
writeReg(int r,int v)79 void OPL::writeReg(int r, int v) {
80 MAME::OPLWriteReg(_opl, r, v);
81 }
82
generateSamples(int16 * buffer,int length)83 void OPL::generateSamples(int16 *buffer, int length) {
84 MAME::YM3812UpdateOne(_opl, buffer, length);
85 }
86
87 /* -------------------- preliminary define section --------------------- */
88 /* attack/decay rate time rate */
89 #define OPL_ARRATE 141280 /* RATE 4 = 2826.24ms @ 3.6MHz */
90 #define OPL_DRRATE 1956000 /* RATE 4 = 39280.64ms @ 3.6MHz */
91
92 #define FREQ_BITS 24 /* frequency turn */
93
94 /* counter bits = 20 , octerve 7 */
95 #define FREQ_RATE (1<<(FREQ_BITS-20))
96 #define TL_BITS (FREQ_BITS+2)
97
98 /* final output shift , limit minimum and maximum */
99 #define OPL_OUTSB (TL_BITS+3-16) /* OPL output final shift 16bit */
100 #define OPL_MAXOUT (0x7fff<<OPL_OUTSB)
101 #define OPL_MINOUT (-(0x8000<<OPL_OUTSB))
102
103 /* -------------------- quality selection --------------------- */
104
105 /* sinwave entries */
106 /* used static memory = SIN_ENT * 4 (byte) */
107 #ifdef __DS__
108 #define SIN_ENT_SHIFT 8
109 #else
110 #define SIN_ENT_SHIFT 11
111 #endif
112 #define SIN_ENT (1<<SIN_ENT_SHIFT)
113
114 /* output level entries (envelope,sinwave) */
115 /* envelope counter lower bits */
116 int ENV_BITS;
117 /* envelope output entries */
118 int EG_ENT;
119
120 /* used dynamic memory = EG_ENT*4*4(byte)or EG_ENT*6*4(byte) */
121 /* used static memory = EG_ENT*4 (byte) */
122 int EG_OFF; /* OFF */
123 int EG_DED;
124 int EG_DST; /* DECAY START */
125 int EG_AED;
126 #define EG_AST 0 /* ATTACK START */
127
128 #define EG_STEP (96.0/EG_ENT) /* OPL is 0.1875 dB step */
129
130 /* LFO table entries */
131 #define VIB_ENT 512
132 #define VIB_SHIFT (32-9)
133 #define AMS_ENT 512
134 #define AMS_SHIFT (32-9)
135
136 #define VIB_RATE_SHIFT 8
137 #define VIB_RATE (1<<VIB_RATE_SHIFT)
138
139 /* -------------------- local defines , macros --------------------- */
140
141 /* register number to channel number , slot offset */
142 #define SLOT1 0
143 #define SLOT2 1
144
145 /* envelope phase */
146 #define ENV_MOD_RR 0x00
147 #define ENV_MOD_DR 0x01
148 #define ENV_MOD_AR 0x02
149
150 /* -------------------- tables --------------------- */
151 static const int slot_array[32] = {
152 0, 2, 4, 1, 3, 5,-1,-1,
153 6, 8,10, 7, 9,11,-1,-1,
154 12,14,16,13,15,17,-1,-1,
155 -1,-1,-1,-1,-1,-1,-1,-1
156 };
157
158 static uint KSL_TABLE[8 * 16];
159
160 static const double KSL_TABLE_SEED[8 * 16] = {
161 /* OCT 0 */
162 0.000, 0.000, 0.000, 0.000,
163 0.000, 0.000, 0.000, 0.000,
164 0.000, 0.000, 0.000, 0.000,
165 0.000, 0.000, 0.000, 0.000,
166 /* OCT 1 */
167 0.000, 0.000, 0.000, 0.000,
168 0.000, 0.000, 0.000, 0.000,
169 0.000, 0.750, 1.125, 1.500,
170 1.875, 2.250, 2.625, 3.000,
171 /* OCT 2 */
172 0.000, 0.000, 0.000, 0.000,
173 0.000, 1.125, 1.875, 2.625,
174 3.000, 3.750, 4.125, 4.500,
175 4.875, 5.250, 5.625, 6.000,
176 /* OCT 3 */
177 0.000, 0.000, 0.000, 1.875,
178 3.000, 4.125, 4.875, 5.625,
179 6.000, 6.750, 7.125, 7.500,
180 7.875, 8.250, 8.625, 9.000,
181 /* OCT 4 */
182 0.000, 0.000, 3.000, 4.875,
183 6.000, 7.125, 7.875, 8.625,
184 9.000, 9.750, 10.125, 10.500,
185 10.875, 11.250, 11.625, 12.000,
186 /* OCT 5 */
187 0.000, 3.000, 6.000, 7.875,
188 9.000, 10.125, 10.875, 11.625,
189 12.000, 12.750, 13.125, 13.500,
190 13.875, 14.250, 14.625, 15.000,
191 /* OCT 6 */
192 0.000, 6.000, 9.000, 10.875,
193 12.000, 13.125, 13.875, 14.625,
194 15.000, 15.750, 16.125, 16.500,
195 16.875, 17.250, 17.625, 18.000,
196 /* OCT 7 */
197 0.000, 9.000, 12.000, 13.875,
198 15.000, 16.125, 16.875, 17.625,
199 18.000, 18.750, 19.125, 19.500,
200 19.875, 20.250, 20.625, 21.000
201 };
202
203 /* sustain level table (3db per step) */
204 /* 0 - 15: 0, 3, 6, 9,12,15,18,21,24,27,30,33,36,39,42,93 (dB)*/
205
206 static int SL_TABLE[16];
207
208 static const uint SL_TABLE_SEED[16] = {
209 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 31
210 };
211
212 #define TL_MAX (EG_ENT * 2) /* limit(tl + ksr + envelope) + sinwave */
213 /* TotalLevel : 48 24 12 6 3 1.5 0.75 (dB) */
214 /* TL_TABLE[ 0 to TL_MAX ] : plus section */
215 /* TL_TABLE[ TL_MAX to TL_MAX+TL_MAX-1 ] : minus section */
216 static int *TL_TABLE;
217
218 /* pointers to TL_TABLE with sinwave output offset */
219 static int **SIN_TABLE;
220
221 /* LFO table */
222 static int *AMS_TABLE;
223 static int *VIB_TABLE;
224
225 /* envelope output curve table */
226 /* attack + decay + OFF */
227 //static int ENV_CURVE[2*EG_ENT+1];
228 //static int ENV_CURVE[2 * 4096 + 1]; // to keep it static ...
229 static int *ENV_CURVE;
230
231
232 /* multiple table */
233 #define ML(a) (uint)(a * 2)
234 static const uint MUL_TABLE[16]= {
235 /* 1/2, 1, 2, 3, 4, 5, 6, 7, 8, 9,10,11,12,13,14,15 */
236 ML(0.50), ML(1.00), ML(2.00), ML(3.00), ML(4.00), ML(5.00), ML(6.00), ML(7.00),
237 ML(8.00), ML(9.00), ML(10.00), ML(10.00),ML(12.00),ML(12.00),ML(15.00),ML(15.00)
238 };
239 #undef ML
240
241 /* dummy attack / decay rate ( when rate == 0 ) */
242 static int RATE_0[16]=
243 {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0};
244
245 /* -------------------- static state --------------------- */
246
247 /* lock level of common table */
248 static int num_lock = 0;
249
250 /* work table */
251 static void *cur_chip = NULL; /* current chip point */
252 /* currenct chip state */
253 /* static OPLSAMPLE *bufL,*bufR; */
254 static OPL_CH *S_CH;
255 static OPL_CH *E_CH;
256 OPL_SLOT *SLOT7_1, *SLOT7_2, *SLOT8_1, *SLOT8_2;
257
258 static int outd[1];
259 static int ams;
260 static int vib;
261 int *ams_table;
262 int *vib_table;
263 static int amsIncr;
264 static int vibIncr;
265 static int feedback2; /* connect for SLOT 2 */
266
267 /* --------------------- rebuild tables ------------------- */
268
269 #define SC_KSL(mydb) ((uint) (mydb / (EG_STEP / 2)))
270 #define SC_SL(db) (int)(db * ((3 / EG_STEP) * (1 << ENV_BITS))) + EG_DST
271
OPLBuildTables(int ENV_BITS_PARAM,int EG_ENT_PARAM)272 void OPLBuildTables(int ENV_BITS_PARAM, int EG_ENT_PARAM) {
273 int i;
274
275 ENV_BITS = ENV_BITS_PARAM;
276 EG_ENT = EG_ENT_PARAM;
277 EG_OFF = ((2 * EG_ENT)<<ENV_BITS); /* OFF */
278 EG_DED = EG_OFF;
279 EG_DST = (EG_ENT << ENV_BITS); /* DECAY START */
280 EG_AED = EG_DST;
281 //EG_STEP = (96.0/EG_ENT);
282
283 for (i = 0; i < ARRAYSIZE(KSL_TABLE_SEED); i++)
284 KSL_TABLE[i] = SC_KSL(KSL_TABLE_SEED[i]);
285
286 for (i = 0; i < ARRAYSIZE(SL_TABLE_SEED); i++)
287 SL_TABLE[i] = SC_SL(SL_TABLE_SEED[i]);
288 }
289
290 #undef SC_KSL
291 #undef SC_SL
292
293 /* --------------------- subroutines --------------------- */
294
295 /* status set and IRQ handling */
OPL_STATUS_SET(FM_OPL * OPL,int flag)296 inline void OPL_STATUS_SET(FM_OPL *OPL, int flag) {
297 /* set status flag */
298 OPL->status |= flag;
299 if (!(OPL->status & 0x80)) {
300 if (OPL->status & OPL->statusmask) { /* IRQ on */
301 OPL->status |= 0x80;
302 /* callback user interrupt handler (IRQ is OFF to ON) */
303 if (OPL->IRQHandler)
304 (OPL->IRQHandler)(OPL->IRQParam,1);
305 }
306 }
307 }
308
309 /* status reset and IRQ handling */
OPL_STATUS_RESET(FM_OPL * OPL,int flag)310 inline void OPL_STATUS_RESET(FM_OPL *OPL, int flag) {
311 /* reset status flag */
312 OPL->status &= ~flag;
313 if ((OPL->status & 0x80)) {
314 if (!(OPL->status & OPL->statusmask)) {
315 OPL->status &= 0x7f;
316 /* callback user interrupt handler (IRQ is ON to OFF) */
317 if (OPL->IRQHandler) (OPL->IRQHandler)(OPL->IRQParam,0);
318 }
319 }
320 }
321
322 /* IRQ mask set */
OPL_STATUSMASK_SET(FM_OPL * OPL,int flag)323 inline void OPL_STATUSMASK_SET(FM_OPL *OPL, int flag) {
324 OPL->statusmask = flag;
325 /* IRQ handling check */
326 OPL_STATUS_SET(OPL,0);
327 OPL_STATUS_RESET(OPL,0);
328 }
329
330 /* ----- key on ----- */
OPL_KEYON(OPL_SLOT * SLOT)331 inline void OPL_KEYON(OPL_SLOT *SLOT) {
332 /* sin wave restart */
333 SLOT->Cnt = 0;
334 /* set attack */
335 SLOT->evm = ENV_MOD_AR;
336 SLOT->evs = SLOT->evsa;
337 SLOT->evc = EG_AST;
338 SLOT->eve = EG_AED;
339 }
340
341 /* ----- key off ----- */
OPL_KEYOFF(OPL_SLOT * SLOT)342 inline void OPL_KEYOFF(OPL_SLOT *SLOT) {
343 if (SLOT->evm > ENV_MOD_RR) {
344 /* set envelope counter from envleope output */
345
346 // WORKAROUND: The Kyra engine does something very strange when
347 // starting a new song. For each channel:
348 //
349 // * The release rate is set to "fastest".
350 // * Any note is keyed off.
351 // * A very low-frequency note is keyed on.
352 //
353 // Usually, what happens next is that the real notes is keyed
354 // on immediately, in which case there's no problem.
355 //
356 // However, if the note is again keyed off (because the channel
357 // begins on a rest rather than a note), the envelope counter
358 // was moved from the very lowest point on the attack curve to
359 // the very highest point on the release curve.
360 //
361 // Again, this might not be a problem, if the release rate is
362 // still set to "fastest". But in many cases, it had already
363 // been increased. And, possibly because of inaccuracies in the
364 // envelope generator, that would cause the note to "fade out"
365 // for quite a long time.
366 //
367 // What we really need is a way to find the correct starting
368 // point for the envelope counter, and that may be what the
369 // commented-out line below is meant to do. For now, simply
370 // handle the pathological case.
371
372 if (SLOT->evm == ENV_MOD_AR && SLOT->evc == EG_AST)
373 SLOT->evc = EG_DED;
374 else if (!(SLOT->evc & EG_DST))
375 //SLOT->evc = (ENV_CURVE[SLOT->evc>>ENV_BITS]<<ENV_BITS) + EG_DST;
376 SLOT->evc = EG_DST;
377 SLOT->eve = EG_DED;
378 SLOT->evs = SLOT->evsr;
379 SLOT->evm = ENV_MOD_RR;
380 }
381 }
382
383 /* ---------- calcrate Envelope Generator & Phase Generator ---------- */
384
385 /* return : envelope output */
OPL_CALC_SLOT(OPL_SLOT * SLOT)386 inline uint OPL_CALC_SLOT(OPL_SLOT *SLOT) {
387 /* calcrate envelope generator */
388 if ((SLOT->evc += SLOT->evs) >= SLOT->eve) {
389 switch (SLOT->evm) {
390 case ENV_MOD_AR: /* ATTACK -> DECAY1 */
391 /* next DR */
392 SLOT->evm = ENV_MOD_DR;
393 SLOT->evc = EG_DST;
394 SLOT->eve = SLOT->SL;
395 SLOT->evs = SLOT->evsd;
396 break;
397 case ENV_MOD_DR: /* DECAY -> SL or RR */
398 SLOT->evc = SLOT->SL;
399 SLOT->eve = EG_DED;
400 if (SLOT->eg_typ) {
401 SLOT->evs = 0;
402 } else {
403 SLOT->evm = ENV_MOD_RR;
404 SLOT->evs = SLOT->evsr;
405 }
406 break;
407 case ENV_MOD_RR: /* RR -> OFF */
408 SLOT->evc = EG_OFF;
409 SLOT->eve = EG_OFF + 1;
410 SLOT->evs = 0;
411 break;
412 }
413 }
414 /* calcrate envelope */
415 return SLOT->TLL + ENV_CURVE[SLOT->evc>>ENV_BITS] + (SLOT->ams ? ams : 0);
416 }
417
418 /* set algorythm connection */
set_algorythm(OPL_CH * CH)419 static void set_algorythm(OPL_CH *CH) {
420 int *carrier = &outd[0];
421 CH->connect1 = CH->CON ? carrier : &feedback2;
422 CH->connect2 = carrier;
423 }
424
425 /* ---------- frequency counter for operater update ---------- */
CALC_FCSLOT(OPL_CH * CH,OPL_SLOT * SLOT)426 inline void CALC_FCSLOT(OPL_CH *CH, OPL_SLOT *SLOT) {
427 int ksr;
428
429 /* frequency step counter */
430 SLOT->Incr = CH->fc * SLOT->mul;
431 ksr = CH->kcode >> SLOT->KSR;
432
433 if (SLOT->ksr != ksr) {
434 SLOT->ksr = ksr;
435 /* attack , decay rate recalcration */
436 SLOT->evsa = SLOT->AR[ksr];
437 SLOT->evsd = SLOT->DR[ksr];
438 SLOT->evsr = SLOT->RR[ksr];
439 }
440 SLOT->TLL = SLOT->TL + (CH->ksl_base>>SLOT->ksl);
441 }
442
443 /* set multi,am,vib,EG-TYP,KSR,mul */
set_mul(FM_OPL * OPL,int slot,int v)444 inline void set_mul(FM_OPL *OPL, int slot, int v) {
445 OPL_CH *CH = &OPL->P_CH[slot>>1];
446 OPL_SLOT *SLOT = &CH->SLOT[slot & 1];
447
448 SLOT->mul = MUL_TABLE[v & 0x0f];
449 SLOT->KSR = (v & 0x10) ? 0 : 2;
450 SLOT->eg_typ = (v & 0x20) >> 5;
451 SLOT->vib = (v & 0x40);
452 SLOT->ams = (v & 0x80);
453 CALC_FCSLOT(CH, SLOT);
454 }
455
456 /* set ksl & tl */
set_ksl_tl(FM_OPL * OPL,int slot,int v)457 inline void set_ksl_tl(FM_OPL *OPL, int slot, int v) {
458 OPL_CH *CH = &OPL->P_CH[slot>>1];
459 OPL_SLOT *SLOT = &CH->SLOT[slot & 1];
460 int ksl = v >> 6; /* 0 / 1.5 / 3 / 6 db/OCT */
461
462 SLOT->ksl = ksl ? 3-ksl : 31;
463 SLOT->TL = (int)((v & 0x3f) * (0.75 / EG_STEP)); /* 0.75db step */
464
465 if (!(OPL->mode & 0x80)) { /* not CSM latch total level */
466 SLOT->TLL = SLOT->TL + (CH->ksl_base >> SLOT->ksl);
467 }
468 }
469
470 /* set attack rate & decay rate */
set_ar_dr(FM_OPL * OPL,int slot,int v)471 inline void set_ar_dr(FM_OPL *OPL, int slot, int v) {
472 OPL_CH *CH = &OPL->P_CH[slot>>1];
473 OPL_SLOT *SLOT = &CH->SLOT[slot & 1];
474 int ar = v >> 4;
475 int dr = v & 0x0f;
476
477 SLOT->AR = ar ? &OPL->AR_TABLE[ar << 2] : RATE_0;
478 SLOT->evsa = SLOT->AR[SLOT->ksr];
479 if (SLOT->evm == ENV_MOD_AR)
480 SLOT->evs = SLOT->evsa;
481
482 SLOT->DR = dr ? &OPL->DR_TABLE[dr<<2] : RATE_0;
483 SLOT->evsd = SLOT->DR[SLOT->ksr];
484 if (SLOT->evm == ENV_MOD_DR)
485 SLOT->evs = SLOT->evsd;
486 }
487
488 /* set sustain level & release rate */
set_sl_rr(FM_OPL * OPL,int slot,int v)489 inline void set_sl_rr(FM_OPL *OPL, int slot, int v) {
490 OPL_CH *CH = &OPL->P_CH[slot>>1];
491 OPL_SLOT *SLOT = &CH->SLOT[slot & 1];
492 int sl = v >> 4;
493 int rr = v & 0x0f;
494
495 SLOT->SL = SL_TABLE[sl];
496 if (SLOT->evm == ENV_MOD_DR)
497 SLOT->eve = SLOT->SL;
498 SLOT->RR = &OPL->DR_TABLE[rr<<2];
499 SLOT->evsr = SLOT->RR[SLOT->ksr];
500 if (SLOT->evm == ENV_MOD_RR)
501 SLOT->evs = SLOT->evsr;
502 }
503
504 /* operator output calcrator */
505
506 #define OP_OUT(slot,env,con) slot->wavetable[((slot->Cnt + con)>>(24-SIN_ENT_SHIFT)) & (SIN_ENT-1)][env]
507 /* ---------- calcrate one of channel ---------- */
OPL_CALC_CH(OPL_CH * CH)508 inline void OPL_CALC_CH(OPL_CH *CH) {
509 uint env_out;
510 OPL_SLOT *SLOT;
511
512 feedback2 = 0;
513 /* SLOT 1 */
514 SLOT = &CH->SLOT[SLOT1];
515 env_out=OPL_CALC_SLOT(SLOT);
516 if (env_out < (uint)(EG_ENT - 1)) {
517 /* PG */
518 if (SLOT->vib)
519 SLOT->Cnt += (SLOT->Incr * vib) >> VIB_RATE_SHIFT;
520 else
521 SLOT->Cnt += SLOT->Incr;
522 /* connection */
523 if (CH->FB) {
524 int feedback1 = (CH->op1_out[0] + CH->op1_out[1]) >> CH->FB;
525 CH->op1_out[1] = CH->op1_out[0];
526 *CH->connect1 += CH->op1_out[0] = OP_OUT(SLOT, env_out, feedback1);
527 } else {
528 *CH->connect1 += OP_OUT(SLOT, env_out, 0);
529 }
530 } else {
531 CH->op1_out[1] = CH->op1_out[0];
532 CH->op1_out[0] = 0;
533 }
534 /* SLOT 2 */
535 SLOT = &CH->SLOT[SLOT2];
536 env_out=OPL_CALC_SLOT(SLOT);
537 if (env_out < (uint)(EG_ENT - 1)) {
538 /* PG */
539 if (SLOT->vib)
540 SLOT->Cnt += (SLOT->Incr * vib) >> VIB_RATE_SHIFT;
541 else
542 SLOT->Cnt += SLOT->Incr;
543 /* connection */
544 outd[0] += OP_OUT(SLOT, env_out, feedback2);
545 }
546 }
547
548 /* ---------- calcrate rythm block ---------- */
549 #define WHITE_NOISE_db 6.0
OPL_CALC_RH(FM_OPL * OPL,OPL_CH * CH)550 inline void OPL_CALC_RH(FM_OPL *OPL, OPL_CH *CH) {
551 uint env_tam, env_sd, env_top, env_hh;
552 // This code used to do int(OPL->rnd.getRandomBit() * (WHITE_NOISE_db / EG_STEP)),
553 // but EG_STEP = 96.0/EG_ENT, and WHITE_NOISE_db=6.0. So, that's equivalent to
554 // int(OPL->rnd.getRandomBit() * EG_ENT/16). We know that EG_ENT is 4096, or 1024,
555 // or 128, so we can safely avoid any FP ops.
556 int whitenoise = OPL->rnd->getRandomBit() * (EG_ENT>>4);
557
558 int tone8;
559
560 OPL_SLOT *SLOT;
561 int env_out;
562
563 /* BD : same as FM serial mode and output level is large */
564 feedback2 = 0;
565 /* SLOT 1 */
566 SLOT = &CH[6].SLOT[SLOT1];
567 env_out = OPL_CALC_SLOT(SLOT);
568 if (env_out < EG_ENT-1) {
569 /* PG */
570 if (SLOT->vib)
571 SLOT->Cnt += (SLOT->Incr * vib) >> VIB_RATE_SHIFT;
572 else
573 SLOT->Cnt += SLOT->Incr;
574 /* connection */
575 if (CH[6].FB) {
576 int feedback1 = (CH[6].op1_out[0] + CH[6].op1_out[1]) >> CH[6].FB;
577 CH[6].op1_out[1] = CH[6].op1_out[0];
578 feedback2 = CH[6].op1_out[0] = OP_OUT(SLOT, env_out, feedback1);
579 }
580 else {
581 feedback2 = OP_OUT(SLOT, env_out, 0);
582 }
583 } else {
584 feedback2 = 0;
585 CH[6].op1_out[1] = CH[6].op1_out[0];
586 CH[6].op1_out[0] = 0;
587 }
588 /* SLOT 2 */
589 SLOT = &CH[6].SLOT[SLOT2];
590 env_out = OPL_CALC_SLOT(SLOT);
591 if (env_out < EG_ENT-1) {
592 /* PG */
593 if (SLOT->vib)
594 SLOT->Cnt += (SLOT->Incr * vib) >> VIB_RATE_SHIFT;
595 else
596 SLOT->Cnt += SLOT->Incr;
597 /* connection */
598 outd[0] += OP_OUT(SLOT, env_out, feedback2) * 2;
599 }
600
601 // SD (17) = mul14[fnum7] + white noise
602 // TAM (15) = mul15[fnum8]
603 // TOP (18) = fnum6(mul18[fnum8]+whitenoise)
604 // HH (14) = fnum7(mul18[fnum8]+whitenoise) + white noise
605 env_sd = OPL_CALC_SLOT(SLOT7_2) + whitenoise;
606 env_tam =OPL_CALC_SLOT(SLOT8_1);
607 env_top = OPL_CALC_SLOT(SLOT8_2);
608 env_hh = OPL_CALC_SLOT(SLOT7_1) + whitenoise;
609
610 /* PG */
611 if (SLOT7_1->vib)
612 SLOT7_1->Cnt += (SLOT7_1->Incr * vib) >> (VIB_RATE_SHIFT-1);
613 else
614 SLOT7_1->Cnt += 2 * SLOT7_1->Incr;
615 if (SLOT7_2->vib)
616 SLOT7_2->Cnt += (CH[7].fc * vib) >> (VIB_RATE_SHIFT-3);
617 else
618 SLOT7_2->Cnt += (CH[7].fc * 8);
619 if (SLOT8_1->vib)
620 SLOT8_1->Cnt += (SLOT8_1->Incr * vib) >> VIB_RATE_SHIFT;
621 else
622 SLOT8_1->Cnt += SLOT8_1->Incr;
623 if (SLOT8_2->vib)
624 SLOT8_2->Cnt += ((CH[8].fc * 3) * vib) >> (VIB_RATE_SHIFT-4);
625 else
626 SLOT8_2->Cnt += (CH[8].fc * 48);
627
628 tone8 = OP_OUT(SLOT8_2,whitenoise,0 );
629
630 /* SD */
631 if (env_sd < (uint)(EG_ENT - 1))
632 outd[0] += OP_OUT(SLOT7_1, env_sd, 0) * 8;
633 /* TAM */
634 if (env_tam < (uint)(EG_ENT - 1))
635 outd[0] += OP_OUT(SLOT8_1, env_tam, 0) * 2;
636 /* TOP-CY */
637 if (env_top < (uint)(EG_ENT - 1))
638 outd[0] += OP_OUT(SLOT7_2, env_top, tone8) * 2;
639 /* HH */
640 if (env_hh < (uint)(EG_ENT-1))
641 outd[0] += OP_OUT(SLOT7_2, env_hh, tone8) * 2;
642 }
643
644 /* ----------- initialize time tabls ----------- */
init_timetables(FM_OPL * OPL,int ARRATE,int DRRATE)645 static void init_timetables(FM_OPL *OPL, int ARRATE, int DRRATE) {
646 int i;
647 double rate;
648
649 /* make attack rate & decay rate tables */
650 for (i = 0; i < 4; i++)
651 OPL->AR_TABLE[i] = OPL->DR_TABLE[i] = 0;
652 for (i = 4; i <= 60; i++) {
653 rate = OPL->freqbase; /* frequency rate */
654 if (i < 60)
655 rate *= 1.0 + (i & 3) * 0.25; /* b0-1 : x1 , x1.25 , x1.5 , x1.75 */
656 rate *= 1 << ((i >> 2) - 1); /* b2-5 : shift bit */
657 rate *= (double)(EG_ENT << ENV_BITS);
658 OPL->AR_TABLE[i] = (int)(rate / ARRATE);
659 OPL->DR_TABLE[i] = (int)(rate / DRRATE);
660 }
661 for (i = 60; i < 76; i++) {
662 OPL->AR_TABLE[i] = EG_AED-1;
663 OPL->DR_TABLE[i] = OPL->DR_TABLE[60];
664 }
665 }
666
667 /* ---------- generic table initialize ---------- */
OPLOpenTable(void)668 static int OPLOpenTable(void) {
669 int s,t;
670 double rate;
671 int i,j;
672 double pom;
673
674 #ifdef __DS__
675 DS::fastRamReset();
676
677 TL_TABLE = (int *) DS::fastRamAlloc(TL_MAX * 2 * sizeof(int *));
678 SIN_TABLE = (int **) DS::fastRamAlloc(SIN_ENT * 4 * sizeof(int *));
679 #else
680
681 /* allocate dynamic tables */
682 if ((TL_TABLE = (int *)malloc(TL_MAX * 2 * sizeof(int))) == NULL)
683 return 0;
684
685 if ((SIN_TABLE = (int **)malloc(SIN_ENT * 4 * sizeof(int *))) == NULL) {
686 free(TL_TABLE);
687 return 0;
688 }
689 #endif
690
691 if ((AMS_TABLE = (int *)malloc(AMS_ENT * 2 * sizeof(int))) == NULL) {
692 free(TL_TABLE);
693 free(SIN_TABLE);
694 return 0;
695 }
696
697 if ((VIB_TABLE = (int *)malloc(VIB_ENT * 2 * sizeof(int))) == NULL) {
698 free(TL_TABLE);
699 free(SIN_TABLE);
700 free(AMS_TABLE);
701 return 0;
702 }
703 /* make total level table */
704 for (t = 0; t < EG_ENT - 1; t++) {
705 rate = ((1 << TL_BITS) - 1) / pow(10.0, EG_STEP * t / 20); /* dB -> voltage */
706 TL_TABLE[ t] = (int)rate;
707 TL_TABLE[TL_MAX + t] = -TL_TABLE[t];
708 }
709 /* fill volume off area */
710 for (t = EG_ENT - 1; t < TL_MAX; t++) {
711 TL_TABLE[t] = TL_TABLE[TL_MAX + t] = 0;
712 }
713
714 /* make sinwave table (total level offet) */
715 /* degree 0 = degree 180 = off */
716 SIN_TABLE[0] = SIN_TABLE[SIN_ENT /2 ] = &TL_TABLE[EG_ENT - 1];
717 for (s = 1;s <= SIN_ENT / 4; s++) {
718 pom = sin(2 * M_PI * s / SIN_ENT); /* sin */
719 pom = 20 * log10(1 / pom); /* decibel */
720 j = int(pom / EG_STEP); /* TL_TABLE steps */
721
722 /* degree 0 - 90 , degree 180 - 90 : plus section */
723 SIN_TABLE[ s] = SIN_TABLE[SIN_ENT / 2 - s] = &TL_TABLE[j];
724 /* degree 180 - 270 , degree 360 - 270 : minus section */
725 SIN_TABLE[SIN_ENT / 2 + s] = SIN_TABLE[SIN_ENT - s] = &TL_TABLE[TL_MAX + j];
726 }
727 for (s = 0;s < SIN_ENT; s++) {
728 SIN_TABLE[SIN_ENT * 1 + s] = s < (SIN_ENT / 2) ? SIN_TABLE[s] : &TL_TABLE[EG_ENT];
729 SIN_TABLE[SIN_ENT * 2 + s] = SIN_TABLE[s % (SIN_ENT / 2)];
730 SIN_TABLE[SIN_ENT * 3 + s] = (s / (SIN_ENT / 4)) & 1 ? &TL_TABLE[EG_ENT] : SIN_TABLE[SIN_ENT * 2 + s];
731 }
732
733
734 ENV_CURVE = (int *)malloc(sizeof(int) * (2*EG_ENT+1));
735 if (!ENV_CURVE)
736 error("[OPLOpenTable] Cannot allocate memory");
737
738 /* envelope counter -> envelope output table */
739 for (i=0; i < EG_ENT; i++) {
740 /* ATTACK curve */
741 pom = pow(((double)(EG_ENT - 1 - i) / EG_ENT), 8) * EG_ENT;
742 /* if (pom >= EG_ENT) pom = EG_ENT-1; */
743 ENV_CURVE[i] = (int)pom;
744 /* DECAY ,RELEASE curve */
745 ENV_CURVE[(EG_DST >> ENV_BITS) + i]= i;
746 }
747 /* off */
748 ENV_CURVE[EG_OFF >> ENV_BITS]= EG_ENT - 1;
749 /* make LFO ams table */
750 for (i=0; i < AMS_ENT; i++) {
751 pom = (1.0 + sin(2 * M_PI * i / AMS_ENT)) / 2; /* sin */
752 AMS_TABLE[i] = (int)((1.0 / EG_STEP) * pom); /* 1dB */
753 AMS_TABLE[AMS_ENT + i] = (int)((4.8 / EG_STEP) * pom); /* 4.8dB */
754 }
755 /* make LFO vibrate table */
756 for (i=0; i < VIB_ENT; i++) {
757 /* 100cent = 1seminote = 6% ?? */
758 pom = (double)VIB_RATE * 0.06 * sin(2 * M_PI * i / VIB_ENT); /* +-100sect step */
759 VIB_TABLE[i] = (int)(VIB_RATE + (pom * 0.07)); /* +- 7cent */
760 VIB_TABLE[VIB_ENT + i] = (int)(VIB_RATE + (pom * 0.14)); /* +-14cent */
761 }
762 return 1;
763 }
764
OPLCloseTable(void)765 static void OPLCloseTable(void) {
766 #ifndef __DS__
767 free(TL_TABLE);
768 free(SIN_TABLE);
769 #endif
770 free(AMS_TABLE);
771 free(VIB_TABLE);
772 free(ENV_CURVE);
773 }
774
775 /* CSM Key Controll */
CSMKeyControll(OPL_CH * CH)776 inline void CSMKeyControll(OPL_CH *CH) {
777 OPL_SLOT *slot1 = &CH->SLOT[SLOT1];
778 OPL_SLOT *slot2 = &CH->SLOT[SLOT2];
779 /* all key off */
780 OPL_KEYOFF(slot1);
781 OPL_KEYOFF(slot2);
782 /* total level latch */
783 slot1->TLL = slot1->TL + (CH->ksl_base>>slot1->ksl);
784 slot1->TLL = slot1->TL + (CH->ksl_base>>slot1->ksl);
785 /* key on */
786 CH->op1_out[0] = CH->op1_out[1] = 0;
787 OPL_KEYON(slot1);
788 OPL_KEYON(slot2);
789 }
790
791 /* ---------- opl initialize ---------- */
OPL_initalize(FM_OPL * OPL)792 static void OPL_initalize(FM_OPL *OPL) {
793 int fn;
794
795 /* frequency base */
796 OPL->freqbase = (OPL->rate) ? ((double)OPL->clock / OPL->rate) / 72 : 0;
797 /* Timer base time */
798 OPL->TimerBase = 1.0/((double)OPL->clock / 72.0 );
799 /* make time tables */
800 init_timetables(OPL, OPL_ARRATE, OPL_DRRATE);
801 /* make fnumber -> increment counter table */
802 for (fn=0; fn < 1024; fn++) {
803 OPL->FN_TABLE[fn] = (uint)(OPL->freqbase * fn * FREQ_RATE * (1<<7) / 2);
804 }
805 /* LFO freq.table */
806 OPL->amsIncr = (int)(OPL->rate ? (double)AMS_ENT * (1 << AMS_SHIFT) / OPL->rate * 3.7 * ((double)OPL->clock/3600000) : 0);
807 OPL->vibIncr = (int)(OPL->rate ? (double)VIB_ENT * (1 << VIB_SHIFT) / OPL->rate * 6.4 * ((double)OPL->clock/3600000) : 0);
808 }
809
810 /* ---------- write a OPL registers ---------- */
OPLWriteReg(FM_OPL * OPL,int r,int v)811 void OPLWriteReg(FM_OPL *OPL, int r, int v) {
812 OPL_CH *CH;
813 int slot;
814 uint block_fnum;
815
816 switch (r & 0xe0) {
817 case 0x00: /* 00-1f:controll */
818 switch (r & 0x1f) {
819 case 0x01:
820 /* wave selector enable */
821 if (OPL->type&OPL_TYPE_WAVESEL) {
822 OPL->wavesel = v & 0x20;
823 if (!OPL->wavesel) {
824 /* preset compatible mode */
825 int c;
826 for (c = 0; c < OPL->max_ch; c++) {
827 OPL->P_CH[c].SLOT[SLOT1].wavetable = &SIN_TABLE[0];
828 OPL->P_CH[c].SLOT[SLOT2].wavetable = &SIN_TABLE[0];
829 }
830 }
831 }
832 return;
833 case 0x02: /* Timer 1 */
834 OPL->T[0] = (256-v) * 4;
835 break;
836 case 0x03: /* Timer 2 */
837 OPL->T[1] = (256-v) * 16;
838 return;
839 case 0x04: /* IRQ clear / mask and Timer enable */
840 if (v & 0x80) { /* IRQ flag clear */
841 OPL_STATUS_RESET(OPL, 0x7f);
842 } else { /* set IRQ mask ,timer enable*/
843 uint8 st1 = v & 1;
844 uint8 st2 = (v >> 1) & 1;
845 /* IRQRST,T1MSK,t2MSK,EOSMSK,BRMSK,x,ST2,ST1 */
846 OPL_STATUS_RESET(OPL, v & 0x78);
847 OPL_STATUSMASK_SET(OPL,((~v) & 0x78) | 0x01);
848 /* timer 2 */
849 if (OPL->st[1] != st2) {
850 double interval = st2 ? (double)OPL->T[1] * OPL->TimerBase : 0.0;
851 OPL->st[1] = st2;
852 if (OPL->TimerHandler) (OPL->TimerHandler)(OPL->TimerParam + 1, interval);
853 }
854 /* timer 1 */
855 if (OPL->st[0] != st1) {
856 double interval = st1 ? (double)OPL->T[0] * OPL->TimerBase : 0.0;
857 OPL->st[0] = st1;
858 if (OPL->TimerHandler) (OPL->TimerHandler)(OPL->TimerParam + 0, interval);
859 }
860 }
861 return;
862 }
863 break;
864 case 0x20: /* am,vib,ksr,eg type,mul */
865 slot = slot_array[r&0x1f];
866 if (slot == -1)
867 return;
868 set_mul(OPL,slot,v);
869 return;
870 case 0x40:
871 slot = slot_array[r&0x1f];
872 if (slot == -1)
873 return;
874 set_ksl_tl(OPL,slot,v);
875 return;
876 case 0x60:
877 slot = slot_array[r&0x1f];
878 if (slot == -1)
879 return;
880 set_ar_dr(OPL,slot,v);
881 return;
882 case 0x80:
883 slot = slot_array[r&0x1f];
884 if (slot == -1)
885 return;
886 set_sl_rr(OPL,slot,v);
887 return;
888 case 0xa0:
889 switch (r) {
890 case 0xbd:
891 /* amsep,vibdep,r,bd,sd,tom,tc,hh */
892 {
893 uint8 rkey = OPL->rythm ^ v;
894 OPL->ams_table = &AMS_TABLE[v & 0x80 ? AMS_ENT : 0];
895 OPL->vib_table = &VIB_TABLE[v & 0x40 ? VIB_ENT : 0];
896 OPL->rythm = v & 0x3f;
897 if (OPL->rythm & 0x20) {
898 /* BD key on/off */
899 if (rkey & 0x10) {
900 if (v & 0x10) {
901 OPL->P_CH[6].op1_out[0] = OPL->P_CH[6].op1_out[1] = 0;
902 OPL_KEYON(&OPL->P_CH[6].SLOT[SLOT1]);
903 OPL_KEYON(&OPL->P_CH[6].SLOT[SLOT2]);
904 } else {
905 OPL_KEYOFF(&OPL->P_CH[6].SLOT[SLOT1]);
906 OPL_KEYOFF(&OPL->P_CH[6].SLOT[SLOT2]);
907 }
908 }
909 /* SD key on/off */
910 if (rkey & 0x08) {
911 if (v & 0x08)
912 OPL_KEYON(&OPL->P_CH[7].SLOT[SLOT2]);
913 else
914 OPL_KEYOFF(&OPL->P_CH[7].SLOT[SLOT2]);
915 }/* TAM key on/off */
916 if (rkey & 0x04) {
917 if (v & 0x04)
918 OPL_KEYON(&OPL->P_CH[8].SLOT[SLOT1]);
919 else
920 OPL_KEYOFF(&OPL->P_CH[8].SLOT[SLOT1]);
921 }
922 /* TOP-CY key on/off */
923 if (rkey & 0x02) {
924 if (v & 0x02)
925 OPL_KEYON(&OPL->P_CH[8].SLOT[SLOT2]);
926 else
927 OPL_KEYOFF(&OPL->P_CH[8].SLOT[SLOT2]);
928 }
929 /* HH key on/off */
930 if (rkey & 0x01) {
931 if (v & 0x01)
932 OPL_KEYON(&OPL->P_CH[7].SLOT[SLOT1]);
933 else
934 OPL_KEYOFF(&OPL->P_CH[7].SLOT[SLOT1]);
935 }
936 }
937 }
938 return;
939
940 default:
941 break;
942 }
943 /* keyon,block,fnum */
944 if ((r & 0x0f) > 8)
945 return;
946 CH = &OPL->P_CH[r & 0x0f];
947 if (!(r&0x10)) { /* a0-a8 */
948 block_fnum = (CH->block_fnum & 0x1f00) | v;
949 } else { /* b0-b8 */
950 int keyon = (v >> 5) & 1;
951 block_fnum = ((v & 0x1f) << 8) | (CH->block_fnum & 0xff);
952 if (CH->keyon != keyon) {
953 if ((CH->keyon=keyon)) {
954 CH->op1_out[0] = CH->op1_out[1] = 0;
955 OPL_KEYON(&CH->SLOT[SLOT1]);
956 OPL_KEYON(&CH->SLOT[SLOT2]);
957 } else {
958 OPL_KEYOFF(&CH->SLOT[SLOT1]);
959 OPL_KEYOFF(&CH->SLOT[SLOT2]);
960 }
961 }
962 }
963 /* update */
964 if (CH->block_fnum != block_fnum) {
965 int blockRv = 7 - (block_fnum >> 10);
966 int fnum = block_fnum & 0x3ff;
967 CH->block_fnum = block_fnum;
968 CH->ksl_base = KSL_TABLE[block_fnum >> 6];
969 CH->fc = OPL->FN_TABLE[fnum] >> blockRv;
970 CH->kcode = CH->block_fnum >> 9;
971 if ((OPL->mode & 0x40) && CH->block_fnum & 0x100)
972 CH->kcode |=1;
973 CALC_FCSLOT(CH,&CH->SLOT[SLOT1]);
974 CALC_FCSLOT(CH,&CH->SLOT[SLOT2]);
975 }
976 return;
977 case 0xc0:
978 /* FB,C */
979 if ((r & 0x0f) > 8)
980 return;
981 CH = &OPL->P_CH[r&0x0f];
982 {
983 int feedback = (v >> 1) & 7;
984 CH->FB = feedback ? (8 + 1) - feedback : 0;
985 CH->CON = v & 1;
986 set_algorythm(CH);
987 }
988 return;
989 case 0xe0: /* wave type */
990 slot = slot_array[r & 0x1f];
991 if (slot == -1)
992 return;
993 CH = &OPL->P_CH[slot>>1];
994 if (OPL->wavesel) {
995 CH->SLOT[slot&1].wavetable = &SIN_TABLE[(v & 0x03) * SIN_ENT];
996 }
997 return;
998 }
999 }
1000
1001 /* lock/unlock for common table */
OPL_LockTable(void)1002 static int OPL_LockTable(void) {
1003 num_lock++;
1004 if (num_lock>1)
1005 return 0;
1006 /* first time */
1007 cur_chip = NULL;
1008 /* allocate total level table (128kb space) */
1009 if (!OPLOpenTable()) {
1010 num_lock--;
1011 return -1;
1012 }
1013 return 0;
1014 }
1015
OPL_UnLockTable(void)1016 static void OPL_UnLockTable(void) {
1017 if (num_lock)
1018 num_lock--;
1019 if (num_lock)
1020 return;
1021 /* last time */
1022 cur_chip = NULL;
1023 OPLCloseTable();
1024 }
1025
1026 /*******************************************************************************/
1027 /* YM3812 local section */
1028 /*******************************************************************************/
1029
1030 /* ---------- update one of chip ----------- */
YM3812UpdateOne(FM_OPL * OPL,int16 * buffer,int length)1031 void YM3812UpdateOne(FM_OPL *OPL, int16 *buffer, int length) {
1032 int i;
1033 int data;
1034 int16 *buf = buffer;
1035 uint amsCnt = OPL->amsCnt;
1036 uint vibCnt = OPL->vibCnt;
1037 uint8 rythm = OPL->rythm & 0x20;
1038 OPL_CH *CH, *R_CH;
1039
1040
1041 if ((void *)OPL != cur_chip) {
1042 cur_chip = (void *)OPL;
1043 /* channel pointers */
1044 S_CH = OPL->P_CH;
1045 E_CH = &S_CH[9];
1046 /* rythm slot */
1047 SLOT7_1 = &S_CH[7].SLOT[SLOT1];
1048 SLOT7_2 = &S_CH[7].SLOT[SLOT2];
1049 SLOT8_1 = &S_CH[8].SLOT[SLOT1];
1050 SLOT8_2 = &S_CH[8].SLOT[SLOT2];
1051 /* LFO state */
1052 amsIncr = OPL->amsIncr;
1053 vibIncr = OPL->vibIncr;
1054 ams_table = OPL->ams_table;
1055 vib_table = OPL->vib_table;
1056 }
1057 R_CH = rythm ? &S_CH[6] : E_CH;
1058 for (i = 0; i < length; i++) {
1059 /* channel A channel B channel C */
1060 /* LFO */
1061 ams = ams_table[(amsCnt += amsIncr) >> AMS_SHIFT];
1062 vib = vib_table[(vibCnt += vibIncr) >> VIB_SHIFT];
1063 outd[0] = 0;
1064 /* FM part */
1065 for (CH = S_CH; CH < R_CH; CH++)
1066 OPL_CALC_CH(CH);
1067 /* Rythn part */
1068 if (rythm)
1069 OPL_CALC_RH(OPL, S_CH);
1070 /* limit check */
1071 data = CLIP(outd[0], OPL_MINOUT, OPL_MAXOUT);
1072 /* store to sound buffer */
1073 buf[i] = data >> OPL_OUTSB;
1074 }
1075
1076 OPL->amsCnt = amsCnt;
1077 OPL->vibCnt = vibCnt;
1078 }
1079
1080 /* ---------- reset a chip ---------- */
OPLResetChip(FM_OPL * OPL)1081 void OPLResetChip(FM_OPL *OPL) {
1082 int c,s;
1083 int i;
1084
1085 /* reset chip */
1086 OPL->mode = 0; /* normal mode */
1087 OPL_STATUS_RESET(OPL, 0x7f);
1088 /* reset with register write */
1089 OPLWriteReg(OPL, 0x01,0); /* wabesel disable */
1090 OPLWriteReg(OPL, 0x02,0); /* Timer1 */
1091 OPLWriteReg(OPL, 0x03,0); /* Timer2 */
1092 OPLWriteReg(OPL, 0x04,0); /* IRQ mask clear */
1093 for (i = 0xff; i >= 0x20; i--)
1094 OPLWriteReg(OPL,i,0);
1095 /* reset OPerator parameter */
1096 for (c = 0; c < OPL->max_ch; c++) {
1097 OPL_CH *CH = &OPL->P_CH[c];
1098 /* OPL->P_CH[c].PAN = OPN_CENTER; */
1099 for (s = 0; s < 2; s++) {
1100 /* wave table */
1101 CH->SLOT[s].wavetable = &SIN_TABLE[0];
1102 /* CH->SLOT[s].evm = ENV_MOD_RR; */
1103 CH->SLOT[s].evc = EG_OFF;
1104 CH->SLOT[s].eve = EG_OFF + 1;
1105 CH->SLOT[s].evs = 0;
1106 }
1107 }
1108 }
1109
1110 /* ---------- Create a virtual YM3812 ---------- */
1111 /* 'rate' is sampling rate and 'bufsiz' is the size of the */
OPLCreate(int type,int clock,int rate)1112 FM_OPL *OPLCreate(int type, int clock, int rate) {
1113 char *ptr;
1114 FM_OPL *OPL;
1115 int state_size;
1116 int max_ch = 9; /* normaly 9 channels */
1117
1118 if (OPL_LockTable() == -1)
1119 return NULL;
1120 /* allocate OPL state space */
1121 state_size = sizeof(FM_OPL);
1122 state_size += sizeof(OPL_CH) * max_ch;
1123
1124 /* allocate memory block */
1125 ptr = (char *)calloc(state_size, 1);
1126 if (ptr == NULL)
1127 return NULL;
1128
1129 /* clear */
1130 memset(ptr, 0, state_size);
1131 OPL = (FM_OPL *)ptr; ptr += sizeof(FM_OPL);
1132 OPL->P_CH = (OPL_CH *)ptr; ptr += sizeof(OPL_CH) * max_ch;
1133
1134 /* set channel state pointer */
1135 OPL->type = type;
1136 OPL->clock = clock;
1137 OPL->rate = rate;
1138 OPL->max_ch = max_ch;
1139
1140 // Init the random source. Note: We use a fixed name for it here.
1141 // So if multiple FM_OPL objects exist in parallel, then their
1142 // random sources will have an equal name. At least in the
1143 // current EventRecorder implementation, this causes no problems;
1144 // but this is probably not guaranteed.
1145 // Alas, it does not seem worthwhile to bother much with this
1146 // at the time, so I am leaving it as it is.
1147 OPL->rnd = new Common::RandomSource("mame");
1148
1149 /* init grobal tables */
1150 OPL_initalize(OPL);
1151
1152 /* reset chip */
1153 OPLResetChip(OPL);
1154 return OPL;
1155 }
1156
1157 /* ---------- Destroy one of virtual YM3812 ---------- */
OPLDestroy(FM_OPL * OPL)1158 void OPLDestroy(FM_OPL *OPL) {
1159 OPL_UnLockTable();
1160 delete OPL->rnd;
1161 free(OPL);
1162 }
1163
1164 /* ---------- Option handlers ---------- */
OPLSetTimerHandler(FM_OPL * OPL,OPL_TIMERHANDLER TimerHandler,int channelOffset)1165 void OPLSetTimerHandler(FM_OPL *OPL, OPL_TIMERHANDLER TimerHandler,int channelOffset) {
1166 OPL->TimerHandler = TimerHandler;
1167 OPL->TimerParam = channelOffset;
1168 }
1169
OPLSetIRQHandler(FM_OPL * OPL,OPL_IRQHANDLER IRQHandler,int param)1170 void OPLSetIRQHandler(FM_OPL *OPL, OPL_IRQHANDLER IRQHandler, int param) {
1171 OPL->IRQHandler = IRQHandler;
1172 OPL->IRQParam = param;
1173 }
1174
OPLSetUpdateHandler(FM_OPL * OPL,OPL_UPDATEHANDLER UpdateHandler,int param)1175 void OPLSetUpdateHandler(FM_OPL *OPL, OPL_UPDATEHANDLER UpdateHandler,int param) {
1176 OPL->UpdateHandler = UpdateHandler;
1177 OPL->UpdateParam = param;
1178 }
1179
1180 /* ---------- YM3812 I/O interface ---------- */
OPLWrite(FM_OPL * OPL,int a,int v)1181 int OPLWrite(FM_OPL *OPL,int a,int v) {
1182 if (!(a & 1)) { /* address port */
1183 OPL->address = v & 0xff;
1184 } else { /* data port */
1185 if (OPL->UpdateHandler)
1186 OPL->UpdateHandler(OPL->UpdateParam,0);
1187 OPLWriteReg(OPL, OPL->address,v);
1188 }
1189 return OPL->status >> 7;
1190 }
1191
OPLRead(FM_OPL * OPL,int a)1192 unsigned char OPLRead(FM_OPL *OPL,int a) {
1193 if (!(a & 1)) { /* status port */
1194 return OPL->status & (OPL->statusmask | 0x80);
1195 }
1196 /* data port */
1197 switch (OPL->address) {
1198 case 0x05: /* KeyBoard IN */
1199 warning("OPL:read unmapped KEYBOARD port");
1200 return 0;
1201 case 0x19: /* I/O DATA */
1202 warning("OPL:read unmapped I/O port");
1203 return 0;
1204 case 0x1a: /* PCM-DATA */
1205 return 0;
1206 default:
1207 break;
1208 }
1209 return 0;
1210 }
1211
OPLTimerOver(FM_OPL * OPL,int c)1212 int OPLTimerOver(FM_OPL *OPL, int c) {
1213 if (c) { /* Timer B */
1214 OPL_STATUS_SET(OPL, 0x20);
1215 } else { /* Timer A */
1216 OPL_STATUS_SET(OPL, 0x40);
1217 /* CSM mode key,TL controll */
1218 if (OPL->mode & 0x80) { /* CSM mode total level latch and auto key on */
1219 int ch;
1220 if (OPL->UpdateHandler)
1221 OPL->UpdateHandler(OPL->UpdateParam,0);
1222 for (ch = 0; ch < 9; ch++)
1223 CSMKeyControll(&OPL->P_CH[ch]);
1224 }
1225 }
1226 /* reload timer */
1227 if (OPL->TimerHandler)
1228 (OPL->TimerHandler)(OPL->TimerParam + c, (double)OPL->T[c] * OPL->TimerBase);
1229 return OPL->status >> 7;
1230 }
1231
makeAdLibOPL(int rate)1232 FM_OPL *makeAdLibOPL(int rate) {
1233 // We need to emulate one YM3812 chip
1234 int env_bits = FMOPL_ENV_BITS_HQ;
1235 int eg_ent = FMOPL_EG_ENT_HQ;
1236 #if defined(_WIN32_WCE) || defined(__SYMBIAN32__) || defined(__GP32__) || defined(GP2X) || defined(__MAEMO__) || defined(__DS__) || defined(__MINT__) || defined(__N64__)
1237 if (ConfMan.hasKey("FM_high_quality") && ConfMan.getBool("FM_high_quality")) {
1238 env_bits = FMOPL_ENV_BITS_HQ;
1239 eg_ent = FMOPL_EG_ENT_HQ;
1240 } else if (ConfMan.hasKey("FM_medium_quality") && ConfMan.getBool("FM_medium_quality")) {
1241 env_bits = FMOPL_ENV_BITS_MQ;
1242 eg_ent = FMOPL_EG_ENT_MQ;
1243 } else {
1244 env_bits = FMOPL_ENV_BITS_LQ;
1245 eg_ent = FMOPL_EG_ENT_LQ;
1246 }
1247 #endif
1248
1249 OPLBuildTables(env_bits, eg_ent);
1250 return OPLCreate(OPL_TYPE_YM3812, 3579545, rate);
1251 }
1252
1253 } // End of namespace MAME
1254 } // End of namespace OPL
1255