e712278ba1bcb3cd73401d19599472b908f252ae
[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         case 2: /* address port 1 */\r
1699                 ym2612.OPN.ST.address = v;\r
1700                 ym2612.addr_A1 = (a & 2) >> 1;\r
1701                 ret = 0;\r
1702                 break;\r
1703 \r
1704         case 1:\r
1705         case 3: /* data port */\r
1706                 addr = ym2612.OPN.ST.address | ((int)ym2612.addr_A1 << 8);\r
1707 \r
1708                 switch( addr & 0x1f0 )\r
1709                 {\r
1710                 case 0x20:      /* 0x20-0x2f Mode */\r
1711                         switch( addr )\r
1712                         {\r
1713                         case 0x22:      /* LFO FREQ (YM2608/YM2610/YM2610B/YM2612) */\r
1714                                 if (v&0x08) /* LFO enabled ? */\r
1715                                 {\r
1716                                         ym2612.OPN.lfo_inc = ym2612.OPN.lfo_freq[v&7];\r
1717                                 }\r
1718                                 else\r
1719                                 {\r
1720                                         ym2612.OPN.lfo_inc = 0;\r
1721                                         ym2612.OPN.lfo_cnt = 0;\r
1722                                 }\r
1723                                 break;\r
1724 #if 0 // handled elsewhere\r
1725                         case 0x24: { // timer A High 8\r
1726                                         int TAnew = (ym2612.OPN.ST.TA & 0x03)|(((int)v)<<2);\r
1727                                         if(ym2612.OPN.ST.TA != TAnew) {\r
1728                                                 // we should reset ticker only if new value is written. Outrun requires this.\r
1729                                                 ym2612.OPN.ST.TA = TAnew;\r
1730                                                 ym2612.OPN.ST.TAC = (1024-TAnew)*18;\r
1731                                                 ym2612.OPN.ST.TAT = 0;\r
1732                                         }\r
1733                                 }\r
1734                                 ret=0;\r
1735                                 break;\r
1736                         case 0x25: { // timer A Low 2\r
1737                                         int TAnew = (ym2612.OPN.ST.TA & 0x3fc)|(v&3);\r
1738                                         if(ym2612.OPN.ST.TA != TAnew) {\r
1739                                                 ym2612.OPN.ST.TA = TAnew;\r
1740                                                 ym2612.OPN.ST.TAC = (1024-TAnew)*18;\r
1741                                                 ym2612.OPN.ST.TAT = 0;\r
1742                                         }\r
1743                                 }\r
1744                                 ret=0;\r
1745                                 break;\r
1746                         case 0x26: // timer B\r
1747                                 if(ym2612.OPN.ST.TB != v) {\r
1748                                         ym2612.OPN.ST.TB = v;\r
1749                                         ym2612.OPN.ST.TBC  = (256-v)<<4;\r
1750                                         ym2612.OPN.ST.TBC *= 18;\r
1751                                         ym2612.OPN.ST.TBT  = 0;\r
1752                                 }\r
1753                                 ret=0;\r
1754                                 break;\r
1755 #endif\r
1756                         case 0x27:      /* mode, timer control */\r
1757                                 set_timers( v );\r
1758                                 ret=0;\r
1759                                 break;\r
1760                         case 0x28:      /* key on / off */\r
1761                                 {\r
1762                                         UINT8 c;\r
1763 \r
1764                                         c = v & 0x03;\r
1765                                         if( c == 3 ) { ret=0; break; }\r
1766                                         if( v&0x04 ) c+=3;\r
1767                                         if(v&0x10) FM_KEYON(c,SLOT1); else FM_KEYOFF(c,SLOT1);\r
1768                                         if(v&0x20) FM_KEYON(c,SLOT2); else FM_KEYOFF(c,SLOT2);\r
1769                                         if(v&0x40) FM_KEYON(c,SLOT3); else FM_KEYOFF(c,SLOT3);\r
1770                                         if(v&0x80) FM_KEYON(c,SLOT4); else FM_KEYOFF(c,SLOT4);\r
1771                                         break;\r
1772                                 }\r
1773                         case 0x2a:      /* DAC data (YM2612) */\r
1774                                 ym2612.dacout = ((int)v - 0x80) << 6;   /* level unknown (notaz: 8 seems to be too much) */\r
1775                                 ret=0;\r
1776                                 break;\r
1777                         case 0x2b:      /* DAC Sel  (YM2612) */\r
1778                                 /* b7 = dac enable */\r
1779                                 ym2612.dacen = v & 0x80;\r
1780                                 ret=0;\r
1781                                 break;\r
1782                         default:\r
1783                                 break;\r
1784                         }\r
1785                         break;\r
1786                 default:        /* 0x30-0xff OPN section */\r
1787                         /* write register */\r
1788                         ret = OPNWriteReg(addr,v);\r
1789                 }\r
1790                 break;\r
1791         }\r
1792 \r
1793         return ret;\r
1794 }\r
1795 \r
1796 #if 0\r
1797 UINT8 YM2612Read_(void)\r
1798 {\r
1799         return ym2612.OPN.ST.status;\r
1800 }\r
1801 \r
1802 int YM2612PicoTick_(int n)\r
1803 {\r
1804         int ret = 0;\r
1805 \r
1806         // timer A\r
1807         if(ym2612.OPN.ST.mode & 0x01 && (ym2612.OPN.ST.TAT+=64*n) >= ym2612.OPN.ST.TAC) {\r
1808                 ym2612.OPN.ST.TAT -= ym2612.OPN.ST.TAC;\r
1809                 if(ym2612.OPN.ST.mode & 0x04) ym2612.OPN.ST.status |= 1;\r
1810                 // CSM mode total level latch and auto key on\r
1811                 if(ym2612.OPN.ST.mode & 0x80) {\r
1812                         CSMKeyControll( &(ym2612.CH[2]) ); // Vectorman2, etc.\r
1813                         ret = 1;\r
1814                 }\r
1815         }\r
1816 \r
1817         // timer B\r
1818         if(ym2612.OPN.ST.mode & 0x02 && (ym2612.OPN.ST.TBT+=64*n) >= ym2612.OPN.ST.TBC) {\r
1819                 ym2612.OPN.ST.TBT -= ym2612.OPN.ST.TBC;\r
1820                 if(ym2612.OPN.ST.mode & 0x08) ym2612.OPN.ST.status |= 2;\r
1821         }\r
1822 \r
1823         return ret;\r
1824 }\r
1825 #endif\r
1826 \r
1827 void YM2612PicoStateLoad_(void)\r
1828 {\r
1829         reset_channels( &ym2612.CH[0] );\r
1830         ym2612.slot_mask = 0xffffff;\r
1831 }\r
1832 \r
1833 /* rather stupid design because I wanted to fit in unused register "space" */\r
1834 typedef struct\r
1835 {\r
1836         UINT32  state_phase;\r
1837         INT16   volume;\r
1838 } ym_save_addon_slot;\r
1839 \r
1840 typedef struct\r
1841 {\r
1842         UINT32  magic;\r
1843         UINT8   address;\r
1844         UINT8   status;\r
1845         UINT8   addr_A1;\r
1846         UINT8   unused;\r
1847         int     TAT;\r
1848         int     TBT;\r
1849         UINT32  eg_cnt;         // 10\r
1850         UINT32  eg_timer;\r
1851         UINT32  lfo_cnt;\r
1852         UINT16  lfo_ampm;\r
1853         UINT16  unused2;\r
1854         UINT32  keyon_field;    // 20\r
1855         UINT32  kcode_fc_sl3_3;\r
1856         UINT32  reserved[2];\r
1857 } ym_save_addon;\r
1858 \r
1859 typedef struct\r
1860 {\r
1861         UINT16  block_fnum[6];\r
1862         UINT16  block_fnum_sl3[3];\r
1863         UINT16  reserved[7];\r
1864 } ym_save_addon2;\r
1865 \r
1866 \r
1867 void YM2612PicoStateSave2(int tat, int tbt)\r
1868 {\r
1869         ym_save_addon_slot ss;\r
1870         ym_save_addon2 sa2;\r
1871         ym_save_addon sa;\r
1872         unsigned char *ptr;\r
1873         int c, s;\r
1874 \r
1875         memset(&sa, 0, sizeof(sa));\r
1876         memset(&sa2, 0, sizeof(sa2));\r
1877 \r
1878         // chans 1,2,3\r
1879         ptr = &ym2612.REGS[0x0b8];\r
1880         for (c = 0; c < 3; c++)\r
1881         {\r
1882                 for (s = 0; s < 4; s++) {\r
1883                         ss.state_phase = (ym2612.CH[c].SLOT[s].state << 29) | (ym2612.CH[c].SLOT[s].phase >> 3);\r
1884                         ss.volume = ym2612.CH[c].SLOT[s].volume;\r
1885                         if (ym2612.CH[c].SLOT[s].key)\r
1886                                 sa.keyon_field |= 1 << (c*4 + s);\r
1887                         memcpy(ptr, &ss, 6);\r
1888                         ptr += 6;\r
1889                 }\r
1890                 sa2.block_fnum[c] = ym2612.CH[c].block_fnum;\r
1891         }\r
1892         // chans 4,5,6\r
1893         ptr = &ym2612.REGS[0x1b8];\r
1894         for (; c < 6; c++)\r
1895         {\r
1896                 for (s = 0; s < 4; s++) {\r
1897                         ss.state_phase = (ym2612.CH[c].SLOT[s].state << 29) | (ym2612.CH[c].SLOT[s].phase >> 3);\r
1898                         ss.volume = ym2612.CH[c].SLOT[s].volume;\r
1899                         if (ym2612.CH[c].SLOT[s].key)\r
1900                                 sa.keyon_field |= 1 << (c*4 + s);\r
1901                         memcpy(ptr, &ss, 6);\r
1902                         ptr += 6;\r
1903                 }\r
1904                 sa2.block_fnum[c] = ym2612.CH[c].block_fnum;\r
1905         }\r
1906         for (c = 0; c < 3; c++)\r
1907         {\r
1908                 sa2.block_fnum_sl3[c] = ym2612.OPN.SL3.block_fnum[c];\r
1909         }\r
1910 \r
1911         memcpy(&ym2612.REGS[0], &sa2, sizeof(sa2)); // 0x20 max\r
1912 \r
1913         // other things\r
1914         ptr = &ym2612.REGS[0x100];\r
1915         sa.magic = 0x41534d59; // 'YMSA'\r
1916         sa.address = ym2612.OPN.ST.address;\r
1917         sa.status  = ym2612.OPN.ST.status;\r
1918         sa.addr_A1 = ym2612.addr_A1;\r
1919         sa.TAT     = tat;\r
1920         sa.TBT     = tbt;\r
1921         sa.eg_cnt  = ym2612.OPN.eg_cnt;\r
1922         sa.eg_timer = ym2612.OPN.eg_timer;\r
1923         sa.lfo_cnt  = ym2612.OPN.lfo_cnt;\r
1924         sa.lfo_ampm = g_lfo_ampm;\r
1925         memcpy(ptr, &sa, sizeof(sa)); // 0x30 max\r
1926 }\r
1927 \r
1928 int YM2612PicoStateLoad2(int *tat, int *tbt)\r
1929 {\r
1930         ym_save_addon_slot ss;\r
1931         ym_save_addon2 sa2;\r
1932         ym_save_addon sa;\r
1933         unsigned char *ptr;\r
1934         UINT32 fn;\r
1935         UINT8 blk;\r
1936         int c, s;\r
1937 \r
1938         ptr = &ym2612.REGS[0x100];\r
1939         memcpy(&sa, ptr, sizeof(sa)); // 0x30 max\r
1940         if (sa.magic != 0x41534d59) return -1;\r
1941 \r
1942         ptr = &ym2612.REGS[0];\r
1943         memcpy(&sa2, ptr, sizeof(sa2));\r
1944 \r
1945         ym2612.OPN.ST.address = sa.address;\r
1946         ym2612.OPN.ST.status = sa.status;\r
1947         ym2612.addr_A1 = sa.addr_A1;\r
1948         ym2612.OPN.eg_cnt = sa.eg_cnt;\r
1949         ym2612.OPN.eg_timer = sa.eg_timer;\r
1950         ym2612.OPN.lfo_cnt = sa.lfo_cnt;\r
1951         g_lfo_ampm = sa.lfo_ampm;\r
1952         if (tat != NULL) *tat = sa.TAT;\r
1953         if (tbt != NULL) *tbt = sa.TBT;\r
1954 \r
1955         // chans 1,2,3\r
1956         ptr = &ym2612.REGS[0x0b8];\r
1957         for (c = 0; c < 3; c++)\r
1958         {\r
1959                 for (s = 0; s < 4; s++) {\r
1960                         memcpy(&ss, ptr, 6);\r
1961                         ym2612.CH[c].SLOT[s].state = ss.state_phase >> 29;\r
1962                         ym2612.CH[c].SLOT[s].phase = ss.state_phase << 3;\r
1963                         ym2612.CH[c].SLOT[s].volume = ss.volume;\r
1964                         ym2612.CH[c].SLOT[s].key = (sa.keyon_field & (1 << (c*4 + s))) ? 1 : 0;\r
1965                         ym2612.CH[c].SLOT[s].ksr = (UINT8)-1;\r
1966                         ptr += 6;\r
1967                 }\r
1968                 ym2612.CH[c].SLOT[SLOT1].Incr=-1;\r
1969                 ym2612.CH[c].block_fnum = sa2.block_fnum[c];\r
1970                 fn = ym2612.CH[c].block_fnum & 0x7ff;\r
1971                 blk = ym2612.CH[c].block_fnum >> 11;\r
1972                 ym2612.CH[c].kcode= (blk<<2) | opn_fktable[fn >> 7];\r
1973                 ym2612.CH[c].fc = fn_table[fn*2]>>(7-blk);\r
1974         }\r
1975         // chans 4,5,6\r
1976         ptr = &ym2612.REGS[0x1b8];\r
1977         for (; c < 6; c++)\r
1978         {\r
1979                 for (s = 0; s < 4; s++) {\r
1980                         memcpy(&ss, ptr, 6);\r
1981                         ym2612.CH[c].SLOT[s].state = ss.state_phase >> 29;\r
1982                         ym2612.CH[c].SLOT[s].phase = ss.state_phase << 3;\r
1983                         ym2612.CH[c].SLOT[s].volume = ss.volume;\r
1984                         ym2612.CH[c].SLOT[s].key = (sa.keyon_field & (1 << (c*4 + s))) ? 1 : 0;\r
1985                         ym2612.CH[c].SLOT[s].ksr = (UINT8)-1;\r
1986                         ptr += 6;\r
1987                 }\r
1988                 ym2612.CH[c].SLOT[SLOT1].Incr=-1;\r
1989                 ym2612.CH[c].block_fnum = sa2.block_fnum[c];\r
1990                 fn = ym2612.CH[c].block_fnum & 0x7ff;\r
1991                 blk = ym2612.CH[c].block_fnum >> 11;\r
1992                 ym2612.CH[c].kcode= (blk<<2) | opn_fktable[fn >> 7];\r
1993                 ym2612.CH[c].fc = fn_table[fn*2]>>(7-blk);\r
1994         }\r
1995         for (c = 0; c < 3; c++)\r
1996         {\r
1997                 ym2612.OPN.SL3.block_fnum[c] = sa2.block_fnum_sl3[c];\r
1998                 fn = ym2612.OPN.SL3.block_fnum[c] & 0x7ff;\r
1999                 blk = ym2612.OPN.SL3.block_fnum[c] >> 11;\r
2000                 ym2612.OPN.SL3.kcode[c]= (blk<<2) | opn_fktable[fn >> 7];\r
2001                 ym2612.OPN.SL3.fc[c] = fn_table[fn*2]>>(7-blk);\r
2002         }\r
2003 \r
2004         return 0;\r
2005 }\r
2006 \r
2007 void *YM2612GetRegs(void)\r
2008 {\r
2009         return ym2612.REGS;\r
2010 }\r
2011 \r