fix ym2612 asm, rework EG
[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
b542be46 564 ym2612.slot_mask |= (1<<s) << (c*4);\r
cc68a136 565 }\r
566}\r
567\r
b542be46 568INLINE void FM_KEYOFF(int c , int s )\r
cc68a136 569{\r
b542be46 570 FM_SLOT *SLOT = &ym2612.CH[c].SLOT[s];\r
cc68a136 571 if( SLOT->key )\r
572 {\r
573 SLOT->key = 0;\r
574 if (SLOT->state>EG_REL)\r
575 SLOT->state = EG_REL;/* phase -> Release */\r
576 }\r
577}\r
578\r
579\r
580/* set detune & multiple */\r
581INLINE void set_det_mul(FM_CH *CH, FM_SLOT *SLOT, int v)\r
582{\r
583 SLOT->mul = (v&0x0f)? (v&0x0f)*2 : 1;\r
584 SLOT->DT = ym2612.OPN.ST.dt_tab[(v>>4)&7];\r
585 CH->SLOT[SLOT1].Incr=-1;\r
586}\r
587\r
588/* set total level */\r
589INLINE void set_tl(FM_SLOT *SLOT, int v)\r
590{\r
591 SLOT->tl = (v&0x7f)<<(ENV_BITS-7); /* 7bit TL */\r
592}\r
593\r
594/* set attack rate & key scale */\r
595INLINE void set_ar_ksr(FM_CH *CH, FM_SLOT *SLOT, int v)\r
596{\r
597 UINT8 old_KSR = SLOT->KSR;\r
598\r
599 SLOT->ar = (v&0x1f) ? 32 + ((v&0x1f)<<1) : 0;\r
600\r
601 SLOT->KSR = 3-(v>>6);\r
602 if (SLOT->KSR != old_KSR)\r
603 {\r
604 CH->SLOT[SLOT1].Incr=-1;\r
605 }\r
606 else\r
607 {\r
608 int eg_sh_ar, eg_sel_ar;\r
609\r
610 /* refresh Attack rate */\r
611 if ((SLOT->ar + SLOT->ksr) < 32+62)\r
612 {\r
613 eg_sh_ar = eg_rate_shift [SLOT->ar + SLOT->ksr ];\r
614 eg_sel_ar = eg_rate_select[SLOT->ar + SLOT->ksr ];\r
615 }\r
616 else\r
617 {\r
618 eg_sh_ar = 0;\r
619 eg_sel_ar = 17;\r
620 }\r
621\r
622 SLOT->eg_pack_ar = eg_inc_pack[eg_sel_ar] | (eg_sh_ar<<24);\r
623 }\r
624}\r
625\r
626/* set decay rate */\r
627INLINE void set_dr(FM_SLOT *SLOT, int v)\r
628{\r
629 int eg_sh_d1r, eg_sel_d1r;\r
630\r
631 SLOT->d1r = (v&0x1f) ? 32 + ((v&0x1f)<<1) : 0;\r
632\r
633 eg_sh_d1r = eg_rate_shift [SLOT->d1r + SLOT->ksr];\r
634 eg_sel_d1r= eg_rate_select[SLOT->d1r + SLOT->ksr];\r
635\r
636 SLOT->eg_pack_d1r = eg_inc_pack[eg_sel_d1r] | (eg_sh_d1r<<24);\r
637}\r
638\r
639/* set sustain rate */\r
640INLINE void set_sr(FM_SLOT *SLOT, int v)\r
641{\r
642 int eg_sh_d2r, eg_sel_d2r;\r
643\r
644 SLOT->d2r = (v&0x1f) ? 32 + ((v&0x1f)<<1) : 0;\r
645\r
646 eg_sh_d2r = eg_rate_shift [SLOT->d2r + SLOT->ksr];\r
647 eg_sel_d2r= eg_rate_select[SLOT->d2r + SLOT->ksr];\r
648\r
649 SLOT->eg_pack_d2r = eg_inc_pack[eg_sel_d2r] | (eg_sh_d2r<<24);\r
650}\r
651\r
652/* set release rate */\r
653INLINE void set_sl_rr(FM_SLOT *SLOT, int v)\r
654{\r
655 int eg_sh_rr, eg_sel_rr;\r
656\r
657 SLOT->sl = sl_table[ v>>4 ];\r
658\r
659 SLOT->rr = 34 + ((v&0x0f)<<2);\r
660\r
661 eg_sh_rr = eg_rate_shift [SLOT->rr + SLOT->ksr];\r
662 eg_sel_rr = eg_rate_select[SLOT->rr + SLOT->ksr];\r
663\r
664 SLOT->eg_pack_rr = eg_inc_pack[eg_sel_rr] | (eg_sh_rr<<24);\r
665}\r
666\r
667\r
668\r
669INLINE signed int op_calc(UINT32 phase, unsigned int env, signed int pm)\r
670{\r
671 int ret, sin = (phase>>16) + (pm>>1);\r
672 int neg = sin & 0x200;\r
673 if (sin & 0x100) sin ^= 0xff;\r
674 sin&=0xff;\r
675 env&=~1;\r
676\r
677 // this was already checked\r
678 // if (env >= ENV_QUIET) // 384\r
679 // return 0;\r
680\r
681 ret = ym_tl_tab[sin | (env<<7)];\r
682\r
683 return neg ? -ret : ret;\r
684}\r
685\r
686INLINE signed int op_calc1(UINT32 phase, unsigned int env, signed int pm)\r
687{\r
688 int ret, sin = (phase+pm)>>16;\r
689 int neg = sin & 0x200;\r
690 if (sin & 0x100) sin ^= 0xff;\r
691 sin&=0xff;\r
692 env&=~1;\r
693\r
694 // if (env >= ENV_QUIET) // 384\r
695 // return 0;\r
696\r
697 ret = ym_tl_tab[sin | (env<<7)];\r
698\r
699 return neg ? -ret : ret;\r
700}\r
701\r
702#if !defined(_ASM_YM2612_C) || defined(EXTERNAL_YM2612)\r
703/* advance LFO to next sample */\r
704INLINE int advance_lfo(int lfo_ampm, UINT32 lfo_cnt_old, UINT32 lfo_cnt)\r
705{\r
706 UINT8 pos;\r
707 UINT8 prev_pos;\r
708\r
709 prev_pos = (lfo_cnt_old >> LFO_SH) & 127;\r
710\r
711 pos = (lfo_cnt >> LFO_SH) & 127;\r
712\r
713 /* update AM when LFO output changes */\r
714\r
715 if (prev_pos != pos)\r
716 {\r
717 lfo_ampm &= 0xff;\r
718 /* triangle */\r
719 /* AM: 0 to 126 step +2, 126 to 0 step -2 */\r
720 if (pos<64)\r
721 lfo_ampm |= ((pos&63) * 2) << 8; /* 0 - 126 */\r
722 else\r
723 lfo_ampm |= (126 - (pos&63)*2) << 8;\r
724 }\r
725 else\r
726 {\r
727 return lfo_ampm;\r
728 }\r
729\r
730 /* PM works with 4 times slower clock */\r
731 prev_pos >>= 2;\r
732 pos >>= 2;\r
733 /* update PM when LFO output changes */\r
734 if (prev_pos != pos)\r
735 {\r
736 lfo_ampm &= ~0xff;\r
737 lfo_ampm |= pos; /* 0 - 32 */\r
738 }\r
739 return lfo_ampm;\r
740}\r
741\r
6d28fb50 742INLINE void update_eg_phase(UINT16 *vol_out, FM_SLOT *SLOT, UINT32 eg_cnt)\r
cc68a136 743{\r
744 INT32 volume = SLOT->volume;\r
6d28fb50 745 UINT32 pack = SLOT->eg_pack[SLOT->state - 1];\r
746 UINT32 shift = pack >> 24;\r
747 INT32 eg_inc_val;\r
cc68a136 748\r
6d28fb50 749 if (eg_cnt & ((1 << shift) - 1))\r
750 return;\r
cc68a136 751\r
6d28fb50 752 eg_inc_val = pack >> ((eg_cnt >> shift) & 7) * 3;\r
753 eg_inc_val = (1 << (eg_inc_val & 7)) >> 1;\r
cc68a136 754\r
6d28fb50 755 switch (SLOT->state)\r
756 {\r
757 case EG_ATT: /* attack phase */\r
758 volume += ( ~volume * eg_inc_val ) >> 4;\r
759 if ( volume <= MIN_ATT_INDEX )\r
cc68a136 760 {\r
6d28fb50 761 volume = MIN_ATT_INDEX;\r
762 SLOT->state = EG_DEC;\r
cc68a136 763 }\r
6d28fb50 764 break;\r
cc68a136 765\r
6d28fb50 766 case EG_DEC: /* decay phase */\r
767 volume += eg_inc_val;\r
768 if ( volume >= (INT32) SLOT->sl )\r
769 SLOT->state = EG_SUS;\r
770 break;\r
cc68a136 771\r
6d28fb50 772 case EG_SUS: /* sustain phase */\r
773 volume += eg_inc_val;\r
774 if ( volume >= MAX_ATT_INDEX )\r
775 {\r
776 volume = MAX_ATT_INDEX;\r
777 /* do not change SLOT->state (verified on real chip) */\r
cc68a136 778 }\r
6d28fb50 779 break;\r
cc68a136 780\r
6d28fb50 781 case EG_REL: /* release phase */\r
782 volume += eg_inc_val;\r
783 if ( volume >= MAX_ATT_INDEX )\r
cc68a136 784 {\r
6d28fb50 785 volume = MAX_ATT_INDEX;\r
786 SLOT->state = EG_OFF;\r
cc68a136 787 }\r
6d28fb50 788 break;\r
cc68a136 789 }\r
790\r
791 SLOT->volume = volume;\r
6d28fb50 792 *vol_out = SLOT->tl + volume; /* tl is 7bit<<3, volume 0-1023 (0-2039 total) */\r
cc68a136 793}\r
794#endif\r
795\r
796\r
797typedef struct\r
798{\r
799 UINT16 vol_out1; /* 00: current output from EG circuit (without AM from LFO) */\r
800 UINT16 vol_out2;\r
801 UINT16 vol_out3;\r
802 UINT16 vol_out4;\r
803 UINT32 pad[2];\r
804 UINT32 phase1; /* 10 */\r
805 UINT32 phase2;\r
806 UINT32 phase3;\r
807 UINT32 phase4;\r
808 UINT32 incr1; /* 20: phase step */\r
809 UINT32 incr2;\r
810 UINT32 incr3;\r
811 UINT32 incr4;\r
812 UINT32 lfo_cnt; /* 30 */\r
813 UINT32 lfo_inc;\r
814 INT32 mem; /* one sample delay memory */\r
815 UINT32 eg_cnt; /* envelope generator counter */\r
816 FM_CH *CH; /* 40: envelope generator counter */\r
817 UINT32 eg_timer;\r
818 UINT32 eg_timer_add;\r
819 UINT32 pack; // 4c: stereo, lastchan, disabled, lfo_enabled | pan_r, pan_l, ams[2] | AMmasks[4] | FB[4] | lfo_ampm[16]\r
85f8e929 820 UINT32 algo; /* 50: algo[3], was_update */\r
cc68a136 821 INT32 op1_out;\r
b542be46 822#ifdef _MIPS_ARCH_ALLEGREX\r
823 UINT32 pad1[3+8];\r
824#endif\r
cc68a136 825} chan_rend_context;\r
826\r
827\r
828#if !defined(_ASM_YM2612_C) || defined(EXTERNAL_YM2612)\r
829static void chan_render_loop(chan_rend_context *ct, int *buffer, int length)\r
830{\r
831 int scounter; /* sample counter */\r
832\r
833 /* sample generating loop */\r
834 for (scounter = 0; scounter < length; scounter++)\r
835 {\r
836 int smp = 0; /* produced sample */\r
837 unsigned int eg_out, eg_out2, eg_out4;\r
838\r
839 if (ct->pack & 8) { /* LFO enabled ? (test Earthworm Jim in between demo 1 and 2) */\r
840 ct->pack = (ct->pack&0xffff) | (advance_lfo(ct->pack >> 16, ct->lfo_cnt, ct->lfo_cnt + ct->lfo_inc) << 16);\r
841 ct->lfo_cnt += ct->lfo_inc;\r
842 }\r
843\r
844 ct->eg_timer += ct->eg_timer_add;\r
845 while (ct->eg_timer >= EG_TIMER_OVERFLOW)\r
846 {\r
847 ct->eg_timer -= EG_TIMER_OVERFLOW;\r
848 ct->eg_cnt++;\r
849\r
6d28fb50 850 if (ct->CH->SLOT[SLOT1].state != EG_OFF) update_eg_phase(&ct->vol_out1, &ct->CH->SLOT[SLOT1], ct->eg_cnt);\r
851 if (ct->CH->SLOT[SLOT2].state != EG_OFF) update_eg_phase(&ct->vol_out2, &ct->CH->SLOT[SLOT2], ct->eg_cnt);\r
852 if (ct->CH->SLOT[SLOT3].state != EG_OFF) update_eg_phase(&ct->vol_out3, &ct->CH->SLOT[SLOT3], ct->eg_cnt);\r
853 if (ct->CH->SLOT[SLOT4].state != EG_OFF) update_eg_phase(&ct->vol_out4, &ct->CH->SLOT[SLOT4], ct->eg_cnt);\r
cc68a136 854 }\r
855\r
856 if (ct->pack & 4) continue; /* output disabled */\r
857\r
858 /* calculate channel sample */\r
859 eg_out = ct->vol_out1;\r
860 if ( (ct->pack & 8) && (ct->pack&(1<<(SLOT1+8))) ) eg_out += ct->pack >> (((ct->pack&0xc0)>>6)+24);\r
861\r
862 if( eg_out < ENV_QUIET ) /* SLOT 1 */\r
863 {\r
864 int out = 0;\r
865\r
db49317b 866 if (ct->pack&0xf000) out = ((ct->op1_out>>16) + ((ct->op1_out<<16)>>16)) << ((ct->pack&0xf000)>>12); /* op1_out0 + op1_out1 */\r
cc68a136 867 ct->op1_out <<= 16;\r
868 ct->op1_out |= (unsigned short)op_calc1(ct->phase1, eg_out, out);\r
869 } else {\r
870 ct->op1_out <<= 16; /* op1_out0 = op1_out1; op1_out1 = 0; */\r
871 }\r
872\r
873 eg_out = ct->vol_out3; // volume_calc(&CH->SLOT[SLOT3]);\r
874 eg_out2 = ct->vol_out2; // volume_calc(&CH->SLOT[SLOT2]);\r
875 eg_out4 = ct->vol_out4; // volume_calc(&CH->SLOT[SLOT4]);\r
876\r
877 if (ct->pack & 8) {\r
878 unsigned int add = ct->pack >> (((ct->pack&0xc0)>>6)+24);\r
879 if (ct->pack & (1<<(SLOT3+8))) eg_out += add;\r
880 if (ct->pack & (1<<(SLOT2+8))) eg_out2 += add;\r
881 if (ct->pack & (1<<(SLOT4+8))) eg_out4 += add;\r
882 }\r
883\r
884 switch( ct->CH->ALGO )\r
885 {\r
cc68a136 886 case 0:\r
887 {\r
888 /* M1---C1---MEM---M2---C2---OUT */\r
889 int m2,c1,c2=0; /* Phase Modulation input for operators 2,3,4 */\r
890 m2 = ct->mem;\r
891 c1 = ct->op1_out>>16;\r
892 if( eg_out < ENV_QUIET ) { /* SLOT 3 */\r
893 c2 = op_calc(ct->phase3, eg_out, m2);\r
894 }\r
895 if( eg_out2 < ENV_QUIET ) { /* SLOT 2 */\r
896 ct->mem = op_calc(ct->phase2, eg_out2, c1);\r
897 }\r
898 else ct->mem = 0;\r
899 if( eg_out4 < ENV_QUIET ) { /* SLOT 4 */\r
900 smp = op_calc(ct->phase4, eg_out4, c2);\r
901 }\r
902 break;\r
903 }\r
904 case 1:\r
905 {\r
906 /* M1------+-MEM---M2---C2---OUT */\r
907 /* C1-+ */\r
908 int m2,c2=0;\r
909 m2 = ct->mem;\r
910 ct->mem = ct->op1_out>>16;\r
911 if( eg_out < ENV_QUIET ) { /* SLOT 3 */\r
912 c2 = op_calc(ct->phase3, eg_out, m2);\r
913 }\r
914 if( eg_out2 < ENV_QUIET ) { /* SLOT 2 */\r
915 ct->mem+= op_calc(ct->phase2, eg_out2, 0);\r
916 }\r
917 if( eg_out4 < ENV_QUIET ) { /* SLOT 4 */\r
918 smp = op_calc(ct->phase4, eg_out4, c2);\r
919 }\r
920 break;\r
921 }\r
922 case 2:\r
923 {\r
924 /* M1-----------------+-C2---OUT */\r
925 /* C1---MEM---M2-+ */\r
926 int m2,c2;\r
927 m2 = ct->mem;\r
928 c2 = ct->op1_out>>16;\r
929 if( eg_out < ENV_QUIET ) { /* SLOT 3 */\r
930 c2 += op_calc(ct->phase3, eg_out, m2);\r
931 }\r
932 if( eg_out2 < ENV_QUIET ) { /* SLOT 2 */\r
933 ct->mem = op_calc(ct->phase2, eg_out2, 0);\r
934 }\r
935 else ct->mem = 0;\r
936 if( eg_out4 < ENV_QUIET ) { /* SLOT 4 */\r
937 smp = op_calc(ct->phase4, eg_out4, c2);\r
938 }\r
939 break;\r
940 }\r
941 case 3:\r
942 {\r
943 /* M1---C1---MEM------+-C2---OUT */\r
944 /* M2-+ */\r
945 int c1,c2;\r
946 c2 = ct->mem;\r
947 c1 = ct->op1_out>>16;\r
948 if( eg_out < ENV_QUIET ) { /* SLOT 3 */\r
949 c2 += op_calc(ct->phase3, eg_out, 0);\r
950 }\r
951 if( eg_out2 < ENV_QUIET ) { /* SLOT 2 */\r
952 ct->mem = op_calc(ct->phase2, eg_out2, c1);\r
953 }\r
954 else ct->mem = 0;\r
955 if( eg_out4 < ENV_QUIET ) { /* SLOT 4 */\r
956 smp = op_calc(ct->phase4, eg_out4, c2);\r
957 }\r
958 break;\r
959 }\r
960 case 4:\r
961 {\r
962 /* M1---C1-+-OUT */\r
963 /* M2---C2-+ */\r
964 /* MEM: not used */\r
965 int c1,c2=0;\r
966 c1 = ct->op1_out>>16;\r
967 if( eg_out < ENV_QUIET ) { /* SLOT 3 */\r
968 c2 = op_calc(ct->phase3, eg_out, 0);\r
969 }\r
970 if( eg_out2 < ENV_QUIET ) { /* SLOT 2 */\r
971 smp = op_calc(ct->phase2, eg_out2, c1);\r
972 }\r
973 if( eg_out4 < ENV_QUIET ) { /* SLOT 4 */\r
974 smp+= op_calc(ct->phase4, eg_out4, c2);\r
975 }\r
976 break;\r
977 }\r
978 case 5:\r
979 {\r
980 /* +----C1----+ */\r
981 /* M1-+-MEM---M2-+-OUT */\r
982 /* +----C2----+ */\r
983 int m2,c1,c2;\r
984 m2 = ct->mem;\r
985 ct->mem = c1 = c2 = ct->op1_out>>16;\r
986 if( eg_out < ENV_QUIET ) { /* SLOT 3 */\r
987 smp = op_calc(ct->phase3, eg_out, m2);\r
988 }\r
989 if( eg_out2 < ENV_QUIET ) { /* SLOT 2 */\r
990 smp+= op_calc(ct->phase2, eg_out2, c1);\r
991 }\r
992 if( eg_out4 < ENV_QUIET ) { /* SLOT 4 */\r
993 smp+= op_calc(ct->phase4, eg_out4, c2);\r
994 }\r
995 break;\r
996 }\r
997 case 6:\r
998 {\r
999 /* M1---C1-+ */\r
1000 /* M2-+-OUT */\r
1001 /* C2-+ */\r
1002 /* MEM: not used */\r
1003 int c1;\r
1004 c1 = ct->op1_out>>16;\r
1005 if( eg_out < ENV_QUIET ) { /* SLOT 3 */\r
1006 smp = op_calc(ct->phase3, eg_out, 0);\r
1007 }\r
1008 if( eg_out2 < ENV_QUIET ) { /* SLOT 2 */\r
1009 smp+= op_calc(ct->phase2, eg_out2, c1);\r
1010 }\r
1011 if( eg_out4 < ENV_QUIET ) { /* SLOT 4 */\r
1012 smp+= op_calc(ct->phase4, eg_out4, 0);\r
1013 }\r
1014 break;\r
1015 }\r
1016 case 7:\r
1017 {\r
1018 /* M1-+ */\r
1019 /* C1-+-OUT */\r
1020 /* M2-+ */\r
1021 /* C2-+ */\r
1022 /* MEM: not used*/\r
1023 smp = ct->op1_out>>16;\r
1024 if( eg_out < ENV_QUIET ) { /* SLOT 3 */\r
1025 smp += op_calc(ct->phase3, eg_out, 0);\r
1026 }\r
1027 if( eg_out2 < ENV_QUIET ) { /* SLOT 2 */\r
1028 smp += op_calc(ct->phase2, eg_out2, 0);\r
1029 }\r
1030 if( eg_out4 < ENV_QUIET ) { /* SLOT 4 */\r
1031 smp += op_calc(ct->phase4, eg_out4, 0);\r
1032 }\r
1033 break;\r
1034 }\r
cc68a136 1035 }\r
1036 /* done calculating channel sample */\r
1037\r
1038 /* mix sample to output buffer */\r
1039 if (smp) {\r
1040 if (ct->pack & 1) { /* stereo */\r
1041 if (ct->pack & 0x20) /* L */ /* TODO: check correctness */\r
1042 buffer[scounter*2] += smp;\r
1043 if (ct->pack & 0x10) /* R */\r
1044 buffer[scounter*2+1] += smp;\r
1045 } else {\r
1046 buffer[scounter] += smp;\r
1047 }\r
6d28fb50 1048 ct->algo |= 8;\r
cc68a136 1049 }\r
1050\r
1051 /* update phase counters AFTER output calculations */\r
1052 ct->phase1 += ct->incr1;\r
1053 ct->phase2 += ct->incr2;\r
1054 ct->phase3 += ct->incr3;\r
1055 ct->phase4 += ct->incr4;\r
1056 }\r
1057}\r
1058#else\r
1059void chan_render_loop(chan_rend_context *ct, int *buffer, unsigned short length);\r
1060#endif\r
1061\r
dca310c4 1062static chan_rend_context crct;\r
cc68a136 1063\r
d2721b08 1064static void chan_render_prep(void)\r
1065{\r
1066 crct.eg_timer_add = ym2612.OPN.eg_timer_add;\r
1067 crct.lfo_inc = ym2612.OPN.lfo_inc;\r
1068}\r
1069\r
1070static void chan_render_finish(void)\r
1071{\r
1072 ym2612.OPN.eg_cnt = crct.eg_cnt;\r
1073 ym2612.OPN.eg_timer = crct.eg_timer;\r
1074 g_lfo_ampm = crct.pack >> 16; // need_save\r
1075 ym2612.OPN.lfo_cnt = crct.lfo_cnt;\r
1076}\r
1077\r
b542be46 1078static int chan_render(int *buffer, int length, int c, UINT32 flags) // flags: stereo, ?, disabled, ?, pan_r, pan_l\r
cc68a136 1079{\r
b542be46 1080 crct.CH = &ym2612.CH[c];\r
1081 crct.mem = crct.CH->mem_value; /* one sample delay memory */\r
1082 crct.lfo_cnt = ym2612.OPN.lfo_cnt;\r
cc68a136 1083\r
b542be46 1084 flags &= 0x35;\r
cc68a136 1085\r
b542be46 1086 if (crct.lfo_inc) {\r
cc68a136 1087 flags |= 8;\r
1088 flags |= g_lfo_ampm << 16;\r
b542be46 1089 flags |= crct.CH->AMmasks << 8;\r
1090 if (crct.CH->ams == 8) // no ams\r
1091 flags &= ~0xf00;\r
1092 else flags |= (crct.CH->ams&3)<<6;\r
cc68a136 1093 }\r
b542be46 1094 flags |= (crct.CH->FB&0xf)<<12; /* feedback shift */\r
1095 crct.pack = flags;\r
cc68a136 1096\r
b542be46 1097 crct.eg_cnt = ym2612.OPN.eg_cnt; /* envelope generator counter */\r
1098 crct.eg_timer = ym2612.OPN.eg_timer;\r
cc68a136 1099\r
1100 /* precalculate phase modulation incr */\r
b542be46 1101 crct.phase1 = crct.CH->SLOT[SLOT1].phase;\r
1102 crct.phase2 = crct.CH->SLOT[SLOT2].phase;\r
1103 crct.phase3 = crct.CH->SLOT[SLOT3].phase;\r
1104 crct.phase4 = crct.CH->SLOT[SLOT4].phase;\r
cc68a136 1105\r
1106 /* current output from EG circuit (without AM from LFO) */\r
b542be46 1107 crct.vol_out1 = crct.CH->SLOT[SLOT1].tl + ((UINT32)crct.CH->SLOT[SLOT1].volume);\r
1108 crct.vol_out2 = crct.CH->SLOT[SLOT2].tl + ((UINT32)crct.CH->SLOT[SLOT2].volume);\r
1109 crct.vol_out3 = crct.CH->SLOT[SLOT3].tl + ((UINT32)crct.CH->SLOT[SLOT3].volume);\r
1110 crct.vol_out4 = crct.CH->SLOT[SLOT4].tl + ((UINT32)crct.CH->SLOT[SLOT4].volume);\r
cc68a136 1111\r
b542be46 1112 crct.op1_out = crct.CH->op1_out;\r
1113 crct.algo = crct.CH->ALGO & 7;\r
cc68a136 1114\r
b542be46 1115 if(crct.CH->pms)\r
cc68a136 1116 {\r
1117 /* add support for 3 slot mode */\r
b542be46 1118 UINT32 block_fnum = crct.CH->block_fnum;\r
cc68a136 1119\r
1120 UINT32 fnum_lfo = ((block_fnum & 0x7f0) >> 4) * 32 * 8;\r
b542be46 1121 INT32 lfo_fn_table_index_offset = lfo_pm_table[ fnum_lfo + crct.CH->pms + ((crct.pack>>16)&0xff) ];\r
cc68a136 1122\r
1123 if (lfo_fn_table_index_offset) /* LFO phase modulation active */\r
1124 {\r
1125 UINT8 blk;\r
1126 UINT32 fn;\r
1127 int kc,fc;\r
1128\r
eaa9417a 1129 blk = block_fnum >> 11;\r
cc68a136 1130 block_fnum = block_fnum*2 + lfo_fn_table_index_offset;\r
1131\r
cc68a136 1132 fn = block_fnum & 0xfff;\r
1133\r
1134 /* keyscale code */\r
1135 kc = (blk<<2) | opn_fktable[fn >> 8];\r
1136 /* phase increment counter */\r
1137 fc = fn_table[fn]>>(7-blk);\r
1138\r
b542be46 1139 crct.incr1 = ((fc+crct.CH->SLOT[SLOT1].DT[kc])*crct.CH->SLOT[SLOT1].mul) >> 1;\r
1140 crct.incr2 = ((fc+crct.CH->SLOT[SLOT2].DT[kc])*crct.CH->SLOT[SLOT2].mul) >> 1;\r
1141 crct.incr3 = ((fc+crct.CH->SLOT[SLOT3].DT[kc])*crct.CH->SLOT[SLOT3].mul) >> 1;\r
1142 crct.incr4 = ((fc+crct.CH->SLOT[SLOT4].DT[kc])*crct.CH->SLOT[SLOT4].mul) >> 1;\r
cc68a136 1143 }\r
1144 else /* LFO phase modulation = zero */\r
1145 {\r
b542be46 1146 crct.incr1 = crct.CH->SLOT[SLOT1].Incr;\r
1147 crct.incr2 = crct.CH->SLOT[SLOT2].Incr;\r
1148 crct.incr3 = crct.CH->SLOT[SLOT3].Incr;\r
1149 crct.incr4 = crct.CH->SLOT[SLOT4].Incr;\r
cc68a136 1150 }\r
1151 }\r
1152 else /* no LFO phase modulation */\r
1153 {\r
b542be46 1154 crct.incr1 = crct.CH->SLOT[SLOT1].Incr;\r
1155 crct.incr2 = crct.CH->SLOT[SLOT2].Incr;\r
1156 crct.incr3 = crct.CH->SLOT[SLOT3].Incr;\r
1157 crct.incr4 = crct.CH->SLOT[SLOT4].Incr;\r
cc68a136 1158 }\r
1159\r
b542be46 1160 chan_render_loop(&crct, buffer, length);\r
cc68a136 1161\r
b542be46 1162 crct.CH->op1_out = crct.op1_out;\r
1163 crct.CH->mem_value = crct.mem;\r
1164 if (crct.CH->SLOT[SLOT1].state | crct.CH->SLOT[SLOT2].state | crct.CH->SLOT[SLOT3].state | crct.CH->SLOT[SLOT4].state)\r
1165 {\r
1166 crct.CH->SLOT[SLOT1].phase = crct.phase1;\r
1167 crct.CH->SLOT[SLOT2].phase = crct.phase2;\r
1168 crct.CH->SLOT[SLOT3].phase = crct.phase3;\r
1169 crct.CH->SLOT[SLOT4].phase = crct.phase4;\r
cc68a136 1170 }\r
b542be46 1171 else\r
1172 ym2612.slot_mask &= ~(0xf << (c*4));\r
cc68a136 1173\r
b542be46 1174 return (crct.algo & 8) >> 3; // had output\r
cc68a136 1175}\r
1176\r
1177/* update phase increment and envelope generator */\r
1178INLINE void refresh_fc_eg_slot(FM_SLOT *SLOT, int fc, int kc)\r
1179{\r
eaa9417a 1180 int ksr, fdt;\r
cc68a136 1181\r
1182 /* (frequency) phase increment counter */\r
eaa9417a 1183 fdt = fc+SLOT->DT[kc];\r
1184 /* detect overflow */\r
1185// if (fdt < 0) fdt += fn_table[0x7ff*2] >> (7-blk-1);\r
1186 if (fdt < 0) fdt += fn_table[0x7ff*2] >> 2;\r
1187 SLOT->Incr = fdt*SLOT->mul >> 1;\r
cc68a136 1188\r
1189 ksr = kc >> SLOT->KSR;\r
1190 if( SLOT->ksr != ksr )\r
1191 {\r
1192 int eg_sh, eg_sel;\r
1193 SLOT->ksr = ksr;\r
1194\r
1195 /* calculate envelope generator rates */\r
d2721b08 1196 if ((SLOT->ar + ksr) < 32+62)\r
cc68a136 1197 {\r
d2721b08 1198 eg_sh = eg_rate_shift [SLOT->ar + ksr ];\r
1199 eg_sel = eg_rate_select[SLOT->ar + ksr ];\r
cc68a136 1200 }\r
1201 else\r
1202 {\r
1203 eg_sh = 0;\r
1204 eg_sel = 17;\r
1205 }\r
1206\r
1207 SLOT->eg_pack_ar = eg_inc_pack[eg_sel] | (eg_sh<<24);\r
1208\r
d2721b08 1209 eg_sh = eg_rate_shift [SLOT->d1r + ksr];\r
1210 eg_sel = eg_rate_select[SLOT->d1r + ksr];\r
cc68a136 1211\r
1212 SLOT->eg_pack_d1r = eg_inc_pack[eg_sel] | (eg_sh<<24);\r
1213\r
d2721b08 1214 eg_sh = eg_rate_shift [SLOT->d2r + ksr];\r
1215 eg_sel = eg_rate_select[SLOT->d2r + ksr];\r
cc68a136 1216\r
1217 SLOT->eg_pack_d2r = eg_inc_pack[eg_sel] | (eg_sh<<24);\r
1218\r
d2721b08 1219 eg_sh = eg_rate_shift [SLOT->rr + ksr];\r
1220 eg_sel = eg_rate_select[SLOT->rr + ksr];\r
cc68a136 1221\r
1222 SLOT->eg_pack_rr = eg_inc_pack[eg_sel] | (eg_sh<<24);\r
1223 }\r
1224}\r
1225\r
1226/* update phase increment counters */\r
1227INLINE void refresh_fc_eg_chan(FM_CH *CH)\r
1228{\r
1229 if( CH->SLOT[SLOT1].Incr==-1){\r
1230 int fc = CH->fc;\r
1231 int kc = CH->kcode;\r
1232 refresh_fc_eg_slot(&CH->SLOT[SLOT1] , fc , kc );\r
1233 refresh_fc_eg_slot(&CH->SLOT[SLOT2] , fc , kc );\r
1234 refresh_fc_eg_slot(&CH->SLOT[SLOT3] , fc , kc );\r
1235 refresh_fc_eg_slot(&CH->SLOT[SLOT4] , fc , kc );\r
1236 }\r
1237}\r
1238\r
eaa9417a 1239INLINE void refresh_fc_eg_chan_sl3(void)\r
1240{\r
1241 if( ym2612.CH[2].SLOT[SLOT1].Incr==-1)\r
1242 {\r
1243 refresh_fc_eg_slot(&ym2612.CH[2].SLOT[SLOT1], ym2612.OPN.SL3.fc[1], ym2612.OPN.SL3.kcode[1] );\r
1244 refresh_fc_eg_slot(&ym2612.CH[2].SLOT[SLOT2], ym2612.OPN.SL3.fc[2], ym2612.OPN.SL3.kcode[2] );\r
1245 refresh_fc_eg_slot(&ym2612.CH[2].SLOT[SLOT3], ym2612.OPN.SL3.fc[0], ym2612.OPN.SL3.kcode[0] );\r
1246 refresh_fc_eg_slot(&ym2612.CH[2].SLOT[SLOT4], ym2612.CH[2].fc , ym2612.CH[2].kcode );\r
1247 }\r
1248}\r
1249\r
cc68a136 1250/* initialize time tables */\r
1251static void init_timetables(const UINT8 *dttable)\r
1252{\r
1253 int i,d;\r
1254 double rate;\r
1255\r
1256 /* DeTune table */\r
1257 for (d = 0;d <= 3;d++){\r
1258 for (i = 0;i <= 31;i++){\r
1259 rate = ((double)dttable[d*32 + i]) * SIN_LEN * ym2612.OPN.ST.freqbase * (1<<FREQ_SH) / ((double)(1<<20));\r
1260 ym2612.OPN.ST.dt_tab[d][i] = (INT32) rate;\r
1261 ym2612.OPN.ST.dt_tab[d+4][i] = -ym2612.OPN.ST.dt_tab[d][i];\r
1262 }\r
1263 }\r
1264}\r
1265\r
1266\r
b542be46 1267static void reset_channels(FM_CH *CH)\r
cc68a136 1268{\r
1269 int c,s;\r
1270\r
1271 ym2612.OPN.ST.mode = 0; /* normal mode */\r
1272 ym2612.OPN.ST.TA = 0;\r
1273 ym2612.OPN.ST.TAC = 0;\r
1274 ym2612.OPN.ST.TB = 0;\r
1275 ym2612.OPN.ST.TBC = 0;\r
1276\r
b542be46 1277 for( c = 0 ; c < 6 ; c++ )\r
cc68a136 1278 {\r
1279 CH[c].fc = 0;\r
1280 for(s = 0 ; s < 4 ; s++ )\r
1281 {\r
1282 CH[c].SLOT[s].state= EG_OFF;\r
1283 CH[c].SLOT[s].volume = MAX_ATT_INDEX;\r
1284 }\r
db49317b 1285 CH[c].mem_value = CH[c].op1_out = 0;\r
cc68a136 1286 }\r
b542be46 1287 ym2612.slot_mask = 0;\r
cc68a136 1288}\r
1289\r
1290/* initialize generic tables */\r
1291static void init_tables(void)\r
1292{\r
1293 signed int i,x,y,p;\r
1294 signed int n;\r
1295 double o,m;\r
1296\r
1297 for (i=0; i < 256; i++)\r
1298 {\r
1299 /* non-standard sinus */\r
1300 m = sin( ((i*2)+1) * M_PI / SIN_LEN ); /* checked against the real chip */\r
1301\r
1302 /* we never reach zero here due to ((i*2)+1) */\r
1303\r
1304 if (m>0.0)\r
1305 o = 8*log(1.0/m)/log(2); /* convert to 'decibels' */\r
1306 else\r
1307 o = 8*log(-1.0/m)/log(2); /* convert to 'decibels' */\r
1308\r
1309 o = o / (ENV_STEP/4);\r
1310\r
1311 n = (int)(2.0*o);\r
1312 if (n&1) /* round to nearest */\r
1313 n = (n>>1)+1;\r
1314 else\r
1315 n = n>>1;\r
1316\r
1317 ym_sin_tab[ i ] = n;\r
1318 //dprintf("FM.C: sin [%4i]= %4i", i, ym_sin_tab[i]);\r
1319 }\r
1320\r
1321 //dprintf("FM.C: ENV_QUIET= %08x", ENV_QUIET );\r
1322\r
1323\r
1324 for (x=0; x < TL_RES_LEN; x++)\r
1325 {\r
1326 m = (1<<16) / pow(2, (x+1) * (ENV_STEP/4.0) / 8.0);\r
1327 m = floor(m);\r
1328\r
1329 /* we never reach (1<<16) here due to the (x+1) */\r
1330 /* result fits within 16 bits at maximum */\r
1331\r
1332 n = (int)m; /* 16 bits here */\r
1333 n >>= 4; /* 12 bits here */\r
1334 if (n&1) /* round to nearest */\r
1335 n = (n>>1)+1;\r
1336 else\r
1337 n = n>>1;\r
1338 /* 11 bits here (rounded) */\r
1339 n <<= 2; /* 13 bits here (as in real chip) */\r
1340 ym_tl_tab2[ x ] = n;\r
1341\r
1342 for (i=1; i < 13; i++)\r
1343 {\r
1344 ym_tl_tab2[ x + i*TL_RES_LEN ] = n >> i;\r
1345 }\r
1346 }\r
1347\r
1348 for (x=0; x < 256; x++)\r
1349 {\r
1350 int sin = ym_sin_tab[ x ];\r
1351\r
1352 for (y=0; y < 2*13*TL_RES_LEN/8; y+=2)\r
1353 {\r
1354 p = (y<<2) + sin;\r
1355 if (p >= 13*TL_RES_LEN)\r
1356 ym_tl_tab[(y<<7) | x] = 0;\r
1357 else ym_tl_tab[(y<<7) | x] = ym_tl_tab2[p];\r
1358 }\r
1359 }\r
1360\r
1361\r
1362 /* build LFO PM modulation table */\r
1363 for(i = 0; i < 8; i++) /* 8 PM depths */\r
1364 {\r
1365 UINT8 fnum;\r
1366 for (fnum=0; fnum<128; fnum++) /* 7 bits meaningful of F-NUMBER */\r
1367 {\r
1368 UINT8 value;\r
1369 UINT8 step;\r
1370 UINT32 offset_depth = i;\r
1371 UINT32 offset_fnum_bit;\r
1372 UINT32 bit_tmp;\r
1373\r
1374 for (step=0; step<8; step++)\r
1375 {\r
1376 value = 0;\r
1377 for (bit_tmp=0; bit_tmp<7; bit_tmp++) /* 7 bits */\r
1378 {\r
1379 if (fnum & (1<<bit_tmp)) /* only if bit "bit_tmp" is set */\r
1380 {\r
1381 offset_fnum_bit = bit_tmp * 8;\r
1382 value += lfo_pm_output[offset_fnum_bit + offset_depth][step];\r
1383 }\r
1384 }\r
1385 lfo_pm_table[(fnum*32*8) + (i*32) + step + 0] = value;\r
1386 lfo_pm_table[(fnum*32*8) + (i*32) +(step^7)+ 8] = value;\r
1387 lfo_pm_table[(fnum*32*8) + (i*32) + step +16] = -value;\r
1388 lfo_pm_table[(fnum*32*8) + (i*32) +(step^7)+24] = -value;\r
1389 }\r
1390 }\r
1391 }\r
1392}\r
1393\r
1394\r
1395/* CSM Key Controll */\r
b542be46 1396#if 0\r
cc68a136 1397INLINE void CSMKeyControll(FM_CH *CH)\r
1398{\r
1399 /* this is wrong, atm */\r
1400\r
1401 /* all key on */\r
1402 FM_KEYON(CH,SLOT1);\r
1403 FM_KEYON(CH,SLOT2);\r
1404 FM_KEYON(CH,SLOT3);\r
1405 FM_KEYON(CH,SLOT4);\r
1406}\r
b542be46 1407#endif\r
cc68a136 1408\r
1409\r
1410/* prescaler set (and make time tables) */\r
1411static void OPNSetPres(int pres)\r
1412{\r
1413 int i;\r
1414\r
1415 /* frequency base */\r
1416 ym2612.OPN.ST.freqbase = (ym2612.OPN.ST.rate) ? ((double)ym2612.OPN.ST.clock / ym2612.OPN.ST.rate) / pres : 0;\r
1417\r
1418 ym2612.OPN.eg_timer_add = (1<<EG_SH) * ym2612.OPN.ST.freqbase;\r
1419\r
cc68a136 1420 /* make time tables */\r
1421 init_timetables( dt_tab );\r
1422\r
1423 /* there are 2048 FNUMs that can be generated using FNUM/BLK registers\r
1424 but LFO works with one more bit of a precision so we really need 4096 elements */\r
1425 /* calculate fnumber -> increment counter table */\r
1426 for(i = 0; i < 4096; i++)\r
1427 {\r
1428 /* freq table for octave 7 */\r
1429 /* OPN phase increment counter = 20bit */\r
1430 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
1431 }\r
1432\r
1433 /* LFO freq. table */\r
1434 for(i = 0; i < 8; i++)\r
1435 {\r
1436 /* Amplitude modulation: 64 output levels (triangle waveform); 1 level lasts for one of "lfo_samples_per_step" samples */\r
1437 /* Phase modulation: one entry from lfo_pm_output lasts for one of 4 * "lfo_samples_per_step" samples */\r
1438 ym2612.OPN.lfo_freq[i] = (1.0 / lfo_samples_per_step[i]) * (1<<LFO_SH) * ym2612.OPN.ST.freqbase;\r
1439 }\r
1440}\r
1441\r
1442\r
1443/* write a OPN register (0x30-0xff) */\r
1444static int OPNWriteReg(int r, int v)\r
1445{\r
1446 int ret = 1;\r
1447 FM_CH *CH;\r
1448 FM_SLOT *SLOT;\r
1449\r
1450 UINT8 c = OPN_CHAN(r);\r
1451\r
1452 if (c == 3) return 0; /* 0xX3,0xX7,0xXB,0xXF */\r
1453\r
1454 if (r >= 0x100) c+=3;\r
1455\r
1456 CH = &ym2612.CH[c];\r
1457\r
1458 SLOT = &(CH->SLOT[OPN_SLOT(r)]);\r
1459\r
1460 switch( r & 0xf0 ) {\r
1461 case 0x30: /* DET , MUL */\r
1462 set_det_mul(CH,SLOT,v);\r
1463 break;\r
1464\r
1465 case 0x40: /* TL */\r
1466 set_tl(SLOT,v);\r
1467 break;\r
1468\r
1469 case 0x50: /* KS, AR */\r
1470 set_ar_ksr(CH,SLOT,v);\r
1471 break;\r
1472\r
db49317b 1473 case 0x60: /* bit7 = AM ENABLE, DR | depends on ksr */\r
cc68a136 1474 set_dr(SLOT,v);\r
1475 if(v&0x80) CH->AMmasks |= 1<<OPN_SLOT(r);\r
1476 else CH->AMmasks &= ~(1<<OPN_SLOT(r));\r
1477 break;\r
1478\r
db49317b 1479 case 0x70: /* SR | depends on ksr */\r
cc68a136 1480 set_sr(SLOT,v);\r
1481 break;\r
1482\r
db49317b 1483 case 0x80: /* SL, RR | depends on ksr */\r
cc68a136 1484 set_sl_rr(SLOT,v);\r
1485 break;\r
1486\r
1487 case 0x90: /* SSG-EG */\r
1488 // removed.\r
1489 ret = 0;\r
1490 break;\r
1491\r
1492 case 0xa0:\r
1493 switch( OPN_SLOT(r) ){\r
db49317b 1494 case 0: /* 0xa0-0xa2 : FNUM1 | depends on fn_h (below) */\r
cc68a136 1495 {\r
eaa9417a 1496 UINT32 fn = (((UINT32)( (CH->fn_h)&7))<<8) + v;\r
1497 UINT8 blk = CH->fn_h>>3;\r
cc68a136 1498 /* keyscale code */\r
1499 CH->kcode = (blk<<2) | opn_fktable[fn >> 7];\r
1500 /* phase increment counter */\r
1501 CH->fc = fn_table[fn*2]>>(7-blk);\r
1502\r
1503 /* store fnum in clear form for LFO PM calculations */\r
1504 CH->block_fnum = (blk<<11) | fn;\r
1505\r
1506 CH->SLOT[SLOT1].Incr=-1;\r
1507 }\r
1508 break;\r
1509 case 1: /* 0xa4-0xa6 : FNUM2,BLK */\r
eaa9417a 1510 CH->fn_h = v&0x3f;\r
cc68a136 1511 ret = 0;\r
1512 break;\r
1513 case 2: /* 0xa8-0xaa : 3CH FNUM1 */\r
1514 if(r < 0x100)\r
1515 {\r
1516 UINT32 fn = (((UINT32)(ym2612.OPN.SL3.fn_h&7))<<8) + v;\r
1517 UINT8 blk = ym2612.OPN.SL3.fn_h>>3;\r
1518 /* keyscale code */\r
1519 ym2612.OPN.SL3.kcode[c]= (blk<<2) | opn_fktable[fn >> 7];\r
1520 /* phase increment counter */\r
1521 ym2612.OPN.SL3.fc[c] = fn_table[fn*2]>>(7-blk);\r
db49317b 1522 ym2612.OPN.SL3.block_fnum[c] = (blk<<11) | fn;\r
cc68a136 1523 ym2612.CH[2].SLOT[SLOT1].Incr=-1;\r
1524 }\r
1525 break;\r
1526 case 3: /* 0xac-0xae : 3CH FNUM2,BLK */\r
1527 if(r < 0x100)\r
1528 ym2612.OPN.SL3.fn_h = v&0x3f;\r
1529 ret = 0;\r
1530 break;\r
1531 default:\r
1532 ret = 0;\r
1533 break;\r
1534 }\r
1535 break;\r
1536\r
1537 case 0xb0:\r
1538 switch( OPN_SLOT(r) ){\r
1539 case 0: /* 0xb0-0xb2 : FB,ALGO */\r
1540 {\r
1541 int feedback = (v>>3)&7;\r
1542 CH->ALGO = v&7;\r
1543 CH->FB = feedback ? feedback+6 : 0;\r
1544 }\r
1545 break;\r
1546 case 1: /* 0xb4-0xb6 : L , R , AMS , PMS (YM2612/YM2610B/YM2610/YM2608) */\r
1547 {\r
1548 int panshift = c<<1;\r
1549\r
1550 /* b0-2 PMS */\r
1551 CH->pms = (v & 7) * 32; /* CH->pms = PM depth * 32 (index in lfo_pm_table) */\r
1552\r
1553 /* b4-5 AMS */\r
1554 CH->ams = lfo_ams_depth_shift[(v>>4) & 3];\r
1555\r
1556 /* PAN : b7 = L, b6 = R */\r
1557 ym2612.OPN.pan &= ~(3<<panshift);\r
1558 ym2612.OPN.pan |= ((v & 0xc0) >> 6) << panshift; // ..LRLR\r
1559 }\r
1560 break;\r
1561 default:\r
1562 ret = 0;\r
1563 break;\r
1564 }\r
1565 break;\r
1566 default:\r
1567 ret = 0;\r
1568 break;\r
1569 }\r
1570\r
1571 return ret;\r
1572}\r
1573\r
1574\r
1575/*******************************************************************************/\r
1576/* YM2612 local section */\r
1577/*******************************************************************************/\r
1578\r
cc68a136 1579/* Generate samples for YM2612 */\r
4f265db7 1580int YM2612UpdateOne_(int *buffer, int length, int stereo, int is_buf_empty)\r
cc68a136 1581{\r
1582 int pan;\r
85f8e929 1583 int active_chs = 0;\r
4f265db7 1584\r
1585 // if !is_buf_empty, it means it has valid samples to mix with, else it may contain trash\r
1586 if (is_buf_empty) memset32(buffer, 0, length<<stereo);\r
cc68a136 1587\r
b542be46 1588/*\r
1589 {\r
1590 int c, s;\r
1591 ppp();\r
1592 for (c = 0; c < 6; c++) {\r
1593 int slr = 0, slm;\r
1594 printf("%i: ", c);\r
1595 for (s = 0; s < 4; s++) {\r
1596 if (ym2612.CH[c].SLOT[s].state != EG_OFF) slr = 1;\r
1597 printf(" %i", ym2612.CH[c].SLOT[s].state != EG_OFF);\r
1598 }\r
1599 slm = (ym2612.slot_mask&(0xf<<(c*4))) ? 1 : 0;\r
1600 printf(" | %i", slm);\r
1601 printf(" | %i\n", ym2612.CH[c].SLOT[SLOT1].Incr==-1);\r
1602 if (slr != slm) exit(1);\r
1603 }\r
1604 }\r
1605*/\r
cc68a136 1606 /* refresh PG and EG */\r
1607 refresh_fc_eg_chan( &ym2612.CH[0] );\r
1608 refresh_fc_eg_chan( &ym2612.CH[1] );\r
1609 if( (ym2612.OPN.ST.mode & 0xc0) )\r
cc68a136 1610 /* 3SLOT MODE */\r
eaa9417a 1611 refresh_fc_eg_chan_sl3();\r
1612 else\r
1613 refresh_fc_eg_chan( &ym2612.CH[2] );\r
cc68a136 1614 refresh_fc_eg_chan( &ym2612.CH[3] );\r
1615 refresh_fc_eg_chan( &ym2612.CH[4] );\r
1616 refresh_fc_eg_chan( &ym2612.CH[5] );\r
1617\r
1618 pan = ym2612.OPN.pan;\r
1619 if (stereo) stereo = 1;\r
1620\r
4f265db7 1621 /* mix to 32bit dest */\r
b542be46 1622 // flags: stereo, ?, disabled, ?, pan_r, pan_l\r
d2721b08 1623 chan_render_prep();\r
b542be46 1624 if (ym2612.slot_mask & 0x00000f) active_chs |= chan_render(buffer, length, 0, stereo|((pan&0x003)<<4)) << 0;\r
1625 if (ym2612.slot_mask & 0x0000f0) active_chs |= chan_render(buffer, length, 1, stereo|((pan&0x00c)<<2)) << 1;\r
1626 if (ym2612.slot_mask & 0x000f00) active_chs |= chan_render(buffer, length, 2, stereo|((pan&0x030) )) << 2;\r
1627 if (ym2612.slot_mask & 0x00f000) active_chs |= chan_render(buffer, length, 3, stereo|((pan&0x0c0)>>2)) << 3;\r
1628 if (ym2612.slot_mask & 0x0f0000) active_chs |= chan_render(buffer, length, 4, stereo|((pan&0x300)>>4)) << 4;\r
1629 if (ym2612.slot_mask & 0xf00000) active_chs |= chan_render(buffer, length, 5, stereo|((pan&0xc00)>>6)|(ym2612.dacen<<2)) << 5;\r
d2721b08 1630 chan_render_finish();\r
85f8e929 1631\r
1632 return active_chs; // 1 if buffer updated\r
cc68a136 1633}\r
1634\r
1635\r
1636/* initialize YM2612 emulator */\r
1637void YM2612Init_(int clock, int rate)\r
1638{\r
5f8c85be 1639 memset(&ym2612, 0, sizeof(ym2612));\r
cc68a136 1640 init_tables();\r
1641\r
1642 ym2612.OPN.ST.clock = clock;\r
1643 ym2612.OPN.ST.rate = rate;\r
1644\r
be297089 1645 OPNSetPres( 6*24 );\r
1646\r
cc68a136 1647 /* Extend handler */\r
1648 YM2612ResetChip_();\r
1649}\r
1650\r
1651\r
1652/* reset */\r
1653void YM2612ResetChip_(void)\r
1654{\r
1655 int i;\r
1656\r
5f8c85be 1657 memset(ym2612.REGS, 0, sizeof(ym2612.REGS));\r
1658\r
cc68a136 1659 set_timers( 0x30 ); /* mode 0 , timer reset */\r
5f8c85be 1660 ym2612.REGS[0x27] = 0x30;\r
cc68a136 1661\r
1662 ym2612.OPN.eg_timer = 0;\r
1663 ym2612.OPN.eg_cnt = 0;\r
1664 ym2612.OPN.ST.status = 0;\r
1665\r
b542be46 1666 reset_channels( &ym2612.CH[0] );\r
cc68a136 1667 for(i = 0xb6 ; i >= 0xb4 ; i-- )\r
1668 {\r
1669 OPNWriteReg(i ,0xc0);\r
1670 OPNWriteReg(i|0x100,0xc0);\r
5f8c85be 1671 ym2612.REGS[i ] = 0xc0;\r
1672 ym2612.REGS[i|0x100] = 0xc0;\r
cc68a136 1673 }\r
1674 for(i = 0xb2 ; i >= 0x30 ; i-- )\r
1675 {\r
1676 OPNWriteReg(i ,0);\r
1677 OPNWriteReg(i|0x100,0);\r
1678 }\r
1679 for(i = 0x26 ; i >= 0x20 ; i-- ) OPNWriteReg(i,0);\r
1680 /* DAC mode clear */\r
1681 ym2612.dacen = 0;\r
5f8c85be 1682 ym2612.addr_A1 = 0;\r
cc68a136 1683}\r
1684\r
1685\r
1686/* YM2612 write */\r
1687/* a = address */\r
1688/* v = value */\r
1689/* returns 1 if sample affecting state changed */\r
1690int YM2612Write_(unsigned int a, unsigned int v)\r
1691{\r
1692 int addr, ret=1;\r
1693\r
1694 v &= 0xff; /* adjust to 8 bit bus */\r
1695\r
1696 switch( a&3){\r
1697 case 0: /* address port 0 */\r
1698 ym2612.OPN.ST.address = v;\r
1699 ym2612.addr_A1 = 0;\r
1700 ret=0;\r
1701 break;\r
1702\r
1703 case 1: /* data port 0 */\r
1704 if (ym2612.addr_A1 != 0) {\r
1705 ret=0;\r
1706 break; /* verified on real YM2608 */\r
1707 }\r
1708\r
1709 addr = ym2612.OPN.ST.address;\r
cc68a136 1710\r
1711 switch( addr & 0xf0 )\r
1712 {\r
1713 case 0x20: /* 0x20-0x2f Mode */\r
1714 switch( addr )\r
1715 {\r
1716 case 0x22: /* LFO FREQ (YM2608/YM2610/YM2610B/YM2612) */\r
1717 if (v&0x08) /* LFO enabled ? */\r
1718 {\r
1719 ym2612.OPN.lfo_inc = ym2612.OPN.lfo_freq[v&7];\r
1720 }\r
1721 else\r
1722 {\r
1723 ym2612.OPN.lfo_inc = 0;\r
1724 }\r
1725 break;\r
4b9c5888 1726#if 0 // handled elsewhere\r
cc68a136 1727 case 0x24: { // timer A High 8\r
1728 int TAnew = (ym2612.OPN.ST.TA & 0x03)|(((int)v)<<2);\r
1729 if(ym2612.OPN.ST.TA != TAnew) {\r
1730 // we should reset ticker only if new value is written. Outrun requires this.\r
1731 ym2612.OPN.ST.TA = TAnew;\r
1732 ym2612.OPN.ST.TAC = (1024-TAnew)*18;\r
1733 ym2612.OPN.ST.TAT = 0;\r
1734 }\r
1735 }\r
1736 ret=0;\r
1737 break;\r
1738 case 0x25: { // timer A Low 2\r
1739 int TAnew = (ym2612.OPN.ST.TA & 0x3fc)|(v&3);\r
1740 if(ym2612.OPN.ST.TA != TAnew) {\r
1741 ym2612.OPN.ST.TA = TAnew;\r
1742 ym2612.OPN.ST.TAC = (1024-TAnew)*18;\r
1743 ym2612.OPN.ST.TAT = 0;\r
1744 }\r
1745 }\r
1746 ret=0;\r
1747 break;\r
1748 case 0x26: // timer B\r
1749 if(ym2612.OPN.ST.TB != v) {\r
1750 ym2612.OPN.ST.TB = v;\r
1751 ym2612.OPN.ST.TBC = (256-v)<<4;\r
1752 ym2612.OPN.ST.TBC *= 18;\r
1753 ym2612.OPN.ST.TBT = 0;\r
1754 }\r
1755 ret=0;\r
1756 break;\r
e4fb433c 1757#endif\r
cc68a136 1758 case 0x27: /* mode, timer control */\r
1759 set_timers( v );\r
1760 ret=0;\r
1761 break;\r
1762 case 0x28: /* key on / off */\r
1763 {\r
1764 UINT8 c;\r
cc68a136 1765\r
1766 c = v & 0x03;\r
1767 if( c == 3 ) { ret=0; break; }\r
1768 if( v&0x04 ) c+=3;\r
b542be46 1769 if(v&0x10) FM_KEYON(c,SLOT1); else FM_KEYOFF(c,SLOT1);\r
1770 if(v&0x20) FM_KEYON(c,SLOT2); else FM_KEYOFF(c,SLOT2);\r
1771 if(v&0x40) FM_KEYON(c,SLOT3); else FM_KEYOFF(c,SLOT3);\r
1772 if(v&0x80) FM_KEYON(c,SLOT4); else FM_KEYOFF(c,SLOT4);\r
cc68a136 1773 break;\r
1774 }\r
1775 case 0x2a: /* DAC data (YM2612) */\r
1776 ym2612.dacout = ((int)v - 0x80) << 6; /* level unknown (notaz: 8 seems to be too much) */\r
1777 ret=0;\r
1778 break;\r
1779 case 0x2b: /* DAC Sel (YM2612) */\r
1780 /* b7 = dac enable */\r
1781 ym2612.dacen = v & 0x80;\r
1782 ret=0;\r
1783 break;\r
1784 default:\r
1785 break;\r
1786 }\r
1787 break;\r
1788 default: /* 0x30-0xff OPN section */\r
1789 /* write register */\r
1790 ret = OPNWriteReg(addr,v);\r
1791 }\r
1792 break;\r
1793\r
1794 case 2: /* address port 1 */\r
1795 ym2612.OPN.ST.address = v;\r
1796 ym2612.addr_A1 = 1;\r
1797 ret=0;\r
1798 break;\r
1799\r
1800 case 3: /* data port 1 */\r
1801 if (ym2612.addr_A1 != 1) {\r
1802 ret=0;\r
1803 break; /* verified on real YM2608 */\r
1804 }\r
1805\r
1806 addr = ym2612.OPN.ST.address | 0x100;\r
cc68a136 1807\r
1808 ret = OPNWriteReg(addr, v);\r
1809 break;\r
1810 }\r
b6d7ac70 1811\r
cc68a136 1812 return ret;\r
1813}\r
1814\r
b542be46 1815#if 0\r
cc68a136 1816UINT8 YM2612Read_(void)\r
1817{\r
1818 return ym2612.OPN.ST.status;\r
1819}\r
1820\r
cc68a136 1821int YM2612PicoTick_(int n)\r
1822{\r
1823 int ret = 0;\r
1824\r
1825 // timer A\r
1826 if(ym2612.OPN.ST.mode & 0x01 && (ym2612.OPN.ST.TAT+=64*n) >= ym2612.OPN.ST.TAC) {\r
1827 ym2612.OPN.ST.TAT -= ym2612.OPN.ST.TAC;\r
1828 if(ym2612.OPN.ST.mode & 0x04) ym2612.OPN.ST.status |= 1;\r
1829 // CSM mode total level latch and auto key on\r
1830 if(ym2612.OPN.ST.mode & 0x80) {\r
1831 CSMKeyControll( &(ym2612.CH[2]) ); // Vectorman2, etc.\r
1832 ret = 1;\r
1833 }\r
1834 }\r
1835\r
1836 // timer B\r
1837 if(ym2612.OPN.ST.mode & 0x02 && (ym2612.OPN.ST.TBT+=64*n) >= ym2612.OPN.ST.TBC) {\r
1838 ym2612.OPN.ST.TBT -= ym2612.OPN.ST.TBC;\r
1839 if(ym2612.OPN.ST.mode & 0x08) ym2612.OPN.ST.status |= 2;\r
1840 }\r
1841\r
1842 return ret;\r
1843}\r
b542be46 1844#endif\r
cc68a136 1845\r
1846void YM2612PicoStateLoad_(void)\r
1847{\r
b542be46 1848 reset_channels( &ym2612.CH[0] );\r
d2721b08 1849 ym2612.slot_mask = 0xffffff;\r
1850}\r
1851\r
db49317b 1852/* rather stupid design because I wanted to fit in unused register "space" */\r
d2721b08 1853typedef struct\r
1854{\r
1855 UINT32 state_phase;\r
1856 INT16 volume;\r
1857} ym_save_addon_slot;\r
1858\r
1859typedef struct\r
1860{\r
1861 UINT32 magic;\r
1862 UINT8 address;\r
1863 UINT8 status;\r
1864 UINT8 addr_A1;\r
1865 UINT8 unused;\r
1866 int TAT;\r
1867 int TBT;\r
db49317b 1868 UINT32 eg_cnt; // 10\r
d2721b08 1869 UINT32 eg_timer;\r
1870 UINT32 lfo_cnt;\r
1871 UINT16 lfo_ampm;\r
eaa9417a 1872 UINT16 unused2;\r
db49317b 1873 UINT32 keyon_field; // 20\r
1874 UINT32 kcode_fc_sl3_3;\r
e4fb433c 1875 UINT32 reserved[2];\r
d2721b08 1876} ym_save_addon;\r
1877\r
db49317b 1878typedef struct\r
1879{\r
1880 UINT16 block_fnum[6];\r
1881 UINT16 block_fnum_sl3[3];\r
e4fb433c 1882 UINT16 reserved[7];\r
db49317b 1883} ym_save_addon2;\r
1884\r
1885\r
d2721b08 1886void YM2612PicoStateSave2(int tat, int tbt)\r
1887{\r
1888 ym_save_addon_slot ss;\r
db49317b 1889 ym_save_addon2 sa2;\r
d2721b08 1890 ym_save_addon sa;\r
1891 unsigned char *ptr;\r
1892 int c, s;\r
1893\r
db49317b 1894 memset(&sa, 0, sizeof(sa));\r
a846766f 1895 memset(&sa2, 0, sizeof(sa2));\r
db49317b 1896\r
d2721b08 1897 // chans 1,2,3\r
1898 ptr = &ym2612.REGS[0x0b8];\r
1899 for (c = 0; c < 3; c++)\r
1900 {\r
1901 for (s = 0; s < 4; s++) {\r
1902 ss.state_phase = (ym2612.CH[c].SLOT[s].state << 29) | (ym2612.CH[c].SLOT[s].phase >> 3);\r
1903 ss.volume = ym2612.CH[c].SLOT[s].volume;\r
db49317b 1904 if (ym2612.CH[c].SLOT[s].key)\r
1905 sa.keyon_field |= 1 << (c*4 + s);\r
d2721b08 1906 memcpy(ptr, &ss, 6);\r
1907 ptr += 6;\r
1908 }\r
db49317b 1909 sa2.block_fnum[c] = ym2612.CH[c].block_fnum;\r
d2721b08 1910 }\r
1911 // chans 4,5,6\r
1912 ptr = &ym2612.REGS[0x1b8];\r
1913 for (; c < 6; c++)\r
1914 {\r
1915 for (s = 0; s < 4; s++) {\r
1916 ss.state_phase = (ym2612.CH[c].SLOT[s].state << 29) | (ym2612.CH[c].SLOT[s].phase >> 3);\r
1917 ss.volume = ym2612.CH[c].SLOT[s].volume;\r
db49317b 1918 if (ym2612.CH[c].SLOT[s].key)\r
1919 sa.keyon_field |= 1 << (c*4 + s);\r
d2721b08 1920 memcpy(ptr, &ss, 6);\r
1921 ptr += 6;\r
1922 }\r
db49317b 1923 sa2.block_fnum[c] = ym2612.CH[c].block_fnum;\r
d2721b08 1924 }\r
db49317b 1925 for (c = 0; c < 3; c++)\r
1926 {\r
1927 sa2.block_fnum_sl3[c] = ym2612.OPN.SL3.block_fnum[c];\r
1928 }\r
1929\r
1930 memcpy(&ym2612.REGS[0], &sa2, sizeof(sa2)); // 0x20 max\r
1931\r
d2721b08 1932 // other things\r
1933 ptr = &ym2612.REGS[0x100];\r
1934 sa.magic = 0x41534d59; // 'YMSA'\r
1935 sa.address = ym2612.OPN.ST.address;\r
1936 sa.status = ym2612.OPN.ST.status;\r
1937 sa.addr_A1 = ym2612.addr_A1;\r
d2721b08 1938 sa.TAT = tat;\r
1939 sa.TBT = tbt;\r
1940 sa.eg_cnt = ym2612.OPN.eg_cnt;\r
1941 sa.eg_timer = ym2612.OPN.eg_timer;\r
1942 sa.lfo_cnt = ym2612.OPN.lfo_cnt;\r
1943 sa.lfo_ampm = g_lfo_ampm;\r
d2721b08 1944 memcpy(ptr, &sa, sizeof(sa)); // 0x30 max\r
1945}\r
1946\r
1947int YM2612PicoStateLoad2(int *tat, int *tbt)\r
1948{\r
1949 ym_save_addon_slot ss;\r
db49317b 1950 ym_save_addon2 sa2;\r
d2721b08 1951 ym_save_addon sa;\r
1952 unsigned char *ptr;\r
db49317b 1953 UINT32 fn;\r
1954 UINT8 blk;\r
d2721b08 1955 int c, s;\r
1956\r
1957 ptr = &ym2612.REGS[0x100];\r
1958 memcpy(&sa, ptr, sizeof(sa)); // 0x30 max\r
1959 if (sa.magic != 0x41534d59) return -1;\r
1960\r
db49317b 1961 ptr = &ym2612.REGS[0];\r
1962 memcpy(&sa2, ptr, sizeof(sa2));\r
1963\r
d2721b08 1964 ym2612.OPN.ST.address = sa.address;\r
1965 ym2612.OPN.ST.status = sa.status;\r
1966 ym2612.addr_A1 = sa.addr_A1;\r
1967 ym2612.OPN.eg_cnt = sa.eg_cnt;\r
1968 ym2612.OPN.eg_timer = sa.eg_timer;\r
1969 ym2612.OPN.lfo_cnt = sa.lfo_cnt;\r
1970 g_lfo_ampm = sa.lfo_ampm;\r
1971 if (tat != NULL) *tat = sa.TAT;\r
1972 if (tbt != NULL) *tbt = sa.TBT;\r
1973\r
1974 // chans 1,2,3\r
1975 ptr = &ym2612.REGS[0x0b8];\r
1976 for (c = 0; c < 3; c++)\r
1977 {\r
1978 for (s = 0; s < 4; s++) {\r
1979 memcpy(&ss, ptr, 6);\r
1980 ym2612.CH[c].SLOT[s].state = ss.state_phase >> 29;\r
1981 ym2612.CH[c].SLOT[s].phase = ss.state_phase << 3;\r
1982 ym2612.CH[c].SLOT[s].volume = ss.volume;\r
db49317b 1983 ym2612.CH[c].SLOT[s].key = (sa.keyon_field & (1 << (c*4 + s))) ? 1 : 0;\r
1984 ym2612.CH[c].SLOT[s].ksr = (UINT8)-1;\r
d2721b08 1985 ptr += 6;\r
1986 }\r
db49317b 1987 ym2612.CH[c].SLOT[SLOT1].Incr=-1;\r
1988 ym2612.CH[c].block_fnum = sa2.block_fnum[c];\r
1989 fn = ym2612.CH[c].block_fnum & 0x7ff;\r
1990 blk = ym2612.CH[c].block_fnum >> 11;\r
1991 ym2612.CH[c].kcode= (blk<<2) | opn_fktable[fn >> 7];\r
1992 ym2612.CH[c].fc = fn_table[fn*2]>>(7-blk);\r
d2721b08 1993 }\r
1994 // chans 4,5,6\r
1995 ptr = &ym2612.REGS[0x1b8];\r
1996 for (; c < 6; c++)\r
1997 {\r
1998 for (s = 0; s < 4; s++) {\r
1999 memcpy(&ss, ptr, 6);\r
2000 ym2612.CH[c].SLOT[s].state = ss.state_phase >> 29;\r
2001 ym2612.CH[c].SLOT[s].phase = ss.state_phase << 3;\r
2002 ym2612.CH[c].SLOT[s].volume = ss.volume;\r
db49317b 2003 ym2612.CH[c].SLOT[s].key = (sa.keyon_field & (1 << (c*4 + s))) ? 1 : 0;\r
2004 ym2612.CH[c].SLOT[s].ksr = (UINT8)-1;\r
d2721b08 2005 ptr += 6;\r
2006 }\r
db49317b 2007 ym2612.CH[c].SLOT[SLOT1].Incr=-1;\r
2008 ym2612.CH[c].block_fnum = sa2.block_fnum[c];\r
2009 fn = ym2612.CH[c].block_fnum & 0x7ff;\r
2010 blk = ym2612.CH[c].block_fnum >> 11;\r
2011 ym2612.CH[c].kcode= (blk<<2) | opn_fktable[fn >> 7];\r
2012 ym2612.CH[c].fc = fn_table[fn*2]>>(7-blk);\r
2013 }\r
2014 for (c = 0; c < 3; c++)\r
2015 {\r
2016 ym2612.OPN.SL3.block_fnum[c] = sa2.block_fnum_sl3[c];\r
2017 fn = ym2612.OPN.SL3.block_fnum[c] & 0x7ff;\r
2018 blk = ym2612.OPN.SL3.block_fnum[c] >> 11;\r
2019 ym2612.OPN.SL3.kcode[c]= (blk<<2) | opn_fktable[fn >> 7];\r
2020 ym2612.OPN.SL3.fc[c] = fn_table[fn*2]>>(7-blk);\r
d2721b08 2021 }\r
2022\r
2023 return 0;\r
cc68a136 2024}\r
2025\r
cc68a136 2026void *YM2612GetRegs(void)\r
2027{\r
2028 return ym2612.REGS;\r
2029}\r
2433f409 2030\r