/*1**2** software implementation of Yamaha FM sound generator (YM2612/YM3438)3**4** Original code (MAME fm.c)5**6** Copyright (C) 2001, 2002, 2003 Jarek Burczynski (bujar at mame dot net)7** Copyright (C) 1998 Tatsuyuki Satoh , MultiArcadeMachineEmulator development8**9** Version 1.4 (final beta)10**11** Additional code & fixes by Eke-Eke for Genesis Plus GX12**13** Huge thanks to Nemesis, most of those fixes came from his tests on Sega Genesis hardware14** More informations at http://gendev.spritesmind.net/forum/viewtopic.php?t=38615**16** TODO:17** - better documentation18** - BUSY flag emulation19*/2021/*22** CHANGELOG:23**24** 01-09-2012 Eke-Eke (Genesis Plus GX):25** - removed input clock / output samplerate frequency ratio, chip now always run at (original) internal sample frequency26** - removed now uneeded extra bits of precision27**28** 2006~2012 Eke-Eke (Genesis Plus GX):29** - removed unused multichip support30** - added YM2612 Context external access functions31** - fixed LFO implementation:32** .added support for CH3 special mode: fixes various sound effects (birds in Warlock, bug sound in Aladdin...)33** .inverted LFO AM waveform: fixes Spider-Man & Venom : Separation Anxiety (intro), California Games (surfing event)34** .improved LFO timing accuracy: now updated AFTER sample output, like EG/PG updates, and without any precision loss anymore.35** - improved internal timers emulation36** - adjusted lowest EG rates increment values37** - fixed Attack Rate not being updated in some specific cases (Batman & Robin intro)38** - fixed EG behavior when Attack Rate is maximal39** - fixed EG behavior when SL=0 (Mega Turrican tracks 03,09...) or/and Key ON occurs at minimal attenuation40** - implemented EG output immediate changes on register writes41** - fixed YM2612 initial values (after the reset): fixes missing intro in B.O.B42** - implemented Detune overflow (Ariel, Comix Zone, Shaq Fu, Spiderman & many other games using GEMS sound engine)43** - implemented accurate CSM mode emulation44** - implemented accurate SSG-EG emulation (Asterix, Beavis&Butthead, Bubba'n Stix & many other games)45** - implemented accurate address/data ports behavior46** - added preliminar support for DAC precision47**48** 03-08-2003 Jarek Burczynski:49** - fixed YM2608 initial values (after the reset)50** - fixed flag and irqmask handling (YM2608)51** - fixed BUFRDY flag handling (YM2608)52**53** 14-06-2003 Jarek Burczynski:54** - implemented all of the YM2608 status register flags55** - implemented support for external memory read/write via YM260856** - implemented support for deltat memory limit register in YM2608 emulation57**58** 22-05-2003 Jarek Burczynski:59** - fixed LFO PM calculations (copy&paste bugfix)60**61** 08-05-2003 Jarek Burczynski:62** - fixed SSG support63**64** 22-04-2003 Jarek Burczynski:65** - implemented 100% correct LFO generator (verified on real YM2610 and YM2608)66**67** 15-04-2003 Jarek Burczynski:68** - added support for YM2608's register 0x110 - status mask69**70** 01-12-2002 Jarek Burczynski:71** - fixed register addressing in YM2608, YM2610, YM2610B chips. (verified on real YM2608)72** The addressing patch used for early Neo-Geo games can be removed now.73**74** 26-11-2002 Jarek Burczynski, Nicola Salmoria:75** - recreated YM2608 ADPCM ROM using data from real YM2608's output which leads to:76** - added emulation of YM2608 drums.77** - output of YM2608 is two times lower now - same as YM2610 (verified on real YM2608)78**79** 16-08-2002 Jarek Burczynski:80** - binary exact Envelope Generator (verified on real YM2203);81** identical to YM215182** - corrected 'off by one' error in feedback calculations (when feedback is off)83** - corrected connection (algorithm) calculation (verified on real YM2203 and YM2610)84**85** 18-12-2001 Jarek Burczynski:86** - added SSG-EG support (verified on real YM2203)87**88** 12-08-2001 Jarek Burczynski:89** - corrected sin_tab and tl_tab data (verified on real chip)90** - corrected feedback calculations (verified on real chip)91** - corrected phase generator calculations (verified on real chip)92** - corrected envelope generator calculations (verified on real chip)93** - corrected FM volume level (YM2610 and YM2610B).94** - changed YMxxxUpdateOne() functions (YM2203, YM2608, YM2610, YM2610B, YM2612) :95** this was needed to calculate YM2610 FM channels output correctly.96** (Each FM channel is calculated as in other chips, but the output of the channel97** gets shifted right by one *before* sending to accumulator. That was impossible to do98** with previous implementation).99**100** 23-07-2001 Jarek Burczynski, Nicola Salmoria:101** - corrected YM2610 ADPCM type A algorithm and tables (verified on real chip)102**103** 11-06-2001 Jarek Burczynski:104** - corrected end of sample bug in ADPCMA_calc_cha().105** Real YM2610 checks for equality between current and end addresses (only 20 LSB bits).106**107** 08-12-98 hiro-shi:108** rename ADPCMA -> ADPCMB, ADPCMB -> ADPCMA109** move ROM limit check.(CALC_CH? -> 2610Write1/2)110** test program (ADPCMB_TEST)111** move ADPCM A/B end check.112** ADPCMB repeat flag(no check)113** change ADPCM volume rate (8->16) (32->48).114**115** 09-12-98 hiro-shi:116** change ADPCM volume. (8->16, 48->64)117** replace ym2610 ch0/3 (YM-2610B)118** change ADPCM_SHIFT (10->8) missing bank change 0x4000-0xffff.119** add ADPCM_SHIFT_MASK120** change ADPCMA_DECODE_MIN/MAX.121*/122123/************************************************************************/124/* comment of hiro-shi(Hiromitsu Shioya) */125/* YM2610(B) = OPN-B */126/* YM2610 : PSG:3ch FM:4ch ADPCM(18.5KHz):6ch DeltaT ADPCM:1ch */127/* YM2610B : PSG:3ch FM:6ch ADPCM(18.5KHz):6ch DeltaT ADPCM:1ch */128/************************************************************************/129130#include "shared.h"131132/* envelope generator */133#define ENV_BITS 10134#define ENV_LEN (1<<ENV_BITS)135#define ENV_STEP (128.0/ENV_LEN)136137#define MAX_ATT_INDEX (ENV_LEN-1) /* 1023 */138#define MIN_ATT_INDEX (0) /* 0 */139140#define EG_ATT 4141#define EG_DEC 3142#define EG_SUS 2143#define EG_REL 1144#define EG_OFF 0145146/* phase generator (detune mask) */147#define DT_BITS 17148#define DT_LEN (1 << DT_BITS)149#define DT_MASK (DT_LEN - 1)150151/* operator unit */152#define SIN_BITS 10153#define SIN_LEN (1<<SIN_BITS)154#define SIN_MASK (SIN_LEN-1)155156#define TL_RES_LEN (256) /* 8 bits addressing (real chip) */157158#define TL_BITS 14 /* channel output */159160/* TL_TAB_LEN is calculated as:161* 13 - sinus amplitude bits (Y axis)162* 2 - sinus sign bit (Y axis)163* TL_RES_LEN - sinus resolution (X axis)164*/165#define TL_TAB_LEN (13*2*TL_RES_LEN)166static signed int tl_tab[TL_TAB_LEN];167168#define ENV_QUIET (TL_TAB_LEN>>3)169170/* sin waveform table in 'decibel' scale */171static unsigned int sin_tab[SIN_LEN];172173/* sustain level table (3dB per step) */174/* bit0, bit1, bit2, bit3, bit4, bit5, bit6 */175/* 1, 2, 4, 8, 16, 32, 64 (value)*/176/* 0.75, 1.5, 3, 6, 12, 24, 48 (dB)*/177178/* 0 - 15: 0, 3, 6, 9,12,15,18,21,24,27,30,33,36,39,42,93 (dB)*/179/* attenuation value (10 bits) = (SL << 2) << 3 */180#define SC(db) (UINT32) ( db * (4.0/ENV_STEP) )181static const UINT32 sl_table[16]={182SC( 0),SC( 1),SC( 2),SC(3 ),SC(4 ),SC(5 ),SC(6 ),SC( 7),183SC( 8),SC( 9),SC(10),SC(11),SC(12),SC(13),SC(14),SC(31)184};185#undef SC186187188#define RATE_STEPS (8)189static const UINT8 eg_inc[19*RATE_STEPS]={190191/*cycle:0 1 2 3 4 5 6 7*/192193/* 0 */ 0,1, 0,1, 0,1, 0,1, /* rates 00..11 0 (increment by 0 or 1) */194/* 1 */ 0,1, 0,1, 1,1, 0,1, /* rates 00..11 1 */195/* 2 */ 0,1, 1,1, 0,1, 1,1, /* rates 00..11 2 */196/* 3 */ 0,1, 1,1, 1,1, 1,1, /* rates 00..11 3 */197198/* 4 */ 1,1, 1,1, 1,1, 1,1, /* rate 12 0 (increment by 1) */199/* 5 */ 1,1, 1,2, 1,1, 1,2, /* rate 12 1 */200/* 6 */ 1,2, 1,2, 1,2, 1,2, /* rate 12 2 */201/* 7 */ 1,2, 2,2, 1,2, 2,2, /* rate 12 3 */202203/* 8 */ 2,2, 2,2, 2,2, 2,2, /* rate 13 0 (increment by 2) */204/* 9 */ 2,2, 2,4, 2,2, 2,4, /* rate 13 1 */205/*10 */ 2,4, 2,4, 2,4, 2,4, /* rate 13 2 */206/*11 */ 2,4, 4,4, 2,4, 4,4, /* rate 13 3 */207208/*12 */ 4,4, 4,4, 4,4, 4,4, /* rate 14 0 (increment by 4) */209/*13 */ 4,4, 4,8, 4,4, 4,8, /* rate 14 1 */210/*14 */ 4,8, 4,8, 4,8, 4,8, /* rate 14 2 */211/*15 */ 4,8, 8,8, 4,8, 8,8, /* rate 14 3 */212213/*16 */ 8,8, 8,8, 8,8, 8,8, /* rates 15 0, 15 1, 15 2, 15 3 (increment by 8) */214/*17 */ 16,16,16,16,16,16,16,16, /* rates 15 2, 15 3 for attack */215/*18 */ 0,0, 0,0, 0,0, 0,0, /* infinity rates for attack and decay(s) */216};217218219#define O(a) (a*RATE_STEPS)220221/*note that there is no O(17) in this table - it's directly in the code */222static const UINT8 eg_rate_select[32+64+32]={ /* Envelope Generator rates (32 + 64 rates + 32 RKS) */223/* 32 infinite time rates (same as Rate 0) */224O(18),O(18),O(18),O(18),O(18),O(18),O(18),O(18),225O(18),O(18),O(18),O(18),O(18),O(18),O(18),O(18),226O(18),O(18),O(18),O(18),O(18),O(18),O(18),O(18),227O(18),O(18),O(18),O(18),O(18),O(18),O(18),O(18),228229/* rates 00-11 */230/*231O( 0),O( 1),O( 2),O( 3),232O( 0),O( 1),O( 2),O( 3),233*/234O(18),O(18),O( 0),O( 0),235O( 0),O( 0),O( 2),O( 2), /* Nemesis's tests */236237O( 0),O( 1),O( 2),O( 3),238O( 0),O( 1),O( 2),O( 3),239O( 0),O( 1),O( 2),O( 3),240O( 0),O( 1),O( 2),O( 3),241O( 0),O( 1),O( 2),O( 3),242O( 0),O( 1),O( 2),O( 3),243O( 0),O( 1),O( 2),O( 3),244O( 0),O( 1),O( 2),O( 3),245O( 0),O( 1),O( 2),O( 3),246O( 0),O( 1),O( 2),O( 3),247248/* rate 12 */249O( 4),O( 5),O( 6),O( 7),250251/* rate 13 */252O( 8),O( 9),O(10),O(11),253254/* rate 14 */255O(12),O(13),O(14),O(15),256257/* rate 15 */258O(16),O(16),O(16),O(16),259260/* 32 dummy rates (same as 15 3) */261O(16),O(16),O(16),O(16),O(16),O(16),O(16),O(16),262O(16),O(16),O(16),O(16),O(16),O(16),O(16),O(16),263O(16),O(16),O(16),O(16),O(16),O(16),O(16),O(16),264O(16),O(16),O(16),O(16),O(16),O(16),O(16),O(16)265266};267#undef O268269/*rate 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15*/270/*shift 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 0, 0, 0, 0, 0 */271/*mask 2047, 1023, 511, 255, 127, 63, 31, 15, 7, 3, 1, 0, 0, 0, 0, 0 */272273#define O(a) (a*1)274static const UINT8 eg_rate_shift[32+64+32]={ /* Envelope Generator counter shifts (32 + 64 rates + 32 RKS) */275/* 32 infinite time rates */276/* O(0),O(0),O(0),O(0),O(0),O(0),O(0),O(0),277O(0),O(0),O(0),O(0),O(0),O(0),O(0),O(0),278O(0),O(0),O(0),O(0),O(0),O(0),O(0),O(0),279O(0),O(0),O(0),O(0),O(0),O(0),O(0),O(0), */280281/* fixed (should be the same as rate 0, even if it makes no difference since increment value is 0 for these rates) */282O(11),O(11),O(11),O(11),O(11),O(11),O(11),O(11),283O(11),O(11),O(11),O(11),O(11),O(11),O(11),O(11),284O(11),O(11),O(11),O(11),O(11),O(11),O(11),O(11),285O(11),O(11),O(11),O(11),O(11),O(11),O(11),O(11),286287/* rates 00-11 */288O(11),O(11),O(11),O(11),289O(10),O(10),O(10),O(10),290O( 9),O( 9),O( 9),O( 9),291O( 8),O( 8),O( 8),O( 8),292O( 7),O( 7),O( 7),O( 7),293O( 6),O( 6),O( 6),O( 6),294O( 5),O( 5),O( 5),O( 5),295O( 4),O( 4),O( 4),O( 4),296O( 3),O( 3),O( 3),O( 3),297O( 2),O( 2),O( 2),O( 2),298O( 1),O( 1),O( 1),O( 1),299O( 0),O( 0),O( 0),O( 0),300301/* rate 12 */302O( 0),O( 0),O( 0),O( 0),303304/* rate 13 */305O( 0),O( 0),O( 0),O( 0),306307/* rate 14 */308O( 0),O( 0),O( 0),O( 0),309310/* rate 15 */311O( 0),O( 0),O( 0),O( 0),312313/* 32 dummy rates (same as 15 3) */314O( 0),O( 0),O( 0),O( 0),O( 0),O( 0),O( 0),O( 0),315O( 0),O( 0),O( 0),O( 0),O( 0),O( 0),O( 0),O( 0),316O( 0),O( 0),O( 0),O( 0),O( 0),O( 0),O( 0),O( 0),317O( 0),O( 0),O( 0),O( 0),O( 0),O( 0),O( 0),O( 0)318319};320#undef O321322static const UINT8 dt_tab[4 * 32]={323/* this is YM2151 and YM2612 phase increment data (in 10.10 fixed point format)*/324/* FD=0 */3250, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,3260, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,327/* FD=1 */3280, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 2, 2, 2, 2,3292, 3, 3, 3, 4, 4, 4, 5, 5, 6, 6, 7, 8, 8, 8, 8,330/* FD=2 */3311, 1, 1, 1, 2, 2, 2, 2, 2, 3, 3, 3, 4, 4, 4, 5,3325, 6, 6, 7, 8, 8, 9,10,11,12,13,14,16,16,16,16,333/* FD=3 */3342, 2, 2, 2, 2, 3, 3, 3, 4, 4, 4, 5, 5, 6, 6, 7,3358 , 8, 9,10,11,12,13,14,16,17,19,20,22,22,22,22336};337338339/* OPN key frequency number -> key code follow table */340/* fnum higher 4bit -> keycode lower 2bit */341static const UINT8 opn_fktable[16] = {0,0,0,0,0,0,0,1,2,3,3,3,3,3,3,3};342343344/* 8 LFO speed parameters */345/* each value represents number of samples that one LFO level will last for */346static const UINT32 lfo_samples_per_step[8] = {108, 77, 71, 67, 62, 44, 8, 5};347348349/*There are 4 different LFO AM depths available, they are:3500 dB, 1.4 dB, 5.9 dB, 11.8 dB351Here is how it is generated (in EG steps):35235311.8 dB = 0, 2, 4, 6, 8, 10,12,14,16...126,126,124,122,120,118,....4,2,03545.9 dB = 0, 1, 2, 3, 4, 5, 6, 7, 8....63, 63, 62, 61, 60, 59,.....2,1,03551.4 dB = 0, 0, 0, 0, 1, 1, 1, 1, 2,...15, 15, 15, 15, 14, 14,.....0,0,0356357(1.4 dB is loosing precision as you can see)358359It's implemented as generator from 0..126 with step 2 then a shift360right N times, where N is:3618 for 0 dB3623 for 1.4 dB3631 for 5.9 dB3640 for 11.8 dB365*/366static const UINT8 lfo_ams_depth_shift[4] = {8, 3, 1, 0};367368369370/*There are 8 different LFO PM depths available, they are:3710, 3.4, 6.7, 10, 14, 20, 40, 80 (cents)372373Modulation level at each depth depends on F-NUMBER bits: 4,5,6,7,8,9,10374(bits 8,9,10 = FNUM MSB from OCT/FNUM register)375376Here we store only first quarter (positive one) of full waveform.377Full table (lfo_pm_table) containing all 128 waveforms is build378at run (init) time.379380One value in table below represents 4 (four) basic LFO steps381(1 PM step = 4 AM steps).382383For example:384at LFO SPEED=0 (which is 108 samples per basic LFO step)385one value from "lfo_pm_output" table lasts for 432 consecutive386samples (4*108=432) and one full LFO waveform cycle lasts for 13824387samples (32*432=13824; 32 because we store only a quarter of whole388waveform in the table below)389*/390static const UINT8 lfo_pm_output[7*8][8]={391/* 7 bits meaningful (of F-NUMBER), 8 LFO output levels per one depth (out of 32), 8 LFO depths */392/* FNUM BIT 4: 000 0001xxxx */393/* DEPTH 0 */ {0, 0, 0, 0, 0, 0, 0, 0},394/* DEPTH 1 */ {0, 0, 0, 0, 0, 0, 0, 0},395/* DEPTH 2 */ {0, 0, 0, 0, 0, 0, 0, 0},396/* DEPTH 3 */ {0, 0, 0, 0, 0, 0, 0, 0},397/* DEPTH 4 */ {0, 0, 0, 0, 0, 0, 0, 0},398/* DEPTH 5 */ {0, 0, 0, 0, 0, 0, 0, 0},399/* DEPTH 6 */ {0, 0, 0, 0, 0, 0, 0, 0},400/* DEPTH 7 */ {0, 0, 0, 0, 1, 1, 1, 1},401402/* FNUM BIT 5: 000 0010xxxx */403/* DEPTH 0 */ {0, 0, 0, 0, 0, 0, 0, 0},404/* DEPTH 1 */ {0, 0, 0, 0, 0, 0, 0, 0},405/* DEPTH 2 */ {0, 0, 0, 0, 0, 0, 0, 0},406/* DEPTH 3 */ {0, 0, 0, 0, 0, 0, 0, 0},407/* DEPTH 4 */ {0, 0, 0, 0, 0, 0, 0, 0},408/* DEPTH 5 */ {0, 0, 0, 0, 0, 0, 0, 0},409/* DEPTH 6 */ {0, 0, 0, 0, 1, 1, 1, 1},410/* DEPTH 7 */ {0, 0, 1, 1, 2, 2, 2, 3},411412/* FNUM BIT 6: 000 0100xxxx */413/* DEPTH 0 */ {0, 0, 0, 0, 0, 0, 0, 0},414/* DEPTH 1 */ {0, 0, 0, 0, 0, 0, 0, 0},415/* DEPTH 2 */ {0, 0, 0, 0, 0, 0, 0, 0},416/* DEPTH 3 */ {0, 0, 0, 0, 0, 0, 0, 0},417/* DEPTH 4 */ {0, 0, 0, 0, 0, 0, 0, 1},418/* DEPTH 5 */ {0, 0, 0, 0, 1, 1, 1, 1},419/* DEPTH 6 */ {0, 0, 1, 1, 2, 2, 2, 3},420/* DEPTH 7 */ {0, 0, 2, 3, 4, 4, 5, 6},421422/* FNUM BIT 7: 000 1000xxxx */423/* DEPTH 0 */ {0, 0, 0, 0, 0, 0, 0, 0},424/* DEPTH 1 */ {0, 0, 0, 0, 0, 0, 0, 0},425/* DEPTH 2 */ {0, 0, 0, 0, 0, 0, 1, 1},426/* DEPTH 3 */ {0, 0, 0, 0, 1, 1, 1, 1},427/* DEPTH 4 */ {0, 0, 0, 1, 1, 1, 1, 2},428/* DEPTH 5 */ {0, 0, 1, 1, 2, 2, 2, 3},429/* DEPTH 6 */ {0, 0, 2, 3, 4, 4, 5, 6},430/* DEPTH 7 */ {0, 0, 4, 6, 8, 8, 0xa, 0xc},431432/* FNUM BIT 8: 001 0000xxxx */433/* DEPTH 0 */ {0, 0, 0, 0, 0, 0, 0, 0},434/* DEPTH 1 */ {0, 0, 0, 0, 1, 1, 1, 1},435/* DEPTH 2 */ {0, 0, 0, 1, 1, 1, 2, 2},436/* DEPTH 3 */ {0, 0, 1, 1, 2, 2, 3, 3},437/* DEPTH 4 */ {0, 0, 1, 2, 2, 2, 3, 4},438/* DEPTH 5 */ {0, 0, 2, 3, 4, 4, 5, 6},439/* DEPTH 6 */ {0, 0, 4, 6, 8, 8, 0xa, 0xc},440/* DEPTH 7 */ {0, 0, 8, 0xc,0x10,0x10,0x14,0x18},441442/* FNUM BIT 9: 010 0000xxxx */443/* DEPTH 0 */ {0, 0, 0, 0, 0, 0, 0, 0},444/* DEPTH 1 */ {0, 0, 0, 0, 2, 2, 2, 2},445/* DEPTH 2 */ {0, 0, 0, 2, 2, 2, 4, 4},446/* DEPTH 3 */ {0, 0, 2, 2, 4, 4, 6, 6},447/* DEPTH 4 */ {0, 0, 2, 4, 4, 4, 6, 8},448/* DEPTH 5 */ {0, 0, 4, 6, 8, 8, 0xa, 0xc},449/* DEPTH 6 */ {0, 0, 8, 0xc,0x10,0x10,0x14,0x18},450/* DEPTH 7 */ {0, 0,0x10,0x18,0x20,0x20,0x28,0x30},451452/* FNUM BIT10: 100 0000xxxx */453/* DEPTH 0 */ {0, 0, 0, 0, 0, 0, 0, 0},454/* DEPTH 1 */ {0, 0, 0, 0, 4, 4, 4, 4},455/* DEPTH 2 */ {0, 0, 0, 4, 4, 4, 8, 8},456/* DEPTH 3 */ {0, 0, 4, 4, 8, 8, 0xc, 0xc},457/* DEPTH 4 */ {0, 0, 4, 8, 8, 8, 0xc,0x10},458/* DEPTH 5 */ {0, 0, 8, 0xc,0x10,0x10,0x14,0x18},459/* DEPTH 6 */ {0, 0,0x10,0x18,0x20,0x20,0x28,0x30},460/* DEPTH 7 */ {0, 0,0x20,0x30,0x40,0x40,0x50,0x60},461462};463464/* all 128 LFO PM waveforms */465static 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 */466467/* register number to channel number , slot offset */468#define OPN_CHAN(N) (N&3)469#define OPN_SLOT(N) ((N>>2)&3)470471/* slot number */472#define SLOT1 0473#define SLOT2 2474#define SLOT3 1475#define SLOT4 3476477/* struct describing a single operator (SLOT) */478typedef struct479{480INT32 *DT; /* detune :dt_tab[DT] */481UINT8 KSR; /* key scale rate :3-KSR */482UINT32 ar; /* attack rate */483UINT32 d1r; /* decay rate */484UINT32 d2r; /* sustain rate */485UINT32 rr; /* release rate */486UINT8 ksr; /* key scale rate :kcode>>(3-KSR) */487UINT32 mul; /* multiple :ML_TABLE[ML] */488489/* Phase Generator */490UINT32 phase; /* phase counter */491INT32 Incr; /* phase step */492493/* Envelope Generator */494UINT8 state; /* phase type */495UINT32 tl; /* total level: TL << 3 */496INT32 volume; /* envelope counter */497UINT32 sl; /* sustain level:sl_table[SL] */498UINT32 vol_out; /* current output from EG circuit (without AM from LFO) */499500UINT8 eg_sh_ar; /* (attack state) */501UINT8 eg_sel_ar; /* (attack state) */502UINT8 eg_sh_d1r; /* (decay state) */503UINT8 eg_sel_d1r; /* (decay state) */504UINT8 eg_sh_d2r; /* (sustain state) */505UINT8 eg_sel_d2r; /* (sustain state) */506UINT8 eg_sh_rr; /* (release state) */507UINT8 eg_sel_rr; /* (release state) */508509UINT8 ssg; /* SSG-EG waveform */510UINT8 ssgn; /* SSG-EG negated output */511512UINT8 key; /* 0=last key was KEY OFF, 1=KEY ON */513514/* LFO */515UINT32 AMmask; /* AM enable flag */516517} FM_SLOT;518519typedef struct520{521FM_SLOT SLOT[4]; /* four SLOTs (operators) */522523UINT8 ALGO; /* algorithm */524UINT8 FB; /* feedback shift */525INT32 op1_out[2]; /* op1 output for feedback */526527INT32 *connect1; /* SLOT1 output pointer */528INT32 *connect3; /* SLOT3 output pointer */529INT32 *connect2; /* SLOT2 output pointer */530INT32 *connect4; /* SLOT4 output pointer */531532INT32 *mem_connect; /* where to put the delayed sample (MEM) */533INT32 mem_value; /* delayed sample (MEM) value */534535INT32 pms; /* channel PMS */536UINT8 ams; /* channel AMS */537538UINT32 fc; /* fnum,blk */539UINT8 kcode; /* key code */540UINT32 block_fnum; /* blk/fnum value (for LFO PM calculations) */541} FM_CH;542543544typedef struct545{546UINT16 address; /* address register */547UINT8 status; /* status flag */548UINT32 mode; /* mode CSM / 3SLOT */549UINT8 fn_h; /* freq latch */550INT32 TA; /* timer a value */551INT32 TAL; /* timer a base */552INT32 TAC; /* timer a counter */553INT32 TB; /* timer b value */554INT32 TBL; /* timer b base */555INT32 TBC; /* timer b counter */556INT32 dt_tab[8][32]; /* DeTune table */557558} FM_ST;559560561/***********************************************************/562/* OPN unit */563/***********************************************************/564565/* OPN 3slot struct */566typedef struct567{568UINT32 fc[3]; /* fnum3,blk3: calculated */569UINT8 fn_h; /* freq3 latch */570UINT8 kcode[3]; /* key code */571UINT32 block_fnum[3]; /* current fnum value for this slot (can be different betweeen slots of one channel in 3slot mode) */572UINT8 key_csm; /* CSM mode Key-ON flag */573574} FM_3SLOT;575576/* OPN/A/B common state */577typedef struct578{579FM_ST ST; /* general state */580FM_3SLOT SL3; /* 3 slot mode state */581unsigned int pan[6*2]; /* fm channels output masks (0xffffffff = enable) */582583/* EG */584UINT32 eg_cnt; /* global envelope generator counter */585UINT32 eg_timer; /* global envelope generator counter works at frequency = chipclock/144/3 */586587/* LFO */588UINT8 lfo_cnt; /* current LFO phase (out of 128) */589UINT32 lfo_timer; /* current LFO phase runs at LFO frequency */590UINT32 lfo_timer_overflow; /* LFO timer overflows every N samples (depends on LFO frequency) */591UINT32 LFO_AM; /* current LFO AM step */592UINT32 LFO_PM; /* current LFO PM step */593594} FM_OPN;595596/***********************************************************/597/* YM2612 chip */598/***********************************************************/599typedef struct600{601FM_CH CH[6]; /* channel state */602UINT8 dacen; /* DAC mode */603INT32 dacout; /* DAC output */604FM_OPN OPN; /* OPN state */605606} YM2612;607608/* emulated chip */609YM2612 ym2612;610611/* current chip state */612INT32 m2,c1,c2; /* Phase Modulation input for operators 2,3,4 */613INT32 mem; /* one sample delay memory */614INT32 out_fm[8]; /* outputs of working channels */615UINT32 bitmask; /* working channels output bitmasking (DAC quantization) */616617618INLINE void FM_KEYON(FM_CH *CH , int s )619{620FM_SLOT *SLOT = &CH->SLOT[s];621622if (!SLOT->key && !ym2612.OPN.SL3.key_csm)623{624/* restart Phase Generator */625SLOT->phase = 0;626627/* reset SSG-EG inversion flag */628SLOT->ssgn = 0;629630if ((SLOT->ar + SLOT->ksr) < 94 /*32+62*/)631{632SLOT->state = (SLOT->volume <= MIN_ATT_INDEX) ? ((SLOT->sl == MIN_ATT_INDEX) ? EG_SUS : EG_DEC) : EG_ATT;633}634else635{636/* force attenuation level to 0 */637SLOT->volume = MIN_ATT_INDEX;638639/* directly switch to Decay (or Sustain) */640SLOT->state = (SLOT->sl == MIN_ATT_INDEX) ? EG_SUS : EG_DEC;641}642643/* recalculate EG output */644if ((SLOT->ssg&0x08) && (SLOT->ssgn ^ (SLOT->ssg&0x04)))645SLOT->vol_out = ((UINT32)(0x200 - SLOT->volume) & MAX_ATT_INDEX) + SLOT->tl;646else647SLOT->vol_out = (UINT32)SLOT->volume + SLOT->tl;648}649650SLOT->key = 1;651}652653INLINE void FM_KEYOFF(FM_CH *CH , int s )654{655FM_SLOT *SLOT = &CH->SLOT[s];656657if (SLOT->key && !ym2612.OPN.SL3.key_csm)658{659if (SLOT->state>EG_REL)660{661SLOT->state = EG_REL; /* phase -> Release */662663/* SSG-EG specific update */664if (SLOT->ssg&0x08)665{666/* convert EG attenuation level */667if (SLOT->ssgn ^ (SLOT->ssg&0x04))668SLOT->volume = (0x200 - SLOT->volume);669670/* force EG attenuation level */671if (SLOT->volume >= 0x200)672{673SLOT->volume = MAX_ATT_INDEX;674SLOT->state = EG_OFF;675}676677/* recalculate EG output */678SLOT->vol_out = (UINT32)SLOT->volume + SLOT->tl;679}680}681}682683SLOT->key = 0;684}685686INLINE void FM_KEYON_CSM(FM_CH *CH , int s )687{688FM_SLOT *SLOT = &CH->SLOT[s];689690if (!SLOT->key && !ym2612.OPN.SL3.key_csm)691{692/* restart Phase Generator */693SLOT->phase = 0;694695/* reset SSG-EG inversion flag */696SLOT->ssgn = 0;697698if ((SLOT->ar + SLOT->ksr) < 94 /*32+62*/)699{700SLOT->state = (SLOT->volume <= MIN_ATT_INDEX) ? ((SLOT->sl == MIN_ATT_INDEX) ? EG_SUS : EG_DEC) : EG_ATT;701}702else703{704/* force attenuation level to 0 */705SLOT->volume = MIN_ATT_INDEX;706707/* directly switch to Decay (or Sustain) */708SLOT->state = (SLOT->sl == MIN_ATT_INDEX) ? EG_SUS : EG_DEC;709}710711/* recalculate EG output */712if ((SLOT->ssg&0x08) && (SLOT->ssgn ^ (SLOT->ssg&0x04)))713SLOT->vol_out = ((UINT32)(0x200 - SLOT->volume) & MAX_ATT_INDEX) + SLOT->tl;714else715SLOT->vol_out = (UINT32)SLOT->volume + SLOT->tl;716}717}718719INLINE void FM_KEYOFF_CSM(FM_CH *CH , int s )720{721FM_SLOT *SLOT = &CH->SLOT[s];722if (!SLOT->key)723{724if (SLOT->state>EG_REL)725{726SLOT->state = EG_REL; /* phase -> Release */727728/* SSG-EG specific update */729if (SLOT->ssg&0x08)730{731/* convert EG attenuation level */732if (SLOT->ssgn ^ (SLOT->ssg&0x04))733SLOT->volume = (0x200 - SLOT->volume);734735/* force EG attenuation level */736if (SLOT->volume >= 0x200)737{738SLOT->volume = MAX_ATT_INDEX;739SLOT->state = EG_OFF;740}741742/* recalculate EG output */743SLOT->vol_out = (UINT32)SLOT->volume + SLOT->tl;744}745}746}747}748749/* CSM Key Controll */750INLINE void CSMKeyControll(FM_CH *CH)751{752/* all key ON (verified by Nemesis on real hardware) */753FM_KEYON_CSM(CH,SLOT1);754FM_KEYON_CSM(CH,SLOT2);755FM_KEYON_CSM(CH,SLOT3);756FM_KEYON_CSM(CH,SLOT4);757ym2612.OPN.SL3.key_csm = 1;758}759760INLINE void INTERNAL_TIMER_A()761{762if (ym2612.OPN.ST.mode & 0x01)763{764ym2612.OPN.ST.TAC--;765if (ym2612.OPN.ST.TAC <= 0)766{767/* set status (if enabled) */768if (ym2612.OPN.ST.mode & 0x04)769ym2612.OPN.ST.status |= 0x01;770771/* reload the counter */772ym2612.OPN.ST.TAC = ym2612.OPN.ST.TAL;773774/* CSM mode auto key on */775if ((ym2612.OPN.ST.mode & 0xC0) == 0x80)776CSMKeyControll(&ym2612.CH[2]);777}778}779}780781INLINE void INTERNAL_TIMER_B(int step)782{783if (ym2612.OPN.ST.mode & 0x02)784{785ym2612.OPN.ST.TBC-=step;786if (ym2612.OPN.ST.TBC <= 0)787{788/* set status (if enabled) */789if (ym2612.OPN.ST.mode & 0x08)790ym2612.OPN.ST.status |= 0x02;791792/* reload the counter */793if (ym2612.OPN.ST.TBL)794ym2612.OPN.ST.TBC += ym2612.OPN.ST.TBL;795else796ym2612.OPN.ST.TBC = ym2612.OPN.ST.TBL;797}798}799}800801/* OPN Mode Register Write */802INLINE void set_timers(int v )803{804/* b7 = CSM MODE */805/* b6 = 3 slot mode */806/* b5 = reset b */807/* b4 = reset a */808/* b3 = timer enable b */809/* b2 = timer enable a */810/* b1 = load b */811/* b0 = load a */812813if ((ym2612.OPN.ST.mode ^ v) & 0xC0)814{815/* phase increment need to be recalculated */816ym2612.CH[2].SLOT[SLOT1].Incr=-1;817818/* CSM mode disabled and CSM key ON active*/819if (((v & 0xC0) != 0x80) && ym2612.OPN.SL3.key_csm)820{821/* CSM Mode Key OFF (verified by Nemesis on real hardware) */822FM_KEYOFF_CSM(&ym2612.CH[2],SLOT1);823FM_KEYOFF_CSM(&ym2612.CH[2],SLOT2);824FM_KEYOFF_CSM(&ym2612.CH[2],SLOT3);825FM_KEYOFF_CSM(&ym2612.CH[2],SLOT4);826ym2612.OPN.SL3.key_csm = 0;827}828}829830/* reload Timers */831if ((v&1) && !(ym2612.OPN.ST.mode&1))832ym2612.OPN.ST.TAC = ym2612.OPN.ST.TAL;833if ((v&2) && !(ym2612.OPN.ST.mode&2))834ym2612.OPN.ST.TBC = ym2612.OPN.ST.TBL;835836/* reset Timers flags */837ym2612.OPN.ST.status &= (~v >> 4);838839ym2612.OPN.ST.mode = v;840}841842/* set algorithm connection */843INLINE void setup_connection( FM_CH *CH, int ch )844{845INT32 *carrier = &out_fm[ch];846847INT32 **om1 = &CH->connect1;848INT32 **om2 = &CH->connect3;849INT32 **oc1 = &CH->connect2;850851INT32 **memc = &CH->mem_connect;852853switch( CH->ALGO ){854case 0:855/* M1---C1---MEM---M2---C2---OUT */856*om1 = &c1;857*oc1 = &mem;858*om2 = &c2;859*memc= &m2;860break;861case 1:862/* M1------+-MEM---M2---C2---OUT */863/* C1-+ */864*om1 = &mem;865*oc1 = &mem;866*om2 = &c2;867*memc= &m2;868break;869case 2:870/* M1-----------------+-C2---OUT */871/* C1---MEM---M2-+ */872*om1 = &c2;873*oc1 = &mem;874*om2 = &c2;875*memc= &m2;876break;877case 3:878/* M1---C1---MEM------+-C2---OUT */879/* M2-+ */880*om1 = &c1;881*oc1 = &mem;882*om2 = &c2;883*memc= &c2;884break;885case 4:886/* M1---C1-+-OUT */887/* M2---C2-+ */888/* MEM: not used */889*om1 = &c1;890*oc1 = carrier;891*om2 = &c2;892*memc= &mem; /* store it anywhere where it will not be used */893break;894case 5:895/* +----C1----+ */896/* M1-+-MEM---M2-+-OUT */897/* +----C2----+ */898*om1 = 0; /* special mark */899*oc1 = carrier;900*om2 = carrier;901*memc= &m2;902break;903case 6:904/* M1---C1-+ */905/* M2-+-OUT */906/* C2-+ */907/* MEM: not used */908*om1 = &c1;909*oc1 = carrier;910*om2 = carrier;911*memc= &mem; /* store it anywhere where it will not be used */912break;913case 7:914/* M1-+ */915/* C1-+-OUT */916/* M2-+ */917/* C2-+ */918/* MEM: not used*/919*om1 = carrier;920*oc1 = carrier;921*om2 = carrier;922*memc= &mem; /* store it anywhere where it will not be used */923break;924}925926CH->connect4 = carrier;927}928929/* set detune & multiple */930INLINE void set_det_mul(FM_CH *CH,FM_SLOT *SLOT,int v)931{932SLOT->mul = (v&0x0f)? (v&0x0f)*2 : 1;933SLOT->DT = ym2612.OPN.ST.dt_tab[(v>>4)&7];934CH->SLOT[SLOT1].Incr=-1;935}936937/* set total level */938INLINE void set_tl(FM_SLOT *SLOT , int v)939{940SLOT->tl = (v&0x7f)<<(ENV_BITS-7); /* 7bit TL */941942/* recalculate EG output */943if ((SLOT->ssg&0x08) && (SLOT->ssgn ^ (SLOT->ssg&0x04)) && (SLOT->state > EG_REL))944SLOT->vol_out = ((UINT32)(0x200 - SLOT->volume) & MAX_ATT_INDEX) + SLOT->tl;945else946SLOT->vol_out = (UINT32)SLOT->volume + SLOT->tl;947}948949/* set attack rate & key scale */950INLINE void set_ar_ksr(FM_CH *CH,FM_SLOT *SLOT,int v)951{952UINT8 old_KSR = SLOT->KSR;953954SLOT->ar = (v&0x1f) ? 32 + ((v&0x1f)<<1) : 0;955956SLOT->KSR = 3-(v>>6);957if (SLOT->KSR != old_KSR)958{959CH->SLOT[SLOT1].Incr=-1;960}961962/* Even if it seems unnecessary to do it here, it could happen that KSR and KC */963/* are modified but the resulted SLOT->ksr value (kc >> SLOT->KSR) remains unchanged. */964/* In such case, Attack Rate would not be recalculated by "refresh_fc_eg_slot". */965/* This actually fixes the intro of "The Adventures of Batman & Robin" (Eke-Eke) */966if ((SLOT->ar + SLOT->ksr) < (32+62))967{968SLOT->eg_sh_ar = eg_rate_shift [SLOT->ar + SLOT->ksr ];969SLOT->eg_sel_ar = eg_rate_select[SLOT->ar + SLOT->ksr ];970}971else972{973/* verified by Nemesis on real hardware (Attack phase is blocked) */974SLOT->eg_sh_ar = 0;975SLOT->eg_sel_ar = 18*RATE_STEPS;976}977}978979/* set decay rate */980INLINE void set_dr(FM_SLOT *SLOT,int v)981{982SLOT->d1r = (v&0x1f) ? 32 + ((v&0x1f)<<1) : 0;983984SLOT->eg_sh_d1r = eg_rate_shift [SLOT->d1r + SLOT->ksr];985SLOT->eg_sel_d1r= eg_rate_select[SLOT->d1r + SLOT->ksr];986987}988989/* set sustain rate */990INLINE void set_sr(FM_SLOT *SLOT,int v)991{992SLOT->d2r = (v&0x1f) ? 32 + ((v&0x1f)<<1) : 0;993994SLOT->eg_sh_d2r = eg_rate_shift [SLOT->d2r + SLOT->ksr];995SLOT->eg_sel_d2r= eg_rate_select[SLOT->d2r + SLOT->ksr];996}997998/* set release rate */999INLINE void set_sl_rr(FM_SLOT *SLOT,int v)1000{1001SLOT->sl = sl_table[ v>>4 ];10021003/* check EG state changes */1004if ((SLOT->state == EG_DEC) && (SLOT->volume >= (INT32)(SLOT->sl)))1005SLOT->state = EG_SUS;10061007SLOT->rr = 34 + ((v&0x0f)<<2);10081009SLOT->eg_sh_rr = eg_rate_shift [SLOT->rr + SLOT->ksr];1010SLOT->eg_sel_rr = eg_rate_select[SLOT->rr + SLOT->ksr];1011}10121013/* advance LFO to next sample */1014INLINE void advance_lfo()1015{1016if (ym2612.OPN.lfo_timer_overflow) /* LFO enabled ? */1017{1018/* increment LFO timer (every samples) */1019ym2612.OPN.lfo_timer ++;10201021/* when LFO is enabled, one level will last for 108, 77, 71, 67, 62, 44, 8 or 5 samples */1022if (ym2612.OPN.lfo_timer >= ym2612.OPN.lfo_timer_overflow)1023{1024ym2612.OPN.lfo_timer = 0;10251026/* There are 128 LFO steps */1027ym2612.OPN.lfo_cnt = ( ym2612.OPN.lfo_cnt + 1 ) & 127;10281029/* triangle (inverted) */1030/* AM: from 126 to 0 step -2, 0 to 126 step +2 */1031if (ym2612.OPN.lfo_cnt<64)1032ym2612.OPN.LFO_AM = (ym2612.OPN.lfo_cnt ^ 63) << 1;1033else1034ym2612.OPN.LFO_AM = (ym2612.OPN.lfo_cnt & 63) << 1;10351036/* PM works with 4 times slower clock */1037ym2612.OPN.LFO_PM = ym2612.OPN.lfo_cnt >> 2;1038}1039}1040}104110421043INLINE void advance_eg_channels(FM_CH *CH, unsigned int eg_cnt)1044{1045unsigned int i = 6; /* six channels */1046unsigned int j;1047FM_SLOT *SLOT;10481049do1050{1051SLOT = &CH->SLOT[SLOT1];1052j = 4; /* four operators per channel */1053do1054{1055switch(SLOT->state)1056{1057case EG_ATT: /* attack phase */1058{1059if (!(eg_cnt & ((1<<SLOT->eg_sh_ar)-1)))1060{1061/* update attenuation level */1062SLOT->volume += (~SLOT->volume * (eg_inc[SLOT->eg_sel_ar + ((eg_cnt>>SLOT->eg_sh_ar)&7)]))>>4;10631064/* check phase transition*/1065if (SLOT->volume <= MIN_ATT_INDEX)1066{1067SLOT->volume = MIN_ATT_INDEX;1068SLOT->state = (SLOT->sl == MIN_ATT_INDEX) ? EG_SUS : EG_DEC; /* special case where SL=0 */1069}10701071/* recalculate EG output */1072if ((SLOT->ssg&0x08) && (SLOT->ssgn ^ (SLOT->ssg&0x04))) /* SSG-EG Output Inversion */1073SLOT->vol_out = ((UINT32)(0x200 - SLOT->volume) & MAX_ATT_INDEX) + SLOT->tl;1074else1075SLOT->vol_out = (UINT32)SLOT->volume + SLOT->tl;1076}1077break;1078}10791080case EG_DEC: /* decay phase */1081{1082if (!(eg_cnt & ((1<<SLOT->eg_sh_d1r)-1)))1083{1084/* SSG EG type */1085if (SLOT->ssg&0x08)1086{1087/* update attenuation level */1088if (SLOT->volume < 0x200)1089{1090SLOT->volume += 4 * eg_inc[SLOT->eg_sel_d1r + ((eg_cnt>>SLOT->eg_sh_d1r)&7)];10911092/* recalculate EG output */1093if (SLOT->ssgn ^ (SLOT->ssg&0x04)) /* SSG-EG Output Inversion */1094SLOT->vol_out = ((UINT32)(0x200 - SLOT->volume) & MAX_ATT_INDEX) + SLOT->tl;1095else1096SLOT->vol_out = (UINT32)SLOT->volume + SLOT->tl;1097}1098}1099else1100{1101/* update attenuation level */1102SLOT->volume += eg_inc[SLOT->eg_sel_d1r + ((eg_cnt>>SLOT->eg_sh_d1r)&7)];11031104/* recalculate EG output */1105SLOT->vol_out = (UINT32)SLOT->volume + SLOT->tl;1106}11071108/* check phase transition*/1109if (SLOT->volume >= (INT32)(SLOT->sl))1110SLOT->state = EG_SUS;1111}1112break;1113}11141115case EG_SUS: /* sustain phase */1116{1117if (!(eg_cnt & ((1<<SLOT->eg_sh_d2r)-1)))1118{1119/* SSG EG type */1120if (SLOT->ssg&0x08)1121{1122/* update attenuation level */1123if (SLOT->volume < 0x200)1124{1125SLOT->volume += 4 * eg_inc[SLOT->eg_sel_d2r + ((eg_cnt>>SLOT->eg_sh_d2r)&7)];11261127/* recalculate EG output */1128if (SLOT->ssgn ^ (SLOT->ssg&0x04)) /* SSG-EG Output Inversion */1129SLOT->vol_out = ((UINT32)(0x200 - SLOT->volume) & MAX_ATT_INDEX) + SLOT->tl;1130else1131SLOT->vol_out = (UINT32)SLOT->volume + SLOT->tl;1132}1133}1134else1135{1136/* update attenuation level */1137SLOT->volume += eg_inc[SLOT->eg_sel_d2r + ((eg_cnt>>SLOT->eg_sh_d2r)&7)];11381139/* check phase transition*/1140if ( SLOT->volume >= MAX_ATT_INDEX )1141SLOT->volume = MAX_ATT_INDEX;1142/* do not change SLOT->state (verified on real chip) */11431144/* recalculate EG output */1145SLOT->vol_out = (UINT32)SLOT->volume + SLOT->tl;1146}1147}1148break;1149}11501151case EG_REL: /* release phase */1152{1153if (!(eg_cnt & ((1<<SLOT->eg_sh_rr)-1)))1154{1155/* SSG EG type */1156if (SLOT->ssg&0x08)1157{1158/* update attenuation level */1159if (SLOT->volume < 0x200)1160SLOT->volume += 4 * eg_inc[SLOT->eg_sel_rr + ((eg_cnt>>SLOT->eg_sh_rr)&7)];11611162/* check phase transition */1163if (SLOT->volume >= 0x200)1164{1165SLOT->volume = MAX_ATT_INDEX;1166SLOT->state = EG_OFF;1167}1168}1169else1170{1171/* update attenuation level */1172SLOT->volume += eg_inc[SLOT->eg_sel_rr + ((eg_cnt>>SLOT->eg_sh_rr)&7)];11731174/* check phase transition*/1175if (SLOT->volume >= MAX_ATT_INDEX)1176{1177SLOT->volume = MAX_ATT_INDEX;1178SLOT->state = EG_OFF;1179}1180}11811182/* recalculate EG output */1183SLOT->vol_out = (UINT32)SLOT->volume + SLOT->tl;11841185}1186break;1187}1188}11891190/* next slot */1191SLOT++;1192} while (--j);11931194/* next channel */1195CH++;1196} while (--i);1197}11981199/* SSG-EG update process */1200/* The behavior is based upon Nemesis tests on real hardware */1201/* This is actually executed before each samples */1202INLINE void update_ssg_eg_channels(FM_CH *CH)1203{1204unsigned int i = 6; /* six channels */1205unsigned int j;1206FM_SLOT *SLOT;12071208do1209{1210j = 4; /* four operators per channel */1211SLOT = &CH->SLOT[SLOT1];12121213do1214{1215/* detect SSG-EG transition */1216/* this is not required during release phase as the attenuation has been forced to MAX and output invert flag is not used */1217/* if an Attack Phase is programmed, inversion can occur on each sample */1218if ((SLOT->ssg & 0x08) && (SLOT->volume >= 0x200) && (SLOT->state > EG_REL))1219{1220if (SLOT->ssg & 0x01) /* bit 0 = hold SSG-EG */1221{1222/* set inversion flag */1223if (SLOT->ssg & 0x02)1224SLOT->ssgn = 4;12251226/* force attenuation level during decay phases */1227if ((SLOT->state != EG_ATT) && !(SLOT->ssgn ^ (SLOT->ssg & 0x04)))1228SLOT->volume = MAX_ATT_INDEX;1229}1230else /* loop SSG-EG */1231{1232/* toggle output inversion flag or reset Phase Generator */1233if (SLOT->ssg & 0x02)1234SLOT->ssgn ^= 4;1235else1236SLOT->phase = 0;12371238/* same as Key ON */1239if (SLOT->state != EG_ATT)1240{1241if ((SLOT->ar + SLOT->ksr) < 94 /*32+62*/)1242{1243SLOT->state = (SLOT->volume <= MIN_ATT_INDEX) ? ((SLOT->sl == MIN_ATT_INDEX) ? EG_SUS : EG_DEC) : EG_ATT;1244}1245else1246{1247/* Attack Rate is maximal: directly switch to Decay or Substain */1248SLOT->volume = MIN_ATT_INDEX;1249SLOT->state = (SLOT->sl == MIN_ATT_INDEX) ? EG_SUS : EG_DEC;1250}1251}1252}12531254/* recalculate EG output */1255if (SLOT->ssgn ^ (SLOT->ssg&0x04))1256SLOT->vol_out = ((UINT32)(0x200 - SLOT->volume) & MAX_ATT_INDEX) + SLOT->tl;1257else1258SLOT->vol_out = (UINT32)SLOT->volume + SLOT->tl;1259}12601261/* next slot */1262SLOT++;1263} while (--j);12641265/* next channel */1266CH++;1267} while (--i);1268}12691270INLINE void update_phase_lfo_slot(FM_SLOT *SLOT, INT32 pms, UINT32 block_fnum)1271{1272INT32 lfo_fn_table_index_offset = lfo_pm_table[(((block_fnum & 0x7f0) >> 4) << 8) + pms + ym2612.OPN.LFO_PM];12731274if (lfo_fn_table_index_offset) /* LFO phase modulation active */1275{1276UINT8 blk;1277unsigned int kc, fc;12781279/* there are 2048 FNUMs that can be generated using FNUM/BLK registers1280but LFO works with one more bit of a precision so we really need 4096 elements */1281block_fnum = block_fnum*2 + lfo_fn_table_index_offset;1282blk = (block_fnum&0x7000) >> 12;1283block_fnum = block_fnum & 0xfff;12841285/* keyscale code */1286kc = (blk<<2) | opn_fktable[block_fnum >> 8];12871288/* (frequency) phase increment counter */1289fc = (((block_fnum << 5) >> (7 - blk)) + SLOT->DT[kc]) & DT_MASK;12901291/* update phase */1292SLOT->phase += (fc * SLOT->mul) >> 1;1293}1294else /* LFO phase modulation = zero */1295{1296SLOT->phase += SLOT->Incr;1297}1298}12991300INLINE void update_phase_lfo_channel(FM_CH *CH)1301{1302UINT32 block_fnum = CH->block_fnum;13031304INT32 lfo_fn_table_index_offset = lfo_pm_table[(((block_fnum & 0x7f0) >> 4) << 8) + CH->pms + ym2612.OPN.LFO_PM];13051306if (lfo_fn_table_index_offset) /* LFO phase modulation active */1307{1308UINT8 blk;1309unsigned int kc, fc, finc;13101311/* there are 2048 FNUMs that can be generated using FNUM/BLK registers1312but LFO works with one more bit of a precision so we really need 4096 elements */1313block_fnum = block_fnum*2 + lfo_fn_table_index_offset;1314blk = (block_fnum&0x7000) >> 12;1315block_fnum = block_fnum & 0xfff;13161317/* keyscale code */1318kc = (blk<<2) | opn_fktable[block_fnum >> 8];13191320/* (frequency) phase increment counter */1321fc = (block_fnum << 5) >> (7 - blk);13221323/* apply DETUNE & MUL operator specific values */1324finc = (fc + CH->SLOT[SLOT1].DT[kc]) & DT_MASK;1325CH->SLOT[SLOT1].phase += (finc*CH->SLOT[SLOT1].mul) >> 1;13261327finc = (fc + CH->SLOT[SLOT2].DT[kc]) & DT_MASK;1328CH->SLOT[SLOT2].phase += (finc*CH->SLOT[SLOT2].mul) >> 1;13291330finc = (fc + CH->SLOT[SLOT3].DT[kc]) & DT_MASK;1331CH->SLOT[SLOT3].phase += (finc*CH->SLOT[SLOT3].mul) >> 1;13321333finc = (fc + CH->SLOT[SLOT4].DT[kc]) & DT_MASK;1334CH->SLOT[SLOT4].phase += (finc*CH->SLOT[SLOT4].mul) >> 1;1335}1336else /* LFO phase modulation = zero */1337{1338CH->SLOT[SLOT1].phase += CH->SLOT[SLOT1].Incr;1339CH->SLOT[SLOT2].phase += CH->SLOT[SLOT2].Incr;1340CH->SLOT[SLOT3].phase += CH->SLOT[SLOT3].Incr;1341CH->SLOT[SLOT4].phase += CH->SLOT[SLOT4].Incr;1342}1343}13441345/* update phase increment and envelope generator */1346INLINE void refresh_fc_eg_slot(FM_SLOT *SLOT , unsigned int fc , unsigned int kc )1347{1348/* add detune value */1349fc += SLOT->DT[kc];13501351/* (frequency) phase overflow (credits to Nemesis) */1352fc &= DT_MASK;13531354/* (frequency) phase increment counter */1355SLOT->Incr = (fc * SLOT->mul) >> 1;13561357/* ksr */1358kc = kc >> SLOT->KSR;13591360if( SLOT->ksr != kc )1361{1362SLOT->ksr = kc;13631364/* recalculate envelope generator rates */1365if ((SLOT->ar + kc) < (32+62))1366{1367SLOT->eg_sh_ar = eg_rate_shift [SLOT->ar + kc ];1368SLOT->eg_sel_ar = eg_rate_select[SLOT->ar + kc ];1369}1370else1371{1372/* verified by Nemesis on real hardware (Attack phase is blocked) */1373SLOT->eg_sh_ar = 0;1374SLOT->eg_sel_ar = 18*RATE_STEPS;1375}13761377SLOT->eg_sh_d1r = eg_rate_shift [SLOT->d1r + kc];1378SLOT->eg_sel_d1r= eg_rate_select[SLOT->d1r + kc];13791380SLOT->eg_sh_d2r = eg_rate_shift [SLOT->d2r + kc];1381SLOT->eg_sel_d2r= eg_rate_select[SLOT->d2r + kc];13821383SLOT->eg_sh_rr = eg_rate_shift [SLOT->rr + kc];1384SLOT->eg_sel_rr = eg_rate_select[SLOT->rr + kc];1385}1386}13871388/* update phase increment counters */1389INLINE void refresh_fc_eg_chan(FM_CH *CH )1390{1391if( CH->SLOT[SLOT1].Incr==-1)1392{1393int fc = CH->fc;1394int kc = CH->kcode;1395refresh_fc_eg_slot(&CH->SLOT[SLOT1] , fc , kc );1396refresh_fc_eg_slot(&CH->SLOT[SLOT2] , fc , kc );1397refresh_fc_eg_slot(&CH->SLOT[SLOT3] , fc , kc );1398refresh_fc_eg_slot(&CH->SLOT[SLOT4] , fc , kc );1399}1400}14011402#define volume_calc(OP) ((OP)->vol_out + (AM & (OP)->AMmask))14031404INLINE signed int op_calc(UINT32 phase, unsigned int env, unsigned int pm)1405{1406UINT32 p = (env<<3) + sin_tab[ ( (phase >> SIN_BITS) + (pm >> 1) ) & SIN_MASK ];14071408if (p >= TL_TAB_LEN)1409return 0;1410return tl_tab[p];1411}14121413INLINE signed int op_calc1(UINT32 phase, unsigned int env, unsigned int pm)1414{1415UINT32 p = (env<<3) + sin_tab[ ( (phase + pm ) >> SIN_BITS ) & SIN_MASK ];14161417if (p >= TL_TAB_LEN)1418return 0;1419return tl_tab[p];1420}14211422INLINE void chan_calc(FM_CH *CH, int num)1423{1424do1425{1426UINT32 AM = ym2612.OPN.LFO_AM >> CH->ams;1427unsigned int eg_out = volume_calc(&CH->SLOT[SLOT1]);14281429m2 = c1 = c2 = mem = 0;14301431*CH->mem_connect = CH->mem_value; /* restore delayed sample (MEM) value to m2 or c2 */1432{1433INT32 out = CH->op1_out[0] + CH->op1_out[1];1434CH->op1_out[0] = CH->op1_out[1];14351436if( !CH->connect1 ){1437/* algorithm 5 */1438mem = c1 = c2 = CH->op1_out[0];1439}else{1440/* other algorithms */1441*CH->connect1 += CH->op1_out[0];1442}14431444CH->op1_out[1] = 0;1445if( eg_out < ENV_QUIET ) /* SLOT 1 */1446{1447if (!CH->FB)1448out=0;14491450CH->op1_out[1] = op_calc1(CH->SLOT[SLOT1].phase, eg_out, (out<<CH->FB) );1451}1452}14531454eg_out = volume_calc(&CH->SLOT[SLOT3]);1455if( eg_out < ENV_QUIET ) /* SLOT 3 */1456*CH->connect3 += op_calc(CH->SLOT[SLOT3].phase, eg_out, m2);14571458eg_out = volume_calc(&CH->SLOT[SLOT2]);1459if( eg_out < ENV_QUIET ) /* SLOT 2 */1460*CH->connect2 += op_calc(CH->SLOT[SLOT2].phase, eg_out, c1);14611462eg_out = volume_calc(&CH->SLOT[SLOT4]);1463if( eg_out < ENV_QUIET ) /* SLOT 4 */1464*CH->connect4 += op_calc(CH->SLOT[SLOT4].phase, eg_out, c2);146514661467/* store current MEM */1468CH->mem_value = mem;14691470/* update phase counters AFTER output calculations */1471if(CH->pms)1472{1473/* add support for 3 slot mode */1474if ((ym2612.OPN.ST.mode & 0xC0) && (CH == &ym2612.CH[2]))1475{1476update_phase_lfo_slot(&CH->SLOT[SLOT1], CH->pms, ym2612.OPN.SL3.block_fnum[1]);1477update_phase_lfo_slot(&CH->SLOT[SLOT2], CH->pms, ym2612.OPN.SL3.block_fnum[2]);1478update_phase_lfo_slot(&CH->SLOT[SLOT3], CH->pms, ym2612.OPN.SL3.block_fnum[0]);1479update_phase_lfo_slot(&CH->SLOT[SLOT4], CH->pms, CH->block_fnum);1480}1481else1482{1483update_phase_lfo_channel(CH);1484}1485}1486else /* no LFO phase modulation */1487{1488CH->SLOT[SLOT1].phase += CH->SLOT[SLOT1].Incr;1489CH->SLOT[SLOT2].phase += CH->SLOT[SLOT2].Incr;1490CH->SLOT[SLOT3].phase += CH->SLOT[SLOT3].Incr;1491CH->SLOT[SLOT4].phase += CH->SLOT[SLOT4].Incr;1492}14931494/* next channel */1495CH++;1496} while (--num);1497}14981499/* write a OPN mode register 0x20-0x2f */1500INLINE void OPNWriteMode(int r, int v)1501{1502UINT8 c;1503FM_CH *CH;15041505switch(r){1506case 0x21: /* Test */1507break;15081509case 0x22: /* LFO FREQ (YM2608/YM2610/YM2610B/ym2612) */1510if (v&8) /* LFO enabled ? */1511{1512ym2612.OPN.lfo_timer_overflow = lfo_samples_per_step[v&7];1513}1514else1515{1516/* hold LFO waveform in reset state */1517ym2612.OPN.lfo_timer_overflow = 0;1518ym2612.OPN.lfo_timer = 0;1519ym2612.OPN.lfo_cnt = 0;1520ym2612.OPN.LFO_PM = 0;1521ym2612.OPN.LFO_AM = 126;1522}1523break;1524case 0x24: /* timer A High 8*/1525ym2612.OPN.ST.TA = (ym2612.OPN.ST.TA & 0x03)|(((int)v)<<2);1526ym2612.OPN.ST.TAL = 1024 - ym2612.OPN.ST.TA;1527break;1528case 0x25: /* timer A Low 2*/1529ym2612.OPN.ST.TA = (ym2612.OPN.ST.TA & 0x3fc)|(v&3);1530ym2612.OPN.ST.TAL = 1024 - ym2612.OPN.ST.TA;1531break;1532case 0x26: /* timer B */1533ym2612.OPN.ST.TB = v;1534ym2612.OPN.ST.TBL = (256 - v) << 4;1535break;1536case 0x27: /* mode, timer control */1537set_timers(v);1538break;1539case 0x28: /* key on / off */1540c = v & 0x03;1541if( c == 3 ) break;1542if (v&0x04) c+=3; /* CH 4-6 */1543CH = &ym2612.CH[c];15441545if (v&0x10) FM_KEYON(CH,SLOT1); else FM_KEYOFF(CH,SLOT1);1546if (v&0x20) FM_KEYON(CH,SLOT2); else FM_KEYOFF(CH,SLOT2);1547if (v&0x40) FM_KEYON(CH,SLOT3); else FM_KEYOFF(CH,SLOT3);1548if (v&0x80) FM_KEYON(CH,SLOT4); else FM_KEYOFF(CH,SLOT4);1549break;1550}1551}15521553/* write a OPN register (0x30-0xff) */1554INLINE void OPNWriteReg(int r, int v)1555{1556FM_CH *CH;1557FM_SLOT *SLOT;15581559UINT8 c = OPN_CHAN(r);15601561if (c == 3) return; /* 0xX3,0xX7,0xXB,0xXF */15621563if (r >= 0x100) c+=3;15641565CH = &ym2612.CH[c];15661567SLOT = &(CH->SLOT[OPN_SLOT(r)]);15681569switch( r & 0xf0 ) {1570case 0x30: /* DET , MUL */1571set_det_mul(CH,SLOT,v);1572break;15731574case 0x40: /* TL */1575set_tl(SLOT,v);1576break;15771578case 0x50: /* KS, AR */1579set_ar_ksr(CH,SLOT,v);1580break;15811582case 0x60: /* bit7 = AM ENABLE, DR */1583set_dr(SLOT,v);1584SLOT->AMmask = (v&0x80) ? ~0 : 0;1585break;15861587case 0x70: /* SR */1588set_sr(SLOT,v);1589break;15901591case 0x80: /* SL, RR */1592set_sl_rr(SLOT,v);1593break;15941595case 0x90: /* SSG-EG */1596SLOT->ssg = v&0x0f;15971598/* recalculate EG output */1599if (SLOT->state > EG_REL)1600{1601if ((SLOT->ssg&0x08) && (SLOT->ssgn ^ (SLOT->ssg&0x04)))1602SLOT->vol_out = ((UINT32)(0x200 - SLOT->volume) & MAX_ATT_INDEX) + SLOT->tl;1603else1604SLOT->vol_out = (UINT32)SLOT->volume + SLOT->tl;1605}16061607/* SSG-EG envelope shapes :16081609E AtAlH16101 0 0 0 \\\\161116121 0 0 1 \___161316141 0 1 0 \/\/1615___16161 0 1 1 \161716181 1 0 0 ////1619___16201 1 0 1 /162116221 1 1 0 /\/\162316241 1 1 1 /___162516261627E = SSG-EG enable162816291630The shapes are generated using Attack, Decay and Sustain phases.16311632Each single character in the diagrams above represents this whole1633sequence:16341635- when KEY-ON = 1, normal Attack phase is generated (*without* any1636difference when compared to normal mode),16371638- later, when envelope level reaches minimum level (max volume),1639the EG switches to Decay phase (which works with bigger steps1640when compared to normal mode - see below),16411642- later when envelope level passes the SL level,1643the EG swithes to Sustain phase (which works with bigger steps1644when compared to normal mode - see below),16451646- finally when envelope level reaches maximum level (min volume),1647the EG switches to Attack phase again (depends on actual waveform).16481649Important is that when switch to Attack phase occurs, the phase counter1650of that operator will be zeroed-out (as in normal KEY-ON) but not always.1651(I havent found the rule for that - perhaps only when the output level is low)16521653The difference (when compared to normal Envelope Generator mode) is1654that the resolution in Decay and Sustain phases is 4 times lower;1655this results in only 256 steps instead of normal 1024.1656In other words:1657when SSG-EG is disabled, the step inside of the EG is one,1658when SSG-EG is enabled, the step is four (in Decay and Sustain phases).16591660Times between the level changes are the same in both modes.166116621663Important:1664Decay 1 Level (so called SL) is compared to actual SSG-EG output, so1665it is the same in both SSG and no-SSG modes, with this exception:16661667when the SSG-EG is enabled and is generating raising levels1668(when the EG output is inverted) the SL will be found at wrong level !!!1669For example, when SL=02:16700 -6 = -6dB in non-inverted EG output167196-6 = -90dB in inverted EG output1672Which means that EG compares its level to SL as usual, and that the1673output is simply inverted afterall.167416751676The Yamaha's manuals say that AR should be set to 0x1f (max speed).1677That is not necessary, but then EG will be generating Attack phase.16781679*/168016811682break;16831684case 0xa0:1685switch( OPN_SLOT(r) ){1686case 0: /* 0xa0-0xa2 : FNUM1 */1687{1688UINT32 fn = (((UINT32)((ym2612.OPN.ST.fn_h)&7))<<8) + v;1689UINT8 blk = ym2612.OPN.ST.fn_h>>3;1690/* keyscale code */1691CH->kcode = (blk<<2) | opn_fktable[fn >> 7];1692/* phase increment counter */1693CH->fc = (fn << 6) >> (7 - blk);16941695/* store fnum in clear form for LFO PM calculations */1696CH->block_fnum = (blk<<11) | fn;16971698CH->SLOT[SLOT1].Incr=-1;1699break;1700}1701case 1: /* 0xa4-0xa6 : FNUM2,BLK */1702ym2612.OPN.ST.fn_h = v&0x3f;1703break;1704case 2: /* 0xa8-0xaa : 3CH FNUM1 */1705if(r < 0x100)1706{1707UINT32 fn = (((UINT32)(ym2612.OPN.SL3.fn_h&7))<<8) + v;1708UINT8 blk = ym2612.OPN.SL3.fn_h>>3;1709/* keyscale code */1710ym2612.OPN.SL3.kcode[c]= (blk<<2) | opn_fktable[fn >> 7];1711/* phase increment counter */1712ym2612.OPN.SL3.fc[c] = (fn << 6) >> (7 - blk);1713ym2612.OPN.SL3.block_fnum[c] = (blk<<11) | fn;1714ym2612.CH[2].SLOT[SLOT1].Incr=-1;1715}1716break;1717case 3: /* 0xac-0xae : 3CH FNUM2,BLK */1718if(r < 0x100)1719ym2612.OPN.SL3.fn_h = v&0x3f;1720break;1721}1722break;17231724case 0xb0:1725switch( OPN_SLOT(r) ){1726case 0: /* 0xb0-0xb2 : FB,ALGO */1727{1728CH->ALGO = v&7;1729CH->FB = (v>>3)&7;1730setup_connection( CH, c );1731break;1732}1733case 1: /* 0xb4-0xb6 : L , R , AMS , PMS */1734/* b0-2 PMS */1735CH->pms = (v & 7) * 32; /* CH->pms = PM depth * 32 (index in lfo_pm_table) */17361737/* b4-5 AMS */1738CH->ams = lfo_ams_depth_shift[(v>>4) & 0x03];17391740/* PAN : b7 = L, b6 = R */1741ym2612.OPN.pan[ c*2 ] = (v & 0x80) ? bitmask : 0;1742ym2612.OPN.pan[ c*2+1 ] = (v & 0x40) ? bitmask : 0;1743break;1744}1745break;1746}1747}17481749static void reset_channels(FM_CH *CH , int num )1750{1751int c,s;17521753for( c = 0 ; c < num ; c++ )1754{1755CH[c].mem_value = 0;1756CH[c].op1_out[0] = 0;1757CH[c].op1_out[1] = 0;1758for(s = 0 ; s < 4 ; s++ )1759{1760CH[c].SLOT[s].Incr = -1;1761CH[c].SLOT[s].key = 0;1762CH[c].SLOT[s].phase = 0;1763CH[c].SLOT[s].ssgn = 0;1764CH[c].SLOT[s].state = EG_OFF;1765CH[c].SLOT[s].volume = MAX_ATT_INDEX;1766CH[c].SLOT[s].vol_out = MAX_ATT_INDEX;1767}1768}1769}17701771/* initialize generic tables */1772static void init_tables(void)1773{1774signed int d,i,x;1775signed int n;1776double o,m;17771778/* build Linear Power Table */1779for (x=0; x<TL_RES_LEN; x++)1780{1781m = (1<<16) / pow(2,(x+1) * (ENV_STEP/4.0) / 8.0);1782m = floor(m);17831784/* we never reach (1<<16) here due to the (x+1) */1785/* result fits within 16 bits at maximum */17861787n = (int)m; /* 16 bits here */1788n >>= 4; /* 12 bits here */1789if (n&1) /* round to nearest */1790n = (n>>1)+1;1791else1792n = n>>1;1793/* 11 bits here (rounded) */1794n <<= 2; /* 13 bits here (as in real chip) */17951796/* 14 bits (with sign bit) */1797tl_tab[ x*2 + 0 ] = n;1798tl_tab[ x*2 + 1 ] = -tl_tab[ x*2 + 0 ];17991800/* one entry in the 'Power' table use the following format, xxxxxyyyyyyyys with: */1801/* s = sign bit */1802/* yyyyyyyy = 8-bits decimal part (0-TL_RES_LEN) */1803/* xxxxx = 5-bits integer 'shift' value (0-31) but, since Power table output is 13 bits, */1804/* any value above 13 (included) would be discarded. */1805for (i=1; i<13; i++)1806{1807tl_tab[ x*2+0 + i*2*TL_RES_LEN ] = tl_tab[ x*2+0 ]>>i;1808tl_tab[ x*2+1 + i*2*TL_RES_LEN ] = -tl_tab[ x*2+0 + i*2*TL_RES_LEN ];1809}1810}18111812/* build Logarithmic Sinus table */1813for (i=0; i<SIN_LEN; i++)1814{1815/* non-standard sinus */1816m = sin( ((i*2)+1) * M_PI / SIN_LEN ); /* checked against the real chip */1817/* we never reach zero here due to ((i*2)+1) */18181819if (m>0.0)1820o = 8*log(1.0/m)/log(2); /* convert to 'decibels' */1821else1822o = 8*log(-1.0/m)/log(2); /* convert to 'decibels' */18231824o = o / (ENV_STEP/4);18251826n = (int)(2.0*o);1827if (n&1) /* round to nearest */1828n = (n>>1)+1;1829else1830n = n>>1;18311832/* 13-bits (8.5) value is formatted for above 'Power' table */1833sin_tab[ i ] = n*2 + (m>=0.0? 0: 1 );1834}18351836/* build LFO PM modulation table */1837for(i = 0; i < 8; i++) /* 8 PM depths */1838{1839UINT8 fnum;1840for (fnum=0; fnum<128; fnum++) /* 7 bits meaningful of F-NUMBER */1841{1842UINT8 value;1843UINT8 step;1844UINT32 offset_depth = i;1845UINT32 offset_fnum_bit;1846UINT32 bit_tmp;18471848for (step=0; step<8; step++)1849{1850value = 0;1851for (bit_tmp=0; bit_tmp<7; bit_tmp++) /* 7 bits */1852{1853if (fnum & (1<<bit_tmp)) /* only if bit "bit_tmp" is set */1854{1855offset_fnum_bit = bit_tmp * 8;1856value += lfo_pm_output[offset_fnum_bit + offset_depth][step];1857}1858}1859/* 32 steps for LFO PM (sinus) */1860lfo_pm_table[(fnum*32*8) + (i*32) + step + 0] = value;1861lfo_pm_table[(fnum*32*8) + (i*32) +(step^7)+ 8] = value;1862lfo_pm_table[(fnum*32*8) + (i*32) + step +16] = -value;1863lfo_pm_table[(fnum*32*8) + (i*32) +(step^7)+24] = -value;1864}1865}1866}18671868/* build DETUNE table */1869for (d = 0;d <= 3;d++)1870{1871for (i = 0;i <= 31;i++)1872{1873ym2612.OPN.ST.dt_tab[d][i] = (INT32) dt_tab[d*32 + i];1874ym2612.OPN.ST.dt_tab[d+4][i] = -ym2612.OPN.ST.dt_tab[d][i];1875}1876}18771878}1879188018811882/* initialize ym2612 emulator */1883void YM2612Init(void)1884{1885memset(&ym2612,0,sizeof(YM2612));1886init_tables();1887}18881889/* reset OPN registers */1890void YM2612ResetChip(void)1891{1892int i;18931894ym2612.OPN.eg_timer = 0;1895ym2612.OPN.eg_cnt = 0;18961897ym2612.OPN.lfo_timer_overflow = 0;1898ym2612.OPN.lfo_timer = 0;1899ym2612.OPN.lfo_cnt = 0;1900ym2612.OPN.LFO_AM = 126;1901ym2612.OPN.LFO_PM = 0;19021903ym2612.OPN.ST.TAC = 0;1904ym2612.OPN.ST.TBC = 0;19051906ym2612.OPN.SL3.key_csm = 0;19071908ym2612.dacen = 0;1909ym2612.dacout = 0;19101911set_timers(0x30);1912ym2612.OPN.ST.TB = 0;1913ym2612.OPN.ST.TBL = 256 << 4;1914ym2612.OPN.ST.TA = 0;1915ym2612.OPN.ST.TAL = 1024;19161917reset_channels(&ym2612.CH[0] , 6 );19181919for(i = 0xb6 ; i >= 0xb4 ; i-- )1920{1921OPNWriteReg(i ,0xc0);1922OPNWriteReg(i|0x100,0xc0);1923}1924for(i = 0xb2 ; i >= 0x30 ; i-- )1925{1926OPNWriteReg(i ,0);1927OPNWriteReg(i|0x100,0);1928}1929}19301931/* ym2612 write */1932/* n = number */1933/* a = address */1934/* v = value */1935void YM2612Write(unsigned int a, unsigned int v)1936{1937v &= 0xff; /* adjust to 8 bit bus */19381939switch( a )1940{1941case 0: /* address port 0 */1942ym2612.OPN.ST.address = v;1943break;19441945case 2: /* address port 1 */1946ym2612.OPN.ST.address = v | 0x100;1947break;19481949default: /* data port */1950{1951int addr = ym2612.OPN.ST.address; /* verified by Nemesis on real YM2612 */1952switch( addr & 0x1f0 )1953{1954case 0x20: /* 0x20-0x2f Mode */1955switch( addr )1956{1957case 0x2a: /* DAC data (ym2612) */1958ym2612.dacout = ((int)v - 0x80) << 6; /* convert to 14-bit output */1959break;1960case 0x2b: /* DAC Sel (ym2612) */1961/* b7 = dac enable */1962ym2612.dacen = v & 0x80;1963break;1964default: /* OPN section */1965/* write register */1966OPNWriteMode(addr,v);1967}1968break;1969default: /* 0x30-0xff OPN section */1970/* write register */1971OPNWriteReg(addr,v);1972}1973break;1974}1975}1976}19771978unsigned int YM2612Read(void)1979{1980return ym2612.OPN.ST.status & 0xff;1981}19821983/* Generate samples for ym2612 */1984void YM2612Update(int *buffer, int length)1985{1986int i;1987int lt,rt;19881989/* refresh PG increments and EG rates if required */1990refresh_fc_eg_chan(&ym2612.CH[0]);1991refresh_fc_eg_chan(&ym2612.CH[1]);19921993if (!(ym2612.OPN.ST.mode & 0xC0))1994{1995refresh_fc_eg_chan(&ym2612.CH[2]);1996}1997else1998{1999/* 3SLOT MODE (operator order is 0,1,3,2) */2000if(ym2612.CH[2].SLOT[SLOT1].Incr==-1)2001{2002refresh_fc_eg_slot(&ym2612.CH[2].SLOT[SLOT1] , ym2612.OPN.SL3.fc[1] , ym2612.OPN.SL3.kcode[1] );2003refresh_fc_eg_slot(&ym2612.CH[2].SLOT[SLOT2] , ym2612.OPN.SL3.fc[2] , ym2612.OPN.SL3.kcode[2] );2004refresh_fc_eg_slot(&ym2612.CH[2].SLOT[SLOT3] , ym2612.OPN.SL3.fc[0] , ym2612.OPN.SL3.kcode[0] );2005refresh_fc_eg_slot(&ym2612.CH[2].SLOT[SLOT4] , ym2612.CH[2].fc , ym2612.CH[2].kcode );2006}2007}20082009refresh_fc_eg_chan(&ym2612.CH[3]);2010refresh_fc_eg_chan(&ym2612.CH[4]);2011refresh_fc_eg_chan(&ym2612.CH[5]);20122013/* buffering */2014for(i=0; i < length ; i++)2015{2016/* clear outputs */2017out_fm[0] = 0;2018out_fm[1] = 0;2019out_fm[2] = 0;2020out_fm[3] = 0;2021out_fm[4] = 0;2022out_fm[5] = 0;20232024/* update SSG-EG output */2025update_ssg_eg_channels(&ym2612.CH[0]);20262027/* calculate FM */2028if (!ym2612.dacen)2029{2030chan_calc(&ym2612.CH[0],6);2031}2032else2033{2034/* DAC Mode */2035out_fm[5] = ym2612.dacout;2036chan_calc(&ym2612.CH[0],5);2037}20382039/* advance LFO */2040advance_lfo();20412042/* advance envelope generator */2043ym2612.OPN.eg_timer ++;20442045/* EG is updated every 3 samples */2046if (ym2612.OPN.eg_timer >= 3)2047{2048ym2612.OPN.eg_timer = 0;2049ym2612.OPN.eg_cnt++;2050advance_eg_channels(&ym2612.CH[0], ym2612.OPN.eg_cnt);2051}20522053/* 14-bit accumulator channels outputs (range is -8192;+8192) */2054if (out_fm[0] > 8192) out_fm[0] = 8192;2055else if (out_fm[0] < -8192) out_fm[0] = -8192;2056if (out_fm[1] > 8192) out_fm[1] = 8192;2057else if (out_fm[1] < -8192) out_fm[1] = -8192;2058if (out_fm[2] > 8192) out_fm[2] = 8192;2059else if (out_fm[2] < -8192) out_fm[2] = -8192;2060if (out_fm[3] > 8192) out_fm[3] = 8192;2061else if (out_fm[3] < -8192) out_fm[3] = -8192;2062if (out_fm[4] > 8192) out_fm[4] = 8192;2063else if (out_fm[4] < -8192) out_fm[4] = -8192;2064if (out_fm[5] > 8192) out_fm[5] = 8192;2065else if (out_fm[5] < -8192) out_fm[5] = -8192;20662067/* stereo DAC channels outputs mixing */2068lt = ((out_fm[0]) & ym2612.OPN.pan[0]);2069rt = ((out_fm[0]) & ym2612.OPN.pan[1]);2070lt += ((out_fm[1]) & ym2612.OPN.pan[2]);2071rt += ((out_fm[1]) & ym2612.OPN.pan[3]);2072lt += ((out_fm[2]) & ym2612.OPN.pan[4]);2073rt += ((out_fm[2]) & ym2612.OPN.pan[5]);2074lt += ((out_fm[3]) & ym2612.OPN.pan[6]);2075rt += ((out_fm[3]) & ym2612.OPN.pan[7]);2076lt += ((out_fm[4]) & ym2612.OPN.pan[8]);2077rt += ((out_fm[4]) & ym2612.OPN.pan[9]);2078lt += ((out_fm[5]) & ym2612.OPN.pan[10]);2079rt += ((out_fm[5]) & ym2612.OPN.pan[11]);20802081/* buffering */2082*buffer++ = lt;2083*buffer++ = rt;20842085/* CSM mode: if CSM Key ON has occured, CSM Key OFF need to be sent */2086/* only if Timer A does not overflow again (i.e CSM Key ON not set again) */2087ym2612.OPN.SL3.key_csm <<= 1;20882089/* timer A control */2090INTERNAL_TIMER_A();20912092/* CSM Mode Key ON still disabled */2093if (ym2612.OPN.SL3.key_csm & 2)2094{2095/* CSM Mode Key OFF (verified by Nemesis on real hardware) */2096FM_KEYOFF_CSM(&ym2612.CH[2],SLOT1);2097FM_KEYOFF_CSM(&ym2612.CH[2],SLOT2);2098FM_KEYOFF_CSM(&ym2612.CH[2],SLOT3);2099FM_KEYOFF_CSM(&ym2612.CH[2],SLOT4);2100ym2612.OPN.SL3.key_csm = 0;2101}2102}21032104/* timer B control */2105INTERNAL_TIMER_B(length);2106}21072108void YM2612Config(unsigned char dac_bits)2109{2110int i;21112112/* DAC precision (normally 9-bit on real hardware, implemented through simple 14-bit channel output bitmasking) */2113bitmask = ~((1 << (TL_BITS - dac_bits)) - 1);21142115/* update L/R panning bitmasks */2116for (i=0; i<2*6; i++)2117{2118if (ym2612.OPN.pan[i])2119{2120ym2612.OPN.pan[i] = bitmask;2121}2122}2123}21242125int YM2612LoadContext(unsigned char *state)2126{2127int c,s;2128uint8 index;2129int bufferptr = 0;21302131/* restore YM2612 context */2132load_param(&ym2612, sizeof(ym2612));21332134/* restore DT table address pointer for each channel slots */2135for (c=0; c<6; c++)2136{2137for (s=0; s<4; s++)2138{2139load_param(&index,sizeof(index));2140bufferptr += sizeof(index);2141ym2612.CH[c].SLOT[s].DT = ym2612.OPN.ST.dt_tab[index&7];2142}2143}21442145/* restore outputs connections */2146setup_connection(&ym2612.CH[0],0);2147setup_connection(&ym2612.CH[1],1);2148setup_connection(&ym2612.CH[2],2);2149setup_connection(&ym2612.CH[3],3);2150setup_connection(&ym2612.CH[4],4);2151setup_connection(&ym2612.CH[5],5);21522153return bufferptr;2154}21552156int YM2612SaveContext(unsigned char *state)2157{2158int c,s;2159uint8 index;2160int bufferptr = 0;21612162/* save YM2612 context */2163save_param(&ym2612, sizeof(ym2612));21642165/* save DT table index for each channel slots */2166for (c=0; c<6; c++)2167{2168for (s=0; s<4; s++)2169{2170index = (ym2612.CH[c].SLOT[s].DT - ym2612.OPN.ST.dt_tab[0]) >> 5;2171save_param(&index,sizeof(index));2172bufferptr += sizeof(index);2173}2174}21752176return bufferptr;2177}217821792180