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