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 ym2612.slot_mask |= (1<<s) << (c*4);
\r
568 INLINE void FM_KEYOFF(int c , int s )
\r
570 FM_SLOT *SLOT = &ym2612.CH[c].SLOT[s];
\r
574 if (SLOT->state>EG_REL)
\r
575 SLOT->state = EG_REL;/* phase -> Release */
\r
580 /* set detune & multiple */
\r
581 INLINE void set_det_mul(FM_CH *CH, FM_SLOT *SLOT, int v)
\r
583 SLOT->mul = (v&0x0f)? (v&0x0f)*2 : 1;
\r
584 SLOT->DT = ym2612.OPN.ST.dt_tab[(v>>4)&7];
\r
585 CH->SLOT[SLOT1].Incr=-1;
\r
588 /* set total level */
\r
589 INLINE void set_tl(FM_SLOT *SLOT, int v)
\r
591 SLOT->tl = (v&0x7f)<<(ENV_BITS-7); /* 7bit TL */
\r
594 /* set attack rate & key scale */
\r
595 INLINE void set_ar_ksr(FM_CH *CH, FM_SLOT *SLOT, int v)
\r
597 UINT8 old_KSR = SLOT->KSR;
\r
599 SLOT->ar = (v&0x1f) ? 32 + ((v&0x1f)<<1) : 0;
\r
601 SLOT->KSR = 3-(v>>6);
\r
602 if (SLOT->KSR != old_KSR)
\r
604 CH->SLOT[SLOT1].Incr=-1;
\r
608 int eg_sh_ar, eg_sel_ar;
\r
610 /* refresh Attack rate */
\r
611 if ((SLOT->ar + SLOT->ksr) < 32+62)
\r
613 eg_sh_ar = eg_rate_shift [SLOT->ar + SLOT->ksr ];
\r
614 eg_sel_ar = eg_rate_select[SLOT->ar + SLOT->ksr ];
\r
622 SLOT->eg_pack_ar = eg_inc_pack[eg_sel_ar] | (eg_sh_ar<<24);
\r
626 /* set decay rate */
\r
627 INLINE void set_dr(FM_SLOT *SLOT, int v)
\r
629 int eg_sh_d1r, eg_sel_d1r;
\r
631 SLOT->d1r = (v&0x1f) ? 32 + ((v&0x1f)<<1) : 0;
\r
633 eg_sh_d1r = eg_rate_shift [SLOT->d1r + SLOT->ksr];
\r
634 eg_sel_d1r= eg_rate_select[SLOT->d1r + SLOT->ksr];
\r
636 SLOT->eg_pack_d1r = eg_inc_pack[eg_sel_d1r] | (eg_sh_d1r<<24);
\r
639 /* set sustain rate */
\r
640 INLINE void set_sr(FM_SLOT *SLOT, int v)
\r
642 int eg_sh_d2r, eg_sel_d2r;
\r
644 SLOT->d2r = (v&0x1f) ? 32 + ((v&0x1f)<<1) : 0;
\r
646 eg_sh_d2r = eg_rate_shift [SLOT->d2r + SLOT->ksr];
\r
647 eg_sel_d2r= eg_rate_select[SLOT->d2r + SLOT->ksr];
\r
649 SLOT->eg_pack_d2r = eg_inc_pack[eg_sel_d2r] | (eg_sh_d2r<<24);
\r
652 /* set release rate */
\r
653 INLINE void set_sl_rr(FM_SLOT *SLOT, int v)
\r
655 int eg_sh_rr, eg_sel_rr;
\r
657 SLOT->sl = sl_table[ v>>4 ];
\r
659 SLOT->rr = 34 + ((v&0x0f)<<2);
\r
661 eg_sh_rr = eg_rate_shift [SLOT->rr + SLOT->ksr];
\r
662 eg_sel_rr = eg_rate_select[SLOT->rr + SLOT->ksr];
\r
664 SLOT->eg_pack_rr = eg_inc_pack[eg_sel_rr] | (eg_sh_rr<<24);
\r
669 INLINE signed int op_calc(UINT32 phase, unsigned int env, signed int pm)
\r
671 int ret, sin = (phase>>16) + (pm>>1);
\r
672 int neg = sin & 0x200;
\r
673 if (sin & 0x100) sin ^= 0xff;
\r
677 // this was already checked
\r
678 // if (env >= ENV_QUIET) // 384
\r
681 ret = ym_tl_tab[sin | (env<<7)];
\r
683 return neg ? -ret : ret;
\r
686 INLINE signed int op_calc1(UINT32 phase, unsigned int env, signed int pm)
\r
688 int ret, sin = (phase+pm)>>16;
\r
689 int neg = sin & 0x200;
\r
690 if (sin & 0x100) sin ^= 0xff;
\r
694 // if (env >= ENV_QUIET) // 384
\r
697 ret = ym_tl_tab[sin | (env<<7)];
\r
699 return neg ? -ret : ret;
\r
702 #if !defined(_ASM_YM2612_C) || defined(EXTERNAL_YM2612)
\r
703 /* advance LFO to next sample */
\r
704 INLINE int advance_lfo(int lfo_ampm, UINT32 lfo_cnt_old, UINT32 lfo_cnt)
\r
709 prev_pos = (lfo_cnt_old >> LFO_SH) & 127;
\r
711 pos = (lfo_cnt >> LFO_SH) & 127;
\r
713 /* update AM when LFO output changes */
\r
715 if (prev_pos != pos)
\r
719 /* AM: 0 to 126 step +2, 126 to 0 step -2 */
\r
721 lfo_ampm |= ((pos&63) * 2) << 8; /* 0 - 126 */
\r
723 lfo_ampm |= (126 - (pos&63)*2) << 8;
\r
730 /* PM works with 4 times slower clock */
\r
733 /* update PM when LFO output changes */
\r
734 if (prev_pos != pos)
\r
737 lfo_ampm |= pos; /* 0 - 32 */
\r
742 #define EG_INC_VAL() \
\r
743 ((1 << ((pack >> ((eg_cnt>>shift)&7)*3)&7)) >> 1)
\r
745 INLINE UINT32 update_eg_phase(FM_SLOT *SLOT, UINT32 eg_cnt)
\r
747 INT32 volume = SLOT->volume;
\r
749 switch(SLOT->state)
\r
751 case EG_ATT: /* attack phase */
\r
753 UINT32 pack = SLOT->eg_pack_ar;
\r
754 UINT32 shift = pack>>24;
\r
755 if ( !(eg_cnt & ((1<<shift)-1) ) )
\r
757 volume += ( ~volume * EG_INC_VAL() ) >>4;
\r
759 if (volume <= MIN_ATT_INDEX)
\r
761 volume = MIN_ATT_INDEX;
\r
762 SLOT->state = EG_DEC;
\r
768 case EG_DEC: /* decay phase */
\r
770 UINT32 pack = SLOT->eg_pack_d1r;
\r
771 UINT32 shift = pack>>24;
\r
772 if ( !(eg_cnt & ((1<<shift)-1) ) )
\r
774 volume += EG_INC_VAL();
\r
776 if ( volume >= (INT32) SLOT->sl )
\r
777 SLOT->state = EG_SUS;
\r
782 case EG_SUS: /* sustain phase */
\r
784 UINT32 pack = SLOT->eg_pack_d2r;
\r
785 UINT32 shift = pack>>24;
\r
786 if ( !(eg_cnt & ((1<<shift)-1) ) )
\r
788 volume += EG_INC_VAL();
\r
790 if ( volume >= MAX_ATT_INDEX )
\r
792 volume = MAX_ATT_INDEX;
\r
793 /* do not change SLOT->state (verified on real chip) */
\r
799 case EG_REL: /* release phase */
\r
801 UINT32 pack = SLOT->eg_pack_rr;
\r
802 UINT32 shift = pack>>24;
\r
803 if ( !(eg_cnt & ((1<<shift)-1) ) )
\r
805 volume += EG_INC_VAL();
\r
807 if ( volume >= MAX_ATT_INDEX )
\r
809 volume = MAX_ATT_INDEX;
\r
810 SLOT->state = EG_OFF;
\r
817 SLOT->volume = volume;
\r
818 return SLOT->tl + ((UINT32)volume); /* tl is 7bit<<3, volume 0-1023 (0-2039 total) */
\r
825 UINT16 vol_out1; /* 00: current output from EG circuit (without AM from LFO) */
\r
830 UINT32 phase1; /* 10 */
\r
834 UINT32 incr1; /* 20: phase step */
\r
838 UINT32 lfo_cnt; /* 30 */
\r
840 INT32 mem; /* one sample delay memory */
\r
841 UINT32 eg_cnt; /* envelope generator counter */
\r
842 FM_CH *CH; /* 40: envelope generator counter */
\r
844 UINT32 eg_timer_add;
\r
845 UINT32 pack; // 4c: stereo, lastchan, disabled, lfo_enabled | pan_r, pan_l, ams[2] | AMmasks[4] | FB[4] | lfo_ampm[16]
\r
846 UINT32 algo; /* 50: algo[3], was_update */
\r
848 #ifdef _MIPS_ARCH_ALLEGREX
\r
851 } chan_rend_context;
\r
854 #if !defined(_ASM_YM2612_C) || defined(EXTERNAL_YM2612)
\r
855 static void chan_render_loop(chan_rend_context *ct, int *buffer, int length)
\r
857 int scounter; /* sample counter */
\r
859 /* sample generating loop */
\r
860 for (scounter = 0; scounter < length; scounter++)
\r
862 int smp = 0; /* produced sample */
\r
863 unsigned int eg_out, eg_out2, eg_out4;
\r
865 if (ct->pack & 8) { /* LFO enabled ? (test Earthworm Jim in between demo 1 and 2) */
\r
866 ct->pack = (ct->pack&0xffff) | (advance_lfo(ct->pack >> 16, ct->lfo_cnt, ct->lfo_cnt + ct->lfo_inc) << 16);
\r
867 ct->lfo_cnt += ct->lfo_inc;
\r
870 ct->eg_timer += ct->eg_timer_add;
\r
871 while (ct->eg_timer >= EG_TIMER_OVERFLOW)
\r
873 ct->eg_timer -= EG_TIMER_OVERFLOW;
\r
876 if (ct->CH->SLOT[SLOT1].state != EG_OFF) ct->vol_out1 = update_eg_phase(&ct->CH->SLOT[SLOT1], ct->eg_cnt);
\r
877 if (ct->CH->SLOT[SLOT2].state != EG_OFF) ct->vol_out2 = update_eg_phase(&ct->CH->SLOT[SLOT2], ct->eg_cnt);
\r
878 if (ct->CH->SLOT[SLOT3].state != EG_OFF) ct->vol_out3 = update_eg_phase(&ct->CH->SLOT[SLOT3], ct->eg_cnt);
\r
879 if (ct->CH->SLOT[SLOT4].state != EG_OFF) ct->vol_out4 = update_eg_phase(&ct->CH->SLOT[SLOT4], ct->eg_cnt);
\r
882 if (ct->pack & 4) continue; /* output disabled */
\r
884 /* calculate channel sample */
\r
885 eg_out = ct->vol_out1;
\r
886 if ( (ct->pack & 8) && (ct->pack&(1<<(SLOT1+8))) ) eg_out += ct->pack >> (((ct->pack&0xc0)>>6)+24);
\r
888 if( eg_out < ENV_QUIET ) /* SLOT 1 */
\r
892 if (ct->pack&0xf000) out = ((ct->op1_out>>16) + ((ct->op1_out<<16)>>16)) << ((ct->pack&0xf000)>>12); /* op1_out0 + op1_out1 */
\r
893 ct->op1_out <<= 16;
\r
894 ct->op1_out |= (unsigned short)op_calc1(ct->phase1, eg_out, out);
\r
896 ct->op1_out <<= 16; /* op1_out0 = op1_out1; op1_out1 = 0; */
\r
899 eg_out = ct->vol_out3; // volume_calc(&CH->SLOT[SLOT3]);
\r
900 eg_out2 = ct->vol_out2; // volume_calc(&CH->SLOT[SLOT2]);
\r
901 eg_out4 = ct->vol_out4; // volume_calc(&CH->SLOT[SLOT4]);
\r
903 if (ct->pack & 8) {
\r
904 unsigned int add = ct->pack >> (((ct->pack&0xc0)>>6)+24);
\r
905 if (ct->pack & (1<<(SLOT3+8))) eg_out += add;
\r
906 if (ct->pack & (1<<(SLOT2+8))) eg_out2 += add;
\r
907 if (ct->pack & (1<<(SLOT4+8))) eg_out4 += add;
\r
910 switch( ct->CH->ALGO )
\r
914 /* M1---C1---MEM---M2---C2---OUT */
\r
915 int m2,c1,c2=0; /* Phase Modulation input for operators 2,3,4 */
\r
917 c1 = ct->op1_out>>16;
\r
918 if( eg_out < ENV_QUIET ) { /* SLOT 3 */
\r
919 c2 = op_calc(ct->phase3, eg_out, m2);
\r
921 if( eg_out2 < ENV_QUIET ) { /* SLOT 2 */
\r
922 ct->mem = op_calc(ct->phase2, eg_out2, c1);
\r
925 if( eg_out4 < ENV_QUIET ) { /* SLOT 4 */
\r
926 smp = op_calc(ct->phase4, eg_out4, c2);
\r
932 /* M1------+-MEM---M2---C2---OUT */
\r
936 ct->mem = ct->op1_out>>16;
\r
937 if( eg_out < ENV_QUIET ) { /* SLOT 3 */
\r
938 c2 = op_calc(ct->phase3, eg_out, m2);
\r
940 if( eg_out2 < ENV_QUIET ) { /* SLOT 2 */
\r
941 ct->mem+= op_calc(ct->phase2, eg_out2, 0);
\r
943 if( eg_out4 < ENV_QUIET ) { /* SLOT 4 */
\r
944 smp = op_calc(ct->phase4, eg_out4, c2);
\r
950 /* M1-----------------+-C2---OUT */
\r
951 /* C1---MEM---M2-+ */
\r
954 c2 = ct->op1_out>>16;
\r
955 if( eg_out < ENV_QUIET ) { /* SLOT 3 */
\r
956 c2 += op_calc(ct->phase3, eg_out, m2);
\r
958 if( eg_out2 < ENV_QUIET ) { /* SLOT 2 */
\r
959 ct->mem = op_calc(ct->phase2, eg_out2, 0);
\r
962 if( eg_out4 < ENV_QUIET ) { /* SLOT 4 */
\r
963 smp = op_calc(ct->phase4, eg_out4, c2);
\r
969 /* M1---C1---MEM------+-C2---OUT */
\r
973 c1 = ct->op1_out>>16;
\r
974 if( eg_out < ENV_QUIET ) { /* SLOT 3 */
\r
975 c2 += op_calc(ct->phase3, eg_out, 0);
\r
977 if( eg_out2 < ENV_QUIET ) { /* SLOT 2 */
\r
978 ct->mem = op_calc(ct->phase2, eg_out2, c1);
\r
981 if( eg_out4 < ENV_QUIET ) { /* SLOT 4 */
\r
982 smp = op_calc(ct->phase4, eg_out4, c2);
\r
988 /* M1---C1-+-OUT */
\r
990 /* MEM: not used */
\r
992 c1 = ct->op1_out>>16;
\r
993 if( eg_out < ENV_QUIET ) { /* SLOT 3 */
\r
994 c2 = op_calc(ct->phase3, eg_out, 0);
\r
996 if( eg_out2 < ENV_QUIET ) { /* SLOT 2 */
\r
997 smp = op_calc(ct->phase2, eg_out2, c1);
\r
999 if( eg_out4 < ENV_QUIET ) { /* SLOT 4 */
\r
1000 smp+= op_calc(ct->phase4, eg_out4, c2);
\r
1006 /* +----C1----+ */
\r
1007 /* M1-+-MEM---M2-+-OUT */
\r
1008 /* +----C2----+ */
\r
1011 ct->mem = c1 = c2 = ct->op1_out>>16;
\r
1012 if( eg_out < ENV_QUIET ) { /* SLOT 3 */
\r
1013 smp = op_calc(ct->phase3, eg_out, m2);
\r
1015 if( eg_out2 < ENV_QUIET ) { /* SLOT 2 */
\r
1016 smp+= op_calc(ct->phase2, eg_out2, c1);
\r
1018 if( eg_out4 < ENV_QUIET ) { /* SLOT 4 */
\r
1019 smp+= op_calc(ct->phase4, eg_out4, c2);
\r
1028 /* MEM: not used */
\r
1030 c1 = ct->op1_out>>16;
\r
1031 if( eg_out < ENV_QUIET ) { /* SLOT 3 */
\r
1032 smp = op_calc(ct->phase3, eg_out, 0);
\r
1034 if( eg_out2 < ENV_QUIET ) { /* SLOT 2 */
\r
1035 smp+= op_calc(ct->phase2, eg_out2, c1);
\r
1037 if( eg_out4 < ENV_QUIET ) { /* SLOT 4 */
\r
1038 smp+= op_calc(ct->phase4, eg_out4, 0);
\r
1048 /* MEM: not used*/
\r
1049 smp = ct->op1_out>>16;
\r
1050 if( eg_out < ENV_QUIET ) { /* SLOT 3 */
\r
1051 smp += op_calc(ct->phase3, eg_out, 0);
\r
1053 if( eg_out2 < ENV_QUIET ) { /* SLOT 2 */
\r
1054 smp += op_calc(ct->phase2, eg_out2, 0);
\r
1056 if( eg_out4 < ENV_QUIET ) { /* SLOT 4 */
\r
1057 smp += op_calc(ct->phase4, eg_out4, 0);
\r
1062 /* done calculating channel sample */
\r
1064 /* mix sample to output buffer */
\r
1066 if (ct->pack & 1) { /* stereo */
\r
1067 if (ct->pack & 0x20) /* L */ /* TODO: check correctness */
\r
1068 buffer[scounter*2] += smp;
\r
1069 if (ct->pack & 0x10) /* R */
\r
1070 buffer[scounter*2+1] += smp;
\r
1072 buffer[scounter] += smp;
\r
1074 ct->algo = 8; // algo is only used in asm, here only bit3 is used
\r
1077 /* update phase counters AFTER output calculations */
\r
1078 ct->phase1 += ct->incr1;
\r
1079 ct->phase2 += ct->incr2;
\r
1080 ct->phase3 += ct->incr3;
\r
1081 ct->phase4 += ct->incr4;
\r
1085 void chan_render_loop(chan_rend_context *ct, int *buffer, unsigned short length);
\r
1088 static chan_rend_context crct;
\r
1090 static void chan_render_prep(void)
\r
1092 crct.eg_timer_add = ym2612.OPN.eg_timer_add;
\r
1093 crct.lfo_inc = ym2612.OPN.lfo_inc;
\r
1096 static void chan_render_finish(void)
\r
1098 ym2612.OPN.eg_cnt = crct.eg_cnt;
\r
1099 ym2612.OPN.eg_timer = crct.eg_timer;
\r
1100 g_lfo_ampm = crct.pack >> 16; // need_save
\r
1101 ym2612.OPN.lfo_cnt = crct.lfo_cnt;
\r
1104 static int chan_render(int *buffer, int length, int c, UINT32 flags) // flags: stereo, ?, disabled, ?, pan_r, pan_l
\r
1106 crct.CH = &ym2612.CH[c];
\r
1107 crct.mem = crct.CH->mem_value; /* one sample delay memory */
\r
1108 crct.lfo_cnt = ym2612.OPN.lfo_cnt;
\r
1112 if (crct.lfo_inc) {
\r
1114 flags |= g_lfo_ampm << 16;
\r
1115 flags |= crct.CH->AMmasks << 8;
\r
1116 if (crct.CH->ams == 8) // no ams
\r
1118 else flags |= (crct.CH->ams&3)<<6;
\r
1120 flags |= (crct.CH->FB&0xf)<<12; /* feedback shift */
\r
1121 crct.pack = flags;
\r
1123 crct.eg_cnt = ym2612.OPN.eg_cnt; /* envelope generator counter */
\r
1124 crct.eg_timer = ym2612.OPN.eg_timer;
\r
1126 /* precalculate phase modulation incr */
\r
1127 crct.phase1 = crct.CH->SLOT[SLOT1].phase;
\r
1128 crct.phase2 = crct.CH->SLOT[SLOT2].phase;
\r
1129 crct.phase3 = crct.CH->SLOT[SLOT3].phase;
\r
1130 crct.phase4 = crct.CH->SLOT[SLOT4].phase;
\r
1132 /* current output from EG circuit (without AM from LFO) */
\r
1133 crct.vol_out1 = crct.CH->SLOT[SLOT1].tl + ((UINT32)crct.CH->SLOT[SLOT1].volume);
\r
1134 crct.vol_out2 = crct.CH->SLOT[SLOT2].tl + ((UINT32)crct.CH->SLOT[SLOT2].volume);
\r
1135 crct.vol_out3 = crct.CH->SLOT[SLOT3].tl + ((UINT32)crct.CH->SLOT[SLOT3].volume);
\r
1136 crct.vol_out4 = crct.CH->SLOT[SLOT4].tl + ((UINT32)crct.CH->SLOT[SLOT4].volume);
\r
1138 crct.op1_out = crct.CH->op1_out;
\r
1139 crct.algo = crct.CH->ALGO & 7;
\r
1143 /* add support for 3 slot mode */
\r
1144 UINT32 block_fnum = crct.CH->block_fnum;
\r
1146 UINT32 fnum_lfo = ((block_fnum & 0x7f0) >> 4) * 32 * 8;
\r
1147 INT32 lfo_fn_table_index_offset = lfo_pm_table[ fnum_lfo + crct.CH->pms + ((crct.pack>>16)&0xff) ];
\r
1149 if (lfo_fn_table_index_offset) /* LFO phase modulation active */
\r
1155 blk = block_fnum >> 11;
\r
1156 block_fnum = block_fnum*2 + lfo_fn_table_index_offset;
\r
1158 fn = block_fnum & 0xfff;
\r
1160 /* keyscale code */
\r
1161 kc = (blk<<2) | opn_fktable[fn >> 8];
\r
1162 /* phase increment counter */
\r
1163 fc = fn_table[fn]>>(7-blk);
\r
1165 crct.incr1 = ((fc+crct.CH->SLOT[SLOT1].DT[kc])*crct.CH->SLOT[SLOT1].mul) >> 1;
\r
1166 crct.incr2 = ((fc+crct.CH->SLOT[SLOT2].DT[kc])*crct.CH->SLOT[SLOT2].mul) >> 1;
\r
1167 crct.incr3 = ((fc+crct.CH->SLOT[SLOT3].DT[kc])*crct.CH->SLOT[SLOT3].mul) >> 1;
\r
1168 crct.incr4 = ((fc+crct.CH->SLOT[SLOT4].DT[kc])*crct.CH->SLOT[SLOT4].mul) >> 1;
\r
1170 else /* LFO phase modulation = zero */
\r
1172 crct.incr1 = crct.CH->SLOT[SLOT1].Incr;
\r
1173 crct.incr2 = crct.CH->SLOT[SLOT2].Incr;
\r
1174 crct.incr3 = crct.CH->SLOT[SLOT3].Incr;
\r
1175 crct.incr4 = crct.CH->SLOT[SLOT4].Incr;
\r
1178 else /* no LFO phase modulation */
\r
1180 crct.incr1 = crct.CH->SLOT[SLOT1].Incr;
\r
1181 crct.incr2 = crct.CH->SLOT[SLOT2].Incr;
\r
1182 crct.incr3 = crct.CH->SLOT[SLOT3].Incr;
\r
1183 crct.incr4 = crct.CH->SLOT[SLOT4].Incr;
\r
1186 chan_render_loop(&crct, buffer, length);
\r
1188 crct.CH->op1_out = crct.op1_out;
\r
1189 crct.CH->mem_value = crct.mem;
\r
1190 if (crct.CH->SLOT[SLOT1].state | crct.CH->SLOT[SLOT2].state | crct.CH->SLOT[SLOT3].state | crct.CH->SLOT[SLOT4].state)
\r
1192 crct.CH->SLOT[SLOT1].phase = crct.phase1;
\r
1193 crct.CH->SLOT[SLOT2].phase = crct.phase2;
\r
1194 crct.CH->SLOT[SLOT3].phase = crct.phase3;
\r
1195 crct.CH->SLOT[SLOT4].phase = crct.phase4;
\r
1198 ym2612.slot_mask &= ~(0xf << (c*4));
\r
1200 return (crct.algo & 8) >> 3; // had output
\r
1203 /* update phase increment and envelope generator */
\r
1204 INLINE void refresh_fc_eg_slot(FM_SLOT *SLOT, int fc, int kc)
\r
1208 /* (frequency) phase increment counter */
\r
1209 fdt = fc+SLOT->DT[kc];
\r
1210 /* detect overflow */
\r
1211 // if (fdt < 0) fdt += fn_table[0x7ff*2] >> (7-blk-1);
\r
1212 if (fdt < 0) fdt += fn_table[0x7ff*2] >> 2;
\r
1213 SLOT->Incr = fdt*SLOT->mul >> 1;
\r
1215 ksr = kc >> SLOT->KSR;
\r
1216 if( SLOT->ksr != ksr )
\r
1218 int eg_sh, eg_sel;
\r
1221 /* calculate envelope generator rates */
\r
1222 if ((SLOT->ar + ksr) < 32+62)
\r
1224 eg_sh = eg_rate_shift [SLOT->ar + ksr ];
\r
1225 eg_sel = eg_rate_select[SLOT->ar + ksr ];
\r
1233 SLOT->eg_pack_ar = eg_inc_pack[eg_sel] | (eg_sh<<24);
\r
1235 eg_sh = eg_rate_shift [SLOT->d1r + ksr];
\r
1236 eg_sel = eg_rate_select[SLOT->d1r + ksr];
\r
1238 SLOT->eg_pack_d1r = eg_inc_pack[eg_sel] | (eg_sh<<24);
\r
1240 eg_sh = eg_rate_shift [SLOT->d2r + ksr];
\r
1241 eg_sel = eg_rate_select[SLOT->d2r + ksr];
\r
1243 SLOT->eg_pack_d2r = eg_inc_pack[eg_sel] | (eg_sh<<24);
\r
1245 eg_sh = eg_rate_shift [SLOT->rr + ksr];
\r
1246 eg_sel = eg_rate_select[SLOT->rr + ksr];
\r
1248 SLOT->eg_pack_rr = eg_inc_pack[eg_sel] | (eg_sh<<24);
\r
1252 /* update phase increment counters */
\r
1253 INLINE void refresh_fc_eg_chan(FM_CH *CH)
\r
1255 if( CH->SLOT[SLOT1].Incr==-1){
\r
1257 int kc = CH->kcode;
\r
1258 refresh_fc_eg_slot(&CH->SLOT[SLOT1] , fc , kc );
\r
1259 refresh_fc_eg_slot(&CH->SLOT[SLOT2] , fc , kc );
\r
1260 refresh_fc_eg_slot(&CH->SLOT[SLOT3] , fc , kc );
\r
1261 refresh_fc_eg_slot(&CH->SLOT[SLOT4] , fc , kc );
\r
1265 INLINE void refresh_fc_eg_chan_sl3(void)
\r
1267 if( ym2612.CH[2].SLOT[SLOT1].Incr==-1)
\r
1269 refresh_fc_eg_slot(&ym2612.CH[2].SLOT[SLOT1], ym2612.OPN.SL3.fc[1], ym2612.OPN.SL3.kcode[1] );
\r
1270 refresh_fc_eg_slot(&ym2612.CH[2].SLOT[SLOT2], ym2612.OPN.SL3.fc[2], ym2612.OPN.SL3.kcode[2] );
\r
1271 refresh_fc_eg_slot(&ym2612.CH[2].SLOT[SLOT3], ym2612.OPN.SL3.fc[0], ym2612.OPN.SL3.kcode[0] );
\r
1272 refresh_fc_eg_slot(&ym2612.CH[2].SLOT[SLOT4], ym2612.CH[2].fc , ym2612.CH[2].kcode );
\r
1276 /* initialize time tables */
\r
1277 static void init_timetables(const UINT8 *dttable)
\r
1282 /* DeTune table */
\r
1283 for (d = 0;d <= 3;d++){
\r
1284 for (i = 0;i <= 31;i++){
\r
1285 rate = ((double)dttable[d*32 + i]) * SIN_LEN * ym2612.OPN.ST.freqbase * (1<<FREQ_SH) / ((double)(1<<20));
\r
1286 ym2612.OPN.ST.dt_tab[d][i] = (INT32) rate;
\r
1287 ym2612.OPN.ST.dt_tab[d+4][i] = -ym2612.OPN.ST.dt_tab[d][i];
\r
1293 static void reset_channels(FM_CH *CH)
\r
1297 ym2612.OPN.ST.mode = 0; /* normal mode */
\r
1298 ym2612.OPN.ST.TA = 0;
\r
1299 ym2612.OPN.ST.TAC = 0;
\r
1300 ym2612.OPN.ST.TB = 0;
\r
1301 ym2612.OPN.ST.TBC = 0;
\r
1303 for( c = 0 ; c < 6 ; c++ )
\r
1306 for(s = 0 ; s < 4 ; s++ )
\r
1308 CH[c].SLOT[s].state= EG_OFF;
\r
1309 CH[c].SLOT[s].volume = MAX_ATT_INDEX;
\r
1311 CH[c].mem_value = CH[c].op1_out = 0;
\r
1313 ym2612.slot_mask = 0;
\r
1316 /* initialize generic tables */
\r
1317 static void init_tables(void)
\r
1319 signed int i,x,y,p;
\r
1323 for (i=0; i < 256; i++)
\r
1325 /* non-standard sinus */
\r
1326 m = sin( ((i*2)+1) * M_PI / SIN_LEN ); /* checked against the real chip */
\r
1328 /* we never reach zero here due to ((i*2)+1) */
\r
1331 o = 8*log(1.0/m)/log(2); /* convert to 'decibels' */
\r
1333 o = 8*log(-1.0/m)/log(2); /* convert to 'decibels' */
\r
1335 o = o / (ENV_STEP/4);
\r
1338 if (n&1) /* round to nearest */
\r
1343 ym_sin_tab[ i ] = n;
\r
1344 //dprintf("FM.C: sin [%4i]= %4i", i, ym_sin_tab[i]);
\r
1347 //dprintf("FM.C: ENV_QUIET= %08x", ENV_QUIET );
\r
1350 for (x=0; x < TL_RES_LEN; x++)
\r
1352 m = (1<<16) / pow(2, (x+1) * (ENV_STEP/4.0) / 8.0);
\r
1355 /* we never reach (1<<16) here due to the (x+1) */
\r
1356 /* result fits within 16 bits at maximum */
\r
1358 n = (int)m; /* 16 bits here */
\r
1359 n >>= 4; /* 12 bits here */
\r
1360 if (n&1) /* round to nearest */
\r
1364 /* 11 bits here (rounded) */
\r
1365 n <<= 2; /* 13 bits here (as in real chip) */
\r
1366 ym_tl_tab2[ x ] = n;
\r
1368 for (i=1; i < 13; i++)
\r
1370 ym_tl_tab2[ x + i*TL_RES_LEN ] = n >> i;
\r
1374 for (x=0; x < 256; x++)
\r
1376 int sin = ym_sin_tab[ x ];
\r
1378 for (y=0; y < 2*13*TL_RES_LEN/8; y+=2)
\r
1381 if (p >= 13*TL_RES_LEN)
\r
1382 ym_tl_tab[(y<<7) | x] = 0;
\r
1383 else ym_tl_tab[(y<<7) | x] = ym_tl_tab2[p];
\r
1388 /* build LFO PM modulation table */
\r
1389 for(i = 0; i < 8; i++) /* 8 PM depths */
\r
1392 for (fnum=0; fnum<128; fnum++) /* 7 bits meaningful of F-NUMBER */
\r
1396 UINT32 offset_depth = i;
\r
1397 UINT32 offset_fnum_bit;
\r
1400 for (step=0; step<8; step++)
\r
1403 for (bit_tmp=0; bit_tmp<7; bit_tmp++) /* 7 bits */
\r
1405 if (fnum & (1<<bit_tmp)) /* only if bit "bit_tmp" is set */
\r
1407 offset_fnum_bit = bit_tmp * 8;
\r
1408 value += lfo_pm_output[offset_fnum_bit + offset_depth][step];
\r
1411 lfo_pm_table[(fnum*32*8) + (i*32) + step + 0] = value;
\r
1412 lfo_pm_table[(fnum*32*8) + (i*32) +(step^7)+ 8] = value;
\r
1413 lfo_pm_table[(fnum*32*8) + (i*32) + step +16] = -value;
\r
1414 lfo_pm_table[(fnum*32*8) + (i*32) +(step^7)+24] = -value;
\r
1421 /* CSM Key Controll */
\r
1423 INLINE void CSMKeyControll(FM_CH *CH)
\r
1425 /* this is wrong, atm */
\r
1428 FM_KEYON(CH,SLOT1);
\r
1429 FM_KEYON(CH,SLOT2);
\r
1430 FM_KEYON(CH,SLOT3);
\r
1431 FM_KEYON(CH,SLOT4);
\r
1436 /* prescaler set (and make time tables) */
\r
1437 static void OPNSetPres(int pres)
\r
1441 /* frequency base */
\r
1442 ym2612.OPN.ST.freqbase = (ym2612.OPN.ST.rate) ? ((double)ym2612.OPN.ST.clock / ym2612.OPN.ST.rate) / pres : 0;
\r
1444 ym2612.OPN.eg_timer_add = (1<<EG_SH) * ym2612.OPN.ST.freqbase;
\r
1446 /* make time tables */
\r
1447 init_timetables( dt_tab );
\r
1449 /* there are 2048 FNUMs that can be generated using FNUM/BLK registers
\r
1450 but LFO works with one more bit of a precision so we really need 4096 elements */
\r
1451 /* calculate fnumber -> increment counter table */
\r
1452 for(i = 0; i < 4096; i++)
\r
1454 /* freq table for octave 7 */
\r
1455 /* OPN phase increment counter = 20bit */
\r
1456 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
1459 /* LFO freq. table */
\r
1460 for(i = 0; i < 8; i++)
\r
1462 /* Amplitude modulation: 64 output levels (triangle waveform); 1 level lasts for one of "lfo_samples_per_step" samples */
\r
1463 /* Phase modulation: one entry from lfo_pm_output lasts for one of 4 * "lfo_samples_per_step" samples */
\r
1464 ym2612.OPN.lfo_freq[i] = (1.0 / lfo_samples_per_step[i]) * (1<<LFO_SH) * ym2612.OPN.ST.freqbase;
\r
1469 /* write a OPN register (0x30-0xff) */
\r
1470 static int OPNWriteReg(int r, int v)
\r
1476 UINT8 c = OPN_CHAN(r);
\r
1478 if (c == 3) return 0; /* 0xX3,0xX7,0xXB,0xXF */
\r
1480 if (r >= 0x100) c+=3;
\r
1482 CH = &ym2612.CH[c];
\r
1484 SLOT = &(CH->SLOT[OPN_SLOT(r)]);
\r
1486 switch( r & 0xf0 ) {
\r
1487 case 0x30: /* DET , MUL */
\r
1488 set_det_mul(CH,SLOT,v);
\r
1491 case 0x40: /* TL */
\r
1495 case 0x50: /* KS, AR */
\r
1496 set_ar_ksr(CH,SLOT,v);
\r
1499 case 0x60: /* bit7 = AM ENABLE, DR | depends on ksr */
\r
1501 if(v&0x80) CH->AMmasks |= 1<<OPN_SLOT(r);
\r
1502 else CH->AMmasks &= ~(1<<OPN_SLOT(r));
\r
1505 case 0x70: /* SR | depends on ksr */
\r
1509 case 0x80: /* SL, RR | depends on ksr */
\r
1510 set_sl_rr(SLOT,v);
\r
1513 case 0x90: /* SSG-EG */
\r
1519 switch( OPN_SLOT(r) ){
\r
1520 case 0: /* 0xa0-0xa2 : FNUM1 | depends on fn_h (below) */
\r
1522 UINT32 fn = (((UINT32)( (CH->fn_h)&7))<<8) + v;
\r
1523 UINT8 blk = CH->fn_h>>3;
\r
1524 /* keyscale code */
\r
1525 CH->kcode = (blk<<2) | opn_fktable[fn >> 7];
\r
1526 /* phase increment counter */
\r
1527 CH->fc = fn_table[fn*2]>>(7-blk);
\r
1529 /* store fnum in clear form for LFO PM calculations */
\r
1530 CH->block_fnum = (blk<<11) | fn;
\r
1532 CH->SLOT[SLOT1].Incr=-1;
\r
1535 case 1: /* 0xa4-0xa6 : FNUM2,BLK */
\r
1536 CH->fn_h = v&0x3f;
\r
1539 case 2: /* 0xa8-0xaa : 3CH FNUM1 */
\r
1542 UINT32 fn = (((UINT32)(ym2612.OPN.SL3.fn_h&7))<<8) + v;
\r
1543 UINT8 blk = ym2612.OPN.SL3.fn_h>>3;
\r
1544 /* keyscale code */
\r
1545 ym2612.OPN.SL3.kcode[c]= (blk<<2) | opn_fktable[fn >> 7];
\r
1546 /* phase increment counter */
\r
1547 ym2612.OPN.SL3.fc[c] = fn_table[fn*2]>>(7-blk);
\r
1548 ym2612.OPN.SL3.block_fnum[c] = (blk<<11) | fn;
\r
1549 ym2612.CH[2].SLOT[SLOT1].Incr=-1;
\r
1552 case 3: /* 0xac-0xae : 3CH FNUM2,BLK */
\r
1554 ym2612.OPN.SL3.fn_h = v&0x3f;
\r
1564 switch( OPN_SLOT(r) ){
\r
1565 case 0: /* 0xb0-0xb2 : FB,ALGO */
\r
1567 int feedback = (v>>3)&7;
\r
1569 CH->FB = feedback ? feedback+6 : 0;
\r
1572 case 1: /* 0xb4-0xb6 : L , R , AMS , PMS (YM2612/YM2610B/YM2610/YM2608) */
\r
1574 int panshift = c<<1;
\r
1577 CH->pms = (v & 7) * 32; /* CH->pms = PM depth * 32 (index in lfo_pm_table) */
\r
1580 CH->ams = lfo_ams_depth_shift[(v>>4) & 3];
\r
1582 /* PAN : b7 = L, b6 = R */
\r
1583 ym2612.OPN.pan &= ~(3<<panshift);
\r
1584 ym2612.OPN.pan |= ((v & 0xc0) >> 6) << panshift; // ..LRLR
\r
1601 /*******************************************************************************/
\r
1602 /* YM2612 local section */
\r
1603 /*******************************************************************************/
\r
1605 /* Generate samples for YM2612 */
\r
1606 int YM2612UpdateOne_(int *buffer, int length, int stereo, int is_buf_empty)
\r
1609 int active_chs = 0;
\r
1611 // if !is_buf_empty, it means it has valid samples to mix with, else it may contain trash
\r
1612 if (is_buf_empty) memset32(buffer, 0, length<<stereo);
\r
1618 for (c = 0; c < 6; c++) {
\r
1620 printf("%i: ", c);
\r
1621 for (s = 0; s < 4; s++) {
\r
1622 if (ym2612.CH[c].SLOT[s].state != EG_OFF) slr = 1;
\r
1623 printf(" %i", ym2612.CH[c].SLOT[s].state != EG_OFF);
\r
1625 slm = (ym2612.slot_mask&(0xf<<(c*4))) ? 1 : 0;
\r
1626 printf(" | %i", slm);
\r
1627 printf(" | %i\n", ym2612.CH[c].SLOT[SLOT1].Incr==-1);
\r
1628 if (slr != slm) exit(1);
\r
1632 /* refresh PG and EG */
\r
1633 refresh_fc_eg_chan( &ym2612.CH[0] );
\r
1634 refresh_fc_eg_chan( &ym2612.CH[1] );
\r
1635 if( (ym2612.OPN.ST.mode & 0xc0) )
\r
1637 refresh_fc_eg_chan_sl3();
\r
1639 refresh_fc_eg_chan( &ym2612.CH[2] );
\r
1640 refresh_fc_eg_chan( &ym2612.CH[3] );
\r
1641 refresh_fc_eg_chan( &ym2612.CH[4] );
\r
1642 refresh_fc_eg_chan( &ym2612.CH[5] );
\r
1644 pan = ym2612.OPN.pan;
\r
1645 if (stereo) stereo = 1;
\r
1647 /* mix to 32bit dest */
\r
1648 // flags: stereo, ?, disabled, ?, pan_r, pan_l
\r
1649 chan_render_prep();
\r
1650 if (ym2612.slot_mask & 0x00000f) active_chs |= chan_render(buffer, length, 0, stereo|((pan&0x003)<<4)) << 0;
\r
1651 if (ym2612.slot_mask & 0x0000f0) active_chs |= chan_render(buffer, length, 1, stereo|((pan&0x00c)<<2)) << 1;
\r
1652 if (ym2612.slot_mask & 0x000f00) active_chs |= chan_render(buffer, length, 2, stereo|((pan&0x030) )) << 2;
\r
1653 if (ym2612.slot_mask & 0x00f000) active_chs |= chan_render(buffer, length, 3, stereo|((pan&0x0c0)>>2)) << 3;
\r
1654 if (ym2612.slot_mask & 0x0f0000) active_chs |= chan_render(buffer, length, 4, stereo|((pan&0x300)>>4)) << 4;
\r
1655 if (ym2612.slot_mask & 0xf00000) active_chs |= chan_render(buffer, length, 5, stereo|((pan&0xc00)>>6)|(ym2612.dacen<<2)) << 5;
\r
1656 chan_render_finish();
\r
1658 return active_chs; // 1 if buffer updated
\r
1662 /* initialize YM2612 emulator */
\r
1663 void YM2612Init_(int clock, int rate)
\r
1665 memset(&ym2612, 0, sizeof(ym2612));
\r
1668 ym2612.OPN.ST.clock = clock;
\r
1669 ym2612.OPN.ST.rate = rate;
\r
1671 OPNSetPres( 6*24 );
\r
1673 /* Extend handler */
\r
1674 YM2612ResetChip_();
\r
1679 void YM2612ResetChip_(void)
\r
1683 memset(ym2612.REGS, 0, sizeof(ym2612.REGS));
\r
1685 set_timers( 0x30 ); /* mode 0 , timer reset */
\r
1686 ym2612.REGS[0x27] = 0x30;
\r
1688 ym2612.OPN.eg_timer = 0;
\r
1689 ym2612.OPN.eg_cnt = 0;
\r
1690 ym2612.OPN.ST.status = 0;
\r
1692 reset_channels( &ym2612.CH[0] );
\r
1693 for(i = 0xb6 ; i >= 0xb4 ; i-- )
\r
1695 OPNWriteReg(i ,0xc0);
\r
1696 OPNWriteReg(i|0x100,0xc0);
\r
1697 ym2612.REGS[i ] = 0xc0;
\r
1698 ym2612.REGS[i|0x100] = 0xc0;
\r
1700 for(i = 0xb2 ; i >= 0x30 ; i-- )
\r
1702 OPNWriteReg(i ,0);
\r
1703 OPNWriteReg(i|0x100,0);
\r
1705 for(i = 0x26 ; i >= 0x20 ; i-- ) OPNWriteReg(i,0);
\r
1706 /* DAC mode clear */
\r
1708 ym2612.addr_A1 = 0;
\r
1712 /* YM2612 write */
\r
1715 /* returns 1 if sample affecting state changed */
\r
1716 int YM2612Write_(unsigned int a, unsigned int v)
\r
1720 v &= 0xff; /* adjust to 8 bit bus */
\r
1723 case 0: /* address port 0 */
\r
1724 ym2612.OPN.ST.address = v;
\r
1725 ym2612.addr_A1 = 0;
\r
1729 case 1: /* data port 0 */
\r
1730 if (ym2612.addr_A1 != 0) {
\r
1732 break; /* verified on real YM2608 */
\r
1735 addr = ym2612.OPN.ST.address;
\r
1737 switch( addr & 0xf0 )
\r
1739 case 0x20: /* 0x20-0x2f Mode */
\r
1742 case 0x22: /* LFO FREQ (YM2608/YM2610/YM2610B/YM2612) */
\r
1743 if (v&0x08) /* LFO enabled ? */
\r
1745 ym2612.OPN.lfo_inc = ym2612.OPN.lfo_freq[v&7];
\r
1749 ym2612.OPN.lfo_inc = 0;
\r
1752 #if 0 // handled elsewhere
\r
1753 case 0x24: { // timer A High 8
\r
1754 int TAnew = (ym2612.OPN.ST.TA & 0x03)|(((int)v)<<2);
\r
1755 if(ym2612.OPN.ST.TA != TAnew) {
\r
1756 // we should reset ticker only if new value is written. Outrun requires this.
\r
1757 ym2612.OPN.ST.TA = TAnew;
\r
1758 ym2612.OPN.ST.TAC = (1024-TAnew)*18;
\r
1759 ym2612.OPN.ST.TAT = 0;
\r
1764 case 0x25: { // timer A Low 2
\r
1765 int TAnew = (ym2612.OPN.ST.TA & 0x3fc)|(v&3);
\r
1766 if(ym2612.OPN.ST.TA != TAnew) {
\r
1767 ym2612.OPN.ST.TA = TAnew;
\r
1768 ym2612.OPN.ST.TAC = (1024-TAnew)*18;
\r
1769 ym2612.OPN.ST.TAT = 0;
\r
1774 case 0x26: // timer B
\r
1775 if(ym2612.OPN.ST.TB != v) {
\r
1776 ym2612.OPN.ST.TB = v;
\r
1777 ym2612.OPN.ST.TBC = (256-v)<<4;
\r
1778 ym2612.OPN.ST.TBC *= 18;
\r
1779 ym2612.OPN.ST.TBT = 0;
\r
1784 case 0x27: /* mode, timer control */
\r
1788 case 0x28: /* key on / off */
\r
1793 if( c == 3 ) { ret=0; break; }
\r
1794 if( v&0x04 ) c+=3;
\r
1795 if(v&0x10) FM_KEYON(c,SLOT1); else FM_KEYOFF(c,SLOT1);
\r
1796 if(v&0x20) FM_KEYON(c,SLOT2); else FM_KEYOFF(c,SLOT2);
\r
1797 if(v&0x40) FM_KEYON(c,SLOT3); else FM_KEYOFF(c,SLOT3);
\r
1798 if(v&0x80) FM_KEYON(c,SLOT4); else FM_KEYOFF(c,SLOT4);
\r
1801 case 0x2a: /* DAC data (YM2612) */
\r
1802 ym2612.dacout = ((int)v - 0x80) << 6; /* level unknown (notaz: 8 seems to be too much) */
\r
1805 case 0x2b: /* DAC Sel (YM2612) */
\r
1806 /* b7 = dac enable */
\r
1807 ym2612.dacen = v & 0x80;
\r
1814 default: /* 0x30-0xff OPN section */
\r
1815 /* write register */
\r
1816 ret = OPNWriteReg(addr,v);
\r
1820 case 2: /* address port 1 */
\r
1821 ym2612.OPN.ST.address = v;
\r
1822 ym2612.addr_A1 = 1;
\r
1826 case 3: /* data port 1 */
\r
1827 if (ym2612.addr_A1 != 1) {
\r
1829 break; /* verified on real YM2608 */
\r
1832 addr = ym2612.OPN.ST.address | 0x100;
\r
1834 ret = OPNWriteReg(addr, v);
\r
1842 UINT8 YM2612Read_(void)
\r
1844 return ym2612.OPN.ST.status;
\r
1847 int YM2612PicoTick_(int n)
\r
1852 if(ym2612.OPN.ST.mode & 0x01 && (ym2612.OPN.ST.TAT+=64*n) >= ym2612.OPN.ST.TAC) {
\r
1853 ym2612.OPN.ST.TAT -= ym2612.OPN.ST.TAC;
\r
1854 if(ym2612.OPN.ST.mode & 0x04) ym2612.OPN.ST.status |= 1;
\r
1855 // CSM mode total level latch and auto key on
\r
1856 if(ym2612.OPN.ST.mode & 0x80) {
\r
1857 CSMKeyControll( &(ym2612.CH[2]) ); // Vectorman2, etc.
\r
1863 if(ym2612.OPN.ST.mode & 0x02 && (ym2612.OPN.ST.TBT+=64*n) >= ym2612.OPN.ST.TBC) {
\r
1864 ym2612.OPN.ST.TBT -= ym2612.OPN.ST.TBC;
\r
1865 if(ym2612.OPN.ST.mode & 0x08) ym2612.OPN.ST.status |= 2;
\r
1872 void YM2612PicoStateLoad_(void)
\r
1874 reset_channels( &ym2612.CH[0] );
\r
1875 ym2612.slot_mask = 0xffffff;
\r
1878 /* rather stupid design because I wanted to fit in unused register "space" */
\r
1881 UINT32 state_phase;
\r
1883 } ym_save_addon_slot;
\r
1894 UINT32 eg_cnt; // 10
\r
1899 UINT32 keyon_field; // 20
\r
1900 UINT32 kcode_fc_sl3_3;
\r
1901 UINT32 reserved[2];
\r
1906 UINT16 block_fnum[6];
\r
1907 UINT16 block_fnum_sl3[3];
\r
1908 UINT16 reserved[7];
\r
1912 void YM2612PicoStateSave2(int tat, int tbt)
\r
1914 ym_save_addon_slot ss;
\r
1915 ym_save_addon2 sa2;
\r
1917 unsigned char *ptr;
\r
1920 memset(&sa, 0, sizeof(sa));
\r
1921 memset(&sa2, 0, sizeof(sa2));
\r
1924 ptr = &ym2612.REGS[0x0b8];
\r
1925 for (c = 0; c < 3; c++)
\r
1927 for (s = 0; s < 4; s++) {
\r
1928 ss.state_phase = (ym2612.CH[c].SLOT[s].state << 29) | (ym2612.CH[c].SLOT[s].phase >> 3);
\r
1929 ss.volume = ym2612.CH[c].SLOT[s].volume;
\r
1930 if (ym2612.CH[c].SLOT[s].key)
\r
1931 sa.keyon_field |= 1 << (c*4 + s);
\r
1932 memcpy(ptr, &ss, 6);
\r
1935 sa2.block_fnum[c] = ym2612.CH[c].block_fnum;
\r
1938 ptr = &ym2612.REGS[0x1b8];
\r
1939 for (; c < 6; c++)
\r
1941 for (s = 0; s < 4; s++) {
\r
1942 ss.state_phase = (ym2612.CH[c].SLOT[s].state << 29) | (ym2612.CH[c].SLOT[s].phase >> 3);
\r
1943 ss.volume = ym2612.CH[c].SLOT[s].volume;
\r
1944 if (ym2612.CH[c].SLOT[s].key)
\r
1945 sa.keyon_field |= 1 << (c*4 + s);
\r
1946 memcpy(ptr, &ss, 6);
\r
1949 sa2.block_fnum[c] = ym2612.CH[c].block_fnum;
\r
1951 for (c = 0; c < 3; c++)
\r
1953 sa2.block_fnum_sl3[c] = ym2612.OPN.SL3.block_fnum[c];
\r
1956 memcpy(&ym2612.REGS[0], &sa2, sizeof(sa2)); // 0x20 max
\r
1959 ptr = &ym2612.REGS[0x100];
\r
1960 sa.magic = 0x41534d59; // 'YMSA'
\r
1961 sa.address = ym2612.OPN.ST.address;
\r
1962 sa.status = ym2612.OPN.ST.status;
\r
1963 sa.addr_A1 = ym2612.addr_A1;
\r
1966 sa.eg_cnt = ym2612.OPN.eg_cnt;
\r
1967 sa.eg_timer = ym2612.OPN.eg_timer;
\r
1968 sa.lfo_cnt = ym2612.OPN.lfo_cnt;
\r
1969 sa.lfo_ampm = g_lfo_ampm;
\r
1970 memcpy(ptr, &sa, sizeof(sa)); // 0x30 max
\r
1973 int YM2612PicoStateLoad2(int *tat, int *tbt)
\r
1975 ym_save_addon_slot ss;
\r
1976 ym_save_addon2 sa2;
\r
1978 unsigned char *ptr;
\r
1983 ptr = &ym2612.REGS[0x100];
\r
1984 memcpy(&sa, ptr, sizeof(sa)); // 0x30 max
\r
1985 if (sa.magic != 0x41534d59) return -1;
\r
1987 ptr = &ym2612.REGS[0];
\r
1988 memcpy(&sa2, ptr, sizeof(sa2));
\r
1990 ym2612.OPN.ST.address = sa.address;
\r
1991 ym2612.OPN.ST.status = sa.status;
\r
1992 ym2612.addr_A1 = sa.addr_A1;
\r
1993 ym2612.OPN.eg_cnt = sa.eg_cnt;
\r
1994 ym2612.OPN.eg_timer = sa.eg_timer;
\r
1995 ym2612.OPN.lfo_cnt = sa.lfo_cnt;
\r
1996 g_lfo_ampm = sa.lfo_ampm;
\r
1997 if (tat != NULL) *tat = sa.TAT;
\r
1998 if (tbt != NULL) *tbt = sa.TBT;
\r
2001 ptr = &ym2612.REGS[0x0b8];
\r
2002 for (c = 0; c < 3; c++)
\r
2004 for (s = 0; s < 4; s++) {
\r
2005 memcpy(&ss, ptr, 6);
\r
2006 ym2612.CH[c].SLOT[s].state = ss.state_phase >> 29;
\r
2007 ym2612.CH[c].SLOT[s].phase = ss.state_phase << 3;
\r
2008 ym2612.CH[c].SLOT[s].volume = ss.volume;
\r
2009 ym2612.CH[c].SLOT[s].key = (sa.keyon_field & (1 << (c*4 + s))) ? 1 : 0;
\r
2010 ym2612.CH[c].SLOT[s].ksr = (UINT8)-1;
\r
2013 ym2612.CH[c].SLOT[SLOT1].Incr=-1;
\r
2014 ym2612.CH[c].block_fnum = sa2.block_fnum[c];
\r
2015 fn = ym2612.CH[c].block_fnum & 0x7ff;
\r
2016 blk = ym2612.CH[c].block_fnum >> 11;
\r
2017 ym2612.CH[c].kcode= (blk<<2) | opn_fktable[fn >> 7];
\r
2018 ym2612.CH[c].fc = fn_table[fn*2]>>(7-blk);
\r
2021 ptr = &ym2612.REGS[0x1b8];
\r
2022 for (; c < 6; c++)
\r
2024 for (s = 0; s < 4; s++) {
\r
2025 memcpy(&ss, ptr, 6);
\r
2026 ym2612.CH[c].SLOT[s].state = ss.state_phase >> 29;
\r
2027 ym2612.CH[c].SLOT[s].phase = ss.state_phase << 3;
\r
2028 ym2612.CH[c].SLOT[s].volume = ss.volume;
\r
2029 ym2612.CH[c].SLOT[s].key = (sa.keyon_field & (1 << (c*4 + s))) ? 1 : 0;
\r
2030 ym2612.CH[c].SLOT[s].ksr = (UINT8)-1;
\r
2033 ym2612.CH[c].SLOT[SLOT1].Incr=-1;
\r
2034 ym2612.CH[c].block_fnum = sa2.block_fnum[c];
\r
2035 fn = ym2612.CH[c].block_fnum & 0x7ff;
\r
2036 blk = ym2612.CH[c].block_fnum >> 11;
\r
2037 ym2612.CH[c].kcode= (blk<<2) | opn_fktable[fn >> 7];
\r
2038 ym2612.CH[c].fc = fn_table[fn*2]>>(7-blk);
\r
2040 for (c = 0; c < 3; c++)
\r
2042 ym2612.OPN.SL3.block_fnum[c] = sa2.block_fnum_sl3[c];
\r
2043 fn = ym2612.OPN.SL3.block_fnum[c] & 0x7ff;
\r
2044 blk = ym2612.OPN.SL3.block_fnum[c] >> 11;
\r
2045 ym2612.OPN.SL3.kcode[c]= (blk<<2) | opn_fktable[fn >> 7];
\r
2046 ym2612.OPN.SL3.fc[c] = fn_table[fn*2]>>(7-blk);
\r
2052 void *YM2612GetRegs(void)
\r
2054 return ym2612.REGS;
\r