eeprom crash fix, PacMan2 hack
[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 static 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 int   *ym2612_dacen;\r
1588 INT32 *ym2612_dacout;\r
1589 FM_ST *ym2612_st;\r
1590 \r
1591 \r
1592 /* Generate samples for YM2612 */\r
1593 int YM2612UpdateOne_(int *buffer, int length, int stereo, int is_buf_empty)\r
1594 {\r
1595         int pan;\r
1596         int active_chs = 0;\r
1597 \r
1598         // if !is_buf_empty, it means it has valid samples to mix with, else it may contain trash\r
1599         if (is_buf_empty) memset32(buffer, 0, length<<stereo);\r
1600 \r
1601 /*\r
1602         {\r
1603                 int c, s;\r
1604                 ppp();\r
1605                 for (c = 0; c < 6; c++) {\r
1606                         int slr = 0, slm;\r
1607                         printf("%i: ", c);\r
1608                         for (s = 0; s < 4; s++) {\r
1609                                 if (ym2612.CH[c].SLOT[s].state != EG_OFF) slr = 1;\r
1610                                 printf(" %i", ym2612.CH[c].SLOT[s].state != EG_OFF);\r
1611                         }\r
1612                         slm = (ym2612.slot_mask&(0xf<<(c*4))) ? 1 : 0;\r
1613                         printf(" | %i", slm);\r
1614                         printf(" | %i\n", ym2612.CH[c].SLOT[SLOT1].Incr==-1);\r
1615                         if (slr != slm) exit(1);\r
1616                 }\r
1617         }\r
1618 */\r
1619         /* refresh PG and EG */\r
1620         refresh_fc_eg_chan( &ym2612.CH[0] );\r
1621         refresh_fc_eg_chan( &ym2612.CH[1] );\r
1622         if( (ym2612.OPN.ST.mode & 0xc0) )\r
1623         {\r
1624                 /* 3SLOT MODE */\r
1625                 if( ym2612.CH[2].SLOT[SLOT1].Incr==-1)\r
1626                 {\r
1627                         refresh_fc_eg_slot(&ym2612.CH[2].SLOT[SLOT1], ym2612.OPN.SL3.fc[1], ym2612.OPN.SL3.kcode[1] );\r
1628                         refresh_fc_eg_slot(&ym2612.CH[2].SLOT[SLOT2], ym2612.OPN.SL3.fc[2], ym2612.OPN.SL3.kcode[2] );\r
1629                         refresh_fc_eg_slot(&ym2612.CH[2].SLOT[SLOT3], ym2612.OPN.SL3.fc[0], ym2612.OPN.SL3.kcode[0] );\r
1630                         refresh_fc_eg_slot(&ym2612.CH[2].SLOT[SLOT4], ym2612.CH[2].fc , ym2612.CH[2].kcode );\r
1631                 }\r
1632         } else refresh_fc_eg_chan( &ym2612.CH[2] );\r
1633         refresh_fc_eg_chan( &ym2612.CH[3] );\r
1634         refresh_fc_eg_chan( &ym2612.CH[4] );\r
1635         refresh_fc_eg_chan( &ym2612.CH[5] );\r
1636 \r
1637         pan = ym2612.OPN.pan;\r
1638         if (stereo) stereo = 1;\r
1639 \r
1640         /* mix to 32bit dest */\r
1641         // flags: stereo, ?, disabled, ?, pan_r, pan_l\r
1642         if (ym2612.slot_mask & 0x00000f) active_chs |= chan_render(buffer, length, 0, stereo|((pan&0x003)<<4)) << 0;\r
1643         if (ym2612.slot_mask & 0x0000f0) active_chs |= chan_render(buffer, length, 1, stereo|((pan&0x00c)<<2)) << 1;\r
1644         if (ym2612.slot_mask & 0x000f00) active_chs |= chan_render(buffer, length, 2, stereo|((pan&0x030)   )) << 2;\r
1645         if (ym2612.slot_mask & 0x00f000) active_chs |= chan_render(buffer, length, 3, stereo|((pan&0x0c0)>>2)) << 3;\r
1646         if (ym2612.slot_mask & 0x0f0000) active_chs |= chan_render(buffer, length, 4, stereo|((pan&0x300)>>4)) << 4;\r
1647         if (ym2612.slot_mask & 0xf00000) active_chs |= chan_render(buffer, length, 5, stereo|((pan&0xc00)>>6)|(ym2612.dacen<<2)) << 5;\r
1648 \r
1649         return active_chs; // 1 if buffer updated\r
1650 }\r
1651 \r
1652 \r
1653 /* initialize YM2612 emulator */\r
1654 void YM2612Init_(int clock, int rate)\r
1655 {\r
1656         // notaz\r
1657         ym2612_dacen = &ym2612.dacen;\r
1658         ym2612_dacout = &ym2612.dacout;\r
1659         ym2612_st = &ym2612.OPN.ST;\r
1660 \r
1661         memset(&ym2612, 0, sizeof(ym2612));\r
1662         init_tables();\r
1663 \r
1664         ym2612.OPN.ST.clock = clock;\r
1665         ym2612.OPN.ST.rate = rate;\r
1666 \r
1667         /* Extend handler */\r
1668         YM2612ResetChip_();\r
1669 }\r
1670 \r
1671 \r
1672 /* reset */\r
1673 void YM2612ResetChip_(void)\r
1674 {\r
1675         int i;\r
1676 \r
1677         memset(ym2612.REGS, 0, sizeof(ym2612.REGS));\r
1678 \r
1679         OPNSetPres( 6*24 );\r
1680         set_timers( 0x30 ); /* mode 0 , timer reset */\r
1681         ym2612.REGS[0x27] = 0x30;\r
1682 \r
1683         ym2612.OPN.eg_timer = 0;\r
1684         ym2612.OPN.eg_cnt   = 0;\r
1685         ym2612.OPN.ST.status = 0;\r
1686 \r
1687         reset_channels( &ym2612.CH[0] );\r
1688         for(i = 0xb6 ; i >= 0xb4 ; i-- )\r
1689         {\r
1690                 OPNWriteReg(i      ,0xc0);\r
1691                 OPNWriteReg(i|0x100,0xc0);\r
1692                 ym2612.REGS[i      ] = 0xc0;\r
1693                 ym2612.REGS[i|0x100] = 0xc0;\r
1694         }\r
1695         for(i = 0xb2 ; i >= 0x30 ; i-- )\r
1696         {\r
1697                 OPNWriteReg(i      ,0);\r
1698                 OPNWriteReg(i|0x100,0);\r
1699         }\r
1700         for(i = 0x26 ; i >= 0x20 ; i-- ) OPNWriteReg(i,0);\r
1701         /* DAC mode clear */\r
1702         ym2612.dacen = 0;\r
1703         ym2612.addr_A1 = 0;\r
1704 }\r
1705 \r
1706 \r
1707 /* YM2612 write */\r
1708 /* a = address */\r
1709 /* v = value   */\r
1710 /* returns 1 if sample affecting state changed */\r
1711 int YM2612Write_(unsigned int a, unsigned int v)\r
1712 {\r
1713         int addr, ret=1;\r
1714 \r
1715         v &= 0xff;      /* adjust to 8 bit bus */\r
1716 \r
1717         switch( a&3){\r
1718         case 0: /* address port 0 */\r
1719                 ym2612.OPN.ST.address = v;\r
1720                 ym2612.addr_A1 = 0;\r
1721                 ret=0;\r
1722                 break;\r
1723 \r
1724         case 1: /* data port 0    */\r
1725                 if (ym2612.addr_A1 != 0) {\r
1726                         ret=0;\r
1727                         break;  /* verified on real YM2608 */\r
1728                 }\r
1729 \r
1730                 addr = ym2612.OPN.ST.address;\r
1731 #ifndef EXTERNAL_YM2612\r
1732                 ym2612.REGS[addr] = v;\r
1733 #endif\r
1734 \r
1735                 switch( addr & 0xf0 )\r
1736                 {\r
1737                 case 0x20:      /* 0x20-0x2f Mode */\r
1738                         switch( addr )\r
1739                         {\r
1740                         case 0x22:      /* LFO FREQ (YM2608/YM2610/YM2610B/YM2612) */\r
1741                                 if (v&0x08) /* LFO enabled ? */\r
1742                                 {\r
1743                                         ym2612.OPN.lfo_inc = ym2612.OPN.lfo_freq[v&7];\r
1744                                 }\r
1745                                 else\r
1746                                 {\r
1747                                         ym2612.OPN.lfo_inc = 0;\r
1748                                 }\r
1749                                 break;\r
1750                         case 0x24: { // timer A High 8\r
1751                                         int TAnew = (ym2612.OPN.ST.TA & 0x03)|(((int)v)<<2);\r
1752                                         if(ym2612.OPN.ST.TA != TAnew) {\r
1753                                                 // we should reset ticker only if new value is written. Outrun requires this.\r
1754                                                 ym2612.OPN.ST.TA = TAnew;\r
1755                                                 ym2612.OPN.ST.TAC = (1024-TAnew)*18;\r
1756                                                 ym2612.OPN.ST.TAT = 0;\r
1757                                         }\r
1758                                 }\r
1759                                 ret=0;\r
1760                                 break;\r
1761                         case 0x25: { // timer A Low 2\r
1762                                         int TAnew = (ym2612.OPN.ST.TA & 0x3fc)|(v&3);\r
1763                                         if(ym2612.OPN.ST.TA != TAnew) {\r
1764                                                 ym2612.OPN.ST.TA = TAnew;\r
1765                                                 ym2612.OPN.ST.TAC = (1024-TAnew)*18;\r
1766                                                 ym2612.OPN.ST.TAT = 0;\r
1767                                         }\r
1768                                 }\r
1769                                 ret=0;\r
1770                                 break;\r
1771                         case 0x26: // timer B\r
1772                                 if(ym2612.OPN.ST.TB != v) {\r
1773                                         ym2612.OPN.ST.TB = v;\r
1774                                         ym2612.OPN.ST.TBC  = (256-v)<<4;\r
1775                                         ym2612.OPN.ST.TBC *= 18;\r
1776                                         ym2612.OPN.ST.TBT  = 0;\r
1777                                 }\r
1778                                 ret=0;\r
1779                                 break;\r
1780                         case 0x27:      /* mode, timer control */\r
1781                                 set_timers( v );\r
1782                                 ret=0;\r
1783                                 break;\r
1784                         case 0x28:      /* key on / off */\r
1785                                 {\r
1786                                         UINT8 c;\r
1787 \r
1788                                         c = v & 0x03;\r
1789                                         if( c == 3 ) { ret=0; break; }\r
1790                                         if( v&0x04 ) c+=3;\r
1791                                         if(v&0x10) FM_KEYON(c,SLOT1); else FM_KEYOFF(c,SLOT1);\r
1792                                         if(v&0x20) FM_KEYON(c,SLOT2); else FM_KEYOFF(c,SLOT2);\r
1793                                         if(v&0x40) FM_KEYON(c,SLOT3); else FM_KEYOFF(c,SLOT3);\r
1794                                         if(v&0x80) FM_KEYON(c,SLOT4); else FM_KEYOFF(c,SLOT4);\r
1795                                         break;\r
1796                                 }\r
1797                         case 0x2a:      /* DAC data (YM2612) */\r
1798                                 ym2612.dacout = ((int)v - 0x80) << 6;   /* level unknown (notaz: 8 seems to be too much) */\r
1799                                 ret=0;\r
1800                                 break;\r
1801                         case 0x2b:      /* DAC Sel  (YM2612) */\r
1802                                 /* b7 = dac enable */\r
1803                                 ym2612.dacen = v & 0x80;\r
1804                                 ret=0;\r
1805                                 break;\r
1806                         default:\r
1807                                 break;\r
1808                         }\r
1809                         break;\r
1810                 default:        /* 0x30-0xff OPN section */\r
1811                         /* write register */\r
1812                         ret = OPNWriteReg(addr,v);\r
1813                 }\r
1814                 break;\r
1815 \r
1816         case 2: /* address port 1 */\r
1817                 ym2612.OPN.ST.address = v;\r
1818                 ym2612.addr_A1 = 1;\r
1819                 ret=0;\r
1820                 break;\r
1821 \r
1822         case 3: /* data port 1    */\r
1823                 if (ym2612.addr_A1 != 1) {\r
1824                         ret=0;\r
1825                         break;  /* verified on real YM2608 */\r
1826                 }\r
1827 \r
1828                 addr = ym2612.OPN.ST.address | 0x100;\r
1829 #ifndef EXTERNAL_YM2612\r
1830                 ym2612.REGS[addr] = v;\r
1831 #endif\r
1832 \r
1833                 ret = OPNWriteReg(addr, v);\r
1834                 break;\r
1835         }\r
1836 /*\r
1837         if(ret) {\r
1838                 extern int Scanline;\r
1839                 dprintf("ymw [%i]", Scanline);\r
1840         }\r
1841 */\r
1842         return ret;\r
1843 }\r
1844 \r
1845 #if 0\r
1846 UINT8 YM2612Read_(void)\r
1847 {\r
1848         return ym2612.OPN.ST.status;\r
1849 }\r
1850 \r
1851 int YM2612PicoTick_(int n)\r
1852 {\r
1853         int ret = 0;\r
1854 \r
1855         // timer A\r
1856         if(ym2612.OPN.ST.mode & 0x01 && (ym2612.OPN.ST.TAT+=64*n) >= ym2612.OPN.ST.TAC) {\r
1857                 ym2612.OPN.ST.TAT -= ym2612.OPN.ST.TAC;\r
1858                 if(ym2612.OPN.ST.mode & 0x04) ym2612.OPN.ST.status |= 1;\r
1859                 // CSM mode total level latch and auto key on\r
1860                 if(ym2612.OPN.ST.mode & 0x80) {\r
1861                         CSMKeyControll( &(ym2612.CH[2]) ); // Vectorman2, etc.\r
1862                         ret = 1;\r
1863                 }\r
1864         }\r
1865 \r
1866         // timer B\r
1867         if(ym2612.OPN.ST.mode & 0x02 && (ym2612.OPN.ST.TBT+=64*n) >= ym2612.OPN.ST.TBC) {\r
1868                 ym2612.OPN.ST.TBT -= ym2612.OPN.ST.TBC;\r
1869                 if(ym2612.OPN.ST.mode & 0x08) ym2612.OPN.ST.status |= 2;\r
1870         }\r
1871 \r
1872         return ret;\r
1873 }\r
1874 #endif\r
1875 \r
1876 void YM2612PicoStateLoad_(void)\r
1877 {\r
1878 #ifndef EXTERNAL_YM2612\r
1879         int i, real_A1 = ym2612.addr_A1;\r
1880 \r
1881         reset_channels( &ym2612.CH[0] );\r
1882 \r
1883         // feed all the registers and update internal state\r
1884         for(i = 0; i < 0x100; i++) {\r
1885                 YM2612Write_(0, i);\r
1886                 YM2612Write_(1, ym2612.REGS[i]);\r
1887         }\r
1888 \r
1889         for(i = 0; i < 0x100; i++) {\r
1890                 YM2612Write_(2, i);\r
1891                 YM2612Write_(3, ym2612.REGS[i|0x100]);\r
1892         }\r
1893 \r
1894         ym2612.addr_A1 = real_A1;\r
1895 #else\r
1896         reset_channels( &ym2612.CH[0] );\r
1897 #endif\r
1898 }\r
1899 \r
1900 #ifndef EXTERNAL_YM2612\r
1901 void *YM2612GetRegs(void)\r
1902 {\r
1903         return ym2612.REGS;\r
1904 }\r
1905 #endif\r
1906 \r