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