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
142 #ifndef STRICTINLINE
\r
143 #define STRICTINLINE static inline
\r
147 #define M_PI 3.14159265358979323846
\r
153 #define FREQ_SH 16 /* 16.16 fixed point (frequency calculations) */
\r
154 #define EG_SH 16 /* 16.16 fixed point (envelope generator timing) */
\r
155 #define LFO_SH 25 /* 7.25 fixed point (LFO calculations) */
\r
156 #define TIMER_SH 16 /* 16.16 fixed point (timers calculations) */
\r
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 #define MAXOUT (+32767)
\r
180 #define MINOUT (-32768)
\r
183 #define Limit(val, max,min) { \
\r
184 if ( val > max ) val = max; \
\r
185 else if ( val < min ) val = min; \
\r
189 /* TL_TAB_LEN is calculated as:
\r
190 * 13 - sinus amplitude bits (Y axis)
\r
191 * 2 - sinus sign bit (Y axis)
\r
192 * TL_RES_LEN - sinus resolution (X axis)
\r
194 //#define TL_TAB_LEN (13*2*TL_RES_LEN)
\r
195 #define TL_TAB_LEN (13*TL_RES_LEN*256/8) // 106496*2
\r
196 UINT16 ym_tl_tab[TL_TAB_LEN];
\r
198 /* ~3K wasted but oh well */
\r
199 UINT16 ym_tl_tab2[13*TL_RES_LEN];
\r
201 #define ENV_QUIET (2*13*TL_RES_LEN/8)
\r
203 /* sin waveform table in 'decibel' scale (use only period/4 values) */
\r
204 static UINT16 ym_sin_tab[256];
\r
206 /* sustain level table (3dB per step) */
\r
207 /* bit0, bit1, bit2, bit3, bit4, bit5, bit6 */
\r
208 /* 1, 2, 4, 8, 16, 32, 64 (value)*/
\r
209 /* 0.75, 1.5, 3, 6, 12, 24, 48 (dB)*/
\r
211 /* 0 - 15: 0, 3, 6, 9,12,15,18,21,24,27,30,33,36,39,42,93 (dB)*/
\r
212 #define SC(db) (UINT32) ( db * (4.0/ENV_STEP) )
\r
213 static const UINT32 sl_table[16]={
\r
214 SC( 0),SC( 1),SC( 2),SC(3 ),SC(4 ),SC(5 ),SC(6 ),SC( 7),
\r
215 SC( 8),SC( 9),SC(10),SC(11),SC(12),SC(13),SC(14),SC(31)
\r
221 #define RATE_STEPS (8)
\r
222 static const UINT8 eg_inc[19*RATE_STEPS]={
\r
224 /*cycle:0 1 2 3 4 5 6 7*/
\r
226 /* 0 */ 0,1, 0,1, 0,1, 0,1, /* rates 00..11 0 (increment by 0 or 1) */
\r
227 /* 1 */ 0,1, 0,1, 1,1, 0,1, /* rates 00..11 1 */
\r
228 /* 2 */ 0,1, 1,1, 0,1, 1,1, /* rates 00..11 2 */
\r
229 /* 3 */ 0,1, 1,1, 1,1, 1,1, /* rates 00..11 3 */
\r
231 /* 4 */ 1,1, 1,1, 1,1, 1,1, /* rate 12 0 (increment by 1) */
\r
232 /* 5 */ 1,1, 1,2, 1,1, 1,2, /* rate 12 1 */
\r
233 /* 6 */ 1,2, 1,2, 1,2, 1,2, /* rate 12 2 */
\r
234 /* 7 */ 1,2, 2,2, 1,2, 2,2, /* rate 12 3 */
\r
236 /* 8 */ 2,2, 2,2, 2,2, 2,2, /* rate 13 0 (increment by 2) */
\r
237 /* 9 */ 2,2, 2,4, 2,2, 2,4, /* rate 13 1 */
\r
238 /*10 */ 2,4, 2,4, 2,4, 2,4, /* rate 13 2 */
\r
239 /*11 */ 2,4, 4,4, 2,4, 4,4, /* rate 13 3 */
\r
241 /*12 */ 4,4, 4,4, 4,4, 4,4, /* rate 14 0 (increment by 4) */
\r
242 /*13 */ 4,4, 4,8, 4,4, 4,8, /* rate 14 1 */
\r
243 /*14 */ 4,8, 4,8, 4,8, 4,8, /* rate 14 2 */
\r
244 /*15 */ 4,8, 8,8, 4,8, 8,8, /* rate 14 3 */
\r
246 /*16 */ 8,8, 8,8, 8,8, 8,8, /* rates 15 0, 15 1, 15 2, 15 3 (increment by 8) */
\r
247 /*17 */ 16,16,16,16,16,16,16,16, /* rates 15 2, 15 3 for attack */
\r
248 /*18 */ 0,0, 0,0, 0,0, 0,0, /* infinity rates for attack and decay(s) */
\r
253 #define PACK(a0,a1,a2,a3,a4,a5,a6,a7) ((a7<<21)|(a6<<18)|(a5<<15)|(a4<<12)|(a3<<9)|(a2<<6)|(a1<<3)|(a0<<0))
\r
254 static const UINT32 eg_inc_pack[19] =
\r
256 /* 0 */ PACK(0,1,0,1,0,1,0,1), /* rates 00..11 0 (increment by 0 or 1) */
\r
257 /* 1 */ PACK(0,1,0,1,1,1,0,1), /* rates 00..11 1 */
\r
258 /* 2 */ PACK(0,1,1,1,0,1,1,1), /* rates 00..11 2 */
\r
259 /* 3 */ PACK(0,1,1,1,1,1,1,1), /* rates 00..11 3 */
\r
261 /* 4 */ PACK(1,1,1,1,1,1,1,1), /* rate 12 0 (increment by 1) */
\r
262 /* 5 */ PACK(1,1,1,2,1,1,1,2), /* rate 12 1 */
\r
263 /* 6 */ PACK(1,2,1,2,1,2,1,2), /* rate 12 2 */
\r
264 /* 7 */ PACK(1,2,2,2,1,2,2,2), /* rate 12 3 */
\r
266 /* 8 */ PACK(2,2,2,2,2,2,2,2), /* rate 13 0 (increment by 2) */
\r
267 /* 9 */ PACK(2,2,2,3,2,2,2,3), /* rate 13 1 */
\r
268 /*10 */ PACK(2,3,2,3,2,3,2,3), /* rate 13 2 */
\r
269 /*11 */ PACK(2,3,3,3,2,3,3,3), /* rate 13 3 */
\r
271 /*12 */ PACK(3,3,3,3,3,3,3,3), /* rate 14 0 (increment by 4) */
\r
272 /*13 */ PACK(3,3,3,4,3,3,3,4), /* rate 14 1 */
\r
273 /*14 */ PACK(3,4,3,4,3,4,3,4), /* rate 14 2 */
\r
274 /*15 */ PACK(3,4,4,4,3,4,4,4), /* rate 14 3 */
\r
276 /*16 */ PACK(4,4,4,4,4,4,4,4), /* rates 15 0, 15 1, 15 2, 15 3 (increment by 8) */
\r
277 /*17 */ PACK(5,5,5,5,5,5,5,5), /* rates 15 2, 15 3 for attack */
\r
278 /*18 */ PACK(0,0,0,0,0,0,0,0), /* infinity rates for attack and decay(s) */
\r
282 //#define O(a) (a*RATE_STEPS)
\r
285 /*note that there is no O(17) in this table - it's directly in the code */
\r
286 static const UINT8 eg_rate_select[32+64+32]={ /* Envelope Generator rates (32 + 64 rates + 32 RKS) */
\r
287 /* 32 infinite time rates */
\r
288 O(18),O(18),O(18),O(18),O(18),O(18),O(18),O(18),
\r
289 O(18),O(18),O(18),O(18),O(18),O(18),O(18),O(18),
\r
290 O(18),O(18),O(18),O(18),O(18),O(18),O(18),O(18),
\r
291 O(18),O(18),O(18),O(18),O(18),O(18),O(18),O(18),
\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
302 O( 0),O( 1),O( 2),O( 3),
\r
303 O( 0),O( 1),O( 2),O( 3),
\r
304 O( 0),O( 1),O( 2),O( 3),
\r
305 O( 0),O( 1),O( 2),O( 3),
\r
308 O( 4),O( 5),O( 6),O( 7),
\r
311 O( 8),O( 9),O(10),O(11),
\r
314 O(12),O(13),O(14),O(15),
\r
317 O(16),O(16),O(16),O(16),
\r
319 /* 32 dummy rates (same as 15 3) */
\r
320 O(16),O(16),O(16),O(16),O(16),O(16),O(16),O(16),
\r
321 O(16),O(16),O(16),O(16),O(16),O(16),O(16),O(16),
\r
322 O(16),O(16),O(16),O(16),O(16),O(16),O(16),O(16),
\r
323 O(16),O(16),O(16),O(16),O(16),O(16),O(16),O(16)
\r
328 /*rate 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15*/
\r
329 /*shift 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 0, 0, 0, 0, 0 */
\r
330 /*mask 2047, 1023, 511, 255, 127, 63, 31, 15, 7, 3, 1, 0, 0, 0, 0, 0 */
\r
333 static const UINT8 eg_rate_shift[32+64+32]={ /* Envelope Generator counter shifts (32 + 64 rates + 32 RKS) */
\r
334 /* 32 infinite time rates */
\r
335 O(0),O(0),O(0),O(0),O(0),O(0),O(0),O(0),
\r
336 O(0),O(0),O(0),O(0),O(0),O(0),O(0),O(0),
\r
337 O(0),O(0),O(0),O(0),O(0),O(0),O(0),O(0),
\r
338 O(0),O(0),O(0),O(0),O(0),O(0),O(0),O(0),
\r
341 O(11),O(11),O(11),O(11),
\r
342 O(10),O(10),O(10),O(10),
\r
343 O( 9),O( 9),O( 9),O( 9),
\r
344 O( 8),O( 8),O( 8),O( 8),
\r
345 O( 7),O( 7),O( 7),O( 7),
\r
346 O( 6),O( 6),O( 6),O( 6),
\r
347 O( 5),O( 5),O( 5),O( 5),
\r
348 O( 4),O( 4),O( 4),O( 4),
\r
349 O( 3),O( 3),O( 3),O( 3),
\r
350 O( 2),O( 2),O( 2),O( 2),
\r
351 O( 1),O( 1),O( 1),O( 1),
\r
352 O( 0),O( 0),O( 0),O( 0),
\r
355 O( 0),O( 0),O( 0),O( 0),
\r
358 O( 0),O( 0),O( 0),O( 0),
\r
361 O( 0),O( 0),O( 0),O( 0),
\r
364 O( 0),O( 0),O( 0),O( 0),
\r
366 /* 32 dummy rates (same as 15 3) */
\r
367 O( 0),O( 0),O( 0),O( 0),O( 0),O( 0),O( 0),O( 0),
\r
368 O( 0),O( 0),O( 0),O( 0),O( 0),O( 0),O( 0),O( 0),
\r
369 O( 0),O( 0),O( 0),O( 0),O( 0),O( 0),O( 0),O( 0),
\r
370 O( 0),O( 0),O( 0),O( 0),O( 0),O( 0),O( 0),O( 0)
\r
375 static const UINT8 dt_tab[4 * 32]={
\r
376 /* this is YM2151 and YM2612 phase increment data (in 10.10 fixed point format)*/
\r
378 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
\r
379 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
\r
381 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 2, 2, 2, 2,
\r
382 2, 3, 3, 3, 4, 4, 4, 5, 5, 6, 6, 7, 8, 8, 8, 8,
\r
384 1, 1, 1, 1, 2, 2, 2, 2, 2, 3, 3, 3, 4, 4, 4, 5,
\r
385 5, 6, 6, 7, 8, 8, 9,10,11,12,13,14,16,16,16,16,
\r
387 2, 2, 2, 2, 2, 3, 3, 3, 4, 4, 4, 5, 5, 6, 6, 7,
\r
388 8 ,8, 9,10,11,12,13,14,16,17,19,20,22,22,22,22
\r
392 /* OPN key frequency number -> key code follow table */
\r
393 /* fnum higher 4bit -> keycode lower 2bit */
\r
394 static const UINT8 opn_fktable[16] = {0,0,0,0,0,0,0,1,2,3,3,3,3,3,3,3};
\r
397 /* 8 LFO speed parameters */
\r
398 /* each value represents number of samples that one LFO level will last for */
\r
399 static const UINT32 lfo_samples_per_step[8] = {108, 77, 71, 67, 62, 44, 8, 5};
\r
403 /*There are 4 different LFO AM depths available, they are:
\r
404 0 dB, 1.4 dB, 5.9 dB, 11.8 dB
\r
405 Here is how it is generated (in EG steps):
\r
407 11.8 dB = 0, 2, 4, 6, 8, 10,12,14,16...126,126,124,122,120,118,....4,2,0
\r
408 5.9 dB = 0, 1, 2, 3, 4, 5, 6, 7, 8....63, 63, 62, 61, 60, 59,.....2,1,0
\r
409 1.4 dB = 0, 0, 0, 0, 1, 1, 1, 1, 2,...15, 15, 15, 15, 14, 14,.....0,0,0
\r
411 (1.4 dB is loosing precision as you can see)
\r
413 It's implemented as generator from 0..126 with step 2 then a shift
\r
414 right N times, where N is:
\r
420 static const UINT8 lfo_ams_depth_shift[4] = {8, 3, 1, 0};
\r
424 /*There are 8 different LFO PM depths available, they are:
\r
425 0, 3.4, 6.7, 10, 14, 20, 40, 80 (cents)
\r
427 Modulation level at each depth depends on F-NUMBER bits: 4,5,6,7,8,9,10
\r
428 (bits 8,9,10 = FNUM MSB from OCT/FNUM register)
\r
430 Here we store only first quarter (positive one) of full waveform.
\r
431 Full table (lfo_pm_table) containing all 128 waveforms is build
\r
432 at run (init) time.
\r
434 One value in table below represents 4 (four) basic LFO steps
\r
435 (1 PM step = 4 AM steps).
\r
438 at LFO SPEED=0 (which is 108 samples per basic LFO step)
\r
439 one value from "lfo_pm_output" table lasts for 432 consecutive
\r
440 samples (4*108=432) and one full LFO waveform cycle lasts for 13824
\r
441 samples (32*432=13824; 32 because we store only a quarter of whole
\r
442 waveform in the table below)
\r
444 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
445 /* FNUM BIT 4: 000 0001xxxx */
\r
446 /* DEPTH 0 */ {0, 0, 0, 0, 0, 0, 0, 0},
\r
447 /* DEPTH 1 */ {0, 0, 0, 0, 0, 0, 0, 0},
\r
448 /* DEPTH 2 */ {0, 0, 0, 0, 0, 0, 0, 0},
\r
449 /* DEPTH 3 */ {0, 0, 0, 0, 0, 0, 0, 0},
\r
450 /* DEPTH 4 */ {0, 0, 0, 0, 0, 0, 0, 0},
\r
451 /* DEPTH 5 */ {0, 0, 0, 0, 0, 0, 0, 0},
\r
452 /* DEPTH 6 */ {0, 0, 0, 0, 0, 0, 0, 0},
\r
453 /* DEPTH 7 */ {0, 0, 0, 0, 1, 1, 1, 1},
\r
455 /* FNUM BIT 5: 000 0010xxxx */
\r
456 /* DEPTH 0 */ {0, 0, 0, 0, 0, 0, 0, 0},
\r
457 /* DEPTH 1 */ {0, 0, 0, 0, 0, 0, 0, 0},
\r
458 /* DEPTH 2 */ {0, 0, 0, 0, 0, 0, 0, 0},
\r
459 /* DEPTH 3 */ {0, 0, 0, 0, 0, 0, 0, 0},
\r
460 /* DEPTH 4 */ {0, 0, 0, 0, 0, 0, 0, 0},
\r
461 /* DEPTH 5 */ {0, 0, 0, 0, 0, 0, 0, 0},
\r
462 /* DEPTH 6 */ {0, 0, 0, 0, 1, 1, 1, 1},
\r
463 /* DEPTH 7 */ {0, 0, 1, 1, 2, 2, 2, 3},
\r
465 /* FNUM BIT 6: 000 0100xxxx */
\r
466 /* DEPTH 0 */ {0, 0, 0, 0, 0, 0, 0, 0},
\r
467 /* DEPTH 1 */ {0, 0, 0, 0, 0, 0, 0, 0},
\r
468 /* DEPTH 2 */ {0, 0, 0, 0, 0, 0, 0, 0},
\r
469 /* DEPTH 3 */ {0, 0, 0, 0, 0, 0, 0, 0},
\r
470 /* DEPTH 4 */ {0, 0, 0, 0, 0, 0, 0, 1},
\r
471 /* DEPTH 5 */ {0, 0, 0, 0, 1, 1, 1, 1},
\r
472 /* DEPTH 6 */ {0, 0, 1, 1, 2, 2, 2, 3},
\r
473 /* DEPTH 7 */ {0, 0, 2, 3, 4, 4, 5, 6},
\r
475 /* FNUM BIT 7: 000 1000xxxx */
\r
476 /* DEPTH 0 */ {0, 0, 0, 0, 0, 0, 0, 0},
\r
477 /* DEPTH 1 */ {0, 0, 0, 0, 0, 0, 0, 0},
\r
478 /* DEPTH 2 */ {0, 0, 0, 0, 0, 0, 1, 1},
\r
479 /* DEPTH 3 */ {0, 0, 0, 0, 1, 1, 1, 1},
\r
480 /* DEPTH 4 */ {0, 0, 0, 1, 1, 1, 1, 2},
\r
481 /* DEPTH 5 */ {0, 0, 1, 1, 2, 2, 2, 3},
\r
482 /* DEPTH 6 */ {0, 0, 2, 3, 4, 4, 5, 6},
\r
483 /* DEPTH 7 */ {0, 0, 4, 6, 8, 8, 0xa, 0xc},
\r
485 /* FNUM BIT 8: 001 0000xxxx */
\r
486 /* DEPTH 0 */ {0, 0, 0, 0, 0, 0, 0, 0},
\r
487 /* DEPTH 1 */ {0, 0, 0, 0, 1, 1, 1, 1},
\r
488 /* DEPTH 2 */ {0, 0, 0, 1, 1, 1, 2, 2},
\r
489 /* DEPTH 3 */ {0, 0, 1, 1, 2, 2, 3, 3},
\r
490 /* DEPTH 4 */ {0, 0, 1, 2, 2, 2, 3, 4},
\r
491 /* DEPTH 5 */ {0, 0, 2, 3, 4, 4, 5, 6},
\r
492 /* DEPTH 6 */ {0, 0, 4, 6, 8, 8, 0xa, 0xc},
\r
493 /* DEPTH 7 */ {0, 0, 8, 0xc,0x10,0x10,0x14,0x18},
\r
495 /* FNUM BIT 9: 010 0000xxxx */
\r
496 /* DEPTH 0 */ {0, 0, 0, 0, 0, 0, 0, 0},
\r
497 /* DEPTH 1 */ {0, 0, 0, 0, 2, 2, 2, 2},
\r
498 /* DEPTH 2 */ {0, 0, 0, 2, 2, 2, 4, 4},
\r
499 /* DEPTH 3 */ {0, 0, 2, 2, 4, 4, 6, 6},
\r
500 /* DEPTH 4 */ {0, 0, 2, 4, 4, 4, 6, 8},
\r
501 /* DEPTH 5 */ {0, 0, 4, 6, 8, 8, 0xa, 0xc},
\r
502 /* DEPTH 6 */ {0, 0, 8, 0xc,0x10,0x10,0x14,0x18},
\r
503 /* DEPTH 7 */ {0, 0,0x10,0x18,0x20,0x20,0x28,0x30},
\r
505 /* FNUM BIT10: 100 0000xxxx */
\r
506 /* DEPTH 0 */ {0, 0, 0, 0, 0, 0, 0, 0},
\r
507 /* DEPTH 1 */ {0, 0, 0, 0, 4, 4, 4, 4},
\r
508 /* DEPTH 2 */ {0, 0, 0, 4, 4, 4, 8, 8},
\r
509 /* DEPTH 3 */ {0, 0, 4, 4, 8, 8, 0xc, 0xc},
\r
510 /* DEPTH 4 */ {0, 0, 4, 8, 8, 8, 0xc,0x10},
\r
511 /* DEPTH 5 */ {0, 0, 8, 0xc,0x10,0x10,0x14,0x18},
\r
512 /* DEPTH 6 */ {0, 0,0x10,0x18,0x20,0x20,0x28,0x30},
\r
513 /* DEPTH 7 */ {0, 0,0x20,0x30,0x40,0x40,0x50,0x60},
\r
517 /* all 128 LFO PM waveforms */
\r
518 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
520 /* there are 2048 FNUMs that can be generated using FNUM/BLK registers
\r
521 but LFO works with one more bit of a precision so we really need 4096 elements */
\r
522 static UINT32 fn_table[4096]; /* fnumber->increment counter */
\r
524 static int g_lfo_ampm = 0;
\r
526 /* register number to channel number , slot offset */
\r
527 #define OPN_CHAN(N) (N&3)
\r
528 #define OPN_SLOT(N) ((N>>2)&3)
\r
537 /* OPN Mode Register Write */
\r
538 INLINE void set_timers( int v )
\r
540 /* b7 = CSM MODE */
\r
541 /* b6 = 3 slot mode */
\r
544 /* b3 = timer enable b */
\r
545 /* b2 = timer enable a */
\r
548 ym2612.OPN.ST.mode = v;
\r
550 /* reset Timer b flag */
\r
552 ym2612.OPN.ST.status &= ~2;
\r
554 /* reset Timer a flag */
\r
556 ym2612.OPN.ST.status &= ~1;
\r
560 INLINE void FM_KEYON(int c , int s )
\r
562 FM_SLOT *SLOT = &ym2612.CH[c].SLOT[s];
\r
566 SLOT->phase = 0; /* restart Phase Generator */
\r
567 SLOT->state = EG_ATT; /* phase -> Attack */
\r
568 ym2612.slot_mask |= (1<<s) << (c*4);
\r
572 INLINE void FM_KEYOFF(int c , int s )
\r
574 FM_SLOT *SLOT = &ym2612.CH[c].SLOT[s];
\r
578 if (SLOT->state>EG_REL)
\r
579 SLOT->state = EG_REL;/* phase -> Release */
\r
584 /* set detune & multiple */
\r
585 INLINE void set_det_mul(FM_CH *CH, FM_SLOT *SLOT, int v)
\r
587 SLOT->mul = (v&0x0f)? (v&0x0f)*2 : 1;
\r
588 SLOT->DT = ym2612.OPN.ST.dt_tab[(v>>4)&7];
\r
589 CH->SLOT[SLOT1].Incr=-1;
\r
592 /* set total level */
\r
593 INLINE void set_tl(FM_SLOT *SLOT, int v)
\r
595 SLOT->tl = (v&0x7f)<<(ENV_BITS-7); /* 7bit TL */
\r
598 /* set attack rate & key scale */
\r
599 INLINE void set_ar_ksr(FM_CH *CH, FM_SLOT *SLOT, int v)
\r
601 UINT8 old_KSR = SLOT->KSR;
\r
603 SLOT->ar = (v&0x1f) ? 32 + ((v&0x1f)<<1) : 0;
\r
605 SLOT->KSR = 3-(v>>6);
\r
606 if (SLOT->KSR != old_KSR)
\r
608 CH->SLOT[SLOT1].Incr=-1;
\r
612 int eg_sh_ar, eg_sel_ar;
\r
614 /* refresh Attack rate */
\r
615 if ((SLOT->ar + SLOT->ksr) < 32+62)
\r
617 eg_sh_ar = eg_rate_shift [SLOT->ar + SLOT->ksr ];
\r
618 eg_sel_ar = eg_rate_select[SLOT->ar + SLOT->ksr ];
\r
626 SLOT->eg_pack_ar = eg_inc_pack[eg_sel_ar] | (eg_sh_ar<<24);
\r
630 /* set decay rate */
\r
631 INLINE void set_dr(FM_SLOT *SLOT, int v)
\r
633 int eg_sh_d1r, eg_sel_d1r;
\r
635 SLOT->d1r = (v&0x1f) ? 32 + ((v&0x1f)<<1) : 0;
\r
637 eg_sh_d1r = eg_rate_shift [SLOT->d1r + SLOT->ksr];
\r
638 eg_sel_d1r= eg_rate_select[SLOT->d1r + SLOT->ksr];
\r
640 SLOT->eg_pack_d1r = eg_inc_pack[eg_sel_d1r] | (eg_sh_d1r<<24);
\r
643 /* set sustain rate */
\r
644 INLINE void set_sr(FM_SLOT *SLOT, int v)
\r
646 int eg_sh_d2r, eg_sel_d2r;
\r
648 SLOT->d2r = (v&0x1f) ? 32 + ((v&0x1f)<<1) : 0;
\r
650 eg_sh_d2r = eg_rate_shift [SLOT->d2r + SLOT->ksr];
\r
651 eg_sel_d2r= eg_rate_select[SLOT->d2r + SLOT->ksr];
\r
653 SLOT->eg_pack_d2r = eg_inc_pack[eg_sel_d2r] | (eg_sh_d2r<<24);
\r
656 /* set release rate */
\r
657 INLINE void set_sl_rr(FM_SLOT *SLOT, int v)
\r
659 int eg_sh_rr, eg_sel_rr;
\r
661 SLOT->sl = sl_table[ v>>4 ];
\r
663 SLOT->rr = 34 + ((v&0x0f)<<2);
\r
665 eg_sh_rr = eg_rate_shift [SLOT->rr + SLOT->ksr];
\r
666 eg_sel_rr = eg_rate_select[SLOT->rr + SLOT->ksr];
\r
668 SLOT->eg_pack_rr = eg_inc_pack[eg_sel_rr] | (eg_sh_rr<<24);
\r
673 INLINE signed int op_calc(UINT32 phase, unsigned int env, signed int pm)
\r
675 int ret, sin = (phase>>16) + (pm>>1);
\r
676 int neg = sin & 0x200;
\r
677 if (sin & 0x100) sin ^= 0xff;
\r
681 // this was already checked
\r
682 // if (env >= ENV_QUIET) // 384
\r
685 ret = ym_tl_tab[sin | (env<<7)];
\r
687 return neg ? -ret : ret;
\r
690 INLINE signed int op_calc1(UINT32 phase, unsigned int env, signed int pm)
\r
692 int ret, sin = (phase+pm)>>16;
\r
693 int neg = sin & 0x200;
\r
694 if (sin & 0x100) sin ^= 0xff;
\r
698 // if (env >= ENV_QUIET) // 384
\r
701 ret = ym_tl_tab[sin | (env<<7)];
\r
703 return neg ? -ret : ret;
\r
706 #if !defined(_ASM_YM2612_C) || defined(EXTERNAL_YM2612)
\r
707 /* advance LFO to next sample */
\r
708 INLINE int advance_lfo(int lfo_ampm, UINT32 lfo_cnt_old, UINT32 lfo_cnt)
\r
713 prev_pos = (lfo_cnt_old >> LFO_SH) & 127;
\r
715 pos = (lfo_cnt >> LFO_SH) & 127;
\r
717 /* update AM when LFO output changes */
\r
719 if (prev_pos != pos)
\r
723 /* AM: 0 to 126 step +2, 126 to 0 step -2 */
\r
725 lfo_ampm |= ((pos&63) * 2) << 8; /* 0 - 126 */
\r
727 lfo_ampm |= (126 - (pos&63)*2) << 8;
\r
734 /* PM works with 4 times slower clock */
\r
737 /* update PM when LFO output changes */
\r
738 if (prev_pos != pos)
\r
741 lfo_ampm |= pos; /* 0 - 32 */
\r
746 #define EG_INC_VAL() \
\r
747 ((1 << ((pack >> ((eg_cnt>>shift)&7)*3)&7)) >> 1)
\r
749 STRICTINLINE UINT32 update_eg_phase(FM_SLOT *SLOT, UINT32 eg_cnt)
\r
751 INT32 volume = SLOT->volume;
\r
753 switch(SLOT->state)
\r
755 case EG_ATT: /* attack phase */
\r
757 UINT32 pack = SLOT->eg_pack_ar;
\r
758 UINT32 shift = pack>>24;
\r
759 if ( !(eg_cnt & ((1<<shift)-1) ) )
\r
761 volume += ( ~volume * EG_INC_VAL() ) >>4;
\r
763 if (volume <= MIN_ATT_INDEX)
\r
765 volume = MIN_ATT_INDEX;
\r
766 SLOT->state = EG_DEC;
\r
772 case EG_DEC: /* decay phase */
\r
774 UINT32 pack = SLOT->eg_pack_d1r;
\r
775 UINT32 shift = pack>>24;
\r
776 if ( !(eg_cnt & ((1<<shift)-1) ) )
\r
778 volume += EG_INC_VAL();
\r
780 if ( volume >= (INT32) SLOT->sl )
\r
781 SLOT->state = EG_SUS;
\r
786 case EG_SUS: /* sustain phase */
\r
788 UINT32 pack = SLOT->eg_pack_d2r;
\r
789 UINT32 shift = pack>>24;
\r
790 if ( !(eg_cnt & ((1<<shift)-1) ) )
\r
792 volume += EG_INC_VAL();
\r
794 if ( volume >= MAX_ATT_INDEX )
\r
796 volume = MAX_ATT_INDEX;
\r
797 /* do not change SLOT->state (verified on real chip) */
\r
803 case EG_REL: /* release phase */
\r
805 UINT32 pack = SLOT->eg_pack_rr;
\r
806 UINT32 shift = pack>>24;
\r
807 if ( !(eg_cnt & ((1<<shift)-1) ) )
\r
809 volume += EG_INC_VAL();
\r
811 if ( volume >= MAX_ATT_INDEX )
\r
813 volume = MAX_ATT_INDEX;
\r
814 SLOT->state = EG_OFF;
\r
821 SLOT->volume = volume;
\r
822 return SLOT->tl + ((UINT32)volume); /* tl is 7bit<<3, volume 0-1023 (0-2039 total) */
\r
829 UINT16 vol_out1; /* 00: current output from EG circuit (without AM from LFO) */
\r
834 UINT32 phase1; /* 10 */
\r
838 UINT32 incr1; /* 20: phase step */
\r
842 UINT32 lfo_cnt; /* 30 */
\r
844 INT32 mem; /* one sample delay memory */
\r
845 UINT32 eg_cnt; /* envelope generator counter */
\r
846 FM_CH *CH; /* 40: envelope generator counter */
\r
848 UINT32 eg_timer_add;
\r
849 UINT32 pack; // 4c: stereo, lastchan, disabled, lfo_enabled | pan_r, pan_l, ams[2] | AMmasks[4] | FB[4] | lfo_ampm[16]
\r
850 UINT32 algo; /* 50: algo[3], was_update */
\r
852 #ifdef _MIPS_ARCH_ALLEGREX
\r
855 } chan_rend_context;
\r
858 #if !defined(_ASM_YM2612_C) || defined(EXTERNAL_YM2612)
\r
859 static void chan_render_loop(chan_rend_context *ct, int *buffer, int length)
\r
861 int scounter; /* sample counter */
\r
863 /* sample generating loop */
\r
864 for (scounter = 0; scounter < length; scounter++)
\r
866 int smp = 0; /* produced sample */
\r
867 unsigned int eg_out, eg_out2, eg_out4;
\r
869 if (ct->pack & 8) { /* LFO enabled ? (test Earthworm Jim in between demo 1 and 2) */
\r
870 ct->pack = (ct->pack&0xffff) | (advance_lfo(ct->pack >> 16, ct->lfo_cnt, ct->lfo_cnt + ct->lfo_inc) << 16);
\r
871 ct->lfo_cnt += ct->lfo_inc;
\r
874 ct->eg_timer += ct->eg_timer_add;
\r
875 while (ct->eg_timer >= EG_TIMER_OVERFLOW)
\r
877 ct->eg_timer -= EG_TIMER_OVERFLOW;
\r
880 if (ct->CH->SLOT[SLOT1].state != EG_OFF) ct->vol_out1 = update_eg_phase(&ct->CH->SLOT[SLOT1], ct->eg_cnt);
\r
881 if (ct->CH->SLOT[SLOT2].state != EG_OFF) ct->vol_out2 = update_eg_phase(&ct->CH->SLOT[SLOT2], ct->eg_cnt);
\r
882 if (ct->CH->SLOT[SLOT3].state != EG_OFF) ct->vol_out3 = update_eg_phase(&ct->CH->SLOT[SLOT3], ct->eg_cnt);
\r
883 if (ct->CH->SLOT[SLOT4].state != EG_OFF) ct->vol_out4 = update_eg_phase(&ct->CH->SLOT[SLOT4], ct->eg_cnt);
\r
886 if (ct->pack & 4) continue; /* output disabled */
\r
888 /* calculate channel sample */
\r
889 eg_out = ct->vol_out1;
\r
890 if ( (ct->pack & 8) && (ct->pack&(1<<(SLOT1+8))) ) eg_out += ct->pack >> (((ct->pack&0xc0)>>6)+24);
\r
892 if( eg_out < ENV_QUIET ) /* SLOT 1 */
\r
896 if (ct->pack&0xf000) out = ((ct->op1_out>>16) + ((ct->op1_out<<16)>>16)) << ((ct->pack&0xf000)>>12); /* op1_out0 + op1_out1 */
\r
897 ct->op1_out <<= 16;
\r
898 ct->op1_out |= (unsigned short)op_calc1(ct->phase1, eg_out, out);
\r
900 ct->op1_out <<= 16; /* op1_out0 = op1_out1; op1_out1 = 0; */
\r
903 eg_out = ct->vol_out3; // volume_calc(&CH->SLOT[SLOT3]);
\r
904 eg_out2 = ct->vol_out2; // volume_calc(&CH->SLOT[SLOT2]);
\r
905 eg_out4 = ct->vol_out4; // volume_calc(&CH->SLOT[SLOT4]);
\r
907 if (ct->pack & 8) {
\r
908 unsigned int add = ct->pack >> (((ct->pack&0xc0)>>6)+24);
\r
909 if (ct->pack & (1<<(SLOT3+8))) eg_out += add;
\r
910 if (ct->pack & (1<<(SLOT2+8))) eg_out2 += add;
\r
911 if (ct->pack & (1<<(SLOT4+8))) eg_out4 += add;
\r
914 switch( ct->CH->ALGO )
\r
918 /* M1---C1---MEM---M2---C2---OUT */
\r
919 int m2,c1,c2=0; /* Phase Modulation input for operators 2,3,4 */
\r
921 c1 = ct->op1_out>>16;
\r
922 if( eg_out < ENV_QUIET ) { /* SLOT 3 */
\r
923 c2 = op_calc(ct->phase3, eg_out, m2);
\r
925 if( eg_out2 < ENV_QUIET ) { /* SLOT 2 */
\r
926 ct->mem = op_calc(ct->phase2, eg_out2, c1);
\r
929 if( eg_out4 < ENV_QUIET ) { /* SLOT 4 */
\r
930 smp = op_calc(ct->phase4, eg_out4, c2);
\r
936 /* M1------+-MEM---M2---C2---OUT */
\r
940 ct->mem = ct->op1_out>>16;
\r
941 if( eg_out < ENV_QUIET ) { /* SLOT 3 */
\r
942 c2 = op_calc(ct->phase3, eg_out, m2);
\r
944 if( eg_out2 < ENV_QUIET ) { /* SLOT 2 */
\r
945 ct->mem+= op_calc(ct->phase2, eg_out2, 0);
\r
947 if( eg_out4 < ENV_QUIET ) { /* SLOT 4 */
\r
948 smp = op_calc(ct->phase4, eg_out4, c2);
\r
954 /* M1-----------------+-C2---OUT */
\r
955 /* C1---MEM---M2-+ */
\r
958 c2 = ct->op1_out>>16;
\r
959 if( eg_out < ENV_QUIET ) { /* SLOT 3 */
\r
960 c2 += op_calc(ct->phase3, eg_out, m2);
\r
962 if( eg_out2 < ENV_QUIET ) { /* SLOT 2 */
\r
963 ct->mem = op_calc(ct->phase2, eg_out2, 0);
\r
966 if( eg_out4 < ENV_QUIET ) { /* SLOT 4 */
\r
967 smp = op_calc(ct->phase4, eg_out4, c2);
\r
973 /* M1---C1---MEM------+-C2---OUT */
\r
977 c1 = ct->op1_out>>16;
\r
978 if( eg_out < ENV_QUIET ) { /* SLOT 3 */
\r
979 c2 += op_calc(ct->phase3, eg_out, 0);
\r
981 if( eg_out2 < ENV_QUIET ) { /* SLOT 2 */
\r
982 ct->mem = op_calc(ct->phase2, eg_out2, c1);
\r
985 if( eg_out4 < ENV_QUIET ) { /* SLOT 4 */
\r
986 smp = op_calc(ct->phase4, eg_out4, c2);
\r
992 /* M1---C1-+-OUT */
\r
994 /* MEM: not used */
\r
996 c1 = ct->op1_out>>16;
\r
997 if( eg_out < ENV_QUIET ) { /* SLOT 3 */
\r
998 c2 = op_calc(ct->phase3, eg_out, 0);
\r
1000 if( eg_out2 < ENV_QUIET ) { /* SLOT 2 */
\r
1001 smp = op_calc(ct->phase2, eg_out2, c1);
\r
1003 if( eg_out4 < ENV_QUIET ) { /* SLOT 4 */
\r
1004 smp+= op_calc(ct->phase4, eg_out4, c2);
\r
1010 /* +----C1----+ */
\r
1011 /* M1-+-MEM---M2-+-OUT */
\r
1012 /* +----C2----+ */
\r
1015 ct->mem = c1 = c2 = ct->op1_out>>16;
\r
1016 if( eg_out < ENV_QUIET ) { /* SLOT 3 */
\r
1017 smp = op_calc(ct->phase3, eg_out, m2);
\r
1019 if( eg_out2 < ENV_QUIET ) { /* SLOT 2 */
\r
1020 smp+= op_calc(ct->phase2, eg_out2, c1);
\r
1022 if( eg_out4 < ENV_QUIET ) { /* SLOT 4 */
\r
1023 smp+= op_calc(ct->phase4, eg_out4, c2);
\r
1032 /* MEM: not used */
\r
1034 c1 = ct->op1_out>>16;
\r
1035 if( eg_out < ENV_QUIET ) { /* SLOT 3 */
\r
1036 smp = op_calc(ct->phase3, eg_out, 0);
\r
1038 if( eg_out2 < ENV_QUIET ) { /* SLOT 2 */
\r
1039 smp+= op_calc(ct->phase2, eg_out2, c1);
\r
1041 if( eg_out4 < ENV_QUIET ) { /* SLOT 4 */
\r
1042 smp+= op_calc(ct->phase4, eg_out4, 0);
\r
1052 /* MEM: not used*/
\r
1053 smp = ct->op1_out>>16;
\r
1054 if( eg_out < ENV_QUIET ) { /* SLOT 3 */
\r
1055 smp += op_calc(ct->phase3, eg_out, 0);
\r
1057 if( eg_out2 < ENV_QUIET ) { /* SLOT 2 */
\r
1058 smp += op_calc(ct->phase2, eg_out2, 0);
\r
1060 if( eg_out4 < ENV_QUIET ) { /* SLOT 4 */
\r
1061 smp += op_calc(ct->phase4, eg_out4, 0);
\r
1066 /* done calculating channel sample */
\r
1068 /* mix sample to output buffer */
\r
1070 if (ct->pack & 1) { /* stereo */
\r
1071 if (ct->pack & 0x20) /* L */ /* TODO: check correctness */
\r
1072 buffer[scounter*2] += smp;
\r
1073 if (ct->pack & 0x10) /* R */
\r
1074 buffer[scounter*2+1] += smp;
\r
1076 buffer[scounter] += smp;
\r
1078 ct->algo = 8; // algo is only used in asm, here only bit3 is used
\r
1081 /* update phase counters AFTER output calculations */
\r
1082 ct->phase1 += ct->incr1;
\r
1083 ct->phase2 += ct->incr2;
\r
1084 ct->phase3 += ct->incr3;
\r
1085 ct->phase4 += ct->incr4;
\r
1089 void chan_render_loop(chan_rend_context *ct, int *buffer, unsigned short length);
\r
1092 static chan_rend_context crct;
\r
1094 static void chan_render_prep(void)
\r
1096 crct.eg_timer_add = ym2612.OPN.eg_timer_add;
\r
1097 crct.lfo_inc = ym2612.OPN.lfo_inc;
\r
1100 static void chan_render_finish(void)
\r
1102 ym2612.OPN.eg_cnt = crct.eg_cnt;
\r
1103 ym2612.OPN.eg_timer = crct.eg_timer;
\r
1104 g_lfo_ampm = crct.pack >> 16; // need_save
\r
1105 ym2612.OPN.lfo_cnt = crct.lfo_cnt;
\r
1108 static int chan_render(int *buffer, int length, int c, UINT32 flags) // flags: stereo, ?, disabled, ?, pan_r, pan_l
\r
1110 crct.CH = &ym2612.CH[c];
\r
1111 crct.mem = crct.CH->mem_value; /* one sample delay memory */
\r
1112 crct.lfo_cnt = ym2612.OPN.lfo_cnt;
\r
1116 if (crct.lfo_inc) {
\r
1118 flags |= g_lfo_ampm << 16;
\r
1119 flags |= crct.CH->AMmasks << 8;
\r
1120 if (crct.CH->ams == 8) // no ams
\r
1122 else flags |= (crct.CH->ams&3)<<6;
\r
1124 flags |= (crct.CH->FB&0xf)<<12; /* feedback shift */
\r
1125 crct.pack = flags;
\r
1127 crct.eg_cnt = ym2612.OPN.eg_cnt; /* envelope generator counter */
\r
1128 crct.eg_timer = ym2612.OPN.eg_timer;
\r
1130 /* precalculate phase modulation incr */
\r
1131 crct.phase1 = crct.CH->SLOT[SLOT1].phase;
\r
1132 crct.phase2 = crct.CH->SLOT[SLOT2].phase;
\r
1133 crct.phase3 = crct.CH->SLOT[SLOT3].phase;
\r
1134 crct.phase4 = crct.CH->SLOT[SLOT4].phase;
\r
1136 /* current output from EG circuit (without AM from LFO) */
\r
1137 crct.vol_out1 = crct.CH->SLOT[SLOT1].tl + ((UINT32)crct.CH->SLOT[SLOT1].volume);
\r
1138 crct.vol_out2 = crct.CH->SLOT[SLOT2].tl + ((UINT32)crct.CH->SLOT[SLOT2].volume);
\r
1139 crct.vol_out3 = crct.CH->SLOT[SLOT3].tl + ((UINT32)crct.CH->SLOT[SLOT3].volume);
\r
1140 crct.vol_out4 = crct.CH->SLOT[SLOT4].tl + ((UINT32)crct.CH->SLOT[SLOT4].volume);
\r
1142 crct.op1_out = crct.CH->op1_out;
\r
1143 crct.algo = crct.CH->ALGO & 7;
\r
1147 /* add support for 3 slot mode */
\r
1148 UINT32 block_fnum = crct.CH->block_fnum;
\r
1150 UINT32 fnum_lfo = ((block_fnum & 0x7f0) >> 4) * 32 * 8;
\r
1151 INT32 lfo_fn_table_index_offset = lfo_pm_table[ fnum_lfo + crct.CH->pms + ((crct.pack>>16)&0xff) ];
\r
1153 if (lfo_fn_table_index_offset) /* LFO phase modulation active */
\r
1159 blk = block_fnum >> 11;
\r
1160 block_fnum = block_fnum*2 + lfo_fn_table_index_offset;
\r
1162 fn = block_fnum & 0xfff;
\r
1164 /* keyscale code */
\r
1165 kc = (blk<<2) | opn_fktable[fn >> 8];
\r
1166 /* phase increment counter */
\r
1167 fc = fn_table[fn]>>(7-blk);
\r
1169 crct.incr1 = ((fc+crct.CH->SLOT[SLOT1].DT[kc])*crct.CH->SLOT[SLOT1].mul) >> 1;
\r
1170 crct.incr2 = ((fc+crct.CH->SLOT[SLOT2].DT[kc])*crct.CH->SLOT[SLOT2].mul) >> 1;
\r
1171 crct.incr3 = ((fc+crct.CH->SLOT[SLOT3].DT[kc])*crct.CH->SLOT[SLOT3].mul) >> 1;
\r
1172 crct.incr4 = ((fc+crct.CH->SLOT[SLOT4].DT[kc])*crct.CH->SLOT[SLOT4].mul) >> 1;
\r
1174 else /* LFO phase modulation = zero */
\r
1176 crct.incr1 = crct.CH->SLOT[SLOT1].Incr;
\r
1177 crct.incr2 = crct.CH->SLOT[SLOT2].Incr;
\r
1178 crct.incr3 = crct.CH->SLOT[SLOT3].Incr;
\r
1179 crct.incr4 = crct.CH->SLOT[SLOT4].Incr;
\r
1182 else /* no LFO phase modulation */
\r
1184 crct.incr1 = crct.CH->SLOT[SLOT1].Incr;
\r
1185 crct.incr2 = crct.CH->SLOT[SLOT2].Incr;
\r
1186 crct.incr3 = crct.CH->SLOT[SLOT3].Incr;
\r
1187 crct.incr4 = crct.CH->SLOT[SLOT4].Incr;
\r
1190 chan_render_loop(&crct, buffer, length);
\r
1192 crct.CH->op1_out = crct.op1_out;
\r
1193 crct.CH->mem_value = crct.mem;
\r
1194 if (crct.CH->SLOT[SLOT1].state | crct.CH->SLOT[SLOT2].state | crct.CH->SLOT[SLOT3].state | crct.CH->SLOT[SLOT4].state)
\r
1196 crct.CH->SLOT[SLOT1].phase = crct.phase1;
\r
1197 crct.CH->SLOT[SLOT2].phase = crct.phase2;
\r
1198 crct.CH->SLOT[SLOT3].phase = crct.phase3;
\r
1199 crct.CH->SLOT[SLOT4].phase = crct.phase4;
\r
1202 ym2612.slot_mask &= ~(0xf << (c*4));
\r
1204 return (crct.algo & 8) >> 3; // had output
\r
1207 /* update phase increment and envelope generator */
\r
1208 STRICTINLINE void refresh_fc_eg_slot(FM_SLOT *SLOT, int fc, int kc)
\r
1212 /* (frequency) phase increment counter */
\r
1213 fdt = fc+SLOT->DT[kc];
\r
1214 /* detect overflow */
\r
1215 // if (fdt < 0) fdt += fn_table[0x7ff*2] >> (7-blk-1);
\r
1216 if (fdt < 0) fdt += fn_table[0x7ff*2] >> 2;
\r
1217 SLOT->Incr = fdt*SLOT->mul >> 1;
\r
1219 ksr = kc >> SLOT->KSR;
\r
1220 if( SLOT->ksr != ksr )
\r
1222 int eg_sh, eg_sel;
\r
1225 /* calculate envelope generator rates */
\r
1226 if ((SLOT->ar + ksr) < 32+62)
\r
1228 eg_sh = eg_rate_shift [SLOT->ar + ksr ];
\r
1229 eg_sel = eg_rate_select[SLOT->ar + ksr ];
\r
1237 SLOT->eg_pack_ar = eg_inc_pack[eg_sel] | (eg_sh<<24);
\r
1239 eg_sh = eg_rate_shift [SLOT->d1r + ksr];
\r
1240 eg_sel = eg_rate_select[SLOT->d1r + ksr];
\r
1242 SLOT->eg_pack_d1r = eg_inc_pack[eg_sel] | (eg_sh<<24);
\r
1244 eg_sh = eg_rate_shift [SLOT->d2r + ksr];
\r
1245 eg_sel = eg_rate_select[SLOT->d2r + ksr];
\r
1247 SLOT->eg_pack_d2r = eg_inc_pack[eg_sel] | (eg_sh<<24);
\r
1249 eg_sh = eg_rate_shift [SLOT->rr + ksr];
\r
1250 eg_sel = eg_rate_select[SLOT->rr + ksr];
\r
1252 SLOT->eg_pack_rr = eg_inc_pack[eg_sel] | (eg_sh<<24);
\r
1256 /* update phase increment counters */
\r
1257 void refresh_fc_eg_chan(FM_CH *CH)
\r
1259 if( CH->SLOT[SLOT1].Incr==-1){
\r
1261 int kc = CH->kcode;
\r
1262 refresh_fc_eg_slot(&CH->SLOT[SLOT1] , fc , kc );
\r
1263 refresh_fc_eg_slot(&CH->SLOT[SLOT2] , fc , kc );
\r
1264 refresh_fc_eg_slot(&CH->SLOT[SLOT3] , fc , kc );
\r
1265 refresh_fc_eg_slot(&CH->SLOT[SLOT4] , fc , kc );
\r
1269 void refresh_fc_eg_chan_sl3(void)
\r
1271 if( ym2612.CH[2].SLOT[SLOT1].Incr==-1)
\r
1273 refresh_fc_eg_slot(&ym2612.CH[2].SLOT[SLOT1], ym2612.OPN.SL3.fc[1], ym2612.OPN.SL3.kcode[1] );
\r
1274 refresh_fc_eg_slot(&ym2612.CH[2].SLOT[SLOT2], ym2612.OPN.SL3.fc[2], ym2612.OPN.SL3.kcode[2] );
\r
1275 refresh_fc_eg_slot(&ym2612.CH[2].SLOT[SLOT3], ym2612.OPN.SL3.fc[0], ym2612.OPN.SL3.kcode[0] );
\r
1276 refresh_fc_eg_slot(&ym2612.CH[2].SLOT[SLOT4], ym2612.CH[2].fc , ym2612.CH[2].kcode );
\r
1280 /* initialize time tables */
\r
1281 static void init_timetables(const UINT8 *dttable)
\r
1286 /* DeTune table */
\r
1287 for (d = 0;d <= 3;d++){
\r
1288 for (i = 0;i <= 31;i++){
\r
1289 rate = ((double)dttable[d*32 + i]) * SIN_LEN * ym2612.OPN.ST.freqbase * (1<<FREQ_SH) / ((double)(1<<20));
\r
1290 ym2612.OPN.ST.dt_tab[d][i] = (INT32) rate;
\r
1291 ym2612.OPN.ST.dt_tab[d+4][i] = -ym2612.OPN.ST.dt_tab[d][i];
\r
1297 static void reset_channels(FM_CH *CH)
\r
1301 ym2612.OPN.ST.mode = 0; /* normal mode */
\r
1302 ym2612.OPN.ST.TA = 0;
\r
1303 ym2612.OPN.ST.TAC = 0;
\r
1304 ym2612.OPN.ST.TB = 0;
\r
1305 ym2612.OPN.ST.TBC = 0;
\r
1307 for( c = 0 ; c < 6 ; c++ )
\r
1310 for(s = 0 ; s < 4 ; s++ )
\r
1312 CH[c].SLOT[s].state= EG_OFF;
\r
1313 CH[c].SLOT[s].volume = MAX_ATT_INDEX;
\r
1315 CH[c].mem_value = CH[c].op1_out = 0;
\r
1317 ym2612.slot_mask = 0;
\r
1320 /* initialize generic tables */
\r
1321 static void init_tables(void)
\r
1323 signed int i,x,y,p;
\r
1327 for (i=0; i < 256; i++)
\r
1329 /* non-standard sinus */
\r
1330 m = sin( ((i*2)+1) * M_PI / SIN_LEN ); /* checked against the real chip */
\r
1332 /* we never reach zero here due to ((i*2)+1) */
\r
1335 o = 8*log(1.0/m)/log(2); /* convert to 'decibels' */
\r
1337 o = 8*log(-1.0/m)/log(2); /* convert to 'decibels' */
\r
1339 o = o / (ENV_STEP/4);
\r
1342 if (n&1) /* round to nearest */
\r
1347 ym_sin_tab[ i ] = n;
\r
1348 //dprintf("FM.C: sin [%4i]= %4i", i, ym_sin_tab[i]);
\r
1351 //dprintf("FM.C: ENV_QUIET= %08x", ENV_QUIET );
\r
1354 for (x=0; x < TL_RES_LEN; x++)
\r
1356 m = (1<<16) / pow(2, (x+1) * (ENV_STEP/4.0) / 8.0);
\r
1359 /* we never reach (1<<16) here due to the (x+1) */
\r
1360 /* result fits within 16 bits at maximum */
\r
1362 n = (int)m; /* 16 bits here */
\r
1363 n >>= 4; /* 12 bits here */
\r
1364 if (n&1) /* round to nearest */
\r
1368 /* 11 bits here (rounded) */
\r
1369 n <<= 2; /* 13 bits here (as in real chip) */
\r
1370 ym_tl_tab2[ x ] = n;
\r
1372 for (i=1; i < 13; i++)
\r
1374 ym_tl_tab2[ x + i*TL_RES_LEN ] = n >> i;
\r
1378 for (x=0; x < 256; x++)
\r
1380 int sin = ym_sin_tab[ x ];
\r
1382 for (y=0; y < 2*13*TL_RES_LEN/8; y+=2)
\r
1385 if (p >= 13*TL_RES_LEN)
\r
1386 ym_tl_tab[(y<<7) | x] = 0;
\r
1387 else ym_tl_tab[(y<<7) | x] = ym_tl_tab2[p];
\r
1392 /* build LFO PM modulation table */
\r
1393 for(i = 0; i < 8; i++) /* 8 PM depths */
\r
1396 for (fnum=0; fnum<128; fnum++) /* 7 bits meaningful of F-NUMBER */
\r
1400 UINT32 offset_depth = i;
\r
1401 UINT32 offset_fnum_bit;
\r
1404 for (step=0; step<8; step++)
\r
1407 for (bit_tmp=0; bit_tmp<7; bit_tmp++) /* 7 bits */
\r
1409 if (fnum & (1<<bit_tmp)) /* only if bit "bit_tmp" is set */
\r
1411 offset_fnum_bit = bit_tmp * 8;
\r
1412 value += lfo_pm_output[offset_fnum_bit + offset_depth][step];
\r
1415 lfo_pm_table[(fnum*32*8) + (i*32) + step + 0] = value;
\r
1416 lfo_pm_table[(fnum*32*8) + (i*32) +(step^7)+ 8] = value;
\r
1417 lfo_pm_table[(fnum*32*8) + (i*32) + step +16] = -value;
\r
1418 lfo_pm_table[(fnum*32*8) + (i*32) +(step^7)+24] = -value;
\r
1425 /* CSM Key Controll */
\r
1427 INLINE void CSMKeyControll(FM_CH *CH)
\r
1429 /* this is wrong, atm */
\r
1432 FM_KEYON(CH,SLOT1);
\r
1433 FM_KEYON(CH,SLOT2);
\r
1434 FM_KEYON(CH,SLOT3);
\r
1435 FM_KEYON(CH,SLOT4);
\r
1440 /* prescaler set (and make time tables) */
\r
1441 static void OPNSetPres(int pres)
\r
1445 /* frequency base */
\r
1446 ym2612.OPN.ST.freqbase = (ym2612.OPN.ST.rate) ? ((double)ym2612.OPN.ST.clock / ym2612.OPN.ST.rate) / pres : 0;
\r
1448 ym2612.OPN.eg_timer_add = (1<<EG_SH) * ym2612.OPN.ST.freqbase;
\r
1450 /* make time tables */
\r
1451 init_timetables( dt_tab );
\r
1453 /* there are 2048 FNUMs that can be generated using FNUM/BLK registers
\r
1454 but LFO works with one more bit of a precision so we really need 4096 elements */
\r
1455 /* calculate fnumber -> increment counter table */
\r
1456 for(i = 0; i < 4096; i++)
\r
1458 /* freq table for octave 7 */
\r
1459 /* OPN phase increment counter = 20bit */
\r
1460 fn_table[i] = (UINT32)( (double)i * 32 * ym2612.OPN.ST.freqbase * (1<<(FREQ_SH-10)) ); /* -10 because chip works with 10.10 fixed point, while we use 16.16 */
\r
1463 /* LFO freq. table */
\r
1464 for(i = 0; i < 8; i++)
\r
1466 /* Amplitude modulation: 64 output levels (triangle waveform); 1 level lasts for one of "lfo_samples_per_step" samples */
\r
1467 /* Phase modulation: one entry from lfo_pm_output lasts for one of 4 * "lfo_samples_per_step" samples */
\r
1468 ym2612.OPN.lfo_freq[i] = (1.0 / lfo_samples_per_step[i]) * (1<<LFO_SH) * ym2612.OPN.ST.freqbase;
\r
1473 /* write a OPN register (0x30-0xff) */
\r
1474 static int OPNWriteReg(int r, int v)
\r
1480 UINT8 c = OPN_CHAN(r);
\r
1482 if (c == 3) return 0; /* 0xX3,0xX7,0xXB,0xXF */
\r
1484 if (r >= 0x100) c+=3;
\r
1486 CH = &ym2612.CH[c];
\r
1488 SLOT = &(CH->SLOT[OPN_SLOT(r)]);
\r
1490 switch( r & 0xf0 ) {
\r
1491 case 0x30: /* DET , MUL */
\r
1492 set_det_mul(CH,SLOT,v);
\r
1495 case 0x40: /* TL */
\r
1499 case 0x50: /* KS, AR */
\r
1500 set_ar_ksr(CH,SLOT,v);
\r
1503 case 0x60: /* bit7 = AM ENABLE, DR | depends on ksr */
\r
1505 if(v&0x80) CH->AMmasks |= 1<<OPN_SLOT(r);
\r
1506 else CH->AMmasks &= ~(1<<OPN_SLOT(r));
\r
1509 case 0x70: /* SR | depends on ksr */
\r
1513 case 0x80: /* SL, RR | depends on ksr */
\r
1514 set_sl_rr(SLOT,v);
\r
1517 case 0x90: /* SSG-EG */
\r
1523 switch( OPN_SLOT(r) ){
\r
1524 case 0: /* 0xa0-0xa2 : FNUM1 | depends on fn_h (below) */
\r
1526 UINT32 fn = (((UINT32)( (CH->fn_h)&7))<<8) + v;
\r
1527 UINT8 blk = CH->fn_h>>3;
\r
1528 /* keyscale code */
\r
1529 CH->kcode = (blk<<2) | opn_fktable[fn >> 7];
\r
1530 /* phase increment counter */
\r
1531 CH->fc = fn_table[fn*2]>>(7-blk);
\r
1533 /* store fnum in clear form for LFO PM calculations */
\r
1534 CH->block_fnum = (blk<<11) | fn;
\r
1536 CH->SLOT[SLOT1].Incr=-1;
\r
1539 case 1: /* 0xa4-0xa6 : FNUM2,BLK */
\r
1540 CH->fn_h = v&0x3f;
\r
1543 case 2: /* 0xa8-0xaa : 3CH FNUM1 */
\r
1546 UINT32 fn = (((UINT32)(ym2612.OPN.SL3.fn_h&7))<<8) + v;
\r
1547 UINT8 blk = ym2612.OPN.SL3.fn_h>>3;
\r
1548 /* keyscale code */
\r
1549 ym2612.OPN.SL3.kcode[c]= (blk<<2) | opn_fktable[fn >> 7];
\r
1550 /* phase increment counter */
\r
1551 ym2612.OPN.SL3.fc[c] = fn_table[fn*2]>>(7-blk);
\r
1552 ym2612.OPN.SL3.block_fnum[c] = (blk<<11) | fn;
\r
1553 ym2612.CH[2].SLOT[SLOT1].Incr=-1;
\r
1556 case 3: /* 0xac-0xae : 3CH FNUM2,BLK */
\r
1558 ym2612.OPN.SL3.fn_h = v&0x3f;
\r
1568 switch( OPN_SLOT(r) ){
\r
1569 case 0: /* 0xb0-0xb2 : FB,ALGO */
\r
1571 int feedback = (v>>3)&7;
\r
1573 CH->FB = feedback ? feedback+6 : 0;
\r
1576 case 1: /* 0xb4-0xb6 : L , R , AMS , PMS (YM2612/YM2610B/YM2610/YM2608) */
\r
1578 int panshift = c<<1;
\r
1581 CH->pms = (v & 7) * 32; /* CH->pms = PM depth * 32 (index in lfo_pm_table) */
\r
1584 CH->ams = lfo_ams_depth_shift[(v>>4) & 3];
\r
1586 /* PAN : b7 = L, b6 = R */
\r
1587 ym2612.OPN.pan &= ~(3<<panshift);
\r
1588 ym2612.OPN.pan |= ((v & 0xc0) >> 6) << panshift; // ..LRLR
\r
1605 /*******************************************************************************/
\r
1606 /* YM2612 local section */
\r
1607 /*******************************************************************************/
\r
1609 /* Generate samples for YM2612 */
\r
1610 int YM2612UpdateOne_(int *buffer, int length, int stereo, int is_buf_empty)
\r
1613 int active_chs = 0;
\r
1615 // if !is_buf_empty, it means it has valid samples to mix with, else it may contain trash
\r
1616 if (is_buf_empty) memset32(buffer, 0, length<<stereo);
\r
1622 for (c = 0; c < 6; c++) {
\r
1624 printf("%i: ", c);
\r
1625 for (s = 0; s < 4; s++) {
\r
1626 if (ym2612.CH[c].SLOT[s].state != EG_OFF) slr = 1;
\r
1627 printf(" %i", ym2612.CH[c].SLOT[s].state != EG_OFF);
\r
1629 slm = (ym2612.slot_mask&(0xf<<(c*4))) ? 1 : 0;
\r
1630 printf(" | %i", slm);
\r
1631 printf(" | %i\n", ym2612.CH[c].SLOT[SLOT1].Incr==-1);
\r
1632 if (slr != slm) exit(1);
\r
1636 /* refresh PG and EG */
\r
1637 refresh_fc_eg_chan( &ym2612.CH[0] );
\r
1638 refresh_fc_eg_chan( &ym2612.CH[1] );
\r
1639 if( (ym2612.OPN.ST.mode & 0xc0) )
\r
1641 refresh_fc_eg_chan_sl3();
\r
1643 refresh_fc_eg_chan( &ym2612.CH[2] );
\r
1644 refresh_fc_eg_chan( &ym2612.CH[3] );
\r
1645 refresh_fc_eg_chan( &ym2612.CH[4] );
\r
1646 refresh_fc_eg_chan( &ym2612.CH[5] );
\r
1648 pan = ym2612.OPN.pan;
\r
1649 if (stereo) stereo = 1;
\r
1651 /* mix to 32bit dest */
\r
1652 // flags: stereo, ?, disabled, ?, pan_r, pan_l
\r
1653 chan_render_prep();
\r
1654 if (ym2612.slot_mask & 0x00000f) active_chs |= chan_render(buffer, length, 0, stereo|((pan&0x003)<<4)) << 0;
\r
1655 if (ym2612.slot_mask & 0x0000f0) active_chs |= chan_render(buffer, length, 1, stereo|((pan&0x00c)<<2)) << 1;
\r
1656 if (ym2612.slot_mask & 0x000f00) active_chs |= chan_render(buffer, length, 2, stereo|((pan&0x030) )) << 2;
\r
1657 if (ym2612.slot_mask & 0x00f000) active_chs |= chan_render(buffer, length, 3, stereo|((pan&0x0c0)>>2)) << 3;
\r
1658 if (ym2612.slot_mask & 0x0f0000) active_chs |= chan_render(buffer, length, 4, stereo|((pan&0x300)>>4)) << 4;
\r
1659 if (ym2612.slot_mask & 0xf00000) active_chs |= chan_render(buffer, length, 5, stereo|((pan&0xc00)>>6)|(ym2612.dacen<<2)) << 5;
\r
1660 chan_render_finish();
\r
1662 return active_chs; // 1 if buffer updated
\r
1666 /* initialize YM2612 emulator */
\r
1667 void YM2612Init_(int clock, int rate)
\r
1669 memset(&ym2612, 0, sizeof(ym2612));
\r
1672 ym2612.OPN.ST.clock = clock;
\r
1673 ym2612.OPN.ST.rate = rate;
\r
1675 OPNSetPres( 6*24 );
\r
1677 /* Extend handler */
\r
1678 YM2612ResetChip_();
\r
1683 void YM2612ResetChip_(void)
\r
1687 memset(ym2612.REGS, 0, sizeof(ym2612.REGS));
\r
1689 set_timers( 0x30 ); /* mode 0 , timer reset */
\r
1690 ym2612.REGS[0x27] = 0x30;
\r
1692 ym2612.OPN.eg_timer = 0;
\r
1693 ym2612.OPN.eg_cnt = 0;
\r
1694 ym2612.OPN.ST.status = 0;
\r
1696 reset_channels( &ym2612.CH[0] );
\r
1697 for(i = 0xb6 ; i >= 0xb4 ; i-- )
\r
1699 OPNWriteReg(i ,0xc0);
\r
1700 OPNWriteReg(i|0x100,0xc0);
\r
1701 ym2612.REGS[i ] = 0xc0;
\r
1702 ym2612.REGS[i|0x100] = 0xc0;
\r
1704 for(i = 0xb2 ; i >= 0x30 ; i-- )
\r
1706 OPNWriteReg(i ,0);
\r
1707 OPNWriteReg(i|0x100,0);
\r
1709 for(i = 0x26 ; i >= 0x20 ; i-- ) OPNWriteReg(i,0);
\r
1710 /* DAC mode clear */
\r
1712 ym2612.addr_A1 = 0;
\r
1716 /* YM2612 write */
\r
1719 /* returns 1 if sample affecting state changed */
\r
1720 int YM2612Write_(unsigned int a, unsigned int v)
\r
1724 v &= 0xff; /* adjust to 8 bit bus */
\r
1727 case 0: /* address port 0 */
\r
1728 ym2612.OPN.ST.address = v;
\r
1729 ym2612.addr_A1 = 0;
\r
1733 case 1: /* data port 0 */
\r
1734 if (ym2612.addr_A1 != 0) {
\r
1736 break; /* verified on real YM2608 */
\r
1739 addr = ym2612.OPN.ST.address;
\r
1741 switch( addr & 0xf0 )
\r
1743 case 0x20: /* 0x20-0x2f Mode */
\r
1746 case 0x22: /* LFO FREQ (YM2608/YM2610/YM2610B/YM2612) */
\r
1747 if (v&0x08) /* LFO enabled ? */
\r
1749 ym2612.OPN.lfo_inc = ym2612.OPN.lfo_freq[v&7];
\r
1753 ym2612.OPN.lfo_inc = 0;
\r
1756 #if 0 // handled elsewhere
\r
1757 case 0x24: { // timer A High 8
\r
1758 int TAnew = (ym2612.OPN.ST.TA & 0x03)|(((int)v)<<2);
\r
1759 if(ym2612.OPN.ST.TA != TAnew) {
\r
1760 // we should reset ticker only if new value is written. Outrun requires this.
\r
1761 ym2612.OPN.ST.TA = TAnew;
\r
1762 ym2612.OPN.ST.TAC = (1024-TAnew)*18;
\r
1763 ym2612.OPN.ST.TAT = 0;
\r
1768 case 0x25: { // timer A Low 2
\r
1769 int TAnew = (ym2612.OPN.ST.TA & 0x3fc)|(v&3);
\r
1770 if(ym2612.OPN.ST.TA != TAnew) {
\r
1771 ym2612.OPN.ST.TA = TAnew;
\r
1772 ym2612.OPN.ST.TAC = (1024-TAnew)*18;
\r
1773 ym2612.OPN.ST.TAT = 0;
\r
1778 case 0x26: // timer B
\r
1779 if(ym2612.OPN.ST.TB != v) {
\r
1780 ym2612.OPN.ST.TB = v;
\r
1781 ym2612.OPN.ST.TBC = (256-v)<<4;
\r
1782 ym2612.OPN.ST.TBC *= 18;
\r
1783 ym2612.OPN.ST.TBT = 0;
\r
1788 case 0x27: /* mode, timer control */
\r
1792 case 0x28: /* key on / off */
\r
1797 if( c == 3 ) { ret=0; break; }
\r
1798 if( v&0x04 ) c+=3;
\r
1799 if(v&0x10) FM_KEYON(c,SLOT1); else FM_KEYOFF(c,SLOT1);
\r
1800 if(v&0x20) FM_KEYON(c,SLOT2); else FM_KEYOFF(c,SLOT2);
\r
1801 if(v&0x40) FM_KEYON(c,SLOT3); else FM_KEYOFF(c,SLOT3);
\r
1802 if(v&0x80) FM_KEYON(c,SLOT4); else FM_KEYOFF(c,SLOT4);
\r
1805 case 0x2a: /* DAC data (YM2612) */
\r
1806 ym2612.dacout = ((int)v - 0x80) << 6; /* level unknown (notaz: 8 seems to be too much) */
\r
1809 case 0x2b: /* DAC Sel (YM2612) */
\r
1810 /* b7 = dac enable */
\r
1811 ym2612.dacen = v & 0x80;
\r
1818 default: /* 0x30-0xff OPN section */
\r
1819 /* write register */
\r
1820 ret = OPNWriteReg(addr,v);
\r
1824 case 2: /* address port 1 */
\r
1825 ym2612.OPN.ST.address = v;
\r
1826 ym2612.addr_A1 = 1;
\r
1830 case 3: /* data port 1 */
\r
1831 if (ym2612.addr_A1 != 1) {
\r
1833 break; /* verified on real YM2608 */
\r
1836 addr = ym2612.OPN.ST.address | 0x100;
\r
1838 ret = OPNWriteReg(addr, v);
\r
1846 UINT8 YM2612Read_(void)
\r
1848 return ym2612.OPN.ST.status;
\r
1851 int YM2612PicoTick_(int n)
\r
1856 if(ym2612.OPN.ST.mode & 0x01 && (ym2612.OPN.ST.TAT+=64*n) >= ym2612.OPN.ST.TAC) {
\r
1857 ym2612.OPN.ST.TAT -= ym2612.OPN.ST.TAC;
\r
1858 if(ym2612.OPN.ST.mode & 0x04) ym2612.OPN.ST.status |= 1;
\r
1859 // CSM mode total level latch and auto key on
\r
1860 if(ym2612.OPN.ST.mode & 0x80) {
\r
1861 CSMKeyControll( &(ym2612.CH[2]) ); // Vectorman2, etc.
\r
1867 if(ym2612.OPN.ST.mode & 0x02 && (ym2612.OPN.ST.TBT+=64*n) >= ym2612.OPN.ST.TBC) {
\r
1868 ym2612.OPN.ST.TBT -= ym2612.OPN.ST.TBC;
\r
1869 if(ym2612.OPN.ST.mode & 0x08) ym2612.OPN.ST.status |= 2;
\r
1876 void YM2612PicoStateLoad_(void)
\r
1878 reset_channels( &ym2612.CH[0] );
\r
1879 ym2612.slot_mask = 0xffffff;
\r
1882 /* rather stupid design because I wanted to fit in unused register "space" */
\r
1885 UINT32 state_phase;
\r
1887 } ym_save_addon_slot;
\r
1898 UINT32 eg_cnt; // 10
\r
1903 UINT32 keyon_field; // 20
\r
1904 UINT32 kcode_fc_sl3_3;
\r
1905 UINT32 reserved[2];
\r
1910 UINT16 block_fnum[6];
\r
1911 UINT16 block_fnum_sl3[3];
\r
1912 UINT16 reserved[7];
\r
1916 void YM2612PicoStateSave2(int tat, int tbt)
\r
1918 ym_save_addon_slot ss;
\r
1919 ym_save_addon2 sa2;
\r
1921 unsigned char *ptr;
\r
1924 memset(&sa, 0, sizeof(sa));
\r
1925 memset(&sa2, 0, sizeof(sa2));
\r
1928 ptr = &ym2612.REGS[0x0b8];
\r
1929 for (c = 0; c < 3; c++)
\r
1931 for (s = 0; s < 4; s++) {
\r
1932 ss.state_phase = (ym2612.CH[c].SLOT[s].state << 29) | (ym2612.CH[c].SLOT[s].phase >> 3);
\r
1933 ss.volume = ym2612.CH[c].SLOT[s].volume;
\r
1934 if (ym2612.CH[c].SLOT[s].key)
\r
1935 sa.keyon_field |= 1 << (c*4 + s);
\r
1936 memcpy(ptr, &ss, 6);
\r
1939 sa2.block_fnum[c] = ym2612.CH[c].block_fnum;
\r
1942 ptr = &ym2612.REGS[0x1b8];
\r
1943 for (; c < 6; c++)
\r
1945 for (s = 0; s < 4; s++) {
\r
1946 ss.state_phase = (ym2612.CH[c].SLOT[s].state << 29) | (ym2612.CH[c].SLOT[s].phase >> 3);
\r
1947 ss.volume = ym2612.CH[c].SLOT[s].volume;
\r
1948 if (ym2612.CH[c].SLOT[s].key)
\r
1949 sa.keyon_field |= 1 << (c*4 + s);
\r
1950 memcpy(ptr, &ss, 6);
\r
1953 sa2.block_fnum[c] = ym2612.CH[c].block_fnum;
\r
1955 for (c = 0; c < 3; c++)
\r
1957 sa2.block_fnum_sl3[c] = ym2612.OPN.SL3.block_fnum[c];
\r
1960 memcpy(&ym2612.REGS[0], &sa2, sizeof(sa2)); // 0x20 max
\r
1963 ptr = &ym2612.REGS[0x100];
\r
1964 sa.magic = 0x41534d59; // 'YMSA'
\r
1965 sa.address = ym2612.OPN.ST.address;
\r
1966 sa.status = ym2612.OPN.ST.status;
\r
1967 sa.addr_A1 = ym2612.addr_A1;
\r
1970 sa.eg_cnt = ym2612.OPN.eg_cnt;
\r
1971 sa.eg_timer = ym2612.OPN.eg_timer;
\r
1972 sa.lfo_cnt = ym2612.OPN.lfo_cnt;
\r
1973 sa.lfo_ampm = g_lfo_ampm;
\r
1974 memcpy(ptr, &sa, sizeof(sa)); // 0x30 max
\r
1977 int YM2612PicoStateLoad2(int *tat, int *tbt)
\r
1979 ym_save_addon_slot ss;
\r
1980 ym_save_addon2 sa2;
\r
1982 unsigned char *ptr;
\r
1987 ptr = &ym2612.REGS[0x100];
\r
1988 memcpy(&sa, ptr, sizeof(sa)); // 0x30 max
\r
1989 if (sa.magic != 0x41534d59) return -1;
\r
1991 ptr = &ym2612.REGS[0];
\r
1992 memcpy(&sa2, ptr, sizeof(sa2));
\r
1994 ym2612.OPN.ST.address = sa.address;
\r
1995 ym2612.OPN.ST.status = sa.status;
\r
1996 ym2612.addr_A1 = sa.addr_A1;
\r
1997 ym2612.OPN.eg_cnt = sa.eg_cnt;
\r
1998 ym2612.OPN.eg_timer = sa.eg_timer;
\r
1999 ym2612.OPN.lfo_cnt = sa.lfo_cnt;
\r
2000 g_lfo_ampm = sa.lfo_ampm;
\r
2001 if (tat != NULL) *tat = sa.TAT;
\r
2002 if (tbt != NULL) *tbt = sa.TBT;
\r
2005 ptr = &ym2612.REGS[0x0b8];
\r
2006 for (c = 0; c < 3; c++)
\r
2008 for (s = 0; s < 4; s++) {
\r
2009 memcpy(&ss, ptr, 6);
\r
2010 ym2612.CH[c].SLOT[s].state = ss.state_phase >> 29;
\r
2011 ym2612.CH[c].SLOT[s].phase = ss.state_phase << 3;
\r
2012 ym2612.CH[c].SLOT[s].volume = ss.volume;
\r
2013 ym2612.CH[c].SLOT[s].key = (sa.keyon_field & (1 << (c*4 + s))) ? 1 : 0;
\r
2014 ym2612.CH[c].SLOT[s].ksr = (UINT8)-1;
\r
2017 ym2612.CH[c].SLOT[SLOT1].Incr=-1;
\r
2018 ym2612.CH[c].block_fnum = sa2.block_fnum[c];
\r
2019 fn = ym2612.CH[c].block_fnum & 0x7ff;
\r
2020 blk = ym2612.CH[c].block_fnum >> 11;
\r
2021 ym2612.CH[c].kcode= (blk<<2) | opn_fktable[fn >> 7];
\r
2022 ym2612.CH[c].fc = fn_table[fn*2]>>(7-blk);
\r
2025 ptr = &ym2612.REGS[0x1b8];
\r
2026 for (; c < 6; c++)
\r
2028 for (s = 0; s < 4; s++) {
\r
2029 memcpy(&ss, ptr, 6);
\r
2030 ym2612.CH[c].SLOT[s].state = ss.state_phase >> 29;
\r
2031 ym2612.CH[c].SLOT[s].phase = ss.state_phase << 3;
\r
2032 ym2612.CH[c].SLOT[s].volume = ss.volume;
\r
2033 ym2612.CH[c].SLOT[s].key = (sa.keyon_field & (1 << (c*4 + s))) ? 1 : 0;
\r
2034 ym2612.CH[c].SLOT[s].ksr = (UINT8)-1;
\r
2037 ym2612.CH[c].SLOT[SLOT1].Incr=-1;
\r
2038 ym2612.CH[c].block_fnum = sa2.block_fnum[c];
\r
2039 fn = ym2612.CH[c].block_fnum & 0x7ff;
\r
2040 blk = ym2612.CH[c].block_fnum >> 11;
\r
2041 ym2612.CH[c].kcode= (blk<<2) | opn_fktable[fn >> 7];
\r
2042 ym2612.CH[c].fc = fn_table[fn*2]>>(7-blk);
\r
2044 for (c = 0; c < 3; c++)
\r
2046 ym2612.OPN.SL3.block_fnum[c] = sa2.block_fnum_sl3[c];
\r
2047 fn = ym2612.OPN.SL3.block_fnum[c] & 0x7ff;
\r
2048 blk = ym2612.OPN.SL3.block_fnum[c] >> 11;
\r
2049 ym2612.OPN.SL3.kcode[c]= (blk<<2) | opn_fktable[fn >> 7];
\r
2050 ym2612.OPN.SL3.fc[c] = fn_table[fn*2]>>(7-blk);
\r
2056 void *YM2612GetRegs(void)
\r
2058 return ym2612.REGS;
\r