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