/src/pico/ym2612.cpp
C++ | 1795 lines | 1206 code | 273 blank | 316 comment | 160 complexity | 278e69c300a3d921330b9280a08eac93 MD5 | raw file
Large files files are truncated, but you can click here to view the full file
- /*
- ** This is a bunch of remains of original fm.c from MAME project. All stuff
- ** unrelated to ym2612 was removed, multiple chip support was removed,
- ** some parts of code were slightly rewritten and tied to the emulator.
- **
- ** SSG-EG was also removed, because it's rarely used, Sega2.doc even does not
- ** document it ("proprietary") and tells to write 0 to SSG-EG control register.
- */
-
- /*
- **
- ** File: fm.c -- software implementation of Yamaha FM sound generator
- **
- ** Copyright (C) 2001, 2002, 2003 Jarek Burczynski (bujar at mame dot net)
- ** Copyright (C) 1998 Tatsuyuki Satoh , MultiArcadeMachineEmulator development
- **
- ** Version 1.4 (final beta)
- **
- */
-
- /*
- ** History:
- **
- ** 03-08-2003 Jarek Burczynski:
- ** - fixed YM2608 initial values (after the reset)
- ** - fixed flag and irqmask handling (YM2608)
- ** - fixed BUFRDY flag handling (YM2608)
- **
- ** 14-06-2003 Jarek Burczynski:
- ** - implemented all of the YM2608 status register flags
- ** - implemented support for external memory read/write via YM2608
- ** - implemented support for deltat memory limit register in YM2608 emulation
- **
- ** 22-05-2003 Jarek Burczynski:
- ** - fixed LFO PM calculations (copy&paste bugfix)
- **
- ** 08-05-2003 Jarek Burczynski:
- ** - fixed SSG support
- **
- ** 22-04-2003 Jarek Burczynski:
- ** - implemented 100% correct LFO generator (verified on real YM2610 and YM2608)
- **
- ** 15-04-2003 Jarek Burczynski:
- ** - added support for YM2608's register 0x110 - status mask
- **
- ** 01-12-2002 Jarek Burczynski:
- ** - fixed register addressing in YM2608, YM2610, YM2610B chips. (verified on real YM2608)
- ** The addressing patch used for early Neo-Geo games can be removed now.
- **
- ** 26-11-2002 Jarek Burczynski, Nicola Salmoria:
- ** - recreated YM2608 ADPCM ROM using data from real YM2608's output which leads to:
- ** - added emulation of YM2608 drums.
- ** - output of YM2608 is two times lower now - same as YM2610 (verified on real YM2608)
- **
- ** 16-08-2002 Jarek Burczynski:
- ** - binary exact Envelope Generator (verified on real YM2203);
- ** identical to YM2151
- ** - corrected 'off by one' error in feedback calculations (when feedback is off)
- ** - corrected connection (algorithm) calculation (verified on real YM2203 and YM2610)
- **
- ** 18-12-2001 Jarek Burczynski:
- ** - added SSG-EG support (verified on real YM2203)
- **
- ** 12-08-2001 Jarek Burczynski:
- ** - corrected ym_sin_tab and ym_tl_tab data (verified on real chip)
- ** - corrected feedback calculations (verified on real chip)
- ** - corrected phase generator calculations (verified on real chip)
- ** - corrected envelope generator calculations (verified on real chip)
- ** - corrected FM volume level (YM2610 and YM2610B).
- ** - changed YMxxxUpdateOne() functions (YM2203, YM2608, YM2610, YM2610B, YM2612) :
- ** this was needed to calculate YM2610 FM channels output correctly.
- ** (Each FM channel is calculated as in other chips, but the output of the channel
- ** gets shifted right by one *before* sending to accumulator. That was impossible to do
- ** with previous implementation).
- **
- ** 23-07-2001 Jarek Burczynski, Nicola Salmoria:
- ** - corrected YM2610 ADPCM type A algorithm and tables (verified on real chip)
- **
- ** 11-06-2001 Jarek Burczynski:
- ** - corrected end of sample bug in ADPCMA_calc_cha().
- ** Real YM2610 checks for equality between current and end addresses (only 20 LSB bits).
- **
- ** 08-12-98 hiro-shi:
- ** rename ADPCMA -> ADPCMB, ADPCMB -> ADPCMA
- ** move ROM limit check.(CALC_CH? -> 2610Write1/2)
- ** test program (ADPCMB_TEST)
- ** move ADPCM A/B end check.
- ** ADPCMB repeat flag(no check)
- ** change ADPCM volume rate (8->16) (32->48).
- **
- ** 09-12-98 hiro-shi:
- ** change ADPCM volume. (8->16, 48->64)
- ** replace ym2610 ch0/3 (YM-2610B)
- ** change ADPCM_SHIFT (10->8) missing bank change 0x4000-0xffff.
- ** add ADPCM_SHIFT_MASK
- ** change ADPCMA_DECODE_MIN/MAX.
- */
-
-
-
-
- /************************************************************************/
- /* comment of hiro-shi(Hiromitsu Shioya) */
- /* YM2610(B) = OPN-B */
- /* YM2610 : PSG:3ch FM:4ch ADPCM(18.5KHz):6ch DeltaT ADPCM:1ch */
- /* YM2610B : PSG:3ch FM:6ch ADPCM(18.5KHz):6ch DeltaT ADPCM:1ch */
- /************************************************************************/
-
- //#include <stdio.h>
-
- #include <string.h>
- #include <math.h>
-
- #include "ym2612.h"
-
- #include <stdlib.h>
- // let it be 1 global to simplify things
- YM2612 ym2612;
-
- extern "C" void memset32(int *dest, int c, int count);
-
- #ifndef INLINE
- #define INLINE static __inline
- #endif
-
- #ifndef M_PI
- #define M_PI 3.14159265358979323846
- #endif
-
-
- /* globals */
-
- #define FREQ_SH 16 /* 16.16 fixed point (frequency calculations) */
- #define EG_SH 16 /* 16.16 fixed point (envelope generator timing) */
- #define LFO_SH 25 /* 7.25 fixed point (LFO calculations) */
- #define TIMER_SH 16 /* 16.16 fixed point (timers calculations) */
-
- #define ENV_BITS 10
- #define ENV_LEN (1<<ENV_BITS)
- #define ENV_STEP (128.0/ENV_LEN)
-
- #define MAX_ATT_INDEX (ENV_LEN-1) /* 1023 */
- #define MIN_ATT_INDEX (0) /* 0 */
-
- #define EG_ATT 4
- #define EG_DEC 3
- #define EG_SUS 2
- #define EG_REL 1
- #define EG_OFF 0
-
- #define SIN_BITS 10
- #define SIN_LEN (1<<SIN_BITS)
- #define SIN_MASK (SIN_LEN-1)
-
- #define TL_RES_LEN (256) /* 8 bits addressing (real chip) */
-
- #define EG_TIMER_OVERFLOW (3*(1<<EG_SH)) /* envelope generator timer overflows every 3 samples (on real chip) */
-
- #define MAXOUT (+32767)
- #define MINOUT (-32768)
-
- /* limitter */
- #define Limit(val, max,min) { \
- if ( val > max ) val = max; \
- else if ( val < min ) val = min; \
- }
-
-
- /* TL_TAB_LEN is calculated as:
- * 13 - sinus amplitude bits (Y axis)
- * 2 - sinus sign bit (Y axis)
- * TL_RES_LEN - sinus resolution (X axis)
- */
- //#define TL_TAB_LEN (13*2*TL_RES_LEN)
- #define TL_TAB_LEN (13*TL_RES_LEN*256/8) // 106496*2
- u16 ym_tl_tab[TL_TAB_LEN];
-
- /* ~3K wasted but oh well */
- u16 ym_tl_tab2[13*TL_RES_LEN];
-
- #define ENV_QUIET (2*13*TL_RES_LEN/8)
-
- /* sin waveform table in 'decibel' scale (use only period/4 values) */
- static u16 ym_sin_tab[256];
-
- /* sustain level table (3dB per step) */
- /* bit0, bit1, bit2, bit3, bit4, bit5, bit6 */
- /* 1, 2, 4, 8, 16, 32, 64 (value)*/
- /* 0.75, 1.5, 3, 6, 12, 24, 48 (dB)*/
-
- /* 0 - 15: 0, 3, 6, 9,12,15,18,21,24,27,30,33,36,39,42,93 (dB)*/
- #define SC(db) (u32) ( db * (4.0/ENV_STEP) )
- static const u32 sl_table[16]={
- SC( 0),SC( 1),SC( 2),SC(3 ),SC(4 ),SC(5 ),SC(6 ),SC( 7),
- SC( 8),SC( 9),SC(10),SC(11),SC(12),SC(13),SC(14),SC(31)
- };
- #undef SC
-
-
- #if 0
- #define RATE_STEPS (8)
- static const u8 eg_inc[19*RATE_STEPS]={
-
- /*cycle:0 1 2 3 4 5 6 7*/
-
- /* 0 */ 0,1, 0,1, 0,1, 0,1, /* rates 00..11 0 (increment by 0 or 1) */
- /* 1 */ 0,1, 0,1, 1,1, 0,1, /* rates 00..11 1 */
- /* 2 */ 0,1, 1,1, 0,1, 1,1, /* rates 00..11 2 */
- /* 3 */ 0,1, 1,1, 1,1, 1,1, /* rates 00..11 3 */
-
- /* 4 */ 1,1, 1,1, 1,1, 1,1, /* rate 12 0 (increment by 1) */
- /* 5 */ 1,1, 1,2, 1,1, 1,2, /* rate 12 1 */
- /* 6 */ 1,2, 1,2, 1,2, 1,2, /* rate 12 2 */
- /* 7 */ 1,2, 2,2, 1,2, 2,2, /* rate 12 3 */
-
- /* 8 */ 2,2, 2,2, 2,2, 2,2, /* rate 13 0 (increment by 2) */
- /* 9 */ 2,2, 2,4, 2,2, 2,4, /* rate 13 1 */
- /*10 */ 2,4, 2,4, 2,4, 2,4, /* rate 13 2 */
- /*11 */ 2,4, 4,4, 2,4, 4,4, /* rate 13 3 */
-
- /*12 */ 4,4, 4,4, 4,4, 4,4, /* rate 14 0 (increment by 4) */
- /*13 */ 4,4, 4,8, 4,4, 4,8, /* rate 14 1 */
- /*14 */ 4,8, 4,8, 4,8, 4,8, /* rate 14 2 */
- /*15 */ 4,8, 8,8, 4,8, 8,8, /* rate 14 3 */
-
- /*16 */ 8,8, 8,8, 8,8, 8,8, /* rates 15 0, 15 1, 15 2, 15 3 (increment by 8) */
- /*17 */ 16,16,16,16,16,16,16,16, /* rates 15 2, 15 3 for attack */
- /*18 */ 0,0, 0,0, 0,0, 0,0, /* infinity rates for attack and decay(s) */
- };
- #endif
-
-
- #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))
- static const u32 eg_inc_pack[19] =
- {
- /* 0 */ PACK(0,1,0,1,0,1,0,1), /* rates 00..11 0 (increment by 0 or 1) */
- /* 1 */ PACK(0,1,0,1,1,1,0,1), /* rates 00..11 1 */
- /* 2 */ PACK(0,1,1,1,0,1,1,1), /* rates 00..11 2 */
- /* 3 */ PACK(0,1,1,1,1,1,1,1), /* rates 00..11 3 */
-
- /* 4 */ PACK(1,1,1,1,1,1,1,1), /* rate 12 0 (increment by 1) */
- /* 5 */ PACK(1,1,1,2,1,1,1,2), /* rate 12 1 */
- /* 6 */ PACK(1,2,1,2,1,2,1,2), /* rate 12 2 */
- /* 7 */ PACK(1,2,2,2,1,2,2,2), /* rate 12 3 */
-
- /* 8 */ PACK(2,2,2,2,2,2,2,2), /* rate 13 0 (increment by 2) */
- /* 9 */ PACK(2,2,2,3,2,2,2,3), /* rate 13 1 */
- /*10 */ PACK(2,3,2,3,2,3,2,3), /* rate 13 2 */
- /*11 */ PACK(2,3,3,3,2,3,3,3), /* rate 13 3 */
-
- /*12 */ PACK(3,3,3,3,3,3,3,3), /* rate 14 0 (increment by 4) */
- /*13 */ PACK(3,3,3,4,3,3,3,4), /* rate 14 1 */
- /*14 */ PACK(3,4,3,4,3,4,3,4), /* rate 14 2 */
- /*15 */ PACK(3,4,4,4,3,4,4,4), /* rate 14 3 */
-
- /*16 */ PACK(4,4,4,4,4,4,4,4), /* rates 15 0, 15 1, 15 2, 15 3 (increment by 8) */
- /*17 */ PACK(5,5,5,5,5,5,5,5), /* rates 15 2, 15 3 for attack */
- /*18 */ PACK(0,0,0,0,0,0,0,0), /* infinity rates for attack and decay(s) */
- };
-
-
- //#define O(a) (a*RATE_STEPS)
- #define O(a) a
-
- /*note that there is no O(17) in this table - it's directly in the code */
- static const u8 eg_rate_select[32+64+32]={ /* Envelope Generator rates (32 + 64 rates + 32 RKS) */
- /* 32 infinite time rates */
- O(18),O(18),O(18),O(18),O(18),O(18),O(18),O(18),
- O(18),O(18),O(18),O(18),O(18),O(18),O(18),O(18),
- O(18),O(18),O(18),O(18),O(18),O(18),O(18),O(18),
- O(18),O(18),O(18),O(18),O(18),O(18),O(18),O(18),
-
- /* rates 00-11 */
- O( 0),O( 1),O( 2),O( 3),
- O( 0),O( 1),O( 2),O( 3),
- O( 0),O( 1),O( 2),O( 3),
- O( 0),O( 1),O( 2),O( 3),
- O( 0),O( 1),O( 2),O( 3),
- O( 0),O( 1),O( 2),O( 3),
- O( 0),O( 1),O( 2),O( 3),
- O( 0),O( 1),O( 2),O( 3),
- O( 0),O( 1),O( 2),O( 3),
- O( 0),O( 1),O( 2),O( 3),
- O( 0),O( 1),O( 2),O( 3),
- O( 0),O( 1),O( 2),O( 3),
-
- /* rate 12 */
- O( 4),O( 5),O( 6),O( 7),
-
- /* rate 13 */
- O( 8),O( 9),O(10),O(11),
-
- /* rate 14 */
- O(12),O(13),O(14),O(15),
-
- /* rate 15 */
- O(16),O(16),O(16),O(16),
-
- /* 32 dummy rates (same as 15 3) */
- O(16),O(16),O(16),O(16),O(16),O(16),O(16),O(16),
- O(16),O(16),O(16),O(16),O(16),O(16),O(16),O(16),
- O(16),O(16),O(16),O(16),O(16),O(16),O(16),O(16),
- O(16),O(16),O(16),O(16),O(16),O(16),O(16),O(16)
-
- };
- #undef O
-
- /*rate 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15*/
- /*shift 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 0, 0, 0, 0, 0 */
- /*mask 2047, 1023, 511, 255, 127, 63, 31, 15, 7, 3, 1, 0, 0, 0, 0, 0 */
-
- #define O(a) (a*1)
- static const u8 eg_rate_shift[32+64+32]={ /* Envelope Generator counter shifts (32 + 64 rates + 32 RKS) */
- /* 32 infinite time rates */
- O(0),O(0),O(0),O(0),O(0),O(0),O(0),O(0),
- O(0),O(0),O(0),O(0),O(0),O(0),O(0),O(0),
- O(0),O(0),O(0),O(0),O(0),O(0),O(0),O(0),
- O(0),O(0),O(0),O(0),O(0),O(0),O(0),O(0),
-
- /* rates 00-11 */
- O(11),O(11),O(11),O(11),
- O(10),O(10),O(10),O(10),
- O( 9),O( 9),O( 9),O( 9),
- O( 8),O( 8),O( 8),O( 8),
- O( 7),O( 7),O( 7),O( 7),
- O( 6),O( 6),O( 6),O( 6),
- O( 5),O( 5),O( 5),O( 5),
- O( 4),O( 4),O( 4),O( 4),
- O( 3),O( 3),O( 3),O( 3),
- O( 2),O( 2),O( 2),O( 2),
- O( 1),O( 1),O( 1),O( 1),
- O( 0),O( 0),O( 0),O( 0),
-
- /* rate 12 */
- O( 0),O( 0),O( 0),O( 0),
-
- /* rate 13 */
- O( 0),O( 0),O( 0),O( 0),
-
- /* rate 14 */
- O( 0),O( 0),O( 0),O( 0),
-
- /* rate 15 */
- O( 0),O( 0),O( 0),O( 0),
-
- /* 32 dummy rates (same as 15 3) */
- O( 0),O( 0),O( 0),O( 0),O( 0),O( 0),O( 0),O( 0),
- O( 0),O( 0),O( 0),O( 0),O( 0),O( 0),O( 0),O( 0),
- O( 0),O( 0),O( 0),O( 0),O( 0),O( 0),O( 0),O( 0),
- O( 0),O( 0),O( 0),O( 0),O( 0),O( 0),O( 0),O( 0)
-
- };
- #undef O
-
- static const u8 dt_tab[4 * 32]={
- /* this is YM2151 and YM2612 phase increment data (in 10.10 fixed point format)*/
- /* FD=0 */
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- /* FD=1 */
- 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 2, 2, 2, 2,
- 2, 3, 3, 3, 4, 4, 4, 5, 5, 6, 6, 7, 8, 8, 8, 8,
- /* FD=2 */
- 1, 1, 1, 1, 2, 2, 2, 2, 2, 3, 3, 3, 4, 4, 4, 5,
- 5, 6, 6, 7, 8, 8, 9,10,11,12,13,14,16,16,16,16,
- /* FD=3 */
- 2, 2, 2, 2, 2, 3, 3, 3, 4, 4, 4, 5, 5, 6, 6, 7,
- 8 , 8, 9,10,11,12,13,14,16,17,19,20,22,22,22,22
- };
-
-
- /* OPN key frequency number -> key code follow table */
- /* fnum higher 4bit -> keycode lower 2bit */
- static const u8 opn_fktable[16] = {0,0,0,0,0,0,0,1,2,3,3,3,3,3,3,3};
-
-
- /* 8 LFO speed parameters */
- /* each value represents number of samples that one LFO level will last for */
- static const u32 lfo_samples_per_step[8] = {108, 77, 71, 67, 62, 44, 8, 5};
-
-
-
- /*There are 4 different LFO AM depths available, they are:
- 0 dB, 1.4 dB, 5.9 dB, 11.8 dB
- Here is how it is generated (in EG steps):
-
- 11.8 dB = 0, 2, 4, 6, 8, 10,12,14,16...126,126,124,122,120,118,....4,2,0
- 5.9 dB = 0, 1, 2, 3, 4, 5, 6, 7, 8....63, 63, 62, 61, 60, 59,.....2,1,0
- 1.4 dB = 0, 0, 0, 0, 1, 1, 1, 1, 2,...15, 15, 15, 15, 14, 14,.....0,0,0
-
- (1.4 dB is loosing precision as you can see)
-
- It's implemented as generator from 0..126 with step 2 then a shift
- right N times, where N is:
- 8 for 0 dB
- 3 for 1.4 dB
- 1 for 5.9 dB
- 0 for 11.8 dB
- */
- static const u8 lfo_ams_depth_shift[4] = {8, 3, 1, 0};
-
-
-
- /*There are 8 different LFO PM depths available, they are:
- 0, 3.4, 6.7, 10, 14, 20, 40, 80 (cents)
-
- Modulation level at each depth depends on F-NUMBER bits: 4,5,6,7,8,9,10
- (bits 8,9,10 = FNUM MSB from OCT/FNUM register)
-
- Here we store only first quarter (positive one) of full waveform.
- Full table (lfo_pm_table) containing all 128 waveforms is build
- at run (init) time.
-
- One value in table below represents 4 (four) basic LFO steps
- (1 PM step = 4 AM steps).
-
- For example:
- at LFO SPEED=0 (which is 108 samples per basic LFO step)
- one value from "lfo_pm_output" table lasts for 432 consecutive
- samples (4*108=432) and one full LFO waveform cycle lasts for 13824
- samples (32*432=13824; 32 because we store only a quarter of whole
- waveform in the table below)
- */
- static const u8 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 */
- /* FNUM BIT 4: 000 0001xxxx */
- /* DEPTH 0 */ {0, 0, 0, 0, 0, 0, 0, 0},
- /* DEPTH 1 */ {0, 0, 0, 0, 0, 0, 0, 0},
- /* DEPTH 2 */ {0, 0, 0, 0, 0, 0, 0, 0},
- /* DEPTH 3 */ {0, 0, 0, 0, 0, 0, 0, 0},
- /* DEPTH 4 */ {0, 0, 0, 0, 0, 0, 0, 0},
- /* DEPTH 5 */ {0, 0, 0, 0, 0, 0, 0, 0},
- /* DEPTH 6 */ {0, 0, 0, 0, 0, 0, 0, 0},
- /* DEPTH 7 */ {0, 0, 0, 0, 1, 1, 1, 1},
-
- /* FNUM BIT 5: 000 0010xxxx */
- /* DEPTH 0 */ {0, 0, 0, 0, 0, 0, 0, 0},
- /* DEPTH 1 */ {0, 0, 0, 0, 0, 0, 0, 0},
- /* DEPTH 2 */ {0, 0, 0, 0, 0, 0, 0, 0},
- /* DEPTH 3 */ {0, 0, 0, 0, 0, 0, 0, 0},
- /* DEPTH 4 */ {0, 0, 0, 0, 0, 0, 0, 0},
- /* DEPTH 5 */ {0, 0, 0, 0, 0, 0, 0, 0},
- /* DEPTH 6 */ {0, 0, 0, 0, 1, 1, 1, 1},
- /* DEPTH 7 */ {0, 0, 1, 1, 2, 2, 2, 3},
-
- /* FNUM BIT 6: 000 0100xxxx */
- /* DEPTH 0 */ {0, 0, 0, 0, 0, 0, 0, 0},
- /* DEPTH 1 */ {0, 0, 0, 0, 0, 0, 0, 0},
- /* DEPTH 2 */ {0, 0, 0, 0, 0, 0, 0, 0},
- /* DEPTH 3 */ {0, 0, 0, 0, 0, 0, 0, 0},
- /* DEPTH 4 */ {0, 0, 0, 0, 0, 0, 0, 1},
- /* DEPTH 5 */ {0, 0, 0, 0, 1, 1, 1, 1},
- /* DEPTH 6 */ {0, 0, 1, 1, 2, 2, 2, 3},
- /* DEPTH 7 */ {0, 0, 2, 3, 4, 4, 5, 6},
-
- /* FNUM BIT 7: 000 1000xxxx */
- /* DEPTH 0 */ {0, 0, 0, 0, 0, 0, 0, 0},
- /* DEPTH 1 */ {0, 0, 0, 0, 0, 0, 0, 0},
- /* DEPTH 2 */ {0, 0, 0, 0, 0, 0, 1, 1},
- /* DEPTH 3 */ {0, 0, 0, 0, 1, 1, 1, 1},
- /* DEPTH 4 */ {0, 0, 0, 1, 1, 1, 1, 2},
- /* DEPTH 5 */ {0, 0, 1, 1, 2, 2, 2, 3},
- /* DEPTH 6 */ {0, 0, 2, 3, 4, 4, 5, 6},
- /* DEPTH 7 */ {0, 0, 4, 6, 8, 8, 0xa, 0xc},
-
- /* FNUM BIT 8: 001 0000xxxx */
- /* DEPTH 0 */ {0, 0, 0, 0, 0, 0, 0, 0},
- /* DEPTH 1 */ {0, 0, 0, 0, 1, 1, 1, 1},
- /* DEPTH 2 */ {0, 0, 0, 1, 1, 1, 2, 2},
- /* DEPTH 3 */ {0, 0, 1, 1, 2, 2, 3, 3},
- /* DEPTH 4 */ {0, 0, 1, 2, 2, 2, 3, 4},
- /* DEPTH 5 */ {0, 0, 2, 3, 4, 4, 5, 6},
- /* DEPTH 6 */ {0, 0, 4, 6, 8, 8, 0xa, 0xc},
- /* DEPTH 7 */ {0, 0, 8, 0xc,0x10,0x10,0x14,0x18},
-
- /* FNUM BIT 9: 010 0000xxxx */
- /* DEPTH 0 */ {0, 0, 0, 0, 0, 0, 0, 0},
- /* DEPTH 1 */ {0, 0, 0, 0, 2, 2, 2, 2},
- /* DEPTH 2 */ {0, 0, 0, 2, 2, 2, 4, 4},
- /* DEPTH 3 */ {0, 0, 2, 2, 4, 4, 6, 6},
- /* DEPTH 4 */ {0, 0, 2, 4, 4, 4, 6, 8},
- /* DEPTH 5 */ {0, 0, 4, 6, 8, 8, 0xa, 0xc},
- /* DEPTH 6 */ {0, 0, 8, 0xc,0x10,0x10,0x14,0x18},
- /* DEPTH 7 */ {0, 0,0x10,0x18,0x20,0x20,0x28,0x30},
-
- /* FNUM BIT10: 100 0000xxxx */
- /* DEPTH 0 */ {0, 0, 0, 0, 0, 0, 0, 0},
- /* DEPTH 1 */ {0, 0, 0, 0, 4, 4, 4, 4},
- /* DEPTH 2 */ {0, 0, 0, 4, 4, 4, 8, 8},
- /* DEPTH 3 */ {0, 0, 4, 4, 8, 8, 0xc, 0xc},
- /* DEPTH 4 */ {0, 0, 4, 8, 8, 8, 0xc,0x10},
- /* DEPTH 5 */ {0, 0, 8, 0xc,0x10,0x10,0x14,0x18},
- /* DEPTH 6 */ {0, 0,0x10,0x18,0x20,0x20,0x28,0x30},
- /* DEPTH 7 */ {0, 0,0x20,0x30,0x40,0x40,0x50,0x60},
-
- };
-
- /* all 128 LFO PM waveforms */
- static s32 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 */
-
- /* there are 2048 FNUMs that can be generated using FNUM/BLK registers
- but LFO works with one more bit of a precision so we really need 4096 elements */
- static u32 fn_table[4096]; /* fnumber->increment counter */
-
- static int g_lfo_ampm = 0;
-
- /* register number to channel number , slot offset */
- #define OPN_CHAN(N) (N&3)
- #define OPN_SLOT(N) ((N>>2)&3)
-
- /* slot number */
- #define SLOT1 0
- #define SLOT2 2
- #define SLOT3 1
- #define SLOT4 3
-
-
- /* OPN Mode Register Write */
- INLINE void set_timers( int v )
- {
- /* b7 = CSM MODE */
- /* b6 = 3 slot mode */
- /* b5 = reset b */
- /* b4 = reset a */
- /* b3 = timer enable b */
- /* b2 = timer enable a */
- /* b1 = load b */
- /* b0 = load a */
- ym2612.OPN.ST.mode = v;
-
- /* reset Timer b flag */
- if( v & 0x20 )
- ym2612.OPN.ST.status &= ~2;
-
- /* reset Timer a flag */
- if( v & 0x10 )
- ym2612.OPN.ST.status &= ~1;
- }
-
-
- INLINE void FM_KEYON(int c , int s )
- {
- FM_SLOT *fmSlot = &ym2612.CH[c].fmSlot[s];
- if( !fmSlot->key )
- {
- fmSlot->key = 1;
- fmSlot->phase = 0; /* restart Phase Generator */
- fmSlot->state = EG_ATT; /* phase -> Attack */
- ym2612.slot_mask |= (1<<s) << (c*4);
- }
- }
-
- INLINE void FM_KEYOFF(int c , int s )
- {
- FM_SLOT *fmSlot = &ym2612.CH[c].fmSlot[s];
- if( fmSlot->key )
- {
- fmSlot->key = 0;
- if (fmSlot->state>EG_REL)
- fmSlot->state = EG_REL;/* phase -> Release */
- }
- }
-
-
- /* set detune & multiple */
- INLINE void set_det_mul(FM_CH *CH, FM_SLOT *fmSlot, int v)
- {
- fmSlot->mul = (v&0x0f)? (v&0x0f)*2 : 1;
- fmSlot->DT = ym2612.OPN.ST.dt_tab[(v>>4)&7];
- CH->fmSlot[SLOT1].Incr=-1;
- }
-
- /* set total level */
- INLINE void set_tl(FM_SLOT *fmSlot, int v)
- {
- fmSlot->tl = (v&0x7f)<<(ENV_BITS-7); /* 7bit TL */
- }
-
- /* set attack rate & key scale */
- INLINE void set_ar_ksr(FM_CH *CH, FM_SLOT *fmSlot, int v)
- {
- u8 old_KSR = fmSlot->KSR;
-
- fmSlot->ar = (v&0x1f) ? 32 + ((v&0x1f)<<1) : 0;
-
- fmSlot->KSR = 3-(v>>6);
- if (fmSlot->KSR != old_KSR)
- {
- CH->fmSlot[SLOT1].Incr=-1;
- }
- else
- {
- int eg_sh_ar, eg_sel_ar;
-
- /* refresh Attack rate */
- if ((fmSlot->ar + fmSlot->ksr) < 32+62)
- {
- eg_sh_ar = eg_rate_shift [fmSlot->ar + fmSlot->ksr ];
- eg_sel_ar = eg_rate_select[fmSlot->ar + fmSlot->ksr ];
- }
- else
- {
- eg_sh_ar = 0;
- eg_sel_ar = 17;
- }
-
- fmSlot->eg_pack_ar = eg_inc_pack[eg_sel_ar] | (eg_sh_ar<<24);
- }
- }
-
- /* set decay rate */
- INLINE void set_dr(FM_SLOT *fmSlot, int v)
- {
- int eg_sh_d1r, eg_sel_d1r;
-
- fmSlot->d1r = (v&0x1f) ? 32 + ((v&0x1f)<<1) : 0;
-
- eg_sh_d1r = eg_rate_shift [fmSlot->d1r + fmSlot->ksr];
- eg_sel_d1r= eg_rate_select[fmSlot->d1r + fmSlot->ksr];
-
- fmSlot->eg_pack_d1r = eg_inc_pack[eg_sel_d1r] | (eg_sh_d1r<<24);
- }
-
- /* set sustain rate */
- INLINE void set_sr(FM_SLOT *fmSlot, int v)
- {
- int eg_sh_d2r, eg_sel_d2r;
-
- fmSlot->d2r = (v&0x1f) ? 32 + ((v&0x1f)<<1) : 0;
-
- eg_sh_d2r = eg_rate_shift [fmSlot->d2r + fmSlot->ksr];
- eg_sel_d2r= eg_rate_select[fmSlot->d2r + fmSlot->ksr];
-
- fmSlot->eg_pack_d2r = eg_inc_pack[eg_sel_d2r] | (eg_sh_d2r<<24);
- }
-
- /* set release rate */
- INLINE void set_sl_rr(FM_SLOT *fmSlot, int v)
- {
- int eg_sh_rr, eg_sel_rr;
-
- fmSlot->sl = sl_table[ v>>4 ];
-
- fmSlot->rr = 34 + ((v&0x0f)<<2);
-
- eg_sh_rr = eg_rate_shift [fmSlot->rr + fmSlot->ksr];
- eg_sel_rr = eg_rate_select[fmSlot->rr + fmSlot->ksr];
-
- fmSlot->eg_pack_rr = eg_inc_pack[eg_sel_rr] | (eg_sh_rr<<24);
- }
-
-
-
- INLINE signed int op_calc(u32 phase, unsigned int env, signed int pm)
- {
- int ret, sin = (phase>>16) + (pm>>1);
- int neg = sin & 0x200;
- if (sin & 0x100) sin ^= 0xff;
- sin&=0xff;
- env&=~1;
-
- // this was already checked
- // if (env >= ENV_QUIET) // 384
- // return 0;
-
- ret = ym_tl_tab[sin | (env<<7)];
-
- return neg ? -ret : ret;
- }
-
- INLINE signed int op_calc1(u32 phase, unsigned int env, signed int pm)
- {
- int ret, sin = (phase+pm)>>16;
- int neg = sin & 0x200;
- if (sin & 0x100) sin ^= 0xff;
- sin&=0xff;
- env&=~1;
-
- // if (env >= ENV_QUIET) // 384
- // return 0;
-
- ret = ym_tl_tab[sin | (env<<7)];
-
- return neg ? -ret : ret;
- }
-
- #if !defined(_ASM_YM2612_C)
- /* advance LFO to next sample */
- INLINE int advance_lfo(int lfo_ampm, u32 lfo_cnt_old, u32 lfo_cnt)
- {
- u8 pos;
- u8 prev_pos;
-
- prev_pos = (lfo_cnt_old >> LFO_SH) & 127;
-
- pos = (lfo_cnt >> LFO_SH) & 127;
-
- /* update AM when LFO output changes */
-
- if (prev_pos != pos)
- {
- lfo_ampm &= 0xff;
- /* triangle */
- /* AM: 0 to 126 step +2, 126 to 0 step -2 */
- if (pos<64)
- lfo_ampm |= ((pos&63) * 2) << 8; /* 0 - 126 */
- else
- lfo_ampm |= (126 - (pos&63)*2) << 8;
- }
- else
- {
- return lfo_ampm;
- }
-
- /* PM works with 4 times slower clock */
- prev_pos >>= 2;
- pos >>= 2;
- /* update PM when LFO output changes */
- if (prev_pos != pos)
- {
- lfo_ampm &= ~0xff;
- lfo_ampm |= pos; /* 0 - 32 */
- }
- return lfo_ampm;
- }
-
- #define EG_INC_VAL() \
- ((1 << ((pack >> ((eg_cnt>>shift)&7)*3)&7)) >> 1)
-
- INLINE u32 update_eg_phase(FM_SLOT *fmSlot, u32 eg_cnt)
- {
- s32 volume = fmSlot->volume;
-
- switch(fmSlot->state)
- {
- case EG_ATT: /* attack phase */
- {
- u32 pack = fmSlot->eg_pack_ar;
- u32 shift = pack>>24;
- if ( !(eg_cnt & ((1<<shift)-1) ) )
- {
- volume += ( ~volume * EG_INC_VAL() ) >>4;
-
- if (volume <= MIN_ATT_INDEX)
- {
- volume = MIN_ATT_INDEX;
- fmSlot->state = EG_DEC;
- }
- }
- break;
- }
-
- case EG_DEC: /* decay phase */
- {
- u32 pack = fmSlot->eg_pack_d1r;
- u32 shift = pack>>24;
- if ( !(eg_cnt & ((1<<shift)-1) ) )
- {
- volume += EG_INC_VAL();
-
- if ( volume >= (s32) fmSlot->sl )
- fmSlot->state = EG_SUS;
- }
- break;
- }
-
- case EG_SUS: /* sustain phase */
- {
- u32 pack = fmSlot->eg_pack_d2r;
- u32 shift = pack>>24;
- if ( !(eg_cnt & ((1<<shift)-1) ) )
- {
- volume += EG_INC_VAL();
-
- if ( volume >= MAX_ATT_INDEX )
- {
- volume = MAX_ATT_INDEX;
- /* do not change SLOT->state (verified on real chip) */
- }
- }
- break;
- }
-
- case EG_REL: /* release phase */
- {
- u32 pack = fmSlot->eg_pack_rr;
- u32 shift = pack>>24;
- if ( !(eg_cnt & ((1<<shift)-1) ) )
- {
- volume += EG_INC_VAL();
-
- if ( volume >= MAX_ATT_INDEX )
- {
- volume = MAX_ATT_INDEX;
- fmSlot->state = EG_OFF;
- }
- }
- break;
- }
- }
-
- fmSlot->volume = volume;
- return fmSlot->tl + ((u32)volume); /* tl is 7bit<<3, volume 0-1023 (0-2039 total) */
- }
- #endif
-
-
- typedef struct
- {
- u16 vol_out1; /* 00: current output from EG circuit (without AM from LFO) */
- u16 vol_out2;
- u16 vol_out3;
- u16 vol_out4;
- u32 pad[2];
- u32 phase1; /* 10 */
- u32 phase2;
- u32 phase3;
- u32 phase4;
- u32 incr1; /* 20: phase step */
- u32 incr2;
- u32 incr3;
- u32 incr4;
- u32 lfo_cnt; /* 30 */
- u32 lfo_inc;
- s32 mem; /* one sample delay memory */
- u32 eg_cnt; /* envelope generator counter */
- FM_CH *CH; /* 40: envelope generator counter */
- u32 eg_timer;
- u32 eg_timer_add;
- u32 pack; // 4c: stereo, lastchan, disabled, lfo_enabled | pan_r, pan_l, ams[2] | AMmasks[4] | FB[4] | lfo_ampm[16]
- u32 algo; /* 50: algo[3], was_update */
- s32 op1_out;
- #ifdef _MIPS_ARCH_ALLEGREX
- u32 pad1[3+8];
- #endif
- } chan_rend_context;
-
-
- #if !defined(_ASM_YM2612_C)
- static void chan_render_loop(chan_rend_context *ct, int *buffer, int length)
- {
- int scounter; /* sample counter */
-
- /* sample generating loop */
- for (scounter = 0; scounter < length; scounter++)
- {
- int smp = 0; /* produced sample */
- unsigned int eg_out, eg_out2, eg_out4;
-
- if (ct->pack & 8) { /* LFO enabled ? (test Earthworm Jim in between demo 1 and 2) */
- ct->pack = (ct->pack&0xffff) | (advance_lfo(ct->pack >> 16, ct->lfo_cnt, ct->lfo_cnt + ct->lfo_inc) << 16);
- ct->lfo_cnt += ct->lfo_inc;
- }
-
- ct->eg_timer += ct->eg_timer_add;
- while (ct->eg_timer >= EG_TIMER_OVERFLOW)
- {
- ct->eg_timer -= EG_TIMER_OVERFLOW;
- ct->eg_cnt++;
-
- if (ct->CH->fmSlot[SLOT1].state != EG_OFF) ct->vol_out1 = update_eg_phase(&ct->CH->fmSlot[SLOT1], ct->eg_cnt);
- if (ct->CH->fmSlot[SLOT2].state != EG_OFF) ct->vol_out2 = update_eg_phase(&ct->CH->fmSlot[SLOT2], ct->eg_cnt);
- if (ct->CH->fmSlot[SLOT3].state != EG_OFF) ct->vol_out3 = update_eg_phase(&ct->CH->fmSlot[SLOT3], ct->eg_cnt);
- if (ct->CH->fmSlot[SLOT4].state != EG_OFF) ct->vol_out4 = update_eg_phase(&ct->CH->fmSlot[SLOT4], ct->eg_cnt);
- }
-
- if (ct->pack & 4) continue; /* output disabled */
-
- /* calculate channel sample */
- eg_out = ct->vol_out1;
- if ( (ct->pack & 8) && (ct->pack&(1<<(SLOT1+8))) ) eg_out += ct->pack >> (((ct->pack&0xc0)>>6)+24);
-
- if( eg_out < ENV_QUIET ) /* SLOT 1 */
- {
- int out = 0;
-
- if (ct->pack&0xf000) out = ((ct->op1_out>>16) + (ct->op1_out<<16>>16)) << ((ct->pack&0xf000)>>12); /* op1_out0 + op1_out1 */
- ct->op1_out <<= 16;
- ct->op1_out |= (unsigned short)op_calc1(ct->phase1, eg_out, out);
- } else {
- ct->op1_out <<= 16; /* op1_out0 = op1_out1; op1_out1 = 0; */
- }
-
- eg_out = ct->vol_out3; // volume_calc(&CH->SLOT[SLOT3]);
- eg_out2 = ct->vol_out2; // volume_calc(&CH->SLOT[SLOT2]);
- eg_out4 = ct->vol_out4; // volume_calc(&CH->SLOT[SLOT4]);
-
- if (ct->pack & 8) {
- unsigned int add = ct->pack >> (((ct->pack&0xc0)>>6)+24);
- if (ct->pack & (1<<(SLOT3+8))) eg_out += add;
- if (ct->pack & (1<<(SLOT2+8))) eg_out2 += add;
- if (ct->pack & (1<<(SLOT4+8))) eg_out4 += add;
- }
-
- switch( ct->CH->ALGO )
- {
- case 0:
- {
- /* M1---C1---MEM---M2---C2---OUT */
- int m2,c1,c2=0; /* Phase Modulation input for operators 2,3,4 */
- m2 = ct->mem;
- c1 = ct->op1_out>>16;
- if( eg_out < ENV_QUIET ) { /* SLOT 3 */
- c2 = op_calc(ct->phase3, eg_out, m2);
- }
- if( eg_out2 < ENV_QUIET ) { /* SLOT 2 */
- ct->mem = op_calc(ct->phase2, eg_out2, c1);
- }
- else ct->mem = 0;
- if( eg_out4 < ENV_QUIET ) { /* SLOT 4 */
- smp = op_calc(ct->phase4, eg_out4, c2);
- }
- break;
- }
- case 1:
- {
- /* M1------+-MEM---M2---C2---OUT */
- /* C1-+ */
- int m2,c2=0;
- m2 = ct->mem;
- ct->mem = ct->op1_out>>16;
- if( eg_out < ENV_QUIET ) { /* SLOT 3 */
- c2 = op_calc(ct->phase3, eg_out, m2);
- }
- if( eg_out2 < ENV_QUIET ) { /* SLOT 2 */
- ct->mem+= op_calc(ct->phase2, eg_out2, 0);
- }
- if( eg_out4 < ENV_QUIET ) { /* SLOT 4 */
- smp = op_calc(ct->phase4, eg_out4, c2);
- }
- break;
- }
- case 2:
- {
- /* M1-----------------+-C2---OUT */
- /* C1---MEM---M2-+ */
- int m2,c2;
- m2 = ct->mem;
- c2 = ct->op1_out>>16;
- if( eg_out < ENV_QUIET ) { /* SLOT 3 */
- c2 += op_calc(ct->phase3, eg_out, m2);
- }
- if( eg_out2 < ENV_QUIET ) { /* SLOT 2 */
- ct->mem = op_calc(ct->phase2, eg_out2, 0);
- }
- else ct->mem = 0;
- if( eg_out4 < ENV_QUIET ) { /* SLOT 4 */
- smp = op_calc(ct->phase4, eg_out4, c2);
- }
- break;
- }
- case 3:
- {
- /* M1---C1---MEM------+-C2---OUT */
- /* M2-+ */
- int c1,c2;
- c2 = ct->mem;
- c1 = ct->op1_out>>16;
- if( eg_out < ENV_QUIET ) { /* SLOT 3 */
- c2 += op_calc(ct->phase3, eg_out, 0);
- }
- if( eg_out2 < ENV_QUIET ) { /* SLOT 2 */
- ct->mem = op_calc(ct->phase2, eg_out2, c1);
- }
- else ct->mem = 0;
- if( eg_out4 < ENV_QUIET ) { /* SLOT 4 */
- smp = op_calc(ct->phase4, eg_out4, c2);
- }
- break;
- }
- case 4:
- {
- /* M1---C1-+-OUT */
- /* M2---C2-+ */
- /* MEM: not used */
- int c1,c2=0;
- c1 = ct->op1_out>>16;
- if( eg_out < ENV_QUIET ) { /* SLOT 3 */
- c2 = op_calc(ct->phase3, eg_out, 0);
- }
- if( eg_out2 < ENV_QUIET ) { /* SLOT 2 */
- smp = op_calc(ct->phase2, eg_out2, c1);
- }
- if( eg_out4 < ENV_QUIET ) { /* SLOT 4 */
- smp+= op_calc(ct->phase4, eg_out4, c2);
- }
- break;
- }
- case 5:
- {
- /* +----C1----+ */
- /* M1-+-MEM---M2-+-OUT */
- /* +----C2----+ */
- int m2,c1,c2;
- m2 = ct->mem;
- ct->mem = c1 = c2 = ct->op1_out>>16;
- if( eg_out < ENV_QUIET ) { /* SLOT 3 */
- smp = op_calc(ct->phase3, eg_out, m2);
- }
- if( eg_out2 < ENV_QUIET ) { /* SLOT 2 */
- smp+= op_calc(ct->phase2, eg_out2, c1);
- }
- if( eg_out4 < ENV_QUIET ) { /* SLOT 4 */
- smp+= op_calc(ct->phase4, eg_out4, c2);
- }
- break;
- }
- case 6:
- {
- /* M1---C1-+ */
- /* M2-+-OUT */
- /* C2-+ */
- /* MEM: not used */
- int c1;
- c1 = ct->op1_out>>16;
- if( eg_out < ENV_QUIET ) { /* SLOT 3 */
- smp = op_calc(ct->phase3, eg_out, 0);
- }
- if( eg_out2 < ENV_QUIET ) { /* SLOT 2 */
- smp+= op_calc(ct->phase2, eg_out2, c1);
- }
- if( eg_out4 < ENV_QUIET ) { /* SLOT 4 */
- smp+= op_calc(ct->phase4, eg_out4, 0);
- }
- break;
- }
- case 7:
- {
- /* M1-+ */
- /* C1-+-OUT */
- /* M2-+ */
- /* C2-+ */
- /* MEM: not used*/
- smp = ct->op1_out>>16;
- if( eg_out < ENV_QUIET ) { /* SLOT 3 */
- smp += op_calc(ct->phase3, eg_out, 0);
- }
- if( eg_out2 < ENV_QUIET ) { /* SLOT 2 */
- smp += op_calc(ct->phase2, eg_out2, 0);
- }
- if( eg_out4 < ENV_QUIET ) { /* SLOT 4 */
- smp += op_calc(ct->phase4, eg_out4, 0);
- }
- break;
- }
- }
- /* done calculating channel sample */
-
- /* mix sample to output buffer */
- if (smp) {
- if (ct->pack & 1) { /* stereo */
- if (ct->pack & 0x20) /* L */ /* TODO: check correctness */
- buffer[scounter*2] += smp;
- if (ct->pack & 0x10) /* R */
- buffer[scounter*2+1] += smp;
- } else {
- buffer[scounter] += smp;
- }
- ct->algo = 8; // algo is only used in asm, here only bit3 is used
- }
-
- /* update phase counters AFTER output calculations */
- ct->phase1 += ct->incr1;
- ct->phase2 += ct->incr2;
- ct->phase3 += ct->incr3;
- ct->phase4 += ct->incr4;
- }
- }
- #else
- extern "C" void chan_render_loop(chan_rend_context *ct, int *buffer, unsigned short length);
- #endif
-
- static chan_rend_context __attribute__((aligned(64))) crct;
-
- static int chan_render(int *buffer, int length, int c, u32 flags) // flags: stereo, ?, disabled, ?, pan_r, pan_l
- {
- crct.CH = &ym2612.CH[c];
- crct.mem = crct.CH->mem_value; /* one sample delay memory */
- crct.lfo_cnt = ym2612.OPN.lfo_cnt;
- crct.lfo_inc = ym2612.OPN.lfo_inc;
-
- flags &= 0x35;
-
- if (crct.lfo_inc) {
- flags |= 8;
- flags |= g_lfo_ampm << 16;
- flags |= crct.CH->AMmasks << 8;
- if (crct.CH->ams == 8) // no ams
- flags &= ~0xf00;
- else flags |= (crct.CH->ams&3)<<6;
- }
- flags |= (crct.CH->FB&0xf)<<12; /* feedback shift */
- crct.pack = flags;
-
- crct.eg_cnt = ym2612.OPN.eg_cnt; /* envelope generator counter */
- crct.eg_timer = ym2612.OPN.eg_timer;
- crct.eg_timer_add = ym2612.OPN.eg_timer_add;
-
- /* precalculate phase modulation incr */
- crct.phase1 = crct.CH->fmSlot[SLOT1].phase;
- crct.phase2 = crct.CH->fmSlot[SLOT2].phase;
- crct.phase3 = crct.CH->fmSlot[SLOT3].phase;
- crct.phase4 = crct.CH->fmSlot[SLOT4].phase;
-
- /* current output from EG circuit (without AM from LFO) */
- crct.vol_out1 = crct.CH->fmSlot[SLOT1].tl + ((u32)crct.CH->fmSlot[SLOT1].volume);
- crct.vol_out2 = crct.CH->fmSlot[SLOT2].tl + ((u32)crct.CH->fmSlot[SLOT2].volume);
- crct.vol_out3 = crct.CH->fmSlot[SLOT3].tl + ((u32)crct.CH->fmSlot[SLOT3].volume);
- crct.vol_out4 = crct.CH->fmSlot[SLOT4].tl + ((u32)crct.CH->fmSlot[SLOT4].volume);
-
- crct.op1_out = crct.CH->op1_out;
- crct.algo = crct.CH->ALGO & 7;
-
- if(crct.CH->pms)
- {
- /* add support for 3 slot mode */
- u32 block_fnum = crct.CH->block_fnum;
-
- u32 fnum_lfo = ((block_fnum & 0x7f0) >> 4) * 32 * 8;
- s32 lfo_fn_table_index_offset = lfo_pm_table[ fnum_lfo + crct.CH->pms + ((crct.pack>>16)&0xff) ];
-
- if (lfo_fn_table_index_offset) /* LFO phase modulation active */
- {
- u8 blk;
- u32 fn;
- int kc,fc;
-
- block_fnum = block_fnum*2 + lfo_fn_table_index_offset;
-
- blk = (block_fnum&0x7000) >> 12;
- fn = block_fnum & 0xfff;
-
- /* keyscale code */
- kc = (blk<<2) | opn_fktable[fn >> 8];
- /* phase increment counter */
- fc = fn_table[fn]>>(7-blk);
-
- crct.incr1 = ((fc+crct.CH->fmSlot[SLOT1].DT[kc])*crct.CH->fmSlot[SLOT1].mul) >> 1;
- crct.incr2 = ((fc+crct.CH->fmSlot[SLOT2].DT[kc])*crct.CH->fmSlot[SLOT2].mul) >> 1;
- crct.incr3 = ((fc+crct.CH->fmSlot[SLOT3].DT[kc])*crct.CH->fmSlot[SLOT3].mul) >> 1;
- crct.incr4 = ((fc+crct.CH->fmSlot[SLOT4].DT[kc])*crct.CH->fmSlot[SLOT4].mul) >> 1;
- }
- else /* LFO phase modulation = zero */
- {
- crct.incr1 = crct.CH->fmSlot[SLOT1].Incr;
- crct.incr2 = crct.CH->fmSlot[SLOT2].Incr;
- crct.incr3 = crct.CH->fmSlot[SLOT3].Incr;
- crct.incr4 = crct.CH->fmSlot[SLOT4].Incr;
- }
- }
- else /* no LFO phase modulation */
- {
- crct.incr1 = crct.CH->fmSlot[SLOT1].Incr;
- crct.incr2 = crct.CH->fmSlot[SLOT2].Incr;
- crct.incr3 = crct.CH->fmSlot[SLOT3].Incr;
- crct.incr4 = crct.CH->fmSlot[SLOT4].Incr;
- }
-
- chan_render_loop(&crct, buffer, length);
-
- crct.CH->op1_out = crct.op1_out;
- crct.CH->mem_value = crct.mem;
- if (crct.CH->fmSlot[SLOT1].state | crct.CH->fmSlot[SLOT2].state | crct.CH->fmSlot[SLOT3].state | crct.CH->fmSlot[SLOT4].state)
- {
- crct.CH->fmSlot[SLOT1].phase = crct.phase1;
- crct.CH->fmSlot[SLOT2].phase = crct.phase2;
- crct.CH->fmSlot[SLOT3].phase = crct.phase3;
- crct.CH->fmSlot[SLOT4].phase = crct.phase4;
- }
- else
- ym2612.slot_mask &= ~(0xf << (c*4));
-
- // if this the last call, write back persistent stuff:
- if ((ym2612.slot_mask >> ((c+1)*4)) == 0)
- {
- ym2612.OPN.eg_cnt = crct.eg_cnt;
- ym2612.OPN.eg_timer = crct.eg_timer;
- g_lfo_ampm = crct.pack >> 16;
- ym2612.OPN.lfo_cnt = crct.lfo_cnt;
- }
-
- return (crct.algo & 8) >> 3; // had output
- }
-
- /* update phase increment and envelope generator */
- INLINE void refresh_fc_eg_slot(FM_SLOT *fmSlot, int fc, int kc)
- {
- int ksr;
-
- /* (frequency) phase increment counter */
- fmSlot->Incr = ((fc+fmSlot->DT[kc])*fmSlot->mul) >> 1;
-
- ksr = kc >> fmSlot->KSR;
- if( fmSlot->ksr != ksr )
- {
- int eg_sh, eg_sel;
- fmSlot->ksr = ksr;
-
- /* calculate envelope generator rates */
- if ((fmSlot->ar + fmSlot->ksr) < 32+62)
- {
- eg_sh = eg_rate_shift [fmSlot->ar + fmSlot->ksr ];
- eg_sel = eg_rate_select[fmSlot->ar + fmSlot->ksr ];
- }
- else
- {
- eg_sh = 0;
- eg_sel = 17;
- }
-
- fmSlot->eg_pack_ar = eg_inc_pack[eg_sel] | (eg_sh<<24);
-
- eg_sh = eg_rate_shift [fmSlot->d1r + fmSlot->ksr];
- eg_sel = eg_rate_select[fmSlot->d1r + fmSlot->ksr];
-
- fmSlot->eg_pack_d1r = eg_inc_pack[eg_sel] | (eg_sh<<24);
-
- eg_sh = eg_rate_shift [fmSlot->d2r + fmSlot->ksr];
- eg_sel = eg_rate_select[fmSlot->d2r + fmSlot->ksr];
-
- fmSlot->eg_pack_d2r = eg_inc_pack[eg_sel] | (eg_sh<<24);
-
- eg_sh = eg_rate_shift [fmSlot->rr + fmSlot->ksr];
- eg_sel = eg_rate_select[fmSlot->rr + fmSlot->ksr];
-
- fmSlot->eg_pack_rr = eg_inc_pack[eg_sel] | (eg_sh<<24);
- }
- }
-
- /* update phase increment counters */
- INLINE void refresh_fc_eg_chan(FM_CH *CH)
- {
- if( CH->fmSlot[SLOT1].Incr == (u32)-1){
- int fc = CH->fc;
- int kc = CH->kcode;
- refresh_fc_eg_slot(&CH->fmSlot[SLOT1] , fc , kc );
- refresh_fc_eg_slot(&CH->fmSlot[SLOT2] , fc , kc );
- refresh_fc_eg_slot(&CH->fmSlot[SLOT3] , fc , kc );
- refresh_fc_eg_slot(&CH->fmSlot[SLOT4] , fc , kc );
- }
- }
-
- /* initialize time tables */
- static void init_timetables(const u8 *dttable)
- {
- int i,d;
- qreal rate;
-
- /* DeTune table */
- for (d = 0;d <= 3;d++){
- for (i = 0;i <= 31;i++){
- rate = ((qreal)dttable[d*32 + i]) * SIN_LEN * ym2612.OPN.ST.freqbase * (1<<FREQ_SH) / ((qreal)(1<<20));
- ym2612.OPN.ST.dt_tab[d][i] = (s32) rate;
- ym2612.OPN.ST.dt_tab[d+4][i] = -ym2612.OPN.ST.dt_tab[d][i];
- }
- }
- }
-
-
- static void reset_channels(FM_CH *CH)
- {
- int c,s;
-
- ym2612.OPN.ST.mode = 0; /* normal mode */
- ym2612.OPN.ST.TA = 0;
- ym2612.OPN.ST.TAC = 0;
- ym2612.OPN.ST.TB = 0;
- ym2612.OPN.ST.TBC = 0;
-
- for( c = 0 ; c < 6 ; c++ )
- {
- CH[c].fc = 0;
- for(s = 0 ; s < 4 ; s++ )
- {
- CH[c].fmSlot[s].state= EG_OFF;
- CH[c].fmSlot[s].volume = MAX_ATT_INDEX;
- }
- }
- ym2612.slot_mask = 0;
- }
-
- /* initialize generic tables */
- static void init_tables(void)
- {
- signed int i,x,y,p;
- signed int n;
- qreal o,m;
-
- for (i=0; i < 256; i++)
- {
- /* non-standard sinus */
- m = sin( ((i*2)+1) * M_PI / SIN_LEN ); /* checked against the real chip */
-
- /* we never reach zero here due to ((i*2)+1) */
-
- if (m>0.0)
- o = 8*log(1.0/m)/log(2); /* convert to 'decibels' */
- else
- o = 8*log(-1.0/m)/log(2); /* convert to 'decibels' */
-
- o = o / (ENV_STEP/4);
-
- n = (int)(2.0*o);
- if (n&1) /* round to nearest */
- n = (n>>1)+1;
- else
- n = n>>1;
-
- ym_sin_tab[ i ] = n;
- //dprintf("FM.C: sin [%4i]= %4i", i, ym_sin_tab[i]);
- }
-
- //dprintf("FM.C: ENV_QUIET= %08x", ENV_QUIET );
-
-
- for (x=0; x < TL_RES_LEN; x++)
- {
- m = (1<<16) / pow(2, (x+1) * (ENV_STEP/4.0) / 8.0);
- m = floor(m);
-
- /* we never reach (1<<16) here due to the (x+1) */
- /* result fits within 16 bits at maximum */
-
- n = (int)m; /* 16 bits here */
- n >>= 4; /* 12 bits here */
- if (n&1) /* round to nearest */
- n = (n>>1)+1;
- else
- n = n>>1;
- /* 11 bits here (rounded) */
- n <<= 2; /* 13 bits here (as in real chip) */
- ym_tl_tab2[ x ] = n;
-
- for (i=1; i < 13; i++)
- {
- ym_tl_tab2[ x + i*TL_RES_LEN ] = n >> i;
- }
- }
-
- for (x=0; x < 256; x++)
- {
- int sin = ym_sin_tab[ x ];
-
- for (y=0; y < 2*13*TL_RES_LEN/8; y+=2)
- {
- p = (y<<2) + sin;
- if (p >= 13*TL_RES_LEN)
- ym_tl_tab[(y<<7) | x] = 0;
- else ym_tl_tab[(y<<7) | x] = ym_tl_tab2[p];
- }
- }
-
-
- /* build LFO PM modulation table */
- for(i = 0; i < 8; i++) /* 8 PM depths */
- {
- u8 fnum;
- for (fnum=0; fnum<128; fnum++) /* 7 bits meaningful of F-NUMBER */
- {
- u8 value;
- u8 step;
- u32 offset_depth = i;
- u32 offset_fnum_bit;
- u32 bit_tmp;
-
- for (step=0; step<8; step++)
- {
- value = 0;
- for (bit_tmp=0; bit_tmp<7; bit_tmp++) /* 7 bits */
- {
- if (fnum & (1<<bit_tmp)) /* only if bit "bit_tmp" is set */
- {
- offset_fnum_bit = bit_tmp * 8;
- value += lfo_pm_output[offset_fnum_bit + offset_depth][step];
- }
- }
- lfo_pm_table[(fnum*32*8) + (i*32) + step + 0] = value;
- lfo_pm_table[(fnum*32*8) + (i*32) +(step^7)+ 8] = value;
- lfo_pm_table[(fnum*32*8) + (i*32) + step +16] = -value;
- lfo_pm_table[(fnum*32*8) + (i*32) +(step^7)+24] = -value;
- }
- }
- }
- }
-
- /* prescaler set (and make time tables) */
- static void OPNSetPres(int pres)
- {
- int i;
-
- /* frequency base */
- ym2612.OPN.ST.freqbase = (ym2612.OPN.ST.rate) ? ((qreal)ym2612.OPN.ST.clock / ym2612.OPN.ST.rate) / pres : 0;
-
- ym2612.OPN.eg_timer_add = (1<<EG_SH) * ym2612.OPN.ST.freqbase;
-
-
- /* make time tables */
- init_timetables( dt_tab );
-
- /* there are 2048 FNUMs that can be generated using FNUM/BLK registers
- but LFO works with one more bit of a precision so we really need 4096 elements */
- /* calculate fnumber -> increment counter table */
- for(i = 0; i < 4096; i++)
- {
- /* freq table for octave 7 */
- /* OPN phase increment counter = 20bit */
- fn_table[i] = (u32)( (qreal)i * 32 * ym2612.OPN.ST.freqbase * (1<<(FREQ_SH-10)) ); /* -10 because chip works with 10.10 fixed point, while we use 16.16 */
- }
-
- /* LFO freq. table */
- for(i = 0; i < 8; i++)
- {
- /* Amplitude modulation: 64 output levels (triangle waveform); 1 level lasts for one of "lfo_samples_per_step" samples */
- /* Phase modulation: one entry from lfo_pm_output lasts for one of 4 * "lfo_samples_per_step" samples */
- ym2612.OPN.lfo_freq[i] = (1.0 / lfo_samples_per_step[i]) * (1<<LFO_SH) * ym2612.OPN.ST.freqbase;
- }
- }
-
-
- /* write a OPN register (0x30-0xff) */
- static int OPNWriteReg(int r, int v)
- {
- int ret = 1;
- FM_CH *CH;
- FM_SLOT *fmSlot;
-
- u8 c = OPN_CHAN(r);
-
- if (c == 3) return 0; /* 0xX3,0xX7,0xXB,0xXF */
-
- if (r >= 0x100) c+=3;
-
- CH = &ym2612.CH[c];
-
- fmSlot = &(CH->fmSlot[OPN_SLOT(r)]);
-
- switch( r & 0xf0 ) {
- case 0x30: /* DET , MUL */
- set_det_mul(CH,fmSlot,v);
- break;
-
- case 0x40: /* TL */
- set_tl(fmSlot,v);
- break;
-
- case 0x50: /* KS, AR */
- set_ar_ksr(CH,fmSlot,v);
- break;
-
- case 0x60: /* bit7 = AM ENABLE, DR */
- set_dr(fmSlot,v);
- if(v&0x80) CH->AMmasks |= 1<<OPN_SLOT(r);
- else CH->AMmasks &= ~(1<<OPN_SLOT(r));
- break;
-
- case 0x70: /* SR */
- set_sr(fmSlot,v);
- break;
-
- case 0x80: /* SL, RR */
- set_sl_rr(fmSlot,v);
- break;
-
- case 0x90: /* SSG-EG */
- // removed.
- ret = 0;
- break;
-
- case 0xa0:
- switch( OPN_SLOT(r) ){
- case 0: /* 0xa0-0xa2 : FNUM1 */
- {
- u32 fn = (((u32)( (ym2612.OPN.ST.fn_h)&7))<<8) + v;
- u8 blk = ym2612.OPN.ST.fn_h>>3;
- /* keyscale code */
- CH->kcode = (blk<<2) | opn_fktable[fn >> 7];
- /* phase increment counter */
- CH->fc = fn_table[fn*2]>>(7-blk);
-
- /* store fnum in clear form for LFO PM calculations */
- CH->block_fnum = (blk<<11) | fn;
-
- CH->fmSlot[SLOT1].Incr=-1;
- }
- break;
- case 1: /* 0xa4-0xa6 : FNUM2,BLK */
- ym2612.OPN.ST.fn_h = v&0x3f;
- ret = 0;
- break;
- case 2: /* 0xa8-0xaa : 3CH FNUM1 */
- if(r < 0x100)
- {
- u32 fn = (((u32)(ym2612.OPN.SL3.fn_h&7))<<8) + v;
- u8 blk = ym2612.OPN.SL3.fn_h>>3;
- /* keyscale code */
- ym2612.OPN.SL3.kcode[c]= (blk<<2) | opn_fktable[fn >> 7];
- /* phase increment counter */
- ym2612.OPN.SL3.fc[c] = fn_table[fn*2]>>(7-blk);
- ym2612.OPN.SL3.block_fnum[c] = fn;
- ym2612.CH[2].fmSlot[SLOT1].Incr=-1;
- }
- break;
- case 3: /* 0xac-0xae : 3CH FNUM2,BLK */
- if(r < 0x100)
- ym2612.OPN.SL3.fn_h = v&0x3f;
- ret = 0;
- break;
- default:
- ret = 0;
- break;
- }
- break;
-
- case 0xb0:
- switch( OPN_SLOT(r) ){
- case 0: /* 0xb0-0xb2 : FB,ALGO */
- {
- int feedback = (v>>3)&7;
- CH->ALGO = v&7;
- CH->FB = feedback ? feedback+6 : 0;
- }
- break;
- case 1: /* 0xb4-0xb6 : L , R , AMS , PMS (YM2612/YM2610B/YM2610/YM2608) */
- {
- int panshift = c<<1;
-
- /* b0-2 PMS */
- CH->pms = (v & 7) * 32; /* CH->pms = PM depth * 32 (index in lfo_pm_table) */
-
- /* b4-5 AMS */
- CH->ams = lfo_ams_depth_shift[(v>>4) & 3];
-
- /* PAN : b7 = L, b6 = R */
- ym2612.OPN.pan &= ~(3<<panshift);
- ym2612.OPN.pan |= ((v & 0xc0) >> 6) << panshift; // ..LRLR
- }
- break;
- default:
- ret = 0;
- break;
- }
- break;
- default:
- ret = 0;
- break;
- }
-
- return ret;
- }
-
-
- /*******************************************************************************/
- /* YM2612 local section */
- /*******************************************************************************/
-
- int *ym2612_dacen;
- s32 *ym2612_dacout;
- FM_ST *ym2612_st;
-
- /* Generate samples for YM2612 */
- void YM2612Update(int *buffer, int length)
- {
- /* refresh PG and EG */
- refresh_fc_eg_chan( &ym2612.CH[0] );
- refresh_fc_eg_chan( &ym2612.CH[1] );
- if( (ym2612.OPN.ST.mode & 0xc0) )
- {
- /* 3SLOT MODE */
- if( ym2612.CH[2].fmSlot[SLOT1].Incr == (u32)-1)
- {
- refresh_fc_eg_slot(&ym2612.CH[2].fmSlot[SLOT1], ym2612.OPN.SL3.fc[1], ym2612.OPN.SL3.kcode[1] );
- refresh_fc_eg_slot(&ym2612.CH[2].fmSlot[SLOT2], ym2612.OPN.SL3.fc[2], ym2612.OPN.SL3.kcode[2] );
- refresh_fc_eg_slot(&ym2612.CH[2].fmSlot[SLOT3], ym2612.OPN.SL3.fc[0], ym2612.OPN.SL3.kcode[0] );
- refresh_fc_eg_slot(&ym2612.CH[2].fmSlot[SLOT4], ym2612.CH[2].fc , ym2612.CH[2].kcode );
- }
- } else refresh_fc_eg_chan( &ym2612.CH[2] );
- refresh_fc_eg_chan( &ym2612.CH[3] );
- refresh_fc_eg_chan( &ym2612.CH[4] );
- refresh_fc_eg_chan( &ym2612.CH[5] );
-
- int pan = ym2612.OPN.pan;
-
- int stereo = 1; // TODO remove, first in assembly
- /* mix to 32bit dest */
- // flags: stereo, ?, disabled, ?, pan_r, pan_l
- if (ym2612.slot_mask & 0x00000f) chan_render(buffer, length, 0, stereo|((pan&0x003)<<4));
- if (ym2612.slot_mask & 0x0000f0) chan_render(buffer, length, 1, stereo|((pan&0x00c)<<2));
- if (ym2612.slot_mask & 0x000f00) chan_render(buffer, length, 2, stereo|((pan&0x030) ));
- if (ym2612.slot_mask & 0x00f000) chan_render(buffer, length, 3, stereo|((pan&0x0c0)>>2));
- if (ym2612.slot_mask & 0x0f0000) chan_render(buffer, length, 4, stereo|((pan&0x300)>>4));
- if (ym2612.slot_mask & 0xf00000) chan_render(buffer, length, 5, stereo|((pan&0xc00)>>6)|(ym2612.dacen<<2));
- }
-
-
- /* initialize YM2612 emulator */
- void YM2612Init(int clock, int rate)
- {
- // notaz
- ym2612_dacen = &ym2612.dacen;
- ym2612_dacout = &ym2612.dacout;
- ym2612_st = &ym2612.OPN.ST;
-
- memset(&ym2612, 0, sizeof(ym2612));
- init_tables();
-
- ym2612.OPN.ST.clock = clock;
- ym2612.OPN.ST.rate = rate;
-
- /* Extend handler */
- YM2612ResetChip();
- }
-
-
- /* reset */
- void YM2612ResetChip()
- {
- int i;
-
- memset(ym2612.REGS, 0, sizeof(ym2612.REGS));
-
- OPNSetPres( 6*24 );
- set_timers( 0x30 ); /* mode 0 , timer reset */
- ym2612.REGS[0x27] = 0x30;
-
- ym2612.OPN.eg_timer = 0;
- ym2612.OPN.eg_cnt = 0;
- ym2612.OPN.ST.status = 0;
-
- reset_channels( &ym2612.CH[0] );
- for(i = 0xb6 ; i >= 0xb4 ; i-- )
- {
- OPNWriteReg(i ,0xc0);
- OPNWriteReg(i|0x100,0xc0);
- ym2612.REGS[i ] = 0xc0;
- ym2612.REGS[i|0x100] = 0xc0;
- }
- for(i = 0xb2 ; i >= 0x30 ; i-- )
- {
- OPNWriteReg(i ,0);
- OPNWriteReg(i|0x100,0);
- }
- for(i = 0x26 ; i >= 0x20 ; i-- ) OPNWriteReg(i,0);
- /* DAC mode clear */
- ym2612.dacen = 0;
- ym2612.addr_A1 = 0;
- }
-
-
- /* YM2612 write */
- /* a = address */
- /* v = value */
- /* returns 1 if sample affecting state changed */
- int YM2612Write(unsigned int a, unsigned int v)
- {
- int addr, ret=1;
-
- v &= 0xff; /* adjust to 8 bit bus */
-
- switch( a&3){
- case 0: /* address port 0 */
- ym2612.OPN.ST.address = v;
- ym2612.addr_A1 = 0;
- ret=0;
- break;
-
- case 1: /* data port 0 */
- if (ym2612.addr_A1 != 0) {
- ret=0;
- break; /* verified on real YM2608 */
- }
-
- addr = ym2612.OPN.ST.address;
- ym2612.REGS[addr] = v;
-
- switch( addr & 0xf0 )
- {
- case 0x20: /* 0x20-0x2f Mode */
- switch( addr )
- {
- case 0x22: /* LFO FREQ (YM2608/YM2610/YM2610B/YM2612) */
- if (v&0x08) /* LFO enabled ? */
- {
- ym2612.OPN.lfo_inc = ym2612.OPN.lfo_freq[v&7];
- }
- else
- {
- ym2612.OPN.lfo_inc = 0;
- }
- break;
- case 0x24: { // timer A High 8
- int TAnew = (ym2612.OPN.ST.TA & 0x03)|(((int)v)<<2);
- if(ym2612.OPN.ST.TA != TAnew) {
- // we should reset ticker only if new value is written. Outrun requires this.
- ym2612.OPN.ST.TA = TAnew;
- ym2612.OPN.ST.TAC = (1024-TAnew)*18;
- ym2612.OPN.ST.TAT = 0;
- }
- }
- ret=0;
- break;
- case 0x25: { // timer A Low 2
- int TAnew = (ym2612.OPN.ST.TA & 0x3fc)|(v&3);
- if(ym2612.OPN.ST.TA != TAnew) {
- ym2612.OPN.ST.TA = TAnew;
- ym2612.OPN.ST.TAC = (1024-TAnew)*18;
- ym2612.OPN.ST.TAT = 0;
- }
- }
- ret=0;
- break;
- case 0x26: // timer B
- if(ym2612.OPN.ST.TB != v) {
- ym2612.OPN.ST.TB = v;
- ym2612.OPN.ST.TBC = (256-v)<<4;
- ym2612.OPN.ST.TBC *= 18;
- ym2612.OPN.ST.TBT = 0;
- }
- ret=0;
- break;
- case 0x27: /* mode, timer control */
- set_timers( v );
- ret=0;
- break;
- case 0x28: /* key on / off */
- {
- u8 c;
-
- c = v & 0x03;
- if( c == 3 ) { ret=0; break; }
- if( v&0x04 ) c+=3;
- if(v&0x10) FM_KEYON(c,SLOT1); else FM_KEYOFF(c,SLOT1);
- if(v&0x20) FM_KEYON(c,SLOT2); else FM_KEYOFF(c,SLOT2);
- if(v&0x40) FM_KEYON(c,SLOT3); else FM_KEYOFF(c,SLOT3);
- if(v&0x80) FM_KEYON(c,SLOT4); else FM_KEYOFF(c,SLOT4);
- break;
- }
- case 0x2a: /* DAC data (YM2612) */
- ym2612.dacout = ((int)v - 0x80) << 6; /* level unknown (notaz: 8 seems to be too much) */
- ret=0;
- break;
- case 0x2b: /* DAC Sel (YM2612) */
- /* b7 = dac enable */
- ym2612.dacen = v & 0x80;
- ret=0;
- break;
- defaul…
Large files files are truncated, but you can click here to view the full file