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