cc68a136 |
1 | /*\r |
4f265db7 |
2 | ** This is a bunch of remains of original fm.c from MAME project. All stuff\r |
cc68a136 |
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 |
9090dc0f |
8 | **\r |
9 | ** updated with fixes from mame 0.216 (file version 1.5.1) (kub)\r |
8ac9ab7f |
10 | ** SSG-EG readded from GenPlus (kub)\r |
cc68a136 |
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 <string.h>\r |
115 | #include <math.h>\r |
116 | \r |
110a49ed |
117 | #include "../pico_int.h"\r |
cc68a136 |
118 | #include "ym2612.h"\r |
119 | \r |
120 | #ifndef EXTERNAL_YM2612\r |
121 | #include <stdlib.h>\r |
122 | // let it be 1 global to simplify things\r |
4b9c5888 |
123 | YM2612 ym2612;\r |
cc68a136 |
124 | \r |
125 | #else\r |
126 | extern YM2612 *ym2612_940;\r |
cc68a136 |
127 | #define ym2612 (*ym2612_940)\r |
128 | \r |
129 | #endif\r |
130 | \r |
1dbda5f8 |
131 | void memset32(void *dest, int c, int count);\r |
cea65903 |
132 | \r |
cc68a136 |
133 | \r |
134 | #ifndef __GNUC__\r |
135 | #pragma warning (disable:4100) // unreferenced formal parameter\r |
136 | #pragma warning (disable:4244)\r |
137 | #pragma warning (disable:4245) // signed/unsigned in conversion\r |
138 | #pragma warning (disable:4710)\r |
139 | #pragma warning (disable:4018) // signed/unsigned\r |
140 | #endif\r |
141 | \r |
142 | #ifndef INLINE\r |
12d506ba |
143 | #define INLINE __inline\r |
cc68a136 |
144 | #endif\r |
145 | \r |
146 | #ifndef M_PI\r |
147 | #define M_PI 3.14159265358979323846\r |
148 | #endif\r |
149 | \r |
150 | \r |
151 | /* globals */\r |
152 | \r |
153 | #define FREQ_SH 16 /* 16.16 fixed point (frequency calculations) */\r |
154 | #define EG_SH 16 /* 16.16 fixed point (envelope generator timing) */\r |
9090dc0f |
155 | #define LFO_SH 24 /* 8.24 fixed point (LFO calculations) */\r |
cc68a136 |
156 | #define TIMER_SH 16 /* 16.16 fixed point (timers 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 |
cc68a136 |
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 |
864ac1d6 |
196 | static int ym_init_tab;\r |
197 | \r |
cc68a136 |
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 |
8ac9ab7f |
286 | O(18),O(18),O( 2),O( 3),\r |
287 | O( 0),O( 1),O( 2),O( 3),\r |
cc68a136 |
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 |
9090dc0f |
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 |
cc68a136 |
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 |
eaa9417a |
380 | 8 ,8, 9,10,11,12,13,14,16,17,19,20,22,22,22,22\r |
cc68a136 |
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 |
1dbda5f8 |
516 | static int g_lfo_ampm;\r |
cc68a136 |
517 | \r |
518 | /* register number to channel number , slot offset */\r |
519 | #define OPN_CHAN(N) (N&3)\r |
520 | #define OPN_SLOT(N) ((N>>2)&3)\r |
521 | \r |
522 | /* slot number */\r |
523 | #define SLOT1 0\r |
524 | #define SLOT2 2\r |
525 | #define SLOT3 1\r |
526 | #define SLOT4 3\r |
527 | \r |
528 | \r |
529 | /* OPN Mode Register Write */\r |
12d506ba |
530 | static INLINE void set_timers( int v )\r |
cc68a136 |
531 | {\r |
532 | /* b7 = CSM MODE */\r |
533 | /* b6 = 3 slot mode */\r |
534 | /* b5 = reset b */\r |
535 | /* b4 = reset a */\r |
536 | /* b3 = timer enable b */\r |
537 | /* b2 = timer enable a */\r |
538 | /* b1 = load b */\r |
539 | /* b0 = load a */\r |
540 | ym2612.OPN.ST.mode = v;\r |
541 | \r |
542 | /* reset Timer b flag */\r |
543 | if( v & 0x20 )\r |
544 | ym2612.OPN.ST.status &= ~2;\r |
545 | \r |
546 | /* reset Timer a flag */\r |
547 | if( v & 0x10 )\r |
548 | ym2612.OPN.ST.status &= ~1;\r |
549 | }\r |
550 | \r |
12d506ba |
551 | static INLINE void recalc_volout(FM_SLOT *SLOT)\r |
8ac9ab7f |
552 | {\r |
553 | INT16 vol_out = SLOT->volume;\r |
554 | if ((SLOT->ssg&0x0c) == 0x0c)\r |
f3876af7 |
555 | vol_out = (0x200 - vol_out) & MAX_ATT_INDEX;\r |
8ac9ab7f |
556 | SLOT->vol_out = vol_out + SLOT->tl;\r |
557 | }\r |
cc68a136 |
558 | \r |
12d506ba |
559 | static INLINE void FM_KEYON(int c , int s )\r |
cc68a136 |
560 | {\r |
b542be46 |
561 | FM_SLOT *SLOT = &ym2612.CH[c].SLOT[s];\r |
cc68a136 |
562 | if( !SLOT->key )\r |
563 | {\r |
564 | SLOT->key = 1;\r |
565 | SLOT->phase = 0; /* restart Phase Generator */\r |
8ac9ab7f |
566 | SLOT->ssg ^= SLOT->ssgn;\r |
567 | SLOT->ssgn = 0;\r |
568 | SLOT->state = (SLOT->sl == MIN_ATT_INDEX) ? EG_SUS : EG_DEC;\r |
b9bc876c |
569 | if (SLOT->ar_ksr < 32+62) {\r |
8ac9ab7f |
570 | if (SLOT->volume > MIN_ATT_INDEX) SLOT->state = EG_ATT;\r |
9090dc0f |
571 | } else {\r |
572 | SLOT->volume = MIN_ATT_INDEX;\r |
9090dc0f |
573 | }\r |
b26071be |
574 | recalc_volout(SLOT);\r |
b542be46 |
575 | ym2612.slot_mask |= (1<<s) << (c*4);\r |
cc68a136 |
576 | }\r |
577 | }\r |
578 | \r |
12d506ba |
579 | static INLINE void FM_KEYOFF(int c , int s )\r |
cc68a136 |
580 | {\r |
b542be46 |
581 | FM_SLOT *SLOT = &ym2612.CH[c].SLOT[s];\r |
cc68a136 |
582 | if( SLOT->key )\r |
583 | {\r |
584 | SLOT->key = 0;\r |
8ac9ab7f |
585 | if (SLOT->state>EG_REL) {\r |
cc68a136 |
586 | SLOT->state = EG_REL;/* phase -> Release */\r |
8ac9ab7f |
587 | if (SLOT->ssg&0x08) {\r |
588 | if (SLOT->ssg&0x04)\r |
589 | SLOT->volume = (0x200 - SLOT->volume);\r |
590 | if (SLOT->volume >= 0x200) {\r |
591 | SLOT->volume = MAX_ATT_INDEX;\r |
592 | SLOT->state = EG_OFF;\r |
593 | }\r |
594 | }\r |
595 | }\r |
596 | SLOT->vol_out = SLOT->volume + SLOT->tl;\r |
cc68a136 |
597 | }\r |
598 | }\r |
599 | \r |
600 | \r |
601 | /* set detune & multiple */\r |
12d506ba |
602 | static INLINE void set_det_mul(FM_CH *CH, FM_SLOT *SLOT, int v)\r |
cc68a136 |
603 | {\r |
604 | SLOT->mul = (v&0x0f)? (v&0x0f)*2 : 1;\r |
605 | SLOT->DT = ym2612.OPN.ST.dt_tab[(v>>4)&7];\r |
606 | CH->SLOT[SLOT1].Incr=-1;\r |
607 | }\r |
608 | \r |
609 | /* set total level */\r |
12d506ba |
610 | static INLINE void set_tl(FM_SLOT *SLOT, int v)\r |
cc68a136 |
611 | {\r |
612 | SLOT->tl = (v&0x7f)<<(ENV_BITS-7); /* 7bit TL */\r |
b26071be |
613 | if (SLOT->state > EG_REL)\r |
614 | recalc_volout(SLOT);\r |
cc68a136 |
615 | }\r |
616 | \r |
617 | /* set attack rate & key scale */\r |
12d506ba |
618 | static INLINE void set_ar_ksr(FM_CH *CH, FM_SLOT *SLOT, int v)\r |
cc68a136 |
619 | {\r |
620 | UINT8 old_KSR = SLOT->KSR;\r |
8ac9ab7f |
621 | int eg_sh_ar, eg_sel_ar;\r |
cc68a136 |
622 | \r |
623 | SLOT->ar = (v&0x1f) ? 32 + ((v&0x1f)<<1) : 0;\r |
b9bc876c |
624 | SLOT->ar_ksr = SLOT->ar + SLOT->ksr;\r |
cc68a136 |
625 | \r |
626 | SLOT->KSR = 3-(v>>6);\r |
627 | if (SLOT->KSR != old_KSR)\r |
628 | {\r |
629 | CH->SLOT[SLOT1].Incr=-1;\r |
630 | }\r |
8ac9ab7f |
631 | \r |
632 | /* refresh Attack rate */\r |
b9bc876c |
633 | if ((SLOT->ar_ksr) < 32+62)\r |
8ac9ab7f |
634 | {\r |
b9bc876c |
635 | eg_sh_ar = eg_rate_shift [SLOT->ar_ksr];\r |
636 | eg_sel_ar = eg_rate_select[SLOT->ar_ksr];\r |
8ac9ab7f |
637 | }\r |
cc68a136 |
638 | else\r |
639 | {\r |
8ac9ab7f |
640 | eg_sh_ar = 0;\r |
641 | eg_sel_ar = 18;\r |
cc68a136 |
642 | }\r |
8ac9ab7f |
643 | \r |
644 | SLOT->eg_pack_ar = eg_inc_pack[eg_sel_ar] | (eg_sh_ar<<24);\r |
cc68a136 |
645 | }\r |
646 | \r |
647 | /* set decay rate */\r |
12d506ba |
648 | static INLINE void set_dr(FM_SLOT *SLOT, int v)\r |
cc68a136 |
649 | {\r |
650 | int eg_sh_d1r, eg_sel_d1r;\r |
651 | \r |
652 | SLOT->d1r = (v&0x1f) ? 32 + ((v&0x1f)<<1) : 0;\r |
653 | \r |
654 | eg_sh_d1r = eg_rate_shift [SLOT->d1r + SLOT->ksr];\r |
655 | eg_sel_d1r= eg_rate_select[SLOT->d1r + SLOT->ksr];\r |
656 | \r |
657 | SLOT->eg_pack_d1r = eg_inc_pack[eg_sel_d1r] | (eg_sh_d1r<<24);\r |
658 | }\r |
659 | \r |
660 | /* set sustain rate */\r |
12d506ba |
661 | static INLINE void set_sr(FM_SLOT *SLOT, int v)\r |
cc68a136 |
662 | {\r |
663 | int eg_sh_d2r, eg_sel_d2r;\r |
664 | \r |
665 | SLOT->d2r = (v&0x1f) ? 32 + ((v&0x1f)<<1) : 0;\r |
666 | \r |
667 | eg_sh_d2r = eg_rate_shift [SLOT->d2r + SLOT->ksr];\r |
668 | eg_sel_d2r= eg_rate_select[SLOT->d2r + SLOT->ksr];\r |
669 | \r |
670 | SLOT->eg_pack_d2r = eg_inc_pack[eg_sel_d2r] | (eg_sh_d2r<<24);\r |
671 | }\r |
672 | \r |
673 | /* set release rate */\r |
12d506ba |
674 | static INLINE void set_sl_rr(FM_SLOT *SLOT, int v)\r |
cc68a136 |
675 | {\r |
676 | int eg_sh_rr, eg_sel_rr;\r |
677 | \r |
678 | SLOT->sl = sl_table[ v>>4 ];\r |
679 | \r |
9090dc0f |
680 | if (SLOT->state == EG_DEC && (SLOT->volume >= (INT32)(SLOT->sl)))\r |
681 | SLOT->state = EG_SUS;\r |
682 | \r |
cc68a136 |
683 | SLOT->rr = 34 + ((v&0x0f)<<2);\r |
684 | \r |
685 | eg_sh_rr = eg_rate_shift [SLOT->rr + SLOT->ksr];\r |
686 | eg_sel_rr = eg_rate_select[SLOT->rr + SLOT->ksr];\r |
687 | \r |
688 | SLOT->eg_pack_rr = eg_inc_pack[eg_sel_rr] | (eg_sh_rr<<24);\r |
689 | }\r |
690 | \r |
691 | \r |
692 | \r |
12d506ba |
693 | static INLINE signed int op_calc(UINT32 phase, unsigned int env, signed int pm)\r |
cc68a136 |
694 | {\r |
695 | int ret, sin = (phase>>16) + (pm>>1);\r |
696 | int neg = sin & 0x200;\r |
697 | if (sin & 0x100) sin ^= 0xff;\r |
698 | sin&=0xff;\r |
699 | env&=~1;\r |
700 | \r |
701 | // this was already checked\r |
702 | // if (env >= ENV_QUIET) // 384\r |
703 | // return 0;\r |
704 | \r |
705 | ret = ym_tl_tab[sin | (env<<7)];\r |
706 | \r |
707 | return neg ? -ret : ret;\r |
708 | }\r |
709 | \r |
12d506ba |
710 | static INLINE signed int op_calc1(UINT32 phase, unsigned int env, signed int pm)\r |
cc68a136 |
711 | {\r |
712 | int ret, sin = (phase+pm)>>16;\r |
713 | int neg = sin & 0x200;\r |
714 | if (sin & 0x100) sin ^= 0xff;\r |
715 | sin&=0xff;\r |
716 | env&=~1;\r |
717 | \r |
718 | // if (env >= ENV_QUIET) // 384\r |
719 | // return 0;\r |
720 | \r |
721 | ret = ym_tl_tab[sin | (env<<7)];\r |
722 | \r |
723 | return neg ? -ret : ret;\r |
724 | }\r |
725 | \r |
726 | #if !defined(_ASM_YM2612_C) || defined(EXTERNAL_YM2612)\r |
727 | /* advance LFO to next sample */\r |
12d506ba |
728 | static INLINE int advance_lfo(int lfo_ampm, UINT32 lfo_cnt_old, UINT32 lfo_cnt)\r |
cc68a136 |
729 | {\r |
730 | UINT8 pos;\r |
731 | UINT8 prev_pos;\r |
732 | \r |
733 | prev_pos = (lfo_cnt_old >> LFO_SH) & 127;\r |
734 | \r |
735 | pos = (lfo_cnt >> LFO_SH) & 127;\r |
736 | \r |
737 | /* update AM when LFO output changes */\r |
738 | \r |
739 | if (prev_pos != pos)\r |
740 | {\r |
741 | lfo_ampm &= 0xff;\r |
9090dc0f |
742 | /* triangle (inverted) */\r |
cc68a136 |
743 | /* AM: 0 to 126 step +2, 126 to 0 step -2 */\r |
744 | if (pos<64)\r |
9090dc0f |
745 | lfo_ampm |= ((pos^63) * 2) << 8; /* 0 - 126 */\r |
cc68a136 |
746 | else\r |
9090dc0f |
747 | lfo_ampm |= ((pos&63) * 2) << 8;\r |
cc68a136 |
748 | }\r |
749 | else\r |
750 | {\r |
751 | return lfo_ampm;\r |
752 | }\r |
753 | \r |
754 | /* PM works with 4 times slower clock */\r |
755 | prev_pos >>= 2;\r |
756 | pos >>= 2;\r |
757 | /* update PM when LFO output changes */\r |
758 | if (prev_pos != pos)\r |
759 | {\r |
760 | lfo_ampm &= ~0xff;\r |
761 | lfo_ampm |= pos; /* 0 - 32 */\r |
762 | }\r |
763 | return lfo_ampm;\r |
764 | }\r |
765 | \r |
12d506ba |
766 | static INLINE void update_eg_phase(FM_SLOT *SLOT, UINT32 eg_cnt, UINT32 ssg_en)\r |
cc68a136 |
767 | {\r |
768 | INT32 volume = SLOT->volume;\r |
6d28fb50 |
769 | UINT32 pack = SLOT->eg_pack[SLOT->state - 1];\r |
770 | UINT32 shift = pack >> 24;\r |
771 | INT32 eg_inc_val;\r |
cc68a136 |
772 | \r |
6d28fb50 |
773 | if (eg_cnt & ((1 << shift) - 1))\r |
774 | return;\r |
cc68a136 |
775 | \r |
6d28fb50 |
776 | eg_inc_val = pack >> ((eg_cnt >> shift) & 7) * 3;\r |
777 | eg_inc_val = (1 << (eg_inc_val & 7)) >> 1;\r |
cc68a136 |
778 | \r |
1dbda5f8 |
779 | if ((SLOT->ssg&0x08) && ssg_en) {\r |
8ac9ab7f |
780 | switch (SLOT->state)\r |
cc68a136 |
781 | {\r |
8ac9ab7f |
782 | case EG_ATT: /* attack phase */\r |
783 | volume += ( ~volume * eg_inc_val ) >> 4;\r |
784 | if ( volume <= MIN_ATT_INDEX )\r |
785 | {\r |
786 | volume = MIN_ATT_INDEX;\r |
787 | SLOT->state = (SLOT->sl == MIN_ATT_INDEX) ? EG_SUS: EG_DEC;\r |
788 | }\r |
789 | break;\r |
790 | \r |
791 | case EG_DEC: /* decay phase */\r |
792 | if (volume < 0x200)\r |
793 | volume += 4*eg_inc_val;\r |
794 | if ( volume >= (INT32) SLOT->sl )\r |
795 | SLOT->state = EG_SUS;\r |
796 | break;\r |
797 | \r |
798 | case EG_SUS: /* sustain phase */\r |
799 | if (volume < 0x200)\r |
800 | volume += 4*eg_inc_val;\r |
801 | break;\r |
802 | \r |
803 | case EG_REL: /* release phase */\r |
804 | if (volume < 0x200)\r |
805 | volume += 4*eg_inc_val;\r |
806 | if ( volume >= 0x200 )\r |
807 | {\r |
808 | volume = MAX_ATT_INDEX;\r |
809 | SLOT->state = EG_OFF;\r |
810 | }\r |
811 | break;\r |
cc68a136 |
812 | }\r |
cc68a136 |
813 | \r |
8ac9ab7f |
814 | SLOT->vol_out = volume + SLOT->tl;\r |
815 | if ((SLOT->ssg&0x04) && (SLOT->state > EG_REL))\r |
816 | SLOT->vol_out = ((0x200 - volume) & MAX_ATT_INDEX) + SLOT->tl;\r |
817 | } else {\r |
818 | switch (SLOT->state)\r |
6d28fb50 |
819 | {\r |
8ac9ab7f |
820 | case EG_ATT: /* attack phase */\r |
821 | volume += ( ~volume * eg_inc_val ) >> 4;\r |
822 | if ( volume <= MIN_ATT_INDEX )\r |
823 | {\r |
824 | volume = MIN_ATT_INDEX;\r |
825 | SLOT->state = (SLOT->sl == MIN_ATT_INDEX) ? EG_SUS: EG_DEC;\r |
826 | }\r |
827 | break;\r |
cc68a136 |
828 | \r |
8ac9ab7f |
829 | case EG_DEC: /* decay phase */\r |
830 | volume += eg_inc_val;\r |
831 | if ( volume >= (INT32) SLOT->sl )\r |
832 | SLOT->state = EG_SUS;\r |
833 | break;\r |
834 | \r |
835 | case EG_SUS: /* sustain phase */\r |
836 | volume += eg_inc_val;\r |
837 | if ( volume >= MAX_ATT_INDEX )\r |
838 | {\r |
839 | volume = MAX_ATT_INDEX;\r |
840 | /* do not change SLOT->state (verified on real chip) */\r |
841 | }\r |
842 | break;\r |
843 | \r |
844 | case EG_REL: /* release phase */\r |
845 | volume += eg_inc_val;\r |
846 | if ( volume >= MAX_ATT_INDEX )\r |
847 | {\r |
848 | volume = MAX_ATT_INDEX;\r |
849 | SLOT->state = EG_OFF;\r |
850 | }\r |
851 | break;\r |
cc68a136 |
852 | }\r |
cc68a136 |
853 | \r |
8ac9ab7f |
854 | SLOT->vol_out = volume + SLOT->tl;\r |
855 | }\r |
cc68a136 |
856 | SLOT->volume = volume;\r |
8ac9ab7f |
857 | }\r |
858 | \r |
12d506ba |
859 | static INLINE UINT32 update_ssg_eg_phase(FM_SLOT *SLOT, UINT32 phase)\r |
8ac9ab7f |
860 | {\r |
861 | if (SLOT->ssg&0x01) {\r |
862 | if (SLOT->ssg&0x02) {\r |
863 | SLOT->ssg ^= SLOT->ssgn ^ 4;\r |
864 | SLOT->ssgn = 4;\r |
865 | }\r |
866 | \r |
867 | if (SLOT->state != EG_ATT && !(SLOT->ssg&0x04))\r |
868 | SLOT->volume = MAX_ATT_INDEX;\r |
869 | } else {\r |
870 | if (SLOT->ssg&0x02) {\r |
871 | SLOT->ssg ^= 4;\r |
872 | SLOT->ssgn ^= 4;\r |
873 | } else\r |
1dbda5f8 |
874 | phase = 0;\r |
8ac9ab7f |
875 | \r |
876 | if (SLOT->state != EG_ATT) {\r |
877 | SLOT->state = (SLOT->sl == MIN_ATT_INDEX) ? EG_SUS : EG_DEC;\r |
b9bc876c |
878 | if (SLOT->ar_ksr < 32+62) {\r |
8ac9ab7f |
879 | if (SLOT->volume > MIN_ATT_INDEX) SLOT->state = EG_ATT;\r |
880 | } else {\r |
881 | SLOT->volume = MIN_ATT_INDEX;\r |
882 | }\r |
883 | }\r |
884 | }\r |
f3876af7 |
885 | recalc_volout(SLOT);\r |
1dbda5f8 |
886 | return phase;\r |
cc68a136 |
887 | }\r |
888 | #endif\r |
889 | \r |
890 | \r |
891 | typedef struct\r |
892 | {\r |
893 | UINT16 vol_out1; /* 00: current output from EG circuit (without AM from LFO) */\r |
894 | UINT16 vol_out2;\r |
895 | UINT16 vol_out3;\r |
896 | UINT16 vol_out4;\r |
ccc39358 |
897 | UINT32 lfo_init_sft16;\r |
898 | UINT32 pad;\r |
cc68a136 |
899 | UINT32 phase1; /* 10 */\r |
900 | UINT32 phase2;\r |
901 | UINT32 phase3;\r |
902 | UINT32 phase4;\r |
903 | UINT32 incr1; /* 20: phase step */\r |
904 | UINT32 incr2;\r |
905 | UINT32 incr3;\r |
906 | UINT32 incr4;\r |
907 | UINT32 lfo_cnt; /* 30 */\r |
908 | UINT32 lfo_inc;\r |
909 | INT32 mem; /* one sample delay memory */\r |
910 | UINT32 eg_cnt; /* envelope generator counter */\r |
911 | FM_CH *CH; /* 40: envelope generator counter */\r |
912 | UINT32 eg_timer;\r |
913 | UINT32 eg_timer_add;\r |
914 | UINT32 pack; // 4c: stereo, lastchan, disabled, lfo_enabled | pan_r, pan_l, ams[2] | AMmasks[4] | FB[4] | lfo_ampm[16]\r |
d127b3f3 |
915 | UINT32 algo; /* 50: algo[3], was_update, unsued, upd_cnt[2], dac */\r |
cc68a136 |
916 | INT32 op1_out;\r |
b542be46 |
917 | #ifdef _MIPS_ARCH_ALLEGREX\r |
918 | UINT32 pad1[3+8];\r |
919 | #endif\r |
cc68a136 |
920 | } chan_rend_context;\r |
921 | \r |
922 | \r |
923 | #if !defined(_ASM_YM2612_C) || defined(EXTERNAL_YM2612)\r |
8794ba5c |
924 | #include <limits.h>\r |
925 | static int clip(int n) \r |
926 | {\r |
d127b3f3 |
927 | unsigned b = 14, s = n < 0;\r |
928 | int m = s + INT_MAX;\r |
929 | if (s + (n>>(b-1))) n = m >> (8*sizeof(int)-b);\r |
930 | return n;\r |
8794ba5c |
931 | }\r |
932 | \r |
d127b3f3 |
933 | static void update_ssg_eg_channel(chan_rend_context *ct)\r |
cc68a136 |
934 | {\r |
d127b3f3 |
935 | FM_SLOT *SLOT;\r |
936 | \r |
937 | SLOT = &ct->CH->SLOT[SLOT1];\r |
938 | if ((SLOT->ssg&0x08) && SLOT->state > EG_REL && SLOT->volume >= 0x200)\r |
939 | ct->phase1 = update_ssg_eg_phase(SLOT, ct->phase1);\r |
940 | SLOT = &ct->CH->SLOT[SLOT2];\r |
941 | if ((SLOT->ssg&0x08) && SLOT->state > EG_REL && SLOT->volume >= 0x200)\r |
942 | ct->phase2 = update_ssg_eg_phase(SLOT, ct->phase2);\r |
943 | SLOT = &ct->CH->SLOT[SLOT3];\r |
944 | if ((SLOT->ssg&0x08) && SLOT->state > EG_REL && SLOT->volume >= 0x200)\r |
945 | ct->phase3 = update_ssg_eg_phase(SLOT, ct->phase3);\r |
946 | SLOT = &ct->CH->SLOT[SLOT4];\r |
947 | if ((SLOT->ssg&0x08) && SLOT->state > EG_REL && SLOT->volume >= 0x200)\r |
948 | ct->phase4 = update_ssg_eg_phase(SLOT, ct->phase4);\r |
949 | }\r |
cc68a136 |
950 | \r |
d127b3f3 |
951 | static void update_eg_phase_channel(chan_rend_context *ct)\r |
952 | {\r |
953 | FM_SLOT *SLOT;\r |
954 | \r |
955 | SLOT = &ct->CH->SLOT[SLOT1];\r |
956 | if (SLOT->state != EG_OFF) update_eg_phase(SLOT, ct->eg_cnt, ct->pack & 2);\r |
957 | SLOT = &ct->CH->SLOT[SLOT2];\r |
958 | if (SLOT->state != EG_OFF) update_eg_phase(SLOT, ct->eg_cnt, ct->pack & 2);\r |
959 | SLOT = &ct->CH->SLOT[SLOT3];\r |
960 | if (SLOT->state != EG_OFF) update_eg_phase(SLOT, ct->eg_cnt, ct->pack & 2);\r |
961 | SLOT = &ct->CH->SLOT[SLOT4];\r |
962 | if (SLOT->state != EG_OFF) update_eg_phase(SLOT, ct->eg_cnt, ct->pack & 2);\r |
963 | }\r |
964 | \r |
965 | static int update_algo_channel(chan_rend_context *ct, unsigned int eg_out, unsigned int eg_out2, unsigned int eg_out4)\r |
966 | {\r |
967 | int m2,c1,c2=0; /* Phase Modulation input for operators 2,3,4 */\r |
968 | int smp = 0;\r |
969 | \r |
970 | switch( ct->algo&0x7 )\r |
cc68a136 |
971 | {\r |
d127b3f3 |
972 | case 0:\r |
973 | {\r |
974 | /* M1---C1---MEM---M2---C2---OUT */\r |
975 | m2 = ct->mem;\r |
976 | c1 = ct->op1_out>>16;\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 |
cc68a136 |
981 | \r |
d127b3f3 |
982 | if( eg_out < ENV_QUIET ) { /* SLOT 3 */\r |
983 | c2 = op_calc(ct->phase3, eg_out, m2);\r |
984 | }\r |
985 | if( eg_out4 < ENV_QUIET ) { /* SLOT 4 */\r |
986 | smp = op_calc(ct->phase4, eg_out4, c2);\r |
987 | }\r |
988 | break;\r |
cc68a136 |
989 | }\r |
d127b3f3 |
990 | case 1:\r |
991 | {\r |
992 | /* M1------+-MEM---M2---C2---OUT */\r |
993 | /* C1-+ */\r |
994 | m2 = ct->mem;\r |
995 | ct->mem = ct->op1_out>>16;\r |
996 | if( eg_out2 < ENV_QUIET ) { /* SLOT 2 */\r |
997 | ct->mem+= op_calc(ct->phase2, eg_out2, 0);\r |
998 | }\r |
cc68a136 |
999 | \r |
d127b3f3 |
1000 | if( eg_out < ENV_QUIET ) { /* SLOT 3 */\r |
1001 | c2 = op_calc(ct->phase3, eg_out, m2);\r |
1002 | }\r |
1003 | if( eg_out4 < ENV_QUIET ) { /* SLOT 4 */\r |
1004 | smp = op_calc(ct->phase4, eg_out4, c2);\r |
1005 | }\r |
1006 | break;\r |
1dbda5f8 |
1007 | }\r |
d127b3f3 |
1008 | case 2:\r |
cc68a136 |
1009 | {\r |
d127b3f3 |
1010 | /* M1-----------------+-C2---OUT */\r |
1011 | /* C1---MEM---M2-+ */\r |
1012 | m2 = ct->mem;\r |
1013 | c2 = ct->op1_out>>16;\r |
1014 | if( eg_out2 < ENV_QUIET ) { /* SLOT 2 */\r |
1015 | ct->mem = op_calc(ct->phase2, eg_out2, 0);\r |
1016 | }\r |
1017 | else ct->mem = 0;\r |
1dbda5f8 |
1018 | \r |
d127b3f3 |
1019 | if( eg_out < ENV_QUIET ) { /* SLOT 3 */\r |
1020 | c2 += op_calc(ct->phase3, eg_out, m2);\r |
1021 | }\r |
1022 | if( eg_out4 < ENV_QUIET ) { /* SLOT 4 */\r |
1023 | smp = op_calc(ct->phase4, eg_out4, c2);\r |
1024 | }\r |
1025 | break;\r |
b9bc876c |
1026 | }\r |
d127b3f3 |
1027 | case 3:\r |
cc68a136 |
1028 | {\r |
d127b3f3 |
1029 | /* M1---C1---MEM------+-C2---OUT */\r |
1030 | /* M2-+ */\r |
1031 | c2 = ct->mem;\r |
1032 | c1 = ct->op1_out>>16;\r |
1033 | if( eg_out2 < ENV_QUIET ) { /* SLOT 2 */\r |
1034 | ct->mem = op_calc(ct->phase2, eg_out2, c1);\r |
1035 | }\r |
1036 | else ct->mem = 0;\r |
cc68a136 |
1037 | \r |
d127b3f3 |
1038 | if( eg_out < ENV_QUIET ) { /* SLOT 3 */\r |
1039 | c2 += op_calc(ct->phase3, eg_out, 0);\r |
1040 | }\r |
1041 | if( eg_out4 < ENV_QUIET ) { /* SLOT 4 */\r |
1042 | smp = op_calc(ct->phase4, eg_out4, c2);\r |
1043 | }\r |
1044 | break;\r |
cc68a136 |
1045 | }\r |
d127b3f3 |
1046 | case 4:\r |
1047 | {\r |
1048 | /* M1---C1-+-OUT */\r |
1049 | /* M2---C2-+ */\r |
1050 | /* MEM: not used */\r |
d127b3f3 |
1051 | \r |
1052 | c1 = ct->op1_out>>16;\r |
1053 | if( eg_out < ENV_QUIET ) { /* SLOT 3 */\r |
1054 | c2 = op_calc(ct->phase3, eg_out, 0);\r |
1055 | }\r |
1056 | if( eg_out2 < ENV_QUIET ) { /* SLOT 2 */\r |
1057 | smp = op_calc(ct->phase2, eg_out2, c1);\r |
1058 | }\r |
1059 | if( eg_out4 < ENV_QUIET ) { /* SLOT 4 */\r |
1060 | smp+= op_calc(ct->phase4, eg_out4, c2);\r |
1061 | }\r |
1062 | break;\r |
cc68a136 |
1063 | }\r |
d127b3f3 |
1064 | case 5:\r |
cc68a136 |
1065 | {\r |
d127b3f3 |
1066 | /* +----C1----+ */\r |
1067 | /* M1-+-MEM---M2-+-OUT */\r |
1068 | /* +----C2----+ */\r |
d127b3f3 |
1069 | m2 = ct->mem;\r |
1070 | ct->mem = c1 = c2 = ct->op1_out>>16;\r |
5494fde2 |
1071 | \r |
d127b3f3 |
1072 | if( eg_out < ENV_QUIET ) { /* SLOT 3 */\r |
1073 | smp = op_calc(ct->phase3, eg_out, m2);\r |
cc68a136 |
1074 | }\r |
d127b3f3 |
1075 | if( eg_out2 < ENV_QUIET ) { /* SLOT 2 */\r |
1076 | smp+= op_calc(ct->phase2, eg_out2, c1);\r |
cc68a136 |
1077 | }\r |
d127b3f3 |
1078 | if( eg_out4 < ENV_QUIET ) { /* SLOT 4 */\r |
1079 | smp+= op_calc(ct->phase4, eg_out4, c2);\r |
cc68a136 |
1080 | }\r |
d127b3f3 |
1081 | break;\r |
1082 | }\r |
1083 | case 6:\r |
1084 | {\r |
1085 | /* M1---C1-+ */\r |
1086 | /* M2-+-OUT */\r |
1087 | /* C2-+ */\r |
1088 | /* MEM: not used */\r |
d127b3f3 |
1089 | \r |
1090 | c1 = ct->op1_out>>16;\r |
1091 | if( eg_out < ENV_QUIET ) { /* SLOT 3 */\r |
1092 | smp = op_calc(ct->phase3, eg_out, 0);\r |
cc68a136 |
1093 | }\r |
d127b3f3 |
1094 | if( eg_out2 < ENV_QUIET ) { /* SLOT 2 */\r |
1095 | smp+= op_calc(ct->phase2, eg_out2, c1);\r |
cc68a136 |
1096 | }\r |
d127b3f3 |
1097 | if( eg_out4 < ENV_QUIET ) { /* SLOT 4 */\r |
1098 | smp+= op_calc(ct->phase4, eg_out4, 0);\r |
cc68a136 |
1099 | }\r |
d127b3f3 |
1100 | break;\r |
1101 | }\r |
1102 | case 7:\r |
1103 | {\r |
1104 | /* M1-+ */\r |
1105 | /* C1-+-OUT */\r |
1106 | /* M2-+ */\r |
1107 | /* C2-+ */\r |
1108 | /* MEM: not used*/\r |
d127b3f3 |
1109 | \r |
1110 | smp = ct->op1_out>>16;\r |
1111 | if( eg_out < ENV_QUIET ) { /* SLOT 3 */\r |
1112 | smp += op_calc(ct->phase3, eg_out, 0);\r |
cc68a136 |
1113 | }\r |
d127b3f3 |
1114 | if( eg_out2 < ENV_QUIET ) { /* SLOT 2 */\r |
1115 | smp += op_calc(ct->phase2, eg_out2, 0);\r |
1116 | }\r |
1117 | if( eg_out4 < ENV_QUIET ) { /* SLOT 4 */\r |
1118 | smp += op_calc(ct->phase4, eg_out4, 0);\r |
1119 | }\r |
1120 | break;\r |
1121 | }\r |
1122 | }\r |
1123 | return smp;\r |
1124 | }\r |
1125 | \r |
f7741cac |
1126 | static void chan_render_loop(chan_rend_context *ct, s32 *buffer, int length)\r |
d127b3f3 |
1127 | {\r |
1128 | int scounter; /* sample counter */\r |
1129 | \r |
1130 | /* sample generating loop */\r |
1131 | for (scounter = 0; scounter < length; scounter++)\r |
1132 | {\r |
1133 | int smp = 0; /* produced sample */\r |
1134 | unsigned int eg_out, eg_out2, eg_out4;\r |
1135 | \r |
1136 | ct->eg_timer += ct->eg_timer_add;\r |
d127b3f3 |
1137 | \r |
5494fde2 |
1138 | while (ct->eg_timer >= 1<<EG_SH) {\r |
1139 | ct->eg_timer -= 1<<EG_SH;\r |
1140 | \r |
d127b3f3 |
1141 | if (ct->pack & 2)\r |
1142 | update_ssg_eg_channel(ct);\r |
1143 | \r |
1144 | if (ct->algo & 0x30)\r |
1145 | ct->algo -= 0x10;\r |
1146 | if (!(ct->algo & 0x30)) {\r |
1147 | ct->algo |= 0x30;\r |
1148 | ct->eg_cnt++;\r |
1149 | if (ct->eg_cnt >= 4096) ct->eg_cnt = 1;\r |
1150 | \r |
1151 | update_eg_phase_channel(ct);\r |
1152 | }\r |
882f697a |
1153 | }\r |
d127b3f3 |
1154 | \r |
882f697a |
1155 | ct->vol_out1 = ct->CH->SLOT[SLOT1].vol_out;\r |
1156 | ct->vol_out2 = ct->CH->SLOT[SLOT2].vol_out;\r |
1157 | ct->vol_out3 = ct->CH->SLOT[SLOT3].vol_out;\r |
1158 | ct->vol_out4 = ct->CH->SLOT[SLOT4].vol_out;\r |
5494fde2 |
1159 | \r |
882f697a |
1160 | if (ct->pack & 4) goto disabled; /* output disabled */\r |
5494fde2 |
1161 | \r |
882f697a |
1162 | if (ct->pack & 8) { /* LFO enabled ? (test Earthworm Jim in between demo 1 and 2) */\r |
1163 | ct->pack = (ct->pack&0xffff) | (advance_lfo(ct->pack >> 16, ct->lfo_cnt, ct->lfo_cnt + ct->lfo_inc) << 16);\r |
1164 | ct->lfo_cnt += ct->lfo_inc;\r |
1165 | }\r |
d127b3f3 |
1166 | \r |
882f697a |
1167 | /* calculate channel sample */\r |
1168 | eg_out = ct->vol_out1;\r |
1169 | if ( (ct->pack & 8) && (ct->pack&(1<<(SLOT1+8))) )\r |
1170 | eg_out += ct->pack >> (((ct->pack&0xc0)>>6)+24);\r |
d127b3f3 |
1171 | \r |
882f697a |
1172 | if( eg_out < ENV_QUIET ) /* SLOT 1 */\r |
1173 | {\r |
1174 | int out = 0;\r |
d127b3f3 |
1175 | \r |
882f697a |
1176 | if (ct->pack&0xf000) out = ((ct->op1_out + (ct->op1_out<<16))>>16) << ((ct->pack&0xf000)>>12); /* op1_out0 + op1_out1 */\r |
1177 | ct->op1_out <<= 16;\r |
1178 | ct->op1_out |= (unsigned short)op_calc1(ct->phase1, eg_out, out);\r |
1179 | } else {\r |
1180 | ct->op1_out <<= 16; /* op1_out0 = op1_out1; op1_out1 = 0; */\r |
1181 | }\r |
5494fde2 |
1182 | \r |
882f697a |
1183 | eg_out = ct->vol_out3; // volume_calc(&CH->SLOT[SLOT3]);\r |
1184 | eg_out2 = ct->vol_out2; // volume_calc(&CH->SLOT[SLOT2]);\r |
1185 | eg_out4 = ct->vol_out4; // volume_calc(&CH->SLOT[SLOT4]);\r |
d127b3f3 |
1186 | \r |
882f697a |
1187 | if (ct->pack & 8) {\r |
1188 | unsigned int add = ct->pack >> (((ct->pack&0xc0)>>6)+24);\r |
1189 | if (ct->pack & (1<<(SLOT3+8))) eg_out += add;\r |
1190 | if (ct->pack & (1<<(SLOT2+8))) eg_out2 += add;\r |
1191 | if (ct->pack & (1<<(SLOT4+8))) eg_out4 += add;\r |
1192 | }\r |
d127b3f3 |
1193 | \r |
882f697a |
1194 | smp = update_algo_channel(ct, eg_out, eg_out2, eg_out4);\r |
1195 | /* done calculating channel sample */\r |
5494fde2 |
1196 | disabled:\r |
882f697a |
1197 | /* update phase counters AFTER output calculations */\r |
1198 | ct->phase1 += ct->incr1;\r |
1199 | ct->phase2 += ct->incr2;\r |
1200 | ct->phase3 += ct->incr3;\r |
1201 | ct->phase4 += ct->incr4;\r |
cc68a136 |
1202 | \r |
1203 | /* mix sample to output buffer */\r |
1204 | if (smp) {\r |
23cd73bc |
1205 | smp = clip(smp); /* saturate to 14 bit */\r |
1206 | if (ct->algo & 0x80) {\r |
1207 | smp &= ~0x1f; /* drop bits (DAC has 9 bits) */\r |
1208 | smp -= (smp < 0 ? 7:0) << 5; /* discontinuity */\r |
1209 | }\r |
cc68a136 |
1210 | if (ct->pack & 1) { /* stereo */\r |
1211 | if (ct->pack & 0x20) /* L */ /* TODO: check correctness */\r |
1212 | buffer[scounter*2] += smp;\r |
1213 | if (ct->pack & 0x10) /* R */\r |
1214 | buffer[scounter*2+1] += smp;\r |
1215 | } else {\r |
1216 | buffer[scounter] += smp;\r |
1217 | }\r |
6d28fb50 |
1218 | ct->algo |= 8;\r |
cc68a136 |
1219 | }\r |
cc68a136 |
1220 | }\r |
1221 | }\r |
1222 | #else\r |
f7741cac |
1223 | void chan_render_loop(chan_rend_context *ct, s32 *buffer, unsigned short length);\r |
cc68a136 |
1224 | #endif\r |
1225 | \r |
dca310c4 |
1226 | static chan_rend_context crct;\r |
cc68a136 |
1227 | \r |
d2721b08 |
1228 | static void chan_render_prep(void)\r |
1229 | {\r |
1230 | crct.eg_timer_add = ym2612.OPN.eg_timer_add;\r |
ccc39358 |
1231 | crct.lfo_init_sft16 = g_lfo_ampm << 16;\r |
d2721b08 |
1232 | crct.lfo_inc = ym2612.OPN.lfo_inc;\r |
1233 | }\r |
1234 | \r |
ccc39358 |
1235 | static void chan_render_finish(s32 *buffer, int length, int active_chans)\r |
d2721b08 |
1236 | {\r |
1237 | ym2612.OPN.eg_cnt = crct.eg_cnt;\r |
1238 | ym2612.OPN.eg_timer = crct.eg_timer;\r |
ccc39358 |
1239 | ym2612.OPN.lfo_cnt += ym2612.OPN.lfo_inc * length;\r |
d2721b08 |
1240 | }\r |
1241 | \r |
ccc39358 |
1242 | static UINT32 update_lfo_phase(const FM_SLOT *SLOT, UINT32 block_fnum)\r |
8ac9ab7f |
1243 | {\r |
1244 | UINT32 fnum_lfo;\r |
1245 | INT32 lfo_fn_table_index_offset;\r |
1246 | UINT8 blk;\r |
1247 | UINT32 fn;\r |
1248 | int fc,fdt;\r |
1249 | \r |
1250 | fnum_lfo = ((block_fnum & 0x7f0) >> 4) * 32 * 8;\r |
1251 | lfo_fn_table_index_offset = lfo_pm_table[ fnum_lfo + crct.CH->pms + ((crct.pack>>16)&0xff) ];\r |
1252 | if (lfo_fn_table_index_offset) /* LFO phase modulation active */\r |
1253 | {\r |
1254 | block_fnum = block_fnum*2 + lfo_fn_table_index_offset;\r |
1255 | blk = (block_fnum&0x7000) >> 12;\r |
1256 | fn = block_fnum & 0xfff;\r |
1257 | \r |
1258 | /* phase increment counter */\r |
1259 | fc = (fn_table[fn]>>(7-blk));\r |
1260 | \r |
1261 | fdt = fc + SLOT->DT[crct.CH->kcode];\r |
1262 | if (fdt < 0) fdt += fn_table[0x7ff*2] >> 2;\r |
1263 | \r |
1264 | return (fdt * SLOT->mul) >> 1;\r |
1265 | } else\r |
1266 | return SLOT->Incr;\r |
1267 | }\r |
1268 | \r |
f7741cac |
1269 | static int chan_render(s32 *buffer, int length, int c, UINT32 flags) // flags: stereo, ?, disabled, ?, pan_r, pan_l\r |
cc68a136 |
1270 | {\r |
b542be46 |
1271 | crct.CH = &ym2612.CH[c];\r |
1272 | crct.mem = crct.CH->mem_value; /* one sample delay memory */\r |
1273 | crct.lfo_cnt = ym2612.OPN.lfo_cnt;\r |
cc68a136 |
1274 | \r |
1dbda5f8 |
1275 | flags &= 0x37;\r |
cc68a136 |
1276 | \r |
b542be46 |
1277 | if (crct.lfo_inc) {\r |
cc68a136 |
1278 | flags |= 8;\r |
ccc39358 |
1279 | flags |= crct.lfo_init_sft16;\r |
b542be46 |
1280 | flags |= crct.CH->AMmasks << 8;\r |
1281 | if (crct.CH->ams == 8) // no ams\r |
1282 | flags &= ~0xf00;\r |
1283 | else flags |= (crct.CH->ams&3)<<6;\r |
cc68a136 |
1284 | }\r |
b542be46 |
1285 | flags |= (crct.CH->FB&0xf)<<12; /* feedback shift */\r |
1286 | crct.pack = flags;\r |
cc68a136 |
1287 | \r |
b542be46 |
1288 | crct.eg_cnt = ym2612.OPN.eg_cnt; /* envelope generator counter */\r |
1289 | crct.eg_timer = ym2612.OPN.eg_timer;\r |
cc68a136 |
1290 | \r |
1291 | /* precalculate phase modulation incr */\r |
b542be46 |
1292 | crct.phase1 = crct.CH->SLOT[SLOT1].phase;\r |
1293 | crct.phase2 = crct.CH->SLOT[SLOT2].phase;\r |
1294 | crct.phase3 = crct.CH->SLOT[SLOT3].phase;\r |
1295 | crct.phase4 = crct.CH->SLOT[SLOT4].phase;\r |
cc68a136 |
1296 | \r |
b542be46 |
1297 | crct.op1_out = crct.CH->op1_out;\r |
1298 | crct.algo = crct.CH->ALGO & 7;\r |
d127b3f3 |
1299 | crct.algo |= crct.CH->upd_cnt << 4;\r |
23cd73bc |
1300 | if (ym2612.OPN.ST.flags & ST_DAC)\r |
1301 | crct.algo |= 0x80;\r |
cc68a136 |
1302 | \r |
8ac9ab7f |
1303 | if(crct.CH->pms && (ym2612.OPN.ST.mode & 0xC0) && c == 2) {\r |
1304 | /* 3 slot mode */\r |
1305 | crct.incr1 = update_lfo_phase(&crct.CH->SLOT[SLOT1], ym2612.OPN.SL3.block_fnum[1]);\r |
1306 | crct.incr2 = update_lfo_phase(&crct.CH->SLOT[SLOT2], ym2612.OPN.SL3.block_fnum[2]);\r |
1307 | crct.incr3 = update_lfo_phase(&crct.CH->SLOT[SLOT3], ym2612.OPN.SL3.block_fnum[0]);\r |
1308 | crct.incr4 = update_lfo_phase(&crct.CH->SLOT[SLOT4], crct.CH->block_fnum);\r |
1309 | }\r |
1310 | else if(crct.CH->pms)\r |
cc68a136 |
1311 | {\r |
8ac9ab7f |
1312 | crct.incr1 = update_lfo_phase(&crct.CH->SLOT[SLOT1], crct.CH->block_fnum);\r |
1313 | crct.incr2 = update_lfo_phase(&crct.CH->SLOT[SLOT2], crct.CH->block_fnum);\r |
1314 | crct.incr3 = update_lfo_phase(&crct.CH->SLOT[SLOT3], crct.CH->block_fnum);\r |
1315 | crct.incr4 = update_lfo_phase(&crct.CH->SLOT[SLOT4], crct.CH->block_fnum);\r |
cc68a136 |
1316 | }\r |
1317 | else /* no LFO phase modulation */\r |
1318 | {\r |
b542be46 |
1319 | crct.incr1 = crct.CH->SLOT[SLOT1].Incr;\r |
1320 | crct.incr2 = crct.CH->SLOT[SLOT2].Incr;\r |
1321 | crct.incr3 = crct.CH->SLOT[SLOT3].Incr;\r |
1322 | crct.incr4 = crct.CH->SLOT[SLOT4].Incr;\r |
cc68a136 |
1323 | }\r |
1324 | \r |
b542be46 |
1325 | chan_render_loop(&crct, buffer, length);\r |
cc68a136 |
1326 | \r |
b542be46 |
1327 | crct.CH->op1_out = crct.op1_out;\r |
1328 | crct.CH->mem_value = crct.mem;\r |
1329 | if (crct.CH->SLOT[SLOT1].state | crct.CH->SLOT[SLOT2].state | crct.CH->SLOT[SLOT3].state | crct.CH->SLOT[SLOT4].state)\r |
1330 | {\r |
1331 | crct.CH->SLOT[SLOT1].phase = crct.phase1;\r |
1332 | crct.CH->SLOT[SLOT2].phase = crct.phase2;\r |
1333 | crct.CH->SLOT[SLOT3].phase = crct.phase3;\r |
1334 | crct.CH->SLOT[SLOT4].phase = crct.phase4;\r |
cc68a136 |
1335 | }\r |
b542be46 |
1336 | else\r |
1337 | ym2612.slot_mask &= ~(0xf << (c*4));\r |
d127b3f3 |
1338 | crct.CH->upd_cnt = (crct.algo >> 4) & 0x7;\r |
cc68a136 |
1339 | \r |
b542be46 |
1340 | return (crct.algo & 8) >> 3; // had output\r |
cc68a136 |
1341 | }\r |
1342 | \r |
1343 | /* update phase increment and envelope generator */\r |
12d506ba |
1344 | static INLINE void refresh_fc_eg_slot(FM_SLOT *SLOT, int fc, int kc)\r |
cc68a136 |
1345 | {\r |
eaa9417a |
1346 | int ksr, fdt;\r |
cc68a136 |
1347 | \r |
1348 | /* (frequency) phase increment counter */\r |
eaa9417a |
1349 | fdt = fc+SLOT->DT[kc];\r |
1350 | /* detect overflow */\r |
1351 | // if (fdt < 0) fdt += fn_table[0x7ff*2] >> (7-blk-1);\r |
1352 | if (fdt < 0) fdt += fn_table[0x7ff*2] >> 2;\r |
1353 | SLOT->Incr = fdt*SLOT->mul >> 1;\r |
cc68a136 |
1354 | \r |
1355 | ksr = kc >> SLOT->KSR;\r |
1356 | if( SLOT->ksr != ksr )\r |
1357 | {\r |
1358 | int eg_sh, eg_sel;\r |
1359 | SLOT->ksr = ksr;\r |
b9bc876c |
1360 | SLOT->ar_ksr = SLOT->ar + ksr;\r |
cc68a136 |
1361 | \r |
1362 | /* calculate envelope generator rates */\r |
b9bc876c |
1363 | if ((SLOT->ar_ksr) < 32+62)\r |
cc68a136 |
1364 | {\r |
b9bc876c |
1365 | eg_sh = eg_rate_shift [SLOT->ar_ksr];\r |
1366 | eg_sel = eg_rate_select[SLOT->ar_ksr];\r |
cc68a136 |
1367 | }\r |
1368 | else\r |
1369 | {\r |
1370 | eg_sh = 0;\r |
9090dc0f |
1371 | eg_sel = 18;\r |
cc68a136 |
1372 | }\r |
1373 | \r |
1374 | SLOT->eg_pack_ar = eg_inc_pack[eg_sel] | (eg_sh<<24);\r |
1375 | \r |
d2721b08 |
1376 | eg_sh = eg_rate_shift [SLOT->d1r + ksr];\r |
1377 | eg_sel = eg_rate_select[SLOT->d1r + ksr];\r |
cc68a136 |
1378 | \r |
1379 | SLOT->eg_pack_d1r = eg_inc_pack[eg_sel] | (eg_sh<<24);\r |
1380 | \r |
d2721b08 |
1381 | eg_sh = eg_rate_shift [SLOT->d2r + ksr];\r |
1382 | eg_sel = eg_rate_select[SLOT->d2r + ksr];\r |
cc68a136 |
1383 | \r |
1384 | SLOT->eg_pack_d2r = eg_inc_pack[eg_sel] | (eg_sh<<24);\r |
1385 | \r |
d2721b08 |
1386 | eg_sh = eg_rate_shift [SLOT->rr + ksr];\r |
1387 | eg_sel = eg_rate_select[SLOT->rr + ksr];\r |
cc68a136 |
1388 | \r |
1389 | SLOT->eg_pack_rr = eg_inc_pack[eg_sel] | (eg_sh<<24);\r |
1390 | }\r |
1391 | }\r |
1392 | \r |
1393 | /* update phase increment counters */\r |
12d506ba |
1394 | static INLINE void refresh_fc_eg_chan(FM_CH *CH)\r |
cc68a136 |
1395 | {\r |
1396 | if( CH->SLOT[SLOT1].Incr==-1){\r |
1397 | int fc = CH->fc;\r |
1398 | int kc = CH->kcode;\r |
1399 | refresh_fc_eg_slot(&CH->SLOT[SLOT1] , fc , kc );\r |
1400 | refresh_fc_eg_slot(&CH->SLOT[SLOT2] , fc , kc );\r |
1401 | refresh_fc_eg_slot(&CH->SLOT[SLOT3] , fc , kc );\r |
1402 | refresh_fc_eg_slot(&CH->SLOT[SLOT4] , fc , kc );\r |
1403 | }\r |
1404 | }\r |
1405 | \r |
12d506ba |
1406 | static INLINE void refresh_fc_eg_chan_sl3(void)\r |
eaa9417a |
1407 | {\r |
1408 | if( ym2612.CH[2].SLOT[SLOT1].Incr==-1)\r |
1409 | {\r |
1410 | refresh_fc_eg_slot(&ym2612.CH[2].SLOT[SLOT1], ym2612.OPN.SL3.fc[1], ym2612.OPN.SL3.kcode[1] );\r |
1411 | refresh_fc_eg_slot(&ym2612.CH[2].SLOT[SLOT2], ym2612.OPN.SL3.fc[2], ym2612.OPN.SL3.kcode[2] );\r |
1412 | refresh_fc_eg_slot(&ym2612.CH[2].SLOT[SLOT3], ym2612.OPN.SL3.fc[0], ym2612.OPN.SL3.kcode[0] );\r |
1413 | refresh_fc_eg_slot(&ym2612.CH[2].SLOT[SLOT4], ym2612.CH[2].fc , ym2612.CH[2].kcode );\r |
1414 | }\r |
1415 | }\r |
1416 | \r |
cc68a136 |
1417 | /* initialize time tables */\r |
1418 | static void init_timetables(const UINT8 *dttable)\r |
1419 | {\r |
1420 | int i,d;\r |
1421 | double rate;\r |
1422 | \r |
1423 | /* DeTune table */\r |
1424 | for (d = 0;d <= 3;d++){\r |
1425 | for (i = 0;i <= 31;i++){\r |
9090dc0f |
1426 | rate = ((double)dttable[d*32 + i]) * ym2612.OPN.ST.freqbase * (1<<(FREQ_SH-10));\r |
cc68a136 |
1427 | ym2612.OPN.ST.dt_tab[d][i] = (INT32) rate;\r |
1428 | ym2612.OPN.ST.dt_tab[d+4][i] = -ym2612.OPN.ST.dt_tab[d][i];\r |
1429 | }\r |
1430 | }\r |
1431 | }\r |
1432 | \r |
1433 | \r |
b542be46 |
1434 | static void reset_channels(FM_CH *CH)\r |
cc68a136 |
1435 | {\r |
1436 | int c,s;\r |
1437 | \r |
1438 | ym2612.OPN.ST.mode = 0; /* normal mode */\r |
1439 | ym2612.OPN.ST.TA = 0;\r |
1440 | ym2612.OPN.ST.TAC = 0;\r |
1441 | ym2612.OPN.ST.TB = 0;\r |
1442 | ym2612.OPN.ST.TBC = 0;\r |
1443 | \r |
b542be46 |
1444 | for( c = 0 ; c < 6 ; c++ )\r |
cc68a136 |
1445 | {\r |
1446 | CH[c].fc = 0;\r |
1447 | for(s = 0 ; s < 4 ; s++ )\r |
1448 | {\r |
8ac9ab7f |
1449 | CH[c].SLOT[s].Incr = -1;\r |
1450 | CH[c].SLOT[s].key = 0;\r |
1451 | CH[c].SLOT[s].phase = 0;\r |
a20300bf |
1452 | CH[c].SLOT[s].ar = CH[c].SLOT[s].ksr = 0;\r |
1453 | CH[c].SLOT[s].ar_ksr = 0;\r |
8ac9ab7f |
1454 | CH[c].SLOT[s].ssg = CH[c].SLOT[s].ssgn = 0;\r |
cc68a136 |
1455 | CH[c].SLOT[s].state= EG_OFF;\r |
1456 | CH[c].SLOT[s].volume = MAX_ATT_INDEX;\r |
8ac9ab7f |
1457 | CH[c].SLOT[s].vol_out = MAX_ATT_INDEX;\r |
cc68a136 |
1458 | }\r |
db49317b |
1459 | CH[c].mem_value = CH[c].op1_out = 0;\r |
cc68a136 |
1460 | }\r |
b542be46 |
1461 | ym2612.slot_mask = 0;\r |
1dbda5f8 |
1462 | ym2612.ssg_mask = 0;\r |
cc68a136 |
1463 | }\r |
1464 | \r |
1465 | /* initialize generic tables */\r |
1466 | static void init_tables(void)\r |
1467 | {\r |
1468 | signed int i,x,y,p;\r |
1469 | signed int n;\r |
1470 | double o,m;\r |
1471 | \r |
864ac1d6 |
1472 | if (ym_init_tab) return;\r |
1473 | ym_init_tab = 1;\r |
1474 | \r |
cc68a136 |
1475 | for (i=0; i < 256; i++)\r |
1476 | {\r |
1477 | /* non-standard sinus */\r |
1478 | m = sin( ((i*2)+1) * M_PI / SIN_LEN ); /* checked against the real chip */\r |
1479 | \r |
1480 | /* we never reach zero here due to ((i*2)+1) */\r |
1481 | \r |
1482 | if (m>0.0)\r |
1483 | o = 8*log(1.0/m)/log(2); /* convert to 'decibels' */\r |
1484 | else\r |
1485 | o = 8*log(-1.0/m)/log(2); /* convert to 'decibels' */\r |
1486 | \r |
1487 | o = o / (ENV_STEP/4);\r |
1488 | \r |
1489 | n = (int)(2.0*o);\r |
1490 | if (n&1) /* round to nearest */\r |
1491 | n = (n>>1)+1;\r |
1492 | else\r |
1493 | n = n>>1;\r |
1494 | \r |
1495 | ym_sin_tab[ i ] = n;\r |
1496 | //dprintf("FM.C: sin [%4i]= %4i", i, ym_sin_tab[i]);\r |
1497 | }\r |
1498 | \r |
1499 | //dprintf("FM.C: ENV_QUIET= %08x", ENV_QUIET );\r |
1500 | \r |
1501 | \r |
1502 | for (x=0; x < TL_RES_LEN; x++)\r |
1503 | {\r |
1504 | m = (1<<16) / pow(2, (x+1) * (ENV_STEP/4.0) / 8.0);\r |
1505 | m = floor(m);\r |
1506 | \r |
1507 | /* we never reach (1<<16) here due to the (x+1) */\r |
1508 | /* result fits within 16 bits at maximum */\r |
1509 | \r |
1510 | n = (int)m; /* 16 bits here */\r |
1511 | n >>= 4; /* 12 bits here */\r |
1512 | if (n&1) /* round to nearest */\r |
1513 | n = (n>>1)+1;\r |
1514 | else\r |
1515 | n = n>>1;\r |
1516 | /* 11 bits here (rounded) */\r |
1517 | n <<= 2; /* 13 bits here (as in real chip) */\r |
1518 | ym_tl_tab2[ x ] = n;\r |
1519 | \r |
1520 | for (i=1; i < 13; i++)\r |
1521 | {\r |
1522 | ym_tl_tab2[ x + i*TL_RES_LEN ] = n >> i;\r |
1523 | }\r |
1524 | }\r |
1525 | \r |
1526 | for (x=0; x < 256; x++)\r |
1527 | {\r |
1528 | int sin = ym_sin_tab[ x ];\r |
1529 | \r |
1530 | for (y=0; y < 2*13*TL_RES_LEN/8; y+=2)\r |
1531 | {\r |
1532 | p = (y<<2) + sin;\r |
1533 | if (p >= 13*TL_RES_LEN)\r |
1534 | ym_tl_tab[(y<<7) | x] = 0;\r |
1535 | else ym_tl_tab[(y<<7) | x] = ym_tl_tab2[p];\r |
1536 | }\r |
1537 | }\r |
1538 | \r |
1539 | \r |
1540 | /* build LFO PM modulation table */\r |
1541 | for(i = 0; i < 8; i++) /* 8 PM depths */\r |
1542 | {\r |
1543 | UINT8 fnum;\r |
1544 | for (fnum=0; fnum<128; fnum++) /* 7 bits meaningful of F-NUMBER */\r |
1545 | {\r |
1546 | UINT8 value;\r |
1547 | UINT8 step;\r |
1548 | UINT32 offset_depth = i;\r |
1549 | UINT32 offset_fnum_bit;\r |
1550 | UINT32 bit_tmp;\r |
1551 | \r |
1552 | for (step=0; step<8; step++)\r |
1553 | {\r |
1554 | value = 0;\r |
1555 | for (bit_tmp=0; bit_tmp<7; bit_tmp++) /* 7 bits */\r |
1556 | {\r |
1557 | if (fnum & (1<<bit_tmp)) /* only if bit "bit_tmp" is set */\r |
1558 | {\r |
1559 | offset_fnum_bit = bit_tmp * 8;\r |
1560 | value += lfo_pm_output[offset_fnum_bit + offset_depth][step];\r |
1561 | }\r |
1562 | }\r |
1563 | lfo_pm_table[(fnum*32*8) + (i*32) + step + 0] = value;\r |
1564 | lfo_pm_table[(fnum*32*8) + (i*32) +(step^7)+ 8] = value;\r |
1565 | lfo_pm_table[(fnum*32*8) + (i*32) + step +16] = -value;\r |
1566 | lfo_pm_table[(fnum*32*8) + (i*32) +(step^7)+24] = -value;\r |
1567 | }\r |
1568 | }\r |
1569 | }\r |
1570 | }\r |
1571 | \r |
1572 | \r |
1573 | /* CSM Key Controll */\r |
b542be46 |
1574 | #if 0\r |
cc68a136 |
1575 | INLINE void CSMKeyControll(FM_CH *CH)\r |
1576 | {\r |
1577 | /* this is wrong, atm */\r |
1578 | \r |
1579 | /* all key on */\r |
1580 | FM_KEYON(CH,SLOT1);\r |
1581 | FM_KEYON(CH,SLOT2);\r |
1582 | FM_KEYON(CH,SLOT3);\r |
1583 | FM_KEYON(CH,SLOT4);\r |
1584 | }\r |
b542be46 |
1585 | #endif\r |
cc68a136 |
1586 | \r |
1587 | \r |
1588 | /* prescaler set (and make time tables) */\r |
1589 | static void OPNSetPres(int pres)\r |
1590 | {\r |
1591 | int i;\r |
1592 | \r |
1593 | /* frequency base */\r |
d127b3f3 |
1594 | double freqbase = (ym2612.OPN.ST.rate) ? ((double)ym2612.OPN.ST.clock / ym2612.OPN.ST.rate) / pres : 0;\r |
cc68a136 |
1595 | \r |
d127b3f3 |
1596 | ym2612.OPN.eg_timer_add = (1<<EG_SH) * freqbase;\r |
882f697a |
1597 | ym2612.OPN.ST.freqbase = freqbase;\r |
cc68a136 |
1598 | \r |
cc68a136 |
1599 | /* make time tables */\r |
1600 | init_timetables( dt_tab );\r |
1601 | \r |
1602 | /* there are 2048 FNUMs that can be generated using FNUM/BLK registers\r |
1603 | but LFO works with one more bit of a precision so we really need 4096 elements */\r |
1604 | /* calculate fnumber -> increment counter table */\r |
1605 | for(i = 0; i < 4096; i++)\r |
1606 | {\r |
1607 | /* freq table for octave 7 */\r |
1608 | /* OPN phase increment counter = 20bit */\r |
1609 | 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 |
1610 | }\r |
1611 | \r |
1612 | /* LFO freq. table */\r |
1613 | for(i = 0; i < 8; i++)\r |
1614 | {\r |
1615 | /* Amplitude modulation: 64 output levels (triangle waveform); 1 level lasts for one of "lfo_samples_per_step" samples */\r |
1616 | /* Phase modulation: one entry from lfo_pm_output lasts for one of 4 * "lfo_samples_per_step" samples */\r |
1617 | ym2612.OPN.lfo_freq[i] = (1.0 / lfo_samples_per_step[i]) * (1<<LFO_SH) * ym2612.OPN.ST.freqbase;\r |
1618 | }\r |
1619 | }\r |
1620 | \r |
1621 | \r |
1622 | /* write a OPN register (0x30-0xff) */\r |
1623 | static int OPNWriteReg(int r, int v)\r |
1624 | {\r |
1625 | int ret = 1;\r |
1626 | FM_CH *CH;\r |
1627 | FM_SLOT *SLOT;\r |
1628 | \r |
1629 | UINT8 c = OPN_CHAN(r);\r |
1630 | \r |
1631 | if (c == 3) return 0; /* 0xX3,0xX7,0xXB,0xXF */\r |
1632 | \r |
1633 | if (r >= 0x100) c+=3;\r |
1634 | \r |
1635 | CH = &ym2612.CH[c];\r |
1636 | \r |
1637 | SLOT = &(CH->SLOT[OPN_SLOT(r)]);\r |
1638 | \r |
1639 | switch( r & 0xf0 ) {\r |
1640 | case 0x30: /* DET , MUL */\r |
1641 | set_det_mul(CH,SLOT,v);\r |
1642 | break;\r |
1643 | \r |
1644 | case 0x40: /* TL */\r |
1645 | set_tl(SLOT,v);\r |
1646 | break;\r |
1647 | \r |
1648 | case 0x50: /* KS, AR */\r |
1649 | set_ar_ksr(CH,SLOT,v);\r |
1650 | break;\r |
1651 | \r |
db49317b |
1652 | case 0x60: /* bit7 = AM ENABLE, DR | depends on ksr */\r |
cc68a136 |
1653 | set_dr(SLOT,v);\r |
1654 | if(v&0x80) CH->AMmasks |= 1<<OPN_SLOT(r);\r |
1655 | else CH->AMmasks &= ~(1<<OPN_SLOT(r));\r |
1656 | break;\r |
1657 | \r |
db49317b |
1658 | case 0x70: /* SR | depends on ksr */\r |
cc68a136 |
1659 | set_sr(SLOT,v);\r |
1660 | break;\r |
1661 | \r |
db49317b |
1662 | case 0x80: /* SL, RR | depends on ksr */\r |
cc68a136 |
1663 | set_sl_rr(SLOT,v);\r |
1664 | break;\r |
1665 | \r |
1666 | case 0x90: /* SSG-EG */\r |
8ac9ab7f |
1667 | SLOT->ssg = v&0x0f;\r |
1668 | SLOT->ssg ^= SLOT->ssgn;\r |
1dbda5f8 |
1669 | if (v&0x08) ym2612.ssg_mask |= 1<<(OPN_SLOT(r) + c*4);\r |
1670 | else ym2612.ssg_mask &= ~(1<<(OPN_SLOT(r) + c*4));\r |
f3876af7 |
1671 | if (SLOT->state > EG_REL)\r |
1672 | recalc_volout(SLOT);\r |
cc68a136 |
1673 | break;\r |
1674 | \r |
1675 | case 0xa0:\r |
1676 | switch( OPN_SLOT(r) ){\r |
db49317b |
1677 | case 0: /* 0xa0-0xa2 : FNUM1 | depends on fn_h (below) */\r |
cc68a136 |
1678 | {\r |
68e06234 |
1679 | UINT32 fn = ((UINT32)(ym2612.OPN.ST.fn_h & 7) << 8) | v;\r |
1680 | UINT8 blk = ym2612.OPN.ST.fn_h >> 3;\r |
cc68a136 |
1681 | /* keyscale code */\r |
1682 | CH->kcode = (blk<<2) | opn_fktable[fn >> 7];\r |
1683 | /* phase increment counter */\r |
1684 | CH->fc = fn_table[fn*2]>>(7-blk);\r |
1685 | \r |
1686 | /* store fnum in clear form for LFO PM calculations */\r |
1687 | CH->block_fnum = (blk<<11) | fn;\r |
1688 | \r |
1689 | CH->SLOT[SLOT1].Incr=-1;\r |
1690 | }\r |
1691 | break;\r |
1692 | case 1: /* 0xa4-0xa6 : FNUM2,BLK */\r |
68e06234 |
1693 | ym2612.OPN.ST.fn_h = v & 0x3f;\r |
cc68a136 |
1694 | ret = 0;\r |
1695 | break;\r |
1696 | case 2: /* 0xa8-0xaa : 3CH FNUM1 */\r |
1697 | if(r < 0x100)\r |
1698 | {\r |
1699 | UINT32 fn = (((UINT32)(ym2612.OPN.SL3.fn_h&7))<<8) + v;\r |
1700 | UINT8 blk = ym2612.OPN.SL3.fn_h>>3;\r |
1701 | /* keyscale code */\r |
1702 | ym2612.OPN.SL3.kcode[c]= (blk<<2) | opn_fktable[fn >> 7];\r |
1703 | /* phase increment counter */\r |
1704 | ym2612.OPN.SL3.fc[c] = fn_table[fn*2]>>(7-blk);\r |
db49317b |
1705 | ym2612.OPN.SL3.block_fnum[c] = (blk<<11) | fn;\r |
cc68a136 |
1706 | ym2612.CH[2].SLOT[SLOT1].Incr=-1;\r |
1707 | }\r |
1708 | break;\r |
1709 | case 3: /* 0xac-0xae : 3CH FNUM2,BLK */\r |
1710 | if(r < 0x100)\r |
1711 | ym2612.OPN.SL3.fn_h = v&0x3f;\r |
1712 | ret = 0;\r |
1713 | break;\r |
1714 | default:\r |
1715 | ret = 0;\r |
1716 | break;\r |
1717 | }\r |
1718 | break;\r |
1719 | \r |
1720 | case 0xb0:\r |
1721 | switch( OPN_SLOT(r) ){\r |
1722 | case 0: /* 0xb0-0xb2 : FB,ALGO */\r |
1723 | {\r |
1724 | int feedback = (v>>3)&7;\r |
1725 | CH->ALGO = v&7;\r |
1726 | CH->FB = feedback ? feedback+6 : 0;\r |
1727 | }\r |
1728 | break;\r |
1729 | case 1: /* 0xb4-0xb6 : L , R , AMS , PMS (YM2612/YM2610B/YM2610/YM2608) */\r |
1730 | {\r |
1731 | int panshift = c<<1;\r |
1732 | \r |
1733 | /* b0-2 PMS */\r |
1734 | CH->pms = (v & 7) * 32; /* CH->pms = PM depth * 32 (index in lfo_pm_table) */\r |
1735 | \r |
1736 | /* b4-5 AMS */\r |
1737 | CH->ams = lfo_ams_depth_shift[(v>>4) & 3];\r |
1738 | \r |
1739 | /* PAN : b7 = L, b6 = R */\r |
1740 | ym2612.OPN.pan &= ~(3<<panshift);\r |
1741 | ym2612.OPN.pan |= ((v & 0xc0) >> 6) << panshift; // ..LRLR\r |
1742 | }\r |
1743 | break;\r |
1744 | default:\r |
1745 | ret = 0;\r |
1746 | break;\r |
1747 | }\r |
1748 | break;\r |
1749 | default:\r |
1750 | ret = 0;\r |
1751 | break;\r |
1752 | }\r |
1753 | \r |
1754 | return ret;\r |
1755 | }\r |
1756 | \r |
1757 | \r |
1758 | /*******************************************************************************/\r |
1759 | /* YM2612 local section */\r |
1760 | /*******************************************************************************/\r |
1761 | \r |
cc68a136 |
1762 | /* Generate samples for YM2612 */\r |
f7741cac |
1763 | int YM2612UpdateOne_(s32 *buffer, int length, int stereo, int is_buf_empty)\r |
cc68a136 |
1764 | {\r |
1765 | int pan;\r |
85f8e929 |
1766 | int active_chs = 0;\r |
1dbda5f8 |
1767 | int flags = stereo ? 1:0;\r |
4f265db7 |
1768 | \r |
1769 | // if !is_buf_empty, it means it has valid samples to mix with, else it may contain trash\r |
1770 | if (is_buf_empty) memset32(buffer, 0, length<<stereo);\r |
cc68a136 |
1771 | \r |
b542be46 |
1772 | /*\r |
1773 | {\r |
1774 | int c, s;\r |
1775 | ppp();\r |
1776 | for (c = 0; c < 6; c++) {\r |
1777 | int slr = 0, slm;\r |
1778 | printf("%i: ", c);\r |
1779 | for (s = 0; s < 4; s++) {\r |
1780 | if (ym2612.CH[c].SLOT[s].state != EG_OFF) slr = 1;\r |
1781 | printf(" %i", ym2612.CH[c].SLOT[s].state != EG_OFF);\r |
1782 | }\r |
1783 | slm = (ym2612.slot_mask&(0xf<<(c*4))) ? 1 : 0;\r |
1784 | printf(" | %i", slm);\r |
1785 | printf(" | %i\n", ym2612.CH[c].SLOT[SLOT1].Incr==-1);\r |
1786 | if (slr != slm) exit(1);\r |
1787 | }\r |
1788 | }\r |
1789 | */\r |
cc68a136 |
1790 | /* refresh PG and EG */\r |
1791 | refresh_fc_eg_chan( &ym2612.CH[0] );\r |
1792 | refresh_fc_eg_chan( &ym2612.CH[1] );\r |
1793 | if( (ym2612.OPN.ST.mode & 0xc0) )\r |
cc68a136 |
1794 | /* 3SLOT MODE */\r |
eaa9417a |
1795 | refresh_fc_eg_chan_sl3();\r |
1796 | else\r |
1797 | refresh_fc_eg_chan( &ym2612.CH[2] );\r |
cc68a136 |
1798 | refresh_fc_eg_chan( &ym2612.CH[3] );\r |
1799 | refresh_fc_eg_chan( &ym2612.CH[4] );\r |
1800 | refresh_fc_eg_chan( &ym2612.CH[5] );\r |
1801 | \r |
1802 | pan = ym2612.OPN.pan;\r |
cc68a136 |
1803 | \r |
4f265db7 |
1804 | /* mix to 32bit dest */\r |
1dbda5f8 |
1805 | // flags: stereo, ssg_enabled, disabled, _, pan_r, pan_l\r |
d2721b08 |
1806 | chan_render_prep();\r |
1dbda5f8 |
1807 | #define BIT_IF(v,b,c) { v &= ~(1<<(b)); if (c) v |= 1<<(b); }\r |
324bd685 |
1808 | BIT_IF(flags, 1, (ym2612.ssg_mask & 0x00000f) && (ym2612.OPN.ST.flags & 1));\r |
1dbda5f8 |
1809 | if (ym2612.slot_mask & 0x00000f) active_chs |= chan_render(buffer, length, 0, flags|((pan&0x003)<<4)) << 0;\r |
324bd685 |
1810 | BIT_IF(flags, 1, (ym2612.ssg_mask & 0x0000f0) && (ym2612.OPN.ST.flags & 1));\r |
1dbda5f8 |
1811 | if (ym2612.slot_mask & 0x0000f0) active_chs |= chan_render(buffer, length, 1, flags|((pan&0x00c)<<2)) << 1;\r |
324bd685 |
1812 | BIT_IF(flags, 1, (ym2612.ssg_mask & 0x000f00) && (ym2612.OPN.ST.flags & 1));\r |
1dbda5f8 |
1813 | if (ym2612.slot_mask & 0x000f00) active_chs |= chan_render(buffer, length, 2, flags|((pan&0x030) )) << 2;\r |
324bd685 |
1814 | BIT_IF(flags, 1, (ym2612.ssg_mask & 0x00f000) && (ym2612.OPN.ST.flags & 1));\r |
1dbda5f8 |
1815 | if (ym2612.slot_mask & 0x00f000) active_chs |= chan_render(buffer, length, 3, flags|((pan&0x0c0)>>2)) << 3;\r |
324bd685 |
1816 | BIT_IF(flags, 1, (ym2612.ssg_mask & 0x0f0000) && (ym2612.OPN.ST.flags & 1));\r |
1dbda5f8 |
1817 | if (ym2612.slot_mask & 0x0f0000) active_chs |= chan_render(buffer, length, 4, flags|((pan&0x300)>>4)) << 4;\r |
ccc39358 |
1818 | g_lfo_ampm = crct.pack >> 16; // need_save; now because ch5 might skip updating it\r |
324bd685 |
1819 | BIT_IF(flags, 1, (ym2612.ssg_mask & 0xf00000) && (ym2612.OPN.ST.flags & 1));\r |
1dbda5f8 |
1820 | if (ym2612.slot_mask & 0xf00000) active_chs |= chan_render(buffer, length, 5, flags|((pan&0xc00)>>6)|(!!ym2612.dacen<<2)) << 5;\r |
1821 | #undef BIT_IF\r |
8794ba5c |
1822 | chan_render_finish(buffer, length, active_chs);\r |
85f8e929 |
1823 | \r |
1824 | return active_chs; // 1 if buffer updated\r |
cc68a136 |
1825 | }\r |
1826 | \r |
1827 | \r |
1828 | /* initialize YM2612 emulator */\r |
8794ba5c |
1829 | void YM2612Init_(int clock, int rate, int flags)\r |
cc68a136 |
1830 | {\r |
5f8c85be |
1831 | memset(&ym2612, 0, sizeof(ym2612));\r |
cc68a136 |
1832 | init_tables();\r |
1833 | \r |
1834 | ym2612.OPN.ST.clock = clock;\r |
1835 | ym2612.OPN.ST.rate = rate;\r |
8794ba5c |
1836 | ym2612.OPN.ST.flags = flags;\r |
cc68a136 |
1837 | \r |
be297089 |
1838 | OPNSetPres( 6*24 );\r |
1839 | \r |
cc68a136 |
1840 | /* Extend handler */\r |
1841 | YM2612ResetChip_();\r |
1842 | }\r |
1843 | \r |
1844 | \r |
1845 | /* reset */\r |
1846 | void YM2612ResetChip_(void)\r |
1847 | {\r |
1848 | int i;\r |
1849 | \r |
5f8c85be |
1850 | memset(ym2612.REGS, 0, sizeof(ym2612.REGS));\r |
1851 | \r |
cc68a136 |
1852 | set_timers( 0x30 ); /* mode 0 , timer reset */\r |
5f8c85be |
1853 | ym2612.REGS[0x27] = 0x30;\r |
cc68a136 |
1854 | \r |
1855 | ym2612.OPN.eg_timer = 0;\r |
1856 | ym2612.OPN.eg_cnt = 0;\r |
9090dc0f |
1857 | ym2612.OPN.lfo_inc = 0;\r |
1858 | ym2612.OPN.lfo_cnt = 0;\r |
1859 | g_lfo_ampm = 126 << 8;\r |
cc68a136 |
1860 | ym2612.OPN.ST.status = 0;\r |
1861 | \r |
b542be46 |
1862 | reset_channels( &ym2612.CH[0] );\r |
cc68a136 |
1863 | for(i = 0xb6 ; i >= 0xb4 ; i-- )\r |
1864 | {\r |
1865 | OPNWriteReg(i ,0xc0);\r |
1866 | OPNWriteReg(i|0x100,0xc0);\r |
5f8c85be |
1867 | ym2612.REGS[i ] = 0xc0;\r |
1868 | ym2612.REGS[i|0x100] = 0xc0;\r |
cc68a136 |
1869 | }\r |
1870 | for(i = 0xb2 ; i >= 0x30 ; i-- )\r |
1871 | {\r |
1872 | OPNWriteReg(i ,0);\r |
1873 | OPNWriteReg(i|0x100,0);\r |
1874 | }\r |
1875 | for(i = 0x26 ; i >= 0x20 ; i-- ) OPNWriteReg(i,0);\r |
1876 | /* DAC mode clear */\r |
1877 | ym2612.dacen = 0;\r |
4f2cdbf5 |
1878 | ym2612.dacout = 0;\r |
5f8c85be |
1879 | ym2612.addr_A1 = 0;\r |
cc68a136 |
1880 | }\r |
1881 | \r |
1882 | \r |
1883 | /* YM2612 write */\r |
1884 | /* a = address */\r |
1885 | /* v = value */\r |
1886 | /* returns 1 if sample affecting state changed */\r |
1887 | int YM2612Write_(unsigned int a, unsigned int v)\r |
1888 | {\r |
1889 | int addr, ret=1;\r |
1890 | \r |
1891 | v &= 0xff; /* adjust to 8 bit bus */\r |
1892 | \r |
151df6ad |
1893 | switch( a & 3 ){\r |
cc68a136 |
1894 | case 0: /* address port 0 */\r |
151df6ad |
1895 | case 2: /* address port 1 */\r |
225260ba |
1896 | /* reminder: this is not used, see ym2612_write_local() */\r |
cc68a136 |
1897 | ym2612.OPN.ST.address = v;\r |
151df6ad |
1898 | ym2612.addr_A1 = (a & 2) >> 1;\r |
1899 | ret = 0;\r |
cc68a136 |
1900 | break;\r |
1901 | \r |
151df6ad |
1902 | case 1:\r |
1903 | case 3: /* data port */\r |
1904 | addr = ym2612.OPN.ST.address | ((int)ym2612.addr_A1 << 8);\r |
cc68a136 |
1905 | \r |
151df6ad |
1906 | switch( addr & 0x1f0 )\r |
cc68a136 |
1907 | {\r |
1908 | case 0x20: /* 0x20-0x2f Mode */\r |
1909 | switch( addr )\r |
1910 | {\r |
1911 | case 0x22: /* LFO FREQ (YM2608/YM2610/YM2610B/YM2612) */\r |
1912 | if (v&0x08) /* LFO enabled ? */\r |
1913 | {\r |
1914 | ym2612.OPN.lfo_inc = ym2612.OPN.lfo_freq[v&7];\r |
1915 | }\r |
1916 | else\r |
1917 | {\r |
1918 | ym2612.OPN.lfo_inc = 0;\r |
151df6ad |
1919 | ym2612.OPN.lfo_cnt = 0;\r |
9090dc0f |
1920 | g_lfo_ampm = 126 << 8;\r |
cc68a136 |
1921 | }\r |
1922 | break;\r |
4b9c5888 |
1923 | #if 0 // handled elsewhere\r |
cc68a136 |
1924 | case 0x24: { // timer A High 8\r |
1925 | int TAnew = (ym2612.OPN.ST.TA & 0x03)|(((int)v)<<2);\r |
1926 | if(ym2612.OPN.ST.TA != TAnew) {\r |
1927 | // we should reset ticker only if new value is written. Outrun requires this.\r |
1928 | ym2612.OPN.ST.TA = TAnew;\r |
1929 | ym2612.OPN.ST.TAC = (1024-TAnew)*18;\r |
1930 | ym2612.OPN.ST.TAT = 0;\r |
1931 | }\r |
1932 | }\r |
1933 | ret=0;\r |
1934 | break;\r |
1935 | case 0x25: { // timer A Low 2\r |
1936 | int TAnew = (ym2612.OPN.ST.TA & 0x3fc)|(v&3);\r |
1937 | if(ym2612.OPN.ST.TA != TAnew) {\r |
1938 | ym2612.OPN.ST.TA = TAnew;\r |
1939 | ym2612.OPN.ST.TAC = (1024-TAnew)*18;\r |
1940 | ym2612.OPN.ST.TAT = 0;\r |
1941 | }\r |
1942 | }\r |
1943 | ret=0;\r |
1944 | break;\r |
1945 | case 0x26: // timer B\r |
1946 | if(ym2612.OPN.ST.TB != v) {\r |
1947 | ym2612.OPN.ST.TB = v;\r |
1948 | ym2612.OPN.ST.TBC = (256-v)<<4;\r |
1949 | ym2612.OPN.ST.TBC *= 18;\r |
1950 | ym2612.OPN.ST.TBT = 0;\r |
1951 | }\r |
1952 | ret=0;\r |
1953 | break;\r |
e4fb433c |
1954 | #endif\r |
cc68a136 |
1955 | case 0x27: /* mode, timer control */\r |
1956 | set_timers( v );\r |
1957 | ret=0;\r |
1958 | break;\r |
1959 | case 0x28: /* key on / off */\r |
1960 | {\r |
1961 | UINT8 c;\r |
cc68a136 |
1962 | \r |
1963 | c = v & 0x03;\r |
1964 | if( c == 3 ) { ret=0; break; }\r |
1965 | if( v&0x04 ) c+=3;\r |
b542be46 |
1966 | if(v&0x10) FM_KEYON(c,SLOT1); else FM_KEYOFF(c,SLOT1);\r |
1967 | if(v&0x20) FM_KEYON(c,SLOT2); else FM_KEYOFF(c,SLOT2);\r |
1968 | if(v&0x40) FM_KEYON(c,SLOT3); else FM_KEYOFF(c,SLOT3);\r |
1969 | if(v&0x80) FM_KEYON(c,SLOT4); else FM_KEYOFF(c,SLOT4);\r |
cc68a136 |
1970 | break;\r |
1971 | }\r |
1972 | case 0x2a: /* DAC data (YM2612) */\r |
1973 | ym2612.dacout = ((int)v - 0x80) << 6; /* level unknown (notaz: 8 seems to be too much) */\r |
1974 | ret=0;\r |
1975 | break;\r |
1976 | case 0x2b: /* DAC Sel (YM2612) */\r |
1977 | /* b7 = dac enable */\r |
1978 | ym2612.dacen = v & 0x80;\r |
1979 | ret=0;\r |
1980 | break;\r |
1981 | default:\r |
1982 | break;\r |
1983 | }\r |
1984 | break;\r |
1985 | default: /* 0x30-0xff OPN section */\r |
1986 | /* write register */\r |
1987 | ret = OPNWriteReg(addr,v);\r |
1988 | }\r |
1989 | break;\r |
cc68a136 |
1990 | }\r |
b6d7ac70 |
1991 | \r |
cc68a136 |
1992 | return ret;\r |
1993 | }\r |
1994 | \r |
b542be46 |
1995 | #if 0\r |
cc68a136 |
1996 | UINT8 YM2612Read_(void)\r |
1997 | {\r |
1998 | return ym2612.OPN.ST.status;\r |
1999 | }\r |
2000 | \r |
cc68a136 |
2001 | int YM2612PicoTick_(int n)\r |
2002 | {\r |
2003 | int ret = 0;\r |
2004 | \r |
2005 | // timer A\r |
2006 | if(ym2612.OPN.ST.mode & 0x01 && (ym2612.OPN.ST.TAT+=64*n) >= ym2612.OPN.ST.TAC) {\r |
2007 | ym2612.OPN.ST.TAT -= ym2612.OPN.ST.TAC;\r |
2008 | if(ym2612.OPN.ST.mode & 0x04) ym2612.OPN.ST.status |= 1;\r |
2009 | // CSM mode total level latch and auto key on\r |
2010 | if(ym2612.OPN.ST.mode & 0x80) {\r |
2011 | CSMKeyControll( &(ym2612.CH[2]) ); // Vectorman2, etc.\r |
2012 | ret = 1;\r |
2013 | }\r |
2014 | }\r |
2015 | \r |
2016 | // timer B\r |
2017 | if(ym2612.OPN.ST.mode & 0x02 && (ym2612.OPN.ST.TBT+=64*n) >= ym2612.OPN.ST.TBC) {\r |
2018 | ym2612.OPN.ST.TBT -= ym2612.OPN.ST.TBC;\r |
2019 | if(ym2612.OPN.ST.mode & 0x08) ym2612.OPN.ST.status |= 2;\r |
2020 | }\r |
2021 | \r |
2022 | return ret;\r |
2023 | }\r |
b542be46 |
2024 | #endif\r |
cc68a136 |
2025 | \r |
2026 | void YM2612PicoStateLoad_(void)\r |
2027 | {\r |
b542be46 |
2028 | reset_channels( &ym2612.CH[0] );\r |
d2721b08 |
2029 | ym2612.slot_mask = 0xffffff;\r |
2030 | }\r |
2031 | \r |
db49317b |
2032 | /* rather stupid design because I wanted to fit in unused register "space" */\r |
d2721b08 |
2033 | typedef struct\r |
2034 | {\r |
2035 | UINT32 state_phase;\r |
2036 | INT16 volume;\r |
2037 | } ym_save_addon_slot;\r |
2038 | \r |
2039 | typedef struct\r |
2040 | {\r |
2041 | UINT32 magic;\r |
2042 | UINT8 address;\r |
2043 | UINT8 status;\r |
2044 | UINT8 addr_A1;\r |
2045 | UINT8 unused;\r |
2046 | int TAT;\r |
2047 | int TBT;\r |
db49317b |
2048 | UINT32 eg_cnt; // 10\r |
d2721b08 |
2049 | UINT32 eg_timer;\r |
2050 | UINT32 lfo_cnt;\r |
2051 | UINT16 lfo_ampm;\r |
f5c022a8 |
2052 | INT16 busy_timer;\r |
db49317b |
2053 | UINT32 keyon_field; // 20\r |
2054 | UINT32 kcode_fc_sl3_3;\r |
e4fb433c |
2055 | UINT32 reserved[2];\r |
d2721b08 |
2056 | } ym_save_addon;\r |
2057 | \r |
db49317b |
2058 | typedef struct\r |
2059 | {\r |
2060 | UINT16 block_fnum[6];\r |
2061 | UINT16 block_fnum_sl3[3];\r |
e4fb433c |
2062 | UINT16 reserved[7];\r |
db49317b |
2063 | } ym_save_addon2;\r |
2064 | \r |
2065 | \r |
f5c022a8 |
2066 | void YM2612PicoStateSave2(int tat, int tbt, int busy)\r |
d2721b08 |
2067 | {\r |
2068 | ym_save_addon_slot ss;\r |
db49317b |
2069 | ym_save_addon2 sa2;\r |
d2721b08 |
2070 | ym_save_addon sa;\r |
2071 | unsigned char *ptr;\r |
2072 | int c, s;\r |
2073 | \r |
db49317b |
2074 | memset(&sa, 0, sizeof(sa));\r |
a846766f |
2075 | memset(&sa2, 0, sizeof(sa2));\r |
db49317b |
2076 | \r |
d2721b08 |
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.volume = ym2612.CH[c].SLOT[s].volume;\r |
db49317b |
2084 | if (ym2612.CH[c].SLOT[s].key)\r |
2085 | sa.keyon_field |= 1 << (c*4 + s);\r |
d2721b08 |
2086 | memcpy(ptr, &ss, 6);\r |
2087 | ptr += 6;\r |
2088 | }\r |
db49317b |
2089 | sa2.block_fnum[c] = ym2612.CH[c].block_fnum;\r |
d2721b08 |
2090 | }\r |
2091 | // chans 4,5,6\r |
2092 | ptr = &ym2612.REGS[0x1b8];\r |
2093 | for (; c < 6; c++)\r |
2094 | {\r |
2095 | for (s = 0; s < 4; s++) {\r |
2096 | ss.state_phase = (ym2612.CH[c].SLOT[s].state << 29) | (ym2612.CH[c].SLOT[s].phase >> 3);\r |
2097 | ss.volume = ym2612.CH[c].SLOT[s].volume;\r |
db49317b |
2098 | if (ym2612.CH[c].SLOT[s].key)\r |
2099 | sa.keyon_field |= 1 << (c*4 + s);\r |
d2721b08 |
2100 | memcpy(ptr, &ss, 6);\r |
2101 | ptr += 6;\r |
2102 | }\r |
db49317b |
2103 | sa2.block_fnum[c] = ym2612.CH[c].block_fnum;\r |
d2721b08 |
2104 | }\r |
db49317b |
2105 | for (c = 0; c < 3; c++)\r |
2106 | {\r |
2107 | sa2.block_fnum_sl3[c] = ym2612.OPN.SL3.block_fnum[c];\r |
2108 | }\r |
2109 | \r |
2110 | memcpy(&ym2612.REGS[0], &sa2, sizeof(sa2)); // 0x20 max\r |
2111 | \r |
d2721b08 |
2112 | // other things\r |
2113 | ptr = &ym2612.REGS[0x100];\r |
2114 | sa.magic = 0x41534d59; // 'YMSA'\r |
2115 | sa.address = ym2612.OPN.ST.address;\r |
2116 | sa.status = ym2612.OPN.ST.status;\r |
2117 | sa.addr_A1 = ym2612.addr_A1;\r |
d2721b08 |
2118 | sa.TAT = tat;\r |
2119 | sa.TBT = tbt;\r |
2120 | sa.eg_cnt = ym2612.OPN.eg_cnt;\r |
2121 | sa.eg_timer = ym2612.OPN.eg_timer;\r |
2122 | sa.lfo_cnt = ym2612.OPN.lfo_cnt;\r |
2123 | sa.lfo_ampm = g_lfo_ampm;\r |
f5c022a8 |
2124 | sa.busy_timer = busy;\r |
d2721b08 |
2125 | memcpy(ptr, &sa, sizeof(sa)); // 0x30 max\r |
2126 | }\r |
2127 | \r |
f5c022a8 |
2128 | int YM2612PicoStateLoad2(int *tat, int *tbt, int *busy)\r |
d2721b08 |
2129 | {\r |
2130 | ym_save_addon_slot ss;\r |
db49317b |
2131 | ym_save_addon2 sa2;\r |
d2721b08 |
2132 | ym_save_addon sa;\r |
2133 | unsigned char *ptr;\r |
db49317b |
2134 | UINT32 fn;\r |
2135 | UINT8 blk;\r |
d2721b08 |
2136 | int c, s;\r |
2137 | \r |
2138 | ptr = &ym2612.REGS[0x100];\r |
2139 | memcpy(&sa, ptr, sizeof(sa)); // 0x30 max\r |
2140 | if (sa.magic != 0x41534d59) return -1;\r |
2141 | \r |
db49317b |
2142 | ptr = &ym2612.REGS[0];\r |
2143 | memcpy(&sa2, ptr, sizeof(sa2));\r |
2144 | \r |
d2721b08 |
2145 | ym2612.OPN.ST.address = sa.address;\r |
2146 | ym2612.OPN.ST.status = sa.status;\r |
2147 | ym2612.addr_A1 = sa.addr_A1;\r |
2148 | ym2612.OPN.eg_cnt = sa.eg_cnt;\r |
2149 | ym2612.OPN.eg_timer = sa.eg_timer;\r |
2150 | ym2612.OPN.lfo_cnt = sa.lfo_cnt;\r |
2151 | g_lfo_ampm = sa.lfo_ampm;\r |
2152 | if (tat != NULL) *tat = sa.TAT;\r |
2153 | if (tbt != NULL) *tbt = sa.TBT;\r |
f5c022a8 |
2154 | if (busy != NULL) *busy = sa.busy_timer;\r |
d2721b08 |
2155 | \r |
2156 | // chans 1,2,3\r |
2157 | ptr = &ym2612.REGS[0x0b8];\r |
2158 | for (c = 0; c < 3; c++)\r |
2159 | {\r |
2160 | for (s = 0; s < 4; s++) {\r |
2161 | memcpy(&ss, ptr, 6);\r |
2162 | ym2612.CH[c].SLOT[s].state = ss.state_phase >> 29;\r |
2163 | ym2612.CH[c].SLOT[s].phase = ss.state_phase << 3;\r |
2164 | ym2612.CH[c].SLOT[s].volume = ss.volume;\r |
db49317b |
2165 | ym2612.CH[c].SLOT[s].key = (sa.keyon_field & (1 << (c*4 + s))) ? 1 : 0;\r |
2166 | ym2612.CH[c].SLOT[s].ksr = (UINT8)-1;\r |
d2721b08 |
2167 | ptr += 6;\r |
2168 | }\r |
db49317b |
2169 | ym2612.CH[c].SLOT[SLOT1].Incr=-1;\r |
2170 | ym2612.CH[c].block_fnum = sa2.block_fnum[c];\r |
2171 | fn = ym2612.CH[c].block_fnum & 0x7ff;\r |
2172 | blk = ym2612.CH[c].block_fnum >> 11;\r |
2173 | ym2612.CH[c].kcode= (blk<<2) | opn_fktable[fn >> 7];\r |
2174 | ym2612.CH[c].fc = fn_table[fn*2]>>(7-blk);\r |
196e2929 |
2175 | refresh_fc_eg_chan( &ym2612.CH[c] );\r |
d2721b08 |
2176 | }\r |
2177 | // chans 4,5,6\r |
2178 | ptr = &ym2612.REGS[0x1b8];\r |
2179 | for (; c < 6; c++)\r |
2180 | {\r |
2181 | for (s = 0; s < 4; s++) {\r |
2182 | memcpy(&ss, ptr, 6);\r |
2183 | ym2612.CH[c].SLOT[s].state = ss.state_phase >> 29;\r |
2184 | ym2612.CH[c].SLOT[s].phase = ss.state_phase << 3;\r |
2185 | ym2612.CH[c].SLOT[s].volume = ss.volume;\r |
db49317b |
2186 | ym2612.CH[c].SLOT[s].key = (sa.keyon_field & (1 << (c*4 + s))) ? 1 : 0;\r |
2187 | ym2612.CH[c].SLOT[s].ksr = (UINT8)-1;\r |
d2721b08 |
2188 | ptr += 6;\r |
2189 | }\r |
db49317b |
2190 | ym2612.CH[c].SLOT[SLOT1].Incr=-1;\r |
2191 | ym2612.CH[c].block_fnum = sa2.block_fnum[c];\r |
2192 | fn = ym2612.CH[c].block_fnum & 0x7ff;\r |
2193 | blk = ym2612.CH[c].block_fnum >> 11;\r |
2194 | ym2612.CH[c].kcode= (blk<<2) | opn_fktable[fn >> 7];\r |
2195 | ym2612.CH[c].fc = fn_table[fn*2]>>(7-blk);\r |
196e2929 |
2196 | refresh_fc_eg_chan( &ym2612.CH[c] );\r |
db49317b |
2197 | }\r |
2198 | for (c = 0; c < 3; c++)\r |
2199 | {\r |
2200 | ym2612.OPN.SL3.block_fnum[c] = sa2.block_fnum_sl3[c];\r |
2201 | fn = ym2612.OPN.SL3.block_fnum[c] & 0x7ff;\r |
2202 | blk = ym2612.OPN.SL3.block_fnum[c] >> 11;\r |
2203 | ym2612.OPN.SL3.kcode[c]= (blk<<2) | opn_fktable[fn >> 7];\r |
2204 | ym2612.OPN.SL3.fc[c] = fn_table[fn*2]>>(7-blk);\r |
d2721b08 |
2205 | }\r |
2206 | \r |
2207 | return 0;\r |
cc68a136 |
2208 | }\r |
2209 | \r |
cc68a136 |
2210 | void *YM2612GetRegs(void)\r |
2211 | {\r |
2212 | return ym2612.REGS;\r |
2213 | }\r |
2433f409 |
2214 | \r |