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