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