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