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