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