f7a073fbc052a4b18666236331a9addb97178f22
[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 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 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 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 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 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 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 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 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 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 \r
672 \r
673 INLINE signed int op_calc(UINT32 phase, unsigned int env, signed int pm)\r
674 {\r
675         int ret, sin = (phase>>16) + (pm>>1);\r
676         int neg = sin & 0x200;\r
677         if (sin & 0x100) sin ^= 0xff;\r
678         sin&=0xff;\r
679         env&=~1;\r
680 \r
681         // this was already checked\r
682         // if (env >= ENV_QUIET) // 384\r
683         //      return 0;\r
684 \r
685         ret = ym_tl_tab[sin | (env<<7)];\r
686 \r
687         return neg ? -ret : ret;\r
688 }\r
689 \r
690 INLINE signed int op_calc1(UINT32 phase, unsigned int env, signed int pm)\r
691 {\r
692         int ret, sin = (phase+pm)>>16;\r
693         int neg = sin & 0x200;\r
694         if (sin & 0x100) sin ^= 0xff;\r
695         sin&=0xff;\r
696         env&=~1;\r
697 \r
698         // if (env >= ENV_QUIET) // 384\r
699         //      return 0;\r
700 \r
701         ret = ym_tl_tab[sin | (env<<7)];\r
702 \r
703         return neg ? -ret : ret;\r
704 }\r
705 \r
706 #if !defined(_ASM_YM2612_C) || defined(EXTERNAL_YM2612)\r
707 /* advance LFO to next sample */\r
708 INLINE int advance_lfo(int lfo_ampm, UINT32 lfo_cnt_old, UINT32 lfo_cnt)\r
709 {\r
710         UINT8 pos;\r
711         UINT8 prev_pos;\r
712 \r
713         prev_pos = (lfo_cnt_old >> LFO_SH) & 127;\r
714 \r
715         pos = (lfo_cnt >> LFO_SH) & 127;\r
716 \r
717         /* update AM when LFO output changes */\r
718 \r
719         if (prev_pos != pos)\r
720         {\r
721                 lfo_ampm &= 0xff;\r
722                 /* triangle */\r
723                 /* AM: 0 to 126 step +2, 126 to 0 step -2 */\r
724                 if (pos<64)\r
725                         lfo_ampm |= ((pos&63) * 2) << 8;           /* 0 - 126 */\r
726                 else\r
727                         lfo_ampm |= (126 - (pos&63)*2) << 8;\r
728         }\r
729         else\r
730         {\r
731                 return lfo_ampm;\r
732         }\r
733 \r
734         /* PM works with 4 times slower clock */\r
735         prev_pos >>= 2;\r
736         pos >>= 2;\r
737         /* update PM when LFO output changes */\r
738         if (prev_pos != pos)\r
739         {\r
740                 lfo_ampm &= ~0xff;\r
741                 lfo_ampm |= pos; /* 0 - 32 */\r
742         }\r
743         return lfo_ampm;\r
744 }\r
745 \r
746 #define EG_INC_VAL() \\r
747         ((1 << ((pack >> ((eg_cnt>>shift)&7)*3)&7)) >> 1)\r
748 \r
749 STRICTINLINE UINT32 update_eg_phase(FM_SLOT *SLOT, UINT32 eg_cnt)\r
750 {\r
751         INT32 volume = SLOT->volume;\r
752 \r
753         switch(SLOT->state)\r
754         {\r
755                 case EG_ATT:            /* attack phase */\r
756                 {\r
757                         UINT32 pack = SLOT->eg_pack_ar;\r
758                         UINT32 shift = pack>>24;\r
759                         if ( !(eg_cnt & ((1<<shift)-1) ) )\r
760                         {\r
761                                 volume += ( ~volume * EG_INC_VAL() ) >>4;\r
762 \r
763                                 if (volume <= MIN_ATT_INDEX)\r
764                                 {\r
765                                         volume = MIN_ATT_INDEX;\r
766                                         SLOT->state = EG_DEC;\r
767                                 }\r
768                         }\r
769                         break;\r
770                 }\r
771 \r
772                 case EG_DEC:    /* decay phase */\r
773                 {\r
774                         UINT32 pack = SLOT->eg_pack_d1r;\r
775                         UINT32 shift = pack>>24;\r
776                         if ( !(eg_cnt & ((1<<shift)-1) ) )\r
777                         {\r
778                                 volume += EG_INC_VAL();\r
779 \r
780                                 if ( volume >= (INT32) SLOT->sl )\r
781                                         SLOT->state = EG_SUS;\r
782                         }\r
783                         break;\r
784                 }\r
785 \r
786                 case EG_SUS:    /* sustain phase */\r
787                 {\r
788                         UINT32 pack = SLOT->eg_pack_d2r;\r
789                         UINT32 shift = pack>>24;\r
790                         if ( !(eg_cnt & ((1<<shift)-1) ) )\r
791                         {\r
792                                 volume += EG_INC_VAL();\r
793 \r
794                                 if ( volume >= MAX_ATT_INDEX )\r
795                                 {\r
796                                         volume = MAX_ATT_INDEX;\r
797                                         /* do not change SLOT->state (verified on real chip) */\r
798                                 }\r
799                         }\r
800                         break;\r
801                 }\r
802 \r
803                 case EG_REL:    /* release phase */\r
804                 {\r
805                         UINT32 pack = SLOT->eg_pack_rr;\r
806                         UINT32 shift = pack>>24;\r
807                         if ( !(eg_cnt & ((1<<shift)-1) ) )\r
808                         {\r
809                                 volume += EG_INC_VAL();\r
810 \r
811                                 if ( volume >= MAX_ATT_INDEX )\r
812                                 {\r
813                                         volume = MAX_ATT_INDEX;\r
814                                         SLOT->state = EG_OFF;\r
815                                 }\r
816                         }\r
817                         break;\r
818                 }\r
819         }\r
820 \r
821         SLOT->volume = volume;\r
822         return SLOT->tl + ((UINT32)volume); /* tl is 7bit<<3, volume 0-1023 (0-2039 total) */\r
823 }\r
824 #endif\r
825 \r
826 \r
827 typedef struct\r
828 {\r
829         UINT16 vol_out1; /* 00: current output from EG circuit (without AM from LFO) */\r
830         UINT16 vol_out2;\r
831         UINT16 vol_out3;\r
832         UINT16 vol_out4;\r
833         UINT32 pad[2];\r
834         UINT32 phase1;   /* 10 */\r
835         UINT32 phase2;\r
836         UINT32 phase3;\r
837         UINT32 phase4;\r
838         UINT32 incr1;    /* 20: phase step */\r
839         UINT32 incr2;\r
840         UINT32 incr3;\r
841         UINT32 incr4;\r
842         UINT32 lfo_cnt;  /* 30 */\r
843         UINT32 lfo_inc;\r
844         INT32  mem;      /* one sample delay memory */\r
845         UINT32 eg_cnt;   /* envelope generator counter */\r
846         FM_CH  *CH;      /* 40: envelope generator counter */\r
847         UINT32 eg_timer;\r
848         UINT32 eg_timer_add;\r
849         UINT32 pack;     // 4c: stereo, lastchan, disabled, lfo_enabled | pan_r, pan_l, ams[2] | AMmasks[4] | FB[4] | lfo_ampm[16]\r
850         UINT32 algo;     /* 50: algo[3], was_update */\r
851         INT32  op1_out;\r
852 #ifdef _MIPS_ARCH_ALLEGREX\r
853         UINT32 pad1[3+8];\r
854 #endif\r
855 } chan_rend_context;\r
856 \r
857 \r
858 #if !defined(_ASM_YM2612_C) || defined(EXTERNAL_YM2612)\r
859 static void chan_render_loop(chan_rend_context *ct, int *buffer, int length)\r
860 {\r
861         int scounter;                                   /* sample counter */\r
862 \r
863         /* sample generating loop */\r
864         for (scounter = 0; scounter < length; scounter++)\r
865         {\r
866                 int smp = 0;            /* produced sample */\r
867                 unsigned int eg_out, eg_out2, eg_out4;\r
868 \r
869                 if (ct->pack & 8) { /* LFO enabled ? (test Earthworm Jim in between demo 1 and 2) */\r
870                         ct->pack = (ct->pack&0xffff) | (advance_lfo(ct->pack >> 16, ct->lfo_cnt, ct->lfo_cnt + ct->lfo_inc) << 16);\r
871                         ct->lfo_cnt += ct->lfo_inc;\r
872                 }\r
873 \r
874                 ct->eg_timer += ct->eg_timer_add;\r
875                 while (ct->eg_timer >= EG_TIMER_OVERFLOW)\r
876                 {\r
877                         ct->eg_timer -= EG_TIMER_OVERFLOW;\r
878                         ct->eg_cnt++;\r
879 \r
880                         if (ct->CH->SLOT[SLOT1].state != EG_OFF) ct->vol_out1 = update_eg_phase(&ct->CH->SLOT[SLOT1], ct->eg_cnt);\r
881                         if (ct->CH->SLOT[SLOT2].state != EG_OFF) ct->vol_out2 = update_eg_phase(&ct->CH->SLOT[SLOT2], ct->eg_cnt);\r
882                         if (ct->CH->SLOT[SLOT3].state != EG_OFF) ct->vol_out3 = update_eg_phase(&ct->CH->SLOT[SLOT3], ct->eg_cnt);\r
883                         if (ct->CH->SLOT[SLOT4].state != EG_OFF) ct->vol_out4 = update_eg_phase(&ct->CH->SLOT[SLOT4], ct->eg_cnt);\r
884                 }\r
885 \r
886                 if (ct->pack & 4) continue; /* output disabled */\r
887 \r
888                 /* calculate channel sample */\r
889                 eg_out = ct->vol_out1;\r
890                 if ( (ct->pack & 8) && (ct->pack&(1<<(SLOT1+8))) ) eg_out += ct->pack >> (((ct->pack&0xc0)>>6)+24);\r
891 \r
892                 if( eg_out < ENV_QUIET )        /* SLOT 1 */\r
893                 {\r
894                         int out = 0;\r
895 \r
896                         if (ct->pack&0xf000) out = ((ct->op1_out>>16) + ((ct->op1_out<<16)>>16)) << ((ct->pack&0xf000)>>12); /* op1_out0 + op1_out1 */\r
897                         ct->op1_out <<= 16;\r
898                         ct->op1_out |= (unsigned short)op_calc1(ct->phase1, eg_out, out);\r
899                 } else {\r
900                         ct->op1_out <<= 16; /* op1_out0 = op1_out1; op1_out1 = 0; */\r
901                 }\r
902 \r
903                 eg_out  = ct->vol_out3; // volume_calc(&CH->SLOT[SLOT3]);\r
904                 eg_out2 = ct->vol_out2; // volume_calc(&CH->SLOT[SLOT2]);\r
905                 eg_out4 = ct->vol_out4; // volume_calc(&CH->SLOT[SLOT4]);\r
906 \r
907                 if (ct->pack & 8) {\r
908                         unsigned int add = ct->pack >> (((ct->pack&0xc0)>>6)+24);\r
909                         if (ct->pack & (1<<(SLOT3+8))) eg_out  += add;\r
910                         if (ct->pack & (1<<(SLOT2+8))) eg_out2 += add;\r
911                         if (ct->pack & (1<<(SLOT4+8))) eg_out4 += add;\r
912                 }\r
913 \r
914                 switch( ct->CH->ALGO )\r
915                 {\r
916                         case 0:\r
917                         {\r
918                                 /* M1---C1---MEM---M2---C2---OUT */\r
919                                 int m2,c1,c2=0; /* Phase Modulation input for operators 2,3,4 */\r
920                                 m2 = ct->mem;\r
921                                 c1 = ct->op1_out>>16;\r
922                                 if( eg_out  < ENV_QUIET ) {             /* SLOT 3 */\r
923                                         c2  = op_calc(ct->phase3, eg_out,  m2);\r
924                                 }\r
925                                 if( eg_out2 < ENV_QUIET ) {             /* SLOT 2 */\r
926                                         ct->mem = op_calc(ct->phase2, eg_out2, c1);\r
927                                 }\r
928                                 else ct->mem = 0;\r
929                                 if( eg_out4 < ENV_QUIET ) {             /* SLOT 4 */\r
930                                         smp = op_calc(ct->phase4, eg_out4, c2);\r
931                                 }\r
932                                 break;\r
933                         }\r
934                         case 1:\r
935                         {\r
936                                 /* M1------+-MEM---M2---C2---OUT */\r
937                                 /*      C1-+                     */\r
938                                 int m2,c2=0;\r
939                                 m2 = ct->mem;\r
940                                 ct->mem = ct->op1_out>>16;\r
941                                 if( eg_out  < ENV_QUIET ) {             /* SLOT 3 */\r
942                                         c2  = op_calc(ct->phase3, eg_out,  m2);\r
943                                 }\r
944                                 if( eg_out2 < ENV_QUIET ) {             /* SLOT 2 */\r
945                                         ct->mem+= op_calc(ct->phase2, eg_out2, 0);\r
946                                 }\r
947                                 if( eg_out4 < ENV_QUIET ) {             /* SLOT 4 */\r
948                                         smp = op_calc(ct->phase4, eg_out4, c2);\r
949                                 }\r
950                                 break;\r
951                         }\r
952                         case 2:\r
953                         {\r
954                                 /* M1-----------------+-C2---OUT */\r
955                                 /*      C1---MEM---M2-+          */\r
956                                 int m2,c2;\r
957                                 m2 = ct->mem;\r
958                                 c2 = ct->op1_out>>16;\r
959                                 if( eg_out  < ENV_QUIET ) {             /* SLOT 3 */\r
960                                         c2 += op_calc(ct->phase3, eg_out,  m2);\r
961                                 }\r
962                                 if( eg_out2 < ENV_QUIET ) {             /* SLOT 2 */\r
963                                         ct->mem = op_calc(ct->phase2, eg_out2, 0);\r
964                                 }\r
965                                 else ct->mem = 0;\r
966                                 if( eg_out4 < ENV_QUIET ) {             /* SLOT 4 */\r
967                                         smp = op_calc(ct->phase4, eg_out4, c2);\r
968                                 }\r
969                                 break;\r
970                         }\r
971                         case 3:\r
972                         {\r
973                                 /* M1---C1---MEM------+-C2---OUT */\r
974                                 /*                 M2-+          */\r
975                                 int c1,c2;\r
976                                 c2 = ct->mem;\r
977                                 c1 = ct->op1_out>>16;\r
978                                 if( eg_out  < ENV_QUIET ) {             /* SLOT 3 */\r
979                                         c2 += op_calc(ct->phase3, eg_out,  0);\r
980                                 }\r
981                                 if( eg_out2 < ENV_QUIET ) {             /* SLOT 2 */\r
982                                         ct->mem = op_calc(ct->phase2, eg_out2, c1);\r
983                                 }\r
984                                 else ct->mem = 0;\r
985                                 if( eg_out4 < ENV_QUIET ) {             /* SLOT 4 */\r
986                                         smp = op_calc(ct->phase4, eg_out4, c2);\r
987                                 }\r
988                                 break;\r
989                         }\r
990                         case 4:\r
991                         {\r
992                                 /* M1---C1-+-OUT */\r
993                                 /* M2---C2-+     */\r
994                                 /* MEM: not used */\r
995                                 int c1,c2=0;\r
996                                 c1 = ct->op1_out>>16;\r
997                                 if( eg_out  < ENV_QUIET ) {             /* SLOT 3 */\r
998                                         c2  = op_calc(ct->phase3, eg_out,  0);\r
999                                 }\r
1000                                 if( eg_out2 < ENV_QUIET ) {             /* SLOT 2 */\r
1001                                         smp = op_calc(ct->phase2, eg_out2, c1);\r
1002                                 }\r
1003                                 if( eg_out4 < ENV_QUIET ) {             /* SLOT 4 */\r
1004                                         smp+= op_calc(ct->phase4, eg_out4, c2);\r
1005                                 }\r
1006                                 break;\r
1007                         }\r
1008                         case 5:\r
1009                         {\r
1010                                 /*    +----C1----+     */\r
1011                                 /* M1-+-MEM---M2-+-OUT */\r
1012                                 /*    +----C2----+     */\r
1013                                 int m2,c1,c2;\r
1014                                 m2 = ct->mem;\r
1015                                 ct->mem = c1 = c2 = ct->op1_out>>16;\r
1016                                 if( eg_out < ENV_QUIET ) {              /* SLOT 3 */\r
1017                                         smp = op_calc(ct->phase3, eg_out, m2);\r
1018                                 }\r
1019                                 if( eg_out2 < ENV_QUIET ) {             /* SLOT 2 */\r
1020                                         smp+= op_calc(ct->phase2, eg_out2, c1);\r
1021                                 }\r
1022                                 if( eg_out4 < ENV_QUIET ) {             /* SLOT 4 */\r
1023                                         smp+= op_calc(ct->phase4, eg_out4, c2);\r
1024                                 }\r
1025                                 break;\r
1026                         }\r
1027                         case 6:\r
1028                         {\r
1029                                 /* M1---C1-+     */\r
1030                                 /*      M2-+-OUT */\r
1031                                 /*      C2-+     */\r
1032                                 /* MEM: not used */\r
1033                                 int c1;\r
1034                                 c1 = ct->op1_out>>16;\r
1035                                 if( eg_out < ENV_QUIET ) {              /* SLOT 3 */\r
1036                                         smp = op_calc(ct->phase3, eg_out,  0);\r
1037                                 }\r
1038                                 if( eg_out2 < ENV_QUIET ) {             /* SLOT 2 */\r
1039                                         smp+= op_calc(ct->phase2, eg_out2, c1);\r
1040                                 }\r
1041                                 if( eg_out4 < ENV_QUIET ) {             /* SLOT 4 */\r
1042                                         smp+= op_calc(ct->phase4, eg_out4, 0);\r
1043                                 }\r
1044                                 break;\r
1045                         }\r
1046                         case 7:\r
1047                         {\r
1048                                 /* M1-+     */\r
1049                                 /* C1-+-OUT */\r
1050                                 /* M2-+     */\r
1051                                 /* C2-+     */\r
1052                                 /* MEM: not used*/\r
1053                                 smp = ct->op1_out>>16;\r
1054                                 if( eg_out < ENV_QUIET ) {              /* SLOT 3 */\r
1055                                         smp += op_calc(ct->phase3, eg_out,  0);\r
1056                                 }\r
1057                                 if( eg_out2 < ENV_QUIET ) {             /* SLOT 2 */\r
1058                                         smp += op_calc(ct->phase2, eg_out2, 0);\r
1059                                 }\r
1060                                 if( eg_out4 < ENV_QUIET ) {             /* SLOT 4 */\r
1061                                         smp += op_calc(ct->phase4, eg_out4, 0);\r
1062                                 }\r
1063                                 break;\r
1064                         }\r
1065                 }\r
1066                 /* done calculating channel sample */\r
1067 \r
1068                 /* mix sample to output buffer */\r
1069                 if (smp) {\r
1070                         if (ct->pack & 1) { /* stereo */\r
1071                                 if (ct->pack & 0x20) /* L */ /* TODO: check correctness */\r
1072                                         buffer[scounter*2] += smp;\r
1073                                 if (ct->pack & 0x10) /* R */\r
1074                                         buffer[scounter*2+1] += smp;\r
1075                         } else {\r
1076                                 buffer[scounter] += smp;\r
1077                         }\r
1078                         ct->algo = 8; // algo is only used in asm, here only bit3 is used\r
1079                 }\r
1080 \r
1081                 /* update phase counters AFTER output calculations */\r
1082                 ct->phase1 += ct->incr1;\r
1083                 ct->phase2 += ct->incr2;\r
1084                 ct->phase3 += ct->incr3;\r
1085                 ct->phase4 += ct->incr4;\r
1086         }\r
1087 }\r
1088 #else\r
1089 void chan_render_loop(chan_rend_context *ct, int *buffer, unsigned short length);\r
1090 #endif\r
1091 \r
1092 static chan_rend_context crct;\r
1093 \r
1094 static void chan_render_prep(void)\r
1095 {\r
1096         crct.eg_timer_add = ym2612.OPN.eg_timer_add;\r
1097         crct.lfo_inc = ym2612.OPN.lfo_inc;\r
1098 }\r
1099 \r
1100 static void chan_render_finish(void)\r
1101 {\r
1102         ym2612.OPN.eg_cnt = crct.eg_cnt;\r
1103         ym2612.OPN.eg_timer = crct.eg_timer;\r
1104         g_lfo_ampm = crct.pack >> 16; // need_save\r
1105         ym2612.OPN.lfo_cnt = crct.lfo_cnt;\r
1106 }\r
1107 \r
1108 static int chan_render(int *buffer, int length, int c, UINT32 flags) // flags: stereo, ?, disabled, ?, pan_r, pan_l\r
1109 {\r
1110         crct.CH = &ym2612.CH[c];\r
1111         crct.mem = crct.CH->mem_value;          /* one sample delay memory */\r
1112         crct.lfo_cnt = ym2612.OPN.lfo_cnt;\r
1113 \r
1114         flags &= 0x35;\r
1115 \r
1116         if (crct.lfo_inc) {\r
1117                 flags |= 8;\r
1118                 flags |= g_lfo_ampm << 16;\r
1119                 flags |= crct.CH->AMmasks << 8;\r
1120                 if (crct.CH->ams == 8) // no ams\r
1121                      flags &= ~0xf00;\r
1122                 else flags |= (crct.CH->ams&3)<<6;\r
1123         }\r
1124         flags |= (crct.CH->FB&0xf)<<12;                         /* feedback shift */\r
1125         crct.pack = flags;\r
1126 \r
1127         crct.eg_cnt = ym2612.OPN.eg_cnt;                        /* envelope generator counter */\r
1128         crct.eg_timer = ym2612.OPN.eg_timer;\r
1129 \r
1130         /* precalculate phase modulation incr */\r
1131         crct.phase1 = crct.CH->SLOT[SLOT1].phase;\r
1132         crct.phase2 = crct.CH->SLOT[SLOT2].phase;\r
1133         crct.phase3 = crct.CH->SLOT[SLOT3].phase;\r
1134         crct.phase4 = crct.CH->SLOT[SLOT4].phase;\r
1135 \r
1136         /* current output from EG circuit (without AM from LFO) */\r
1137         crct.vol_out1 = crct.CH->SLOT[SLOT1].tl + ((UINT32)crct.CH->SLOT[SLOT1].volume);\r
1138         crct.vol_out2 = crct.CH->SLOT[SLOT2].tl + ((UINT32)crct.CH->SLOT[SLOT2].volume);\r
1139         crct.vol_out3 = crct.CH->SLOT[SLOT3].tl + ((UINT32)crct.CH->SLOT[SLOT3].volume);\r
1140         crct.vol_out4 = crct.CH->SLOT[SLOT4].tl + ((UINT32)crct.CH->SLOT[SLOT4].volume);\r
1141 \r
1142         crct.op1_out = crct.CH->op1_out;\r
1143         crct.algo = crct.CH->ALGO & 7;\r
1144 \r
1145         if(crct.CH->pms)\r
1146         {\r
1147                 /* add support for 3 slot mode */\r
1148                 UINT32 block_fnum = crct.CH->block_fnum;\r
1149 \r
1150                 UINT32 fnum_lfo   = ((block_fnum & 0x7f0) >> 4) * 32 * 8;\r
1151                 INT32  lfo_fn_table_index_offset = lfo_pm_table[ fnum_lfo + crct.CH->pms + ((crct.pack>>16)&0xff) ];\r
1152 \r
1153                 if (lfo_fn_table_index_offset)  /* LFO phase modulation active */\r
1154                 {\r
1155                         UINT8  blk;\r
1156                         UINT32 fn;\r
1157                         int kc,fc;\r
1158 \r
1159                         blk = block_fnum >> 11;\r
1160                         block_fnum = block_fnum*2 + lfo_fn_table_index_offset;\r
1161 \r
1162                         fn  = block_fnum & 0xfff;\r
1163 \r
1164                         /* keyscale code */\r
1165                         kc = (blk<<2) | opn_fktable[fn >> 8];\r
1166                         /* phase increment counter */\r
1167                         fc = fn_table[fn]>>(7-blk);\r
1168 \r
1169                         crct.incr1 = ((fc+crct.CH->SLOT[SLOT1].DT[kc])*crct.CH->SLOT[SLOT1].mul) >> 1;\r
1170                         crct.incr2 = ((fc+crct.CH->SLOT[SLOT2].DT[kc])*crct.CH->SLOT[SLOT2].mul) >> 1;\r
1171                         crct.incr3 = ((fc+crct.CH->SLOT[SLOT3].DT[kc])*crct.CH->SLOT[SLOT3].mul) >> 1;\r
1172                         crct.incr4 = ((fc+crct.CH->SLOT[SLOT4].DT[kc])*crct.CH->SLOT[SLOT4].mul) >> 1;\r
1173                 }\r
1174                 else    /* LFO phase modulation  = zero */\r
1175                 {\r
1176                         crct.incr1 = crct.CH->SLOT[SLOT1].Incr;\r
1177                         crct.incr2 = crct.CH->SLOT[SLOT2].Incr;\r
1178                         crct.incr3 = crct.CH->SLOT[SLOT3].Incr;\r
1179                         crct.incr4 = crct.CH->SLOT[SLOT4].Incr;\r
1180                 }\r
1181         }\r
1182         else    /* no LFO phase modulation */\r
1183         {\r
1184                 crct.incr1 = crct.CH->SLOT[SLOT1].Incr;\r
1185                 crct.incr2 = crct.CH->SLOT[SLOT2].Incr;\r
1186                 crct.incr3 = crct.CH->SLOT[SLOT3].Incr;\r
1187                 crct.incr4 = crct.CH->SLOT[SLOT4].Incr;\r
1188         }\r
1189 \r
1190         chan_render_loop(&crct, buffer, length);\r
1191 \r
1192         crct.CH->op1_out = crct.op1_out;\r
1193         crct.CH->mem_value = crct.mem;\r
1194         if (crct.CH->SLOT[SLOT1].state | crct.CH->SLOT[SLOT2].state | crct.CH->SLOT[SLOT3].state | crct.CH->SLOT[SLOT4].state)\r
1195         {\r
1196                 crct.CH->SLOT[SLOT1].phase = crct.phase1;\r
1197                 crct.CH->SLOT[SLOT2].phase = crct.phase2;\r
1198                 crct.CH->SLOT[SLOT3].phase = crct.phase3;\r
1199                 crct.CH->SLOT[SLOT4].phase = crct.phase4;\r
1200         }\r
1201         else\r
1202                 ym2612.slot_mask &= ~(0xf << (c*4));\r
1203 \r
1204         return (crct.algo & 8) >> 3; // had output\r
1205 }\r
1206 \r
1207 /* update phase increment and envelope generator */\r
1208 STRICTINLINE void refresh_fc_eg_slot(FM_SLOT *SLOT, int fc, int kc)\r
1209 {\r
1210         int ksr, fdt;\r
1211 \r
1212         /* (frequency) phase increment counter */\r
1213         fdt = fc+SLOT->DT[kc];\r
1214         /* detect overflow */\r
1215 //      if (fdt < 0) fdt += fn_table[0x7ff*2] >> (7-blk-1);\r
1216         if (fdt < 0) fdt += fn_table[0x7ff*2] >> 2;\r
1217         SLOT->Incr = fdt*SLOT->mul >> 1;\r
1218 \r
1219         ksr = kc >> SLOT->KSR;\r
1220         if( SLOT->ksr != ksr )\r
1221         {\r
1222                 int eg_sh, eg_sel;\r
1223                 SLOT->ksr = ksr;\r
1224 \r
1225                 /* calculate envelope generator rates */\r
1226                 if ((SLOT->ar + ksr) < 32+62)\r
1227                 {\r
1228                         eg_sh  = eg_rate_shift [SLOT->ar  + ksr ];\r
1229                         eg_sel = eg_rate_select[SLOT->ar  + ksr ];\r
1230                 }\r
1231                 else\r
1232                 {\r
1233                         eg_sh  = 0;\r
1234                         eg_sel = 17;\r
1235                 }\r
1236 \r
1237                 SLOT->eg_pack_ar = eg_inc_pack[eg_sel] | (eg_sh<<24);\r
1238 \r
1239                 eg_sh  = eg_rate_shift [SLOT->d1r + ksr];\r
1240                 eg_sel = eg_rate_select[SLOT->d1r + ksr];\r
1241 \r
1242                 SLOT->eg_pack_d1r = eg_inc_pack[eg_sel] | (eg_sh<<24);\r
1243 \r
1244                 eg_sh  = eg_rate_shift [SLOT->d2r + ksr];\r
1245                 eg_sel = eg_rate_select[SLOT->d2r + ksr];\r
1246 \r
1247                 SLOT->eg_pack_d2r = eg_inc_pack[eg_sel] | (eg_sh<<24);\r
1248 \r
1249                 eg_sh  = eg_rate_shift [SLOT->rr  + ksr];\r
1250                 eg_sel = eg_rate_select[SLOT->rr  + ksr];\r
1251 \r
1252                 SLOT->eg_pack_rr = eg_inc_pack[eg_sel] | (eg_sh<<24);\r
1253         }\r
1254 }\r
1255 \r
1256 /* update phase increment counters */\r
1257 INLINE void refresh_fc_eg_chan(FM_CH *CH)\r
1258 {\r
1259         if( CH->SLOT[SLOT1].Incr==-1){\r
1260                 int fc = CH->fc;\r
1261                 int kc = CH->kcode;\r
1262                 refresh_fc_eg_slot(&CH->SLOT[SLOT1] , fc , kc );\r
1263                 refresh_fc_eg_slot(&CH->SLOT[SLOT2] , fc , kc );\r
1264                 refresh_fc_eg_slot(&CH->SLOT[SLOT3] , fc , kc );\r
1265                 refresh_fc_eg_slot(&CH->SLOT[SLOT4] , fc , kc );\r
1266         }\r
1267 }\r
1268 \r
1269 INLINE void refresh_fc_eg_chan_sl3(void)\r
1270 {\r
1271         if( ym2612.CH[2].SLOT[SLOT1].Incr==-1)\r
1272         {\r
1273                 refresh_fc_eg_slot(&ym2612.CH[2].SLOT[SLOT1], ym2612.OPN.SL3.fc[1], ym2612.OPN.SL3.kcode[1] );\r
1274                 refresh_fc_eg_slot(&ym2612.CH[2].SLOT[SLOT2], ym2612.OPN.SL3.fc[2], ym2612.OPN.SL3.kcode[2] );\r
1275                 refresh_fc_eg_slot(&ym2612.CH[2].SLOT[SLOT3], ym2612.OPN.SL3.fc[0], ym2612.OPN.SL3.kcode[0] );\r
1276                 refresh_fc_eg_slot(&ym2612.CH[2].SLOT[SLOT4], ym2612.CH[2].fc , ym2612.CH[2].kcode );\r
1277         }\r
1278 }\r
1279 \r
1280 /* initialize time tables */\r
1281 static void init_timetables(const UINT8 *dttable)\r
1282 {\r
1283         int i,d;\r
1284         double rate;\r
1285 \r
1286         /* DeTune table */\r
1287         for (d = 0;d <= 3;d++){\r
1288                 for (i = 0;i <= 31;i++){\r
1289                         rate = ((double)dttable[d*32 + i]) * SIN_LEN  * ym2612.OPN.ST.freqbase  * (1<<FREQ_SH) / ((double)(1<<20));\r
1290                         ym2612.OPN.ST.dt_tab[d][i]   = (INT32) rate;\r
1291                         ym2612.OPN.ST.dt_tab[d+4][i] = -ym2612.OPN.ST.dt_tab[d][i];\r
1292                 }\r
1293         }\r
1294 }\r
1295 \r
1296 \r
1297 static void reset_channels(FM_CH *CH)\r
1298 {\r
1299         int c,s;\r
1300 \r
1301         ym2612.OPN.ST.mode   = 0;       /* normal mode */\r
1302         ym2612.OPN.ST.TA     = 0;\r
1303         ym2612.OPN.ST.TAC    = 0;\r
1304         ym2612.OPN.ST.TB     = 0;\r
1305         ym2612.OPN.ST.TBC    = 0;\r
1306 \r
1307         for( c = 0 ; c < 6 ; c++ )\r
1308         {\r
1309                 CH[c].fc = 0;\r
1310                 for(s = 0 ; s < 4 ; s++ )\r
1311                 {\r
1312                         CH[c].SLOT[s].state= EG_OFF;\r
1313                         CH[c].SLOT[s].volume = MAX_ATT_INDEX;\r
1314                 }\r
1315                 CH[c].mem_value = CH[c].op1_out = 0;\r
1316         }\r
1317         ym2612.slot_mask = 0;\r
1318 }\r
1319 \r
1320 /* initialize generic tables */\r
1321 static void init_tables(void)\r
1322 {\r
1323         signed int i,x,y,p;\r
1324         signed int n;\r
1325         double o,m;\r
1326 \r
1327         for (i=0; i < 256; i++)\r
1328         {\r
1329                 /* non-standard sinus */\r
1330                 m = sin( ((i*2)+1) * M_PI / SIN_LEN ); /* checked against the real chip */\r
1331 \r
1332                 /* we never reach zero here due to ((i*2)+1) */\r
1333 \r
1334                 if (m>0.0)\r
1335                         o = 8*log(1.0/m)/log(2);        /* convert to 'decibels' */\r
1336                 else\r
1337                         o = 8*log(-1.0/m)/log(2);       /* convert to 'decibels' */\r
1338 \r
1339                 o = o / (ENV_STEP/4);\r
1340 \r
1341                 n = (int)(2.0*o);\r
1342                 if (n&1)                                                /* round to nearest */\r
1343                         n = (n>>1)+1;\r
1344                 else\r
1345                         n = n>>1;\r
1346 \r
1347                 ym_sin_tab[ i ] = n;\r
1348                 //dprintf("FM.C: sin [%4i]= %4i", i, ym_sin_tab[i]);\r
1349         }\r
1350 \r
1351         //dprintf("FM.C: ENV_QUIET= %08x", ENV_QUIET );\r
1352 \r
1353 \r
1354         for (x=0; x < TL_RES_LEN; x++)\r
1355         {\r
1356                 m = (1<<16) / pow(2, (x+1) * (ENV_STEP/4.0) / 8.0);\r
1357                 m = floor(m);\r
1358 \r
1359                 /* we never reach (1<<16) here due to the (x+1) */\r
1360                 /* result fits within 16 bits at maximum */\r
1361 \r
1362                 n = (int)m;             /* 16 bits here */\r
1363                 n >>= 4;                /* 12 bits here */\r
1364                 if (n&1)                /* round to nearest */\r
1365                         n = (n>>1)+1;\r
1366                 else\r
1367                         n = n>>1;\r
1368                                                 /* 11 bits here (rounded) */\r
1369                 n <<= 2;                /* 13 bits here (as in real chip) */\r
1370                 ym_tl_tab2[ x ] = n;\r
1371 \r
1372                 for (i=1; i < 13; i++)\r
1373                 {\r
1374                         ym_tl_tab2[ x + i*TL_RES_LEN ] = n >> i;\r
1375                 }\r
1376         }\r
1377 \r
1378         for (x=0; x < 256; x++)\r
1379         {\r
1380                 int sin = ym_sin_tab[ x ];\r
1381 \r
1382                 for (y=0; y < 2*13*TL_RES_LEN/8; y+=2)\r
1383                 {\r
1384                         p = (y<<2) + sin;\r
1385                         if (p >= 13*TL_RES_LEN)\r
1386                                  ym_tl_tab[(y<<7) | x] = 0;\r
1387                         else ym_tl_tab[(y<<7) | x] = ym_tl_tab2[p];\r
1388                 }\r
1389         }\r
1390 \r
1391 \r
1392         /* build LFO PM modulation table */\r
1393         for(i = 0; i < 8; i++) /* 8 PM depths */\r
1394         {\r
1395                 UINT8 fnum;\r
1396                 for (fnum=0; fnum<128; fnum++) /* 7 bits meaningful of F-NUMBER */\r
1397                 {\r
1398                         UINT8 value;\r
1399                         UINT8 step;\r
1400                         UINT32 offset_depth = i;\r
1401                         UINT32 offset_fnum_bit;\r
1402                         UINT32 bit_tmp;\r
1403 \r
1404                         for (step=0; step<8; step++)\r
1405                         {\r
1406                                 value = 0;\r
1407                                 for (bit_tmp=0; bit_tmp<7; bit_tmp++) /* 7 bits */\r
1408                                 {\r
1409                                         if (fnum & (1<<bit_tmp)) /* only if bit "bit_tmp" is set */\r
1410                                         {\r
1411                                                 offset_fnum_bit = bit_tmp * 8;\r
1412                                                 value += lfo_pm_output[offset_fnum_bit + offset_depth][step];\r
1413                                         }\r
1414                                 }\r
1415                                 lfo_pm_table[(fnum*32*8) + (i*32) + step   + 0] = value;\r
1416                                 lfo_pm_table[(fnum*32*8) + (i*32) +(step^7)+ 8] = value;\r
1417                                 lfo_pm_table[(fnum*32*8) + (i*32) + step   +16] = -value;\r
1418                                 lfo_pm_table[(fnum*32*8) + (i*32) +(step^7)+24] = -value;\r
1419                         }\r
1420                 }\r
1421         }\r
1422 }\r
1423 \r
1424 \r
1425 /* CSM Key Controll */\r
1426 #if 0\r
1427 INLINE void CSMKeyControll(FM_CH *CH)\r
1428 {\r
1429         /* this is wrong, atm */\r
1430 \r
1431         /* all key on */\r
1432         FM_KEYON(CH,SLOT1);\r
1433         FM_KEYON(CH,SLOT2);\r
1434         FM_KEYON(CH,SLOT3);\r
1435         FM_KEYON(CH,SLOT4);\r
1436 }\r
1437 #endif\r
1438 \r
1439 \r
1440 /* prescaler set (and make time tables) */\r
1441 static void OPNSetPres(int pres)\r
1442 {\r
1443         int i;\r
1444 \r
1445         /* frequency base */\r
1446         ym2612.OPN.ST.freqbase = (ym2612.OPN.ST.rate) ? ((double)ym2612.OPN.ST.clock / ym2612.OPN.ST.rate) / pres : 0;\r
1447 \r
1448         ym2612.OPN.eg_timer_add  = (1<<EG_SH) * ym2612.OPN.ST.freqbase;\r
1449 \r
1450         /* make time tables */\r
1451         init_timetables( dt_tab );\r
1452 \r
1453         /* there are 2048 FNUMs that can be generated using FNUM/BLK registers\r
1454         but LFO works with one more bit of a precision so we really need 4096 elements */\r
1455         /* calculate fnumber -> increment counter table */\r
1456         for(i = 0; i < 4096; i++)\r
1457         {\r
1458                 /* freq table for octave 7 */\r
1459                 /* OPN phase increment counter = 20bit */\r
1460                 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
1461         }\r
1462 \r
1463         /* LFO freq. table */\r
1464         for(i = 0; i < 8; i++)\r
1465         {\r
1466                 /* Amplitude modulation: 64 output levels (triangle waveform); 1 level lasts for one of "lfo_samples_per_step" samples */\r
1467                 /* Phase modulation: one entry from lfo_pm_output lasts for one of 4 * "lfo_samples_per_step" samples  */\r
1468                 ym2612.OPN.lfo_freq[i] = (1.0 / lfo_samples_per_step[i]) * (1<<LFO_SH) * ym2612.OPN.ST.freqbase;\r
1469         }\r
1470 }\r
1471 \r
1472 \r
1473 /* write a OPN register (0x30-0xff) */\r
1474 static int OPNWriteReg(int r, int v)\r
1475 {\r
1476         int ret = 1;\r
1477         FM_CH *CH;\r
1478         FM_SLOT *SLOT;\r
1479 \r
1480         UINT8 c = OPN_CHAN(r);\r
1481 \r
1482         if (c == 3) return 0; /* 0xX3,0xX7,0xXB,0xXF */\r
1483 \r
1484         if (r >= 0x100) c+=3;\r
1485 \r
1486         CH = &ym2612.CH[c];\r
1487 \r
1488         SLOT = &(CH->SLOT[OPN_SLOT(r)]);\r
1489 \r
1490         switch( r & 0xf0 ) {\r
1491         case 0x30:      /* DET , MUL */\r
1492                 set_det_mul(CH,SLOT,v);\r
1493                 break;\r
1494 \r
1495         case 0x40:      /* TL */\r
1496                 set_tl(SLOT,v);\r
1497                 break;\r
1498 \r
1499         case 0x50:      /* KS, AR */\r
1500                 set_ar_ksr(CH,SLOT,v);\r
1501                 break;\r
1502 \r
1503         case 0x60:      /* bit7 = AM ENABLE, DR | depends on ksr */\r
1504                 set_dr(SLOT,v);\r
1505                 if(v&0x80) CH->AMmasks |=   1<<OPN_SLOT(r);\r
1506                 else       CH->AMmasks &= ~(1<<OPN_SLOT(r));\r
1507                 break;\r
1508 \r
1509         case 0x70:      /*     SR | depends on ksr */\r
1510                 set_sr(SLOT,v);\r
1511                 break;\r
1512 \r
1513         case 0x80:      /* SL, RR | depends on ksr */\r
1514                 set_sl_rr(SLOT,v);\r
1515                 break;\r
1516 \r
1517         case 0x90:      /* SSG-EG */\r
1518                 // removed.\r
1519                 ret = 0;\r
1520                 break;\r
1521 \r
1522         case 0xa0:\r
1523                 switch( OPN_SLOT(r) ){\r
1524                 case 0:         /* 0xa0-0xa2 : FNUM1 | depends on fn_h (below) */\r
1525                         {\r
1526                                 UINT32 fn = (((UINT32)( (CH->fn_h)&7))<<8) + v;\r
1527                                 UINT8 blk = CH->fn_h>>3;\r
1528                                 /* keyscale code */\r
1529                                 CH->kcode = (blk<<2) | opn_fktable[fn >> 7];\r
1530                                 /* phase increment counter */\r
1531                                 CH->fc = fn_table[fn*2]>>(7-blk);\r
1532 \r
1533                                 /* store fnum in clear form for LFO PM calculations */\r
1534                                 CH->block_fnum = (blk<<11) | fn;\r
1535 \r
1536                                 CH->SLOT[SLOT1].Incr=-1;\r
1537                         }\r
1538                         break;\r
1539                 case 1:         /* 0xa4-0xa6 : FNUM2,BLK */\r
1540                         CH->fn_h = v&0x3f;\r
1541                         ret = 0;\r
1542                         break;\r
1543                 case 2:         /* 0xa8-0xaa : 3CH FNUM1 */\r
1544                         if(r < 0x100)\r
1545                         {\r
1546                                 UINT32 fn = (((UINT32)(ym2612.OPN.SL3.fn_h&7))<<8) + v;\r
1547                                 UINT8 blk = ym2612.OPN.SL3.fn_h>>3;\r
1548                                 /* keyscale code */\r
1549                                 ym2612.OPN.SL3.kcode[c]= (blk<<2) | opn_fktable[fn >> 7];\r
1550                                 /* phase increment counter */\r
1551                                 ym2612.OPN.SL3.fc[c] = fn_table[fn*2]>>(7-blk);\r
1552                                 ym2612.OPN.SL3.block_fnum[c] = (blk<<11) | fn;\r
1553                                 ym2612.CH[2].SLOT[SLOT1].Incr=-1;\r
1554                         }\r
1555                         break;\r
1556                 case 3:         /* 0xac-0xae : 3CH FNUM2,BLK */\r
1557                         if(r < 0x100)\r
1558                                 ym2612.OPN.SL3.fn_h = v&0x3f;\r
1559                         ret = 0;\r
1560                         break;\r
1561                 default:\r
1562                         ret = 0;\r
1563                         break;\r
1564                 }\r
1565                 break;\r
1566 \r
1567         case 0xb0:\r
1568                 switch( OPN_SLOT(r) ){\r
1569                 case 0:         /* 0xb0-0xb2 : FB,ALGO */\r
1570                         {\r
1571                                 int feedback = (v>>3)&7;\r
1572                                 CH->ALGO = v&7;\r
1573                                 CH->FB   = feedback ? feedback+6 : 0;\r
1574                         }\r
1575                         break;\r
1576                 case 1:         /* 0xb4-0xb6 : L , R , AMS , PMS (YM2612/YM2610B/YM2610/YM2608) */\r
1577                         {\r
1578                                 int panshift = c<<1;\r
1579 \r
1580                                 /* b0-2 PMS */\r
1581                                 CH->pms = (v & 7) * 32; /* CH->pms = PM depth * 32 (index in lfo_pm_table) */\r
1582 \r
1583                                 /* b4-5 AMS */\r
1584                                 CH->ams = lfo_ams_depth_shift[(v>>4) & 3];\r
1585 \r
1586                                 /* PAN :  b7 = L, b6 = R */\r
1587                                 ym2612.OPN.pan &= ~(3<<panshift);\r
1588                                 ym2612.OPN.pan |= ((v & 0xc0) >> 6) << panshift; // ..LRLR\r
1589                         }\r
1590                         break;\r
1591                 default:\r
1592                         ret = 0;\r
1593                         break;\r
1594                 }\r
1595                 break;\r
1596         default:\r
1597                 ret = 0;\r
1598                 break;\r
1599         }\r
1600 \r
1601         return ret;\r
1602 }\r
1603 \r
1604 \r
1605 /*******************************************************************************/\r
1606 /*      YM2612 local section                                                   */\r
1607 /*******************************************************************************/\r
1608 \r
1609 /* Generate samples for YM2612 */\r
1610 int YM2612UpdateOne_(int *buffer, int length, int stereo, int is_buf_empty)\r
1611 {\r
1612         int pan;\r
1613         int active_chs = 0;\r
1614 \r
1615         // if !is_buf_empty, it means it has valid samples to mix with, else it may contain trash\r
1616         if (is_buf_empty) memset32(buffer, 0, length<<stereo);\r
1617 \r
1618 /*\r
1619         {\r
1620                 int c, s;\r
1621                 ppp();\r
1622                 for (c = 0; c < 6; c++) {\r
1623                         int slr = 0, slm;\r
1624                         printf("%i: ", c);\r
1625                         for (s = 0; s < 4; s++) {\r
1626                                 if (ym2612.CH[c].SLOT[s].state != EG_OFF) slr = 1;\r
1627                                 printf(" %i", ym2612.CH[c].SLOT[s].state != EG_OFF);\r
1628                         }\r
1629                         slm = (ym2612.slot_mask&(0xf<<(c*4))) ? 1 : 0;\r
1630                         printf(" | %i", slm);\r
1631                         printf(" | %i\n", ym2612.CH[c].SLOT[SLOT1].Incr==-1);\r
1632                         if (slr != slm) exit(1);\r
1633                 }\r
1634         }\r
1635 */\r
1636         /* refresh PG and EG */\r
1637         refresh_fc_eg_chan( &ym2612.CH[0] );\r
1638         refresh_fc_eg_chan( &ym2612.CH[1] );\r
1639         if( (ym2612.OPN.ST.mode & 0xc0) )\r
1640                 /* 3SLOT MODE */\r
1641                 refresh_fc_eg_chan_sl3();\r
1642         else\r
1643                 refresh_fc_eg_chan( &ym2612.CH[2] );\r
1644         refresh_fc_eg_chan( &ym2612.CH[3] );\r
1645         refresh_fc_eg_chan( &ym2612.CH[4] );\r
1646         refresh_fc_eg_chan( &ym2612.CH[5] );\r
1647 \r
1648         pan = ym2612.OPN.pan;\r
1649         if (stereo) stereo = 1;\r
1650 \r
1651         /* mix to 32bit dest */\r
1652         // flags: stereo, ?, disabled, ?, pan_r, pan_l\r
1653         chan_render_prep();\r
1654         if (ym2612.slot_mask & 0x00000f) active_chs |= chan_render(buffer, length, 0, stereo|((pan&0x003)<<4)) << 0;\r
1655         if (ym2612.slot_mask & 0x0000f0) active_chs |= chan_render(buffer, length, 1, stereo|((pan&0x00c)<<2)) << 1;\r
1656         if (ym2612.slot_mask & 0x000f00) active_chs |= chan_render(buffer, length, 2, stereo|((pan&0x030)   )) << 2;\r
1657         if (ym2612.slot_mask & 0x00f000) active_chs |= chan_render(buffer, length, 3, stereo|((pan&0x0c0)>>2)) << 3;\r
1658         if (ym2612.slot_mask & 0x0f0000) active_chs |= chan_render(buffer, length, 4, stereo|((pan&0x300)>>4)) << 4;\r
1659         if (ym2612.slot_mask & 0xf00000) active_chs |= chan_render(buffer, length, 5, stereo|((pan&0xc00)>>6)|(ym2612.dacen<<2)) << 5;\r
1660         chan_render_finish();\r
1661 \r
1662         return active_chs; // 1 if buffer updated\r
1663 }\r
1664 \r
1665 \r
1666 /* initialize YM2612 emulator */\r
1667 void YM2612Init_(int clock, int rate)\r
1668 {\r
1669         memset(&ym2612, 0, sizeof(ym2612));\r
1670         init_tables();\r
1671 \r
1672         ym2612.OPN.ST.clock = clock;\r
1673         ym2612.OPN.ST.rate = rate;\r
1674 \r
1675         OPNSetPres( 6*24 );\r
1676 \r
1677         /* Extend handler */\r
1678         YM2612ResetChip_();\r
1679 }\r
1680 \r
1681 \r
1682 /* reset */\r
1683 void YM2612ResetChip_(void)\r
1684 {\r
1685         int i;\r
1686 \r
1687         memset(ym2612.REGS, 0, sizeof(ym2612.REGS));\r
1688 \r
1689         set_timers( 0x30 ); /* mode 0 , timer reset */\r
1690         ym2612.REGS[0x27] = 0x30;\r
1691 \r
1692         ym2612.OPN.eg_timer = 0;\r
1693         ym2612.OPN.eg_cnt   = 0;\r
1694         ym2612.OPN.ST.status = 0;\r
1695 \r
1696         reset_channels( &ym2612.CH[0] );\r
1697         for(i = 0xb6 ; i >= 0xb4 ; i-- )\r
1698         {\r
1699                 OPNWriteReg(i      ,0xc0);\r
1700                 OPNWriteReg(i|0x100,0xc0);\r
1701                 ym2612.REGS[i      ] = 0xc0;\r
1702                 ym2612.REGS[i|0x100] = 0xc0;\r
1703         }\r
1704         for(i = 0xb2 ; i >= 0x30 ; i-- )\r
1705         {\r
1706                 OPNWriteReg(i      ,0);\r
1707                 OPNWriteReg(i|0x100,0);\r
1708         }\r
1709         for(i = 0x26 ; i >= 0x20 ; i-- ) OPNWriteReg(i,0);\r
1710         /* DAC mode clear */\r
1711         ym2612.dacen = 0;\r
1712         ym2612.addr_A1 = 0;\r
1713 }\r
1714 \r
1715 \r
1716 /* YM2612 write */\r
1717 /* a = address */\r
1718 /* v = value   */\r
1719 /* returns 1 if sample affecting state changed */\r
1720 int YM2612Write_(unsigned int a, unsigned int v)\r
1721 {\r
1722         int addr, ret=1;\r
1723 \r
1724         v &= 0xff;      /* adjust to 8 bit bus */\r
1725 \r
1726         switch( a&3){\r
1727         case 0: /* address port 0 */\r
1728                 ym2612.OPN.ST.address = v;\r
1729                 ym2612.addr_A1 = 0;\r
1730                 ret=0;\r
1731                 break;\r
1732 \r
1733         case 1: /* data port 0    */\r
1734                 if (ym2612.addr_A1 != 0) {\r
1735                         ret=0;\r
1736                         break;  /* verified on real YM2608 */\r
1737                 }\r
1738 \r
1739                 addr = ym2612.OPN.ST.address;\r
1740 \r
1741                 switch( addr & 0xf0 )\r
1742                 {\r
1743                 case 0x20:      /* 0x20-0x2f Mode */\r
1744                         switch( addr )\r
1745                         {\r
1746                         case 0x22:      /* LFO FREQ (YM2608/YM2610/YM2610B/YM2612) */\r
1747                                 if (v&0x08) /* LFO enabled ? */\r
1748                                 {\r
1749                                         ym2612.OPN.lfo_inc = ym2612.OPN.lfo_freq[v&7];\r
1750                                 }\r
1751                                 else\r
1752                                 {\r
1753                                         ym2612.OPN.lfo_inc = 0;\r
1754                                 }\r
1755                                 break;\r
1756 #if 0 // handled elsewhere\r
1757                         case 0x24: { // timer A High 8\r
1758                                         int TAnew = (ym2612.OPN.ST.TA & 0x03)|(((int)v)<<2);\r
1759                                         if(ym2612.OPN.ST.TA != TAnew) {\r
1760                                                 // we should reset ticker only if new value is written. Outrun requires this.\r
1761                                                 ym2612.OPN.ST.TA = TAnew;\r
1762                                                 ym2612.OPN.ST.TAC = (1024-TAnew)*18;\r
1763                                                 ym2612.OPN.ST.TAT = 0;\r
1764                                         }\r
1765                                 }\r
1766                                 ret=0;\r
1767                                 break;\r
1768                         case 0x25: { // timer A Low 2\r
1769                                         int TAnew = (ym2612.OPN.ST.TA & 0x3fc)|(v&3);\r
1770                                         if(ym2612.OPN.ST.TA != TAnew) {\r
1771                                                 ym2612.OPN.ST.TA = TAnew;\r
1772                                                 ym2612.OPN.ST.TAC = (1024-TAnew)*18;\r
1773                                                 ym2612.OPN.ST.TAT = 0;\r
1774                                         }\r
1775                                 }\r
1776                                 ret=0;\r
1777                                 break;\r
1778                         case 0x26: // timer B\r
1779                                 if(ym2612.OPN.ST.TB != v) {\r
1780                                         ym2612.OPN.ST.TB = v;\r
1781                                         ym2612.OPN.ST.TBC  = (256-v)<<4;\r
1782                                         ym2612.OPN.ST.TBC *= 18;\r
1783                                         ym2612.OPN.ST.TBT  = 0;\r
1784                                 }\r
1785                                 ret=0;\r
1786                                 break;\r
1787 #endif\r
1788                         case 0x27:      /* mode, timer control */\r
1789                                 set_timers( v );\r
1790                                 ret=0;\r
1791                                 break;\r
1792                         case 0x28:      /* key on / off */\r
1793                                 {\r
1794                                         UINT8 c;\r
1795 \r
1796                                         c = v & 0x03;\r
1797                                         if( c == 3 ) { ret=0; break; }\r
1798                                         if( v&0x04 ) c+=3;\r
1799                                         if(v&0x10) FM_KEYON(c,SLOT1); else FM_KEYOFF(c,SLOT1);\r
1800                                         if(v&0x20) FM_KEYON(c,SLOT2); else FM_KEYOFF(c,SLOT2);\r
1801                                         if(v&0x40) FM_KEYON(c,SLOT3); else FM_KEYOFF(c,SLOT3);\r
1802                                         if(v&0x80) FM_KEYON(c,SLOT4); else FM_KEYOFF(c,SLOT4);\r
1803                                         break;\r
1804                                 }\r
1805                         case 0x2a:      /* DAC data (YM2612) */\r
1806                                 ym2612.dacout = ((int)v - 0x80) << 6;   /* level unknown (notaz: 8 seems to be too much) */\r
1807                                 ret=0;\r
1808                                 break;\r
1809                         case 0x2b:      /* DAC Sel  (YM2612) */\r
1810                                 /* b7 = dac enable */\r
1811                                 ym2612.dacen = v & 0x80;\r
1812                                 ret=0;\r
1813                                 break;\r
1814                         default:\r
1815                                 break;\r
1816                         }\r
1817                         break;\r
1818                 default:        /* 0x30-0xff OPN section */\r
1819                         /* write register */\r
1820                         ret = OPNWriteReg(addr,v);\r
1821                 }\r
1822                 break;\r
1823 \r
1824         case 2: /* address port 1 */\r
1825                 ym2612.OPN.ST.address = v;\r
1826                 ym2612.addr_A1 = 1;\r
1827                 ret=0;\r
1828                 break;\r
1829 \r
1830         case 3: /* data port 1    */\r
1831                 if (ym2612.addr_A1 != 1) {\r
1832                         ret=0;\r
1833                         break;  /* verified on real YM2608 */\r
1834                 }\r
1835 \r
1836                 addr = ym2612.OPN.ST.address | 0x100;\r
1837 \r
1838                 ret = OPNWriteReg(addr, v);\r
1839                 break;\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         reset_channels( &ym2612.CH[0] );\r
1879         ym2612.slot_mask = 0xffffff;\r
1880 }\r
1881 \r
1882 /* rather stupid design because I wanted to fit in unused register "space" */\r
1883 typedef struct\r
1884 {\r
1885         UINT32  state_phase;\r
1886         INT16   volume;\r
1887 } ym_save_addon_slot;\r
1888 \r
1889 typedef struct\r
1890 {\r
1891         UINT32  magic;\r
1892         UINT8   address;\r
1893         UINT8   status;\r
1894         UINT8   addr_A1;\r
1895         UINT8   unused;\r
1896         int     TAT;\r
1897         int     TBT;\r
1898         UINT32  eg_cnt;         // 10\r
1899         UINT32  eg_timer;\r
1900         UINT32  lfo_cnt;\r
1901         UINT16  lfo_ampm;\r
1902         UINT16  unused2;\r
1903         UINT32  keyon_field;    // 20\r
1904         UINT32  kcode_fc_sl3_3;\r
1905         UINT32  reserved[2];\r
1906 } ym_save_addon;\r
1907 \r
1908 typedef struct\r
1909 {\r
1910         UINT16  block_fnum[6];\r
1911         UINT16  block_fnum_sl3[3];\r
1912         UINT16  reserved[7];\r
1913 } ym_save_addon2;\r
1914 \r
1915 \r
1916 void YM2612PicoStateSave2(int tat, int tbt)\r
1917 {\r
1918         ym_save_addon_slot ss;\r
1919         ym_save_addon2 sa2;\r
1920         ym_save_addon sa;\r
1921         unsigned char *ptr;\r
1922         int c, s;\r
1923 \r
1924         memset(&sa, 0, sizeof(sa));\r
1925         memset(&sa2, 0, sizeof(sa2));\r
1926 \r
1927         // chans 1,2,3\r
1928         ptr = &ym2612.REGS[0x0b8];\r
1929         for (c = 0; c < 3; c++)\r
1930         {\r
1931                 for (s = 0; s < 4; s++) {\r
1932                         ss.state_phase = (ym2612.CH[c].SLOT[s].state << 29) | (ym2612.CH[c].SLOT[s].phase >> 3);\r
1933                         ss.volume = ym2612.CH[c].SLOT[s].volume;\r
1934                         if (ym2612.CH[c].SLOT[s].key)\r
1935                                 sa.keyon_field |= 1 << (c*4 + s);\r
1936                         memcpy(ptr, &ss, 6);\r
1937                         ptr += 6;\r
1938                 }\r
1939                 sa2.block_fnum[c] = ym2612.CH[c].block_fnum;\r
1940         }\r
1941         // chans 4,5,6\r
1942         ptr = &ym2612.REGS[0x1b8];\r
1943         for (; c < 6; c++)\r
1944         {\r
1945                 for (s = 0; s < 4; s++) {\r
1946                         ss.state_phase = (ym2612.CH[c].SLOT[s].state << 29) | (ym2612.CH[c].SLOT[s].phase >> 3);\r
1947                         ss.volume = ym2612.CH[c].SLOT[s].volume;\r
1948                         if (ym2612.CH[c].SLOT[s].key)\r
1949                                 sa.keyon_field |= 1 << (c*4 + s);\r
1950                         memcpy(ptr, &ss, 6);\r
1951                         ptr += 6;\r
1952                 }\r
1953                 sa2.block_fnum[c] = ym2612.CH[c].block_fnum;\r
1954         }\r
1955         for (c = 0; c < 3; c++)\r
1956         {\r
1957                 sa2.block_fnum_sl3[c] = ym2612.OPN.SL3.block_fnum[c];\r
1958         }\r
1959 \r
1960         memcpy(&ym2612.REGS[0], &sa2, sizeof(sa2)); // 0x20 max\r
1961 \r
1962         // other things\r
1963         ptr = &ym2612.REGS[0x100];\r
1964         sa.magic = 0x41534d59; // 'YMSA'\r
1965         sa.address = ym2612.OPN.ST.address;\r
1966         sa.status  = ym2612.OPN.ST.status;\r
1967         sa.addr_A1 = ym2612.addr_A1;\r
1968         sa.TAT     = tat;\r
1969         sa.TBT     = tbt;\r
1970         sa.eg_cnt  = ym2612.OPN.eg_cnt;\r
1971         sa.eg_timer = ym2612.OPN.eg_timer;\r
1972         sa.lfo_cnt  = ym2612.OPN.lfo_cnt;\r
1973         sa.lfo_ampm = g_lfo_ampm;\r
1974         memcpy(ptr, &sa, sizeof(sa)); // 0x30 max\r
1975 }\r
1976 \r
1977 int YM2612PicoStateLoad2(int *tat, int *tbt)\r
1978 {\r
1979         ym_save_addon_slot ss;\r
1980         ym_save_addon2 sa2;\r
1981         ym_save_addon sa;\r
1982         unsigned char *ptr;\r
1983         UINT32 fn;\r
1984         UINT8 blk;\r
1985         int c, s;\r
1986 \r
1987         ptr = &ym2612.REGS[0x100];\r
1988         memcpy(&sa, ptr, sizeof(sa)); // 0x30 max\r
1989         if (sa.magic != 0x41534d59) return -1;\r
1990 \r
1991         ptr = &ym2612.REGS[0];\r
1992         memcpy(&sa2, ptr, sizeof(sa2));\r
1993 \r
1994         ym2612.OPN.ST.address = sa.address;\r
1995         ym2612.OPN.ST.status = sa.status;\r
1996         ym2612.addr_A1 = sa.addr_A1;\r
1997         ym2612.OPN.eg_cnt = sa.eg_cnt;\r
1998         ym2612.OPN.eg_timer = sa.eg_timer;\r
1999         ym2612.OPN.lfo_cnt = sa.lfo_cnt;\r
2000         g_lfo_ampm = sa.lfo_ampm;\r
2001         if (tat != NULL) *tat = sa.TAT;\r
2002         if (tbt != NULL) *tbt = sa.TBT;\r
2003 \r
2004         // chans 1,2,3\r
2005         ptr = &ym2612.REGS[0x0b8];\r
2006         for (c = 0; c < 3; c++)\r
2007         {\r
2008                 for (s = 0; s < 4; s++) {\r
2009                         memcpy(&ss, ptr, 6);\r
2010                         ym2612.CH[c].SLOT[s].state = ss.state_phase >> 29;\r
2011                         ym2612.CH[c].SLOT[s].phase = ss.state_phase << 3;\r
2012                         ym2612.CH[c].SLOT[s].volume = ss.volume;\r
2013                         ym2612.CH[c].SLOT[s].key = (sa.keyon_field & (1 << (c*4 + s))) ? 1 : 0;\r
2014                         ym2612.CH[c].SLOT[s].ksr = (UINT8)-1;\r
2015                         ptr += 6;\r
2016                 }\r
2017                 ym2612.CH[c].SLOT[SLOT1].Incr=-1;\r
2018                 ym2612.CH[c].block_fnum = sa2.block_fnum[c];\r
2019                 fn = ym2612.CH[c].block_fnum & 0x7ff;\r
2020                 blk = ym2612.CH[c].block_fnum >> 11;\r
2021                 ym2612.CH[c].kcode= (blk<<2) | opn_fktable[fn >> 7];\r
2022                 ym2612.CH[c].fc = fn_table[fn*2]>>(7-blk);\r
2023         }\r
2024         // chans 4,5,6\r
2025         ptr = &ym2612.REGS[0x1b8];\r
2026         for (; c < 6; c++)\r
2027         {\r
2028                 for (s = 0; s < 4; s++) {\r
2029                         memcpy(&ss, ptr, 6);\r
2030                         ym2612.CH[c].SLOT[s].state = ss.state_phase >> 29;\r
2031                         ym2612.CH[c].SLOT[s].phase = ss.state_phase << 3;\r
2032                         ym2612.CH[c].SLOT[s].volume = ss.volume;\r
2033                         ym2612.CH[c].SLOT[s].key = (sa.keyon_field & (1 << (c*4 + s))) ? 1 : 0;\r
2034                         ym2612.CH[c].SLOT[s].ksr = (UINT8)-1;\r
2035                         ptr += 6;\r
2036                 }\r
2037                 ym2612.CH[c].SLOT[SLOT1].Incr=-1;\r
2038                 ym2612.CH[c].block_fnum = sa2.block_fnum[c];\r
2039                 fn = ym2612.CH[c].block_fnum & 0x7ff;\r
2040                 blk = ym2612.CH[c].block_fnum >> 11;\r
2041                 ym2612.CH[c].kcode= (blk<<2) | opn_fktable[fn >> 7];\r
2042                 ym2612.CH[c].fc = fn_table[fn*2]>>(7-blk);\r
2043         }\r
2044         for (c = 0; c < 3; c++)\r
2045         {\r
2046                 ym2612.OPN.SL3.block_fnum[c] = sa2.block_fnum_sl3[c];\r
2047                 fn = ym2612.OPN.SL3.block_fnum[c] & 0x7ff;\r
2048                 blk = ym2612.OPN.SL3.block_fnum[c] >> 11;\r
2049                 ym2612.OPN.SL3.kcode[c]= (blk<<2) | opn_fktable[fn >> 7];\r
2050                 ym2612.OPN.SL3.fc[c] = fn_table[fn*2]>>(7-blk);\r
2051         }\r
2052 \r
2053         return 0;\r
2054 }\r
2055 \r
2056 void *YM2612GetRegs(void)\r
2057 {\r
2058         return ym2612.REGS;\r
2059 }\r
2060 \r