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