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