platform ps2, handle audio similar to psp
[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** updated with fixes from mame 0.216 (file version 1.5.1) (kub)\r
10** SSG-EG readded from GenPlus (kub)\r
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
117#include "../pico_int.h"\r
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
123YM2612 ym2612;\r
124\r
125#else\r
126extern YM2612 *ym2612_940;\r
127#define ym2612 (*ym2612_940)\r
128\r
129#endif\r
130\r
131void memset32(void *dest, int c, int count);\r
132\r
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
143#define INLINE __inline\r
144#endif\r
145\r
146#ifndef M_PI\r
147#define M_PI 3.14159265358979323846\r
148#endif\r
149\r
150\r
151/* globals */\r
152\r
153#define FREQ_SH 16 /* 16.16 fixed point (frequency calculations) */\r
154#define EG_SH 16 /* 16.16 fixed point (envelope generator timing) */\r
155#define LFO_SH 24 /* 8.24 fixed point (LFO calculations) */\r
156#define TIMER_SH 16 /* 16.16 fixed point (timers calculations) */\r
157\r
158#define ENV_BITS 10\r
159#define ENV_LEN (1<<ENV_BITS)\r
160#define ENV_STEP (128.0/ENV_LEN)\r
161\r
162#define MAX_ATT_INDEX (ENV_LEN-1) /* 1023 */\r
163#define MIN_ATT_INDEX (0) /* 0 */\r
164\r
165#define EG_ATT 4\r
166#define EG_DEC 3\r
167#define EG_SUS 2\r
168#define EG_REL 1\r
169#define EG_OFF 0\r
170\r
171#define SIN_BITS 10\r
172#define SIN_LEN (1<<SIN_BITS)\r
173#define SIN_MASK (SIN_LEN-1)\r
174\r
175#define TL_RES_LEN (256) /* 8 bits addressing (real chip) */\r
176\r
177#define EG_TIMER_OVERFLOW (3*(1<<EG_SH)) /* envelope generator timer overflows every 3 samples (on real chip) */\r
178\r
179/* 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
196static int ym_init_tab;\r
197\r
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
286O(18),O(18),O( 2),O( 3),\r
287O( 0),O( 1),O( 2),O( 3),\r
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
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
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
380 8 ,8, 9,10,11,12,13,14,16,17,19,20,22,22,22,22\r
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
516static int g_lfo_ampm;\r
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
530static INLINE void set_timers( int v )\r
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
551static INLINE void recalc_volout(FM_SLOT *SLOT)\r
552{\r
553 INT16 vol_out = SLOT->volume;\r
554 if ((SLOT->ssg&0x0c) == 0x0c)\r
555 vol_out = (0x200 - vol_out) & MAX_ATT_INDEX;\r
556 SLOT->vol_out = vol_out + SLOT->tl;\r
557}\r
558\r
559static INLINE void FM_KEYON(int c , int s )\r
560{\r
561 FM_SLOT *SLOT = &ym2612.CH[c].SLOT[s];\r
562 if( !SLOT->key )\r
563 {\r
564 SLOT->key = 1;\r
565 SLOT->phase = 0; /* restart Phase Generator */\r
566 SLOT->ssg ^= SLOT->ssgn;\r
567 SLOT->ssgn = 0;\r
568 SLOT->state = (SLOT->sl == MIN_ATT_INDEX) ? EG_SUS : EG_DEC;\r
569 if (SLOT->ar_ksr < 32+62) {\r
570 if (SLOT->volume > MIN_ATT_INDEX) SLOT->state = EG_ATT;\r
571 } else {\r
572 SLOT->volume = MIN_ATT_INDEX;\r
573 }\r
574 recalc_volout(SLOT);\r
575 ym2612.slot_mask |= (1<<s) << (c*4);\r
576 }\r
577}\r
578\r
579static INLINE void FM_KEYOFF(int c , int s )\r
580{\r
581 FM_SLOT *SLOT = &ym2612.CH[c].SLOT[s];\r
582 if( SLOT->key )\r
583 {\r
584 SLOT->key = 0;\r
585 if (SLOT->state>EG_REL) {\r
586 SLOT->state = EG_REL;/* phase -> Release */\r
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
597 }\r
598}\r
599\r
600\r
601/* set detune & multiple */\r
602static INLINE void set_det_mul(FM_CH *CH, FM_SLOT *SLOT, int v)\r
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
610static INLINE void set_tl(FM_SLOT *SLOT, int v)\r
611{\r
612 SLOT->tl = (v&0x7f)<<(ENV_BITS-7); /* 7bit TL */\r
613 if (SLOT->state > EG_REL)\r
614 recalc_volout(SLOT);\r
615}\r
616\r
617/* set attack rate & key scale */\r
618static INLINE void set_ar_ksr(FM_CH *CH, FM_SLOT *SLOT, int v)\r
619{\r
620 UINT8 old_KSR = SLOT->KSR;\r
621 int eg_sh_ar, eg_sel_ar;\r
622\r
623 SLOT->ar = (v&0x1f) ? 32 + ((v&0x1f)<<1) : 0;\r
624 SLOT->ar_ksr = SLOT->ar + SLOT->ksr;\r
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
631\r
632 /* refresh Attack rate */\r
633 if ((SLOT->ar_ksr) < 32+62)\r
634 {\r
635 eg_sh_ar = eg_rate_shift [SLOT->ar_ksr];\r
636 eg_sel_ar = eg_rate_select[SLOT->ar_ksr];\r
637 }\r
638 else\r
639 {\r
640 eg_sh_ar = 0;\r
641 eg_sel_ar = 18;\r
642 }\r
643\r
644 SLOT->eg_pack_ar = eg_inc_pack[eg_sel_ar] | (eg_sh_ar<<24);\r
645}\r
646\r
647/* set decay rate */\r
648static INLINE void set_dr(FM_SLOT *SLOT, int v)\r
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
661static INLINE void set_sr(FM_SLOT *SLOT, int v)\r
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
674static INLINE void set_sl_rr(FM_SLOT *SLOT, int v)\r
675{\r
676 int eg_sh_rr, eg_sel_rr;\r
677\r
678 SLOT->sl = sl_table[ v>>4 ];\r
679\r
680 if (SLOT->state == EG_DEC && (SLOT->volume >= (INT32)(SLOT->sl)))\r
681 SLOT->state = EG_SUS;\r
682\r
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
693static INLINE signed int op_calc(UINT32 phase, unsigned int env, signed int pm)\r
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
710static INLINE signed int op_calc1(UINT32 phase, unsigned int env, signed int pm)\r
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
728static INLINE int advance_lfo(int lfo_ampm, UINT32 lfo_cnt_old, UINT32 lfo_cnt)\r
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
742 /* triangle (inverted) */\r
743 /* AM: 0 to 126 step +2, 126 to 0 step -2 */\r
744 if (pos<64)\r
745 lfo_ampm |= ((pos^63) * 2) << 8; /* 0 - 126 */\r
746 else\r
747 lfo_ampm |= ((pos&63) * 2) << 8;\r
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
766static INLINE void update_eg_phase(FM_SLOT *SLOT, UINT32 eg_cnt, UINT32 ssg_en)\r
767{\r
768 INT32 volume = SLOT->volume;\r
769 UINT32 pack = SLOT->eg_pack[SLOT->state - 1];\r
770 UINT32 shift = pack >> 24;\r
771 INT32 eg_inc_val;\r
772\r
773 if (eg_cnt & ((1 << shift) - 1))\r
774 return;\r
775\r
776 eg_inc_val = pack >> ((eg_cnt >> shift) & 7) * 3;\r
777 eg_inc_val = (1 << (eg_inc_val & 7)) >> 1;\r
778\r
779 if ((SLOT->ssg&0x08) && ssg_en) {\r
780 switch (SLOT->state)\r
781 {\r
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
812 }\r
813\r
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
819 {\r
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
828\r
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
852 }\r
853\r
854 SLOT->vol_out = volume + SLOT->tl;\r
855 }\r
856 SLOT->volume = volume;\r
857}\r
858\r
859static INLINE UINT32 update_ssg_eg_phase(FM_SLOT *SLOT, UINT32 phase)\r
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
874 phase = 0;\r
875\r
876 if (SLOT->state != EG_ATT) {\r
877 SLOT->state = (SLOT->sl == MIN_ATT_INDEX) ? EG_SUS : EG_DEC;\r
878 if (SLOT->ar_ksr < 32+62) {\r
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
885 recalc_volout(SLOT);\r
886 return phase;\r
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
897 UINT32 lfo_init_sft16;\r
898 UINT32 pad;\r
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
915 UINT32 algo; /* 50: algo[3], was_update, unsued, upd_cnt[2], dac */\r
916 INT32 op1_out;\r
917#ifdef _MIPS_ARCH_ALLEGREX\r
918 UINT32 pad1[3+8];\r
919#endif\r
920} chan_rend_context;\r
921\r
922\r
923#if !defined(_ASM_YM2612_C) || defined(EXTERNAL_YM2612)\r
924#include <limits.h>\r
925static int clip(int n) \r
926{\r
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
931}\r
932\r
933static void update_ssg_eg_channel(chan_rend_context *ct)\r
934{\r
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
950\r
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
971 {\r
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
981\r
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
989 }\r
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
999\r
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
1007 }\r
1008 case 2:\r
1009 {\r
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
1018\r
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
1026 }\r
1027 case 3:\r
1028 {\r
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
1037\r
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
1045 }\r
1046 case 4:\r
1047 {\r
1048 /* M1---C1-+-OUT */\r
1049 /* M2---C2-+ */\r
1050 /* MEM: not used */\r
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
1063 }\r
1064 case 5:\r
1065 {\r
1066 /* +----C1----+ */\r
1067 /* M1-+-MEM---M2-+-OUT */\r
1068 /* +----C2----+ */\r
1069 m2 = ct->mem;\r
1070 ct->mem = c1 = c2 = ct->op1_out>>16;\r
1071\r
1072 if( eg_out < ENV_QUIET ) { /* SLOT 3 */\r
1073 smp = op_calc(ct->phase3, eg_out, m2);\r
1074 }\r
1075 if( eg_out2 < ENV_QUIET ) { /* SLOT 2 */\r
1076 smp+= op_calc(ct->phase2, eg_out2, c1);\r
1077 }\r
1078 if( eg_out4 < ENV_QUIET ) { /* SLOT 4 */\r
1079 smp+= op_calc(ct->phase4, eg_out4, c2);\r
1080 }\r
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
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
1093 }\r
1094 if( eg_out2 < ENV_QUIET ) { /* SLOT 2 */\r
1095 smp+= op_calc(ct->phase2, eg_out2, c1);\r
1096 }\r
1097 if( eg_out4 < ENV_QUIET ) { /* SLOT 4 */\r
1098 smp+= op_calc(ct->phase4, eg_out4, 0);\r
1099 }\r
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
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
1113 }\r
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
1126static void chan_render_loop(chan_rend_context *ct, s32 *buffer, int length)\r
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
1137\r
1138 while (ct->eg_timer >= 1<<EG_SH) {\r
1139 ct->eg_timer -= 1<<EG_SH;\r
1140\r
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
1153 }\r
1154\r
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
1159\r
1160 if (ct->pack & 4) goto disabled; /* output disabled */\r
1161\r
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
1166\r
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
1171\r
1172 if( eg_out < ENV_QUIET ) /* SLOT 1 */\r
1173 {\r
1174 int out = 0;\r
1175\r
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
1182\r
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
1186\r
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
1193\r
1194 smp = update_algo_channel(ct, eg_out, eg_out2, eg_out4);\r
1195 /* done calculating channel sample */\r
1196disabled:\r
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
1202\r
1203 /* mix sample to output buffer */\r
1204 if (smp) {\r
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
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
1218 ct->algo |= 8;\r
1219 }\r
1220 }\r
1221}\r
1222#else\r
1223void chan_render_loop(chan_rend_context *ct, s32 *buffer, unsigned short length);\r
1224#endif\r
1225\r
1226static chan_rend_context crct;\r
1227\r
1228static void chan_render_prep(void)\r
1229{\r
1230 crct.eg_timer_add = ym2612.OPN.eg_timer_add;\r
1231 crct.lfo_init_sft16 = g_lfo_ampm << 16;\r
1232 crct.lfo_inc = ym2612.OPN.lfo_inc;\r
1233}\r
1234\r
1235static void chan_render_finish(s32 *buffer, int length, int active_chans)\r
1236{\r
1237 ym2612.OPN.eg_cnt = crct.eg_cnt;\r
1238 ym2612.OPN.eg_timer = crct.eg_timer;\r
1239 ym2612.OPN.lfo_cnt += ym2612.OPN.lfo_inc * length;\r
1240}\r
1241\r
1242static UINT32 update_lfo_phase(const FM_SLOT *SLOT, UINT32 block_fnum)\r
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
1269static int chan_render(s32 *buffer, int length, int c, UINT32 flags) // flags: stereo, ?, disabled, ?, pan_r, pan_l\r
1270{\r
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
1274\r
1275 flags &= 0x37;\r
1276\r
1277 if (crct.lfo_inc) {\r
1278 flags |= 8;\r
1279 flags |= crct.lfo_init_sft16;\r
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
1284 }\r
1285 flags |= (crct.CH->FB&0xf)<<12; /* feedback shift */\r
1286 crct.pack = flags;\r
1287\r
1288 crct.eg_cnt = ym2612.OPN.eg_cnt; /* envelope generator counter */\r
1289 crct.eg_timer = ym2612.OPN.eg_timer;\r
1290\r
1291 /* precalculate phase modulation incr */\r
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
1296\r
1297 crct.op1_out = crct.CH->op1_out;\r
1298 crct.algo = crct.CH->ALGO & 7;\r
1299 crct.algo |= crct.CH->upd_cnt << 4;\r
1300 if (ym2612.OPN.ST.flags & ST_DAC)\r
1301 crct.algo |= 0x80;\r
1302\r
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
1311 {\r
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
1316 }\r
1317 else /* no LFO phase modulation */\r
1318 {\r
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
1323 }\r
1324\r
1325 chan_render_loop(&crct, buffer, length);\r
1326\r
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
1335 }\r
1336 else\r
1337 ym2612.slot_mask &= ~(0xf << (c*4));\r
1338 crct.CH->upd_cnt = (crct.algo >> 4) & 0x7;\r
1339\r
1340 return (crct.algo & 8) >> 3; // had output\r
1341}\r
1342\r
1343/* update phase increment and envelope generator */\r
1344static INLINE void refresh_fc_eg_slot(FM_SLOT *SLOT, int fc, int kc)\r
1345{\r
1346 int ksr, fdt;\r
1347\r
1348 /* (frequency) phase increment counter */\r
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
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
1360 SLOT->ar_ksr = SLOT->ar + ksr;\r
1361\r
1362 /* calculate envelope generator rates */\r
1363 if ((SLOT->ar_ksr) < 32+62)\r
1364 {\r
1365 eg_sh = eg_rate_shift [SLOT->ar_ksr];\r
1366 eg_sel = eg_rate_select[SLOT->ar_ksr];\r
1367 }\r
1368 else\r
1369 {\r
1370 eg_sh = 0;\r
1371 eg_sel = 18;\r
1372 }\r
1373\r
1374 SLOT->eg_pack_ar = eg_inc_pack[eg_sel] | (eg_sh<<24);\r
1375\r
1376 eg_sh = eg_rate_shift [SLOT->d1r + ksr];\r
1377 eg_sel = eg_rate_select[SLOT->d1r + ksr];\r
1378\r
1379 SLOT->eg_pack_d1r = eg_inc_pack[eg_sel] | (eg_sh<<24);\r
1380\r
1381 eg_sh = eg_rate_shift [SLOT->d2r + ksr];\r
1382 eg_sel = eg_rate_select[SLOT->d2r + ksr];\r
1383\r
1384 SLOT->eg_pack_d2r = eg_inc_pack[eg_sel] | (eg_sh<<24);\r
1385\r
1386 eg_sh = eg_rate_shift [SLOT->rr + ksr];\r
1387 eg_sel = eg_rate_select[SLOT->rr + ksr];\r
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
1394static INLINE void refresh_fc_eg_chan(FM_CH *CH)\r
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
1406static INLINE void refresh_fc_eg_chan_sl3(void)\r
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
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
1426 rate = ((double)dttable[d*32 + i]) * ym2612.OPN.ST.freqbase * (1<<(FREQ_SH-10));\r
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
1434static void reset_channels(FM_CH *CH)\r
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
1444 for( c = 0 ; c < 6 ; c++ )\r
1445 {\r
1446 CH[c].fc = 0;\r
1447 for(s = 0 ; s < 4 ; s++ )\r
1448 {\r
1449 CH[c].SLOT[s].Incr = -1;\r
1450 CH[c].SLOT[s].key = 0;\r
1451 CH[c].SLOT[s].phase = 0;\r
1452 CH[c].SLOT[s].ar = CH[c].SLOT[s].ksr = 0;\r
1453 CH[c].SLOT[s].ar_ksr = 0;\r
1454 CH[c].SLOT[s].ssg = CH[c].SLOT[s].ssgn = 0;\r
1455 CH[c].SLOT[s].state= EG_OFF;\r
1456 CH[c].SLOT[s].volume = MAX_ATT_INDEX;\r
1457 CH[c].SLOT[s].vol_out = MAX_ATT_INDEX;\r
1458 }\r
1459 CH[c].mem_value = CH[c].op1_out = 0;\r
1460 }\r
1461 ym2612.slot_mask = 0;\r
1462 ym2612.ssg_mask = 0;\r
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
1472 if (ym_init_tab) return;\r
1473 ym_init_tab = 1;\r
1474\r
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
1574#if 0\r
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
1585#endif\r
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
1594 double freqbase = (ym2612.OPN.ST.rate) ? ((double)ym2612.OPN.ST.clock / ym2612.OPN.ST.rate) / pres : 0;\r
1595\r
1596 ym2612.OPN.eg_timer_add = (1<<EG_SH) * freqbase;\r
1597 ym2612.OPN.ST.freqbase = freqbase;\r
1598\r
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
1652 case 0x60: /* bit7 = AM ENABLE, DR | depends on ksr */\r
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
1658 case 0x70: /* SR | depends on ksr */\r
1659 set_sr(SLOT,v);\r
1660 break;\r
1661\r
1662 case 0x80: /* SL, RR | depends on ksr */\r
1663 set_sl_rr(SLOT,v);\r
1664 break;\r
1665\r
1666 case 0x90: /* SSG-EG */\r
1667 SLOT->ssg = v&0x0f;\r
1668 SLOT->ssg ^= SLOT->ssgn;\r
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
1671 if (SLOT->state > EG_REL)\r
1672 recalc_volout(SLOT);\r
1673 break;\r
1674\r
1675 case 0xa0:\r
1676 switch( OPN_SLOT(r) ){\r
1677 case 0: /* 0xa0-0xa2 : FNUM1 | depends on fn_h (below) */\r
1678 {\r
1679 UINT32 fn = ((UINT32)(ym2612.OPN.ST.fn_h & 7) << 8) | v;\r
1680 UINT8 blk = ym2612.OPN.ST.fn_h >> 3;\r
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
1693 ym2612.OPN.ST.fn_h = v & 0x3f;\r
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
1705 ym2612.OPN.SL3.block_fnum[c] = (blk<<11) | fn;\r
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
1762/* Generate samples for YM2612 */\r
1763int YM2612UpdateOne_(s32 *buffer, int length, int stereo, int is_buf_empty)\r
1764{\r
1765 int pan;\r
1766 int active_chs = 0;\r
1767 int flags = stereo ? 1:0;\r
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
1771\r
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
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
1794 /* 3SLOT MODE */\r
1795 refresh_fc_eg_chan_sl3();\r
1796 else\r
1797 refresh_fc_eg_chan( &ym2612.CH[2] );\r
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
1803\r
1804 /* mix to 32bit dest */\r
1805 // flags: stereo, ssg_enabled, disabled, _, pan_r, pan_l\r
1806 chan_render_prep();\r
1807#define BIT_IF(v,b,c) { v &= ~(1<<(b)); if (c) v |= 1<<(b); }\r
1808 BIT_IF(flags, 1, (ym2612.ssg_mask & 0x00000f) && (ym2612.OPN.ST.flags & 1));\r
1809 if (ym2612.slot_mask & 0x00000f) active_chs |= chan_render(buffer, length, 0, flags|((pan&0x003)<<4)) << 0;\r
1810 BIT_IF(flags, 1, (ym2612.ssg_mask & 0x0000f0) && (ym2612.OPN.ST.flags & 1));\r
1811 if (ym2612.slot_mask & 0x0000f0) active_chs |= chan_render(buffer, length, 1, flags|((pan&0x00c)<<2)) << 1;\r
1812 BIT_IF(flags, 1, (ym2612.ssg_mask & 0x000f00) && (ym2612.OPN.ST.flags & 1));\r
1813 if (ym2612.slot_mask & 0x000f00) active_chs |= chan_render(buffer, length, 2, flags|((pan&0x030) )) << 2;\r
1814 BIT_IF(flags, 1, (ym2612.ssg_mask & 0x00f000) && (ym2612.OPN.ST.flags & 1));\r
1815 if (ym2612.slot_mask & 0x00f000) active_chs |= chan_render(buffer, length, 3, flags|((pan&0x0c0)>>2)) << 3;\r
1816 BIT_IF(flags, 1, (ym2612.ssg_mask & 0x0f0000) && (ym2612.OPN.ST.flags & 1));\r
1817 if (ym2612.slot_mask & 0x0f0000) active_chs |= chan_render(buffer, length, 4, flags|((pan&0x300)>>4)) << 4;\r
1818 g_lfo_ampm = crct.pack >> 16; // need_save; now because ch5 might skip updating it\r
1819 BIT_IF(flags, 1, (ym2612.ssg_mask & 0xf00000) && (ym2612.OPN.ST.flags & 1));\r
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
1822 chan_render_finish(buffer, length, active_chs);\r
1823\r
1824 return active_chs; // 1 if buffer updated\r
1825}\r
1826\r
1827\r
1828/* initialize YM2612 emulator */\r
1829void YM2612Init_(int clock, int rate, int flags)\r
1830{\r
1831 memset(&ym2612, 0, sizeof(ym2612));\r
1832 init_tables();\r
1833\r
1834 ym2612.OPN.ST.clock = clock;\r
1835 ym2612.OPN.ST.rate = rate;\r
1836 ym2612.OPN.ST.flags = flags;\r
1837\r
1838 OPNSetPres( 6*24 );\r
1839\r
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
1850 memset(ym2612.REGS, 0, sizeof(ym2612.REGS));\r
1851\r
1852 set_timers( 0x30 ); /* mode 0 , timer reset */\r
1853 ym2612.REGS[0x27] = 0x30;\r
1854\r
1855 ym2612.OPN.eg_timer = 0;\r
1856 ym2612.OPN.eg_cnt = 0;\r
1857 ym2612.OPN.lfo_inc = 0;\r
1858 ym2612.OPN.lfo_cnt = 0;\r
1859 g_lfo_ampm = 126 << 8;\r
1860 ym2612.OPN.ST.status = 0;\r
1861\r
1862 reset_channels( &ym2612.CH[0] );\r
1863 for(i = 0xb6 ; i >= 0xb4 ; i-- )\r
1864 {\r
1865 OPNWriteReg(i ,0xc0);\r
1866 OPNWriteReg(i|0x100,0xc0);\r
1867 ym2612.REGS[i ] = 0xc0;\r
1868 ym2612.REGS[i|0x100] = 0xc0;\r
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
1878 ym2612.dacout = 0;\r
1879 ym2612.addr_A1 = 0;\r
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
1893 switch( a & 3 ){\r
1894 case 0: /* address port 0 */\r
1895 case 2: /* address port 1 */\r
1896 /* reminder: this is not used, see ym2612_write_local() */\r
1897 ym2612.OPN.ST.address = v;\r
1898 ym2612.addr_A1 = (a & 2) >> 1;\r
1899 ret = 0;\r
1900 break;\r
1901\r
1902 case 1:\r
1903 case 3: /* data port */\r
1904 addr = ym2612.OPN.ST.address | ((int)ym2612.addr_A1 << 8);\r
1905\r
1906 switch( addr & 0x1f0 )\r
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
1919 ym2612.OPN.lfo_cnt = 0;\r
1920 g_lfo_ampm = 126 << 8;\r
1921 }\r
1922 break;\r
1923#if 0 // handled elsewhere\r
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
1954#endif\r
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
1962\r
1963 c = v & 0x03;\r
1964 if( c == 3 ) { ret=0; break; }\r
1965 if( v&0x04 ) c+=3;\r
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
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
1990 }\r
1991\r
1992 return ret;\r
1993}\r
1994\r
1995#if 0\r
1996UINT8 YM2612Read_(void)\r
1997{\r
1998 return ym2612.OPN.ST.status;\r
1999}\r
2000\r
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
2024#endif\r
2025\r
2026void YM2612PicoStateLoad_(void)\r
2027{\r
2028 reset_channels( &ym2612.CH[0] );\r
2029 ym2612.slot_mask = 0xffffff;\r
2030}\r
2031\r
2032/* rather stupid design because I wanted to fit in unused register "space" */\r
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
2048 UINT32 eg_cnt; // 10\r
2049 UINT32 eg_timer;\r
2050 UINT32 lfo_cnt;\r
2051 UINT16 lfo_ampm;\r
2052 INT16 busy_timer;\r
2053 UINT32 keyon_field; // 20\r
2054 UINT32 kcode_fc_sl3_3;\r
2055 UINT32 reserved[2];\r
2056} ym_save_addon;\r
2057\r
2058typedef struct\r
2059{\r
2060 UINT16 block_fnum[6];\r
2061 UINT16 block_fnum_sl3[3];\r
2062 UINT16 reserved[7];\r
2063} ym_save_addon2;\r
2064\r
2065\r
2066void YM2612PicoStateSave2(int tat, int tbt, int busy)\r
2067{\r
2068 ym_save_addon_slot ss;\r
2069 ym_save_addon2 sa2;\r
2070 ym_save_addon sa;\r
2071 unsigned char *ptr;\r
2072 int c, s;\r
2073\r
2074 memset(&sa, 0, sizeof(sa));\r
2075 memset(&sa2, 0, sizeof(sa2));\r
2076\r
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
2084 if (ym2612.CH[c].SLOT[s].key)\r
2085 sa.keyon_field |= 1 << (c*4 + s);\r
2086 memcpy(ptr, &ss, 6);\r
2087 ptr += 6;\r
2088 }\r
2089 sa2.block_fnum[c] = ym2612.CH[c].block_fnum;\r
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
2098 if (ym2612.CH[c].SLOT[s].key)\r
2099 sa.keyon_field |= 1 << (c*4 + s);\r
2100 memcpy(ptr, &ss, 6);\r
2101 ptr += 6;\r
2102 }\r
2103 sa2.block_fnum[c] = ym2612.CH[c].block_fnum;\r
2104 }\r
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
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
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
2124 sa.busy_timer = busy;\r
2125 memcpy(ptr, &sa, sizeof(sa)); // 0x30 max\r
2126}\r
2127\r
2128int YM2612PicoStateLoad2(int *tat, int *tbt, int *busy)\r
2129{\r
2130 ym_save_addon_slot ss;\r
2131 ym_save_addon2 sa2;\r
2132 ym_save_addon sa;\r
2133 unsigned char *ptr;\r
2134 UINT32 fn;\r
2135 UINT8 blk;\r
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
2142 ptr = &ym2612.REGS[0];\r
2143 memcpy(&sa2, ptr, sizeof(sa2));\r
2144\r
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
2154 if (busy != NULL) *busy = sa.busy_timer;\r
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
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
2167 ptr += 6;\r
2168 }\r
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
2175 refresh_fc_eg_chan( &ym2612.CH[c] );\r
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
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
2188 ptr += 6;\r
2189 }\r
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
2196 refresh_fc_eg_chan( &ym2612.CH[c] );\r
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
2205 }\r
2206\r
2207 return 0;\r
2208}\r
2209\r
2210void *YM2612GetRegs(void)\r
2211{\r
2212 return ym2612.REGS;\r
2213}\r
2214\r