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