bugfixes, state load for new mode
[picodrive.git] / Pico / sound / ym2612.c
1 /*\r
2 ** This is a bunch of remains of original fm.c from MAME project. All stuff\r
3 ** unrelated to ym2612 was removed, multiple chip support was removed,\r
4 ** some parts of code were slightly rewritten and tied to the emulator.\r
5 **\r
6 ** SSG-EG was also removed, because it's rarely used, Sega2.doc even does not\r
7 ** document it ("proprietary") and tells to write 0 to SSG-EG control register.\r
8 */\r
9 \r
10 /*\r
11 **\r
12 ** File: fm.c -- software implementation of Yamaha FM sound generator\r
13 **\r
14 ** Copyright (C) 2001, 2002, 2003 Jarek Burczynski (bujar at mame dot net)\r
15 ** Copyright (C) 1998 Tatsuyuki Satoh , MultiArcadeMachineEmulator development\r
16 **\r
17 ** Version 1.4 (final beta)\r
18 **\r
19 */\r
20 \r
21 /*\r
22 ** History:\r
23 **\r
24 ** 03-08-2003 Jarek Burczynski:\r
25 **  - fixed YM2608 initial values (after the reset)\r
26 **  - fixed flag and irqmask handling (YM2608)\r
27 **  - fixed BUFRDY flag handling (YM2608)\r
28 **\r
29 ** 14-06-2003 Jarek Burczynski:\r
30 **  - implemented all of the YM2608 status register flags\r
31 **  - implemented support for external memory read/write via YM2608\r
32 **  - implemented support for deltat memory limit register in YM2608 emulation\r
33 **\r
34 ** 22-05-2003 Jarek Burczynski:\r
35 **  - fixed LFO PM calculations (copy&paste bugfix)\r
36 **\r
37 ** 08-05-2003 Jarek Burczynski:\r
38 **  - fixed SSG support\r
39 **\r
40 ** 22-04-2003 Jarek Burczynski:\r
41 **  - implemented 100% correct LFO generator (verified on real YM2610 and YM2608)\r
42 **\r
43 ** 15-04-2003 Jarek Burczynski:\r
44 **  - added support for YM2608's register 0x110 - status mask\r
45 **\r
46 ** 01-12-2002 Jarek Burczynski:\r
47 **  - fixed register addressing in YM2608, YM2610, YM2610B chips. (verified on real YM2608)\r
48 **    The addressing patch used for early Neo-Geo games can be removed now.\r
49 **\r
50 ** 26-11-2002 Jarek Burczynski, Nicola Salmoria:\r
51 **  - recreated YM2608 ADPCM ROM using data from real YM2608's output which leads to:\r
52 **  - added emulation of YM2608 drums.\r
53 **  - output of YM2608 is two times lower now - same as YM2610 (verified on real YM2608)\r
54 **\r
55 ** 16-08-2002 Jarek Burczynski:\r
56 **  - binary exact Envelope Generator (verified on real YM2203);\r
57 **    identical to YM2151\r
58 **  - corrected 'off by one' error in feedback calculations (when feedback is off)\r
59 **  - corrected connection (algorithm) calculation (verified on real YM2203 and YM2610)\r
60 **\r
61 ** 18-12-2001 Jarek Burczynski:\r
62 **  - added SSG-EG support (verified on real YM2203)\r
63 **\r
64 ** 12-08-2001 Jarek Burczynski:\r
65 **  - corrected ym_sin_tab and ym_tl_tab data (verified on real chip)\r
66 **  - corrected feedback calculations (verified on real chip)\r
67 **  - corrected phase generator calculations (verified on real chip)\r
68 **  - corrected envelope generator calculations (verified on real chip)\r
69 **  - corrected FM volume level (YM2610 and YM2610B).\r
70 **  - changed YMxxxUpdateOne() functions (YM2203, YM2608, YM2610, YM2610B, YM2612) :\r
71 **    this was needed to calculate YM2610 FM channels output correctly.\r
72 **    (Each FM channel is calculated as in other chips, but the output of the channel\r
73 **    gets shifted right by one *before* sending to accumulator. That was impossible to do\r
74 **    with previous implementation).\r
75 **\r
76 ** 23-07-2001 Jarek Burczynski, Nicola Salmoria:\r
77 **  - corrected YM2610 ADPCM type A algorithm and tables (verified on real chip)\r
78 **\r
79 ** 11-06-2001 Jarek Burczynski:\r
80 **  - corrected end of sample bug in ADPCMA_calc_cha().\r
81 **    Real YM2610 checks for equality between current and end addresses (only 20 LSB bits).\r
82 **\r
83 ** 08-12-98 hiro-shi:\r
84 ** rename ADPCMA -> ADPCMB, ADPCMB -> ADPCMA\r
85 ** move ROM limit check.(CALC_CH? -> 2610Write1/2)\r
86 ** test program (ADPCMB_TEST)\r
87 ** move ADPCM A/B end check.\r
88 ** ADPCMB repeat flag(no check)\r
89 ** change ADPCM volume rate (8->16) (32->48).\r
90 **\r
91 ** 09-12-98 hiro-shi:\r
92 ** change ADPCM volume. (8->16, 48->64)\r
93 ** replace ym2610 ch0/3 (YM-2610B)\r
94 ** change ADPCM_SHIFT (10->8) missing bank change 0x4000-0xffff.\r
95 ** add ADPCM_SHIFT_MASK\r
96 ** change ADPCMA_DECODE_MIN/MAX.\r
97 */\r
98 \r
99 \r
100 \r
101 \r
102 /************************************************************************/\r
103 /*    comment of hiro-shi(Hiromitsu Shioya)                             */\r
104 /*    YM2610(B) = OPN-B                                                 */\r
105 /*    YM2610  : PSG:3ch FM:4ch ADPCM(18.5KHz):6ch DeltaT ADPCM:1ch      */\r
106 /*    YM2610B : PSG:3ch FM:6ch ADPCM(18.5KHz):6ch DeltaT ADPCM:1ch      */\r
107 /************************************************************************/\r
108 \r
109 //#include <stdio.h>\r
110 \r
111 #include <string.h>\r
112 #include <math.h>\r
113 \r
114 #include "ym2612.h"\r
115 \r
116 #ifndef EXTERNAL_YM2612\r
117 #include <stdlib.h>\r
118 // let it be 1 global to simplify things\r
119 YM2612 ym2612;\r
120 \r
121 #else\r
122 extern YM2612 *ym2612_940;\r
123 #define ym2612 (*ym2612_940)\r
124 \r
125 #endif\r
126 \r
127 void memset32(int *dest, int c, int count);\r
128 \r
129 \r
130 #ifndef __GNUC__\r
131 #pragma warning (disable:4100) // unreferenced formal parameter\r
132 #pragma warning (disable:4244)\r
133 #pragma warning (disable:4245) // signed/unsigned in conversion\r
134 #pragma warning (disable:4710)\r
135 #pragma warning (disable:4018) // signed/unsigned\r
136 #endif\r
137 \r
138 #ifndef INLINE\r
139 #define INLINE static __inline\r
140 #endif\r
141 \r
142 #ifndef M_PI\r
143 #define M_PI    3.14159265358979323846\r
144 #endif\r
145 \r
146 \r
147 /* globals */\r
148 \r
149 #define FREQ_SH                 16  /* 16.16 fixed point (frequency calculations) */\r
150 #define EG_SH                   16  /* 16.16 fixed point (envelope generator timing) */\r
151 #define LFO_SH                  25  /*  7.25 fixed point (LFO calculations)       */\r
152 #define TIMER_SH                16  /* 16.16 fixed point (timers calculations)    */\r
153 \r
154 #define ENV_BITS                10\r
155 #define ENV_LEN                 (1<<ENV_BITS)\r
156 #define ENV_STEP                (128.0/ENV_LEN)\r
157 \r
158 #define MAX_ATT_INDEX   (ENV_LEN-1) /* 1023 */\r
159 #define MIN_ATT_INDEX   (0)                     /* 0 */\r
160 \r
161 #define EG_ATT                  4\r
162 #define EG_DEC                  3\r
163 #define EG_SUS                  2\r
164 #define EG_REL                  1\r
165 #define EG_OFF                  0\r
166 \r
167 #define SIN_BITS                10\r
168 #define SIN_LEN                 (1<<SIN_BITS)\r
169 #define SIN_MASK                (SIN_LEN-1)\r
170 \r
171 #define TL_RES_LEN              (256) /* 8 bits addressing (real chip) */\r
172 \r
173 #define EG_TIMER_OVERFLOW (3*(1<<EG_SH)) /* envelope generator timer overflows every 3 samples (on real chip) */\r
174 \r
175 #define MAXOUT          (+32767)\r
176 #define MINOUT          (-32768)\r
177 \r
178 /* limitter */\r
179 #define Limit(val, max,min) { \\r
180         if ( val > max )      val = max; \\r
181         else if ( val < min ) val = min; \\r
182 }\r
183 \r
184 \r
185 /*  TL_TAB_LEN is calculated as:\r
186 *   13 - sinus amplitude bits     (Y axis)\r
187 *   2  - sinus sign bit           (Y axis)\r
188 *   TL_RES_LEN - sinus resolution (X axis)\r
189 */\r
190 //#define TL_TAB_LEN (13*2*TL_RES_LEN)\r
191 #define TL_TAB_LEN (13*TL_RES_LEN*256/8) // 106496*2\r
192 UINT16 ym_tl_tab[TL_TAB_LEN];\r
193 \r
194 /* ~3K wasted but oh well */\r
195 UINT16 ym_tl_tab2[13*TL_RES_LEN];\r
196 \r
197 #define ENV_QUIET               (2*13*TL_RES_LEN/8)\r
198 \r
199 /* sin waveform table in 'decibel' scale (use only period/4 values) */\r
200 static UINT16 ym_sin_tab[256];\r
201 \r
202 /* sustain level table (3dB per step) */\r
203 /* bit0, bit1, bit2, bit3, bit4, bit5, bit6 */\r
204 /* 1,    2,    4,    8,    16,   32,   64   (value)*/\r
205 /* 0.75, 1.5,  3,    6,    12,   24,   48   (dB)*/\r
206 \r
207 /* 0 - 15: 0, 3, 6, 9,12,15,18,21,24,27,30,33,36,39,42,93 (dB)*/\r
208 #define SC(db) (UINT32) ( db * (4.0/ENV_STEP) )\r
209 static const UINT32 sl_table[16]={\r
210  SC( 0),SC( 1),SC( 2),SC(3 ),SC(4 ),SC(5 ),SC(6 ),SC( 7),\r
211  SC( 8),SC( 9),SC(10),SC(11),SC(12),SC(13),SC(14),SC(31)\r
212 };\r
213 #undef SC\r
214 \r
215 \r
216 #if 0\r
217 #define RATE_STEPS (8)\r
218 static const UINT8 eg_inc[19*RATE_STEPS]={\r
219 \r
220 /*cycle:0 1  2 3  4 5  6 7*/\r
221 \r
222 /* 0 */ 0,1, 0,1, 0,1, 0,1, /* rates 00..11 0 (increment by 0 or 1) */\r
223 /* 1 */ 0,1, 0,1, 1,1, 0,1, /* rates 00..11 1 */\r
224 /* 2 */ 0,1, 1,1, 0,1, 1,1, /* rates 00..11 2 */\r
225 /* 3 */ 0,1, 1,1, 1,1, 1,1, /* rates 00..11 3 */\r
226 \r
227 /* 4 */ 1,1, 1,1, 1,1, 1,1, /* rate 12 0 (increment by 1) */\r
228 /* 5 */ 1,1, 1,2, 1,1, 1,2, /* rate 12 1 */\r
229 /* 6 */ 1,2, 1,2, 1,2, 1,2, /* rate 12 2 */\r
230 /* 7 */ 1,2, 2,2, 1,2, 2,2, /* rate 12 3 */\r
231 \r
232 /* 8 */ 2,2, 2,2, 2,2, 2,2, /* rate 13 0 (increment by 2) */\r
233 /* 9 */ 2,2, 2,4, 2,2, 2,4, /* rate 13 1 */\r
234 /*10 */ 2,4, 2,4, 2,4, 2,4, /* rate 13 2 */\r
235 /*11 */ 2,4, 4,4, 2,4, 4,4, /* rate 13 3 */\r
236 \r
237 /*12 */ 4,4, 4,4, 4,4, 4,4, /* rate 14 0 (increment by 4) */\r
238 /*13 */ 4,4, 4,8, 4,4, 4,8, /* rate 14 1 */\r
239 /*14 */ 4,8, 4,8, 4,8, 4,8, /* rate 14 2 */\r
240 /*15 */ 4,8, 8,8, 4,8, 8,8, /* rate 14 3 */\r
241 \r
242 /*16 */ 8,8, 8,8, 8,8, 8,8, /* rates 15 0, 15 1, 15 2, 15 3 (increment by 8) */\r
243 /*17 */ 16,16,16,16,16,16,16,16, /* rates 15 2, 15 3 for attack */\r
244 /*18 */ 0,0, 0,0, 0,0, 0,0, /* infinity rates for attack and decay(s) */\r
245 };\r
246 #endif\r
247 \r
248 \r
249 #define PACK(a0,a1,a2,a3,a4,a5,a6,a7) ((a7<<21)|(a6<<18)|(a5<<15)|(a4<<12)|(a3<<9)|(a2<<6)|(a1<<3)|(a0<<0))\r
250 static const UINT32 eg_inc_pack[19] =\r
251 {\r
252 /* 0 */ PACK(0,1,0,1,0,1,0,1), /* rates 00..11 0 (increment by 0 or 1) */\r
253 /* 1 */ PACK(0,1,0,1,1,1,0,1), /* rates 00..11 1 */\r
254 /* 2 */ PACK(0,1,1,1,0,1,1,1), /* rates 00..11 2 */\r
255 /* 3 */ PACK(0,1,1,1,1,1,1,1), /* rates 00..11 3 */\r
256 \r
257 /* 4 */ PACK(1,1,1,1,1,1,1,1), /* rate 12 0 (increment by 1) */\r
258 /* 5 */ PACK(1,1,1,2,1,1,1,2), /* rate 12 1 */\r
259 /* 6 */ PACK(1,2,1,2,1,2,1,2), /* rate 12 2 */\r
260 /* 7 */ PACK(1,2,2,2,1,2,2,2), /* rate 12 3 */\r
261 \r
262 /* 8 */ PACK(2,2,2,2,2,2,2,2), /* rate 13 0 (increment by 2) */\r
263 /* 9 */ PACK(2,2,2,3,2,2,2,3), /* rate 13 1 */\r
264 /*10 */ PACK(2,3,2,3,2,3,2,3), /* rate 13 2 */\r
265 /*11 */ PACK(2,3,3,3,2,3,3,3), /* rate 13 3 */\r
266 \r
267 /*12 */ PACK(3,3,3,3,3,3,3,3), /* rate 14 0 (increment by 4) */\r
268 /*13 */ PACK(3,3,3,4,3,3,3,4), /* rate 14 1 */\r
269 /*14 */ PACK(3,4,3,4,3,4,3,4), /* rate 14 2 */\r
270 /*15 */ PACK(3,4,4,4,3,4,4,4), /* rate 14 3 */\r
271 \r
272 /*16 */ PACK(4,4,4,4,4,4,4,4), /* rates 15 0, 15 1, 15 2, 15 3 (increment by 8) */\r
273 /*17 */ PACK(5,5,5,5,5,5,5,5), /* rates 15 2, 15 3 for attack */\r
274 /*18 */ PACK(0,0,0,0,0,0,0,0), /* infinity rates for attack and decay(s) */\r
275 };\r
276 \r
277 \r
278 //#define O(a) (a*RATE_STEPS)\r
279 #define O(a) a\r
280 \r
281 /*note that there is no O(17) in this table - it's directly in the code */\r
282 static const UINT8 eg_rate_select[32+64+32]={   /* Envelope Generator rates (32 + 64 rates + 32 RKS) */\r
283 /* 32 infinite time rates */\r
284 O(18),O(18),O(18),O(18),O(18),O(18),O(18),O(18),\r
285 O(18),O(18),O(18),O(18),O(18),O(18),O(18),O(18),\r
286 O(18),O(18),O(18),O(18),O(18),O(18),O(18),O(18),\r
287 O(18),O(18),O(18),O(18),O(18),O(18),O(18),O(18),\r
288 \r
289 /* rates 00-11 */\r
290 O( 0),O( 1),O( 2),O( 3),\r
291 O( 0),O( 1),O( 2),O( 3),\r
292 O( 0),O( 1),O( 2),O( 3),\r
293 O( 0),O( 1),O( 2),O( 3),\r
294 O( 0),O( 1),O( 2),O( 3),\r
295 O( 0),O( 1),O( 2),O( 3),\r
296 O( 0),O( 1),O( 2),O( 3),\r
297 O( 0),O( 1),O( 2),O( 3),\r
298 O( 0),O( 1),O( 2),O( 3),\r
299 O( 0),O( 1),O( 2),O( 3),\r
300 O( 0),O( 1),O( 2),O( 3),\r
301 O( 0),O( 1),O( 2),O( 3),\r
302 \r
303 /* rate 12 */\r
304 O( 4),O( 5),O( 6),O( 7),\r
305 \r
306 /* rate 13 */\r
307 O( 8),O( 9),O(10),O(11),\r
308 \r
309 /* rate 14 */\r
310 O(12),O(13),O(14),O(15),\r
311 \r
312 /* rate 15 */\r
313 O(16),O(16),O(16),O(16),\r
314 \r
315 /* 32 dummy rates (same as 15 3) */\r
316 O(16),O(16),O(16),O(16),O(16),O(16),O(16),O(16),\r
317 O(16),O(16),O(16),O(16),O(16),O(16),O(16),O(16),\r
318 O(16),O(16),O(16),O(16),O(16),O(16),O(16),O(16),\r
319 O(16),O(16),O(16),O(16),O(16),O(16),O(16),O(16)\r
320 \r
321 };\r
322 #undef O\r
323 \r
324 /*rate  0,    1,    2,   3,   4,   5,  6,  7,  8,  9, 10, 11, 12, 13, 14, 15*/\r
325 /*shift 11,   10,   9,   8,   7,   6,  5,  4,  3,  2, 1,  0,  0,  0,  0,  0 */\r
326 /*mask  2047, 1023, 511, 255, 127, 63, 31, 15, 7,  3, 1,  0,  0,  0,  0,  0 */\r
327 \r
328 #define O(a) (a*1)\r
329 static const UINT8 eg_rate_shift[32+64+32]={    /* Envelope Generator counter shifts (32 + 64 rates + 32 RKS) */\r
330 /* 32 infinite time rates */\r
331 O(0),O(0),O(0),O(0),O(0),O(0),O(0),O(0),\r
332 O(0),O(0),O(0),O(0),O(0),O(0),O(0),O(0),\r
333 O(0),O(0),O(0),O(0),O(0),O(0),O(0),O(0),\r
334 O(0),O(0),O(0),O(0),O(0),O(0),O(0),O(0),\r
335 \r
336 /* rates 00-11 */\r
337 O(11),O(11),O(11),O(11),\r
338 O(10),O(10),O(10),O(10),\r
339 O( 9),O( 9),O( 9),O( 9),\r
340 O( 8),O( 8),O( 8),O( 8),\r
341 O( 7),O( 7),O( 7),O( 7),\r
342 O( 6),O( 6),O( 6),O( 6),\r
343 O( 5),O( 5),O( 5),O( 5),\r
344 O( 4),O( 4),O( 4),O( 4),\r
345 O( 3),O( 3),O( 3),O( 3),\r
346 O( 2),O( 2),O( 2),O( 2),\r
347 O( 1),O( 1),O( 1),O( 1),\r
348 O( 0),O( 0),O( 0),O( 0),\r
349 \r
350 /* rate 12 */\r
351 O( 0),O( 0),O( 0),O( 0),\r
352 \r
353 /* rate 13 */\r
354 O( 0),O( 0),O( 0),O( 0),\r
355 \r
356 /* rate 14 */\r
357 O( 0),O( 0),O( 0),O( 0),\r
358 \r
359 /* rate 15 */\r
360 O( 0),O( 0),O( 0),O( 0),\r
361 \r
362 /* 32 dummy rates (same as 15 3) */\r
363 O( 0),O( 0),O( 0),O( 0),O( 0),O( 0),O( 0),O( 0),\r
364 O( 0),O( 0),O( 0),O( 0),O( 0),O( 0),O( 0),O( 0),\r
365 O( 0),O( 0),O( 0),O( 0),O( 0),O( 0),O( 0),O( 0),\r
366 O( 0),O( 0),O( 0),O( 0),O( 0),O( 0),O( 0),O( 0)\r
367 \r
368 };\r
369 #undef O\r
370 \r
371 static const UINT8 dt_tab[4 * 32]={\r
372 /* this is YM2151 and YM2612 phase increment data (in 10.10 fixed point format)*/\r
373 /* FD=0 */\r
374         0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\r
375         0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\r
376 /* FD=1 */\r
377         0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 2, 2, 2, 2,\r
378         2, 3, 3, 3, 4, 4, 4, 5, 5, 6, 6, 7, 8, 8, 8, 8,\r
379 /* FD=2 */\r
380         1, 1, 1, 1, 2, 2, 2, 2, 2, 3, 3, 3, 4, 4, 4, 5,\r
381         5, 6, 6, 7, 8, 8, 9,10,11,12,13,14,16,16,16,16,\r
382 /* FD=3 */\r
383         2, 2, 2, 2, 2, 3, 3, 3, 4, 4, 4, 5, 5, 6, 6, 7,\r
384         8 , 8, 9,10,11,12,13,14,16,17,19,20,22,22,22,22\r
385 };\r
386 \r
387 \r
388 /* OPN key frequency number -> key code follow table */\r
389 /* fnum higher 4bit -> keycode lower 2bit */\r
390 static const UINT8 opn_fktable[16] = {0,0,0,0,0,0,0,1,2,3,3,3,3,3,3,3};\r
391 \r
392 \r
393 /* 8 LFO speed parameters */\r
394 /* each value represents number of samples that one LFO level will last for */\r
395 static const UINT32 lfo_samples_per_step[8] = {108, 77, 71, 67, 62, 44, 8, 5};\r
396 \r
397 \r
398 \r
399 /*There are 4 different LFO AM depths available, they are:\r
400   0 dB, 1.4 dB, 5.9 dB, 11.8 dB\r
401   Here is how it is generated (in EG steps):\r
402 \r
403   11.8 dB = 0, 2, 4, 6, 8, 10,12,14,16...126,126,124,122,120,118,....4,2,0\r
404    5.9 dB = 0, 1, 2, 3, 4, 5, 6, 7, 8....63, 63, 62, 61, 60, 59,.....2,1,0\r
405    1.4 dB = 0, 0, 0, 0, 1, 1, 1, 1, 2,...15, 15, 15, 15, 14, 14,.....0,0,0\r
406 \r
407   (1.4 dB is loosing precision as you can see)\r
408 \r
409   It's implemented as generator from 0..126 with step 2 then a shift\r
410   right N times, where N is:\r
411     8 for 0 dB\r
412     3 for 1.4 dB\r
413     1 for 5.9 dB\r
414     0 for 11.8 dB\r
415 */\r
416 static const UINT8 lfo_ams_depth_shift[4] = {8, 3, 1, 0};\r
417 \r
418 \r
419 \r
420 /*There are 8 different LFO PM depths available, they are:\r
421   0, 3.4, 6.7, 10, 14, 20, 40, 80 (cents)\r
422 \r
423   Modulation level at each depth depends on F-NUMBER bits: 4,5,6,7,8,9,10\r
424   (bits 8,9,10 = FNUM MSB from OCT/FNUM register)\r
425 \r
426   Here we store only first quarter (positive one) of full waveform.\r
427   Full table (lfo_pm_table) containing all 128 waveforms is build\r
428   at run (init) time.\r
429 \r
430   One value in table below represents 4 (four) basic LFO steps\r
431   (1 PM step = 4 AM steps).\r
432 \r
433   For example:\r
434    at LFO SPEED=0 (which is 108 samples per basic LFO step)\r
435    one value from "lfo_pm_output" table lasts for 432 consecutive\r
436    samples (4*108=432) and one full LFO waveform cycle lasts for 13824\r
437    samples (32*432=13824; 32 because we store only a quarter of whole\r
438             waveform in the table below)\r
439 */\r
440 static const UINT8 lfo_pm_output[7*8][8]={ /* 7 bits meaningful (of F-NUMBER), 8 LFO output levels per one depth (out of 32), 8 LFO depths */\r
441 /* FNUM BIT 4: 000 0001xxxx */\r
442 /* DEPTH 0 */ {0,   0,   0,   0,   0,   0,   0,   0},\r
443 /* DEPTH 1 */ {0,   0,   0,   0,   0,   0,   0,   0},\r
444 /* DEPTH 2 */ {0,   0,   0,   0,   0,   0,   0,   0},\r
445 /* DEPTH 3 */ {0,   0,   0,   0,   0,   0,   0,   0},\r
446 /* DEPTH 4 */ {0,   0,   0,   0,   0,   0,   0,   0},\r
447 /* DEPTH 5 */ {0,   0,   0,   0,   0,   0,   0,   0},\r
448 /* DEPTH 6 */ {0,   0,   0,   0,   0,   0,   0,   0},\r
449 /* DEPTH 7 */ {0,   0,   0,   0,   1,   1,   1,   1},\r
450 \r
451 /* FNUM BIT 5: 000 0010xxxx */\r
452 /* DEPTH 0 */ {0,   0,   0,   0,   0,   0,   0,   0},\r
453 /* DEPTH 1 */ {0,   0,   0,   0,   0,   0,   0,   0},\r
454 /* DEPTH 2 */ {0,   0,   0,   0,   0,   0,   0,   0},\r
455 /* DEPTH 3 */ {0,   0,   0,   0,   0,   0,   0,   0},\r
456 /* DEPTH 4 */ {0,   0,   0,   0,   0,   0,   0,   0},\r
457 /* DEPTH 5 */ {0,   0,   0,   0,   0,   0,   0,   0},\r
458 /* DEPTH 6 */ {0,   0,   0,   0,   1,   1,   1,   1},\r
459 /* DEPTH 7 */ {0,   0,   1,   1,   2,   2,   2,   3},\r
460 \r
461 /* FNUM BIT 6: 000 0100xxxx */\r
462 /* DEPTH 0 */ {0,   0,   0,   0,   0,   0,   0,   0},\r
463 /* DEPTH 1 */ {0,   0,   0,   0,   0,   0,   0,   0},\r
464 /* DEPTH 2 */ {0,   0,   0,   0,   0,   0,   0,   0},\r
465 /* DEPTH 3 */ {0,   0,   0,   0,   0,   0,   0,   0},\r
466 /* DEPTH 4 */ {0,   0,   0,   0,   0,   0,   0,   1},\r
467 /* DEPTH 5 */ {0,   0,   0,   0,   1,   1,   1,   1},\r
468 /* DEPTH 6 */ {0,   0,   1,   1,   2,   2,   2,   3},\r
469 /* DEPTH 7 */ {0,   0,   2,   3,   4,   4,   5,   6},\r
470 \r
471 /* FNUM BIT 7: 000 1000xxxx */\r
472 /* DEPTH 0 */ {0,   0,   0,   0,   0,   0,   0,   0},\r
473 /* DEPTH 1 */ {0,   0,   0,   0,   0,   0,   0,   0},\r
474 /* DEPTH 2 */ {0,   0,   0,   0,   0,   0,   1,   1},\r
475 /* DEPTH 3 */ {0,   0,   0,   0,   1,   1,   1,   1},\r
476 /* DEPTH 4 */ {0,   0,   0,   1,   1,   1,   1,   2},\r
477 /* DEPTH 5 */ {0,   0,   1,   1,   2,   2,   2,   3},\r
478 /* DEPTH 6 */ {0,   0,   2,   3,   4,   4,   5,   6},\r
479 /* DEPTH 7 */ {0,   0,   4,   6,   8,   8, 0xa, 0xc},\r
480 \r
481 /* FNUM BIT 8: 001 0000xxxx */\r
482 /* DEPTH 0 */ {0,   0,   0,   0,   0,   0,   0,   0},\r
483 /* DEPTH 1 */ {0,   0,   0,   0,   1,   1,   1,   1},\r
484 /* DEPTH 2 */ {0,   0,   0,   1,   1,   1,   2,   2},\r
485 /* DEPTH 3 */ {0,   0,   1,   1,   2,   2,   3,   3},\r
486 /* DEPTH 4 */ {0,   0,   1,   2,   2,   2,   3,   4},\r
487 /* DEPTH 5 */ {0,   0,   2,   3,   4,   4,   5,   6},\r
488 /* DEPTH 6 */ {0,   0,   4,   6,   8,   8, 0xa, 0xc},\r
489 /* DEPTH 7 */ {0,   0,   8, 0xc,0x10,0x10,0x14,0x18},\r
490 \r
491 /* FNUM BIT 9: 010 0000xxxx */\r
492 /* DEPTH 0 */ {0,   0,   0,   0,   0,   0,   0,   0},\r
493 /* DEPTH 1 */ {0,   0,   0,   0,   2,   2,   2,   2},\r
494 /* DEPTH 2 */ {0,   0,   0,   2,   2,   2,   4,   4},\r
495 /* DEPTH 3 */ {0,   0,   2,   2,   4,   4,   6,   6},\r
496 /* DEPTH 4 */ {0,   0,   2,   4,   4,   4,   6,   8},\r
497 /* DEPTH 5 */ {0,   0,   4,   6,   8,   8, 0xa, 0xc},\r
498 /* DEPTH 6 */ {0,   0,   8, 0xc,0x10,0x10,0x14,0x18},\r
499 /* DEPTH 7 */ {0,   0,0x10,0x18,0x20,0x20,0x28,0x30},\r
500 \r
501 /* FNUM BIT10: 100 0000xxxx */\r
502 /* DEPTH 0 */ {0,   0,   0,   0,   0,   0,   0,   0},\r
503 /* DEPTH 1 */ {0,   0,   0,   0,   4,   4,   4,   4},\r
504 /* DEPTH 2 */ {0,   0,   0,   4,   4,   4,   8,   8},\r
505 /* DEPTH 3 */ {0,   0,   4,   4,   8,   8, 0xc, 0xc},\r
506 /* DEPTH 4 */ {0,   0,   4,   8,   8,   8, 0xc,0x10},\r
507 /* DEPTH 5 */ {0,   0,   8, 0xc,0x10,0x10,0x14,0x18},\r
508 /* DEPTH 6 */ {0,   0,0x10,0x18,0x20,0x20,0x28,0x30},\r
509 /* DEPTH 7 */ {0,   0,0x20,0x30,0x40,0x40,0x50,0x60},\r
510 \r
511 };\r
512 \r
513 /* all 128 LFO PM waveforms */\r
514 static INT32 lfo_pm_table[128*8*32]; /* 128 combinations of 7 bits meaningful (of F-NUMBER), 8 LFO depths, 32 LFO output levels per one depth */\r
515 \r
516 /* there are 2048 FNUMs that can be generated using FNUM/BLK registers\r
517         but LFO works with one more bit of a precision so we really need 4096 elements */\r
518 static UINT32 fn_table[4096];   /* fnumber->increment counter */\r
519 \r
520 static int g_lfo_ampm = 0;\r
521 \r
522 /* register number to channel number , slot offset */\r
523 #define OPN_CHAN(N) (N&3)\r
524 #define OPN_SLOT(N) ((N>>2)&3)\r
525 \r
526 /* slot number */\r
527 #define SLOT1 0\r
528 #define SLOT2 2\r
529 #define SLOT3 1\r
530 #define SLOT4 3\r
531 \r
532 \r
533 /* OPN Mode Register Write */\r
534 INLINE void set_timers( int v )\r
535 {\r
536         /* b7 = CSM MODE */\r
537         /* b6 = 3 slot mode */\r
538         /* b5 = reset b */\r
539         /* b4 = reset a */\r
540         /* b3 = timer enable b */\r
541         /* b2 = timer enable a */\r
542         /* b1 = load b */\r
543         /* b0 = load a */\r
544         ym2612.OPN.ST.mode = v;\r
545 \r
546         /* reset Timer b flag */\r
547         if( v & 0x20 )\r
548                 ym2612.OPN.ST.status &= ~2;\r
549 \r
550         /* reset Timer a flag */\r
551         if( v & 0x10 )\r
552                 ym2612.OPN.ST.status &= ~1;\r
553 }\r
554 \r
555 \r
556 INLINE void FM_KEYON(int c , int s )\r
557 {\r
558         FM_SLOT *SLOT = &ym2612.CH[c].SLOT[s];\r
559         if( !SLOT->key )\r
560         {\r
561                 SLOT->key = 1;\r
562                 SLOT->phase = 0;                /* restart Phase Generator */\r
563                 SLOT->state = EG_ATT;   /* phase -> Attack */\r
564                 ym2612.slot_mask |= (1<<s) << (c*4);\r
565         }\r
566 }\r
567 \r
568 INLINE void FM_KEYOFF(int c , int s )\r
569 {\r
570         FM_SLOT *SLOT = &ym2612.CH[c].SLOT[s];\r
571         if( SLOT->key )\r
572         {\r
573                 SLOT->key = 0;\r
574                 if (SLOT->state>EG_REL)\r
575                         SLOT->state = EG_REL;/* phase -> Release */\r
576         }\r
577 }\r
578 \r
579 \r
580 /* set detune & multiple */\r
581 INLINE void set_det_mul(FM_CH *CH, FM_SLOT *SLOT, int v)\r
582 {\r
583         SLOT->mul = (v&0x0f)? (v&0x0f)*2 : 1;\r
584         SLOT->DT  = ym2612.OPN.ST.dt_tab[(v>>4)&7];\r
585         CH->SLOT[SLOT1].Incr=-1;\r
586 }\r
587 \r
588 /* set total level */\r
589 INLINE void set_tl(FM_SLOT *SLOT, int v)\r
590 {\r
591         SLOT->tl = (v&0x7f)<<(ENV_BITS-7); /* 7bit TL */\r
592 }\r
593 \r
594 /* set attack rate & key scale  */\r
595 INLINE void set_ar_ksr(FM_CH *CH, FM_SLOT *SLOT, int v)\r
596 {\r
597         UINT8 old_KSR = SLOT->KSR;\r
598 \r
599         SLOT->ar = (v&0x1f) ? 32 + ((v&0x1f)<<1) : 0;\r
600 \r
601         SLOT->KSR = 3-(v>>6);\r
602         if (SLOT->KSR != old_KSR)\r
603         {\r
604                 CH->SLOT[SLOT1].Incr=-1;\r
605         }\r
606         else\r
607         {\r
608                 int eg_sh_ar, eg_sel_ar;\r
609 \r
610                 /* refresh Attack rate */\r
611                 if ((SLOT->ar + SLOT->ksr) < 32+62)\r
612                 {\r
613                         eg_sh_ar  = eg_rate_shift [SLOT->ar  + SLOT->ksr ];\r
614                         eg_sel_ar = eg_rate_select[SLOT->ar  + SLOT->ksr ];\r
615                 }\r
616                 else\r
617                 {\r
618                         eg_sh_ar  = 0;\r
619                         eg_sel_ar = 17;\r
620                 }\r
621 \r
622                 SLOT->eg_pack_ar = eg_inc_pack[eg_sel_ar] | (eg_sh_ar<<24);\r
623         }\r
624 }\r
625 \r
626 /* set decay rate */\r
627 INLINE void set_dr(FM_SLOT *SLOT, int v)\r
628 {\r
629         int eg_sh_d1r, eg_sel_d1r;\r
630 \r
631         SLOT->d1r = (v&0x1f) ? 32 + ((v&0x1f)<<1) : 0;\r
632 \r
633         eg_sh_d1r = eg_rate_shift [SLOT->d1r + SLOT->ksr];\r
634         eg_sel_d1r= eg_rate_select[SLOT->d1r + SLOT->ksr];\r
635 \r
636         SLOT->eg_pack_d1r = eg_inc_pack[eg_sel_d1r] | (eg_sh_d1r<<24);\r
637 }\r
638 \r
639 /* set sustain rate */\r
640 INLINE void set_sr(FM_SLOT *SLOT, int v)\r
641 {\r
642         int eg_sh_d2r, eg_sel_d2r;\r
643 \r
644         SLOT->d2r = (v&0x1f) ? 32 + ((v&0x1f)<<1) : 0;\r
645 \r
646         eg_sh_d2r = eg_rate_shift [SLOT->d2r + SLOT->ksr];\r
647         eg_sel_d2r= eg_rate_select[SLOT->d2r + SLOT->ksr];\r
648 \r
649         SLOT->eg_pack_d2r = eg_inc_pack[eg_sel_d2r] | (eg_sh_d2r<<24);\r
650 }\r
651 \r
652 /* set release rate */\r
653 INLINE void set_sl_rr(FM_SLOT *SLOT, int v)\r
654 {\r
655         int eg_sh_rr, eg_sel_rr;\r
656 \r
657         SLOT->sl = sl_table[ v>>4 ];\r
658 \r
659         SLOT->rr  = 34 + ((v&0x0f)<<2);\r
660 \r
661         eg_sh_rr  = eg_rate_shift [SLOT->rr  + SLOT->ksr];\r
662         eg_sel_rr = eg_rate_select[SLOT->rr  + SLOT->ksr];\r
663 \r
664         SLOT->eg_pack_rr = eg_inc_pack[eg_sel_rr] | (eg_sh_rr<<24);\r
665 }\r
666 \r
667 \r
668 \r
669 INLINE signed int op_calc(UINT32 phase, unsigned int env, signed int pm)\r
670 {\r
671         int ret, sin = (phase>>16) + (pm>>1);\r
672         int neg = sin & 0x200;\r
673         if (sin & 0x100) sin ^= 0xff;\r
674         sin&=0xff;\r
675         env&=~1;\r
676 \r
677         // this was already checked\r
678         // if (env >= ENV_QUIET) // 384\r
679         //      return 0;\r
680 \r
681         ret = ym_tl_tab[sin | (env<<7)];\r
682 \r
683         return neg ? -ret : ret;\r
684 }\r
685 \r
686 INLINE signed int op_calc1(UINT32 phase, unsigned int env, signed int pm)\r
687 {\r
688         int ret, sin = (phase+pm)>>16;\r
689         int neg = sin & 0x200;\r
690         if (sin & 0x100) sin ^= 0xff;\r
691         sin&=0xff;\r
692         env&=~1;\r
693 \r
694         // if (env >= ENV_QUIET) // 384\r
695         //      return 0;\r
696 \r
697         ret = ym_tl_tab[sin | (env<<7)];\r
698 \r
699         return neg ? -ret : ret;\r
700 }\r
701 \r
702 #if !defined(_ASM_YM2612_C) || defined(EXTERNAL_YM2612)\r
703 /* advance LFO to next sample */\r
704 INLINE int advance_lfo(int lfo_ampm, UINT32 lfo_cnt_old, UINT32 lfo_cnt)\r
705 {\r
706         UINT8 pos;\r
707         UINT8 prev_pos;\r
708 \r
709         prev_pos = (lfo_cnt_old >> LFO_SH) & 127;\r
710 \r
711         pos = (lfo_cnt >> LFO_SH) & 127;\r
712 \r
713         /* update AM when LFO output changes */\r
714 \r
715         if (prev_pos != pos)\r
716         {\r
717                 lfo_ampm &= 0xff;\r
718                 /* triangle */\r
719                 /* AM: 0 to 126 step +2, 126 to 0 step -2 */\r
720                 if (pos<64)\r
721                         lfo_ampm |= ((pos&63) * 2) << 8;           /* 0 - 126 */\r
722                 else\r
723                         lfo_ampm |= (126 - (pos&63)*2) << 8;\r
724         }\r
725         else\r
726         {\r
727                 return lfo_ampm;\r
728         }\r
729 \r
730         /* PM works with 4 times slower clock */\r
731         prev_pos >>= 2;\r
732         pos >>= 2;\r
733         /* update PM when LFO output changes */\r
734         if (prev_pos != pos)\r
735         {\r
736                 lfo_ampm &= ~0xff;\r
737                 lfo_ampm |= pos; /* 0 - 32 */\r
738         }\r
739         return lfo_ampm;\r
740 }\r
741 \r
742 #define EG_INC_VAL() \\r
743         ((1 << ((pack >> ((eg_cnt>>shift)&7)*3)&7)) >> 1)\r
744 \r
745 INLINE UINT32 update_eg_phase(FM_SLOT *SLOT, UINT32 eg_cnt)\r
746 {\r
747         INT32 volume = SLOT->volume;\r
748 \r
749         switch(SLOT->state)\r
750         {\r
751                 case EG_ATT:            /* attack phase */\r
752                 {\r
753                         UINT32 pack = SLOT->eg_pack_ar;\r
754                         UINT32 shift = pack>>24;\r
755                         if ( !(eg_cnt & ((1<<shift)-1) ) )\r
756                         {\r
757                                 volume += ( ~volume * EG_INC_VAL() ) >>4;\r
758 \r
759                                 if (volume <= MIN_ATT_INDEX)\r
760                                 {\r
761                                         volume = MIN_ATT_INDEX;\r
762                                         SLOT->state = EG_DEC;\r
763                                 }\r
764                         }\r
765                         break;\r
766                 }\r
767 \r
768                 case EG_DEC:    /* decay phase */\r
769                 {\r
770                         UINT32 pack = SLOT->eg_pack_d1r;\r
771                         UINT32 shift = pack>>24;\r
772                         if ( !(eg_cnt & ((1<<shift)-1) ) )\r
773                         {\r
774                                 volume += EG_INC_VAL();\r
775 \r
776                                 if ( volume >= (INT32) SLOT->sl )\r
777                                         SLOT->state = EG_SUS;\r
778                         }\r
779                         break;\r
780                 }\r
781 \r
782                 case EG_SUS:    /* sustain phase */\r
783                 {\r
784                         UINT32 pack = SLOT->eg_pack_d2r;\r
785                         UINT32 shift = pack>>24;\r
786                         if ( !(eg_cnt & ((1<<shift)-1) ) )\r
787                         {\r
788                                 volume += EG_INC_VAL();\r
789 \r
790                                 if ( volume >= MAX_ATT_INDEX )\r
791                                 {\r
792                                         volume = MAX_ATT_INDEX;\r
793                                         /* do not change SLOT->state (verified on real chip) */\r
794                                 }\r
795                         }\r
796                         break;\r
797                 }\r
798 \r
799                 case EG_REL:    /* release phase */\r
800                 {\r
801                         UINT32 pack = SLOT->eg_pack_rr;\r
802                         UINT32 shift = pack>>24;\r
803                         if ( !(eg_cnt & ((1<<shift)-1) ) )\r
804                         {\r
805                                 volume += EG_INC_VAL();\r
806 \r
807                                 if ( volume >= MAX_ATT_INDEX )\r
808                                 {\r
809                                         volume = MAX_ATT_INDEX;\r
810                                         SLOT->state = EG_OFF;\r
811                                 }\r
812                         }\r
813                         break;\r
814                 }\r
815         }\r
816 \r
817         SLOT->volume = volume;\r
818         return SLOT->tl + ((UINT32)volume); /* tl is 7bit<<3, volume 0-1023 (0-2039 total) */\r
819 }\r
820 #endif\r
821 \r
822 \r
823 typedef struct\r
824 {\r
825         UINT16 vol_out1; /* 00: current output from EG circuit (without AM from LFO) */\r
826         UINT16 vol_out2;\r
827         UINT16 vol_out3;\r
828         UINT16 vol_out4;\r
829         UINT32 pad[2];\r
830         UINT32 phase1;   /* 10 */\r
831         UINT32 phase2;\r
832         UINT32 phase3;\r
833         UINT32 phase4;\r
834         UINT32 incr1;    /* 20: phase step */\r
835         UINT32 incr2;\r
836         UINT32 incr3;\r
837         UINT32 incr4;\r
838         UINT32 lfo_cnt;  /* 30 */\r
839         UINT32 lfo_inc;\r
840         INT32  mem;      /* one sample delay memory */\r
841         UINT32 eg_cnt;   /* envelope generator counter */\r
842         FM_CH  *CH;      /* 40: envelope generator counter */\r
843         UINT32 eg_timer;\r
844         UINT32 eg_timer_add;\r
845         UINT32 pack;     // 4c: stereo, lastchan, disabled, lfo_enabled | pan_r, pan_l, ams[2] | AMmasks[4] | FB[4] | lfo_ampm[16]\r
846         UINT32 algo;     /* 50: algo[3], was_update */\r
847         INT32  op1_out;\r
848 #ifdef _MIPS_ARCH_ALLEGREX\r
849         UINT32 pad1[3+8];\r
850 #endif\r
851 } chan_rend_context;\r
852 \r
853 \r
854 #if !defined(_ASM_YM2612_C) || defined(EXTERNAL_YM2612)\r
855 static void chan_render_loop(chan_rend_context *ct, int *buffer, int length)\r
856 {\r
857         int scounter;                                   /* sample counter */\r
858 \r
859         /* sample generating loop */\r
860         for (scounter = 0; scounter < length; scounter++)\r
861         {\r
862                 int smp = 0;            /* produced sample */\r
863                 unsigned int eg_out, eg_out2, eg_out4;\r
864 \r
865                 if (ct->pack & 8) { /* LFO enabled ? (test Earthworm Jim in between demo 1 and 2) */\r
866                         ct->pack = (ct->pack&0xffff) | (advance_lfo(ct->pack >> 16, ct->lfo_cnt, ct->lfo_cnt + ct->lfo_inc) << 16);\r
867                         ct->lfo_cnt += ct->lfo_inc;\r
868                 }\r
869 \r
870                 ct->eg_timer += ct->eg_timer_add;\r
871                 while (ct->eg_timer >= EG_TIMER_OVERFLOW)\r
872                 {\r
873                         ct->eg_timer -= EG_TIMER_OVERFLOW;\r
874                         ct->eg_cnt++;\r
875 \r
876                         if (ct->CH->SLOT[SLOT1].state != EG_OFF) ct->vol_out1 = update_eg_phase(&ct->CH->SLOT[SLOT1], ct->eg_cnt);\r
877                         if (ct->CH->SLOT[SLOT2].state != EG_OFF) ct->vol_out2 = update_eg_phase(&ct->CH->SLOT[SLOT2], ct->eg_cnt);\r
878                         if (ct->CH->SLOT[SLOT3].state != EG_OFF) ct->vol_out3 = update_eg_phase(&ct->CH->SLOT[SLOT3], ct->eg_cnt);\r
879                         if (ct->CH->SLOT[SLOT4].state != EG_OFF) ct->vol_out4 = update_eg_phase(&ct->CH->SLOT[SLOT4], ct->eg_cnt);\r
880                 }\r
881 \r
882                 if (ct->pack & 4) continue; /* output disabled */\r
883 \r
884                 /* calculate channel sample */\r
885                 eg_out = ct->vol_out1;\r
886                 if ( (ct->pack & 8) && (ct->pack&(1<<(SLOT1+8))) ) eg_out += ct->pack >> (((ct->pack&0xc0)>>6)+24);\r
887 \r
888                 if( eg_out < ENV_QUIET )        /* SLOT 1 */\r
889                 {\r
890                         int out = 0;\r
891 \r
892                         if (ct->pack&0xf000) out = ((ct->op1_out>>16) + (ct->op1_out<<16>>16)) << ((ct->pack&0xf000)>>12); /* op1_out0 + op1_out1 */\r
893                         ct->op1_out <<= 16;\r
894                         ct->op1_out |= (unsigned short)op_calc1(ct->phase1, eg_out, out);\r
895                 } else {\r
896                         ct->op1_out <<= 16; /* op1_out0 = op1_out1; op1_out1 = 0; */\r
897                 }\r
898 \r
899                 eg_out  = ct->vol_out3; // volume_calc(&CH->SLOT[SLOT3]);\r
900                 eg_out2 = ct->vol_out2; // volume_calc(&CH->SLOT[SLOT2]);\r
901                 eg_out4 = ct->vol_out4; // volume_calc(&CH->SLOT[SLOT4]);\r
902 \r
903                 if (ct->pack & 8) {\r
904                         unsigned int add = ct->pack >> (((ct->pack&0xc0)>>6)+24);\r
905                         if (ct->pack & (1<<(SLOT3+8))) eg_out  += add;\r
906                         if (ct->pack & (1<<(SLOT2+8))) eg_out2 += add;\r
907                         if (ct->pack & (1<<(SLOT4+8))) eg_out4 += add;\r
908                 }\r
909 \r
910                 switch( ct->CH->ALGO )\r
911                 {\r
912                         case 0:\r
913                         {\r
914                                 /* M1---C1---MEM---M2---C2---OUT */\r
915                                 int m2,c1,c2=0; /* Phase Modulation input for operators 2,3,4 */\r
916                                 m2 = ct->mem;\r
917                                 c1 = ct->op1_out>>16;\r
918                                 if( eg_out  < ENV_QUIET ) {             /* SLOT 3 */\r
919                                         c2  = op_calc(ct->phase3, eg_out,  m2);\r
920                                 }\r
921                                 if( eg_out2 < ENV_QUIET ) {             /* SLOT 2 */\r
922                                         ct->mem = op_calc(ct->phase2, eg_out2, c1);\r
923                                 }\r
924                                 else ct->mem = 0;\r
925                                 if( eg_out4 < ENV_QUIET ) {             /* SLOT 4 */\r
926                                         smp = op_calc(ct->phase4, eg_out4, c2);\r
927                                 }\r
928                                 break;\r
929                         }\r
930                         case 1:\r
931                         {\r
932                                 /* M1------+-MEM---M2---C2---OUT */\r
933                                 /*      C1-+                     */\r
934                                 int m2,c2=0;\r
935                                 m2 = ct->mem;\r
936                                 ct->mem = ct->op1_out>>16;\r
937                                 if( eg_out  < ENV_QUIET ) {             /* SLOT 3 */\r
938                                         c2  = op_calc(ct->phase3, eg_out,  m2);\r
939                                 }\r
940                                 if( eg_out2 < ENV_QUIET ) {             /* SLOT 2 */\r
941                                         ct->mem+= op_calc(ct->phase2, eg_out2, 0);\r
942                                 }\r
943                                 if( eg_out4 < ENV_QUIET ) {             /* SLOT 4 */\r
944                                         smp = op_calc(ct->phase4, eg_out4, c2);\r
945                                 }\r
946                                 break;\r
947                         }\r
948                         case 2:\r
949                         {\r
950                                 /* M1-----------------+-C2---OUT */\r
951                                 /*      C1---MEM---M2-+          */\r
952                                 int m2,c2;\r
953                                 m2 = ct->mem;\r
954                                 c2 = ct->op1_out>>16;\r
955                                 if( eg_out  < ENV_QUIET ) {             /* SLOT 3 */\r
956                                         c2 += op_calc(ct->phase3, eg_out,  m2);\r
957                                 }\r
958                                 if( eg_out2 < ENV_QUIET ) {             /* SLOT 2 */\r
959                                         ct->mem = op_calc(ct->phase2, eg_out2, 0);\r
960                                 }\r
961                                 else ct->mem = 0;\r
962                                 if( eg_out4 < ENV_QUIET ) {             /* SLOT 4 */\r
963                                         smp = op_calc(ct->phase4, eg_out4, c2);\r
964                                 }\r
965                                 break;\r
966                         }\r
967                         case 3:\r
968                         {\r
969                                 /* M1---C1---MEM------+-C2---OUT */\r
970                                 /*                 M2-+          */\r
971                                 int c1,c2;\r
972                                 c2 = ct->mem;\r
973                                 c1 = ct->op1_out>>16;\r
974                                 if( eg_out  < ENV_QUIET ) {             /* SLOT 3 */\r
975                                         c2 += op_calc(ct->phase3, eg_out,  0);\r
976                                 }\r
977                                 if( eg_out2 < ENV_QUIET ) {             /* SLOT 2 */\r
978                                         ct->mem = op_calc(ct->phase2, eg_out2, c1);\r
979                                 }\r
980                                 else ct->mem = 0;\r
981                                 if( eg_out4 < ENV_QUIET ) {             /* SLOT 4 */\r
982                                         smp = op_calc(ct->phase4, eg_out4, c2);\r
983                                 }\r
984                                 break;\r
985                         }\r
986                         case 4:\r
987                         {\r
988                                 /* M1---C1-+-OUT */\r
989                                 /* M2---C2-+     */\r
990                                 /* MEM: not used */\r
991                                 int c1,c2=0;\r
992                                 c1 = ct->op1_out>>16;\r
993                                 if( eg_out  < ENV_QUIET ) {             /* SLOT 3 */\r
994                                         c2  = op_calc(ct->phase3, eg_out,  0);\r
995                                 }\r
996                                 if( eg_out2 < ENV_QUIET ) {             /* SLOT 2 */\r
997                                         smp = op_calc(ct->phase2, eg_out2, c1);\r
998                                 }\r
999                                 if( eg_out4 < ENV_QUIET ) {             /* SLOT 4 */\r
1000                                         smp+= op_calc(ct->phase4, eg_out4, c2);\r
1001                                 }\r
1002                                 break;\r
1003                         }\r
1004                         case 5:\r
1005                         {\r
1006                                 /*    +----C1----+     */\r
1007                                 /* M1-+-MEM---M2-+-OUT */\r
1008                                 /*    +----C2----+     */\r
1009                                 int m2,c1,c2;\r
1010                                 m2 = ct->mem;\r
1011                                 ct->mem = c1 = c2 = ct->op1_out>>16;\r
1012                                 if( eg_out < ENV_QUIET ) {              /* SLOT 3 */\r
1013                                         smp = op_calc(ct->phase3, eg_out, m2);\r
1014                                 }\r
1015                                 if( eg_out2 < ENV_QUIET ) {             /* SLOT 2 */\r
1016                                         smp+= op_calc(ct->phase2, eg_out2, c1);\r
1017                                 }\r
1018                                 if( eg_out4 < ENV_QUIET ) {             /* SLOT 4 */\r
1019                                         smp+= op_calc(ct->phase4, eg_out4, c2);\r
1020                                 }\r
1021                                 break;\r
1022                         }\r
1023                         case 6:\r
1024                         {\r
1025                                 /* M1---C1-+     */\r
1026                                 /*      M2-+-OUT */\r
1027                                 /*      C2-+     */\r
1028                                 /* MEM: not used */\r
1029                                 int c1;\r
1030                                 c1 = ct->op1_out>>16;\r
1031                                 if( eg_out < ENV_QUIET ) {              /* SLOT 3 */\r
1032                                         smp = op_calc(ct->phase3, eg_out,  0);\r
1033                                 }\r
1034                                 if( eg_out2 < ENV_QUIET ) {             /* SLOT 2 */\r
1035                                         smp+= op_calc(ct->phase2, eg_out2, c1);\r
1036                                 }\r
1037                                 if( eg_out4 < ENV_QUIET ) {             /* SLOT 4 */\r
1038                                         smp+= op_calc(ct->phase4, eg_out4, 0);\r
1039                                 }\r
1040                                 break;\r
1041                         }\r
1042                         case 7:\r
1043                         {\r
1044                                 /* M1-+     */\r
1045                                 /* C1-+-OUT */\r
1046                                 /* M2-+     */\r
1047                                 /* C2-+     */\r
1048                                 /* MEM: not used*/\r
1049                                 smp = ct->op1_out>>16;\r
1050                                 if( eg_out < ENV_QUIET ) {              /* SLOT 3 */\r
1051                                         smp += op_calc(ct->phase3, eg_out,  0);\r
1052                                 }\r
1053                                 if( eg_out2 < ENV_QUIET ) {             /* SLOT 2 */\r
1054                                         smp += op_calc(ct->phase2, eg_out2, 0);\r
1055                                 }\r
1056                                 if( eg_out4 < ENV_QUIET ) {             /* SLOT 4 */\r
1057                                         smp += op_calc(ct->phase4, eg_out4, 0);\r
1058                                 }\r
1059                                 break;\r
1060                         }\r
1061                 }\r
1062                 /* done calculating channel sample */\r
1063 \r
1064                 /* mix sample to output buffer */\r
1065                 if (smp) {\r
1066                         if (ct->pack & 1) { /* stereo */\r
1067                                 if (ct->pack & 0x20) /* L */ /* TODO: check correctness */\r
1068                                         buffer[scounter*2] += smp;\r
1069                                 if (ct->pack & 0x10) /* R */\r
1070                                         buffer[scounter*2+1] += smp;\r
1071                         } else {\r
1072                                 buffer[scounter] += smp;\r
1073                         }\r
1074                         ct->algo = 8; // algo is only used in asm, here only bit3 is used\r
1075                 }\r
1076 \r
1077                 /* update phase counters AFTER output calculations */\r
1078                 ct->phase1 += ct->incr1;\r
1079                 ct->phase2 += ct->incr2;\r
1080                 ct->phase3 += ct->incr3;\r
1081                 ct->phase4 += ct->incr4;\r
1082         }\r
1083 }\r
1084 #else\r
1085 void chan_render_loop(chan_rend_context *ct, int *buffer, unsigned short length);\r
1086 #endif\r
1087 \r
1088 static chan_rend_context crct;\r
1089 \r
1090 static int chan_render(int *buffer, int length, int c, UINT32 flags) // flags: stereo, ?, disabled, ?, pan_r, pan_l\r
1091 {\r
1092         crct.CH = &ym2612.CH[c];\r
1093         crct.mem = crct.CH->mem_value;          /* one sample delay memory */\r
1094         crct.lfo_cnt = ym2612.OPN.lfo_cnt;\r
1095         crct.lfo_inc = ym2612.OPN.lfo_inc;\r
1096 \r
1097         flags &= 0x35;\r
1098 \r
1099         if (crct.lfo_inc) {\r
1100                 flags |= 8;\r
1101                 flags |= g_lfo_ampm << 16;\r
1102                 flags |= crct.CH->AMmasks << 8;\r
1103                 if (crct.CH->ams == 8) // no ams\r
1104                      flags &= ~0xf00;\r
1105                 else flags |= (crct.CH->ams&3)<<6;\r
1106         }\r
1107         flags |= (crct.CH->FB&0xf)<<12;                         /* feedback shift */\r
1108         crct.pack = flags;\r
1109 \r
1110         crct.eg_cnt = ym2612.OPN.eg_cnt;                        /* envelope generator counter */\r
1111         crct.eg_timer = ym2612.OPN.eg_timer;\r
1112         crct.eg_timer_add = ym2612.OPN.eg_timer_add;\r
1113 \r
1114         /* precalculate phase modulation incr */\r
1115         crct.phase1 = crct.CH->SLOT[SLOT1].phase;\r
1116         crct.phase2 = crct.CH->SLOT[SLOT2].phase;\r
1117         crct.phase3 = crct.CH->SLOT[SLOT3].phase;\r
1118         crct.phase4 = crct.CH->SLOT[SLOT4].phase;\r
1119 \r
1120         /* current output from EG circuit (without AM from LFO) */\r
1121         crct.vol_out1 = crct.CH->SLOT[SLOT1].tl + ((UINT32)crct.CH->SLOT[SLOT1].volume);\r
1122         crct.vol_out2 = crct.CH->SLOT[SLOT2].tl + ((UINT32)crct.CH->SLOT[SLOT2].volume);\r
1123         crct.vol_out3 = crct.CH->SLOT[SLOT3].tl + ((UINT32)crct.CH->SLOT[SLOT3].volume);\r
1124         crct.vol_out4 = crct.CH->SLOT[SLOT4].tl + ((UINT32)crct.CH->SLOT[SLOT4].volume);\r
1125 \r
1126         crct.op1_out = crct.CH->op1_out;\r
1127         crct.algo = crct.CH->ALGO & 7;\r
1128 \r
1129         if(crct.CH->pms)\r
1130         {\r
1131                 /* add support for 3 slot mode */\r
1132                 UINT32 block_fnum = crct.CH->block_fnum;\r
1133 \r
1134                 UINT32 fnum_lfo   = ((block_fnum & 0x7f0) >> 4) * 32 * 8;\r
1135                 INT32  lfo_fn_table_index_offset = lfo_pm_table[ fnum_lfo + crct.CH->pms + ((crct.pack>>16)&0xff) ];\r
1136 \r
1137                 if (lfo_fn_table_index_offset)  /* LFO phase modulation active */\r
1138                 {\r
1139                         UINT8  blk;\r
1140                         UINT32 fn;\r
1141                         int kc,fc;\r
1142 \r
1143                         block_fnum = block_fnum*2 + lfo_fn_table_index_offset;\r
1144 \r
1145                         blk = (block_fnum&0x7000) >> 12;\r
1146                         fn  = block_fnum & 0xfff;\r
1147 \r
1148                         /* keyscale code */\r
1149                         kc = (blk<<2) | opn_fktable[fn >> 8];\r
1150                         /* phase increment counter */\r
1151                         fc = fn_table[fn]>>(7-blk);\r
1152 \r
1153                         crct.incr1 = ((fc+crct.CH->SLOT[SLOT1].DT[kc])*crct.CH->SLOT[SLOT1].mul) >> 1;\r
1154                         crct.incr2 = ((fc+crct.CH->SLOT[SLOT2].DT[kc])*crct.CH->SLOT[SLOT2].mul) >> 1;\r
1155                         crct.incr3 = ((fc+crct.CH->SLOT[SLOT3].DT[kc])*crct.CH->SLOT[SLOT3].mul) >> 1;\r
1156                         crct.incr4 = ((fc+crct.CH->SLOT[SLOT4].DT[kc])*crct.CH->SLOT[SLOT4].mul) >> 1;\r
1157                 }\r
1158                 else    /* LFO phase modulation  = zero */\r
1159                 {\r
1160                         crct.incr1 = crct.CH->SLOT[SLOT1].Incr;\r
1161                         crct.incr2 = crct.CH->SLOT[SLOT2].Incr;\r
1162                         crct.incr3 = crct.CH->SLOT[SLOT3].Incr;\r
1163                         crct.incr4 = crct.CH->SLOT[SLOT4].Incr;\r
1164                 }\r
1165         }\r
1166         else    /* no LFO phase modulation */\r
1167         {\r
1168                 crct.incr1 = crct.CH->SLOT[SLOT1].Incr;\r
1169                 crct.incr2 = crct.CH->SLOT[SLOT2].Incr;\r
1170                 crct.incr3 = crct.CH->SLOT[SLOT3].Incr;\r
1171                 crct.incr4 = crct.CH->SLOT[SLOT4].Incr;\r
1172         }\r
1173 \r
1174         chan_render_loop(&crct, buffer, length);\r
1175 \r
1176         crct.CH->op1_out = crct.op1_out;\r
1177         crct.CH->mem_value = crct.mem;\r
1178         if (crct.CH->SLOT[SLOT1].state | crct.CH->SLOT[SLOT2].state | crct.CH->SLOT[SLOT3].state | crct.CH->SLOT[SLOT4].state)\r
1179         {\r
1180                 crct.CH->SLOT[SLOT1].phase = crct.phase1;\r
1181                 crct.CH->SLOT[SLOT2].phase = crct.phase2;\r
1182                 crct.CH->SLOT[SLOT3].phase = crct.phase3;\r
1183                 crct.CH->SLOT[SLOT4].phase = crct.phase4;\r
1184         }\r
1185         else\r
1186                 ym2612.slot_mask &= ~(0xf << (c*4));\r
1187 \r
1188         // if this the last call, write back persistent stuff:\r
1189         if ((ym2612.slot_mask >> ((c+1)*4)) == 0)\r
1190         {\r
1191                 ym2612.OPN.eg_cnt = crct.eg_cnt;\r
1192                 ym2612.OPN.eg_timer = crct.eg_timer;\r
1193                 g_lfo_ampm = crct.pack >> 16;\r
1194                 ym2612.OPN.lfo_cnt = crct.lfo_cnt;\r
1195         }\r
1196 \r
1197         return (crct.algo & 8) >> 3; // had output\r
1198 }\r
1199 \r
1200 /* update phase increment and envelope generator */\r
1201 INLINE void refresh_fc_eg_slot(FM_SLOT *SLOT, int fc, int kc)\r
1202 {\r
1203         int ksr;\r
1204 \r
1205         /* (frequency) phase increment counter */\r
1206         SLOT->Incr = ((fc+SLOT->DT[kc])*SLOT->mul) >> 1;\r
1207 \r
1208         ksr = kc >> SLOT->KSR;\r
1209         if( SLOT->ksr != ksr )\r
1210         {\r
1211                 int eg_sh, eg_sel;\r
1212                 SLOT->ksr = ksr;\r
1213 \r
1214                 /* calculate envelope generator rates */\r
1215                 if ((SLOT->ar + SLOT->ksr) < 32+62)\r
1216                 {\r
1217                         eg_sh  = eg_rate_shift [SLOT->ar  + SLOT->ksr ];\r
1218                         eg_sel = eg_rate_select[SLOT->ar  + SLOT->ksr ];\r
1219                 }\r
1220                 else\r
1221                 {\r
1222                         eg_sh  = 0;\r
1223                         eg_sel = 17;\r
1224                 }\r
1225 \r
1226                 SLOT->eg_pack_ar = eg_inc_pack[eg_sel] | (eg_sh<<24);\r
1227 \r
1228                 eg_sh  = eg_rate_shift [SLOT->d1r + SLOT->ksr];\r
1229                 eg_sel = eg_rate_select[SLOT->d1r + SLOT->ksr];\r
1230 \r
1231                 SLOT->eg_pack_d1r = eg_inc_pack[eg_sel] | (eg_sh<<24);\r
1232 \r
1233                 eg_sh  = eg_rate_shift [SLOT->d2r + SLOT->ksr];\r
1234                 eg_sel = eg_rate_select[SLOT->d2r + SLOT->ksr];\r
1235 \r
1236                 SLOT->eg_pack_d2r = eg_inc_pack[eg_sel] | (eg_sh<<24);\r
1237 \r
1238                 eg_sh  = eg_rate_shift [SLOT->rr  + SLOT->ksr];\r
1239                 eg_sel = eg_rate_select[SLOT->rr  + SLOT->ksr];\r
1240 \r
1241                 SLOT->eg_pack_rr = eg_inc_pack[eg_sel] | (eg_sh<<24);\r
1242         }\r
1243 }\r
1244 \r
1245 /* update phase increment counters */\r
1246 INLINE void refresh_fc_eg_chan(FM_CH *CH)\r
1247 {\r
1248         if( CH->SLOT[SLOT1].Incr==-1){\r
1249                 int fc = CH->fc;\r
1250                 int kc = CH->kcode;\r
1251                 refresh_fc_eg_slot(&CH->SLOT[SLOT1] , fc , kc );\r
1252                 refresh_fc_eg_slot(&CH->SLOT[SLOT2] , fc , kc );\r
1253                 refresh_fc_eg_slot(&CH->SLOT[SLOT3] , fc , kc );\r
1254                 refresh_fc_eg_slot(&CH->SLOT[SLOT4] , fc , kc );\r
1255         }\r
1256 }\r
1257 \r
1258 /* initialize time tables */\r
1259 static void init_timetables(const UINT8 *dttable)\r
1260 {\r
1261         int i,d;\r
1262         double rate;\r
1263 \r
1264         /* DeTune table */\r
1265         for (d = 0;d <= 3;d++){\r
1266                 for (i = 0;i <= 31;i++){\r
1267                         rate = ((double)dttable[d*32 + i]) * SIN_LEN  * ym2612.OPN.ST.freqbase  * (1<<FREQ_SH) / ((double)(1<<20));\r
1268                         ym2612.OPN.ST.dt_tab[d][i]   = (INT32) rate;\r
1269                         ym2612.OPN.ST.dt_tab[d+4][i] = -ym2612.OPN.ST.dt_tab[d][i];\r
1270                 }\r
1271         }\r
1272 }\r
1273 \r
1274 \r
1275 static void reset_channels(FM_CH *CH)\r
1276 {\r
1277         int c,s;\r
1278 \r
1279         ym2612.OPN.ST.mode   = 0;       /* normal mode */\r
1280         ym2612.OPN.ST.TA     = 0;\r
1281         ym2612.OPN.ST.TAC    = 0;\r
1282         ym2612.OPN.ST.TB     = 0;\r
1283         ym2612.OPN.ST.TBC    = 0;\r
1284 \r
1285         for( c = 0 ; c < 6 ; c++ )\r
1286         {\r
1287                 CH[c].fc = 0;\r
1288                 for(s = 0 ; s < 4 ; s++ )\r
1289                 {\r
1290                         CH[c].SLOT[s].state= EG_OFF;\r
1291                         CH[c].SLOT[s].volume = MAX_ATT_INDEX;\r
1292                 }\r
1293         }\r
1294         ym2612.slot_mask = 0;\r
1295 }\r
1296 \r
1297 /* initialize generic tables */\r
1298 static void init_tables(void)\r
1299 {\r
1300         signed int i,x,y,p;\r
1301         signed int n;\r
1302         double o,m;\r
1303 \r
1304         for (i=0; i < 256; i++)\r
1305         {\r
1306                 /* non-standard sinus */\r
1307                 m = sin( ((i*2)+1) * M_PI / SIN_LEN ); /* checked against the real chip */\r
1308 \r
1309                 /* we never reach zero here due to ((i*2)+1) */\r
1310 \r
1311                 if (m>0.0)\r
1312                         o = 8*log(1.0/m)/log(2);        /* convert to 'decibels' */\r
1313                 else\r
1314                         o = 8*log(-1.0/m)/log(2);       /* convert to 'decibels' */\r
1315 \r
1316                 o = o / (ENV_STEP/4);\r
1317 \r
1318                 n = (int)(2.0*o);\r
1319                 if (n&1)                                                /* round to nearest */\r
1320                         n = (n>>1)+1;\r
1321                 else\r
1322                         n = n>>1;\r
1323 \r
1324                 ym_sin_tab[ i ] = n;\r
1325                 //dprintf("FM.C: sin [%4i]= %4i", i, ym_sin_tab[i]);\r
1326         }\r
1327 \r
1328         //dprintf("FM.C: ENV_QUIET= %08x", ENV_QUIET );\r
1329 \r
1330 \r
1331         for (x=0; x < TL_RES_LEN; x++)\r
1332         {\r
1333                 m = (1<<16) / pow(2, (x+1) * (ENV_STEP/4.0) / 8.0);\r
1334                 m = floor(m);\r
1335 \r
1336                 /* we never reach (1<<16) here due to the (x+1) */\r
1337                 /* result fits within 16 bits at maximum */\r
1338 \r
1339                 n = (int)m;             /* 16 bits here */\r
1340                 n >>= 4;                /* 12 bits here */\r
1341                 if (n&1)                /* round to nearest */\r
1342                         n = (n>>1)+1;\r
1343                 else\r
1344                         n = n>>1;\r
1345                                                 /* 11 bits here (rounded) */\r
1346                 n <<= 2;                /* 13 bits here (as in real chip) */\r
1347                 ym_tl_tab2[ x ] = n;\r
1348 \r
1349                 for (i=1; i < 13; i++)\r
1350                 {\r
1351                         ym_tl_tab2[ x + i*TL_RES_LEN ] = n >> i;\r
1352                 }\r
1353         }\r
1354 \r
1355         for (x=0; x < 256; x++)\r
1356         {\r
1357                 int sin = ym_sin_tab[ x ];\r
1358 \r
1359                 for (y=0; y < 2*13*TL_RES_LEN/8; y+=2)\r
1360                 {\r
1361                         p = (y<<2) + sin;\r
1362                         if (p >= 13*TL_RES_LEN)\r
1363                                  ym_tl_tab[(y<<7) | x] = 0;\r
1364                         else ym_tl_tab[(y<<7) | x] = ym_tl_tab2[p];\r
1365                 }\r
1366         }\r
1367 \r
1368 \r
1369         /* build LFO PM modulation table */\r
1370         for(i = 0; i < 8; i++) /* 8 PM depths */\r
1371         {\r
1372                 UINT8 fnum;\r
1373                 for (fnum=0; fnum<128; fnum++) /* 7 bits meaningful of F-NUMBER */\r
1374                 {\r
1375                         UINT8 value;\r
1376                         UINT8 step;\r
1377                         UINT32 offset_depth = i;\r
1378                         UINT32 offset_fnum_bit;\r
1379                         UINT32 bit_tmp;\r
1380 \r
1381                         for (step=0; step<8; step++)\r
1382                         {\r
1383                                 value = 0;\r
1384                                 for (bit_tmp=0; bit_tmp<7; bit_tmp++) /* 7 bits */\r
1385                                 {\r
1386                                         if (fnum & (1<<bit_tmp)) /* only if bit "bit_tmp" is set */\r
1387                                         {\r
1388                                                 offset_fnum_bit = bit_tmp * 8;\r
1389                                                 value += lfo_pm_output[offset_fnum_bit + offset_depth][step];\r
1390                                         }\r
1391                                 }\r
1392                                 lfo_pm_table[(fnum*32*8) + (i*32) + step   + 0] = value;\r
1393                                 lfo_pm_table[(fnum*32*8) + (i*32) +(step^7)+ 8] = value;\r
1394                                 lfo_pm_table[(fnum*32*8) + (i*32) + step   +16] = -value;\r
1395                                 lfo_pm_table[(fnum*32*8) + (i*32) +(step^7)+24] = -value;\r
1396                         }\r
1397                 }\r
1398         }\r
1399 }\r
1400 \r
1401 \r
1402 /* CSM Key Controll */\r
1403 #if 0\r
1404 INLINE void CSMKeyControll(FM_CH *CH)\r
1405 {\r
1406         /* this is wrong, atm */\r
1407 \r
1408         /* all key on */\r
1409         FM_KEYON(CH,SLOT1);\r
1410         FM_KEYON(CH,SLOT2);\r
1411         FM_KEYON(CH,SLOT3);\r
1412         FM_KEYON(CH,SLOT4);\r
1413 }\r
1414 #endif\r
1415 \r
1416 \r
1417 /* prescaler set (and make time tables) */\r
1418 static void OPNSetPres(int pres)\r
1419 {\r
1420         int i;\r
1421 \r
1422         /* frequency base */\r
1423         ym2612.OPN.ST.freqbase = (ym2612.OPN.ST.rate) ? ((double)ym2612.OPN.ST.clock / ym2612.OPN.ST.rate) / pres : 0;\r
1424 \r
1425         ym2612.OPN.eg_timer_add  = (1<<EG_SH) * ym2612.OPN.ST.freqbase;\r
1426 \r
1427 \r
1428         /* make time tables */\r
1429         init_timetables( dt_tab );\r
1430 \r
1431         /* there are 2048 FNUMs that can be generated using FNUM/BLK registers\r
1432         but LFO works with one more bit of a precision so we really need 4096 elements */\r
1433         /* calculate fnumber -> increment counter table */\r
1434         for(i = 0; i < 4096; i++)\r
1435         {\r
1436                 /* freq table for octave 7 */\r
1437                 /* OPN phase increment counter = 20bit */\r
1438                 fn_table[i] = (UINT32)( (double)i * 32 * ym2612.OPN.ST.freqbase * (1<<(FREQ_SH-10)) ); /* -10 because chip works with 10.10 fixed point, while we use 16.16 */\r
1439         }\r
1440 \r
1441         /* LFO freq. table */\r
1442         for(i = 0; i < 8; i++)\r
1443         {\r
1444                 /* Amplitude modulation: 64 output levels (triangle waveform); 1 level lasts for one of "lfo_samples_per_step" samples */\r
1445                 /* Phase modulation: one entry from lfo_pm_output lasts for one of 4 * "lfo_samples_per_step" samples  */\r
1446                 ym2612.OPN.lfo_freq[i] = (1.0 / lfo_samples_per_step[i]) * (1<<LFO_SH) * ym2612.OPN.ST.freqbase;\r
1447         }\r
1448 }\r
1449 \r
1450 \r
1451 /* write a OPN register (0x30-0xff) */\r
1452 static int OPNWriteReg(int r, int v)\r
1453 {\r
1454         int ret = 1;\r
1455         FM_CH *CH;\r
1456         FM_SLOT *SLOT;\r
1457 \r
1458         UINT8 c = OPN_CHAN(r);\r
1459 \r
1460         if (c == 3) return 0; /* 0xX3,0xX7,0xXB,0xXF */\r
1461 \r
1462         if (r >= 0x100) c+=3;\r
1463 \r
1464         CH = &ym2612.CH[c];\r
1465 \r
1466         SLOT = &(CH->SLOT[OPN_SLOT(r)]);\r
1467 \r
1468         switch( r & 0xf0 ) {\r
1469         case 0x30:      /* DET , MUL */\r
1470                 set_det_mul(CH,SLOT,v);\r
1471                 break;\r
1472 \r
1473         case 0x40:      /* TL */\r
1474                 set_tl(SLOT,v);\r
1475                 break;\r
1476 \r
1477         case 0x50:      /* KS, AR */\r
1478                 set_ar_ksr(CH,SLOT,v);\r
1479                 break;\r
1480 \r
1481         case 0x60:      /* bit7 = AM ENABLE, DR */\r
1482                 set_dr(SLOT,v);\r
1483                 if(v&0x80) CH->AMmasks |=   1<<OPN_SLOT(r);\r
1484                 else       CH->AMmasks &= ~(1<<OPN_SLOT(r));\r
1485                 break;\r
1486 \r
1487         case 0x70:      /*     SR */\r
1488                 set_sr(SLOT,v);\r
1489                 break;\r
1490 \r
1491         case 0x80:      /* SL, RR */\r
1492                 set_sl_rr(SLOT,v);\r
1493                 break;\r
1494 \r
1495         case 0x90:      /* SSG-EG */\r
1496                 // removed.\r
1497                 ret = 0;\r
1498                 break;\r
1499 \r
1500         case 0xa0:\r
1501                 switch( OPN_SLOT(r) ){\r
1502                 case 0:         /* 0xa0-0xa2 : FNUM1 */\r
1503                         {\r
1504                                 UINT32 fn = (((UINT32)( (ym2612.OPN.ST.fn_h)&7))<<8) + v;\r
1505                                 UINT8 blk = ym2612.OPN.ST.fn_h>>3;\r
1506                                 /* keyscale code */\r
1507                                 CH->kcode = (blk<<2) | opn_fktable[fn >> 7];\r
1508                                 /* phase increment counter */\r
1509                                 CH->fc = fn_table[fn*2]>>(7-blk);\r
1510 \r
1511                                 /* store fnum in clear form for LFO PM calculations */\r
1512                                 CH->block_fnum = (blk<<11) | fn;\r
1513 \r
1514                                 CH->SLOT[SLOT1].Incr=-1;\r
1515                         }\r
1516                         break;\r
1517                 case 1:         /* 0xa4-0xa6 : FNUM2,BLK */\r
1518                         ym2612.OPN.ST.fn_h = v&0x3f;\r
1519                         ret = 0;\r
1520                         break;\r
1521                 case 2:         /* 0xa8-0xaa : 3CH FNUM1 */\r
1522                         if(r < 0x100)\r
1523                         {\r
1524                                 UINT32 fn = (((UINT32)(ym2612.OPN.SL3.fn_h&7))<<8) + v;\r
1525                                 UINT8 blk = ym2612.OPN.SL3.fn_h>>3;\r
1526                                 /* keyscale code */\r
1527                                 ym2612.OPN.SL3.kcode[c]= (blk<<2) | opn_fktable[fn >> 7];\r
1528                                 /* phase increment counter */\r
1529                                 ym2612.OPN.SL3.fc[c] = fn_table[fn*2]>>(7-blk);\r
1530                                 ym2612.OPN.SL3.block_fnum[c] = fn;\r
1531                                 ym2612.CH[2].SLOT[SLOT1].Incr=-1;\r
1532                         }\r
1533                         break;\r
1534                 case 3:         /* 0xac-0xae : 3CH FNUM2,BLK */\r
1535                         if(r < 0x100)\r
1536                                 ym2612.OPN.SL3.fn_h = v&0x3f;\r
1537                         ret = 0;\r
1538                         break;\r
1539                 default:\r
1540                         ret = 0;\r
1541                         break;\r
1542                 }\r
1543                 break;\r
1544 \r
1545         case 0xb0:\r
1546                 switch( OPN_SLOT(r) ){\r
1547                 case 0:         /* 0xb0-0xb2 : FB,ALGO */\r
1548                         {\r
1549                                 int feedback = (v>>3)&7;\r
1550                                 CH->ALGO = v&7;\r
1551                                 CH->FB   = feedback ? feedback+6 : 0;\r
1552                         }\r
1553                         break;\r
1554                 case 1:         /* 0xb4-0xb6 : L , R , AMS , PMS (YM2612/YM2610B/YM2610/YM2608) */\r
1555                         {\r
1556                                 int panshift = c<<1;\r
1557 \r
1558                                 /* b0-2 PMS */\r
1559                                 CH->pms = (v & 7) * 32; /* CH->pms = PM depth * 32 (index in lfo_pm_table) */\r
1560 \r
1561                                 /* b4-5 AMS */\r
1562                                 CH->ams = lfo_ams_depth_shift[(v>>4) & 3];\r
1563 \r
1564                                 /* PAN :  b7 = L, b6 = R */\r
1565                                 ym2612.OPN.pan &= ~(3<<panshift);\r
1566                                 ym2612.OPN.pan |= ((v & 0xc0) >> 6) << panshift; // ..LRLR\r
1567                         }\r
1568                         break;\r
1569                 default:\r
1570                         ret = 0;\r
1571                         break;\r
1572                 }\r
1573                 break;\r
1574         default:\r
1575                 ret = 0;\r
1576                 break;\r
1577         }\r
1578 \r
1579         return ret;\r
1580 }\r
1581 \r
1582 \r
1583 /*******************************************************************************/\r
1584 /*      YM2612 local section                                                   */\r
1585 /*******************************************************************************/\r
1586 \r
1587 /* Generate samples for YM2612 */\r
1588 int YM2612UpdateOne_(int *buffer, int length, int stereo, int is_buf_empty)\r
1589 {\r
1590         int pan;\r
1591         int active_chs = 0;\r
1592 \r
1593         // if !is_buf_empty, it means it has valid samples to mix with, else it may contain trash\r
1594         if (is_buf_empty) memset32(buffer, 0, length<<stereo);\r
1595 \r
1596 /*\r
1597         {\r
1598                 int c, s;\r
1599                 ppp();\r
1600                 for (c = 0; c < 6; c++) {\r
1601                         int slr = 0, slm;\r
1602                         printf("%i: ", c);\r
1603                         for (s = 0; s < 4; s++) {\r
1604                                 if (ym2612.CH[c].SLOT[s].state != EG_OFF) slr = 1;\r
1605                                 printf(" %i", ym2612.CH[c].SLOT[s].state != EG_OFF);\r
1606                         }\r
1607                         slm = (ym2612.slot_mask&(0xf<<(c*4))) ? 1 : 0;\r
1608                         printf(" | %i", slm);\r
1609                         printf(" | %i\n", ym2612.CH[c].SLOT[SLOT1].Incr==-1);\r
1610                         if (slr != slm) exit(1);\r
1611                 }\r
1612         }\r
1613 */\r
1614         /* refresh PG and EG */\r
1615         refresh_fc_eg_chan( &ym2612.CH[0] );\r
1616         refresh_fc_eg_chan( &ym2612.CH[1] );\r
1617         if( (ym2612.OPN.ST.mode & 0xc0) )\r
1618         {\r
1619                 /* 3SLOT MODE */\r
1620                 if( ym2612.CH[2].SLOT[SLOT1].Incr==-1)\r
1621                 {\r
1622                         refresh_fc_eg_slot(&ym2612.CH[2].SLOT[SLOT1], ym2612.OPN.SL3.fc[1], ym2612.OPN.SL3.kcode[1] );\r
1623                         refresh_fc_eg_slot(&ym2612.CH[2].SLOT[SLOT2], ym2612.OPN.SL3.fc[2], ym2612.OPN.SL3.kcode[2] );\r
1624                         refresh_fc_eg_slot(&ym2612.CH[2].SLOT[SLOT3], ym2612.OPN.SL3.fc[0], ym2612.OPN.SL3.kcode[0] );\r
1625                         refresh_fc_eg_slot(&ym2612.CH[2].SLOT[SLOT4], ym2612.CH[2].fc , ym2612.CH[2].kcode );\r
1626                 }\r
1627         } else refresh_fc_eg_chan( &ym2612.CH[2] );\r
1628         refresh_fc_eg_chan( &ym2612.CH[3] );\r
1629         refresh_fc_eg_chan( &ym2612.CH[4] );\r
1630         refresh_fc_eg_chan( &ym2612.CH[5] );\r
1631 \r
1632         pan = ym2612.OPN.pan;\r
1633         if (stereo) stereo = 1;\r
1634 \r
1635         /* mix to 32bit dest */\r
1636         // flags: stereo, ?, disabled, ?, pan_r, pan_l\r
1637         if (ym2612.slot_mask & 0x00000f) active_chs |= chan_render(buffer, length, 0, stereo|((pan&0x003)<<4)) << 0;\r
1638         if (ym2612.slot_mask & 0x0000f0) active_chs |= chan_render(buffer, length, 1, stereo|((pan&0x00c)<<2)) << 1;\r
1639         if (ym2612.slot_mask & 0x000f00) active_chs |= chan_render(buffer, length, 2, stereo|((pan&0x030)   )) << 2;\r
1640         if (ym2612.slot_mask & 0x00f000) active_chs |= chan_render(buffer, length, 3, stereo|((pan&0x0c0)>>2)) << 3;\r
1641         if (ym2612.slot_mask & 0x0f0000) active_chs |= chan_render(buffer, length, 4, stereo|((pan&0x300)>>4)) << 4;\r
1642         if (ym2612.slot_mask & 0xf00000) active_chs |= chan_render(buffer, length, 5, stereo|((pan&0xc00)>>6)|(ym2612.dacen<<2)) << 5;\r
1643 \r
1644         return active_chs; // 1 if buffer updated\r
1645 }\r
1646 \r
1647 \r
1648 /* initialize YM2612 emulator */\r
1649 void YM2612Init_(int clock, int rate)\r
1650 {\r
1651         memset(&ym2612, 0, sizeof(ym2612));\r
1652         init_tables();\r
1653 \r
1654         ym2612.OPN.ST.clock = clock;\r
1655         ym2612.OPN.ST.rate = rate;\r
1656 \r
1657         /* Extend handler */\r
1658         YM2612ResetChip_();\r
1659 }\r
1660 \r
1661 \r
1662 /* reset */\r
1663 void YM2612ResetChip_(void)\r
1664 {\r
1665         int i;\r
1666 \r
1667         memset(ym2612.REGS, 0, sizeof(ym2612.REGS));\r
1668 \r
1669         OPNSetPres( 6*24 );\r
1670         set_timers( 0x30 ); /* mode 0 , timer reset */\r
1671         ym2612.REGS[0x27] = 0x30;\r
1672 \r
1673         ym2612.OPN.eg_timer = 0;\r
1674         ym2612.OPN.eg_cnt   = 0;\r
1675         ym2612.OPN.ST.status = 0;\r
1676 \r
1677         reset_channels( &ym2612.CH[0] );\r
1678         for(i = 0xb6 ; i >= 0xb4 ; i-- )\r
1679         {\r
1680                 OPNWriteReg(i      ,0xc0);\r
1681                 OPNWriteReg(i|0x100,0xc0);\r
1682                 ym2612.REGS[i      ] = 0xc0;\r
1683                 ym2612.REGS[i|0x100] = 0xc0;\r
1684         }\r
1685         for(i = 0xb2 ; i >= 0x30 ; i-- )\r
1686         {\r
1687                 OPNWriteReg(i      ,0);\r
1688                 OPNWriteReg(i|0x100,0);\r
1689         }\r
1690         for(i = 0x26 ; i >= 0x20 ; i-- ) OPNWriteReg(i,0);\r
1691         /* DAC mode clear */\r
1692         ym2612.dacen = 0;\r
1693         ym2612.addr_A1 = 0;\r
1694 }\r
1695 \r
1696 \r
1697 /* YM2612 write */\r
1698 /* a = address */\r
1699 /* v = value   */\r
1700 /* returns 1 if sample affecting state changed */\r
1701 int YM2612Write_(unsigned int a, unsigned int v)\r
1702 {\r
1703         int addr, ret=1;\r
1704 \r
1705         v &= 0xff;      /* adjust to 8 bit bus */\r
1706 \r
1707         switch( a&3){\r
1708         case 0: /* address port 0 */\r
1709                 ym2612.OPN.ST.address = v;\r
1710                 ym2612.addr_A1 = 0;\r
1711                 ret=0;\r
1712                 break;\r
1713 \r
1714         case 1: /* data port 0    */\r
1715                 if (ym2612.addr_A1 != 0) {\r
1716                         ret=0;\r
1717                         break;  /* verified on real YM2608 */\r
1718                 }\r
1719 \r
1720                 addr = ym2612.OPN.ST.address;\r
1721 \r
1722                 switch( addr & 0xf0 )\r
1723                 {\r
1724                 case 0x20:      /* 0x20-0x2f Mode */\r
1725                         switch( addr )\r
1726                         {\r
1727                         case 0x22:      /* LFO FREQ (YM2608/YM2610/YM2610B/YM2612) */\r
1728                                 if (v&0x08) /* LFO enabled ? */\r
1729                                 {\r
1730                                         ym2612.OPN.lfo_inc = ym2612.OPN.lfo_freq[v&7];\r
1731                                 }\r
1732                                 else\r
1733                                 {\r
1734                                         ym2612.OPN.lfo_inc = 0;\r
1735                                 }\r
1736                                 break;\r
1737 #if 0 // handled elsewhere\r
1738                         case 0x24: { // timer A High 8\r
1739                                         int TAnew = (ym2612.OPN.ST.TA & 0x03)|(((int)v)<<2);\r
1740                                         if(ym2612.OPN.ST.TA != TAnew) {\r
1741                                                 // we should reset ticker only if new value is written. Outrun requires this.\r
1742                                                 ym2612.OPN.ST.TA = TAnew;\r
1743                                                 ym2612.OPN.ST.TAC = (1024-TAnew)*18;\r
1744                                                 ym2612.OPN.ST.TAT = 0;\r
1745                                         }\r
1746                                 }\r
1747                                 ret=0;\r
1748                                 break;\r
1749                         case 0x25: { // timer A Low 2\r
1750                                         int TAnew = (ym2612.OPN.ST.TA & 0x3fc)|(v&3);\r
1751                                         if(ym2612.OPN.ST.TA != TAnew) {\r
1752                                                 ym2612.OPN.ST.TA = TAnew;\r
1753                                                 ym2612.OPN.ST.TAC = (1024-TAnew)*18;\r
1754                                                 ym2612.OPN.ST.TAT = 0;\r
1755                                         }\r
1756                                 }\r
1757                                 ret=0;\r
1758                                 break;\r
1759                         case 0x26: // timer B\r
1760                                 if(ym2612.OPN.ST.TB != v) {\r
1761                                         ym2612.OPN.ST.TB = v;\r
1762                                         ym2612.OPN.ST.TBC  = (256-v)<<4;\r
1763                                         ym2612.OPN.ST.TBC *= 18;\r
1764                                         ym2612.OPN.ST.TBT  = 0;\r
1765                                 }\r
1766                                 ret=0;\r
1767                                 break;\r
1768                         case 0x27:      /* mode, timer control */\r
1769                                 set_timers( v );\r
1770                                 ret=0;\r
1771                                 break;\r
1772 #endif\r
1773                         case 0x28:      /* key on / off */\r
1774                                 {\r
1775                                         UINT8 c;\r
1776 \r
1777                                         c = v & 0x03;\r
1778                                         if( c == 3 ) { ret=0; break; }\r
1779                                         if( v&0x04 ) c+=3;\r
1780                                         if(v&0x10) FM_KEYON(c,SLOT1); else FM_KEYOFF(c,SLOT1);\r
1781                                         if(v&0x20) FM_KEYON(c,SLOT2); else FM_KEYOFF(c,SLOT2);\r
1782                                         if(v&0x40) FM_KEYON(c,SLOT3); else FM_KEYOFF(c,SLOT3);\r
1783                                         if(v&0x80) FM_KEYON(c,SLOT4); else FM_KEYOFF(c,SLOT4);\r
1784                                         break;\r
1785                                 }\r
1786 #if 0\r
1787                         case 0x2a:      /* DAC data (YM2612) */\r
1788                                 ym2612.dacout = ((int)v - 0x80) << 6;   /* level unknown (notaz: 8 seems to be too much) */\r
1789                                 ret=0;\r
1790                                 break;\r
1791                         case 0x2b:      /* DAC Sel  (YM2612) */\r
1792                                 /* b7 = dac enable */\r
1793                                 ym2612.dacen = v & 0x80;\r
1794                                 ret=0;\r
1795                                 break;\r
1796 #endif\r
1797                         default:\r
1798                                 break;\r
1799                         }\r
1800                         break;\r
1801                 default:        /* 0x30-0xff OPN section */\r
1802                         /* write register */\r
1803                         ret = OPNWriteReg(addr,v);\r
1804                 }\r
1805                 break;\r
1806 \r
1807         case 2: /* address port 1 */\r
1808                 ym2612.OPN.ST.address = v;\r
1809                 ym2612.addr_A1 = 1;\r
1810                 ret=0;\r
1811                 break;\r
1812 \r
1813         case 3: /* data port 1    */\r
1814                 if (ym2612.addr_A1 != 1) {\r
1815                         ret=0;\r
1816                         break;  /* verified on real YM2608 */\r
1817                 }\r
1818 \r
1819                 addr = ym2612.OPN.ST.address | 0x100;\r
1820 \r
1821                 ret = OPNWriteReg(addr, v);\r
1822                 break;\r
1823         }\r
1824 /*\r
1825         if(ret) {\r
1826                 extern int Scanline;\r
1827                 dprintf("ymw [%i]", Scanline);\r
1828         }\r
1829 */\r
1830         return ret;\r
1831 }\r
1832 \r
1833 #if 0\r
1834 UINT8 YM2612Read_(void)\r
1835 {\r
1836         return ym2612.OPN.ST.status;\r
1837 }\r
1838 \r
1839 int YM2612PicoTick_(int n)\r
1840 {\r
1841         int ret = 0;\r
1842 \r
1843         // timer A\r
1844         if(ym2612.OPN.ST.mode & 0x01 && (ym2612.OPN.ST.TAT+=64*n) >= ym2612.OPN.ST.TAC) {\r
1845                 ym2612.OPN.ST.TAT -= ym2612.OPN.ST.TAC;\r
1846                 if(ym2612.OPN.ST.mode & 0x04) ym2612.OPN.ST.status |= 1;\r
1847                 // CSM mode total level latch and auto key on\r
1848                 if(ym2612.OPN.ST.mode & 0x80) {\r
1849                         CSMKeyControll( &(ym2612.CH[2]) ); // Vectorman2, etc.\r
1850                         ret = 1;\r
1851                 }\r
1852         }\r
1853 \r
1854         // timer B\r
1855         if(ym2612.OPN.ST.mode & 0x02 && (ym2612.OPN.ST.TBT+=64*n) >= ym2612.OPN.ST.TBC) {\r
1856                 ym2612.OPN.ST.TBT -= ym2612.OPN.ST.TBC;\r
1857                 if(ym2612.OPN.ST.mode & 0x08) ym2612.OPN.ST.status |= 2;\r
1858         }\r
1859 \r
1860         return ret;\r
1861 }\r
1862 #endif\r
1863 \r
1864 void YM2612PicoStateLoad_(void)\r
1865 {\r
1866         reset_channels( &ym2612.CH[0] );\r
1867 }\r
1868 \r
1869 #ifndef EXTERNAL_YM2612\r
1870 void *YM2612GetRegs(void)\r
1871 {\r
1872         return ym2612.REGS;\r
1873 }\r
1874 #endif\r
1875 \r