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
119 static YM2612 ym2612;
\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(FM_CH *CH , int s )
\r
558 FM_SLOT *SLOT = &CH->SLOT[s];
\r
562 SLOT->phase = 0; /* restart Phase Generator */
\r
563 SLOT->state = EG_ATT; /* phase -> Attack */
\r
567 INLINE void FM_KEYOFF(FM_CH *CH , int s )
\r
569 FM_SLOT *SLOT = &CH->SLOT[s];
\r
573 if (SLOT->state>EG_REL)
\r
574 SLOT->state = EG_REL;/* phase -> Release */
\r
579 /* set detune & multiple */
\r
580 INLINE void set_det_mul(FM_CH *CH, FM_SLOT *SLOT, int v)
\r
582 SLOT->mul = (v&0x0f)? (v&0x0f)*2 : 1;
\r
583 SLOT->DT = ym2612.OPN.ST.dt_tab[(v>>4)&7];
\r
584 CH->SLOT[SLOT1].Incr=-1;
\r
587 /* set total level */
\r
588 INLINE void set_tl(FM_SLOT *SLOT, int v)
\r
590 SLOT->tl = (v&0x7f)<<(ENV_BITS-7); /* 7bit TL */
\r
593 /* set attack rate & key scale */
\r
594 INLINE void set_ar_ksr(FM_CH *CH, FM_SLOT *SLOT, int v)
\r
596 UINT8 old_KSR = SLOT->KSR;
\r
598 SLOT->ar = (v&0x1f) ? 32 + ((v&0x1f)<<1) : 0;
\r
600 SLOT->KSR = 3-(v>>6);
\r
601 if (SLOT->KSR != old_KSR)
\r
603 CH->SLOT[SLOT1].Incr=-1;
\r
607 int eg_sh_ar, eg_sel_ar;
\r
609 /* refresh Attack rate */
\r
610 if ((SLOT->ar + SLOT->ksr) < 32+62)
\r
612 eg_sh_ar = eg_rate_shift [SLOT->ar + SLOT->ksr ];
\r
613 eg_sel_ar = eg_rate_select[SLOT->ar + SLOT->ksr ];
\r
621 SLOT->eg_pack_ar = eg_inc_pack[eg_sel_ar] | (eg_sh_ar<<24);
\r
625 /* set decay rate */
\r
626 INLINE void set_dr(FM_SLOT *SLOT, int v)
\r
628 int eg_sh_d1r, eg_sel_d1r;
\r
630 SLOT->d1r = (v&0x1f) ? 32 + ((v&0x1f)<<1) : 0;
\r
632 eg_sh_d1r = eg_rate_shift [SLOT->d1r + SLOT->ksr];
\r
633 eg_sel_d1r= eg_rate_select[SLOT->d1r + SLOT->ksr];
\r
635 SLOT->eg_pack_d1r = eg_inc_pack[eg_sel_d1r] | (eg_sh_d1r<<24);
\r
638 /* set sustain rate */
\r
639 INLINE void set_sr(FM_SLOT *SLOT, int v)
\r
641 int eg_sh_d2r, eg_sel_d2r;
\r
643 SLOT->d2r = (v&0x1f) ? 32 + ((v&0x1f)<<1) : 0;
\r
645 eg_sh_d2r = eg_rate_shift [SLOT->d2r + SLOT->ksr];
\r
646 eg_sel_d2r= eg_rate_select[SLOT->d2r + SLOT->ksr];
\r
648 SLOT->eg_pack_d2r = eg_inc_pack[eg_sel_d2r] | (eg_sh_d2r<<24);
\r
651 /* set release rate */
\r
652 INLINE void set_sl_rr(FM_SLOT *SLOT, int v)
\r
654 int eg_sh_rr, eg_sel_rr;
\r
656 SLOT->sl = sl_table[ v>>4 ];
\r
658 SLOT->rr = 34 + ((v&0x0f)<<2);
\r
660 eg_sh_rr = eg_rate_shift [SLOT->rr + SLOT->ksr];
\r
661 eg_sel_rr = eg_rate_select[SLOT->rr + SLOT->ksr];
\r
663 SLOT->eg_pack_rr = eg_inc_pack[eg_sel_rr] | (eg_sh_rr<<24);
\r
668 INLINE signed int op_calc(UINT32 phase, unsigned int env, signed int pm)
\r
670 int ret, sin = (phase>>16) + (pm>>1);
\r
671 int neg = sin & 0x200;
\r
672 if (sin & 0x100) sin ^= 0xff;
\r
676 // this was already checked
\r
677 // if (env >= ENV_QUIET) // 384
\r
680 ret = ym_tl_tab[sin | (env<<7)];
\r
682 return neg ? -ret : ret;
\r
685 INLINE signed int op_calc1(UINT32 phase, unsigned int env, signed int pm)
\r
687 int ret, sin = (phase+pm)>>16;
\r
688 int neg = sin & 0x200;
\r
689 if (sin & 0x100) sin ^= 0xff;
\r
693 // if (env >= ENV_QUIET) // 384
\r
696 ret = ym_tl_tab[sin | (env<<7)];
\r
698 return neg ? -ret : ret;
\r
701 #if !defined(_ASM_YM2612_C) || defined(EXTERNAL_YM2612)
\r
702 /* advance LFO to next sample */
\r
703 INLINE int advance_lfo(int lfo_ampm, UINT32 lfo_cnt_old, UINT32 lfo_cnt)
\r
708 prev_pos = (lfo_cnt_old >> LFO_SH) & 127;
\r
710 pos = (lfo_cnt >> LFO_SH) & 127;
\r
712 /* update AM when LFO output changes */
\r
714 if (prev_pos != pos)
\r
718 /* AM: 0 to 126 step +2, 126 to 0 step -2 */
\r
720 lfo_ampm |= ((pos&63) * 2) << 8; /* 0 - 126 */
\r
722 lfo_ampm |= (126 - (pos&63)*2) << 8;
\r
729 /* PM works with 4 times slower clock */
\r
732 /* update PM when LFO output changes */
\r
733 if (prev_pos != pos)
\r
736 lfo_ampm |= pos; /* 0 - 32 */
\r
741 #define EG_INC_VAL() \
\r
742 ((1 << ((pack >> ((eg_cnt>>shift)&7)*3)&7)) >> 1)
\r
744 INLINE UINT32 update_eg_phase(FM_SLOT *SLOT, UINT32 eg_cnt)
\r
746 INT32 volume = SLOT->volume;
\r
748 switch(SLOT->state)
\r
750 case EG_ATT: /* attack phase */
\r
752 UINT32 pack = SLOT->eg_pack_ar;
\r
753 UINT32 shift = pack>>24;
\r
754 if ( !(eg_cnt & ((1<<shift)-1) ) )
\r
756 volume += ( ~volume * EG_INC_VAL() ) >>4;
\r
758 if (volume <= MIN_ATT_INDEX)
\r
760 volume = MIN_ATT_INDEX;
\r
761 SLOT->state = EG_DEC;
\r
767 case EG_DEC: /* decay phase */
\r
769 UINT32 pack = SLOT->eg_pack_d1r;
\r
770 UINT32 shift = pack>>24;
\r
771 if ( !(eg_cnt & ((1<<shift)-1) ) )
\r
773 volume += EG_INC_VAL();
\r
775 if ( volume >= (INT32) SLOT->sl )
\r
776 SLOT->state = EG_SUS;
\r
781 case EG_SUS: /* sustain phase */
\r
783 UINT32 pack = SLOT->eg_pack_d2r;
\r
784 UINT32 shift = pack>>24;
\r
785 if ( !(eg_cnt & ((1<<shift)-1) ) )
\r
787 volume += EG_INC_VAL();
\r
789 if ( volume >= MAX_ATT_INDEX )
\r
791 volume = MAX_ATT_INDEX;
\r
792 /* do not change SLOT->state (verified on real chip) */
\r
798 case EG_REL: /* release phase */
\r
800 UINT32 pack = SLOT->eg_pack_rr;
\r
801 UINT32 shift = pack>>24;
\r
802 if ( !(eg_cnt & ((1<<shift)-1) ) )
\r
804 volume += EG_INC_VAL();
\r
806 if ( volume >= MAX_ATT_INDEX )
\r
808 volume = MAX_ATT_INDEX;
\r
809 SLOT->state = EG_OFF;
\r
816 SLOT->volume = volume;
\r
817 return SLOT->tl + ((UINT32)volume); /* tl is 7bit<<3, volume 0-1023 (0-2039 total) */
\r
824 UINT16 vol_out1; /* 00: current output from EG circuit (without AM from LFO) */
\r
829 UINT32 phase1; /* 10 */
\r
833 UINT32 incr1; /* 20: phase step */
\r
837 UINT32 lfo_cnt; /* 30 */
\r
839 INT32 mem; /* one sample delay memory */
\r
840 UINT32 eg_cnt; /* envelope generator counter */
\r
841 FM_CH *CH; /* 40: envelope generator counter */
\r
843 UINT32 eg_timer_add;
\r
844 UINT32 pack; // 4c: stereo, lastchan, disabled, lfo_enabled | pan_r, pan_l, ams[2] | AMmasks[4] | FB[4] | lfo_ampm[16]
\r
845 UINT32 algo; /* 50: algo[3], was_update */
\r
847 } chan_rend_context;
\r
850 #if !defined(_ASM_YM2612_C) || defined(EXTERNAL_YM2612)
\r
851 static void chan_render_loop(chan_rend_context *ct, int *buffer, int length)
\r
853 int scounter; /* sample counter */
\r
855 /* sample generating loop */
\r
856 for (scounter = 0; scounter < length; scounter++)
\r
858 int smp = 0; /* produced sample */
\r
859 unsigned int eg_out, eg_out2, eg_out4;
\r
861 if (ct->pack & 8) { /* LFO enabled ? (test Earthworm Jim in between demo 1 and 2) */
\r
862 ct->pack = (ct->pack&0xffff) | (advance_lfo(ct->pack >> 16, ct->lfo_cnt, ct->lfo_cnt + ct->lfo_inc) << 16);
\r
863 ct->lfo_cnt += ct->lfo_inc;
\r
866 ct->eg_timer += ct->eg_timer_add;
\r
867 while (ct->eg_timer >= EG_TIMER_OVERFLOW)
\r
869 ct->eg_timer -= EG_TIMER_OVERFLOW;
\r
872 if (ct->CH->SLOT[SLOT1].state != EG_OFF) ct->vol_out1 = update_eg_phase(&ct->CH->SLOT[SLOT1], ct->eg_cnt);
\r
873 if (ct->CH->SLOT[SLOT2].state != EG_OFF) ct->vol_out2 = update_eg_phase(&ct->CH->SLOT[SLOT2], ct->eg_cnt);
\r
874 if (ct->CH->SLOT[SLOT3].state != EG_OFF) ct->vol_out3 = update_eg_phase(&ct->CH->SLOT[SLOT3], ct->eg_cnt);
\r
875 if (ct->CH->SLOT[SLOT4].state != EG_OFF) ct->vol_out4 = update_eg_phase(&ct->CH->SLOT[SLOT4], ct->eg_cnt);
\r
878 if (ct->pack & 4) continue; /* output disabled */
\r
880 /* calculate channel sample */
\r
881 eg_out = ct->vol_out1;
\r
882 if ( (ct->pack & 8) && (ct->pack&(1<<(SLOT1+8))) ) eg_out += ct->pack >> (((ct->pack&0xc0)>>6)+24);
\r
884 if( eg_out < ENV_QUIET ) /* SLOT 1 */
\r
888 if (ct->pack&0xf000) out = ((ct->op1_out>>16) + (ct->op1_out<<16>>16)) << ((ct->pack&0xf000)>>12); /* op1_out0 + op1_out1 */
\r
889 ct->op1_out <<= 16;
\r
890 ct->op1_out |= (unsigned short)op_calc1(ct->phase1, eg_out, out);
\r
892 ct->op1_out <<= 16; /* op1_out0 = op1_out1; op1_out1 = 0; */
\r
895 eg_out = ct->vol_out3; // volume_calc(&CH->SLOT[SLOT3]);
\r
896 eg_out2 = ct->vol_out2; // volume_calc(&CH->SLOT[SLOT2]);
\r
897 eg_out4 = ct->vol_out4; // volume_calc(&CH->SLOT[SLOT4]);
\r
899 if (ct->pack & 8) {
\r
900 unsigned int add = ct->pack >> (((ct->pack&0xc0)>>6)+24);
\r
901 if (ct->pack & (1<<(SLOT3+8))) eg_out += add;
\r
902 if (ct->pack & (1<<(SLOT2+8))) eg_out2 += add;
\r
903 if (ct->pack & (1<<(SLOT4+8))) eg_out4 += add;
\r
906 switch( ct->CH->ALGO )
\r
909 case 0: smp = upd_algo0(ct); break;
\r
910 case 1: smp = upd_algo1(ct); break;
\r
911 case 2: smp = upd_algo2(ct); break;
\r
912 case 3: smp = upd_algo3(ct); break;
\r
913 case 4: smp = upd_algo4(ct); break;
\r
914 case 5: smp = upd_algo5(ct); break;
\r
915 case 6: smp = upd_algo6(ct); break;
\r
916 case 7: smp = upd_algo7(ct); break;
\r
920 /* M1---C1---MEM---M2---C2---OUT */
\r
921 int m2,c1,c2=0; /* Phase Modulation input for operators 2,3,4 */
\r
923 c1 = ct->op1_out>>16;
\r
924 if( eg_out < ENV_QUIET ) { /* SLOT 3 */
\r
925 c2 = op_calc(ct->phase3, eg_out, m2);
\r
927 if( eg_out2 < ENV_QUIET ) { /* SLOT 2 */
\r
928 ct->mem = op_calc(ct->phase2, eg_out2, c1);
\r
931 if( eg_out4 < ENV_QUIET ) { /* SLOT 4 */
\r
932 smp = op_calc(ct->phase4, eg_out4, c2);
\r
938 /* M1------+-MEM---M2---C2---OUT */
\r
942 ct->mem = ct->op1_out>>16;
\r
943 if( eg_out < ENV_QUIET ) { /* SLOT 3 */
\r
944 c2 = op_calc(ct->phase3, eg_out, m2);
\r
946 if( eg_out2 < ENV_QUIET ) { /* SLOT 2 */
\r
947 ct->mem+= op_calc(ct->phase2, eg_out2, 0);
\r
949 if( eg_out4 < ENV_QUIET ) { /* SLOT 4 */
\r
950 smp = op_calc(ct->phase4, eg_out4, c2);
\r
956 /* M1-----------------+-C2---OUT */
\r
957 /* C1---MEM---M2-+ */
\r
960 c2 = ct->op1_out>>16;
\r
961 if( eg_out < ENV_QUIET ) { /* SLOT 3 */
\r
962 c2 += op_calc(ct->phase3, eg_out, m2);
\r
964 if( eg_out2 < ENV_QUIET ) { /* SLOT 2 */
\r
965 ct->mem = op_calc(ct->phase2, eg_out2, 0);
\r
968 if( eg_out4 < ENV_QUIET ) { /* SLOT 4 */
\r
969 smp = op_calc(ct->phase4, eg_out4, c2);
\r
975 /* M1---C1---MEM------+-C2---OUT */
\r
979 c1 = ct->op1_out>>16;
\r
980 if( eg_out < ENV_QUIET ) { /* SLOT 3 */
\r
981 c2 += op_calc(ct->phase3, eg_out, 0);
\r
983 if( eg_out2 < ENV_QUIET ) { /* SLOT 2 */
\r
984 ct->mem = op_calc(ct->phase2, eg_out2, c1);
\r
987 if( eg_out4 < ENV_QUIET ) { /* SLOT 4 */
\r
988 smp = op_calc(ct->phase4, eg_out4, c2);
\r
994 /* M1---C1-+-OUT */
\r
996 /* MEM: not used */
\r
998 c1 = ct->op1_out>>16;
\r
999 if( eg_out < ENV_QUIET ) { /* SLOT 3 */
\r
1000 c2 = op_calc(ct->phase3, eg_out, 0);
\r
1002 if( eg_out2 < ENV_QUIET ) { /* SLOT 2 */
\r
1003 smp = op_calc(ct->phase2, eg_out2, c1);
\r
1005 if( eg_out4 < ENV_QUIET ) { /* SLOT 4 */
\r
1006 smp+= op_calc(ct->phase4, eg_out4, c2);
\r
1012 /* +----C1----+ */
\r
1013 /* M1-+-MEM---M2-+-OUT */
\r
1014 /* +----C2----+ */
\r
1017 ct->mem = c1 = c2 = ct->op1_out>>16;
\r
1018 if( eg_out < ENV_QUIET ) { /* SLOT 3 */
\r
1019 smp = op_calc(ct->phase3, eg_out, m2);
\r
1021 if( eg_out2 < ENV_QUIET ) { /* SLOT 2 */
\r
1022 smp+= op_calc(ct->phase2, eg_out2, c1);
\r
1024 if( eg_out4 < ENV_QUIET ) { /* SLOT 4 */
\r
1025 smp+= op_calc(ct->phase4, eg_out4, c2);
\r
1034 /* MEM: not used */
\r
1036 c1 = ct->op1_out>>16;
\r
1037 if( eg_out < ENV_QUIET ) { /* SLOT 3 */
\r
1038 smp = op_calc(ct->phase3, eg_out, 0);
\r
1040 if( eg_out2 < ENV_QUIET ) { /* SLOT 2 */
\r
1041 smp+= op_calc(ct->phase2, eg_out2, c1);
\r
1043 if( eg_out4 < ENV_QUIET ) { /* SLOT 4 */
\r
1044 smp+= op_calc(ct->phase4, eg_out4, 0);
\r
1054 /* MEM: not used*/
\r
1055 smp = ct->op1_out>>16;
\r
1056 if( eg_out < ENV_QUIET ) { /* SLOT 3 */
\r
1057 smp += op_calc(ct->phase3, eg_out, 0);
\r
1059 if( eg_out2 < ENV_QUIET ) { /* SLOT 2 */
\r
1060 smp += op_calc(ct->phase2, eg_out2, 0);
\r
1062 if( eg_out4 < ENV_QUIET ) { /* SLOT 4 */
\r
1063 smp += op_calc(ct->phase4, eg_out4, 0);
\r
1069 /* done calculating channel sample */
\r
1071 /* mix sample to output buffer */
\r
1073 if (ct->pack & 1) { /* stereo */
\r
1074 if (ct->pack & 0x20) /* L */ /* TODO: check correctness */
\r
1075 buffer[scounter*2] += smp;
\r
1076 if (ct->pack & 0x10) /* R */
\r
1077 buffer[scounter*2+1] += smp;
\r
1079 buffer[scounter] += smp;
\r
1081 ct->algo = 8; // algo is only used in asm, here only bit3 is used
\r
1084 /* update phase counters AFTER output calculations */
\r
1085 ct->phase1 += ct->incr1;
\r
1086 ct->phase2 += ct->incr2;
\r
1087 ct->phase3 += ct->incr3;
\r
1088 ct->phase4 += ct->incr4;
\r
1092 void chan_render_loop(chan_rend_context *ct, int *buffer, unsigned short length);
\r
1096 static int chan_render(int *buffer, int length, FM_CH *CH, UINT32 flags) // flags: stereo, lastchan, disabled, ?, pan_r, pan_l
\r
1098 chan_rend_context ct;
\r
1101 ct.mem = CH->mem_value; /* one sample delay memory */
\r
1102 ct.lfo_cnt = ym2612.OPN.lfo_cnt;
\r
1103 ct.lfo_inc = ym2612.OPN.lfo_inc;
\r
1109 flags |= g_lfo_ampm << 16;
\r
1110 flags |= CH->AMmasks << 8;
\r
1111 if (CH->ams == 8) // no ams
\r
1113 else flags |= (CH->ams&3)<<6;
\r
1115 flags |= (CH->FB&0xf)<<12; /* feedback shift */
\r
1118 ct.eg_cnt = ym2612.OPN.eg_cnt; /* envelope generator counter */
\r
1119 ct.eg_timer = ym2612.OPN.eg_timer;
\r
1120 ct.eg_timer_add = ym2612.OPN.eg_timer_add;
\r
1122 /* precalculate phase modulation incr */
\r
1123 ct.phase1 = CH->SLOT[SLOT1].phase;
\r
1124 ct.phase2 = CH->SLOT[SLOT2].phase;
\r
1125 ct.phase3 = CH->SLOT[SLOT3].phase;
\r
1126 ct.phase4 = CH->SLOT[SLOT4].phase;
\r
1128 /* current output from EG circuit (without AM from LFO) */
\r
1129 ct.vol_out1 = CH->SLOT[SLOT1].tl + ((UINT32)CH->SLOT[SLOT1].volume);
\r
1130 ct.vol_out2 = CH->SLOT[SLOT2].tl + ((UINT32)CH->SLOT[SLOT2].volume);
\r
1131 ct.vol_out3 = CH->SLOT[SLOT3].tl + ((UINT32)CH->SLOT[SLOT3].volume);
\r
1132 ct.vol_out4 = CH->SLOT[SLOT4].tl + ((UINT32)CH->SLOT[SLOT4].volume);
\r
1134 ct.op1_out = CH->op1_out;
\r
1135 ct.algo = CH->ALGO & 7;
\r
1139 /* add support for 3 slot mode */
\r
1140 UINT32 block_fnum = CH->block_fnum;
\r
1142 UINT32 fnum_lfo = ((block_fnum & 0x7f0) >> 4) * 32 * 8;
\r
1143 INT32 lfo_fn_table_index_offset = lfo_pm_table[ fnum_lfo + CH->pms + ((ct.pack>>16)&0xff) ];
\r
1145 if (lfo_fn_table_index_offset) /* LFO phase modulation active */
\r
1151 block_fnum = block_fnum*2 + lfo_fn_table_index_offset;
\r
1153 blk = (block_fnum&0x7000) >> 12;
\r
1154 fn = block_fnum & 0xfff;
\r
1156 /* keyscale code */
\r
1157 kc = (blk<<2) | opn_fktable[fn >> 8];
\r
1158 /* phase increment counter */
\r
1159 fc = fn_table[fn]>>(7-blk);
\r
1161 ct.incr1 = ((fc+CH->SLOT[SLOT1].DT[kc])*CH->SLOT[SLOT1].mul) >> 1;
\r
1162 ct.incr2 = ((fc+CH->SLOT[SLOT2].DT[kc])*CH->SLOT[SLOT2].mul) >> 1;
\r
1163 ct.incr3 = ((fc+CH->SLOT[SLOT3].DT[kc])*CH->SLOT[SLOT3].mul) >> 1;
\r
1164 ct.incr4 = ((fc+CH->SLOT[SLOT4].DT[kc])*CH->SLOT[SLOT4].mul) >> 1;
\r
1166 else /* LFO phase modulation = zero */
\r
1168 ct.incr1 = CH->SLOT[SLOT1].Incr;
\r
1169 ct.incr2 = CH->SLOT[SLOT2].Incr;
\r
1170 ct.incr3 = CH->SLOT[SLOT3].Incr;
\r
1171 ct.incr4 = CH->SLOT[SLOT4].Incr;
\r
1174 else /* no LFO phase modulation */
\r
1176 ct.incr1 = CH->SLOT[SLOT1].Incr;
\r
1177 ct.incr2 = CH->SLOT[SLOT2].Incr;
\r
1178 ct.incr3 = CH->SLOT[SLOT3].Incr;
\r
1179 ct.incr4 = CH->SLOT[SLOT4].Incr;
\r
1182 chan_render_loop(&ct, buffer, length);
\r
1184 // write back persistent stuff:
\r
1185 if (flags & 2) { /* last channel */
\r
1186 ym2612.OPN.eg_cnt = ct.eg_cnt;
\r
1187 ym2612.OPN.eg_timer = ct.eg_timer;
\r
1188 g_lfo_ampm = ct.pack >> 16;
\r
1189 ym2612.OPN.lfo_cnt = ct.lfo_cnt;
\r
1192 CH->op1_out = ct.op1_out;
\r
1193 CH->SLOT[SLOT1].phase = ct.phase1;
\r
1194 CH->SLOT[SLOT2].phase = ct.phase2;
\r
1195 CH->SLOT[SLOT3].phase = ct.phase3;
\r
1196 CH->SLOT[SLOT4].phase = ct.phase4;
\r
1197 CH->mem_value = ct.mem;
\r
1199 return (ct.algo & 8) >> 3; // had output
\r
1202 /* update phase increment and envelope generator */
\r
1203 INLINE void refresh_fc_eg_slot(FM_SLOT *SLOT, int fc, int kc)
\r
1207 /* (frequency) phase increment counter */
\r
1208 SLOT->Incr = ((fc+SLOT->DT[kc])*SLOT->mul) >> 1;
\r
1210 ksr = kc >> SLOT->KSR;
\r
1211 if( SLOT->ksr != ksr )
\r
1213 int eg_sh, eg_sel;
\r
1216 /* calculate envelope generator rates */
\r
1217 if ((SLOT->ar + SLOT->ksr) < 32+62)
\r
1219 eg_sh = eg_rate_shift [SLOT->ar + SLOT->ksr ];
\r
1220 eg_sel = eg_rate_select[SLOT->ar + SLOT->ksr ];
\r
1228 SLOT->eg_pack_ar = eg_inc_pack[eg_sel] | (eg_sh<<24);
\r
1230 eg_sh = eg_rate_shift [SLOT->d1r + SLOT->ksr];
\r
1231 eg_sel = eg_rate_select[SLOT->d1r + SLOT->ksr];
\r
1233 SLOT->eg_pack_d1r = eg_inc_pack[eg_sel] | (eg_sh<<24);
\r
1235 eg_sh = eg_rate_shift [SLOT->d2r + SLOT->ksr];
\r
1236 eg_sel = eg_rate_select[SLOT->d2r + SLOT->ksr];
\r
1238 SLOT->eg_pack_d2r = eg_inc_pack[eg_sel] | (eg_sh<<24);
\r
1240 eg_sh = eg_rate_shift [SLOT->rr + SLOT->ksr];
\r
1241 eg_sel = eg_rate_select[SLOT->rr + SLOT->ksr];
\r
1243 SLOT->eg_pack_rr = eg_inc_pack[eg_sel] | (eg_sh<<24);
\r
1247 /* update phase increment counters */
\r
1248 INLINE void refresh_fc_eg_chan(FM_CH *CH)
\r
1250 if( CH->SLOT[SLOT1].Incr==-1){
\r
1252 int kc = CH->kcode;
\r
1253 refresh_fc_eg_slot(&CH->SLOT[SLOT1] , fc , kc );
\r
1254 refresh_fc_eg_slot(&CH->SLOT[SLOT2] , fc , kc );
\r
1255 refresh_fc_eg_slot(&CH->SLOT[SLOT3] , fc , kc );
\r
1256 refresh_fc_eg_slot(&CH->SLOT[SLOT4] , fc , kc );
\r
1260 /* initialize time tables */
\r
1261 static void init_timetables(const UINT8 *dttable)
\r
1266 /* DeTune table */
\r
1267 for (d = 0;d <= 3;d++){
\r
1268 for (i = 0;i <= 31;i++){
\r
1269 rate = ((double)dttable[d*32 + i]) * SIN_LEN * ym2612.OPN.ST.freqbase * (1<<FREQ_SH) / ((double)(1<<20));
\r
1270 ym2612.OPN.ST.dt_tab[d][i] = (INT32) rate;
\r
1271 ym2612.OPN.ST.dt_tab[d+4][i] = -ym2612.OPN.ST.dt_tab[d][i];
\r
1277 static void reset_channels(FM_CH *CH, int num)
\r
1281 ym2612.OPN.ST.mode = 0; /* normal mode */
\r
1282 ym2612.OPN.ST.TA = 0;
\r
1283 ym2612.OPN.ST.TAC = 0;
\r
1284 ym2612.OPN.ST.TB = 0;
\r
1285 ym2612.OPN.ST.TBC = 0;
\r
1287 for( c = 0 ; c < num ; c++ )
\r
1290 for(s = 0 ; s < 4 ; s++ )
\r
1292 CH[c].SLOT[s].state= EG_OFF;
\r
1293 CH[c].SLOT[s].volume = MAX_ATT_INDEX;
\r
1298 /* initialize generic tables */
\r
1299 static void init_tables(void)
\r
1301 signed int i,x,y,p;
\r
1305 for (i=0; i < 256; i++)
\r
1307 /* non-standard sinus */
\r
1308 m = sin( ((i*2)+1) * M_PI / SIN_LEN ); /* checked against the real chip */
\r
1310 /* we never reach zero here due to ((i*2)+1) */
\r
1313 o = 8*log(1.0/m)/log(2); /* convert to 'decibels' */
\r
1315 o = 8*log(-1.0/m)/log(2); /* convert to 'decibels' */
\r
1317 o = o / (ENV_STEP/4);
\r
1320 if (n&1) /* round to nearest */
\r
1325 ym_sin_tab[ i ] = n;
\r
1326 //dprintf("FM.C: sin [%4i]= %4i", i, ym_sin_tab[i]);
\r
1329 //dprintf("FM.C: ENV_QUIET= %08x", ENV_QUIET );
\r
1332 for (x=0; x < TL_RES_LEN; x++)
\r
1334 m = (1<<16) / pow(2, (x+1) * (ENV_STEP/4.0) / 8.0);
\r
1337 /* we never reach (1<<16) here due to the (x+1) */
\r
1338 /* result fits within 16 bits at maximum */
\r
1340 n = (int)m; /* 16 bits here */
\r
1341 n >>= 4; /* 12 bits here */
\r
1342 if (n&1) /* round to nearest */
\r
1346 /* 11 bits here (rounded) */
\r
1347 n <<= 2; /* 13 bits here (as in real chip) */
\r
1348 ym_tl_tab2[ x ] = n;
\r
1350 for (i=1; i < 13; i++)
\r
1352 ym_tl_tab2[ x + i*TL_RES_LEN ] = n >> i;
\r
1356 for (x=0; x < 256; x++)
\r
1358 int sin = ym_sin_tab[ x ];
\r
1360 for (y=0; y < 2*13*TL_RES_LEN/8; y+=2)
\r
1363 if (p >= 13*TL_RES_LEN)
\r
1364 ym_tl_tab[(y<<7) | x] = 0;
\r
1365 else ym_tl_tab[(y<<7) | x] = ym_tl_tab2[p];
\r
1370 /* build LFO PM modulation table */
\r
1371 for(i = 0; i < 8; i++) /* 8 PM depths */
\r
1374 for (fnum=0; fnum<128; fnum++) /* 7 bits meaningful of F-NUMBER */
\r
1378 UINT32 offset_depth = i;
\r
1379 UINT32 offset_fnum_bit;
\r
1382 for (step=0; step<8; step++)
\r
1385 for (bit_tmp=0; bit_tmp<7; bit_tmp++) /* 7 bits */
\r
1387 if (fnum & (1<<bit_tmp)) /* only if bit "bit_tmp" is set */
\r
1389 offset_fnum_bit = bit_tmp * 8;
\r
1390 value += lfo_pm_output[offset_fnum_bit + offset_depth][step];
\r
1393 lfo_pm_table[(fnum*32*8) + (i*32) + step + 0] = value;
\r
1394 lfo_pm_table[(fnum*32*8) + (i*32) +(step^7)+ 8] = value;
\r
1395 lfo_pm_table[(fnum*32*8) + (i*32) + step +16] = -value;
\r
1396 lfo_pm_table[(fnum*32*8) + (i*32) +(step^7)+24] = -value;
\r
1403 /* CSM Key Controll */
\r
1404 INLINE void CSMKeyControll(FM_CH *CH)
\r
1406 /* this is wrong, atm */
\r
1409 FM_KEYON(CH,SLOT1);
\r
1410 FM_KEYON(CH,SLOT2);
\r
1411 FM_KEYON(CH,SLOT3);
\r
1412 FM_KEYON(CH,SLOT4);
\r
1416 /* prescaler set (and make time tables) */
\r
1417 static void OPNSetPres(int pres)
\r
1421 /* frequency base */
\r
1422 ym2612.OPN.ST.freqbase = (ym2612.OPN.ST.rate) ? ((double)ym2612.OPN.ST.clock / ym2612.OPN.ST.rate) / pres : 0;
\r
1424 ym2612.OPN.eg_timer_add = (1<<EG_SH) * ym2612.OPN.ST.freqbase;
\r
1427 /* make time tables */
\r
1428 init_timetables( dt_tab );
\r
1430 /* there are 2048 FNUMs that can be generated using FNUM/BLK registers
\r
1431 but LFO works with one more bit of a precision so we really need 4096 elements */
\r
1432 /* calculate fnumber -> increment counter table */
\r
1433 for(i = 0; i < 4096; i++)
\r
1435 /* freq table for octave 7 */
\r
1436 /* OPN phase increment counter = 20bit */
\r
1437 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
1440 /* LFO freq. table */
\r
1441 for(i = 0; i < 8; i++)
\r
1443 /* Amplitude modulation: 64 output levels (triangle waveform); 1 level lasts for one of "lfo_samples_per_step" samples */
\r
1444 /* Phase modulation: one entry from lfo_pm_output lasts for one of 4 * "lfo_samples_per_step" samples */
\r
1445 ym2612.OPN.lfo_freq[i] = (1.0 / lfo_samples_per_step[i]) * (1<<LFO_SH) * ym2612.OPN.ST.freqbase;
\r
1450 /* write a OPN register (0x30-0xff) */
\r
1451 static int OPNWriteReg(int r, int v)
\r
1457 UINT8 c = OPN_CHAN(r);
\r
1459 if (c == 3) return 0; /* 0xX3,0xX7,0xXB,0xXF */
\r
1461 if (r >= 0x100) c+=3;
\r
1463 CH = &ym2612.CH[c];
\r
1465 SLOT = &(CH->SLOT[OPN_SLOT(r)]);
\r
1467 switch( r & 0xf0 ) {
\r
1468 case 0x30: /* DET , MUL */
\r
1469 set_det_mul(CH,SLOT,v);
\r
1472 case 0x40: /* TL */
\r
1476 case 0x50: /* KS, AR */
\r
1477 set_ar_ksr(CH,SLOT,v);
\r
1480 case 0x60: /* bit7 = AM ENABLE, DR */
\r
1482 if(v&0x80) CH->AMmasks |= 1<<OPN_SLOT(r);
\r
1483 else CH->AMmasks &= ~(1<<OPN_SLOT(r));
\r
1486 case 0x70: /* SR */
\r
1490 case 0x80: /* SL, RR */
\r
1491 set_sl_rr(SLOT,v);
\r
1494 case 0x90: /* SSG-EG */
\r
1500 switch( OPN_SLOT(r) ){
\r
1501 case 0: /* 0xa0-0xa2 : FNUM1 */
\r
1503 UINT32 fn = (((UINT32)( (ym2612.OPN.ST.fn_h)&7))<<8) + v;
\r
1504 UINT8 blk = ym2612.OPN.ST.fn_h>>3;
\r
1505 /* keyscale code */
\r
1506 CH->kcode = (blk<<2) | opn_fktable[fn >> 7];
\r
1507 /* phase increment counter */
\r
1508 CH->fc = fn_table[fn*2]>>(7-blk);
\r
1510 /* store fnum in clear form for LFO PM calculations */
\r
1511 CH->block_fnum = (blk<<11) | fn;
\r
1513 CH->SLOT[SLOT1].Incr=-1;
\r
1516 case 1: /* 0xa4-0xa6 : FNUM2,BLK */
\r
1517 ym2612.OPN.ST.fn_h = v&0x3f;
\r
1520 case 2: /* 0xa8-0xaa : 3CH FNUM1 */
\r
1523 UINT32 fn = (((UINT32)(ym2612.OPN.SL3.fn_h&7))<<8) + v;
\r
1524 UINT8 blk = ym2612.OPN.SL3.fn_h>>3;
\r
1525 /* keyscale code */
\r
1526 ym2612.OPN.SL3.kcode[c]= (blk<<2) | opn_fktable[fn >> 7];
\r
1527 /* phase increment counter */
\r
1528 ym2612.OPN.SL3.fc[c] = fn_table[fn*2]>>(7-blk);
\r
1529 ym2612.OPN.SL3.block_fnum[c] = fn;
\r
1530 ym2612.CH[2].SLOT[SLOT1].Incr=-1;
\r
1533 case 3: /* 0xac-0xae : 3CH FNUM2,BLK */
\r
1535 ym2612.OPN.SL3.fn_h = v&0x3f;
\r
1545 switch( OPN_SLOT(r) ){
\r
1546 case 0: /* 0xb0-0xb2 : FB,ALGO */
\r
1548 int feedback = (v>>3)&7;
\r
1550 CH->FB = feedback ? feedback+6 : 0;
\r
1553 case 1: /* 0xb4-0xb6 : L , R , AMS , PMS (YM2612/YM2610B/YM2610/YM2608) */
\r
1555 int panshift = c<<1;
\r
1558 CH->pms = (v & 7) * 32; /* CH->pms = PM depth * 32 (index in lfo_pm_table) */
\r
1561 CH->ams = lfo_ams_depth_shift[(v>>4) & 3];
\r
1563 /* PAN : b7 = L, b6 = R */
\r
1564 ym2612.OPN.pan &= ~(3<<panshift);
\r
1565 ym2612.OPN.pan |= ((v & 0xc0) >> 6) << panshift; // ..LRLR
\r
1582 /*******************************************************************************/
\r
1583 /* YM2612 local section */
\r
1584 /*******************************************************************************/
\r
1586 int *ym2612_dacen;
\r
1587 INT32 *ym2612_dacout;
\r
1590 /* Generate samples for YM2612 */
\r
1591 int YM2612UpdateOne_(int *buffer, int length, int stereo, int is_buf_empty)
\r
1594 int active_chs = 0;
\r
1596 // if !is_buf_empty, it means it has valid samples to mix with, else it may contain trash
\r
1597 if (is_buf_empty) memset32(buffer, 0, length<<stereo);
\r
1599 /* refresh PG and EG */
\r
1600 refresh_fc_eg_chan( &ym2612.CH[0] );
\r
1601 refresh_fc_eg_chan( &ym2612.CH[1] );
\r
1602 if( (ym2612.OPN.ST.mode & 0xc0) )
\r
1605 if( ym2612.CH[2].SLOT[SLOT1].Incr==-1)
\r
1607 refresh_fc_eg_slot(&ym2612.CH[2].SLOT[SLOT1], ym2612.OPN.SL3.fc[1], ym2612.OPN.SL3.kcode[1] );
\r
1608 refresh_fc_eg_slot(&ym2612.CH[2].SLOT[SLOT2], ym2612.OPN.SL3.fc[2], ym2612.OPN.SL3.kcode[2] );
\r
1609 refresh_fc_eg_slot(&ym2612.CH[2].SLOT[SLOT3], ym2612.OPN.SL3.fc[0], ym2612.OPN.SL3.kcode[0] );
\r
1610 refresh_fc_eg_slot(&ym2612.CH[2].SLOT[SLOT4], ym2612.CH[2].fc , ym2612.CH[2].kcode );
\r
1612 } else refresh_fc_eg_chan( &ym2612.CH[2] );
\r
1613 refresh_fc_eg_chan( &ym2612.CH[3] );
\r
1614 refresh_fc_eg_chan( &ym2612.CH[4] );
\r
1615 refresh_fc_eg_chan( &ym2612.CH[5] );
\r
1617 pan = ym2612.OPN.pan;
\r
1618 if (stereo) stereo = 1;
\r
1620 /* mix to 32bit dest */
\r
1621 // flags: stereo, lastchan, disabled, ?, pan_r, pan_l
\r
1622 active_chs |= chan_render(buffer, length, &ym2612.CH[0], stereo|((pan&0x003)<<4)) << 0;
\r
1623 active_chs |= chan_render(buffer, length, &ym2612.CH[1], stereo|((pan&0x00c)<<2)) << 1;
\r
1624 active_chs |= chan_render(buffer, length, &ym2612.CH[2], stereo|((pan&0x030) )) << 2;
\r
1625 active_chs |= chan_render(buffer, length, &ym2612.CH[3], stereo|((pan&0x0c0)>>2)) << 3;
\r
1626 active_chs |= chan_render(buffer, length, &ym2612.CH[4], stereo|((pan&0x300)>>4)) << 4;
\r
1627 active_chs |= chan_render(buffer, length, &ym2612.CH[5], stereo|((pan&0xc00)>>6)|(ym2612.dacen<<2)|2) << 5;
\r
1629 return active_chs; // 1 if buffer updated
\r
1633 /* initialize YM2612 emulator */
\r
1634 void YM2612Init_(int clock, int rate)
\r
1637 ym2612_dacen = &ym2612.dacen;
\r
1638 ym2612_dacout = &ym2612.dacout;
\r
1640 /* clear everything but the regs */
\r
1641 memset(ym2612.CH, 0, sizeof(ym2612)-sizeof(ym2612.REGS)-4);
\r
1644 ym2612.OPN.ST.clock = clock;
\r
1645 ym2612.OPN.ST.rate = rate;
\r
1647 /* Extend handler */
\r
1648 YM2612ResetChip_();
\r
1653 void YM2612ResetChip_(void)
\r
1657 OPNSetPres( 6*24 );
\r
1658 set_timers( 0x30 ); /* mode 0 , timer reset */
\r
1660 ym2612.OPN.eg_timer = 0;
\r
1661 ym2612.OPN.eg_cnt = 0;
\r
1662 ym2612.OPN.ST.status = 0;
\r
1664 reset_channels( &ym2612.CH[0] , 6 );
\r
1665 for(i = 0xb6 ; i >= 0xb4 ; i-- )
\r
1667 OPNWriteReg(i ,0xc0);
\r
1668 OPNWriteReg(i|0x100,0xc0);
\r
1670 for(i = 0xb2 ; i >= 0x30 ; i-- )
\r
1672 OPNWriteReg(i ,0);
\r
1673 OPNWriteReg(i|0x100,0);
\r
1675 for(i = 0x26 ; i >= 0x20 ; i-- ) OPNWriteReg(i,0);
\r
1676 /* DAC mode clear */
\r
1681 /* YM2612 write */
\r
1684 /* returns 1 if sample affecting state changed */
\r
1685 int YM2612Write_(unsigned int a, unsigned int v)
\r
1689 v &= 0xff; /* adjust to 8 bit bus */
\r
1692 case 0: /* address port 0 */
\r
1693 ym2612.OPN.ST.address = v;
\r
1694 ym2612.addr_A1 = 0;
\r
1698 case 1: /* data port 0 */
\r
1699 if (ym2612.addr_A1 != 0) {
\r
1701 break; /* verified on real YM2608 */
\r
1704 addr = ym2612.OPN.ST.address;
\r
1705 ym2612.REGS[addr] = v;
\r
1707 switch( addr & 0xf0 )
\r
1709 case 0x20: /* 0x20-0x2f Mode */
\r
1712 case 0x22: /* LFO FREQ (YM2608/YM2610/YM2610B/YM2612) */
\r
1713 if (v&0x08) /* LFO enabled ? */
\r
1715 ym2612.OPN.lfo_inc = ym2612.OPN.lfo_freq[v&7];
\r
1719 ym2612.OPN.lfo_inc = 0;
\r
1722 case 0x24: { // timer A High 8
\r
1723 int TAnew = (ym2612.OPN.ST.TA & 0x03)|(((int)v)<<2);
\r
1724 if(ym2612.OPN.ST.TA != TAnew) {
\r
1725 // we should reset ticker only if new value is written. Outrun requires this.
\r
1726 ym2612.OPN.ST.TA = TAnew;
\r
1727 ym2612.OPN.ST.TAC = (1024-TAnew)*18;
\r
1728 ym2612.OPN.ST.TAT = 0;
\r
1733 case 0x25: { // timer A Low 2
\r
1734 int TAnew = (ym2612.OPN.ST.TA & 0x3fc)|(v&3);
\r
1735 if(ym2612.OPN.ST.TA != TAnew) {
\r
1736 ym2612.OPN.ST.TA = TAnew;
\r
1737 ym2612.OPN.ST.TAC = (1024-TAnew)*18;
\r
1738 ym2612.OPN.ST.TAT = 0;
\r
1743 case 0x26: // timer B
\r
1744 if(ym2612.OPN.ST.TB != v) {
\r
1745 ym2612.OPN.ST.TB = v;
\r
1746 ym2612.OPN.ST.TBC = (256-v)<<4;
\r
1747 ym2612.OPN.ST.TBC *= 18;
\r
1748 ym2612.OPN.ST.TBT = 0;
\r
1752 case 0x27: /* mode, timer control */
\r
1756 case 0x28: /* key on / off */
\r
1762 if( c == 3 ) { ret=0; break; }
\r
1763 if( v&0x04 ) c+=3;
\r
1764 CH = &ym2612.CH[c];
\r
1765 if(v&0x10) FM_KEYON(CH,SLOT1); else FM_KEYOFF(CH,SLOT1);
\r
1766 if(v&0x20) FM_KEYON(CH,SLOT2); else FM_KEYOFF(CH,SLOT2);
\r
1767 if(v&0x40) FM_KEYON(CH,SLOT3); else FM_KEYOFF(CH,SLOT3);
\r
1768 if(v&0x80) FM_KEYON(CH,SLOT4); else FM_KEYOFF(CH,SLOT4);
\r
1771 case 0x2a: /* DAC data (YM2612) */
\r
1772 ym2612.dacout = ((int)v - 0x80) << 6; /* level unknown (notaz: 8 seems to be too much) */
\r
1775 case 0x2b: /* DAC Sel (YM2612) */
\r
1776 /* b7 = dac enable */
\r
1777 ym2612.dacen = v & 0x80;
\r
1784 default: /* 0x30-0xff OPN section */
\r
1785 /* write register */
\r
1786 ret = OPNWriteReg(addr,v);
\r
1790 case 2: /* address port 1 */
\r
1791 ym2612.OPN.ST.address = v;
\r
1792 ym2612.addr_A1 = 1;
\r
1796 case 3: /* data port 1 */
\r
1797 if (ym2612.addr_A1 != 1) {
\r
1799 break; /* verified on real YM2608 */
\r
1802 addr = ym2612.OPN.ST.address | 0x100;
\r
1803 ym2612.REGS[addr] = v;
\r
1805 ret = OPNWriteReg(addr, v);
\r
1810 extern int Scanline;
\r
1811 dprintf("ymw [%i]", Scanline);
\r
1817 UINT8 YM2612Read_(void)
\r
1819 return ym2612.OPN.ST.status;
\r
1823 int YM2612PicoTick_(int n)
\r
1828 if(ym2612.OPN.ST.mode & 0x01 && (ym2612.OPN.ST.TAT+=64*n) >= ym2612.OPN.ST.TAC) {
\r
1829 ym2612.OPN.ST.TAT -= ym2612.OPN.ST.TAC;
\r
1830 if(ym2612.OPN.ST.mode & 0x04) ym2612.OPN.ST.status |= 1;
\r
1831 // CSM mode total level latch and auto key on
\r
1832 if(ym2612.OPN.ST.mode & 0x80) {
\r
1833 CSMKeyControll( &(ym2612.CH[2]) ); // Vectorman2, etc.
\r
1839 if(ym2612.OPN.ST.mode & 0x02 && (ym2612.OPN.ST.TBT+=64*n) >= ym2612.OPN.ST.TBC) {
\r
1840 ym2612.OPN.ST.TBT -= ym2612.OPN.ST.TBC;
\r
1841 if(ym2612.OPN.ST.mode & 0x08) ym2612.OPN.ST.status |= 2;
\r
1848 void YM2612PicoStateLoad_(void)
\r
1850 #ifndef EXTERNAL_YM2612
\r
1851 int i, old_A1 = ym2612.addr_A1;
\r
1853 reset_channels( &ym2612.CH[0], 6 );
\r
1855 // feed all the registers and update internal state
\r
1856 for(i = 0; i < 0x100; i++) {
\r
1857 YM2612Write_(0, i);
\r
1858 YM2612Write_(1, ym2612.REGS[i]);
\r
1860 for(i = 0; i < 0x100; i++) {
\r
1861 YM2612Write_(2, i);
\r
1862 YM2612Write_(3, ym2612.REGS[i|0x100]);
\r
1865 ym2612.addr_A1 = old_A1;
\r
1867 reset_channels( &ym2612.CH[0], 6 );
\r
1872 void *YM2612GetRegs(void)
\r
1874 return ym2612.REGS;
\r