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
117 #ifndef EXTERNAL_YM2612
\r
118 #include <stdlib.h>
\r
119 // let it be 1 global to simplify things
\r
120 static YM2612 ym2612;
\r
123 extern YM2612 *ym2612_940;
\r
124 #define ym2612 (*ym2612_940)
\r
130 #pragma warning (disable:4100) // unreferenced formal parameter
\r
131 #pragma warning (disable:4244)
\r
132 #pragma warning (disable:4245) // signed/unsigned in conversion
\r
133 #pragma warning (disable:4710)
\r
134 #pragma warning (disable:4018) // signed/unsigned
\r
138 #define INLINE static __inline
\r
142 #define M_PI 3.14159265358979323846
\r
148 #define FREQ_SH 16 /* 16.16 fixed point (frequency calculations) */
\r
149 #define EG_SH 16 /* 16.16 fixed point (envelope generator timing) */
\r
150 #define LFO_SH 25 /* 7.25 fixed point (LFO calculations) */
\r
151 #define TIMER_SH 16 /* 16.16 fixed point (timers calculations) */
\r
153 #define ENV_BITS 10
\r
154 #define ENV_LEN (1<<ENV_BITS)
\r
155 #define ENV_STEP (128.0/ENV_LEN)
\r
157 #define MAX_ATT_INDEX (ENV_LEN-1) /* 1023 */
\r
158 #define MIN_ATT_INDEX (0) /* 0 */
\r
166 #define SIN_BITS 10
\r
167 #define SIN_LEN (1<<SIN_BITS)
\r
168 #define SIN_MASK (SIN_LEN-1)
\r
170 #define TL_RES_LEN (256) /* 8 bits addressing (real chip) */
\r
172 #define EG_TIMER_OVERFLOW (3*(1<<EG_SH)) /* envelope generator timer overflows every 3 samples (on real chip) */
\r
174 #define MAXOUT (+32767)
\r
175 #define MINOUT (-32768)
\r
178 #define Limit(val, max,min) { \
\r
179 if ( val > max ) val = max; \
\r
180 else if ( val < min ) val = min; \
\r
184 /* TL_TAB_LEN is calculated as:
\r
185 * 13 - sinus amplitude bits (Y axis)
\r
186 * 2 - sinus sign bit (Y axis)
\r
187 * TL_RES_LEN - sinus resolution (X axis)
\r
189 //#define TL_TAB_LEN (13*2*TL_RES_LEN)
\r
190 #define TL_TAB_LEN (13*TL_RES_LEN*256/8) // 106496*2
\r
191 UINT16 ym_tl_tab[TL_TAB_LEN];
\r
193 /* ~3K wasted but oh well */
\r
194 UINT16 ym_tl_tab2[13*TL_RES_LEN];
\r
196 #define ENV_QUIET (2*13*TL_RES_LEN/8)
\r
198 /* sin waveform table in 'decibel' scale (use only period/4 values) */
\r
199 static UINT16 ym_sin_tab[256];
\r
201 /* sustain level table (3dB per step) */
\r
202 /* bit0, bit1, bit2, bit3, bit4, bit5, bit6 */
\r
203 /* 1, 2, 4, 8, 16, 32, 64 (value)*/
\r
204 /* 0.75, 1.5, 3, 6, 12, 24, 48 (dB)*/
\r
206 /* 0 - 15: 0, 3, 6, 9,12,15,18,21,24,27,30,33,36,39,42,93 (dB)*/
\r
207 #define SC(db) (UINT32) ( db * (4.0/ENV_STEP) )
\r
208 static const UINT32 sl_table[16]={
\r
209 SC( 0),SC( 1),SC( 2),SC(3 ),SC(4 ),SC(5 ),SC(6 ),SC( 7),
\r
210 SC( 8),SC( 9),SC(10),SC(11),SC(12),SC(13),SC(14),SC(31)
\r
216 #define RATE_STEPS (8)
\r
217 static const UINT8 eg_inc[19*RATE_STEPS]={
\r
219 /*cycle:0 1 2 3 4 5 6 7*/
\r
221 /* 0 */ 0,1, 0,1, 0,1, 0,1, /* rates 00..11 0 (increment by 0 or 1) */
\r
222 /* 1 */ 0,1, 0,1, 1,1, 0,1, /* rates 00..11 1 */
\r
223 /* 2 */ 0,1, 1,1, 0,1, 1,1, /* rates 00..11 2 */
\r
224 /* 3 */ 0,1, 1,1, 1,1, 1,1, /* rates 00..11 3 */
\r
226 /* 4 */ 1,1, 1,1, 1,1, 1,1, /* rate 12 0 (increment by 1) */
\r
227 /* 5 */ 1,1, 1,2, 1,1, 1,2, /* rate 12 1 */
\r
228 /* 6 */ 1,2, 1,2, 1,2, 1,2, /* rate 12 2 */
\r
229 /* 7 */ 1,2, 2,2, 1,2, 2,2, /* rate 12 3 */
\r
231 /* 8 */ 2,2, 2,2, 2,2, 2,2, /* rate 13 0 (increment by 2) */
\r
232 /* 9 */ 2,2, 2,4, 2,2, 2,4, /* rate 13 1 */
\r
233 /*10 */ 2,4, 2,4, 2,4, 2,4, /* rate 13 2 */
\r
234 /*11 */ 2,4, 4,4, 2,4, 4,4, /* rate 13 3 */
\r
236 /*12 */ 4,4, 4,4, 4,4, 4,4, /* rate 14 0 (increment by 4) */
\r
237 /*13 */ 4,4, 4,8, 4,4, 4,8, /* rate 14 1 */
\r
238 /*14 */ 4,8, 4,8, 4,8, 4,8, /* rate 14 2 */
\r
239 /*15 */ 4,8, 8,8, 4,8, 8,8, /* rate 14 3 */
\r
241 /*16 */ 8,8, 8,8, 8,8, 8,8, /* rates 15 0, 15 1, 15 2, 15 3 (increment by 8) */
\r
242 /*17 */ 16,16,16,16,16,16,16,16, /* rates 15 2, 15 3 for attack */
\r
243 /*18 */ 0,0, 0,0, 0,0, 0,0, /* infinity rates for attack and decay(s) */
\r
248 #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
249 static const UINT32 eg_inc_pack[19] =
\r
251 /* 0 */ PACK(0,1,0,1,0,1,0,1), /* rates 00..11 0 (increment by 0 or 1) */
\r
252 /* 1 */ PACK(0,1,0,1,1,1,0,1), /* rates 00..11 1 */
\r
253 /* 2 */ PACK(0,1,1,1,0,1,1,1), /* rates 00..11 2 */
\r
254 /* 3 */ PACK(0,1,1,1,1,1,1,1), /* rates 00..11 3 */
\r
256 /* 4 */ PACK(1,1,1,1,1,1,1,1), /* rate 12 0 (increment by 1) */
\r
257 /* 5 */ PACK(1,1,1,2,1,1,1,2), /* rate 12 1 */
\r
258 /* 6 */ PACK(1,2,1,2,1,2,1,2), /* rate 12 2 */
\r
259 /* 7 */ PACK(1,2,2,2,1,2,2,2), /* rate 12 3 */
\r
261 /* 8 */ PACK(2,2,2,2,2,2,2,2), /* rate 13 0 (increment by 2) */
\r
262 /* 9 */ PACK(2,2,2,3,2,2,2,3), /* rate 13 1 */
\r
263 /*10 */ PACK(2,3,2,3,2,3,2,3), /* rate 13 2 */
\r
264 /*11 */ PACK(2,3,3,3,2,3,3,3), /* rate 13 3 */
\r
266 /*12 */ PACK(3,3,3,3,3,3,3,3), /* rate 14 0 (increment by 4) */
\r
267 /*13 */ PACK(3,3,3,4,3,3,3,4), /* rate 14 1 */
\r
268 /*14 */ PACK(3,4,3,4,3,4,3,4), /* rate 14 2 */
\r
269 /*15 */ PACK(3,4,4,4,3,4,4,4), /* rate 14 3 */
\r
271 /*16 */ PACK(4,4,4,4,4,4,4,4), /* rates 15 0, 15 1, 15 2, 15 3 (increment by 8) */
\r
272 /*17 */ PACK(5,5,5,5,5,5,5,5), /* rates 15 2, 15 3 for attack */
\r
273 /*18 */ PACK(0,0,0,0,0,0,0,0), /* infinity rates for attack and decay(s) */
\r
277 //#define O(a) (a*RATE_STEPS)
\r
280 /*note that there is no O(17) in this table - it's directly in the code */
\r
281 static const UINT8 eg_rate_select[32+64+32]={ /* Envelope Generator rates (32 + 64 rates + 32 RKS) */
\r
282 /* 32 infinite time rates */
\r
283 O(18),O(18),O(18),O(18),O(18),O(18),O(18),O(18),
\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
289 O( 0),O( 1),O( 2),O( 3),
\r
290 O( 0),O( 1),O( 2),O( 3),
\r
291 O( 0),O( 1),O( 2),O( 3),
\r
292 O( 0),O( 1),O( 2),O( 3),
\r
293 O( 0),O( 1),O( 2),O( 3),
\r
294 O( 0),O( 1),O( 2),O( 3),
\r
295 O( 0),O( 1),O( 2),O( 3),
\r
296 O( 0),O( 1),O( 2),O( 3),
\r
297 O( 0),O( 1),O( 2),O( 3),
\r
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
303 O( 4),O( 5),O( 6),O( 7),
\r
306 O( 8),O( 9),O(10),O(11),
\r
309 O(12),O(13),O(14),O(15),
\r
312 O(16),O(16),O(16),O(16),
\r
314 /* 32 dummy rates (same as 15 3) */
\r
315 O(16),O(16),O(16),O(16),O(16),O(16),O(16),O(16),
\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
323 /*rate 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15*/
\r
324 /*shift 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 0, 0, 0, 0, 0 */
\r
325 /*mask 2047, 1023, 511, 255, 127, 63, 31, 15, 7, 3, 1, 0, 0, 0, 0, 0 */
\r
328 static const UINT8 eg_rate_shift[32+64+32]={ /* Envelope Generator counter shifts (32 + 64 rates + 32 RKS) */
\r
329 /* 32 infinite time rates */
\r
330 O(0),O(0),O(0),O(0),O(0),O(0),O(0),O(0),
\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
336 O(11),O(11),O(11),O(11),
\r
337 O(10),O(10),O(10),O(10),
\r
338 O( 9),O( 9),O( 9),O( 9),
\r
339 O( 8),O( 8),O( 8),O( 8),
\r
340 O( 7),O( 7),O( 7),O( 7),
\r
341 O( 6),O( 6),O( 6),O( 6),
\r
342 O( 5),O( 5),O( 5),O( 5),
\r
343 O( 4),O( 4),O( 4),O( 4),
\r
344 O( 3),O( 3),O( 3),O( 3),
\r
345 O( 2),O( 2),O( 2),O( 2),
\r
346 O( 1),O( 1),O( 1),O( 1),
\r
347 O( 0),O( 0),O( 0),O( 0),
\r
350 O( 0),O( 0),O( 0),O( 0),
\r
353 O( 0),O( 0),O( 0),O( 0),
\r
356 O( 0),O( 0),O( 0),O( 0),
\r
359 O( 0),O( 0),O( 0),O( 0),
\r
361 /* 32 dummy rates (same as 15 3) */
\r
362 O( 0),O( 0),O( 0),O( 0),O( 0),O( 0),O( 0),O( 0),
\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
370 static const UINT8 dt_tab[4 * 32]={
\r
371 /* this is YM2151 and YM2612 phase increment data (in 10.10 fixed point format)*/
\r
373 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
\r
374 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
\r
376 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 2, 2, 2, 2,
\r
377 2, 3, 3, 3, 4, 4, 4, 5, 5, 6, 6, 7, 8, 8, 8, 8,
\r
379 1, 1, 1, 1, 2, 2, 2, 2, 2, 3, 3, 3, 4, 4, 4, 5,
\r
380 5, 6, 6, 7, 8, 8, 9,10,11,12,13,14,16,16,16,16,
\r
382 2, 2, 2, 2, 2, 3, 3, 3, 4, 4, 4, 5, 5, 6, 6, 7,
\r
383 8 , 8, 9,10,11,12,13,14,16,17,19,20,22,22,22,22
\r
387 /* OPN key frequency number -> key code follow table */
\r
388 /* fnum higher 4bit -> keycode lower 2bit */
\r
389 static const UINT8 opn_fktable[16] = {0,0,0,0,0,0,0,1,2,3,3,3,3,3,3,3};
\r
392 /* 8 LFO speed parameters */
\r
393 /* each value represents number of samples that one LFO level will last for */
\r
394 static const UINT32 lfo_samples_per_step[8] = {108, 77, 71, 67, 62, 44, 8, 5};
\r
398 /*There are 4 different LFO AM depths available, they are:
\r
399 0 dB, 1.4 dB, 5.9 dB, 11.8 dB
\r
400 Here is how it is generated (in EG steps):
\r
402 11.8 dB = 0, 2, 4, 6, 8, 10,12,14,16...126,126,124,122,120,118,....4,2,0
\r
403 5.9 dB = 0, 1, 2, 3, 4, 5, 6, 7, 8....63, 63, 62, 61, 60, 59,.....2,1,0
\r
404 1.4 dB = 0, 0, 0, 0, 1, 1, 1, 1, 2,...15, 15, 15, 15, 14, 14,.....0,0,0
\r
406 (1.4 dB is loosing precision as you can see)
\r
408 It's implemented as generator from 0..126 with step 2 then a shift
\r
409 right N times, where N is:
\r
415 static const UINT8 lfo_ams_depth_shift[4] = {8, 3, 1, 0};
\r
419 /*There are 8 different LFO PM depths available, they are:
\r
420 0, 3.4, 6.7, 10, 14, 20, 40, 80 (cents)
\r
422 Modulation level at each depth depends on F-NUMBER bits: 4,5,6,7,8,9,10
\r
423 (bits 8,9,10 = FNUM MSB from OCT/FNUM register)
\r
425 Here we store only first quarter (positive one) of full waveform.
\r
426 Full table (lfo_pm_table) containing all 128 waveforms is build
\r
427 at run (init) time.
\r
429 One value in table below represents 4 (four) basic LFO steps
\r
430 (1 PM step = 4 AM steps).
\r
433 at LFO SPEED=0 (which is 108 samples per basic LFO step)
\r
434 one value from "lfo_pm_output" table lasts for 432 consecutive
\r
435 samples (4*108=432) and one full LFO waveform cycle lasts for 13824
\r
436 samples (32*432=13824; 32 because we store only a quarter of whole
\r
437 waveform in the table below)
\r
439 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
440 /* FNUM BIT 4: 000 0001xxxx */
\r
441 /* DEPTH 0 */ {0, 0, 0, 0, 0, 0, 0, 0},
\r
442 /* DEPTH 1 */ {0, 0, 0, 0, 0, 0, 0, 0},
\r
443 /* DEPTH 2 */ {0, 0, 0, 0, 0, 0, 0, 0},
\r
444 /* DEPTH 3 */ {0, 0, 0, 0, 0, 0, 0, 0},
\r
445 /* DEPTH 4 */ {0, 0, 0, 0, 0, 0, 0, 0},
\r
446 /* DEPTH 5 */ {0, 0, 0, 0, 0, 0, 0, 0},
\r
447 /* DEPTH 6 */ {0, 0, 0, 0, 0, 0, 0, 0},
\r
448 /* DEPTH 7 */ {0, 0, 0, 0, 1, 1, 1, 1},
\r
450 /* FNUM BIT 5: 000 0010xxxx */
\r
451 /* DEPTH 0 */ {0, 0, 0, 0, 0, 0, 0, 0},
\r
452 /* DEPTH 1 */ {0, 0, 0, 0, 0, 0, 0, 0},
\r
453 /* DEPTH 2 */ {0, 0, 0, 0, 0, 0, 0, 0},
\r
454 /* DEPTH 3 */ {0, 0, 0, 0, 0, 0, 0, 0},
\r
455 /* DEPTH 4 */ {0, 0, 0, 0, 0, 0, 0, 0},
\r
456 /* DEPTH 5 */ {0, 0, 0, 0, 0, 0, 0, 0},
\r
457 /* DEPTH 6 */ {0, 0, 0, 0, 1, 1, 1, 1},
\r
458 /* DEPTH 7 */ {0, 0, 1, 1, 2, 2, 2, 3},
\r
460 /* FNUM BIT 6: 000 0100xxxx */
\r
461 /* DEPTH 0 */ {0, 0, 0, 0, 0, 0, 0, 0},
\r
462 /* DEPTH 1 */ {0, 0, 0, 0, 0, 0, 0, 0},
\r
463 /* DEPTH 2 */ {0, 0, 0, 0, 0, 0, 0, 0},
\r
464 /* DEPTH 3 */ {0, 0, 0, 0, 0, 0, 0, 0},
\r
465 /* DEPTH 4 */ {0, 0, 0, 0, 0, 0, 0, 1},
\r
466 /* DEPTH 5 */ {0, 0, 0, 0, 1, 1, 1, 1},
\r
467 /* DEPTH 6 */ {0, 0, 1, 1, 2, 2, 2, 3},
\r
468 /* DEPTH 7 */ {0, 0, 2, 3, 4, 4, 5, 6},
\r
470 /* FNUM BIT 7: 000 1000xxxx */
\r
471 /* DEPTH 0 */ {0, 0, 0, 0, 0, 0, 0, 0},
\r
472 /* DEPTH 1 */ {0, 0, 0, 0, 0, 0, 0, 0},
\r
473 /* DEPTH 2 */ {0, 0, 0, 0, 0, 0, 1, 1},
\r
474 /* DEPTH 3 */ {0, 0, 0, 0, 1, 1, 1, 1},
\r
475 /* DEPTH 4 */ {0, 0, 0, 1, 1, 1, 1, 2},
\r
476 /* DEPTH 5 */ {0, 0, 1, 1, 2, 2, 2, 3},
\r
477 /* DEPTH 6 */ {0, 0, 2, 3, 4, 4, 5, 6},
\r
478 /* DEPTH 7 */ {0, 0, 4, 6, 8, 8, 0xa, 0xc},
\r
480 /* FNUM BIT 8: 001 0000xxxx */
\r
481 /* DEPTH 0 */ {0, 0, 0, 0, 0, 0, 0, 0},
\r
482 /* DEPTH 1 */ {0, 0, 0, 0, 1, 1, 1, 1},
\r
483 /* DEPTH 2 */ {0, 0, 0, 1, 1, 1, 2, 2},
\r
484 /* DEPTH 3 */ {0, 0, 1, 1, 2, 2, 3, 3},
\r
485 /* DEPTH 4 */ {0, 0, 1, 2, 2, 2, 3, 4},
\r
486 /* DEPTH 5 */ {0, 0, 2, 3, 4, 4, 5, 6},
\r
487 /* DEPTH 6 */ {0, 0, 4, 6, 8, 8, 0xa, 0xc},
\r
488 /* DEPTH 7 */ {0, 0, 8, 0xc,0x10,0x10,0x14,0x18},
\r
490 /* FNUM BIT 9: 010 0000xxxx */
\r
491 /* DEPTH 0 */ {0, 0, 0, 0, 0, 0, 0, 0},
\r
492 /* DEPTH 1 */ {0, 0, 0, 0, 2, 2, 2, 2},
\r
493 /* DEPTH 2 */ {0, 0, 0, 2, 2, 2, 4, 4},
\r
494 /* DEPTH 3 */ {0, 0, 2, 2, 4, 4, 6, 6},
\r
495 /* DEPTH 4 */ {0, 0, 2, 4, 4, 4, 6, 8},
\r
496 /* DEPTH 5 */ {0, 0, 4, 6, 8, 8, 0xa, 0xc},
\r
497 /* DEPTH 6 */ {0, 0, 8, 0xc,0x10,0x10,0x14,0x18},
\r
498 /* DEPTH 7 */ {0, 0,0x10,0x18,0x20,0x20,0x28,0x30},
\r
500 /* FNUM BIT10: 100 0000xxxx */
\r
501 /* DEPTH 0 */ {0, 0, 0, 0, 0, 0, 0, 0},
\r
502 /* DEPTH 1 */ {0, 0, 0, 0, 4, 4, 4, 4},
\r
503 /* DEPTH 2 */ {0, 0, 0, 4, 4, 4, 8, 8},
\r
504 /* DEPTH 3 */ {0, 0, 4, 4, 8, 8, 0xc, 0xc},
\r
505 /* DEPTH 4 */ {0, 0, 4, 8, 8, 8, 0xc,0x10},
\r
506 /* DEPTH 5 */ {0, 0, 8, 0xc,0x10,0x10,0x14,0x18},
\r
507 /* DEPTH 6 */ {0, 0,0x10,0x18,0x20,0x20,0x28,0x30},
\r
508 /* DEPTH 7 */ {0, 0,0x20,0x30,0x40,0x40,0x50,0x60},
\r
512 /* all 128 LFO PM waveforms */
\r
513 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
515 /* there are 2048 FNUMs that can be generated using FNUM/BLK registers
\r
516 but LFO works with one more bit of a precision so we really need 4096 elements */
\r
517 static UINT32 fn_table[4096]; /* fnumber->increment counter */
\r
519 static int g_lfo_ampm = 0;
\r
521 /* register number to channel number , slot offset */
\r
522 #define OPN_CHAN(N) (N&3)
\r
523 #define OPN_SLOT(N) ((N>>2)&3)
\r
532 /* OPN Mode Register Write */
\r
533 INLINE void set_timers( int v )
\r
535 /* b7 = CSM MODE */
\r
536 /* b6 = 3 slot mode */
\r
539 /* b3 = timer enable b */
\r
540 /* b2 = timer enable a */
\r
543 ym2612.OPN.ST.mode = v;
\r
545 /* reset Timer b flag */
\r
547 ym2612.OPN.ST.status &= ~2;
\r
549 /* reset Timer a flag */
\r
551 ym2612.OPN.ST.status &= ~1;
\r
555 INLINE void FM_KEYON(FM_CH *CH , int s )
\r
557 FM_SLOT *SLOT = &CH->SLOT[s];
\r
561 SLOT->phase = 0; /* restart Phase Generator */
\r
562 SLOT->state = EG_ATT; /* phase -> Attack */
\r
566 INLINE void FM_KEYOFF(FM_CH *CH , int s )
\r
568 FM_SLOT *SLOT = &CH->SLOT[s];
\r
572 if (SLOT->state>EG_REL)
\r
573 SLOT->state = EG_REL;/* phase -> Release */
\r
578 /* set detune & multiple */
\r
579 INLINE void set_det_mul(FM_CH *CH, FM_SLOT *SLOT, int v)
\r
581 SLOT->mul = (v&0x0f)? (v&0x0f)*2 : 1;
\r
582 SLOT->DT = ym2612.OPN.ST.dt_tab[(v>>4)&7];
\r
583 CH->SLOT[SLOT1].Incr=-1;
\r
586 /* set total level */
\r
587 INLINE void set_tl(FM_SLOT *SLOT, int v)
\r
589 SLOT->tl = (v&0x7f)<<(ENV_BITS-7); /* 7bit TL */
\r
592 /* set attack rate & key scale */
\r
593 INLINE void set_ar_ksr(FM_CH *CH, FM_SLOT *SLOT, int v)
\r
595 UINT8 old_KSR = SLOT->KSR;
\r
597 SLOT->ar = (v&0x1f) ? 32 + ((v&0x1f)<<1) : 0;
\r
599 SLOT->KSR = 3-(v>>6);
\r
600 if (SLOT->KSR != old_KSR)
\r
602 CH->SLOT[SLOT1].Incr=-1;
\r
606 int eg_sh_ar, eg_sel_ar;
\r
608 /* refresh Attack rate */
\r
609 if ((SLOT->ar + SLOT->ksr) < 32+62)
\r
611 eg_sh_ar = eg_rate_shift [SLOT->ar + SLOT->ksr ];
\r
612 eg_sel_ar = eg_rate_select[SLOT->ar + SLOT->ksr ];
\r
620 SLOT->eg_pack_ar = eg_inc_pack[eg_sel_ar] | (eg_sh_ar<<24);
\r
624 /* set decay rate */
\r
625 INLINE void set_dr(FM_SLOT *SLOT, int v)
\r
627 int eg_sh_d1r, eg_sel_d1r;
\r
629 SLOT->d1r = (v&0x1f) ? 32 + ((v&0x1f)<<1) : 0;
\r
631 eg_sh_d1r = eg_rate_shift [SLOT->d1r + SLOT->ksr];
\r
632 eg_sel_d1r= eg_rate_select[SLOT->d1r + SLOT->ksr];
\r
634 SLOT->eg_pack_d1r = eg_inc_pack[eg_sel_d1r] | (eg_sh_d1r<<24);
\r
637 /* set sustain rate */
\r
638 INLINE void set_sr(FM_SLOT *SLOT, int v)
\r
640 int eg_sh_d2r, eg_sel_d2r;
\r
642 SLOT->d2r = (v&0x1f) ? 32 + ((v&0x1f)<<1) : 0;
\r
644 eg_sh_d2r = eg_rate_shift [SLOT->d2r + SLOT->ksr];
\r
645 eg_sel_d2r= eg_rate_select[SLOT->d2r + SLOT->ksr];
\r
647 SLOT->eg_pack_d2r = eg_inc_pack[eg_sel_d2r] | (eg_sh_d2r<<24);
\r
650 /* set release rate */
\r
651 INLINE void set_sl_rr(FM_SLOT *SLOT, int v)
\r
653 int eg_sh_rr, eg_sel_rr;
\r
655 SLOT->sl = sl_table[ v>>4 ];
\r
657 SLOT->rr = 34 + ((v&0x0f)<<2);
\r
659 eg_sh_rr = eg_rate_shift [SLOT->rr + SLOT->ksr];
\r
660 eg_sel_rr = eg_rate_select[SLOT->rr + SLOT->ksr];
\r
662 SLOT->eg_pack_rr = eg_inc_pack[eg_sel_rr] | (eg_sh_rr<<24);
\r
667 INLINE signed int op_calc(UINT32 phase, unsigned int env, signed int pm)
\r
669 int ret, sin = (phase>>16) + (pm>>1);
\r
670 int neg = sin & 0x200;
\r
671 if (sin & 0x100) sin ^= 0xff;
\r
675 // this was already checked
\r
676 // if (env >= ENV_QUIET) // 384
\r
679 ret = ym_tl_tab[sin | (env<<7)];
\r
681 return neg ? -ret : ret;
\r
684 INLINE signed int op_calc1(UINT32 phase, unsigned int env, signed int pm)
\r
686 int ret, sin = (phase+pm)>>16;
\r
687 int neg = sin & 0x200;
\r
688 if (sin & 0x100) sin ^= 0xff;
\r
692 // if (env >= ENV_QUIET) // 384
\r
695 ret = ym_tl_tab[sin | (env<<7)];
\r
697 return neg ? -ret : ret;
\r
700 #if !defined(_ASM_YM2612_C) || defined(EXTERNAL_YM2612)
\r
701 /* advance LFO to next sample */
\r
702 INLINE int advance_lfo(int lfo_ampm, UINT32 lfo_cnt_old, UINT32 lfo_cnt)
\r
707 prev_pos = (lfo_cnt_old >> LFO_SH) & 127;
\r
709 pos = (lfo_cnt >> LFO_SH) & 127;
\r
711 /* update AM when LFO output changes */
\r
713 if (prev_pos != pos)
\r
717 /* AM: 0 to 126 step +2, 126 to 0 step -2 */
\r
719 lfo_ampm |= ((pos&63) * 2) << 8; /* 0 - 126 */
\r
721 lfo_ampm |= (126 - (pos&63)*2) << 8;
\r
728 /* PM works with 4 times slower clock */
\r
731 /* update PM when LFO output changes */
\r
732 if (prev_pos != pos)
\r
735 lfo_ampm |= pos; /* 0 - 32 */
\r
740 #define EG_INC_VAL() \
\r
741 ((1 << ((pack >> ((eg_cnt>>shift)&7)*3)&7)) >> 1)
\r
743 INLINE UINT32 update_eg_phase(FM_SLOT *SLOT, UINT32 eg_cnt)
\r
745 INT32 volume = SLOT->volume;
\r
747 switch(SLOT->state)
\r
749 case EG_ATT: /* attack phase */
\r
751 UINT32 pack = SLOT->eg_pack_ar;
\r
752 UINT32 shift = pack>>24;
\r
753 if ( !(eg_cnt & ((1<<shift)-1) ) )
\r
755 volume += ( ~volume * EG_INC_VAL() ) >>4;
\r
757 if (volume <= MIN_ATT_INDEX)
\r
759 volume = MIN_ATT_INDEX;
\r
760 SLOT->state = EG_DEC;
\r
766 case EG_DEC: /* decay phase */
\r
768 UINT32 pack = SLOT->eg_pack_d1r;
\r
769 UINT32 shift = pack>>24;
\r
770 if ( !(eg_cnt & ((1<<shift)-1) ) )
\r
772 volume += EG_INC_VAL();
\r
774 if ( volume >= (INT32) SLOT->sl )
\r
775 SLOT->state = EG_SUS;
\r
780 case EG_SUS: /* sustain phase */
\r
782 UINT32 pack = SLOT->eg_pack_d2r;
\r
783 UINT32 shift = pack>>24;
\r
784 if ( !(eg_cnt & ((1<<shift)-1) ) )
\r
786 volume += EG_INC_VAL();
\r
788 if ( volume >= MAX_ATT_INDEX )
\r
790 volume = MAX_ATT_INDEX;
\r
791 /* do not change SLOT->state (verified on real chip) */
\r
797 case EG_REL: /* release phase */
\r
799 UINT32 pack = SLOT->eg_pack_rr;
\r
800 UINT32 shift = pack>>24;
\r
801 if ( !(eg_cnt & ((1<<shift)-1) ) )
\r
803 volume += EG_INC_VAL();
\r
805 if ( volume >= MAX_ATT_INDEX )
\r
807 volume = MAX_ATT_INDEX;
\r
808 SLOT->state = EG_OFF;
\r
815 SLOT->volume = volume;
\r
816 return SLOT->tl + ((UINT32)volume); /* tl is 7bit<<3, volume 0-1023 (0-2039 total) */
\r
823 UINT16 vol_out1; /* 00: current output from EG circuit (without AM from LFO) */
\r
828 UINT32 phase1; /* 10 */
\r
832 UINT32 incr1; /* 20: phase step */
\r
836 UINT32 lfo_cnt; /* 30 */
\r
838 INT32 mem; /* one sample delay memory */
\r
839 UINT32 eg_cnt; /* envelope generator counter */
\r
840 FM_CH *CH; /* 40: envelope generator counter */
\r
842 UINT32 eg_timer_add;
\r
843 UINT32 pack; // 4c: stereo, lastchan, disabled, lfo_enabled | pan_r, pan_l, ams[2] | AMmasks[4] | FB[4] | lfo_ampm[16]
\r
844 UINT32 algo; /* 50: algo[3], was_update */
\r
846 } chan_rend_context;
\r
849 #if !defined(_ASM_YM2612_C) || defined(EXTERNAL_YM2612)
\r
850 static void chan_render_loop(chan_rend_context *ct, int *buffer, int length)
\r
852 int scounter; /* sample counter */
\r
854 /* sample generating loop */
\r
855 for (scounter = 0; scounter < length; scounter++)
\r
857 int smp = 0; /* produced sample */
\r
858 unsigned int eg_out, eg_out2, eg_out4;
\r
860 if (ct->pack & 8) { /* LFO enabled ? (test Earthworm Jim in between demo 1 and 2) */
\r
861 ct->pack = (ct->pack&0xffff) | (advance_lfo(ct->pack >> 16, ct->lfo_cnt, ct->lfo_cnt + ct->lfo_inc) << 16);
\r
862 ct->lfo_cnt += ct->lfo_inc;
\r
865 ct->eg_timer += ct->eg_timer_add;
\r
866 while (ct->eg_timer >= EG_TIMER_OVERFLOW)
\r
868 ct->eg_timer -= EG_TIMER_OVERFLOW;
\r
871 if (ct->CH->SLOT[SLOT1].state != EG_OFF) ct->vol_out1 = update_eg_phase(&ct->CH->SLOT[SLOT1], ct->eg_cnt);
\r
872 if (ct->CH->SLOT[SLOT2].state != EG_OFF) ct->vol_out2 = update_eg_phase(&ct->CH->SLOT[SLOT2], ct->eg_cnt);
\r
873 if (ct->CH->SLOT[SLOT3].state != EG_OFF) ct->vol_out3 = update_eg_phase(&ct->CH->SLOT[SLOT3], ct->eg_cnt);
\r
874 if (ct->CH->SLOT[SLOT4].state != EG_OFF) ct->vol_out4 = update_eg_phase(&ct->CH->SLOT[SLOT4], ct->eg_cnt);
\r
877 if (ct->pack & 4) continue; /* output disabled */
\r
879 /* calculate channel sample */
\r
880 eg_out = ct->vol_out1;
\r
881 if ( (ct->pack & 8) && (ct->pack&(1<<(SLOT1+8))) ) eg_out += ct->pack >> (((ct->pack&0xc0)>>6)+24);
\r
883 if( eg_out < ENV_QUIET ) /* SLOT 1 */
\r
887 if (ct->pack&0xf000) out = ((ct->op1_out>>16) + (ct->op1_out<<16>>16)) << ((ct->pack&0xf000)>>12); /* op1_out0 + op1_out1 */
\r
888 ct->op1_out <<= 16;
\r
889 ct->op1_out |= (unsigned short)op_calc1(ct->phase1, eg_out, out);
\r
891 ct->op1_out <<= 16; /* op1_out0 = op1_out1; op1_out1 = 0; */
\r
894 eg_out = ct->vol_out3; // volume_calc(&CH->SLOT[SLOT3]);
\r
895 eg_out2 = ct->vol_out2; // volume_calc(&CH->SLOT[SLOT2]);
\r
896 eg_out4 = ct->vol_out4; // volume_calc(&CH->SLOT[SLOT4]);
\r
898 if (ct->pack & 8) {
\r
899 unsigned int add = ct->pack >> (((ct->pack&0xc0)>>6)+24);
\r
900 if (ct->pack & (1<<(SLOT3+8))) eg_out += add;
\r
901 if (ct->pack & (1<<(SLOT2+8))) eg_out2 += add;
\r
902 if (ct->pack & (1<<(SLOT4+8))) eg_out4 += add;
\r
905 switch( ct->CH->ALGO )
\r
908 case 0: smp = upd_algo0(ct); break;
\r
909 case 1: smp = upd_algo1(ct); break;
\r
910 case 2: smp = upd_algo2(ct); break;
\r
911 case 3: smp = upd_algo3(ct); break;
\r
912 case 4: smp = upd_algo4(ct); break;
\r
913 case 5: smp = upd_algo5(ct); break;
\r
914 case 6: smp = upd_algo6(ct); break;
\r
915 case 7: smp = upd_algo7(ct); break;
\r
919 /* M1---C1---MEM---M2---C2---OUT */
\r
920 int m2,c1,c2=0; /* Phase Modulation input for operators 2,3,4 */
\r
922 c1 = ct->op1_out>>16;
\r
923 if( eg_out < ENV_QUIET ) { /* SLOT 3 */
\r
924 c2 = op_calc(ct->phase3, eg_out, m2);
\r
926 if( eg_out2 < ENV_QUIET ) { /* SLOT 2 */
\r
927 ct->mem = op_calc(ct->phase2, eg_out2, c1);
\r
930 if( eg_out4 < ENV_QUIET ) { /* SLOT 4 */
\r
931 smp = op_calc(ct->phase4, eg_out4, c2);
\r
937 /* M1------+-MEM---M2---C2---OUT */
\r
941 ct->mem = ct->op1_out>>16;
\r
942 if( eg_out < ENV_QUIET ) { /* SLOT 3 */
\r
943 c2 = op_calc(ct->phase3, eg_out, m2);
\r
945 if( eg_out2 < ENV_QUIET ) { /* SLOT 2 */
\r
946 ct->mem+= op_calc(ct->phase2, eg_out2, 0);
\r
948 if( eg_out4 < ENV_QUIET ) { /* SLOT 4 */
\r
949 smp = op_calc(ct->phase4, eg_out4, c2);
\r
955 /* M1-----------------+-C2---OUT */
\r
956 /* C1---MEM---M2-+ */
\r
959 c2 = ct->op1_out>>16;
\r
960 if( eg_out < ENV_QUIET ) { /* SLOT 3 */
\r
961 c2 += op_calc(ct->phase3, eg_out, m2);
\r
963 if( eg_out2 < ENV_QUIET ) { /* SLOT 2 */
\r
964 ct->mem = op_calc(ct->phase2, eg_out2, 0);
\r
967 if( eg_out4 < ENV_QUIET ) { /* SLOT 4 */
\r
968 smp = op_calc(ct->phase4, eg_out4, c2);
\r
974 /* M1---C1---MEM------+-C2---OUT */
\r
978 c1 = ct->op1_out>>16;
\r
979 if( eg_out < ENV_QUIET ) { /* SLOT 3 */
\r
980 c2 += op_calc(ct->phase3, eg_out, 0);
\r
982 if( eg_out2 < ENV_QUIET ) { /* SLOT 2 */
\r
983 ct->mem = op_calc(ct->phase2, eg_out2, c1);
\r
986 if( eg_out4 < ENV_QUIET ) { /* SLOT 4 */
\r
987 smp = op_calc(ct->phase4, eg_out4, c2);
\r
993 /* M1---C1-+-OUT */
\r
995 /* MEM: not used */
\r
997 c1 = ct->op1_out>>16;
\r
998 if( eg_out < ENV_QUIET ) { /* SLOT 3 */
\r
999 c2 = op_calc(ct->phase3, eg_out, 0);
\r
1001 if( eg_out2 < ENV_QUIET ) { /* SLOT 2 */
\r
1002 smp = op_calc(ct->phase2, eg_out2, c1);
\r
1004 if( eg_out4 < ENV_QUIET ) { /* SLOT 4 */
\r
1005 smp+= op_calc(ct->phase4, eg_out4, c2);
\r
1011 /* +----C1----+ */
\r
1012 /* M1-+-MEM---M2-+-OUT */
\r
1013 /* +----C2----+ */
\r
1016 ct->mem = c1 = c2 = ct->op1_out>>16;
\r
1017 if( eg_out < ENV_QUIET ) { /* SLOT 3 */
\r
1018 smp = op_calc(ct->phase3, eg_out, m2);
\r
1020 if( eg_out2 < ENV_QUIET ) { /* SLOT 2 */
\r
1021 smp+= op_calc(ct->phase2, eg_out2, c1);
\r
1023 if( eg_out4 < ENV_QUIET ) { /* SLOT 4 */
\r
1024 smp+= op_calc(ct->phase4, eg_out4, c2);
\r
1033 /* MEM: not used */
\r
1035 c1 = ct->op1_out>>16;
\r
1036 if( eg_out < ENV_QUIET ) { /* SLOT 3 */
\r
1037 smp = op_calc(ct->phase3, eg_out, 0);
\r
1039 if( eg_out2 < ENV_QUIET ) { /* SLOT 2 */
\r
1040 smp+= op_calc(ct->phase2, eg_out2, c1);
\r
1042 if( eg_out4 < ENV_QUIET ) { /* SLOT 4 */
\r
1043 smp+= op_calc(ct->phase4, eg_out4, 0);
\r
1053 /* MEM: not used*/
\r
1054 smp = ct->op1_out>>16;
\r
1055 if( eg_out < ENV_QUIET ) { /* SLOT 3 */
\r
1056 smp += op_calc(ct->phase3, eg_out, 0);
\r
1058 if( eg_out2 < ENV_QUIET ) { /* SLOT 2 */
\r
1059 smp += op_calc(ct->phase2, eg_out2, 0);
\r
1061 if( eg_out4 < ENV_QUIET ) { /* SLOT 4 */
\r
1062 smp += op_calc(ct->phase4, eg_out4, 0);
\r
1068 /* done calculating channel sample */
\r
1070 /* mix sample to output buffer */
\r
1072 if (ct->pack & 1) { /* stereo */
\r
1073 if (ct->pack & 0x20) /* L */ /* TODO: check correctness */
\r
1074 buffer[scounter*2] += smp;
\r
1075 if (ct->pack & 0x10) /* R */
\r
1076 buffer[scounter*2+1] += smp;
\r
1078 buffer[scounter] += smp;
\r
1080 ct->algo = 8; // algo is only used in asm, here only bit3 is used
\r
1083 /* update phase counters AFTER output calculations */
\r
1084 ct->phase1 += ct->incr1;
\r
1085 ct->phase2 += ct->incr2;
\r
1086 ct->phase3 += ct->incr3;
\r
1087 ct->phase4 += ct->incr4;
\r
1091 void chan_render_loop(chan_rend_context *ct, int *buffer, unsigned short length);
\r
1095 static int chan_render(int *buffer, int length, FM_CH *CH, UINT32 flags) // flags: stereo, lastchan, disabled, ?, pan_r, pan_l
\r
1097 chan_rend_context ct;
\r
1100 ct.mem = CH->mem_value; /* one sample delay memory */
\r
1101 ct.lfo_cnt = ym2612.OPN.lfo_cnt;
\r
1102 ct.lfo_inc = ym2612.OPN.lfo_inc;
\r
1108 flags |= g_lfo_ampm << 16;
\r
1109 flags |= CH->AMmasks << 8;
\r
1110 if (CH->ams == 8) // no ams
\r
1112 else flags |= (CH->ams&3)<<6;
\r
1114 flags |= (CH->FB&0xf)<<12; /* feedback shift */
\r
1117 ct.eg_cnt = ym2612.OPN.eg_cnt; /* envelope generator counter */
\r
1118 ct.eg_timer = ym2612.OPN.eg_timer;
\r
1119 ct.eg_timer_add = ym2612.OPN.eg_timer_add;
\r
1121 /* precalculate phase modulation incr */
\r
1122 ct.phase1 = CH->SLOT[SLOT1].phase;
\r
1123 ct.phase2 = CH->SLOT[SLOT2].phase;
\r
1124 ct.phase3 = CH->SLOT[SLOT3].phase;
\r
1125 ct.phase4 = CH->SLOT[SLOT4].phase;
\r
1127 /* current output from EG circuit (without AM from LFO) */
\r
1128 ct.vol_out1 = CH->SLOT[SLOT1].tl + ((UINT32)CH->SLOT[SLOT1].volume);
\r
1129 ct.vol_out2 = CH->SLOT[SLOT2].tl + ((UINT32)CH->SLOT[SLOT2].volume);
\r
1130 ct.vol_out3 = CH->SLOT[SLOT3].tl + ((UINT32)CH->SLOT[SLOT3].volume);
\r
1131 ct.vol_out4 = CH->SLOT[SLOT4].tl + ((UINT32)CH->SLOT[SLOT4].volume);
\r
1133 ct.op1_out = CH->op1_out;
\r
1134 ct.algo = CH->ALGO & 7;
\r
1138 /* add support for 3 slot mode */
\r
1139 UINT32 block_fnum = CH->block_fnum;
\r
1141 UINT32 fnum_lfo = ((block_fnum & 0x7f0) >> 4) * 32 * 8;
\r
1142 INT32 lfo_fn_table_index_offset = lfo_pm_table[ fnum_lfo + CH->pms + ((ct.pack>>16)&0xff) ];
\r
1144 if (lfo_fn_table_index_offset) /* LFO phase modulation active */
\r
1150 block_fnum = block_fnum*2 + lfo_fn_table_index_offset;
\r
1152 blk = (block_fnum&0x7000) >> 12;
\r
1153 fn = block_fnum & 0xfff;
\r
1155 /* keyscale code */
\r
1156 kc = (blk<<2) | opn_fktable[fn >> 8];
\r
1157 /* phase increment counter */
\r
1158 fc = fn_table[fn]>>(7-blk);
\r
1160 ct.incr1 = ((fc+CH->SLOT[SLOT1].DT[kc])*CH->SLOT[SLOT1].mul) >> 1;
\r
1161 ct.incr2 = ((fc+CH->SLOT[SLOT2].DT[kc])*CH->SLOT[SLOT2].mul) >> 1;
\r
1162 ct.incr3 = ((fc+CH->SLOT[SLOT3].DT[kc])*CH->SLOT[SLOT3].mul) >> 1;
\r
1163 ct.incr4 = ((fc+CH->SLOT[SLOT4].DT[kc])*CH->SLOT[SLOT4].mul) >> 1;
\r
1165 else /* LFO phase modulation = zero */
\r
1167 ct.incr1 = CH->SLOT[SLOT1].Incr;
\r
1168 ct.incr2 = CH->SLOT[SLOT2].Incr;
\r
1169 ct.incr3 = CH->SLOT[SLOT3].Incr;
\r
1170 ct.incr4 = CH->SLOT[SLOT4].Incr;
\r
1173 else /* no LFO phase modulation */
\r
1175 ct.incr1 = CH->SLOT[SLOT1].Incr;
\r
1176 ct.incr2 = CH->SLOT[SLOT2].Incr;
\r
1177 ct.incr3 = CH->SLOT[SLOT3].Incr;
\r
1178 ct.incr4 = CH->SLOT[SLOT4].Incr;
\r
1181 chan_render_loop(&ct, buffer, length);
\r
1183 // write back persistent stuff:
\r
1184 if (flags & 2) { /* last channel */
\r
1185 ym2612.OPN.eg_cnt = ct.eg_cnt;
\r
1186 ym2612.OPN.eg_timer = ct.eg_timer;
\r
1187 g_lfo_ampm = ct.pack >> 16;
\r
1188 ym2612.OPN.lfo_cnt = ct.lfo_cnt;
\r
1191 CH->op1_out = ct.op1_out;
\r
1192 CH->SLOT[SLOT1].phase = ct.phase1;
\r
1193 CH->SLOT[SLOT2].phase = ct.phase2;
\r
1194 CH->SLOT[SLOT3].phase = ct.phase3;
\r
1195 CH->SLOT[SLOT4].phase = ct.phase4;
\r
1196 CH->mem_value = ct.mem;
\r
1198 return (ct.algo & 8) >> 3; // had output
\r
1201 /* update phase increment and envelope generator */
\r
1202 INLINE void refresh_fc_eg_slot(FM_SLOT *SLOT, int fc, int kc)
\r
1206 /* (frequency) phase increment counter */
\r
1207 SLOT->Incr = ((fc+SLOT->DT[kc])*SLOT->mul) >> 1;
\r
1209 ksr = kc >> SLOT->KSR;
\r
1210 if( SLOT->ksr != ksr )
\r
1212 int eg_sh, eg_sel;
\r
1215 /* calculate envelope generator rates */
\r
1216 if ((SLOT->ar + SLOT->ksr) < 32+62)
\r
1218 eg_sh = eg_rate_shift [SLOT->ar + SLOT->ksr ];
\r
1219 eg_sel = eg_rate_select[SLOT->ar + SLOT->ksr ];
\r
1227 SLOT->eg_pack_ar = eg_inc_pack[eg_sel] | (eg_sh<<24);
\r
1229 eg_sh = eg_rate_shift [SLOT->d1r + SLOT->ksr];
\r
1230 eg_sel = eg_rate_select[SLOT->d1r + SLOT->ksr];
\r
1232 SLOT->eg_pack_d1r = eg_inc_pack[eg_sel] | (eg_sh<<24);
\r
1234 eg_sh = eg_rate_shift [SLOT->d2r + SLOT->ksr];
\r
1235 eg_sel = eg_rate_select[SLOT->d2r + SLOT->ksr];
\r
1237 SLOT->eg_pack_d2r = eg_inc_pack[eg_sel] | (eg_sh<<24);
\r
1239 eg_sh = eg_rate_shift [SLOT->rr + SLOT->ksr];
\r
1240 eg_sel = eg_rate_select[SLOT->rr + SLOT->ksr];
\r
1242 SLOT->eg_pack_rr = eg_inc_pack[eg_sel] | (eg_sh<<24);
\r
1246 /* update phase increment counters */
\r
1247 INLINE void refresh_fc_eg_chan(FM_CH *CH)
\r
1249 if( CH->SLOT[SLOT1].Incr==-1){
\r
1251 int kc = CH->kcode;
\r
1252 refresh_fc_eg_slot(&CH->SLOT[SLOT1] , fc , kc );
\r
1253 refresh_fc_eg_slot(&CH->SLOT[SLOT2] , fc , kc );
\r
1254 refresh_fc_eg_slot(&CH->SLOT[SLOT3] , fc , kc );
\r
1255 refresh_fc_eg_slot(&CH->SLOT[SLOT4] , fc , kc );
\r
1259 /* initialize time tables */
\r
1260 static void init_timetables(const UINT8 *dttable)
\r
1265 /* DeTune table */
\r
1266 for (d = 0;d <= 3;d++){
\r
1267 for (i = 0;i <= 31;i++){
\r
1268 rate = ((double)dttable[d*32 + i]) * SIN_LEN * ym2612.OPN.ST.freqbase * (1<<FREQ_SH) / ((double)(1<<20));
\r
1269 ym2612.OPN.ST.dt_tab[d][i] = (INT32) rate;
\r
1270 ym2612.OPN.ST.dt_tab[d+4][i] = -ym2612.OPN.ST.dt_tab[d][i];
\r
1276 static void reset_channels(FM_CH *CH, int num)
\r
1280 ym2612.OPN.ST.mode = 0; /* normal mode */
\r
1281 ym2612.OPN.ST.TA = 0;
\r
1282 ym2612.OPN.ST.TAC = 0;
\r
1283 ym2612.OPN.ST.TB = 0;
\r
1284 ym2612.OPN.ST.TBC = 0;
\r
1286 for( c = 0 ; c < num ; c++ )
\r
1289 for(s = 0 ; s < 4 ; s++ )
\r
1291 CH[c].SLOT[s].state= EG_OFF;
\r
1292 CH[c].SLOT[s].volume = MAX_ATT_INDEX;
\r
1297 /* initialize generic tables */
\r
1298 static void init_tables(void)
\r
1300 signed int i,x,y,p;
\r
1304 for (i=0; i < 256; i++)
\r
1306 /* non-standard sinus */
\r
1307 m = sin( ((i*2)+1) * M_PI / SIN_LEN ); /* checked against the real chip */
\r
1309 /* we never reach zero here due to ((i*2)+1) */
\r
1312 o = 8*log(1.0/m)/log(2); /* convert to 'decibels' */
\r
1314 o = 8*log(-1.0/m)/log(2); /* convert to 'decibels' */
\r
1316 o = o / (ENV_STEP/4);
\r
1319 if (n&1) /* round to nearest */
\r
1324 ym_sin_tab[ i ] = n;
\r
1325 //dprintf("FM.C: sin [%4i]= %4i", i, ym_sin_tab[i]);
\r
1328 //dprintf("FM.C: ENV_QUIET= %08x", ENV_QUIET );
\r
1331 for (x=0; x < TL_RES_LEN; x++)
\r
1333 m = (1<<16) / pow(2, (x+1) * (ENV_STEP/4.0) / 8.0);
\r
1336 /* we never reach (1<<16) here due to the (x+1) */
\r
1337 /* result fits within 16 bits at maximum */
\r
1339 n = (int)m; /* 16 bits here */
\r
1340 n >>= 4; /* 12 bits here */
\r
1341 if (n&1) /* round to nearest */
\r
1345 /* 11 bits here (rounded) */
\r
1346 n <<= 2; /* 13 bits here (as in real chip) */
\r
1347 ym_tl_tab2[ x ] = n;
\r
1349 for (i=1; i < 13; i++)
\r
1351 ym_tl_tab2[ x + i*TL_RES_LEN ] = n >> i;
\r
1355 for (x=0; x < 256; x++)
\r
1357 int sin = ym_sin_tab[ x ];
\r
1359 for (y=0; y < 2*13*TL_RES_LEN/8; y+=2)
\r
1362 if (p >= 13*TL_RES_LEN)
\r
1363 ym_tl_tab[(y<<7) | x] = 0;
\r
1364 else ym_tl_tab[(y<<7) | x] = ym_tl_tab2[p];
\r
1369 /* build LFO PM modulation table */
\r
1370 for(i = 0; i < 8; i++) /* 8 PM depths */
\r
1373 for (fnum=0; fnum<128; fnum++) /* 7 bits meaningful of F-NUMBER */
\r
1377 UINT32 offset_depth = i;
\r
1378 UINT32 offset_fnum_bit;
\r
1381 for (step=0; step<8; step++)
\r
1384 for (bit_tmp=0; bit_tmp<7; bit_tmp++) /* 7 bits */
\r
1386 if (fnum & (1<<bit_tmp)) /* only if bit "bit_tmp" is set */
\r
1388 offset_fnum_bit = bit_tmp * 8;
\r
1389 value += lfo_pm_output[offset_fnum_bit + offset_depth][step];
\r
1392 lfo_pm_table[(fnum*32*8) + (i*32) + step + 0] = value;
\r
1393 lfo_pm_table[(fnum*32*8) + (i*32) +(step^7)+ 8] = value;
\r
1394 lfo_pm_table[(fnum*32*8) + (i*32) + step +16] = -value;
\r
1395 lfo_pm_table[(fnum*32*8) + (i*32) +(step^7)+24] = -value;
\r
1402 /* CSM Key Controll */
\r
1403 INLINE void CSMKeyControll(FM_CH *CH)
\r
1405 /* this is wrong, atm */
\r
1408 FM_KEYON(CH,SLOT1);
\r
1409 FM_KEYON(CH,SLOT2);
\r
1410 FM_KEYON(CH,SLOT3);
\r
1411 FM_KEYON(CH,SLOT4);
\r
1415 /* prescaler set (and make time tables) */
\r
1416 static void OPNSetPres(int pres)
\r
1420 /* frequency base */
\r
1421 ym2612.OPN.ST.freqbase = (ym2612.OPN.ST.rate) ? ((double)ym2612.OPN.ST.clock / ym2612.OPN.ST.rate) / pres : 0;
\r
1423 ym2612.OPN.eg_timer_add = (1<<EG_SH) * ym2612.OPN.ST.freqbase;
\r
1426 /* make time tables */
\r
1427 init_timetables( dt_tab );
\r
1429 /* there are 2048 FNUMs that can be generated using FNUM/BLK registers
\r
1430 but LFO works with one more bit of a precision so we really need 4096 elements */
\r
1431 /* calculate fnumber -> increment counter table */
\r
1432 for(i = 0; i < 4096; i++)
\r
1434 /* freq table for octave 7 */
\r
1435 /* OPN phase increment counter = 20bit */
\r
1436 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
1439 /* LFO freq. table */
\r
1440 for(i = 0; i < 8; i++)
\r
1442 /* Amplitude modulation: 64 output levels (triangle waveform); 1 level lasts for one of "lfo_samples_per_step" samples */
\r
1443 /* Phase modulation: one entry from lfo_pm_output lasts for one of 4 * "lfo_samples_per_step" samples */
\r
1444 ym2612.OPN.lfo_freq[i] = (1.0 / lfo_samples_per_step[i]) * (1<<LFO_SH) * ym2612.OPN.ST.freqbase;
\r
1449 /* write a OPN register (0x30-0xff) */
\r
1450 static int OPNWriteReg(int r, int v)
\r
1456 UINT8 c = OPN_CHAN(r);
\r
1458 if (c == 3) return 0; /* 0xX3,0xX7,0xXB,0xXF */
\r
1460 if (r >= 0x100) c+=3;
\r
1462 CH = &ym2612.CH[c];
\r
1464 SLOT = &(CH->SLOT[OPN_SLOT(r)]);
\r
1466 switch( r & 0xf0 ) {
\r
1467 case 0x30: /* DET , MUL */
\r
1468 set_det_mul(CH,SLOT,v);
\r
1471 case 0x40: /* TL */
\r
1475 case 0x50: /* KS, AR */
\r
1476 set_ar_ksr(CH,SLOT,v);
\r
1479 case 0x60: /* bit7 = AM ENABLE, DR */
\r
1481 if(v&0x80) CH->AMmasks |= 1<<OPN_SLOT(r);
\r
1482 else CH->AMmasks &= ~(1<<OPN_SLOT(r));
\r
1485 case 0x70: /* SR */
\r
1489 case 0x80: /* SL, RR */
\r
1490 set_sl_rr(SLOT,v);
\r
1493 case 0x90: /* SSG-EG */
\r
1499 switch( OPN_SLOT(r) ){
\r
1500 case 0: /* 0xa0-0xa2 : FNUM1 */
\r
1502 UINT32 fn = (((UINT32)( (ym2612.OPN.ST.fn_h)&7))<<8) + v;
\r
1503 UINT8 blk = ym2612.OPN.ST.fn_h>>3;
\r
1504 /* keyscale code */
\r
1505 CH->kcode = (blk<<2) | opn_fktable[fn >> 7];
\r
1506 /* phase increment counter */
\r
1507 CH->fc = fn_table[fn*2]>>(7-blk);
\r
1509 /* store fnum in clear form for LFO PM calculations */
\r
1510 CH->block_fnum = (blk<<11) | fn;
\r
1512 CH->SLOT[SLOT1].Incr=-1;
\r
1515 case 1: /* 0xa4-0xa6 : FNUM2,BLK */
\r
1516 ym2612.OPN.ST.fn_h = v&0x3f;
\r
1519 case 2: /* 0xa8-0xaa : 3CH FNUM1 */
\r
1522 UINT32 fn = (((UINT32)(ym2612.OPN.SL3.fn_h&7))<<8) + v;
\r
1523 UINT8 blk = ym2612.OPN.SL3.fn_h>>3;
\r
1524 /* keyscale code */
\r
1525 ym2612.OPN.SL3.kcode[c]= (blk<<2) | opn_fktable[fn >> 7];
\r
1526 /* phase increment counter */
\r
1527 ym2612.OPN.SL3.fc[c] = fn_table[fn*2]>>(7-blk);
\r
1528 ym2612.OPN.SL3.block_fnum[c] = fn;
\r
1529 ym2612.CH[2].SLOT[SLOT1].Incr=-1;
\r
1532 case 3: /* 0xac-0xae : 3CH FNUM2,BLK */
\r
1534 ym2612.OPN.SL3.fn_h = v&0x3f;
\r
1544 switch( OPN_SLOT(r) ){
\r
1545 case 0: /* 0xb0-0xb2 : FB,ALGO */
\r
1547 int feedback = (v>>3)&7;
\r
1549 CH->FB = feedback ? feedback+6 : 0;
\r
1552 case 1: /* 0xb4-0xb6 : L , R , AMS , PMS (YM2612/YM2610B/YM2610/YM2608) */
\r
1554 int panshift = c<<1;
\r
1557 CH->pms = (v & 7) * 32; /* CH->pms = PM depth * 32 (index in lfo_pm_table) */
\r
1560 CH->ams = lfo_ams_depth_shift[(v>>4) & 3];
\r
1562 /* PAN : b7 = L, b6 = R */
\r
1563 ym2612.OPN.pan &= ~(3<<panshift);
\r
1564 ym2612.OPN.pan |= ((v & 0xc0) >> 6) << panshift; // ..LRLR
\r
1581 /*******************************************************************************/
\r
1582 /* YM2612 local section */
\r
1583 /*******************************************************************************/
\r
1585 int *ym2612_dacen;
\r
1586 INT32 *ym2612_dacout;
\r
1589 /* Generate samples for YM2612 */
\r
1590 int YM2612UpdateOne_(int *buffer, int length, int stereo, int is_buf_empty)
\r
1593 int active_chs = 0;
\r
1595 // if !is_buf_empty, it means it has valid samples to mix with, else it may contain trash
\r
1596 if (is_buf_empty) memset32(buffer, 0, length<<stereo);
\r
1598 /* refresh PG and EG */
\r
1599 refresh_fc_eg_chan( &ym2612.CH[0] );
\r
1600 refresh_fc_eg_chan( &ym2612.CH[1] );
\r
1601 if( (ym2612.OPN.ST.mode & 0xc0) )
\r
1604 if( ym2612.CH[2].SLOT[SLOT1].Incr==-1)
\r
1606 refresh_fc_eg_slot(&ym2612.CH[2].SLOT[SLOT1], ym2612.OPN.SL3.fc[1], ym2612.OPN.SL3.kcode[1] );
\r
1607 refresh_fc_eg_slot(&ym2612.CH[2].SLOT[SLOT2], ym2612.OPN.SL3.fc[2], ym2612.OPN.SL3.kcode[2] );
\r
1608 refresh_fc_eg_slot(&ym2612.CH[2].SLOT[SLOT3], ym2612.OPN.SL3.fc[0], ym2612.OPN.SL3.kcode[0] );
\r
1609 refresh_fc_eg_slot(&ym2612.CH[2].SLOT[SLOT4], ym2612.CH[2].fc , ym2612.CH[2].kcode );
\r
1611 } else refresh_fc_eg_chan( &ym2612.CH[2] );
\r
1612 refresh_fc_eg_chan( &ym2612.CH[3] );
\r
1613 refresh_fc_eg_chan( &ym2612.CH[4] );
\r
1614 refresh_fc_eg_chan( &ym2612.CH[5] );
\r
1616 pan = ym2612.OPN.pan;
\r
1617 if (stereo) stereo = 1;
\r
1619 /* mix to 32bit dest */
\r
1620 // flags: stereo, lastchan, disabled, ?, pan_r, pan_l
\r
1621 active_chs |= chan_render(buffer, length, &ym2612.CH[0], stereo|((pan&0x003)<<4)) << 0;
\r
1622 active_chs |= chan_render(buffer, length, &ym2612.CH[1], stereo|((pan&0x00c)<<2)) << 1;
\r
1623 active_chs |= chan_render(buffer, length, &ym2612.CH[2], stereo|((pan&0x030) )) << 2;
\r
1624 active_chs |= chan_render(buffer, length, &ym2612.CH[3], stereo|((pan&0x0c0)>>2)) << 3;
\r
1625 active_chs |= chan_render(buffer, length, &ym2612.CH[4], stereo|((pan&0x300)>>4)) << 4;
\r
1626 active_chs |= chan_render(buffer, length, &ym2612.CH[5], stereo|((pan&0xc00)>>6)|(ym2612.dacen<<2)|2) << 5;
\r
1628 return active_chs; // 1 if buffer updated
\r
1632 /* initialize YM2612 emulator */
\r
1633 void YM2612Init_(int clock, int rate)
\r
1636 ym2612_dacen = &ym2612.dacen;
\r
1637 ym2612_dacout = &ym2612.dacout;
\r
1639 /* clear everything but the regs */
\r
1640 memset(ym2612.CH, 0, sizeof(ym2612)-sizeof(ym2612.REGS)-4);
\r
1643 ym2612.OPN.ST.clock = clock;
\r
1644 ym2612.OPN.ST.rate = rate;
\r
1646 /* Extend handler */
\r
1647 YM2612ResetChip_();
\r
1652 void YM2612ResetChip_(void)
\r
1656 OPNSetPres( 6*24 );
\r
1657 set_timers( 0x30 ); /* mode 0 , timer reset */
\r
1659 ym2612.OPN.eg_timer = 0;
\r
1660 ym2612.OPN.eg_cnt = 0;
\r
1661 ym2612.OPN.ST.status = 0;
\r
1663 reset_channels( &ym2612.CH[0] , 6 );
\r
1664 for(i = 0xb6 ; i >= 0xb4 ; i-- )
\r
1666 OPNWriteReg(i ,0xc0);
\r
1667 OPNWriteReg(i|0x100,0xc0);
\r
1669 for(i = 0xb2 ; i >= 0x30 ; i-- )
\r
1671 OPNWriteReg(i ,0);
\r
1672 OPNWriteReg(i|0x100,0);
\r
1674 for(i = 0x26 ; i >= 0x20 ; i-- ) OPNWriteReg(i,0);
\r
1675 /* DAC mode clear */
\r
1680 /* YM2612 write */
\r
1683 /* returns 1 if sample affecting state changed */
\r
1684 int YM2612Write_(unsigned int a, unsigned int v)
\r
1688 v &= 0xff; /* adjust to 8 bit bus */
\r
1691 case 0: /* address port 0 */
\r
1692 ym2612.OPN.ST.address = v;
\r
1693 ym2612.addr_A1 = 0;
\r
1697 case 1: /* data port 0 */
\r
1698 if (ym2612.addr_A1 != 0) {
\r
1700 break; /* verified on real YM2608 */
\r
1703 addr = ym2612.OPN.ST.address;
\r
1704 ym2612.REGS[addr] = v;
\r
1706 switch( addr & 0xf0 )
\r
1708 case 0x20: /* 0x20-0x2f Mode */
\r
1711 case 0x22: /* LFO FREQ (YM2608/YM2610/YM2610B/YM2612) */
\r
1712 if (v&0x08) /* LFO enabled ? */
\r
1714 ym2612.OPN.lfo_inc = ym2612.OPN.lfo_freq[v&7];
\r
1718 ym2612.OPN.lfo_inc = 0;
\r
1721 case 0x24: { // timer A High 8
\r
1722 int TAnew = (ym2612.OPN.ST.TA & 0x03)|(((int)v)<<2);
\r
1723 if(ym2612.OPN.ST.TA != TAnew) {
\r
1724 // we should reset ticker only if new value is written. Outrun requires this.
\r
1725 ym2612.OPN.ST.TA = TAnew;
\r
1726 ym2612.OPN.ST.TAC = (1024-TAnew)*18;
\r
1727 ym2612.OPN.ST.TAT = 0;
\r
1732 case 0x25: { // timer A Low 2
\r
1733 int TAnew = (ym2612.OPN.ST.TA & 0x3fc)|(v&3);
\r
1734 if(ym2612.OPN.ST.TA != TAnew) {
\r
1735 ym2612.OPN.ST.TA = TAnew;
\r
1736 ym2612.OPN.ST.TAC = (1024-TAnew)*18;
\r
1737 ym2612.OPN.ST.TAT = 0;
\r
1742 case 0x26: // timer B
\r
1743 if(ym2612.OPN.ST.TB != v) {
\r
1744 ym2612.OPN.ST.TB = v;
\r
1745 ym2612.OPN.ST.TBC = (256-v)<<4;
\r
1746 ym2612.OPN.ST.TBC *= 18;
\r
1747 ym2612.OPN.ST.TBT = 0;
\r
1751 case 0x27: /* mode, timer control */
\r
1755 case 0x28: /* key on / off */
\r
1761 if( c == 3 ) { ret=0; break; }
\r
1762 if( v&0x04 ) c+=3;
\r
1763 CH = &ym2612.CH[c];
\r
1764 if(v&0x10) FM_KEYON(CH,SLOT1); else FM_KEYOFF(CH,SLOT1);
\r
1765 if(v&0x20) FM_KEYON(CH,SLOT2); else FM_KEYOFF(CH,SLOT2);
\r
1766 if(v&0x40) FM_KEYON(CH,SLOT3); else FM_KEYOFF(CH,SLOT3);
\r
1767 if(v&0x80) FM_KEYON(CH,SLOT4); else FM_KEYOFF(CH,SLOT4);
\r
1770 case 0x2a: /* DAC data (YM2612) */
\r
1771 ym2612.dacout = ((int)v - 0x80) << 6; /* level unknown (notaz: 8 seems to be too much) */
\r
1774 case 0x2b: /* DAC Sel (YM2612) */
\r
1775 /* b7 = dac enable */
\r
1776 ym2612.dacen = v & 0x80;
\r
1783 default: /* 0x30-0xff OPN section */
\r
1784 /* write register */
\r
1785 ret = OPNWriteReg(addr,v);
\r
1789 case 2: /* address port 1 */
\r
1790 ym2612.OPN.ST.address = v;
\r
1791 ym2612.addr_A1 = 1;
\r
1795 case 3: /* data port 1 */
\r
1796 if (ym2612.addr_A1 != 1) {
\r
1798 break; /* verified on real YM2608 */
\r
1801 addr = ym2612.OPN.ST.address | 0x100;
\r
1802 ym2612.REGS[addr] = v;
\r
1804 ret = OPNWriteReg(addr, v);
\r
1809 extern int Scanline;
\r
1810 dprintf("ymw [%i]", Scanline);
\r
1816 UINT8 YM2612Read_(void)
\r
1818 return ym2612.OPN.ST.status;
\r
1822 int YM2612PicoTick_(int n)
\r
1827 if(ym2612.OPN.ST.mode & 0x01 && (ym2612.OPN.ST.TAT+=64*n) >= ym2612.OPN.ST.TAC) {
\r
1828 ym2612.OPN.ST.TAT -= ym2612.OPN.ST.TAC;
\r
1829 if(ym2612.OPN.ST.mode & 0x04) ym2612.OPN.ST.status |= 1;
\r
1830 // CSM mode total level latch and auto key on
\r
1831 if(ym2612.OPN.ST.mode & 0x80) {
\r
1832 CSMKeyControll( &(ym2612.CH[2]) ); // Vectorman2, etc.
\r
1838 if(ym2612.OPN.ST.mode & 0x02 && (ym2612.OPN.ST.TBT+=64*n) >= ym2612.OPN.ST.TBC) {
\r
1839 ym2612.OPN.ST.TBT -= ym2612.OPN.ST.TBC;
\r
1840 if(ym2612.OPN.ST.mode & 0x08) ym2612.OPN.ST.status |= 2;
\r
1847 void YM2612PicoStateLoad_(void)
\r
1849 #ifndef EXTERNAL_YM2612
\r
1850 int i, old_A1 = ym2612.addr_A1;
\r
1852 reset_channels( &ym2612.CH[0], 6 );
\r
1854 // feed all the registers and update internal state
\r
1855 for(i = 0; i < 0x100; i++) {
\r
1856 YM2612Write_(0, i);
\r
1857 YM2612Write_(1, ym2612.REGS[i]);
\r
1859 for(i = 0; i < 0x100; i++) {
\r
1860 YM2612Write_(2, i);
\r
1861 YM2612Write_(3, ym2612.REGS[i|0x100]);
\r
1864 ym2612.addr_A1 = old_A1;
\r
1866 reset_channels( &ym2612.CH[0], 6 );
\r
1871 void *YM2612GetRegs(void)
\r
1873 return ym2612.REGS;
\r