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
12 ** File: fm.c -- software implementation of Yamaha FM sound generator
\r
14 ** Copyright (C) 2001, 2002, 2003 Jarek Burczynski (bujar at mame dot net)
\r
15 ** Copyright (C) 1998 Tatsuyuki Satoh , MultiArcadeMachineEmulator development
\r
17 ** Version 1.4 (final beta)
\r
24 ** 03-08-2003 Jarek Burczynski:
\r
25 ** - fixed YM2608 initial values (after the reset)
\r
26 ** - fixed flag and irqmask handling (YM2608)
\r
27 ** - fixed BUFRDY flag handling (YM2608)
\r
29 ** 14-06-2003 Jarek Burczynski:
\r
30 ** - implemented all of the YM2608 status register flags
\r
31 ** - implemented support for external memory read/write via YM2608
\r
32 ** - implemented support for deltat memory limit register in YM2608 emulation
\r
34 ** 22-05-2003 Jarek Burczynski:
\r
35 ** - fixed LFO PM calculations (copy&paste bugfix)
\r
37 ** 08-05-2003 Jarek Burczynski:
\r
38 ** - fixed SSG support
\r
40 ** 22-04-2003 Jarek Burczynski:
\r
41 ** - implemented 100% correct LFO generator (verified on real YM2610 and YM2608)
\r
43 ** 15-04-2003 Jarek Burczynski:
\r
44 ** - added support for YM2608's register 0x110 - status mask
\r
46 ** 01-12-2002 Jarek Burczynski:
\r
47 ** - fixed register addressing in YM2608, YM2610, YM2610B chips. (verified on real YM2608)
\r
48 ** The addressing patch used for early Neo-Geo games can be removed now.
\r
50 ** 26-11-2002 Jarek Burczynski, Nicola Salmoria:
\r
51 ** - recreated YM2608 ADPCM ROM using data from real YM2608's output which leads to:
\r
52 ** - added emulation of YM2608 drums.
\r
53 ** - output of YM2608 is two times lower now - same as YM2610 (verified on real YM2608)
\r
55 ** 16-08-2002 Jarek Burczynski:
\r
56 ** - binary exact Envelope Generator (verified on real YM2203);
\r
57 ** identical to YM2151
\r
58 ** - corrected 'off by one' error in feedback calculations (when feedback is off)
\r
59 ** - corrected connection (algorithm) calculation (verified on real YM2203 and YM2610)
\r
61 ** 18-12-2001 Jarek Burczynski:
\r
62 ** - added SSG-EG support (verified on real YM2203)
\r
64 ** 12-08-2001 Jarek Burczynski:
\r
65 ** - corrected ym_sin_tab and ym_tl_tab data (verified on real chip)
\r
66 ** - corrected feedback calculations (verified on real chip)
\r
67 ** - corrected phase generator calculations (verified on real chip)
\r
68 ** - corrected envelope generator calculations (verified on real chip)
\r
69 ** - corrected FM volume level (YM2610 and YM2610B).
\r
70 ** - changed YMxxxUpdateOne() functions (YM2203, YM2608, YM2610, YM2610B, YM2612) :
\r
71 ** this was needed to calculate YM2610 FM channels output correctly.
\r
72 ** (Each FM channel is calculated as in other chips, but the output of the channel
\r
73 ** gets shifted right by one *before* sending to accumulator. That was impossible to do
\r
74 ** with previous implementation).
\r
76 ** 23-07-2001 Jarek Burczynski, Nicola Salmoria:
\r
77 ** - corrected YM2610 ADPCM type A algorithm and tables (verified on real chip)
\r
79 ** 11-06-2001 Jarek Burczynski:
\r
80 ** - corrected end of sample bug in ADPCMA_calc_cha().
\r
81 ** Real YM2610 checks for equality between current and end addresses (only 20 LSB bits).
\r
83 ** 08-12-98 hiro-shi:
\r
84 ** rename ADPCMA -> ADPCMB, ADPCMB -> ADPCMA
\r
85 ** move ROM limit check.(CALC_CH? -> 2610Write1/2)
\r
86 ** test program (ADPCMB_TEST)
\r
87 ** move ADPCM A/B end check.
\r
88 ** ADPCMB repeat flag(no check)
\r
89 ** change ADPCM volume rate (8->16) (32->48).
\r
91 ** 09-12-98 hiro-shi:
\r
92 ** change ADPCM volume. (8->16, 48->64)
\r
93 ** replace ym2610 ch0/3 (YM-2610B)
\r
94 ** change ADPCM_SHIFT (10->8) missing bank change 0x4000-0xffff.
\r
95 ** add ADPCM_SHIFT_MASK
\r
96 ** change ADPCMA_DECODE_MIN/MAX.
\r
102 /************************************************************************/
\r
103 /* comment of hiro-shi(Hiromitsu Shioya) */
\r
104 /* YM2610(B) = OPN-B */
\r
105 /* YM2610 : PSG:3ch FM:4ch ADPCM(18.5KHz):6ch DeltaT ADPCM:1ch */
\r
106 /* YM2610B : PSG:3ch FM:6ch ADPCM(18.5KHz):6ch DeltaT ADPCM:1ch */
\r
107 /************************************************************************/
\r
109 //#include <stdio.h>
\r
111 #include <string.h>
\r
114 #include "ym2612.h"
\r
116 #ifndef EXTERNAL_YM2612
\r
117 #include <stdlib.h>
\r
118 // let it be 1 global to simplify things
\r
122 extern YM2612 *ym2612_940;
\r
123 #define ym2612 (*ym2612_940)
\r
127 void memset32(int *dest, int c, int count);
\r
131 #pragma warning (disable:4100) // unreferenced formal parameter
\r
132 #pragma warning (disable:4244)
\r
133 #pragma warning (disable:4245) // signed/unsigned in conversion
\r
134 #pragma warning (disable:4710)
\r
135 #pragma warning (disable:4018) // signed/unsigned
\r
139 #define INLINE static __inline
\r
143 #define M_PI 3.14159265358979323846
\r
149 #define FREQ_SH 16 /* 16.16 fixed point (frequency calculations) */
\r
150 #define EG_SH 16 /* 16.16 fixed point (envelope generator timing) */
\r
151 #define LFO_SH 25 /* 7.25 fixed point (LFO calculations) */
\r
152 #define TIMER_SH 16 /* 16.16 fixed point (timers calculations) */
\r
154 #define ENV_BITS 10
\r
155 #define ENV_LEN (1<<ENV_BITS)
\r
156 #define ENV_STEP (128.0/ENV_LEN)
\r
158 #define MAX_ATT_INDEX (ENV_LEN-1) /* 1023 */
\r
159 #define MIN_ATT_INDEX (0) /* 0 */
\r
167 #define SIN_BITS 10
\r
168 #define SIN_LEN (1<<SIN_BITS)
\r
169 #define SIN_MASK (SIN_LEN-1)
\r
171 #define TL_RES_LEN (256) /* 8 bits addressing (real chip) */
\r
173 #define EG_TIMER_OVERFLOW (3*(1<<EG_SH)) /* envelope generator timer overflows every 3 samples (on real chip) */
\r
175 #define MAXOUT (+32767)
\r
176 #define MINOUT (-32768)
\r
179 #define Limit(val, max,min) { \
\r
180 if ( val > max ) val = max; \
\r
181 else if ( val < min ) val = min; \
\r
185 /* TL_TAB_LEN is calculated as:
\r
186 * 13 - sinus amplitude bits (Y axis)
\r
187 * 2 - sinus sign bit (Y axis)
\r
188 * TL_RES_LEN - sinus resolution (X axis)
\r
190 //#define TL_TAB_LEN (13*2*TL_RES_LEN)
\r
191 #define TL_TAB_LEN (13*TL_RES_LEN*256/8) // 106496*2
\r
192 UINT16 ym_tl_tab[TL_TAB_LEN];
\r
194 /* ~3K wasted but oh well */
\r
195 UINT16 ym_tl_tab2[13*TL_RES_LEN];
\r
197 #define ENV_QUIET (2*13*TL_RES_LEN/8)
\r
199 /* sin waveform table in 'decibel' scale (use only period/4 values) */
\r
200 static UINT16 ym_sin_tab[256];
\r
202 /* sustain level table (3dB per step) */
\r
203 /* bit0, bit1, bit2, bit3, bit4, bit5, bit6 */
\r
204 /* 1, 2, 4, 8, 16, 32, 64 (value)*/
\r
205 /* 0.75, 1.5, 3, 6, 12, 24, 48 (dB)*/
\r
207 /* 0 - 15: 0, 3, 6, 9,12,15,18,21,24,27,30,33,36,39,42,93 (dB)*/
\r
208 #define SC(db) (UINT32) ( db * (4.0/ENV_STEP) )
\r
209 static const UINT32 sl_table[16]={
\r
210 SC( 0),SC( 1),SC( 2),SC(3 ),SC(4 ),SC(5 ),SC(6 ),SC( 7),
\r
211 SC( 8),SC( 9),SC(10),SC(11),SC(12),SC(13),SC(14),SC(31)
\r
217 #define RATE_STEPS (8)
\r
218 static const UINT8 eg_inc[19*RATE_STEPS]={
\r
220 /*cycle:0 1 2 3 4 5 6 7*/
\r
222 /* 0 */ 0,1, 0,1, 0,1, 0,1, /* rates 00..11 0 (increment by 0 or 1) */
\r
223 /* 1 */ 0,1, 0,1, 1,1, 0,1, /* rates 00..11 1 */
\r
224 /* 2 */ 0,1, 1,1, 0,1, 1,1, /* rates 00..11 2 */
\r
225 /* 3 */ 0,1, 1,1, 1,1, 1,1, /* rates 00..11 3 */
\r
227 /* 4 */ 1,1, 1,1, 1,1, 1,1, /* rate 12 0 (increment by 1) */
\r
228 /* 5 */ 1,1, 1,2, 1,1, 1,2, /* rate 12 1 */
\r
229 /* 6 */ 1,2, 1,2, 1,2, 1,2, /* rate 12 2 */
\r
230 /* 7 */ 1,2, 2,2, 1,2, 2,2, /* rate 12 3 */
\r
232 /* 8 */ 2,2, 2,2, 2,2, 2,2, /* rate 13 0 (increment by 2) */
\r
233 /* 9 */ 2,2, 2,4, 2,2, 2,4, /* rate 13 1 */
\r
234 /*10 */ 2,4, 2,4, 2,4, 2,4, /* rate 13 2 */
\r
235 /*11 */ 2,4, 4,4, 2,4, 4,4, /* rate 13 3 */
\r
237 /*12 */ 4,4, 4,4, 4,4, 4,4, /* rate 14 0 (increment by 4) */
\r
238 /*13 */ 4,4, 4,8, 4,4, 4,8, /* rate 14 1 */
\r
239 /*14 */ 4,8, 4,8, 4,8, 4,8, /* rate 14 2 */
\r
240 /*15 */ 4,8, 8,8, 4,8, 8,8, /* rate 14 3 */
\r
242 /*16 */ 8,8, 8,8, 8,8, 8,8, /* rates 15 0, 15 1, 15 2, 15 3 (increment by 8) */
\r
243 /*17 */ 16,16,16,16,16,16,16,16, /* rates 15 2, 15 3 for attack */
\r
244 /*18 */ 0,0, 0,0, 0,0, 0,0, /* infinity rates for attack and decay(s) */
\r
249 #define PACK(a0,a1,a2,a3,a4,a5,a6,a7) ((a7<<21)|(a6<<18)|(a5<<15)|(a4<<12)|(a3<<9)|(a2<<6)|(a1<<3)|(a0<<0))
\r
250 static const UINT32 eg_inc_pack[19] =
\r
252 /* 0 */ PACK(0,1,0,1,0,1,0,1), /* rates 00..11 0 (increment by 0 or 1) */
\r
253 /* 1 */ PACK(0,1,0,1,1,1,0,1), /* rates 00..11 1 */
\r
254 /* 2 */ PACK(0,1,1,1,0,1,1,1), /* rates 00..11 2 */
\r
255 /* 3 */ PACK(0,1,1,1,1,1,1,1), /* rates 00..11 3 */
\r
257 /* 4 */ PACK(1,1,1,1,1,1,1,1), /* rate 12 0 (increment by 1) */
\r
258 /* 5 */ PACK(1,1,1,2,1,1,1,2), /* rate 12 1 */
\r
259 /* 6 */ PACK(1,2,1,2,1,2,1,2), /* rate 12 2 */
\r
260 /* 7 */ PACK(1,2,2,2,1,2,2,2), /* rate 12 3 */
\r
262 /* 8 */ PACK(2,2,2,2,2,2,2,2), /* rate 13 0 (increment by 2) */
\r
263 /* 9 */ PACK(2,2,2,3,2,2,2,3), /* rate 13 1 */
\r
264 /*10 */ PACK(2,3,2,3,2,3,2,3), /* rate 13 2 */
\r
265 /*11 */ PACK(2,3,3,3,2,3,3,3), /* rate 13 3 */
\r
267 /*12 */ PACK(3,3,3,3,3,3,3,3), /* rate 14 0 (increment by 4) */
\r
268 /*13 */ PACK(3,3,3,4,3,3,3,4), /* rate 14 1 */
\r
269 /*14 */ PACK(3,4,3,4,3,4,3,4), /* rate 14 2 */
\r
270 /*15 */ PACK(3,4,4,4,3,4,4,4), /* rate 14 3 */
\r
272 /*16 */ PACK(4,4,4,4,4,4,4,4), /* rates 15 0, 15 1, 15 2, 15 3 (increment by 8) */
\r
273 /*17 */ PACK(5,5,5,5,5,5,5,5), /* rates 15 2, 15 3 for attack */
\r
274 /*18 */ PACK(0,0,0,0,0,0,0,0), /* infinity rates for attack and decay(s) */
\r
278 //#define O(a) (a*RATE_STEPS)
\r
281 /*note that there is no O(17) in this table - it's directly in the code */
\r
282 static const UINT8 eg_rate_select[32+64+32]={ /* Envelope Generator rates (32 + 64 rates + 32 RKS) */
\r
283 /* 32 infinite time rates */
\r
284 O(18),O(18),O(18),O(18),O(18),O(18),O(18),O(18),
\r
285 O(18),O(18),O(18),O(18),O(18),O(18),O(18),O(18),
\r
286 O(18),O(18),O(18),O(18),O(18),O(18),O(18),O(18),
\r
287 O(18),O(18),O(18),O(18),O(18),O(18),O(18),O(18),
\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
298 O( 0),O( 1),O( 2),O( 3),
\r
299 O( 0),O( 1),O( 2),O( 3),
\r
300 O( 0),O( 1),O( 2),O( 3),
\r
301 O( 0),O( 1),O( 2),O( 3),
\r
304 O( 4),O( 5),O( 6),O( 7),
\r
307 O( 8),O( 9),O(10),O(11),
\r
310 O(12),O(13),O(14),O(15),
\r
313 O(16),O(16),O(16),O(16),
\r
315 /* 32 dummy rates (same as 15 3) */
\r
316 O(16),O(16),O(16),O(16),O(16),O(16),O(16),O(16),
\r
317 O(16),O(16),O(16),O(16),O(16),O(16),O(16),O(16),
\r
318 O(16),O(16),O(16),O(16),O(16),O(16),O(16),O(16),
\r
319 O(16),O(16),O(16),O(16),O(16),O(16),O(16),O(16)
\r
324 /*rate 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15*/
\r
325 /*shift 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 0, 0, 0, 0, 0 */
\r
326 /*mask 2047, 1023, 511, 255, 127, 63, 31, 15, 7, 3, 1, 0, 0, 0, 0, 0 */
\r
329 static const UINT8 eg_rate_shift[32+64+32]={ /* Envelope Generator counter shifts (32 + 64 rates + 32 RKS) */
\r
330 /* 32 infinite time rates */
\r
331 O(0),O(0),O(0),O(0),O(0),O(0),O(0),O(0),
\r
332 O(0),O(0),O(0),O(0),O(0),O(0),O(0),O(0),
\r
333 O(0),O(0),O(0),O(0),O(0),O(0),O(0),O(0),
\r
334 O(0),O(0),O(0),O(0),O(0),O(0),O(0),O(0),
\r
337 O(11),O(11),O(11),O(11),
\r
338 O(10),O(10),O(10),O(10),
\r
339 O( 9),O( 9),O( 9),O( 9),
\r
340 O( 8),O( 8),O( 8),O( 8),
\r
341 O( 7),O( 7),O( 7),O( 7),
\r
342 O( 6),O( 6),O( 6),O( 6),
\r
343 O( 5),O( 5),O( 5),O( 5),
\r
344 O( 4),O( 4),O( 4),O( 4),
\r
345 O( 3),O( 3),O( 3),O( 3),
\r
346 O( 2),O( 2),O( 2),O( 2),
\r
347 O( 1),O( 1),O( 1),O( 1),
\r
348 O( 0),O( 0),O( 0),O( 0),
\r
351 O( 0),O( 0),O( 0),O( 0),
\r
354 O( 0),O( 0),O( 0),O( 0),
\r
357 O( 0),O( 0),O( 0),O( 0),
\r
360 O( 0),O( 0),O( 0),O( 0),
\r
362 /* 32 dummy rates (same as 15 3) */
\r
363 O( 0),O( 0),O( 0),O( 0),O( 0),O( 0),O( 0),O( 0),
\r
364 O( 0),O( 0),O( 0),O( 0),O( 0),O( 0),O( 0),O( 0),
\r
365 O( 0),O( 0),O( 0),O( 0),O( 0),O( 0),O( 0),O( 0),
\r
366 O( 0),O( 0),O( 0),O( 0),O( 0),O( 0),O( 0),O( 0)
\r
371 static const UINT8 dt_tab[4 * 32]={
\r
372 /* this is YM2151 and YM2612 phase increment data (in 10.10 fixed point format)*/
\r
374 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
\r
375 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
\r
377 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 2, 2, 2, 2,
\r
378 2, 3, 3, 3, 4, 4, 4, 5, 5, 6, 6, 7, 8, 8, 8, 8,
\r
380 1, 1, 1, 1, 2, 2, 2, 2, 2, 3, 3, 3, 4, 4, 4, 5,
\r
381 5, 6, 6, 7, 8, 8, 9,10,11,12,13,14,16,16,16,16,
\r
383 2, 2, 2, 2, 2, 3, 3, 3, 4, 4, 4, 5, 5, 6, 6, 7,
\r
384 8 ,8, 9,10,11,12,13,14,16,17,19,20,22,22,22,22
\r
388 /* OPN key frequency number -> key code follow table */
\r
389 /* fnum higher 4bit -> keycode lower 2bit */
\r
390 static const UINT8 opn_fktable[16] = {0,0,0,0,0,0,0,1,2,3,3,3,3,3,3,3};
\r
393 /* 8 LFO speed parameters */
\r
394 /* each value represents number of samples that one LFO level will last for */
\r
395 static const UINT32 lfo_samples_per_step[8] = {108, 77, 71, 67, 62, 44, 8, 5};
\r
399 /*There are 4 different LFO AM depths available, they are:
\r
400 0 dB, 1.4 dB, 5.9 dB, 11.8 dB
\r
401 Here is how it is generated (in EG steps):
\r
403 11.8 dB = 0, 2, 4, 6, 8, 10,12,14,16...126,126,124,122,120,118,....4,2,0
\r
404 5.9 dB = 0, 1, 2, 3, 4, 5, 6, 7, 8....63, 63, 62, 61, 60, 59,.....2,1,0
\r
405 1.4 dB = 0, 0, 0, 0, 1, 1, 1, 1, 2,...15, 15, 15, 15, 14, 14,.....0,0,0
\r
407 (1.4 dB is loosing precision as you can see)
\r
409 It's implemented as generator from 0..126 with step 2 then a shift
\r
410 right N times, where N is:
\r
416 static const UINT8 lfo_ams_depth_shift[4] = {8, 3, 1, 0};
\r
420 /*There are 8 different LFO PM depths available, they are:
\r
421 0, 3.4, 6.7, 10, 14, 20, 40, 80 (cents)
\r
423 Modulation level at each depth depends on F-NUMBER bits: 4,5,6,7,8,9,10
\r
424 (bits 8,9,10 = FNUM MSB from OCT/FNUM register)
\r
426 Here we store only first quarter (positive one) of full waveform.
\r
427 Full table (lfo_pm_table) containing all 128 waveforms is build
\r
428 at run (init) time.
\r
430 One value in table below represents 4 (four) basic LFO steps
\r
431 (1 PM step = 4 AM steps).
\r
434 at LFO SPEED=0 (which is 108 samples per basic LFO step)
\r
435 one value from "lfo_pm_output" table lasts for 432 consecutive
\r
436 samples (4*108=432) and one full LFO waveform cycle lasts for 13824
\r
437 samples (32*432=13824; 32 because we store only a quarter of whole
\r
438 waveform in the table below)
\r
440 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
441 /* FNUM BIT 4: 000 0001xxxx */
\r
442 /* DEPTH 0 */ {0, 0, 0, 0, 0, 0, 0, 0},
\r
443 /* DEPTH 1 */ {0, 0, 0, 0, 0, 0, 0, 0},
\r
444 /* DEPTH 2 */ {0, 0, 0, 0, 0, 0, 0, 0},
\r
445 /* DEPTH 3 */ {0, 0, 0, 0, 0, 0, 0, 0},
\r
446 /* DEPTH 4 */ {0, 0, 0, 0, 0, 0, 0, 0},
\r
447 /* DEPTH 5 */ {0, 0, 0, 0, 0, 0, 0, 0},
\r
448 /* DEPTH 6 */ {0, 0, 0, 0, 0, 0, 0, 0},
\r
449 /* DEPTH 7 */ {0, 0, 0, 0, 1, 1, 1, 1},
\r
451 /* FNUM BIT 5: 000 0010xxxx */
\r
452 /* DEPTH 0 */ {0, 0, 0, 0, 0, 0, 0, 0},
\r
453 /* DEPTH 1 */ {0, 0, 0, 0, 0, 0, 0, 0},
\r
454 /* DEPTH 2 */ {0, 0, 0, 0, 0, 0, 0, 0},
\r
455 /* DEPTH 3 */ {0, 0, 0, 0, 0, 0, 0, 0},
\r
456 /* DEPTH 4 */ {0, 0, 0, 0, 0, 0, 0, 0},
\r
457 /* DEPTH 5 */ {0, 0, 0, 0, 0, 0, 0, 0},
\r
458 /* DEPTH 6 */ {0, 0, 0, 0, 1, 1, 1, 1},
\r
459 /* DEPTH 7 */ {0, 0, 1, 1, 2, 2, 2, 3},
\r
461 /* FNUM BIT 6: 000 0100xxxx */
\r
462 /* DEPTH 0 */ {0, 0, 0, 0, 0, 0, 0, 0},
\r
463 /* DEPTH 1 */ {0, 0, 0, 0, 0, 0, 0, 0},
\r
464 /* DEPTH 2 */ {0, 0, 0, 0, 0, 0, 0, 0},
\r
465 /* DEPTH 3 */ {0, 0, 0, 0, 0, 0, 0, 0},
\r
466 /* DEPTH 4 */ {0, 0, 0, 0, 0, 0, 0, 1},
\r
467 /* DEPTH 5 */ {0, 0, 0, 0, 1, 1, 1, 1},
\r
468 /* DEPTH 6 */ {0, 0, 1, 1, 2, 2, 2, 3},
\r
469 /* DEPTH 7 */ {0, 0, 2, 3, 4, 4, 5, 6},
\r
471 /* FNUM BIT 7: 000 1000xxxx */
\r
472 /* DEPTH 0 */ {0, 0, 0, 0, 0, 0, 0, 0},
\r
473 /* DEPTH 1 */ {0, 0, 0, 0, 0, 0, 0, 0},
\r
474 /* DEPTH 2 */ {0, 0, 0, 0, 0, 0, 1, 1},
\r
475 /* DEPTH 3 */ {0, 0, 0, 0, 1, 1, 1, 1},
\r
476 /* DEPTH 4 */ {0, 0, 0, 1, 1, 1, 1, 2},
\r
477 /* DEPTH 5 */ {0, 0, 1, 1, 2, 2, 2, 3},
\r
478 /* DEPTH 6 */ {0, 0, 2, 3, 4, 4, 5, 6},
\r
479 /* DEPTH 7 */ {0, 0, 4, 6, 8, 8, 0xa, 0xc},
\r
481 /* FNUM BIT 8: 001 0000xxxx */
\r
482 /* DEPTH 0 */ {0, 0, 0, 0, 0, 0, 0, 0},
\r
483 /* DEPTH 1 */ {0, 0, 0, 0, 1, 1, 1, 1},
\r
484 /* DEPTH 2 */ {0, 0, 0, 1, 1, 1, 2, 2},
\r
485 /* DEPTH 3 */ {0, 0, 1, 1, 2, 2, 3, 3},
\r
486 /* DEPTH 4 */ {0, 0, 1, 2, 2, 2, 3, 4},
\r
487 /* DEPTH 5 */ {0, 0, 2, 3, 4, 4, 5, 6},
\r
488 /* DEPTH 6 */ {0, 0, 4, 6, 8, 8, 0xa, 0xc},
\r
489 /* DEPTH 7 */ {0, 0, 8, 0xc,0x10,0x10,0x14,0x18},
\r
491 /* FNUM BIT 9: 010 0000xxxx */
\r
492 /* DEPTH 0 */ {0, 0, 0, 0, 0, 0, 0, 0},
\r
493 /* DEPTH 1 */ {0, 0, 0, 0, 2, 2, 2, 2},
\r
494 /* DEPTH 2 */ {0, 0, 0, 2, 2, 2, 4, 4},
\r
495 /* DEPTH 3 */ {0, 0, 2, 2, 4, 4, 6, 6},
\r
496 /* DEPTH 4 */ {0, 0, 2, 4, 4, 4, 6, 8},
\r
497 /* DEPTH 5 */ {0, 0, 4, 6, 8, 8, 0xa, 0xc},
\r
498 /* DEPTH 6 */ {0, 0, 8, 0xc,0x10,0x10,0x14,0x18},
\r
499 /* DEPTH 7 */ {0, 0,0x10,0x18,0x20,0x20,0x28,0x30},
\r
501 /* FNUM BIT10: 100 0000xxxx */
\r
502 /* DEPTH 0 */ {0, 0, 0, 0, 0, 0, 0, 0},
\r
503 /* DEPTH 1 */ {0, 0, 0, 0, 4, 4, 4, 4},
\r
504 /* DEPTH 2 */ {0, 0, 0, 4, 4, 4, 8, 8},
\r
505 /* DEPTH 3 */ {0, 0, 4, 4, 8, 8, 0xc, 0xc},
\r
506 /* DEPTH 4 */ {0, 0, 4, 8, 8, 8, 0xc,0x10},
\r
507 /* DEPTH 5 */ {0, 0, 8, 0xc,0x10,0x10,0x14,0x18},
\r
508 /* DEPTH 6 */ {0, 0,0x10,0x18,0x20,0x20,0x28,0x30},
\r
509 /* DEPTH 7 */ {0, 0,0x20,0x30,0x40,0x40,0x50,0x60},
\r
513 /* all 128 LFO PM waveforms */
\r
514 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
516 /* there are 2048 FNUMs that can be generated using FNUM/BLK registers
\r
517 but LFO works with one more bit of a precision so we really need 4096 elements */
\r
518 static UINT32 fn_table[4096]; /* fnumber->increment counter */
\r
520 static int g_lfo_ampm = 0;
\r
522 /* register number to channel number , slot offset */
\r
523 #define OPN_CHAN(N) (N&3)
\r
524 #define OPN_SLOT(N) ((N>>2)&3)
\r
533 /* OPN Mode Register Write */
\r
534 INLINE void set_timers( int v )
\r
536 /* b7 = CSM MODE */
\r
537 /* b6 = 3 slot mode */
\r
540 /* b3 = timer enable b */
\r
541 /* b2 = timer enable a */
\r
544 ym2612.OPN.ST.mode = v;
\r
546 /* reset Timer b flag */
\r
548 ym2612.OPN.ST.status &= ~2;
\r
550 /* reset Timer a flag */
\r
552 ym2612.OPN.ST.status &= ~1;
\r
556 INLINE void FM_KEYON(int c , int s )
\r
558 FM_SLOT *SLOT = &ym2612.CH[c].SLOT[s];
\r
562 SLOT->phase = 0; /* restart Phase Generator */
\r
563 SLOT->state = EG_ATT; /* phase -> Attack */
\r
564 SLOT->volume = MAX_ATT_INDEX; /* fix Ecco 2 splash sound */
\r
565 ym2612.slot_mask |= (1<<s) << (c*4);
\r
569 INLINE void FM_KEYOFF(int c , int s )
\r
571 FM_SLOT *SLOT = &ym2612.CH[c].SLOT[s];
\r
575 if (SLOT->state>EG_REL)
\r
576 SLOT->state = EG_REL;/* phase -> Release */
\r
581 /* set detune & multiple */
\r
582 INLINE void set_det_mul(FM_CH *CH, FM_SLOT *SLOT, int v)
\r
584 SLOT->mul = (v&0x0f)? (v&0x0f)*2 : 1;
\r
585 SLOT->DT = ym2612.OPN.ST.dt_tab[(v>>4)&7];
\r
586 CH->SLOT[SLOT1].Incr=-1;
\r
589 /* set total level */
\r
590 INLINE void set_tl(FM_SLOT *SLOT, int v)
\r
592 SLOT->tl = (v&0x7f)<<(ENV_BITS-7); /* 7bit TL */
\r
595 /* set attack rate & key scale */
\r
596 INLINE void set_ar_ksr(FM_CH *CH, FM_SLOT *SLOT, int v)
\r
598 UINT8 old_KSR = SLOT->KSR;
\r
600 SLOT->ar = (v&0x1f) ? 32 + ((v&0x1f)<<1) : 0;
\r
602 SLOT->KSR = 3-(v>>6);
\r
603 if (SLOT->KSR != old_KSR)
\r
605 CH->SLOT[SLOT1].Incr=-1;
\r
609 int eg_sh_ar, eg_sel_ar;
\r
611 /* refresh Attack rate */
\r
612 if ((SLOT->ar + SLOT->ksr) < 32+62)
\r
614 eg_sh_ar = eg_rate_shift [SLOT->ar + SLOT->ksr ];
\r
615 eg_sel_ar = eg_rate_select[SLOT->ar + SLOT->ksr ];
\r
623 SLOT->eg_pack_ar = eg_inc_pack[eg_sel_ar] | (eg_sh_ar<<24);
\r
627 /* set decay rate */
\r
628 INLINE void set_dr(FM_SLOT *SLOT, int v)
\r
630 int eg_sh_d1r, eg_sel_d1r;
\r
632 SLOT->d1r = (v&0x1f) ? 32 + ((v&0x1f)<<1) : 0;
\r
634 eg_sh_d1r = eg_rate_shift [SLOT->d1r + SLOT->ksr];
\r
635 eg_sel_d1r= eg_rate_select[SLOT->d1r + SLOT->ksr];
\r
637 SLOT->eg_pack_d1r = eg_inc_pack[eg_sel_d1r] | (eg_sh_d1r<<24);
\r
640 /* set sustain rate */
\r
641 INLINE void set_sr(FM_SLOT *SLOT, int v)
\r
643 int eg_sh_d2r, eg_sel_d2r;
\r
645 SLOT->d2r = (v&0x1f) ? 32 + ((v&0x1f)<<1) : 0;
\r
647 eg_sh_d2r = eg_rate_shift [SLOT->d2r + SLOT->ksr];
\r
648 eg_sel_d2r= eg_rate_select[SLOT->d2r + SLOT->ksr];
\r
650 SLOT->eg_pack_d2r = eg_inc_pack[eg_sel_d2r] | (eg_sh_d2r<<24);
\r
653 /* set release rate */
\r
654 INLINE void set_sl_rr(FM_SLOT *SLOT, int v)
\r
656 int eg_sh_rr, eg_sel_rr;
\r
658 SLOT->sl = sl_table[ v>>4 ];
\r
660 SLOT->rr = 34 + ((v&0x0f)<<2);
\r
662 eg_sh_rr = eg_rate_shift [SLOT->rr + SLOT->ksr];
\r
663 eg_sel_rr = eg_rate_select[SLOT->rr + SLOT->ksr];
\r
665 SLOT->eg_pack_rr = eg_inc_pack[eg_sel_rr] | (eg_sh_rr<<24);
\r
670 INLINE signed int op_calc(UINT32 phase, unsigned int env, signed int pm)
\r
672 int ret, sin = (phase>>16) + (pm>>1);
\r
673 int neg = sin & 0x200;
\r
674 if (sin & 0x100) sin ^= 0xff;
\r
678 // this was already checked
\r
679 // if (env >= ENV_QUIET) // 384
\r
682 ret = ym_tl_tab[sin | (env<<7)];
\r
684 return neg ? -ret : ret;
\r
687 INLINE signed int op_calc1(UINT32 phase, unsigned int env, signed int pm)
\r
689 int ret, sin = (phase+pm)>>16;
\r
690 int neg = sin & 0x200;
\r
691 if (sin & 0x100) sin ^= 0xff;
\r
695 // if (env >= ENV_QUIET) // 384
\r
698 ret = ym_tl_tab[sin | (env<<7)];
\r
700 return neg ? -ret : ret;
\r
703 #if !defined(_ASM_YM2612_C) || defined(EXTERNAL_YM2612)
\r
704 /* advance LFO to next sample */
\r
705 INLINE int advance_lfo(int lfo_ampm, UINT32 lfo_cnt_old, UINT32 lfo_cnt)
\r
710 prev_pos = (lfo_cnt_old >> LFO_SH) & 127;
\r
712 pos = (lfo_cnt >> LFO_SH) & 127;
\r
714 /* update AM when LFO output changes */
\r
716 if (prev_pos != pos)
\r
720 /* AM: 0 to 126 step +2, 126 to 0 step -2 */
\r
722 lfo_ampm |= ((pos&63) * 2) << 8; /* 0 - 126 */
\r
724 lfo_ampm |= (126 - (pos&63)*2) << 8;
\r
731 /* PM works with 4 times slower clock */
\r
734 /* update PM when LFO output changes */
\r
735 if (prev_pos != pos)
\r
738 lfo_ampm |= pos; /* 0 - 32 */
\r
743 #define EG_INC_VAL() \
\r
744 ((1 << ((pack >> ((eg_cnt>>shift)&7)*3)&7)) >> 1)
\r
746 INLINE UINT32 update_eg_phase(FM_SLOT *SLOT, UINT32 eg_cnt)
\r
748 INT32 volume = SLOT->volume;
\r
750 switch(SLOT->state)
\r
752 case EG_ATT: /* attack phase */
\r
754 UINT32 pack = SLOT->eg_pack_ar;
\r
755 UINT32 shift = pack>>24;
\r
756 if ( !(eg_cnt & ((1<<shift)-1) ) )
\r
758 volume += ( ~volume * EG_INC_VAL() ) >>4;
\r
760 if (volume <= MIN_ATT_INDEX)
\r
762 volume = MIN_ATT_INDEX;
\r
763 SLOT->state = EG_DEC;
\r
769 case EG_DEC: /* decay phase */
\r
771 UINT32 pack = SLOT->eg_pack_d1r;
\r
772 UINT32 shift = pack>>24;
\r
773 if ( !(eg_cnt & ((1<<shift)-1) ) )
\r
775 volume += EG_INC_VAL();
\r
777 if ( volume >= (INT32) SLOT->sl )
\r
778 SLOT->state = EG_SUS;
\r
783 case EG_SUS: /* sustain phase */
\r
785 UINT32 pack = SLOT->eg_pack_d2r;
\r
786 UINT32 shift = pack>>24;
\r
787 if ( !(eg_cnt & ((1<<shift)-1) ) )
\r
789 volume += EG_INC_VAL();
\r
791 if ( volume >= MAX_ATT_INDEX )
\r
793 volume = MAX_ATT_INDEX;
\r
794 /* do not change SLOT->state (verified on real chip) */
\r
800 case EG_REL: /* release phase */
\r
802 UINT32 pack = SLOT->eg_pack_rr;
\r
803 UINT32 shift = pack>>24;
\r
804 if ( !(eg_cnt & ((1<<shift)-1) ) )
\r
806 volume += EG_INC_VAL();
\r
808 if ( volume >= MAX_ATT_INDEX )
\r
810 volume = MAX_ATT_INDEX;
\r
811 SLOT->state = EG_OFF;
\r
818 SLOT->volume = volume;
\r
819 return SLOT->tl + ((UINT32)volume); /* tl is 7bit<<3, volume 0-1023 (0-2039 total) */
\r
826 UINT16 vol_out1; /* 00: current output from EG circuit (without AM from LFO) */
\r
831 UINT32 phase1; /* 10 */
\r
835 UINT32 incr1; /* 20: phase step */
\r
839 UINT32 lfo_cnt; /* 30 */
\r
841 INT32 mem; /* one sample delay memory */
\r
842 UINT32 eg_cnt; /* envelope generator counter */
\r
843 FM_CH *CH; /* 40: envelope generator counter */
\r
845 UINT32 eg_timer_add;
\r
846 UINT32 pack; // 4c: stereo, lastchan, disabled, lfo_enabled | pan_r, pan_l, ams[2] | AMmasks[4] | FB[4] | lfo_ampm[16]
\r
847 UINT32 algo; /* 50: algo[3], was_update */
\r
849 #ifdef _MIPS_ARCH_ALLEGREX
\r
852 } chan_rend_context;
\r
855 #if !defined(_ASM_YM2612_C) || defined(EXTERNAL_YM2612)
\r
856 static void chan_render_loop(chan_rend_context *ct, int *buffer, int length)
\r
858 int scounter; /* sample counter */
\r
860 /* sample generating loop */
\r
861 for (scounter = 0; scounter < length; scounter++)
\r
863 int smp = 0; /* produced sample */
\r
864 unsigned int eg_out, eg_out2, eg_out4;
\r
866 if (ct->pack & 8) { /* LFO enabled ? (test Earthworm Jim in between demo 1 and 2) */
\r
867 ct->pack = (ct->pack&0xffff) | (advance_lfo(ct->pack >> 16, ct->lfo_cnt, ct->lfo_cnt + ct->lfo_inc) << 16);
\r
868 ct->lfo_cnt += ct->lfo_inc;
\r
871 ct->eg_timer += ct->eg_timer_add;
\r
872 while (ct->eg_timer >= EG_TIMER_OVERFLOW)
\r
874 ct->eg_timer -= EG_TIMER_OVERFLOW;
\r
877 if (ct->CH->SLOT[SLOT1].state != EG_OFF) ct->vol_out1 = update_eg_phase(&ct->CH->SLOT[SLOT1], ct->eg_cnt);
\r
878 if (ct->CH->SLOT[SLOT2].state != EG_OFF) ct->vol_out2 = update_eg_phase(&ct->CH->SLOT[SLOT2], ct->eg_cnt);
\r
879 if (ct->CH->SLOT[SLOT3].state != EG_OFF) ct->vol_out3 = update_eg_phase(&ct->CH->SLOT[SLOT3], ct->eg_cnt);
\r
880 if (ct->CH->SLOT[SLOT4].state != EG_OFF) ct->vol_out4 = update_eg_phase(&ct->CH->SLOT[SLOT4], ct->eg_cnt);
\r
883 if (ct->pack & 4) continue; /* output disabled */
\r
885 /* calculate channel sample */
\r
886 eg_out = ct->vol_out1;
\r
887 if ( (ct->pack & 8) && (ct->pack&(1<<(SLOT1+8))) ) eg_out += ct->pack >> (((ct->pack&0xc0)>>6)+24);
\r
889 if( eg_out < ENV_QUIET ) /* SLOT 1 */
\r
893 if (ct->pack&0xf000) out = ((ct->op1_out>>16) + ((ct->op1_out<<16)>>16)) << ((ct->pack&0xf000)>>12); /* op1_out0 + op1_out1 */
\r
894 ct->op1_out <<= 16;
\r
895 ct->op1_out |= (unsigned short)op_calc1(ct->phase1, eg_out, out);
\r
897 ct->op1_out <<= 16; /* op1_out0 = op1_out1; op1_out1 = 0; */
\r
900 eg_out = ct->vol_out3; // volume_calc(&CH->SLOT[SLOT3]);
\r
901 eg_out2 = ct->vol_out2; // volume_calc(&CH->SLOT[SLOT2]);
\r
902 eg_out4 = ct->vol_out4; // volume_calc(&CH->SLOT[SLOT4]);
\r
904 if (ct->pack & 8) {
\r
905 unsigned int add = ct->pack >> (((ct->pack&0xc0)>>6)+24);
\r
906 if (ct->pack & (1<<(SLOT3+8))) eg_out += add;
\r
907 if (ct->pack & (1<<(SLOT2+8))) eg_out2 += add;
\r
908 if (ct->pack & (1<<(SLOT4+8))) eg_out4 += add;
\r
911 switch( ct->CH->ALGO )
\r
915 /* M1---C1---MEM---M2---C2---OUT */
\r
916 int m2,c1,c2=0; /* Phase Modulation input for operators 2,3,4 */
\r
918 c1 = ct->op1_out>>16;
\r
919 if( eg_out < ENV_QUIET ) { /* SLOT 3 */
\r
920 c2 = op_calc(ct->phase3, eg_out, m2);
\r
922 if( eg_out2 < ENV_QUIET ) { /* SLOT 2 */
\r
923 ct->mem = op_calc(ct->phase2, eg_out2, c1);
\r
926 if( eg_out4 < ENV_QUIET ) { /* SLOT 4 */
\r
927 smp = op_calc(ct->phase4, eg_out4, c2);
\r
933 /* M1------+-MEM---M2---C2---OUT */
\r
937 ct->mem = ct->op1_out>>16;
\r
938 if( eg_out < ENV_QUIET ) { /* SLOT 3 */
\r
939 c2 = op_calc(ct->phase3, eg_out, m2);
\r
941 if( eg_out2 < ENV_QUIET ) { /* SLOT 2 */
\r
942 ct->mem+= op_calc(ct->phase2, eg_out2, 0);
\r
944 if( eg_out4 < ENV_QUIET ) { /* SLOT 4 */
\r
945 smp = op_calc(ct->phase4, eg_out4, c2);
\r
951 /* M1-----------------+-C2---OUT */
\r
952 /* C1---MEM---M2-+ */
\r
955 c2 = ct->op1_out>>16;
\r
956 if( eg_out < ENV_QUIET ) { /* SLOT 3 */
\r
957 c2 += op_calc(ct->phase3, eg_out, m2);
\r
959 if( eg_out2 < ENV_QUIET ) { /* SLOT 2 */
\r
960 ct->mem = op_calc(ct->phase2, eg_out2, 0);
\r
963 if( eg_out4 < ENV_QUIET ) { /* SLOT 4 */
\r
964 smp = op_calc(ct->phase4, eg_out4, c2);
\r
970 /* M1---C1---MEM------+-C2---OUT */
\r
974 c1 = ct->op1_out>>16;
\r
975 if( eg_out < ENV_QUIET ) { /* SLOT 3 */
\r
976 c2 += op_calc(ct->phase3, eg_out, 0);
\r
978 if( eg_out2 < ENV_QUIET ) { /* SLOT 2 */
\r
979 ct->mem = op_calc(ct->phase2, eg_out2, c1);
\r
982 if( eg_out4 < ENV_QUIET ) { /* SLOT 4 */
\r
983 smp = op_calc(ct->phase4, eg_out4, c2);
\r
989 /* M1---C1-+-OUT */
\r
991 /* MEM: not used */
\r
993 c1 = ct->op1_out>>16;
\r
994 if( eg_out < ENV_QUIET ) { /* SLOT 3 */
\r
995 c2 = op_calc(ct->phase3, eg_out, 0);
\r
997 if( eg_out2 < ENV_QUIET ) { /* SLOT 2 */
\r
998 smp = op_calc(ct->phase2, eg_out2, c1);
\r
1000 if( eg_out4 < ENV_QUIET ) { /* SLOT 4 */
\r
1001 smp+= op_calc(ct->phase4, eg_out4, c2);
\r
1007 /* +----C1----+ */
\r
1008 /* M1-+-MEM---M2-+-OUT */
\r
1009 /* +----C2----+ */
\r
1012 ct->mem = c1 = c2 = ct->op1_out>>16;
\r
1013 if( eg_out < ENV_QUIET ) { /* SLOT 3 */
\r
1014 smp = op_calc(ct->phase3, eg_out, m2);
\r
1016 if( eg_out2 < ENV_QUIET ) { /* SLOT 2 */
\r
1017 smp+= op_calc(ct->phase2, eg_out2, c1);
\r
1019 if( eg_out4 < ENV_QUIET ) { /* SLOT 4 */
\r
1020 smp+= op_calc(ct->phase4, eg_out4, c2);
\r
1029 /* MEM: not used */
\r
1031 c1 = ct->op1_out>>16;
\r
1032 if( eg_out < ENV_QUIET ) { /* SLOT 3 */
\r
1033 smp = op_calc(ct->phase3, eg_out, 0);
\r
1035 if( eg_out2 < ENV_QUIET ) { /* SLOT 2 */
\r
1036 smp+= op_calc(ct->phase2, eg_out2, c1);
\r
1038 if( eg_out4 < ENV_QUIET ) { /* SLOT 4 */
\r
1039 smp+= op_calc(ct->phase4, eg_out4, 0);
\r
1049 /* MEM: not used*/
\r
1050 smp = ct->op1_out>>16;
\r
1051 if( eg_out < ENV_QUIET ) { /* SLOT 3 */
\r
1052 smp += 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, 0);
\r
1057 if( eg_out4 < ENV_QUIET ) { /* SLOT 4 */
\r
1058 smp += op_calc(ct->phase4, eg_out4, 0);
\r
1063 /* done calculating channel sample */
\r
1065 /* mix sample to output buffer */
\r
1067 if (ct->pack & 1) { /* stereo */
\r
1068 if (ct->pack & 0x20) /* L */ /* TODO: check correctness */
\r
1069 buffer[scounter*2] += smp;
\r
1070 if (ct->pack & 0x10) /* R */
\r
1071 buffer[scounter*2+1] += smp;
\r
1073 buffer[scounter] += smp;
\r
1075 ct->algo = 8; // algo is only used in asm, here only bit3 is used
\r
1078 /* update phase counters AFTER output calculations */
\r
1079 ct->phase1 += ct->incr1;
\r
1080 ct->phase2 += ct->incr2;
\r
1081 ct->phase3 += ct->incr3;
\r
1082 ct->phase4 += ct->incr4;
\r
1086 void chan_render_loop(chan_rend_context *ct, int *buffer, unsigned short length);
\r
1089 static chan_rend_context crct;
\r
1091 static void chan_render_prep(void)
\r
1093 crct.eg_timer_add = ym2612.OPN.eg_timer_add;
\r
1094 crct.lfo_inc = ym2612.OPN.lfo_inc;
\r
1097 static void chan_render_finish(void)
\r
1099 ym2612.OPN.eg_cnt = crct.eg_cnt;
\r
1100 ym2612.OPN.eg_timer = crct.eg_timer;
\r
1101 g_lfo_ampm = crct.pack >> 16; // need_save
\r
1102 ym2612.OPN.lfo_cnt = crct.lfo_cnt;
\r
1105 static int chan_render(int *buffer, int length, int c, UINT32 flags) // flags: stereo, ?, disabled, ?, pan_r, pan_l
\r
1107 crct.CH = &ym2612.CH[c];
\r
1108 crct.mem = crct.CH->mem_value; /* one sample delay memory */
\r
1109 crct.lfo_cnt = ym2612.OPN.lfo_cnt;
\r
1113 if (crct.lfo_inc) {
\r
1115 flags |= g_lfo_ampm << 16;
\r
1116 flags |= crct.CH->AMmasks << 8;
\r
1117 if (crct.CH->ams == 8) // no ams
\r
1119 else flags |= (crct.CH->ams&3)<<6;
\r
1121 flags |= (crct.CH->FB&0xf)<<12; /* feedback shift */
\r
1122 crct.pack = flags;
\r
1124 crct.eg_cnt = ym2612.OPN.eg_cnt; /* envelope generator counter */
\r
1125 crct.eg_timer = ym2612.OPN.eg_timer;
\r
1127 /* precalculate phase modulation incr */
\r
1128 crct.phase1 = crct.CH->SLOT[SLOT1].phase;
\r
1129 crct.phase2 = crct.CH->SLOT[SLOT2].phase;
\r
1130 crct.phase3 = crct.CH->SLOT[SLOT3].phase;
\r
1131 crct.phase4 = crct.CH->SLOT[SLOT4].phase;
\r
1133 /* current output from EG circuit (without AM from LFO) */
\r
1134 crct.vol_out1 = crct.CH->SLOT[SLOT1].tl + ((UINT32)crct.CH->SLOT[SLOT1].volume);
\r
1135 crct.vol_out2 = crct.CH->SLOT[SLOT2].tl + ((UINT32)crct.CH->SLOT[SLOT2].volume);
\r
1136 crct.vol_out3 = crct.CH->SLOT[SLOT3].tl + ((UINT32)crct.CH->SLOT[SLOT3].volume);
\r
1137 crct.vol_out4 = crct.CH->SLOT[SLOT4].tl + ((UINT32)crct.CH->SLOT[SLOT4].volume);
\r
1139 crct.op1_out = crct.CH->op1_out;
\r
1140 crct.algo = crct.CH->ALGO & 7;
\r
1144 /* add support for 3 slot mode */
\r
1145 UINT32 block_fnum = crct.CH->block_fnum;
\r
1147 UINT32 fnum_lfo = ((block_fnum & 0x7f0) >> 4) * 32 * 8;
\r
1148 INT32 lfo_fn_table_index_offset = lfo_pm_table[ fnum_lfo + crct.CH->pms + ((crct.pack>>16)&0xff) ];
\r
1150 if (lfo_fn_table_index_offset) /* LFO phase modulation active */
\r
1156 blk = block_fnum >> 11;
\r
1157 block_fnum = block_fnum*2 + lfo_fn_table_index_offset;
\r
1159 fn = block_fnum & 0xfff;
\r
1161 /* keyscale code */
\r
1162 kc = (blk<<2) | opn_fktable[fn >> 8];
\r
1163 /* phase increment counter */
\r
1164 fc = fn_table[fn]>>(7-blk);
\r
1166 crct.incr1 = ((fc+crct.CH->SLOT[SLOT1].DT[kc])*crct.CH->SLOT[SLOT1].mul) >> 1;
\r
1167 crct.incr2 = ((fc+crct.CH->SLOT[SLOT2].DT[kc])*crct.CH->SLOT[SLOT2].mul) >> 1;
\r
1168 crct.incr3 = ((fc+crct.CH->SLOT[SLOT3].DT[kc])*crct.CH->SLOT[SLOT3].mul) >> 1;
\r
1169 crct.incr4 = ((fc+crct.CH->SLOT[SLOT4].DT[kc])*crct.CH->SLOT[SLOT4].mul) >> 1;
\r
1171 else /* LFO phase modulation = zero */
\r
1173 crct.incr1 = crct.CH->SLOT[SLOT1].Incr;
\r
1174 crct.incr2 = crct.CH->SLOT[SLOT2].Incr;
\r
1175 crct.incr3 = crct.CH->SLOT[SLOT3].Incr;
\r
1176 crct.incr4 = crct.CH->SLOT[SLOT4].Incr;
\r
1179 else /* no LFO phase modulation */
\r
1181 crct.incr1 = crct.CH->SLOT[SLOT1].Incr;
\r
1182 crct.incr2 = crct.CH->SLOT[SLOT2].Incr;
\r
1183 crct.incr3 = crct.CH->SLOT[SLOT3].Incr;
\r
1184 crct.incr4 = crct.CH->SLOT[SLOT4].Incr;
\r
1187 chan_render_loop(&crct, buffer, length);
\r
1189 crct.CH->op1_out = crct.op1_out;
\r
1190 crct.CH->mem_value = crct.mem;
\r
1191 if (crct.CH->SLOT[SLOT1].state | crct.CH->SLOT[SLOT2].state | crct.CH->SLOT[SLOT3].state | crct.CH->SLOT[SLOT4].state)
\r
1193 crct.CH->SLOT[SLOT1].phase = crct.phase1;
\r
1194 crct.CH->SLOT[SLOT2].phase = crct.phase2;
\r
1195 crct.CH->SLOT[SLOT3].phase = crct.phase3;
\r
1196 crct.CH->SLOT[SLOT4].phase = crct.phase4;
\r
1199 ym2612.slot_mask &= ~(0xf << (c*4));
\r
1201 return (crct.algo & 8) >> 3; // had output
\r
1204 /* update phase increment and envelope generator */
\r
1205 INLINE void refresh_fc_eg_slot(FM_SLOT *SLOT, int fc, int kc)
\r
1209 /* (frequency) phase increment counter */
\r
1210 fdt = fc+SLOT->DT[kc];
\r
1211 /* detect overflow */
\r
1212 // if (fdt < 0) fdt += fn_table[0x7ff*2] >> (7-blk-1);
\r
1213 if (fdt < 0) fdt += fn_table[0x7ff*2] >> 2;
\r
1214 SLOT->Incr = fdt*SLOT->mul >> 1;
\r
1216 ksr = kc >> SLOT->KSR;
\r
1217 if( SLOT->ksr != ksr )
\r
1219 int eg_sh, eg_sel;
\r
1222 /* calculate envelope generator rates */
\r
1223 if ((SLOT->ar + ksr) < 32+62)
\r
1225 eg_sh = eg_rate_shift [SLOT->ar + ksr ];
\r
1226 eg_sel = eg_rate_select[SLOT->ar + ksr ];
\r
1234 SLOT->eg_pack_ar = eg_inc_pack[eg_sel] | (eg_sh<<24);
\r
1236 eg_sh = eg_rate_shift [SLOT->d1r + ksr];
\r
1237 eg_sel = eg_rate_select[SLOT->d1r + ksr];
\r
1239 SLOT->eg_pack_d1r = eg_inc_pack[eg_sel] | (eg_sh<<24);
\r
1241 eg_sh = eg_rate_shift [SLOT->d2r + ksr];
\r
1242 eg_sel = eg_rate_select[SLOT->d2r + ksr];
\r
1244 SLOT->eg_pack_d2r = eg_inc_pack[eg_sel] | (eg_sh<<24);
\r
1246 eg_sh = eg_rate_shift [SLOT->rr + ksr];
\r
1247 eg_sel = eg_rate_select[SLOT->rr + ksr];
\r
1249 SLOT->eg_pack_rr = eg_inc_pack[eg_sel] | (eg_sh<<24);
\r
1253 /* update phase increment counters */
\r
1254 INLINE void refresh_fc_eg_chan(FM_CH *CH)
\r
1256 if( CH->SLOT[SLOT1].Incr==-1){
\r
1258 int kc = CH->kcode;
\r
1259 refresh_fc_eg_slot(&CH->SLOT[SLOT1] , fc , kc );
\r
1260 refresh_fc_eg_slot(&CH->SLOT[SLOT2] , fc , kc );
\r
1261 refresh_fc_eg_slot(&CH->SLOT[SLOT3] , fc , kc );
\r
1262 refresh_fc_eg_slot(&CH->SLOT[SLOT4] , fc , kc );
\r
1266 INLINE void refresh_fc_eg_chan_sl3(void)
\r
1268 if( ym2612.CH[2].SLOT[SLOT1].Incr==-1)
\r
1270 refresh_fc_eg_slot(&ym2612.CH[2].SLOT[SLOT1], ym2612.OPN.SL3.fc[1], ym2612.OPN.SL3.kcode[1] );
\r
1271 refresh_fc_eg_slot(&ym2612.CH[2].SLOT[SLOT2], ym2612.OPN.SL3.fc[2], ym2612.OPN.SL3.kcode[2] );
\r
1272 refresh_fc_eg_slot(&ym2612.CH[2].SLOT[SLOT3], ym2612.OPN.SL3.fc[0], ym2612.OPN.SL3.kcode[0] );
\r
1273 refresh_fc_eg_slot(&ym2612.CH[2].SLOT[SLOT4], ym2612.CH[2].fc , ym2612.CH[2].kcode );
\r
1277 /* initialize time tables */
\r
1278 static void init_timetables(const UINT8 *dttable)
\r
1283 /* DeTune table */
\r
1284 for (d = 0;d <= 3;d++){
\r
1285 for (i = 0;i <= 31;i++){
\r
1286 rate = ((double)dttable[d*32 + i]) * SIN_LEN * ym2612.OPN.ST.freqbase * (1<<FREQ_SH) / ((double)(1<<20));
\r
1287 ym2612.OPN.ST.dt_tab[d][i] = (INT32) rate;
\r
1288 ym2612.OPN.ST.dt_tab[d+4][i] = -ym2612.OPN.ST.dt_tab[d][i];
\r
1294 static void reset_channels(FM_CH *CH)
\r
1298 ym2612.OPN.ST.mode = 0; /* normal mode */
\r
1299 ym2612.OPN.ST.TA = 0;
\r
1300 ym2612.OPN.ST.TAC = 0;
\r
1301 ym2612.OPN.ST.TB = 0;
\r
1302 ym2612.OPN.ST.TBC = 0;
\r
1304 for( c = 0 ; c < 6 ; c++ )
\r
1307 for(s = 0 ; s < 4 ; s++ )
\r
1309 CH[c].SLOT[s].state= EG_OFF;
\r
1310 CH[c].SLOT[s].volume = MAX_ATT_INDEX;
\r
1312 CH[c].mem_value = CH[c].op1_out = 0;
\r
1314 ym2612.slot_mask = 0;
\r
1317 /* initialize generic tables */
\r
1318 static void init_tables(void)
\r
1320 signed int i,x,y,p;
\r
1324 for (i=0; i < 256; i++)
\r
1326 /* non-standard sinus */
\r
1327 m = sin( ((i*2)+1) * M_PI / SIN_LEN ); /* checked against the real chip */
\r
1329 /* we never reach zero here due to ((i*2)+1) */
\r
1332 o = 8*log(1.0/m)/log(2); /* convert to 'decibels' */
\r
1334 o = 8*log(-1.0/m)/log(2); /* convert to 'decibels' */
\r
1336 o = o / (ENV_STEP/4);
\r
1339 if (n&1) /* round to nearest */
\r
1344 ym_sin_tab[ i ] = n;
\r
1345 //dprintf("FM.C: sin [%4i]= %4i", i, ym_sin_tab[i]);
\r
1348 //dprintf("FM.C: ENV_QUIET= %08x", ENV_QUIET );
\r
1351 for (x=0; x < TL_RES_LEN; x++)
\r
1353 m = (1<<16) / pow(2, (x+1) * (ENV_STEP/4.0) / 8.0);
\r
1356 /* we never reach (1<<16) here due to the (x+1) */
\r
1357 /* result fits within 16 bits at maximum */
\r
1359 n = (int)m; /* 16 bits here */
\r
1360 n >>= 4; /* 12 bits here */
\r
1361 if (n&1) /* round to nearest */
\r
1365 /* 11 bits here (rounded) */
\r
1366 n <<= 2; /* 13 bits here (as in real chip) */
\r
1367 ym_tl_tab2[ x ] = n;
\r
1369 for (i=1; i < 13; i++)
\r
1371 ym_tl_tab2[ x + i*TL_RES_LEN ] = n >> i;
\r
1375 for (x=0; x < 256; x++)
\r
1377 int sin = ym_sin_tab[ x ];
\r
1379 for (y=0; y < 2*13*TL_RES_LEN/8; y+=2)
\r
1382 if (p >= 13*TL_RES_LEN)
\r
1383 ym_tl_tab[(y<<7) | x] = 0;
\r
1384 else ym_tl_tab[(y<<7) | x] = ym_tl_tab2[p];
\r
1389 /* build LFO PM modulation table */
\r
1390 for(i = 0; i < 8; i++) /* 8 PM depths */
\r
1393 for (fnum=0; fnum<128; fnum++) /* 7 bits meaningful of F-NUMBER */
\r
1397 UINT32 offset_depth = i;
\r
1398 UINT32 offset_fnum_bit;
\r
1401 for (step=0; step<8; step++)
\r
1404 for (bit_tmp=0; bit_tmp<7; bit_tmp++) /* 7 bits */
\r
1406 if (fnum & (1<<bit_tmp)) /* only if bit "bit_tmp" is set */
\r
1408 offset_fnum_bit = bit_tmp * 8;
\r
1409 value += lfo_pm_output[offset_fnum_bit + offset_depth][step];
\r
1412 lfo_pm_table[(fnum*32*8) + (i*32) + step + 0] = value;
\r
1413 lfo_pm_table[(fnum*32*8) + (i*32) +(step^7)+ 8] = value;
\r
1414 lfo_pm_table[(fnum*32*8) + (i*32) + step +16] = -value;
\r
1415 lfo_pm_table[(fnum*32*8) + (i*32) +(step^7)+24] = -value;
\r
1422 /* CSM Key Controll */
\r
1424 INLINE void CSMKeyControll(FM_CH *CH)
\r
1426 /* this is wrong, atm */
\r
1429 FM_KEYON(CH,SLOT1);
\r
1430 FM_KEYON(CH,SLOT2);
\r
1431 FM_KEYON(CH,SLOT3);
\r
1432 FM_KEYON(CH,SLOT4);
\r
1437 /* prescaler set (and make time tables) */
\r
1438 static void OPNSetPres(int pres)
\r
1442 /* frequency base */
\r
1443 ym2612.OPN.ST.freqbase = (ym2612.OPN.ST.rate) ? ((double)ym2612.OPN.ST.clock / ym2612.OPN.ST.rate) / pres : 0;
\r
1445 ym2612.OPN.eg_timer_add = (1<<EG_SH) * ym2612.OPN.ST.freqbase;
\r
1447 /* make time tables */
\r
1448 init_timetables( dt_tab );
\r
1450 /* there are 2048 FNUMs that can be generated using FNUM/BLK registers
\r
1451 but LFO works with one more bit of a precision so we really need 4096 elements */
\r
1452 /* calculate fnumber -> increment counter table */
\r
1453 for(i = 0; i < 4096; i++)
\r
1455 /* freq table for octave 7 */
\r
1456 /* OPN phase increment counter = 20bit */
\r
1457 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
1460 /* LFO freq. table */
\r
1461 for(i = 0; i < 8; i++)
\r
1463 /* Amplitude modulation: 64 output levels (triangle waveform); 1 level lasts for one of "lfo_samples_per_step" samples */
\r
1464 /* Phase modulation: one entry from lfo_pm_output lasts for one of 4 * "lfo_samples_per_step" samples */
\r
1465 ym2612.OPN.lfo_freq[i] = (1.0 / lfo_samples_per_step[i]) * (1<<LFO_SH) * ym2612.OPN.ST.freqbase;
\r
1470 /* write a OPN register (0x30-0xff) */
\r
1471 static int OPNWriteReg(int r, int v)
\r
1477 UINT8 c = OPN_CHAN(r);
\r
1479 if (c == 3) return 0; /* 0xX3,0xX7,0xXB,0xXF */
\r
1481 if (r >= 0x100) c+=3;
\r
1483 CH = &ym2612.CH[c];
\r
1485 SLOT = &(CH->SLOT[OPN_SLOT(r)]);
\r
1487 switch( r & 0xf0 ) {
\r
1488 case 0x30: /* DET , MUL */
\r
1489 set_det_mul(CH,SLOT,v);
\r
1492 case 0x40: /* TL */
\r
1496 case 0x50: /* KS, AR */
\r
1497 set_ar_ksr(CH,SLOT,v);
\r
1500 case 0x60: /* bit7 = AM ENABLE, DR | depends on ksr */
\r
1502 if(v&0x80) CH->AMmasks |= 1<<OPN_SLOT(r);
\r
1503 else CH->AMmasks &= ~(1<<OPN_SLOT(r));
\r
1506 case 0x70: /* SR | depends on ksr */
\r
1510 case 0x80: /* SL, RR | depends on ksr */
\r
1511 set_sl_rr(SLOT,v);
\r
1514 case 0x90: /* SSG-EG */
\r
1520 switch( OPN_SLOT(r) ){
\r
1521 case 0: /* 0xa0-0xa2 : FNUM1 | depends on fn_h (below) */
\r
1523 UINT32 fn = (((UINT32)( (CH->fn_h)&7))<<8) + v;
\r
1524 UINT8 blk = CH->fn_h>>3;
\r
1525 /* keyscale code */
\r
1526 CH->kcode = (blk<<2) | opn_fktable[fn >> 7];
\r
1527 /* phase increment counter */
\r
1528 CH->fc = fn_table[fn*2]>>(7-blk);
\r
1530 /* store fnum in clear form for LFO PM calculations */
\r
1531 CH->block_fnum = (blk<<11) | fn;
\r
1533 CH->SLOT[SLOT1].Incr=-1;
\r
1536 case 1: /* 0xa4-0xa6 : FNUM2,BLK */
\r
1537 CH->fn_h = v&0x3f;
\r
1540 case 2: /* 0xa8-0xaa : 3CH FNUM1 */
\r
1543 UINT32 fn = (((UINT32)(ym2612.OPN.SL3.fn_h&7))<<8) + v;
\r
1544 UINT8 blk = ym2612.OPN.SL3.fn_h>>3;
\r
1545 /* keyscale code */
\r
1546 ym2612.OPN.SL3.kcode[c]= (blk<<2) | opn_fktable[fn >> 7];
\r
1547 /* phase increment counter */
\r
1548 ym2612.OPN.SL3.fc[c] = fn_table[fn*2]>>(7-blk);
\r
1549 ym2612.OPN.SL3.block_fnum[c] = (blk<<11) | fn;
\r
1550 ym2612.CH[2].SLOT[SLOT1].Incr=-1;
\r
1553 case 3: /* 0xac-0xae : 3CH FNUM2,BLK */
\r
1555 ym2612.OPN.SL3.fn_h = v&0x3f;
\r
1565 switch( OPN_SLOT(r) ){
\r
1566 case 0: /* 0xb0-0xb2 : FB,ALGO */
\r
1568 int feedback = (v>>3)&7;
\r
1570 CH->FB = feedback ? feedback+6 : 0;
\r
1573 case 1: /* 0xb4-0xb6 : L , R , AMS , PMS (YM2612/YM2610B/YM2610/YM2608) */
\r
1575 int panshift = c<<1;
\r
1578 CH->pms = (v & 7) * 32; /* CH->pms = PM depth * 32 (index in lfo_pm_table) */
\r
1581 CH->ams = lfo_ams_depth_shift[(v>>4) & 3];
\r
1583 /* PAN : b7 = L, b6 = R */
\r
1584 ym2612.OPN.pan &= ~(3<<panshift);
\r
1585 ym2612.OPN.pan |= ((v & 0xc0) >> 6) << panshift; // ..LRLR
\r
1602 /*******************************************************************************/
\r
1603 /* YM2612 local section */
\r
1604 /*******************************************************************************/
\r
1606 /* Generate samples for YM2612 */
\r
1607 int YM2612UpdateOne_(int *buffer, int length, int stereo, int is_buf_empty)
\r
1610 int active_chs = 0;
\r
1612 // if !is_buf_empty, it means it has valid samples to mix with, else it may contain trash
\r
1613 if (is_buf_empty) memset32(buffer, 0, length<<stereo);
\r
1619 for (c = 0; c < 6; c++) {
\r
1621 printf("%i: ", c);
\r
1622 for (s = 0; s < 4; s++) {
\r
1623 if (ym2612.CH[c].SLOT[s].state != EG_OFF) slr = 1;
\r
1624 printf(" %i", ym2612.CH[c].SLOT[s].state != EG_OFF);
\r
1626 slm = (ym2612.slot_mask&(0xf<<(c*4))) ? 1 : 0;
\r
1627 printf(" | %i", slm);
\r
1628 printf(" | %i\n", ym2612.CH[c].SLOT[SLOT1].Incr==-1);
\r
1629 if (slr != slm) exit(1);
\r
1633 /* refresh PG and EG */
\r
1634 refresh_fc_eg_chan( &ym2612.CH[0] );
\r
1635 refresh_fc_eg_chan( &ym2612.CH[1] );
\r
1636 if( (ym2612.OPN.ST.mode & 0xc0) )
\r
1638 refresh_fc_eg_chan_sl3();
\r
1640 refresh_fc_eg_chan( &ym2612.CH[2] );
\r
1641 refresh_fc_eg_chan( &ym2612.CH[3] );
\r
1642 refresh_fc_eg_chan( &ym2612.CH[4] );
\r
1643 refresh_fc_eg_chan( &ym2612.CH[5] );
\r
1645 pan = ym2612.OPN.pan;
\r
1646 if (stereo) stereo = 1;
\r
1648 /* mix to 32bit dest */
\r
1649 // flags: stereo, ?, disabled, ?, pan_r, pan_l
\r
1650 chan_render_prep();
\r
1651 if (ym2612.slot_mask & 0x00000f) active_chs |= chan_render(buffer, length, 0, stereo|((pan&0x003)<<4)) << 0;
\r
1652 if (ym2612.slot_mask & 0x0000f0) active_chs |= chan_render(buffer, length, 1, stereo|((pan&0x00c)<<2)) << 1;
\r
1653 if (ym2612.slot_mask & 0x000f00) active_chs |= chan_render(buffer, length, 2, stereo|((pan&0x030) )) << 2;
\r
1654 if (ym2612.slot_mask & 0x00f000) active_chs |= chan_render(buffer, length, 3, stereo|((pan&0x0c0)>>2)) << 3;
\r
1655 if (ym2612.slot_mask & 0x0f0000) active_chs |= chan_render(buffer, length, 4, stereo|((pan&0x300)>>4)) << 4;
\r
1656 if (ym2612.slot_mask & 0xf00000) active_chs |= chan_render(buffer, length, 5, stereo|((pan&0xc00)>>6)|(ym2612.dacen<<2)) << 5;
\r
1657 chan_render_finish();
\r
1659 return active_chs; // 1 if buffer updated
\r
1663 /* initialize YM2612 emulator */
\r
1664 void YM2612Init_(int clock, int rate)
\r
1666 memset(&ym2612, 0, sizeof(ym2612));
\r
1669 ym2612.OPN.ST.clock = clock;
\r
1670 ym2612.OPN.ST.rate = rate;
\r
1672 OPNSetPres( 6*24 );
\r
1674 /* Extend handler */
\r
1675 YM2612ResetChip_();
\r
1680 void YM2612ResetChip_(void)
\r
1684 memset(ym2612.REGS, 0, sizeof(ym2612.REGS));
\r
1686 set_timers( 0x30 ); /* mode 0 , timer reset */
\r
1687 ym2612.REGS[0x27] = 0x30;
\r
1689 ym2612.OPN.eg_timer = 0;
\r
1690 ym2612.OPN.eg_cnt = 0;
\r
1691 ym2612.OPN.ST.status = 0;
\r
1693 reset_channels( &ym2612.CH[0] );
\r
1694 for(i = 0xb6 ; i >= 0xb4 ; i-- )
\r
1696 OPNWriteReg(i ,0xc0);
\r
1697 OPNWriteReg(i|0x100,0xc0);
\r
1698 ym2612.REGS[i ] = 0xc0;
\r
1699 ym2612.REGS[i|0x100] = 0xc0;
\r
1701 for(i = 0xb2 ; i >= 0x30 ; i-- )
\r
1703 OPNWriteReg(i ,0);
\r
1704 OPNWriteReg(i|0x100,0);
\r
1706 for(i = 0x26 ; i >= 0x20 ; i-- ) OPNWriteReg(i,0);
\r
1707 /* DAC mode clear */
\r
1709 ym2612.addr_A1 = 0;
\r
1713 /* YM2612 write */
\r
1716 /* returns 1 if sample affecting state changed */
\r
1717 int YM2612Write_(unsigned int a, unsigned int v)
\r
1721 v &= 0xff; /* adjust to 8 bit bus */
\r
1724 case 0: /* address port 0 */
\r
1725 ym2612.OPN.ST.address = v;
\r
1726 ym2612.addr_A1 = 0;
\r
1730 case 1: /* data port 0 */
\r
1731 if (ym2612.addr_A1 != 0) {
\r
1733 break; /* verified on real YM2608 */
\r
1736 addr = ym2612.OPN.ST.address;
\r
1738 switch( addr & 0xf0 )
\r
1740 case 0x20: /* 0x20-0x2f Mode */
\r
1743 case 0x22: /* LFO FREQ (YM2608/YM2610/YM2610B/YM2612) */
\r
1744 if (v&0x08) /* LFO enabled ? */
\r
1746 ym2612.OPN.lfo_inc = ym2612.OPN.lfo_freq[v&7];
\r
1750 ym2612.OPN.lfo_inc = 0;
\r
1753 #if 0 // handled elsewhere
\r
1754 case 0x24: { // timer A High 8
\r
1755 int TAnew = (ym2612.OPN.ST.TA & 0x03)|(((int)v)<<2);
\r
1756 if(ym2612.OPN.ST.TA != TAnew) {
\r
1757 // we should reset ticker only if new value is written. Outrun requires this.
\r
1758 ym2612.OPN.ST.TA = TAnew;
\r
1759 ym2612.OPN.ST.TAC = (1024-TAnew)*18;
\r
1760 ym2612.OPN.ST.TAT = 0;
\r
1765 case 0x25: { // timer A Low 2
\r
1766 int TAnew = (ym2612.OPN.ST.TA & 0x3fc)|(v&3);
\r
1767 if(ym2612.OPN.ST.TA != TAnew) {
\r
1768 ym2612.OPN.ST.TA = TAnew;
\r
1769 ym2612.OPN.ST.TAC = (1024-TAnew)*18;
\r
1770 ym2612.OPN.ST.TAT = 0;
\r
1775 case 0x26: // timer B
\r
1776 if(ym2612.OPN.ST.TB != v) {
\r
1777 ym2612.OPN.ST.TB = v;
\r
1778 ym2612.OPN.ST.TBC = (256-v)<<4;
\r
1779 ym2612.OPN.ST.TBC *= 18;
\r
1780 ym2612.OPN.ST.TBT = 0;
\r
1785 case 0x27: /* mode, timer control */
\r
1789 case 0x28: /* key on / off */
\r
1794 if( c == 3 ) { ret=0; break; }
\r
1795 if( v&0x04 ) c+=3;
\r
1796 if(v&0x10) FM_KEYON(c,SLOT1); else FM_KEYOFF(c,SLOT1);
\r
1797 if(v&0x20) FM_KEYON(c,SLOT2); else FM_KEYOFF(c,SLOT2);
\r
1798 if(v&0x40) FM_KEYON(c,SLOT3); else FM_KEYOFF(c,SLOT3);
\r
1799 if(v&0x80) FM_KEYON(c,SLOT4); else FM_KEYOFF(c,SLOT4);
\r
1802 case 0x2a: /* DAC data (YM2612) */
\r
1803 ym2612.dacout = ((int)v - 0x80) << 6; /* level unknown (notaz: 8 seems to be too much) */
\r
1806 case 0x2b: /* DAC Sel (YM2612) */
\r
1807 /* b7 = dac enable */
\r
1808 ym2612.dacen = v & 0x80;
\r
1815 default: /* 0x30-0xff OPN section */
\r
1816 /* write register */
\r
1817 ret = OPNWriteReg(addr,v);
\r
1821 case 2: /* address port 1 */
\r
1822 ym2612.OPN.ST.address = v;
\r
1823 ym2612.addr_A1 = 1;
\r
1827 case 3: /* data port 1 */
\r
1828 if (ym2612.addr_A1 != 1) {
\r
1830 break; /* verified on real YM2608 */
\r
1833 addr = ym2612.OPN.ST.address | 0x100;
\r
1835 ret = OPNWriteReg(addr, v);
\r
1843 UINT8 YM2612Read_(void)
\r
1845 return ym2612.OPN.ST.status;
\r
1848 int YM2612PicoTick_(int n)
\r
1853 if(ym2612.OPN.ST.mode & 0x01 && (ym2612.OPN.ST.TAT+=64*n) >= ym2612.OPN.ST.TAC) {
\r
1854 ym2612.OPN.ST.TAT -= ym2612.OPN.ST.TAC;
\r
1855 if(ym2612.OPN.ST.mode & 0x04) ym2612.OPN.ST.status |= 1;
\r
1856 // CSM mode total level latch and auto key on
\r
1857 if(ym2612.OPN.ST.mode & 0x80) {
\r
1858 CSMKeyControll( &(ym2612.CH[2]) ); // Vectorman2, etc.
\r
1864 if(ym2612.OPN.ST.mode & 0x02 && (ym2612.OPN.ST.TBT+=64*n) >= ym2612.OPN.ST.TBC) {
\r
1865 ym2612.OPN.ST.TBT -= ym2612.OPN.ST.TBC;
\r
1866 if(ym2612.OPN.ST.mode & 0x08) ym2612.OPN.ST.status |= 2;
\r
1873 void YM2612PicoStateLoad_(void)
\r
1875 reset_channels( &ym2612.CH[0] );
\r
1876 ym2612.slot_mask = 0xffffff;
\r
1879 /* rather stupid design because I wanted to fit in unused register "space" */
\r
1882 UINT32 state_phase;
\r
1884 } ym_save_addon_slot;
\r
1895 UINT32 eg_cnt; // 10
\r
1900 UINT32 keyon_field; // 20
\r
1901 UINT32 kcode_fc_sl3_3;
\r
1902 UINT32 reserved[2];
\r
1907 UINT16 block_fnum[6];
\r
1908 UINT16 block_fnum_sl3[3];
\r
1909 UINT16 reserved[7];
\r
1913 void YM2612PicoStateSave2(int tat, int tbt)
\r
1915 ym_save_addon_slot ss;
\r
1916 ym_save_addon2 sa2;
\r
1918 unsigned char *ptr;
\r
1921 memset(&sa, 0, sizeof(sa));
\r
1922 memset(&sa2, 0, sizeof(sa2));
\r
1925 ptr = &ym2612.REGS[0x0b8];
\r
1926 for (c = 0; c < 3; c++)
\r
1928 for (s = 0; s < 4; s++) {
\r
1929 ss.state_phase = (ym2612.CH[c].SLOT[s].state << 29) | (ym2612.CH[c].SLOT[s].phase >> 3);
\r
1930 ss.volume = ym2612.CH[c].SLOT[s].volume;
\r
1931 if (ym2612.CH[c].SLOT[s].key)
\r
1932 sa.keyon_field |= 1 << (c*4 + s);
\r
1933 memcpy(ptr, &ss, 6);
\r
1936 sa2.block_fnum[c] = ym2612.CH[c].block_fnum;
\r
1939 ptr = &ym2612.REGS[0x1b8];
\r
1940 for (; c < 6; c++)
\r
1942 for (s = 0; s < 4; s++) {
\r
1943 ss.state_phase = (ym2612.CH[c].SLOT[s].state << 29) | (ym2612.CH[c].SLOT[s].phase >> 3);
\r
1944 ss.volume = ym2612.CH[c].SLOT[s].volume;
\r
1945 if (ym2612.CH[c].SLOT[s].key)
\r
1946 sa.keyon_field |= 1 << (c*4 + s);
\r
1947 memcpy(ptr, &ss, 6);
\r
1950 sa2.block_fnum[c] = ym2612.CH[c].block_fnum;
\r
1952 for (c = 0; c < 3; c++)
\r
1954 sa2.block_fnum_sl3[c] = ym2612.OPN.SL3.block_fnum[c];
\r
1957 memcpy(&ym2612.REGS[0], &sa2, sizeof(sa2)); // 0x20 max
\r
1960 ptr = &ym2612.REGS[0x100];
\r
1961 sa.magic = 0x41534d59; // 'YMSA'
\r
1962 sa.address = ym2612.OPN.ST.address;
\r
1963 sa.status = ym2612.OPN.ST.status;
\r
1964 sa.addr_A1 = ym2612.addr_A1;
\r
1967 sa.eg_cnt = ym2612.OPN.eg_cnt;
\r
1968 sa.eg_timer = ym2612.OPN.eg_timer;
\r
1969 sa.lfo_cnt = ym2612.OPN.lfo_cnt;
\r
1970 sa.lfo_ampm = g_lfo_ampm;
\r
1971 memcpy(ptr, &sa, sizeof(sa)); // 0x30 max
\r
1974 int YM2612PicoStateLoad2(int *tat, int *tbt)
\r
1976 ym_save_addon_slot ss;
\r
1977 ym_save_addon2 sa2;
\r
1979 unsigned char *ptr;
\r
1984 ptr = &ym2612.REGS[0x100];
\r
1985 memcpy(&sa, ptr, sizeof(sa)); // 0x30 max
\r
1986 if (sa.magic != 0x41534d59) return -1;
\r
1988 ptr = &ym2612.REGS[0];
\r
1989 memcpy(&sa2, ptr, sizeof(sa2));
\r
1991 ym2612.OPN.ST.address = sa.address;
\r
1992 ym2612.OPN.ST.status = sa.status;
\r
1993 ym2612.addr_A1 = sa.addr_A1;
\r
1994 ym2612.OPN.eg_cnt = sa.eg_cnt;
\r
1995 ym2612.OPN.eg_timer = sa.eg_timer;
\r
1996 ym2612.OPN.lfo_cnt = sa.lfo_cnt;
\r
1997 g_lfo_ampm = sa.lfo_ampm;
\r
1998 if (tat != NULL) *tat = sa.TAT;
\r
1999 if (tbt != NULL) *tbt = sa.TBT;
\r
2002 ptr = &ym2612.REGS[0x0b8];
\r
2003 for (c = 0; c < 3; c++)
\r
2005 for (s = 0; s < 4; s++) {
\r
2006 memcpy(&ss, ptr, 6);
\r
2007 ym2612.CH[c].SLOT[s].state = ss.state_phase >> 29;
\r
2008 ym2612.CH[c].SLOT[s].phase = ss.state_phase << 3;
\r
2009 ym2612.CH[c].SLOT[s].volume = ss.volume;
\r
2010 ym2612.CH[c].SLOT[s].key = (sa.keyon_field & (1 << (c*4 + s))) ? 1 : 0;
\r
2011 ym2612.CH[c].SLOT[s].ksr = (UINT8)-1;
\r
2014 ym2612.CH[c].SLOT[SLOT1].Incr=-1;
\r
2015 ym2612.CH[c].block_fnum = sa2.block_fnum[c];
\r
2016 fn = ym2612.CH[c].block_fnum & 0x7ff;
\r
2017 blk = ym2612.CH[c].block_fnum >> 11;
\r
2018 ym2612.CH[c].kcode= (blk<<2) | opn_fktable[fn >> 7];
\r
2019 ym2612.CH[c].fc = fn_table[fn*2]>>(7-blk);
\r
2022 ptr = &ym2612.REGS[0x1b8];
\r
2023 for (; c < 6; c++)
\r
2025 for (s = 0; s < 4; s++) {
\r
2026 memcpy(&ss, ptr, 6);
\r
2027 ym2612.CH[c].SLOT[s].state = ss.state_phase >> 29;
\r
2028 ym2612.CH[c].SLOT[s].phase = ss.state_phase << 3;
\r
2029 ym2612.CH[c].SLOT[s].volume = ss.volume;
\r
2030 ym2612.CH[c].SLOT[s].key = (sa.keyon_field & (1 << (c*4 + s))) ? 1 : 0;
\r
2031 ym2612.CH[c].SLOT[s].ksr = (UINT8)-1;
\r
2034 ym2612.CH[c].SLOT[SLOT1].Incr=-1;
\r
2035 ym2612.CH[c].block_fnum = sa2.block_fnum[c];
\r
2036 fn = ym2612.CH[c].block_fnum & 0x7ff;
\r
2037 blk = ym2612.CH[c].block_fnum >> 11;
\r
2038 ym2612.CH[c].kcode= (blk<<2) | opn_fktable[fn >> 7];
\r
2039 ym2612.CH[c].fc = fn_table[fn*2]>>(7-blk);
\r
2041 for (c = 0; c < 3; c++)
\r
2043 ym2612.OPN.SL3.block_fnum[c] = sa2.block_fnum_sl3[c];
\r
2044 fn = ym2612.OPN.SL3.block_fnum[c] & 0x7ff;
\r
2045 blk = ym2612.OPN.SL3.block_fnum[c] >> 11;
\r
2046 ym2612.OPN.SL3.kcode[c]= (blk<<2) | opn_fktable[fn >> 7];
\r
2047 ym2612.OPN.SL3.fc[c] = fn_table[fn*2]>>(7-blk);
\r
2053 void *YM2612GetRegs(void)
\r
2055 return ym2612.REGS;
\r