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
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
9 ** updated with fixes from mame 0.216 (file version 1.5.1) (kub)
\r
10 ** SSG-EG readded from GenPlus (kub)
\r
15 ** File: fm.c -- software implementation of Yamaha FM sound generator
\r
17 ** Copyright (C) 2001, 2002, 2003 Jarek Burczynski (bujar at mame dot net)
\r
18 ** Copyright (C) 1998 Tatsuyuki Satoh , MultiArcadeMachineEmulator development
\r
20 ** Version 1.4 (final beta)
\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
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
37 ** 22-05-2003 Jarek Burczynski:
\r
38 ** - fixed LFO PM calculations (copy&paste bugfix)
\r
40 ** 08-05-2003 Jarek Burczynski:
\r
41 ** - fixed SSG support
\r
43 ** 22-04-2003 Jarek Burczynski:
\r
44 ** - implemented 100% correct LFO generator (verified on real YM2610 and YM2608)
\r
46 ** 15-04-2003 Jarek Burczynski:
\r
47 ** - added support for YM2608's register 0x110 - status mask
\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
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
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
64 ** 18-12-2001 Jarek Burczynski:
\r
65 ** - added SSG-EG support (verified on real YM2203)
\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
79 ** 23-07-2001 Jarek Burczynski, Nicola Salmoria:
\r
80 ** - corrected YM2610 ADPCM type A algorithm and tables (verified on real chip)
\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
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
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
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
112 //#include <stdio.h>
\r
114 #include <assert.h>
\r
115 #include <string.h>
\r
118 #include "../pico_int.h"
\r
119 #include "ym2612.h"
\r
121 #ifndef EXTERNAL_YM2612
\r
122 #include <stdlib.h>
\r
123 // let it be 1 global to simplify things
\r
127 extern YM2612 *ym2612_940;
\r
128 #define ym2612 (*ym2612_940)
\r
132 void memset32(void *dest, int c, int count);
\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
144 #define INLINE __inline
\r
148 #define M_PI 3.14159265358979323846
\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
158 #define ENV_BITS 10
\r
159 #define ENV_LEN (1<<ENV_BITS)
\r
160 #define ENV_STEP (128.0/ENV_LEN)
\r
162 #define MAX_ATT_INDEX (ENV_LEN-1) /* 1023 */
\r
163 #define MIN_ATT_INDEX (0) /* 0 */
\r
171 #define SIN_BITS 10
\r
172 #define SIN_LEN (1<<SIN_BITS)
\r
173 #define SIN_MASK (SIN_LEN-1)
\r
175 #define TL_RES_LEN (256) /* 8 bits addressing (real chip) */
\r
177 #define EG_TIMER_OVERFLOW (3*(1<<EG_SH)) /* envelope generator timer overflows every 3 samples (on real chip) */
\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
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
186 UINT16 ym_tl_tab[TL_TAB_LEN];
\r
188 /* ~3K wasted but oh well */
\r
189 UINT16 ym_tl_tab2[13*TL_RES_LEN];
\r
191 #define ENV_QUIET (2*13*TL_RES_LEN/8)
\r
193 /* sin waveform table in 'decibel' scale (use only period/4 values) */
\r
194 static UINT16 ym_sin_tab[256];
\r
196 static int ym_init_tab;
\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
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
205 static 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
213 #define RATE_STEPS (8)
\r
214 static const UINT8 eg_inc[19*RATE_STEPS]={
\r
216 /*cycle:0 1 2 3 4 5 6 7*/
\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
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
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
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
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
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
246 static const UINT32 eg_inc_pack[19] =
\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
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
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
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
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
274 //#define O(a) (a*RATE_STEPS)
\r
277 /*note that there is no O(17) in this table - it's directly in the code */
\r
278 static const UINT8 eg_rate_select[32+64+32]={ /* Envelope Generator rates (32 + 64 rates + 32 RKS) */
\r
279 /* 32 infinite time rates */
\r
280 O(18),O(18),O(18),O(18),O(18),O(18),O(18),O(18),
\r
281 O(18),O(18),O(18),O(18),O(18),O(18),O(18),O(18),
\r
282 O(18),O(18),O(18),O(18),O(18),O(18),O(18),O(18),
\r
283 O(18),O(18),O(18),O(18),O(18),O(18),O(18),O(18),
\r
286 O(18),O(18),O( 2),O( 3),
\r
287 O( 0),O( 1),O( 2),O( 3),
\r
288 O( 0),O( 1),O( 2),O( 3),
\r
289 O( 0),O( 1),O( 2),O( 3),
\r
290 O( 0),O( 1),O( 2),O( 3),
\r
291 O( 0),O( 1),O( 2),O( 3),
\r
292 O( 0),O( 1),O( 2),O( 3),
\r
293 O( 0),O( 1),O( 2),O( 3),
\r
294 O( 0),O( 1),O( 2),O( 3),
\r
295 O( 0),O( 1),O( 2),O( 3),
\r
296 O( 0),O( 1),O( 2),O( 3),
\r
297 O( 0),O( 1),O( 2),O( 3),
\r
300 O( 4),O( 5),O( 6),O( 7),
\r
303 O( 8),O( 9),O(10),O(11),
\r
306 O(12),O(13),O(14),O(15),
\r
309 O(16),O(16),O(16),O(16),
\r
311 /* 32 dummy rates (same as 15 3) */
\r
312 O(16),O(16),O(16),O(16),O(16),O(16),O(16),O(16),
\r
313 O(16),O(16),O(16),O(16),O(16),O(16),O(16),O(16),
\r
314 O(16),O(16),O(16),O(16),O(16),O(16),O(16),O(16),
\r
315 O(16),O(16),O(16),O(16),O(16),O(16),O(16),O(16)
\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
325 static const UINT8 eg_rate_shift[32+64+32]={ /* Envelope Generator counter shifts (32 + 64 rates + 32 RKS) */
\r
326 /* 32 infinite time rates */
\r
327 O(11),O(11),O(11),O(11),O(11),O(11),O(11),O(11),
\r
328 O(11),O(11),O(11),O(11),O(11),O(11),O(11),O(11),
\r
329 O(11),O(11),O(11),O(11),O(11),O(11),O(11),O(11),
\r
330 O(11),O(11),O(11),O(11),O(11),O(11),O(11),O(11),
\r
333 O(11),O(11),O(11),O(11),
\r
334 O(10),O(10),O(10),O(10),
\r
335 O( 9),O( 9),O( 9),O( 9),
\r
336 O( 8),O( 8),O( 8),O( 8),
\r
337 O( 7),O( 7),O( 7),O( 7),
\r
338 O( 6),O( 6),O( 6),O( 6),
\r
339 O( 5),O( 5),O( 5),O( 5),
\r
340 O( 4),O( 4),O( 4),O( 4),
\r
341 O( 3),O( 3),O( 3),O( 3),
\r
342 O( 2),O( 2),O( 2),O( 2),
\r
343 O( 1),O( 1),O( 1),O( 1),
\r
344 O( 0),O( 0),O( 0),O( 0),
\r
347 O( 0),O( 0),O( 0),O( 0),
\r
350 O( 0),O( 0),O( 0),O( 0),
\r
353 O( 0),O( 0),O( 0),O( 0),
\r
356 O( 0),O( 0),O( 0),O( 0),
\r
358 /* 32 dummy rates (same as 15 3) */
\r
359 O( 0),O( 0),O( 0),O( 0),O( 0),O( 0),O( 0),O( 0),
\r
360 O( 0),O( 0),O( 0),O( 0),O( 0),O( 0),O( 0),O( 0),
\r
361 O( 0),O( 0),O( 0),O( 0),O( 0),O( 0),O( 0),O( 0),
\r
362 O( 0),O( 0),O( 0),O( 0),O( 0),O( 0),O( 0),O( 0)
\r
367 static const UINT8 dt_tab[4 * 32]={
\r
368 /* this is YM2151 and YM2612 phase increment data (in 10.10 fixed point format)*/
\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
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
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
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
384 /* OPN key frequency number -> key code follow table */
\r
385 /* fnum higher 4bit -> keycode lower 2bit */
\r
386 static const UINT8 opn_fktable[16] = {0,0,0,0,0,0,0,1,2,3,3,3,3,3,3,3};
\r
389 /* 8 LFO speed parameters */
\r
390 /* each value represents number of samples that one LFO level will last for */
\r
391 static const UINT32 lfo_samples_per_step[8] = {108, 77, 71, 67, 62, 44, 8, 5};
\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
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
403 (1.4 dB is loosing precision as you can see)
\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
412 static const UINT8 lfo_ams_depth_shift[4] = {8, 3, 1, 0};
\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
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
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
426 One value in table below represents 4 (four) basic LFO steps
\r
427 (1 PM step = 4 AM steps).
\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
436 static 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
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
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
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
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
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
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
509 /* all 128 LFO PM waveforms */
\r
510 static 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
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
514 static UINT32 fn_table[4096]; /* fnumber->increment counter */
\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
527 /* OPN Mode Register Write */
\r
528 static INLINE void set_timers( int v )
\r
530 /* b7 = CSM MODE */
\r
531 /* b6 = 3 slot mode */
\r
534 /* b3 = timer enable b */
\r
535 /* b2 = timer enable a */
\r
538 ym2612.OPN.ST.mode = v;
\r
540 /* reset Timer b flag */
\r
542 ym2612.OPN.ST.status &= ~2;
\r
544 /* reset Timer a flag */
\r
546 ym2612.OPN.ST.status &= ~1;
\r
549 static INLINE void recalc_volout(FM_SLOT *SLOT)
\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
557 static INLINE void FM_KEYON(int c , int s )
\r
559 FM_SLOT *SLOT = &ym2612.CH[c].SLOT[s];
\r
563 SLOT->phase = 0; /* restart Phase Generator */
\r
564 SLOT->ssg ^= SLOT->ssgn;
\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
570 SLOT->volume = MIN_ATT_INDEX;
\r
572 recalc_volout(SLOT);
\r
573 ym2612.slot_mask |= (1<<s) << (c*4);
\r
577 static INLINE void FM_KEYOFF(int c , int s )
\r
579 FM_SLOT *SLOT = &ym2612.CH[c].SLOT[s];
\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
594 SLOT->vol_out = SLOT->volume + SLOT->tl;
\r
599 /* set detune & multiple */
\r
600 static INLINE void set_det_mul(FM_CH *CH, FM_SLOT *SLOT, int v)
\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
607 /* set total level */
\r
608 static INLINE void set_tl(FM_SLOT *SLOT, int v)
\r
610 SLOT->tl = (v&0x7f)<<(ENV_BITS-7); /* 7bit TL */
\r
611 if (SLOT->state > EG_REL)
\r
612 recalc_volout(SLOT);
\r
615 /* set attack rate & key scale */
\r
616 static INLINE void set_ar_ksr(FM_CH *CH, FM_SLOT *SLOT, int v)
\r
618 UINT8 old_KSR = SLOT->KSR;
\r
619 int eg_sh_ar, eg_sel_ar;
\r
621 SLOT->ar = (v&0x1f) ? 32 + ((v&0x1f)<<1) : 0;
\r
622 SLOT->ar_ksr = SLOT->ar + SLOT->ksr;
\r
624 SLOT->KSR = 3-(v>>6);
\r
625 if (SLOT->KSR != old_KSR)
\r
627 CH->SLOT[SLOT1].Incr=-1;
\r
630 /* refresh Attack rate */
\r
631 if ((SLOT->ar_ksr) < 32+62)
\r
633 eg_sh_ar = eg_rate_shift [SLOT->ar_ksr];
\r
634 eg_sel_ar = eg_rate_select[SLOT->ar_ksr];
\r
642 SLOT->eg_pack_ar = eg_inc_pack[eg_sel_ar] | (eg_sh_ar<<24);
\r
645 /* set decay rate */
\r
646 static INLINE void set_dr(FM_SLOT *SLOT, int v)
\r
648 int eg_sh_d1r, eg_sel_d1r;
\r
650 SLOT->d1r = (v&0x1f) ? 32 + ((v&0x1f)<<1) : 0;
\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
655 SLOT->eg_pack_d1r = eg_inc_pack[eg_sel_d1r] | (eg_sh_d1r<<24);
\r
658 /* set sustain rate */
\r
659 static INLINE void set_sr(FM_SLOT *SLOT, int v)
\r
661 int eg_sh_d2r, eg_sel_d2r;
\r
663 SLOT->d2r = (v&0x1f) ? 32 + ((v&0x1f)<<1) : 0;
\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
668 SLOT->eg_pack_d2r = eg_inc_pack[eg_sel_d2r] | (eg_sh_d2r<<24);
\r
671 /* set release rate */
\r
672 static INLINE void set_sl_rr(FM_SLOT *SLOT, int v)
\r
674 int eg_sh_rr, eg_sel_rr;
\r
676 SLOT->sl = sl_table[ v>>4 ];
\r
678 if (SLOT->state == EG_DEC && (SLOT->volume >= (INT32)(SLOT->sl)))
\r
679 SLOT->state = EG_SUS;
\r
681 SLOT->rr = 34 + ((v&0x0f)<<2);
\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
686 SLOT->eg_pack_rr = eg_inc_pack[eg_sel_rr] | (eg_sh_rr<<24);
\r
691 static INLINE signed int op_calc(UINT32 phase, unsigned int env, signed int pm)
\r
693 int ret, sin = (phase>>16) + (pm>>1);
\r
694 int neg = sin & 0x200;
\r
695 if (sin & 0x100) sin ^= 0xff;
\r
699 // this was already checked
\r
700 // if (env >= ENV_QUIET) // 384
\r
703 ret = ym_tl_tab[sin | (env<<7)];
\r
705 return neg ? -ret : ret;
\r
708 static INLINE signed int op_calc1(UINT32 phase, unsigned int env, signed int pm)
\r
710 int ret, sin = (phase+pm)>>16;
\r
711 int neg = sin & 0x200;
\r
712 if (sin & 0x100) sin ^= 0xff;
\r
716 // if (env >= ENV_QUIET) // 384
\r
719 ret = ym_tl_tab[sin | (env<<7)];
\r
721 return neg ? -ret : ret;
\r
724 #if !defined(_ASM_YM2612_C) || defined(EXTERNAL_YM2612)
\r
725 /* advance LFO to next sample */
\r
726 static INLINE int advance_lfo(int lfo_ampm, UINT32 lfo_cnt_old, UINT32 lfo_cnt)
\r
731 prev_pos = (lfo_cnt_old >> LFO_SH) & 127;
\r
733 pos = (lfo_cnt >> LFO_SH) & 127;
\r
735 /* update AM when LFO output changes */
\r
737 if (prev_pos != pos)
\r
740 /* triangle (inverted) */
\r
741 /* AM: 0 to 126 step +2, 126 to 0 step -2 */
\r
743 lfo_ampm |= ((pos^63) * 2) << 8; /* 0 - 126 */
\r
745 lfo_ampm |= ((pos&63) * 2) << 8;
\r
752 /* PM works with 4 times slower clock */
\r
755 /* update PM when LFO output changes */
\r
756 if (prev_pos != pos)
\r
759 lfo_ampm |= pos; /* 0 - 32 */
\r
764 static INLINE void update_eg_phase(FM_SLOT *SLOT, UINT32 eg_cnt, UINT32 ssg_en)
\r
766 INT32 volume = SLOT->volume;
\r
767 UINT32 pack = SLOT->eg_pack[SLOT->state - 1];
\r
768 UINT32 shift = pack >> 24;
\r
771 if (eg_cnt & ((1 << shift) - 1))
\r
774 eg_inc_val = pack >> ((eg_cnt >> shift) & 7) * 3;
\r
775 eg_inc_val = (1 << (eg_inc_val & 7)) >> 1;
\r
777 if ((SLOT->ssg&0x08) && ssg_en) {
\r
778 switch (SLOT->state)
\r
780 case EG_ATT: /* attack phase */
\r
781 volume += ( ~volume * eg_inc_val ) >> 4;
\r
782 if ( volume <= MIN_ATT_INDEX )
\r
784 volume = MIN_ATT_INDEX;
\r
785 SLOT->state = (SLOT->sl == MIN_ATT_INDEX) ? EG_SUS: EG_DEC;
\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
796 case EG_SUS: /* sustain phase */
\r
797 if (volume < 0x200)
\r
798 volume += 4*eg_inc_val;
\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
806 volume = MAX_ATT_INDEX;
\r
807 SLOT->state = EG_OFF;
\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
816 switch (SLOT->state)
\r
818 case EG_ATT: /* attack phase */
\r
819 volume += ( ~volume * eg_inc_val ) >> 4;
\r
820 if ( volume <= MIN_ATT_INDEX )
\r
822 volume = MIN_ATT_INDEX;
\r
823 SLOT->state = (SLOT->sl == MIN_ATT_INDEX) ? EG_SUS: EG_DEC;
\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
833 case EG_SUS: /* sustain phase */
\r
834 volume += eg_inc_val;
\r
835 if ( volume >= MAX_ATT_INDEX )
\r
837 volume = MAX_ATT_INDEX;
\r
838 /* do not change SLOT->state (verified on real chip) */
\r
842 case EG_REL: /* release phase */
\r
843 volume += eg_inc_val;
\r
844 if ( volume >= MAX_ATT_INDEX )
\r
846 volume = MAX_ATT_INDEX;
\r
847 SLOT->state = EG_OFF;
\r
852 SLOT->vol_out = volume + SLOT->tl;
\r
854 SLOT->volume = volume;
\r
857 static INLINE UINT32 update_ssg_eg_phase(FM_SLOT *SLOT, UINT32 phase)
\r
859 if (SLOT->ssg&0x01) {
\r
860 if (SLOT->ssg&0x02) {
\r
861 SLOT->ssg ^= SLOT->ssgn ^ 4;
\r
865 if (SLOT->state != EG_ATT && !(SLOT->ssg&0x04))
\r
866 SLOT->volume = MAX_ATT_INDEX;
\r
868 if (SLOT->ssg&0x02) {
\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
879 SLOT->volume = MIN_ATT_INDEX;
\r
883 recalc_volout(SLOT);
\r
891 UINT16 vol_out1; /* 00: current output from EG circuit (without AM from LFO) */
\r
895 UINT32 lfo_init_sft16;
\r
897 UINT32 phase1; /* 10 */
\r
901 UINT32 incr1; /* 20: phase step */
\r
905 UINT32 lfo_cnt; /* 30 */
\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
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
915 #ifdef _MIPS_ARCH_ALLEGREX
\r
918 } chan_rend_context;
\r
921 #if !defined(_ASM_YM2612_C) || defined(EXTERNAL_YM2612)
\r
922 #include <limits.h>
\r
923 static int clip(int n)
\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
931 static void update_ssg_eg_channel(chan_rend_context *ct)
\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
949 static void update_eg_phase_channel(chan_rend_context *ct)
\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
963 static int update_algo_channel(chan_rend_context *ct, unsigned int eg_out, unsigned int eg_out2, unsigned int eg_out4)
\r
965 int m2,c1,c2=0; /* Phase Modulation input for operators 2,3,4 */
\r
968 switch( ct->algo&0x7 )
\r
972 /* M1---C1---MEM---M2---C2---OUT */
\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
980 if( eg_out < ENV_QUIET ) { /* SLOT 3 */
\r
981 c2 = op_calc(ct->phase3, eg_out, m2);
\r
983 if( eg_out4 < ENV_QUIET ) { /* SLOT 4 */
\r
984 smp = op_calc(ct->phase4, eg_out4, c2);
\r
990 /* M1------+-MEM---M2---C2---OUT */
\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
998 if( eg_out < ENV_QUIET ) { /* SLOT 3 */
\r
999 c2 = op_calc(ct->phase3, eg_out, m2);
\r
1001 if( eg_out4 < ENV_QUIET ) { /* SLOT 4 */
\r
1002 smp = op_calc(ct->phase4, eg_out4, c2);
\r
1008 /* M1-----------------+-C2---OUT */
\r
1009 /* C1---MEM---M2-+ */
\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
1017 if( eg_out < ENV_QUIET ) { /* SLOT 3 */
\r
1018 c2 += op_calc(ct->phase3, eg_out, m2);
\r
1020 if( eg_out4 < ENV_QUIET ) { /* SLOT 4 */
\r
1021 smp = op_calc(ct->phase4, eg_out4, c2);
\r
1027 /* M1---C1---MEM------+-C2---OUT */
\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
1036 if( eg_out < ENV_QUIET ) { /* SLOT 3 */
\r
1037 c2 += op_calc(ct->phase3, eg_out, 0);
\r
1039 if( eg_out4 < ENV_QUIET ) { /* SLOT 4 */
\r
1040 smp = op_calc(ct->phase4, eg_out4, c2);
\r
1046 /* M1---C1-+-OUT */
\r
1048 /* MEM: not used */
\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
1054 if( eg_out2 < ENV_QUIET ) { /* SLOT 2 */
\r
1055 smp = op_calc(ct->phase2, eg_out2, c1);
\r
1057 if( eg_out4 < ENV_QUIET ) { /* SLOT 4 */
\r
1058 smp+= op_calc(ct->phase4, eg_out4, c2);
\r
1064 /* +----C1----+ */
\r
1065 /* M1-+-MEM---M2-+-OUT */
\r
1066 /* +----C2----+ */
\r
1068 ct->mem = c1 = c2 = ct->op1_out>>16;
\r
1070 if( eg_out < ENV_QUIET ) { /* SLOT 3 */
\r
1071 smp = op_calc(ct->phase3, eg_out, m2);
\r
1073 if( eg_out2 < ENV_QUIET ) { /* SLOT 2 */
\r
1074 smp+= op_calc(ct->phase2, eg_out2, c1);
\r
1076 if( eg_out4 < ENV_QUIET ) { /* SLOT 4 */
\r
1077 smp+= op_calc(ct->phase4, eg_out4, c2);
\r
1086 /* MEM: not used */
\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
1092 if( eg_out2 < ENV_QUIET ) { /* SLOT 2 */
\r
1093 smp+= op_calc(ct->phase2, eg_out2, c1);
\r
1095 if( eg_out4 < ENV_QUIET ) { /* SLOT 4 */
\r
1096 smp+= op_calc(ct->phase4, eg_out4, 0);
\r
1106 /* MEM: not used*/
\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
1112 if( eg_out2 < ENV_QUIET ) { /* SLOT 2 */
\r
1113 smp += op_calc(ct->phase2, eg_out2, 0);
\r
1115 if( eg_out4 < ENV_QUIET ) { /* SLOT 4 */
\r
1116 smp += op_calc(ct->phase4, eg_out4, 0);
\r
1124 static void chan_render_loop(chan_rend_context *ct, s32 *buffer, int length)
\r
1126 int scounter; /* sample counter */
\r
1128 /* sample generating loop */
\r
1129 for (scounter = 0; scounter < length; scounter++)
\r
1131 int smp = 0; /* produced sample */
\r
1132 unsigned int eg_out, eg_out2, eg_out4;
\r
1134 ct->eg_timer += ct->eg_timer_add;
\r
1136 while (ct->eg_timer >= 1<<EG_SH) {
\r
1137 ct->eg_timer -= 1<<EG_SH;
\r
1140 update_ssg_eg_channel(ct);
\r
1142 if (ct->algo & 0x30)
\r
1144 if (!(ct->algo & 0x30)) {
\r
1147 if (ct->eg_cnt >= 4096) ct->eg_cnt = 1;
\r
1149 update_eg_phase_channel(ct);
\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
1158 if (ct->pack & 4) goto disabled; /* output disabled */
\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
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
1170 if( eg_out < ENV_QUIET ) /* SLOT 1 */
\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
1178 ct->op1_out <<= 16; /* op1_out0 = op1_out1; op1_out1 = 0; */
\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
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
1192 smp = update_algo_channel(ct, eg_out, eg_out2, eg_out4);
\r
1193 /* done calculating channel sample */
\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
1201 /* mix sample to output buffer */
\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
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
1214 buffer[scounter] += smp;
\r
1221 void chan_render_loop(chan_rend_context *ct, s32 *buffer, unsigned short length);
\r
1224 static chan_rend_context crct;
\r
1226 static void chan_render_prep(void)
\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
1233 static void chan_render_finish(s32 *buffer, int length, int active_chans)
\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
1240 static UINT32 update_lfo_phase(const FM_SLOT *SLOT, UINT32 block_fnum)
\r
1243 INT32 lfo_fn_table_index_offset;
\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
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
1256 /* phase increment counter */
\r
1257 fc = (fn_table[fn]>>(7-blk));
\r
1259 fdt = fc + SLOT->DT[crct.CH->kcode];
\r
1260 if (fdt < 0) fdt += fn_table[0x7ff*2] >> 2;
\r
1262 return (fdt * SLOT->mul) >> 1;
\r
1264 return SLOT->Incr;
\r
1267 static int chan_render(s32 *buffer, int length, int c, UINT32 flags) // flags: stereo, ?, disabled, ?, pan_r, pan_l
\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
1275 if (crct.lfo_inc) {
\r
1277 flags |= crct.lfo_init_sft16;
\r
1278 flags |= crct.CH->AMmasks << 8;
\r
1279 if (crct.CH->ams == 8) // no ams
\r
1281 else flags |= (crct.CH->ams&3)<<6;
\r
1283 flags |= (crct.CH->FB&0xf)<<12; /* feedback shift */
\r
1284 crct.pack = flags;
\r
1286 crct.eg_cnt = ym2612.OPN.eg_cnt; /* envelope generator counter */
\r
1287 crct.eg_timer = ym2612.OPN.eg_timer;
\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
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
1301 if(crct.CH->pms && (ym2612.OPN.ST.mode & 0xC0) && c == 2) {
\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
1308 else if(crct.CH->pms)
\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
1315 else /* no LFO phase modulation */
\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
1323 chan_render_loop(&crct, buffer, length);
\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
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
1335 ym2612.slot_mask &= ~(0xf << (c*4));
\r
1336 crct.CH->upd_cnt = (crct.algo >> 4) & 0x7;
\r
1338 return (crct.algo & 8) >> 3; // had output
\r
1341 /* update phase increment and envelope generator */
\r
1342 static INLINE void refresh_fc_eg_slot(FM_SLOT *SLOT, int fc, int kc)
\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
1353 ksr = kc >> SLOT->KSR;
\r
1354 if( SLOT->ksr != ksr )
\r
1356 int eg_sh, eg_sel;
\r
1358 SLOT->ar_ksr = SLOT->ar + ksr;
\r
1360 /* calculate envelope generator rates */
\r
1361 if ((SLOT->ar_ksr) < 32+62)
\r
1363 eg_sh = eg_rate_shift [SLOT->ar_ksr];
\r
1364 eg_sel = eg_rate_select[SLOT->ar_ksr];
\r
1372 SLOT->eg_pack_ar = eg_inc_pack[eg_sel] | (eg_sh<<24);
\r
1374 eg_sh = eg_rate_shift [SLOT->d1r + ksr];
\r
1375 eg_sel = eg_rate_select[SLOT->d1r + ksr];
\r
1377 SLOT->eg_pack_d1r = eg_inc_pack[eg_sel] | (eg_sh<<24);
\r
1379 eg_sh = eg_rate_shift [SLOT->d2r + ksr];
\r
1380 eg_sel = eg_rate_select[SLOT->d2r + ksr];
\r
1382 SLOT->eg_pack_d2r = eg_inc_pack[eg_sel] | (eg_sh<<24);
\r
1384 eg_sh = eg_rate_shift [SLOT->rr + ksr];
\r
1385 eg_sel = eg_rate_select[SLOT->rr + ksr];
\r
1387 SLOT->eg_pack_rr = eg_inc_pack[eg_sel] | (eg_sh<<24);
\r
1391 /* update phase increment counters */
\r
1392 static INLINE void refresh_fc_eg_chan(FM_CH *CH)
\r
1394 if( CH->SLOT[SLOT1].Incr==-1){
\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
1404 static INLINE void refresh_fc_eg_chan_sl3(void)
\r
1406 if( ym2612.CH[2].SLOT[SLOT1].Incr==-1)
\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
1415 /* initialize time tables */
\r
1416 static void init_timetables(const UINT8 *dttable)
\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
1432 static void reset_channels(FM_CH *CH)
\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
1442 for( c = 0 ; c < 6 ; c++ )
\r
1445 for(s = 0 ; s < 4 ; s++ )
\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
1457 CH[c].mem_value = CH[c].op1_out = 0;
\r
1459 ym2612.slot_mask = 0;
\r
1460 ym2612.ssg_mask = 0;
\r
1463 /* initialize generic tables */
\r
1464 static void init_tables(void)
\r
1466 signed int i,x,y,p;
\r
1470 if (ym_init_tab) return;
\r
1473 for (i=0; i < 256; i++)
\r
1475 /* non-standard sinus */
\r
1476 m = sin( ((i*2)+1) * M_PI / SIN_LEN ); /* checked against the real chip */
\r
1478 /* we never reach zero here due to ((i*2)+1) */
\r
1481 o = 8*log(1.0/m)/log(2); /* convert to 'decibels' */
\r
1483 o = 8*log(-1.0/m)/log(2); /* convert to 'decibels' */
\r
1485 o = o / (ENV_STEP/4);
\r
1488 if (n&1) /* round to nearest */
\r
1493 ym_sin_tab[ i ] = n;
\r
1494 //dprintf("FM.C: sin [%4i]= %4i", i, ym_sin_tab[i]);
\r
1497 //dprintf("FM.C: ENV_QUIET= %08x", ENV_QUIET );
\r
1500 for (x=0; x < TL_RES_LEN; x++)
\r
1502 m = (1<<16) / pow(2, (x+1) * (ENV_STEP/4.0) / 8.0);
\r
1505 /* we never reach (1<<16) here due to the (x+1) */
\r
1506 /* result fits within 16 bits at maximum */
\r
1508 n = (int)m; /* 16 bits here */
\r
1509 n >>= 4; /* 12 bits here */
\r
1510 if (n&1) /* round to nearest */
\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
1518 for (i=1; i < 13; i++)
\r
1520 ym_tl_tab2[ x + i*TL_RES_LEN ] = n >> i;
\r
1524 for (x=0; x < 256; x++)
\r
1526 int sin = ym_sin_tab[ x ];
\r
1528 for (y=0; y < 2*13*TL_RES_LEN/8; y+=2)
\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
1538 /* build LFO PM modulation table */
\r
1539 for(i = 0; i < 8; i++) /* 8 PM depths */
\r
1542 for (fnum=0; fnum<128; fnum++) /* 7 bits meaningful of F-NUMBER */
\r
1546 UINT32 offset_depth = i;
\r
1547 UINT32 offset_fnum_bit;
\r
1550 for (step=0; step<8; step++)
\r
1553 for (bit_tmp=0; bit_tmp<7; bit_tmp++) /* 7 bits */
\r
1555 if (fnum & (1<<bit_tmp)) /* only if bit "bit_tmp" is set */
\r
1557 offset_fnum_bit = bit_tmp * 8;
\r
1558 value += lfo_pm_output[offset_fnum_bit + offset_depth][step];
\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
1571 /* CSM Key Controll */
\r
1573 INLINE void CSMKeyControll(FM_CH *CH)
\r
1575 /* this is wrong, atm */
\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
1586 /* prescaler set (and make time tables) */
\r
1587 static void OPNSetPres(int pres)
\r
1591 /* frequency base */
\r
1592 double freqbase = (ym2612.OPN.ST.rate) ? ((double)ym2612.OPN.ST.clock / ym2612.OPN.ST.rate) / pres : 0;
\r
1594 ym2612.OPN.eg_timer_add = (1<<EG_SH) * freqbase;
\r
1595 ym2612.OPN.ST.freqbase = freqbase;
\r
1597 /* make time tables */
\r
1598 init_timetables( dt_tab );
\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
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
1610 /* LFO freq. table */
\r
1611 for(i = 0; i < 8; i++)
\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
1620 /* write a OPN register (0x30-0xff) */
\r
1621 static int OPNWriteReg(int r, int v)
\r
1627 UINT8 c = OPN_CHAN(r);
\r
1629 if (c == 3) return 0; /* 0xX3,0xX7,0xXB,0xXF */
\r
1631 if (r >= 0x100) c+=3;
\r
1633 CH = &ym2612.CH[c];
\r
1635 SLOT = &(CH->SLOT[OPN_SLOT(r)]);
\r
1637 switch( r & 0xf0 ) {
\r
1638 case 0x30: /* DET , MUL */
\r
1639 set_det_mul(CH,SLOT,v);
\r
1642 case 0x40: /* TL */
\r
1646 case 0x50: /* KS, AR */
\r
1647 set_ar_ksr(CH,SLOT,v);
\r
1650 case 0x60: /* bit7 = AM ENABLE, DR | depends on ksr */
\r
1652 if(v&0x80) CH->AMmasks |= 1<<OPN_SLOT(r);
\r
1653 else CH->AMmasks &= ~(1<<OPN_SLOT(r));
\r
1656 case 0x70: /* SR | depends on ksr */
\r
1660 case 0x80: /* SL, RR | depends on ksr */
\r
1661 set_sl_rr(SLOT,v);
\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
1674 switch( OPN_SLOT(r) ){
\r
1675 case 0: /* 0xa0-0xa2 : FNUM1 | depends on fn_h (below) */
\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
1684 /* store fnum in clear form for LFO PM calculations */
\r
1685 CH->block_fnum = (blk<<11) | fn;
\r
1687 CH->SLOT[SLOT1].Incr=-1;
\r
1690 case 1: /* 0xa4-0xa6 : FNUM2,BLK */
\r
1691 ym2612.OPN.ST.fn_h = v & 0x3f;
\r
1694 case 2: /* 0xa8-0xaa : 3CH FNUM1 */
\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
1707 case 3: /* 0xac-0xae : 3CH FNUM2,BLK */
\r
1709 ym2612.OPN.SL3.fn_h = v&0x3f;
\r
1719 switch( OPN_SLOT(r) ){
\r
1720 case 0: /* 0xb0-0xb2 : FB,ALGO */
\r
1722 int feedback = (v>>3)&7;
\r
1724 CH->FB = feedback ? feedback+6 : 0;
\r
1727 case 1: /* 0xb4-0xb6 : L , R , AMS , PMS (YM2612/YM2610B/YM2610/YM2608) */
\r
1729 int panshift = c<<1;
\r
1732 CH->pms = (v & 7) * 32; /* CH->pms = PM depth * 32 (index in lfo_pm_table) */
\r
1735 CH->ams = lfo_ams_depth_shift[(v>>4) & 3];
\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
1756 /*******************************************************************************/
\r
1757 /* YM2612 local section */
\r
1758 /*******************************************************************************/
\r
1760 /* Generate samples for YM2612 */
\r
1761 int YM2612UpdateOne_(s32 *buffer, int length, int stereo, int is_buf_empty)
\r
1764 int active_chs = 0;
\r
1765 int flags = stereo ? 1:0;
\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
1774 for (c = 0; c < 6; c++) {
\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
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
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
1793 refresh_fc_eg_chan_sl3();
\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
1800 pan = ym2612.OPN.pan;
\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
1820 chan_render_finish(buffer, length, active_chs);
\r
1822 return active_chs; // 1 if buffer updated
\r
1826 /* initialize YM2612 emulator */
\r
1827 void YM2612Init_(int clock, int rate, int flags)
\r
1829 memset(&ym2612, 0, sizeof(ym2612));
\r
1832 ym2612.OPN.ST.clock = clock;
\r
1833 ym2612.OPN.ST.rate = rate;
\r
1834 ym2612.OPN.ST.flags = flags;
\r
1836 OPNSetPres( 6*24 );
\r
1838 /* Extend handler */
\r
1839 YM2612ResetChip_();
\r
1844 void YM2612ResetChip_(void)
\r
1848 memset(ym2612.REGS, 0, sizeof(ym2612.REGS));
\r
1850 set_timers( 0x30 ); /* mode 0 , timer reset */
\r
1851 ym2612.REGS[0x27] = 0x30;
\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
1860 reset_channels( &ym2612.CH[0] );
\r
1861 for(i = 0xb6 ; i >= 0xb4 ; i-- )
\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
1868 for(i = 0xb2 ; i >= 0x30 ; i-- )
\r
1870 OPNWriteReg(i ,0);
\r
1871 OPNWriteReg(i|0x100,0);
\r
1873 for(i = 0x26 ; i >= 0x20 ; i-- ) OPNWriteReg(i,0);
\r
1874 /* DAC mode clear */
\r
1876 ym2612.dacout = 0;
\r
1877 ym2612.addr_A1 = 0;
\r
1881 /* YM2612 write */
\r
1884 /* returns 1 if sample affecting state changed */
\r
1885 int YM2612Write_(unsigned int a, unsigned int v)
\r
1889 v &= 0xff; /* adjust to 8 bit bus */
\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
1901 case 3: /* data port */
\r
1902 addr = ym2612.OPN.ST.address | ((int)ym2612.addr_A1 << 8);
\r
1904 switch( addr & 0x1f0 )
\r
1906 case 0x20: /* 0x20-0x2f Mode */
\r
1909 case 0x22: /* LFO FREQ (YM2608/YM2610/YM2610B/YM2612) */
\r
1910 if (v&0x08) /* LFO enabled ? */
\r
1912 ym2612.OPN.lfo_inc = ym2612.OPN.lfo_freq[v&7];
\r
1916 ym2612.OPN.lfo_inc = 0;
\r
1917 ym2612.OPN.lfo_cnt = 0;
\r
1918 ym2612.OPN.lfo_ampm = 126 << 8;
\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
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
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
1953 case 0x27: /* mode, timer control */
\r
1957 case 0x28: /* key on / off */
\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
1970 case 0x2a: /* DAC data (YM2612) */
\r
1971 ym2612.dacout = ((int)v - 0x80) << DAC_SHIFT;
\r
1974 case 0x2b: /* DAC Sel (YM2612) */
\r
1975 /* b7 = dac enable */
\r
1976 ym2612.dacen = v & 0x80;
\r
1983 default: /* 0x30-0xff OPN section */
\r
1984 /* write register */
\r
1985 ret = OPNWriteReg(addr,v);
\r
1994 UINT8 YM2612Read_(void)
\r
1996 return ym2612.OPN.ST.status;
\r
1999 int YM2612PicoTick_(int n)
\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
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
2024 void YM2612PicoStateLoad_(void)
\r
2026 reset_channels( &ym2612.CH[0] );
\r
2027 ym2612.slot_mask = 0xffffff;
\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
2034 UINT32 state_phase;
\r
2036 } ym_save_addon_slot;
\r
2047 UINT32 eg_cnt; // 10
\r
2052 UINT32 keyon_field; // 20
\r
2053 INT16 mem_value[6];
\r
2058 UINT16 op1_out_l[6];
\r
2059 UINT16 unused_sl3[3];
\r
2060 UINT16 op1_out_h[6];
\r
2063 #define _block_fnum op1_out_l
\r
2064 #define _block_fnum_sl3 unused_sl3
\r
2066 void YM2612PicoStateSave2(int tat, int tbt, int busy)
\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
2074 sa.magic = 0x41534d59; // 'YMSA'
\r
2078 ptr = &ym2612.REGS[0x0b8];
\r
2079 for (c = 0; c < 3; c++)
\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
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
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
2096 sa2._block_fnum[c] = ym2612.CH[c].block_fnum;
\r
2097 sa2._block_fnum_sl3[c] = ym2612.OPN.SL3.block_fnum[c];
\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
2104 ptr = &ym2612.REGS[0x1b8];
\r
2105 for (; c < 6; c++)
\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
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
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
2122 sa2._block_fnum[c] = ym2612.CH[c].block_fnum;
\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
2127 sa2.fn_h = ym2612.OPN.ST.fn_h | (ym2612.OPN.SL3.fn_h<<8);
\r
2129 memcpy(&ym2612.REGS[0], &sa2, sizeof(sa2)); // 0x20 max
\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
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
2147 int YM2612PicoStateLoad2(int *tat, int *tbt, int *busy)
\r
2149 ym_save_addon_slot ss;
\r
2150 ym_save_addon2 sa2;
\r
2152 unsigned char *ptr;
\r
2154 UINT8 fn_h, fn_h_sl3;
\r
2156 ptr = &ym2612.REGS[0x100];
\r
2157 memcpy(&sa, ptr, sizeof(sa)); // 0x30 max
\r
2158 if (sa.magic != 0x41534d59) return -1;
\r
2160 ptr = &ym2612.REGS[0];
\r
2161 memcpy(&sa2, ptr, sizeof(sa2));
\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
2175 fn_h = ym2612.OPN.ST.fn_h;
\r
2176 fn_h_sl3 = ym2612.OPN.SL3.fn_h;
\r
2179 ptr = &ym2612.REGS[0x0b8];
\r
2180 for (c = 0; c < 3; c++)
\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
2194 ym2612.CH[c].SLOT[SLOT1].Incr=-1;
\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
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
2206 OPNWriteReg(0xa0 + (c&3), ym2612.REGS[0xa0 + (c&3)]);
\r
2207 OPNWriteReg(0xa8 + (c&3), ym2612.REGS[0xa8 + (c&3)]);
\r
2210 ptr = &ym2612.REGS[0x1b8];
\r
2211 for (; c < 6; c++)
\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
2225 ym2612.CH[c].SLOT[SLOT1].Incr=-1;
\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
2232 ym2612.OPN.ST.fn_h = sa2._block_fnum[c] >> 8;
\r
2235 OPNWriteReg(0x1a0 + ((c-3)&3), ym2612.REGS[0x1a0 + ((c-3)&3)]);
\r
2238 ym2612.OPN.ST.fn_h = sa2.fn_h;
\r
2239 ym2612.OPN.SL3.fn_h = sa2.fn_h >> 8;
\r
2241 ym2612.OPN.ST.fn_h = fn_h;
\r
2242 ym2612.OPN.SL3.fn_h = fn_h_sl3;
\r
2248 #include "../state.h"
\r
2250 #define SLOT_SIZE_MIN 22
\r
2251 #define CH_SIZE_MIN 16
\r
2252 #define OTHER_SIZE_MIN 35
\r
2254 static size_t save_slot(u8 *buf, const FM_SLOT *slot)
\r
2256 size_t tmp, b = 0;
\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
2276 //printf("slot size: %zd\n", b);
\r
2277 assert(b >= SLOT_SIZE_MIN);
\r
2283 static void load_slot(const u8 *buf, FM_SLOT *slot)
\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
2304 assert(dt_reg < 8);
\r
2305 slot->DT = ym2612.OPN.ST.dt_tab[dt_reg & 7];
\r
2306 recalc_volout( slot );
\r
2308 // trigger a refresh
\r
2313 static size_t save_channel(u8 *buf, const FM_CH *ch)
\r
2318 for (i = 0; i < 4; i++)
\r
2319 b += save_slot(&buf[b], &ch->SLOT[i]);
\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
2333 assert(b - size_pos - 1 < 256u);
\r
2334 buf[size_pos] = b - size_pos - 1;
\r
2338 static size_t load_channel(const u8 *buf, size_t size, FM_CH *ch)
\r
2340 size_t i, b = 0, slot_size = 0, ch_size;
\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
2347 if (slot_size + size_next > size)
\r
2349 load_slot(&buf[slot_size], &ch->SLOT[i]);
\r
2350 slot_size += size_next;
\r
2352 if (slot_size + CH_SIZE_MIN > 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
2367 fn = ch->block_fnum & 0x7ff;
\r
2368 blk = ch->block_fnum >> 11;
\r
2369 ch->fc = fn_table[fn*2] >> (7 - blk);
\r
2371 assert(ch_size >= b - slot_size - 1);
\r
2372 return slot_size + 1 + ch_size;
\r
2375 size_t YM2612PicoStateSave3(void *buf_, size_t size)
\r
2379 u8 lfo_inc_reg = 0;
\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
2387 assert(ym2612.OPN.lfo_inc == 0 || i < 8);
\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
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
2414 //printf("ym2612 state size: %zu\n", b);
\r
2415 assert(b <= size);
\r
2419 void YM2612PicoStateLoad3(const void *buf_, size_t size)
\r
2421 const u8 *buf = buf_;
\r
2423 u8 lfo_inc_reg = 0;
\r
2425 for (i = 0; i < 6; i++) {
\r
2426 size_t r = load_channel(&buf[b], size - b, &ym2612.CH[i]);
\r
2431 if (b + OTHER_SIZE_MIN > size)
\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
2441 ym2612.OPN.SL3.kcode[i] = load_u8_(buf, &b);
\r
2442 ym2612.OPN.SL3.block_fnum[i] = load_u16(buf, &b) & 0x3fff;
\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
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
2459 assert(lfo_inc_reg < 9u);
\r
2460 ym2612.OPN.lfo_inc = 0;
\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
2468 elprintf(EL_STATUS, "broken ym2612 state");
\r
2471 void *YM2612GetRegs(void)
\r
2473 return ym2612.REGS;
\r