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