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