| | 1 | /*\r |
| | 2 | ** This is a bunch of remains of original fm.c from MAME project. All stuff\r |
| | 3 | ** unrelated to ym2612 was removed, multiple chip support was removed,\r |
| | 4 | ** some parts of code were slightly rewritten and tied to the emulator.\r |
| | 5 | **\r |
| | 6 | ** SSG-EG was also removed, because it's rarely used, Sega2.doc even does not\r |
| | 7 | ** document it ("proprietary") and tells to write 0 to SSG-EG control register.\r |
| | 8 | **\r |
| | 9 | ** updated with fixes from mame 0.216 (file version 1.5.1) (kub)\r |
| | 10 | ** SSG-EG readded from GenPlus (kub)\r |
| | 11 | */\r |
| | 12 | \r |
| | 13 | /*\r |
| | 14 | **\r |
| | 15 | ** File: fm.c -- software implementation of Yamaha FM sound generator\r |
| | 16 | **\r |
| | 17 | ** Copyright (C) 2001, 2002, 2003 Jarek Burczynski (bujar at mame dot net)\r |
| | 18 | ** Copyright (C) 1998 Tatsuyuki Satoh , MultiArcadeMachineEmulator development\r |
| | 19 | **\r |
| | 20 | ** Version 1.4 (final beta)\r |
| | 21 | **\r |
| | 22 | */\r |
| | 23 | \r |
| | 24 | /*\r |
| | 25 | ** History:\r |
| | 26 | **\r |
| | 27 | ** 03-08-2003 Jarek Burczynski:\r |
| | 28 | ** - fixed YM2608 initial values (after the reset)\r |
| | 29 | ** - fixed flag and irqmask handling (YM2608)\r |
| | 30 | ** - fixed BUFRDY flag handling (YM2608)\r |
| | 31 | **\r |
| | 32 | ** 14-06-2003 Jarek Burczynski:\r |
| | 33 | ** - implemented all of the YM2608 status register flags\r |
| | 34 | ** - implemented support for external memory read/write via YM2608\r |
| | 35 | ** - implemented support for deltat memory limit register in YM2608 emulation\r |
| | 36 | **\r |
| | 37 | ** 22-05-2003 Jarek Burczynski:\r |
| | 38 | ** - fixed LFO PM calculations (copy&paste bugfix)\r |
| | 39 | **\r |
| | 40 | ** 08-05-2003 Jarek Burczynski:\r |
| | 41 | ** - fixed SSG support\r |
| | 42 | **\r |
| | 43 | ** 22-04-2003 Jarek Burczynski:\r |
| | 44 | ** - implemented 100% correct LFO generator (verified on real YM2610 and YM2608)\r |
| | 45 | **\r |
| | 46 | ** 15-04-2003 Jarek Burczynski:\r |
| | 47 | ** - added support for YM2608's register 0x110 - status mask\r |
| | 48 | **\r |
| | 49 | ** 01-12-2002 Jarek Burczynski:\r |
| | 50 | ** - fixed register addressing in YM2608, YM2610, YM2610B chips. (verified on real YM2608)\r |
| | 51 | ** The addressing patch used for early Neo-Geo games can be removed now.\r |
| | 52 | **\r |
| | 53 | ** 26-11-2002 Jarek Burczynski, Nicola Salmoria:\r |
| | 54 | ** - recreated YM2608 ADPCM ROM using data from real YM2608's output which leads to:\r |
| | 55 | ** - added emulation of YM2608 drums.\r |
| | 56 | ** - output of YM2608 is two times lower now - same as YM2610 (verified on real YM2608)\r |
| | 57 | **\r |
| | 58 | ** 16-08-2002 Jarek Burczynski:\r |
| | 59 | ** - binary exact Envelope Generator (verified on real YM2203);\r |
| | 60 | ** identical to YM2151\r |
| | 61 | ** - corrected 'off by one' error in feedback calculations (when feedback is off)\r |
| | 62 | ** - corrected connection (algorithm) calculation (verified on real YM2203 and YM2610)\r |
| | 63 | **\r |
| | 64 | ** 18-12-2001 Jarek Burczynski:\r |
| | 65 | ** - added SSG-EG support (verified on real YM2203)\r |
| | 66 | **\r |
| | 67 | ** 12-08-2001 Jarek Burczynski:\r |
| | 68 | ** - corrected ym_sin_tab and ym_tl_tab data (verified on real chip)\r |
| | 69 | ** - corrected feedback calculations (verified on real chip)\r |
| | 70 | ** - corrected phase generator calculations (verified on real chip)\r |
| | 71 | ** - corrected envelope generator calculations (verified on real chip)\r |
| | 72 | ** - corrected FM volume level (YM2610 and YM2610B).\r |
| | 73 | ** - changed YMxxxUpdateOne() functions (YM2203, YM2608, YM2610, YM2610B, YM2612) :\r |
| | 74 | ** this was needed to calculate YM2610 FM channels output correctly.\r |
| | 75 | ** (Each FM channel is calculated as in other chips, but the output of the channel\r |
| | 76 | ** gets shifted right by one *before* sending to accumulator. That was impossible to do\r |
| | 77 | ** with previous implementation).\r |
| | 78 | **\r |
| | 79 | ** 23-07-2001 Jarek Burczynski, Nicola Salmoria:\r |
| | 80 | ** - corrected YM2610 ADPCM type A algorithm and tables (verified on real chip)\r |
| | 81 | **\r |
| | 82 | ** 11-06-2001 Jarek Burczynski:\r |
| | 83 | ** - corrected end of sample bug in ADPCMA_calc_cha().\r |
| | 84 | ** Real YM2610 checks for equality between current and end addresses (only 20 LSB bits).\r |
| | 85 | **\r |
| | 86 | ** 08-12-98 hiro-shi:\r |
| | 87 | ** rename ADPCMA -> ADPCMB, ADPCMB -> ADPCMA\r |
| | 88 | ** move ROM limit check.(CALC_CH? -> 2610Write1/2)\r |
| | 89 | ** test program (ADPCMB_TEST)\r |
| | 90 | ** move ADPCM A/B end check.\r |
| | 91 | ** ADPCMB repeat flag(no check)\r |
| | 92 | ** change ADPCM volume rate (8->16) (32->48).\r |
| | 93 | **\r |
| | 94 | ** 09-12-98 hiro-shi:\r |
| | 95 | ** change ADPCM volume. (8->16, 48->64)\r |
| | 96 | ** replace ym2610 ch0/3 (YM-2610B)\r |
| | 97 | ** change ADPCM_SHIFT (10->8) missing bank change 0x4000-0xffff.\r |
| | 98 | ** add ADPCM_SHIFT_MASK\r |
| | 99 | ** change ADPCMA_DECODE_MIN/MAX.\r |
| | 100 | */\r |
| | 101 | \r |
| | 102 | \r |
| | 103 | \r |
| | 104 | \r |
| | 105 | /************************************************************************/\r |
| | 106 | /* comment of hiro-shi(Hiromitsu Shioya) */\r |
| | 107 | /* YM2610(B) = OPN-B */\r |
| | 108 | /* YM2610 : PSG:3ch FM:4ch ADPCM(18.5KHz):6ch DeltaT ADPCM:1ch */\r |
| | 109 | /* YM2610B : PSG:3ch FM:6ch ADPCM(18.5KHz):6ch DeltaT ADPCM:1ch */\r |
| | 110 | /************************************************************************/\r |
| | 111 | \r |
| | 112 | //#include <stdio.h>\r |
| | 113 | \r |
| | 114 | #include <assert.h>\r |
| | 115 | #include <string.h>\r |
| | 116 | #include <math.h>\r |
| | 117 | \r |
| | 118 | #include "../pico_int.h"\r |
| | 119 | #include "ym2612.h"\r |
| | 120 | \r |
| | 121 | #ifndef EXTERNAL_YM2612\r |
| | 122 | #include <stdlib.h>\r |
| | 123 | // let it be 1 global to simplify things\r |
| | 124 | YM2612 ym2612;\r |
| | 125 | \r |
| | 126 | #else\r |
| | 127 | extern YM2612 *ym2612_940;\r |
| | 128 | #define ym2612 (*ym2612_940)\r |
| | 129 | \r |
| | 130 | #endif\r |
| | 131 | \r |
| | 132 | void memset32(void *dest, int c, int count);\r |
| | 133 | \r |
| | 134 | \r |
| | 135 | #ifndef __GNUC__\r |
| | 136 | #pragma warning (disable:4100) // unreferenced formal parameter\r |
| | 137 | #pragma warning (disable:4244)\r |
| | 138 | #pragma warning (disable:4245) // signed/unsigned in conversion\r |
| | 139 | #pragma warning (disable:4710)\r |
| | 140 | #pragma warning (disable:4018) // signed/unsigned\r |
| | 141 | #endif\r |
| | 142 | \r |
| | 143 | #ifndef INLINE\r |
| | 144 | #define INLINE __inline\r |
| | 145 | #endif\r |
| | 146 | \r |
| | 147 | #ifndef M_PI\r |
| | 148 | #define M_PI 3.14159265358979323846\r |
| | 149 | #endif\r |
| | 150 | \r |
| | 151 | \r |
| | 152 | /* globals */\r |
| | 153 | \r |
| | 154 | #define FREQ_SH 16 /* 16.16 fixed point (frequency calculations) */\r |
| | 155 | #define EG_SH 16 /* 16.16 fixed point (envelope generator timing) */\r |
| | 156 | #define LFO_SH 24 /* 8.24 fixed point (LFO calculations) */\r |
| | 157 | \r |
| | 158 | #define ENV_BITS 10\r |
| | 159 | #define ENV_LEN (1<<ENV_BITS)\r |
| | 160 | #define ENV_STEP (128.0/ENV_LEN)\r |
| | 161 | \r |
| | 162 | #define MAX_ATT_INDEX (ENV_LEN-1) /* 1023 */\r |
| | 163 | #define MIN_ATT_INDEX (0) /* 0 */\r |
| | 164 | \r |
| | 165 | #define EG_ATT 4\r |
| | 166 | #define EG_DEC 3\r |
| | 167 | #define EG_SUS 2\r |
| | 168 | #define EG_REL 1\r |
| | 169 | #define EG_OFF 0\r |
| | 170 | \r |
| | 171 | #define SIN_BITS 10\r |
| | 172 | #define SIN_LEN (1<<SIN_BITS)\r |
| | 173 | #define SIN_MASK (SIN_LEN-1)\r |
| | 174 | \r |
| | 175 | #define TL_RES_LEN (256) /* 8 bits addressing (real chip) */\r |
| | 176 | \r |
| | 177 | #define EG_TIMER_OVERFLOW (3*(1<<EG_SH)) /* envelope generator timer overflows every 3 samples (on real chip) */\r |
| | 178 | \r |
| | 179 | /* TL_TAB_LEN is calculated as:\r |
| | 180 | * 13 - sinus amplitude bits (Y axis)\r |
| | 181 | * 2 - sinus sign bit (Y axis)\r |
| | 182 | * TL_RES_LEN - sinus resolution (X axis)\r |
| | 183 | */\r |
| | 184 | //#define TL_TAB_LEN (13*2*TL_RES_LEN)\r |
| | 185 | #define TL_TAB_LEN (13*TL_RES_LEN*256/8) // 106496*2\r |
| | 186 | UINT16 ym_tl_tab[TL_TAB_LEN];\r |
| | 187 | \r |
| | 188 | /* ~3K wasted but oh well */\r |
| | 189 | UINT16 ym_tl_tab2[13*TL_RES_LEN];\r |
| | 190 | \r |
| | 191 | #define ENV_QUIET (2*13*TL_RES_LEN/8)\r |
| | 192 | \r |
| | 193 | /* sin waveform table in 'decibel' scale (use only period/4 values) */\r |
| | 194 | static UINT16 ym_sin_tab[256];\r |
| | 195 | \r |
| | 196 | static int ym_init_tab;\r |
| | 197 | \r |
| | 198 | /* sustain level table (3dB per step) */\r |
| | 199 | /* bit0, bit1, bit2, bit3, bit4, bit5, bit6 */\r |
| | 200 | /* 1, 2, 4, 8, 16, 32, 64 (value)*/\r |
| | 201 | /* 0.75, 1.5, 3, 6, 12, 24, 48 (dB)*/\r |
| | 202 | \r |
| | 203 | /* 0 - 15: 0, 3, 6, 9,12,15,18,21,24,27,30,33,36,39,42,93 (dB)*/\r |
| | 204 | #define SC(db) (UINT32) ( db * (4.0/ENV_STEP) )\r |
| | 205 | static const UINT32 sl_table[16]={\r |
| | 206 | SC( 0),SC( 1),SC( 2),SC(3 ),SC(4 ),SC(5 ),SC(6 ),SC( 7),\r |
| | 207 | SC( 8),SC( 9),SC(10),SC(11),SC(12),SC(13),SC(14),SC(31)\r |
| | 208 | };\r |
| | 209 | #undef SC\r |
| | 210 | \r |
| | 211 | \r |
| | 212 | #if 0\r |
| | 213 | #define RATE_STEPS (8)\r |
| | 214 | static const UINT8 eg_inc[19*RATE_STEPS]={\r |
| | 215 | \r |
| | 216 | /*cycle:0 1 2 3 4 5 6 7*/\r |
| | 217 | \r |
| | 218 | /* 0 */ 0,1, 0,1, 0,1, 0,1, /* rates 00..11 0 (increment by 0 or 1) */\r |
| | 219 | /* 1 */ 0,1, 0,1, 1,1, 0,1, /* rates 00..11 1 */\r |
| | 220 | /* 2 */ 0,1, 1,1, 0,1, 1,1, /* rates 00..11 2 */\r |
| | 221 | /* 3 */ 0,1, 1,1, 1,1, 1,1, /* rates 00..11 3 */\r |
| | 222 | \r |
| | 223 | /* 4 */ 1,1, 1,1, 1,1, 1,1, /* rate 12 0 (increment by 1) */\r |
| | 224 | /* 5 */ 1,1, 1,2, 1,1, 1,2, /* rate 12 1 */\r |
| | 225 | /* 6 */ 1,2, 1,2, 1,2, 1,2, /* rate 12 2 */\r |
| | 226 | /* 7 */ 1,2, 2,2, 1,2, 2,2, /* rate 12 3 */\r |
| | 227 | \r |
| | 228 | /* 8 */ 2,2, 2,2, 2,2, 2,2, /* rate 13 0 (increment by 2) */\r |
| | 229 | /* 9 */ 2,2, 2,4, 2,2, 2,4, /* rate 13 1 */\r |
| | 230 | /*10 */ 2,4, 2,4, 2,4, 2,4, /* rate 13 2 */\r |
| | 231 | /*11 */ 2,4, 4,4, 2,4, 4,4, /* rate 13 3 */\r |
| | 232 | \r |
| | 233 | /*12 */ 4,4, 4,4, 4,4, 4,4, /* rate 14 0 (increment by 4) */\r |
| | 234 | /*13 */ 4,4, 4,8, 4,4, 4,8, /* rate 14 1 */\r |
| | 235 | /*14 */ 4,8, 4,8, 4,8, 4,8, /* rate 14 2 */\r |
| | 236 | /*15 */ 4,8, 8,8, 4,8, 8,8, /* rate 14 3 */\r |
| | 237 | \r |
| | 238 | /*16 */ 8,8, 8,8, 8,8, 8,8, /* rates 15 0, 15 1, 15 2, 15 3 (increment by 8) */\r |
| | 239 | /*17 */ 16,16,16,16,16,16,16,16, /* rates 15 2, 15 3 for attack */\r |
| | 240 | /*18 */ 0,0, 0,0, 0,0, 0,0, /* infinity rates for attack and decay(s) */\r |
| | 241 | };\r |
| | 242 | #endif\r |
| | 243 | \r |
| | 244 | \r |
| | 245 | #define PACK(a0,a1,a2,a3,a4,a5,a6,a7) ((a7<<21)|(a6<<18)|(a5<<15)|(a4<<12)|(a3<<9)|(a2<<6)|(a1<<3)|(a0<<0))\r |
| | 246 | static const UINT32 eg_inc_pack[19] =\r |
| | 247 | {\r |
| | 248 | /* 0 */ PACK(0,1,0,1,0,1,0,1), /* rates 00..11 0 (increment by 0 or 1) */\r |
| | 249 | /* 1 */ PACK(0,1,0,1,1,1,0,1), /* rates 00..11 1 */\r |
| | 250 | /* 2 */ PACK(0,1,1,1,0,1,1,1), /* rates 00..11 2 */\r |
| | 251 | /* 3 */ PACK(0,1,1,1,1,1,1,1), /* rates 00..11 3 */\r |
| | 252 | \r |
| | 253 | /* 4 */ PACK(1,1,1,1,1,1,1,1), /* rate 12 0 (increment by 1) */\r |
| | 254 | /* 5 */ PACK(1,1,1,2,1,1,1,2), /* rate 12 1 */\r |
| | 255 | /* 6 */ PACK(1,2,1,2,1,2,1,2), /* rate 12 2 */\r |
| | 256 | /* 7 */ PACK(1,2,2,2,1,2,2,2), /* rate 12 3 */\r |
| | 257 | \r |
| | 258 | /* 8 */ PACK(2,2,2,2,2,2,2,2), /* rate 13 0 (increment by 2) */\r |
| | 259 | /* 9 */ PACK(2,2,2,3,2,2,2,3), /* rate 13 1 */\r |
| | 260 | /*10 */ PACK(2,3,2,3,2,3,2,3), /* rate 13 2 */\r |
| | 261 | /*11 */ PACK(2,3,3,3,2,3,3,3), /* rate 13 3 */\r |
| | 262 | \r |
| | 263 | /*12 */ PACK(3,3,3,3,3,3,3,3), /* rate 14 0 (increment by 4) */\r |
| | 264 | /*13 */ PACK(3,3,3,4,3,3,3,4), /* rate 14 1 */\r |
| | 265 | /*14 */ PACK(3,4,3,4,3,4,3,4), /* rate 14 2 */\r |
| | 266 | /*15 */ PACK(3,4,4,4,3,4,4,4), /* rate 14 3 */\r |
| | 267 | \r |
| | 268 | /*16 */ PACK(4,4,4,4,4,4,4,4), /* rates 15 0, 15 1, 15 2, 15 3 (increment by 8) */\r |
| | 269 | /*17 */ PACK(5,5,5,5,5,5,5,5), /* rates 15 2, 15 3 for attack */\r |
| | 270 | /*18 */ PACK(0,0,0,0,0,0,0,0), /* infinity rates for attack and decay(s) */\r |
| | 271 | };\r |
| | 272 | \r |
| | 273 | \r |
| | 274 | //#define O(a) (a*RATE_STEPS)\r |
| | 275 | #define O(a) a\r |
| | 276 | \r |
| | 277 | /*note that there is no O(17) in this table - it's directly in the code */\r |
| | 278 | static const UINT8 eg_rate_select[32+64+32]={ /* Envelope Generator rates (32 + 64 rates + 32 RKS) */\r |
| | 279 | /* 32 infinite time rates */\r |
| | 280 | O(18),O(18),O(18),O(18),O(18),O(18),O(18),O(18),\r |
| | 281 | O(18),O(18),O(18),O(18),O(18),O(18),O(18),O(18),\r |
| | 282 | O(18),O(18),O(18),O(18),O(18),O(18),O(18),O(18),\r |
| | 283 | O(18),O(18),O(18),O(18),O(18),O(18),O(18),O(18),\r |
| | 284 | \r |
| | 285 | /* rates 00-11 */\r |
| | 286 | O(18),O(18),O( 2),O( 3),\r |
| | 287 | O( 0),O( 1),O( 2),O( 3),\r |
| | 288 | O( 0),O( 1),O( 2),O( 3),\r |
| | 289 | O( 0),O( 1),O( 2),O( 3),\r |
| | 290 | O( 0),O( 1),O( 2),O( 3),\r |
| | 291 | O( 0),O( 1),O( 2),O( 3),\r |
| | 292 | O( 0),O( 1),O( 2),O( 3),\r |
| | 293 | O( 0),O( 1),O( 2),O( 3),\r |
| | 294 | O( 0),O( 1),O( 2),O( 3),\r |
| | 295 | O( 0),O( 1),O( 2),O( 3),\r |
| | 296 | O( 0),O( 1),O( 2),O( 3),\r |
| | 297 | O( 0),O( 1),O( 2),O( 3),\r |
| | 298 | \r |
| | 299 | /* rate 12 */\r |
| | 300 | O( 4),O( 5),O( 6),O( 7),\r |
| | 301 | \r |
| | 302 | /* rate 13 */\r |
| | 303 | O( 8),O( 9),O(10),O(11),\r |
| | 304 | \r |
| | 305 | /* rate 14 */\r |
| | 306 | O(12),O(13),O(14),O(15),\r |
| | 307 | \r |
| | 308 | /* rate 15 */\r |
| | 309 | O(16),O(16),O(16),O(16),\r |
| | 310 | \r |
| | 311 | /* 32 dummy rates (same as 15 3) */\r |
| | 312 | O(16),O(16),O(16),O(16),O(16),O(16),O(16),O(16),\r |
| | 313 | O(16),O(16),O(16),O(16),O(16),O(16),O(16),O(16),\r |
| | 314 | O(16),O(16),O(16),O(16),O(16),O(16),O(16),O(16),\r |
| | 315 | O(16),O(16),O(16),O(16),O(16),O(16),O(16),O(16)\r |
| | 316 | \r |
| | 317 | };\r |
| | 318 | #undef O\r |
| | 319 | \r |
| | 320 | /*rate 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15*/\r |
| | 321 | /*shift 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 0, 0, 0, 0, 0 */\r |
| | 322 | /*mask 2047, 1023, 511, 255, 127, 63, 31, 15, 7, 3, 1, 0, 0, 0, 0, 0 */\r |
| | 323 | \r |
| | 324 | #define O(a) (a*1)\r |
| | 325 | static const UINT8 eg_rate_shift[32+64+32]={ /* Envelope Generator counter shifts (32 + 64 rates + 32 RKS) */\r |
| | 326 | /* 32 infinite time rates */\r |
| | 327 | O(11),O(11),O(11),O(11),O(11),O(11),O(11),O(11),\r |
| | 328 | O(11),O(11),O(11),O(11),O(11),O(11),O(11),O(11),\r |
| | 329 | O(11),O(11),O(11),O(11),O(11),O(11),O(11),O(11),\r |
| | 330 | O(11),O(11),O(11),O(11),O(11),O(11),O(11),O(11),\r |
| | 331 | \r |
| | 332 | /* rates 00-11 */\r |
| | 333 | O(11),O(11),O(11),O(11),\r |
| | 334 | O(10),O(10),O(10),O(10),\r |
| | 335 | O( 9),O( 9),O( 9),O( 9),\r |
| | 336 | O( 8),O( 8),O( 8),O( 8),\r |
| | 337 | O( 7),O( 7),O( 7),O( 7),\r |
| | 338 | O( 6),O( 6),O( 6),O( 6),\r |
| | 339 | O( 5),O( 5),O( 5),O( 5),\r |
| | 340 | O( 4),O( 4),O( 4),O( 4),\r |
| | 341 | O( 3),O( 3),O( 3),O( 3),\r |
| | 342 | O( 2),O( 2),O( 2),O( 2),\r |
| | 343 | O( 1),O( 1),O( 1),O( 1),\r |
| | 344 | O( 0),O( 0),O( 0),O( 0),\r |
| | 345 | \r |
| | 346 | /* rate 12 */\r |
| | 347 | O( 0),O( 0),O( 0),O( 0),\r |
| | 348 | \r |
| | 349 | /* rate 13 */\r |
| | 350 | O( 0),O( 0),O( 0),O( 0),\r |
| | 351 | \r |
| | 352 | /* rate 14 */\r |
| | 353 | O( 0),O( 0),O( 0),O( 0),\r |
| | 354 | \r |
| | 355 | /* rate 15 */\r |
| | 356 | O( 0),O( 0),O( 0),O( 0),\r |
| | 357 | \r |
| | 358 | /* 32 dummy rates (same as 15 3) */\r |
| | 359 | O( 0),O( 0),O( 0),O( 0),O( 0),O( 0),O( 0),O( 0),\r |
| | 360 | O( 0),O( 0),O( 0),O( 0),O( 0),O( 0),O( 0),O( 0),\r |
| | 361 | O( 0),O( 0),O( 0),O( 0),O( 0),O( 0),O( 0),O( 0),\r |
| | 362 | O( 0),O( 0),O( 0),O( 0),O( 0),O( 0),O( 0),O( 0)\r |
| | 363 | \r |
| | 364 | };\r |
| | 365 | #undef O\r |
| | 366 | \r |
| | 367 | static const UINT8 dt_tab[4 * 32]={\r |
| | 368 | /* this is YM2151 and YM2612 phase increment data (in 10.10 fixed point format)*/\r |
| | 369 | /* FD=0 */\r |
| | 370 | 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\r |
| | 371 | 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\r |
| | 372 | /* FD=1 */\r |
| | 373 | 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 2, 2, 2, 2,\r |
| | 374 | 2, 3, 3, 3, 4, 4, 4, 5, 5, 6, 6, 7, 8, 8, 8, 8,\r |
| | 375 | /* FD=2 */\r |
| | 376 | 1, 1, 1, 1, 2, 2, 2, 2, 2, 3, 3, 3, 4, 4, 4, 5,\r |
| | 377 | 5, 6, 6, 7, 8, 8, 9,10,11,12,13,14,16,16,16,16,\r |
| | 378 | /* FD=3 */\r |
| | 379 | 2, 2, 2, 2, 2, 3, 3, 3, 4, 4, 4, 5, 5, 6, 6, 7,\r |
| | 380 | 8 ,8, 9,10,11,12,13,14,16,17,19,20,22,22,22,22\r |
| | 381 | };\r |
| | 382 | \r |
| | 383 | \r |
| | 384 | /* OPN key frequency number -> key code follow table */\r |
| | 385 | /* fnum higher 4bit -> keycode lower 2bit */\r |
| | 386 | static const UINT8 opn_fktable[16] = {0,0,0,0,0,0,0,1,2,3,3,3,3,3,3,3};\r |
| | 387 | \r |
| | 388 | \r |
| | 389 | /* 8 LFO speed parameters */\r |
| | 390 | /* each value represents number of samples that one LFO level will last for */\r |
| | 391 | static const UINT32 lfo_samples_per_step[8] = {108, 77, 71, 67, 62, 44, 8, 5};\r |
| | 392 | \r |
| | 393 | \r |
| | 394 | \r |
| | 395 | /*There are 4 different LFO AM depths available, they are:\r |
| | 396 | 0 dB, 1.4 dB, 5.9 dB, 11.8 dB\r |
| | 397 | Here is how it is generated (in EG steps):\r |
| | 398 | \r |
| | 399 | 11.8 dB = 0, 2, 4, 6, 8, 10,12,14,16...126,126,124,122,120,118,....4,2,0\r |
| | 400 | 5.9 dB = 0, 1, 2, 3, 4, 5, 6, 7, 8....63, 63, 62, 61, 60, 59,.....2,1,0\r |
| | 401 | 1.4 dB = 0, 0, 0, 0, 1, 1, 1, 1, 2,...15, 15, 15, 15, 14, 14,.....0,0,0\r |
| | 402 | \r |
| | 403 | (1.4 dB is loosing precision as you can see)\r |
| | 404 | \r |
| | 405 | It's implemented as generator from 0..126 with step 2 then a shift\r |
| | 406 | right N times, where N is:\r |
| | 407 | 8 for 0 dB\r |
| | 408 | 3 for 1.4 dB\r |
| | 409 | 1 for 5.9 dB\r |
| | 410 | 0 for 11.8 dB\r |
| | 411 | */\r |
| | 412 | static const UINT8 lfo_ams_depth_shift[4] = {8, 3, 1, 0};\r |
| | 413 | \r |
| | 414 | \r |
| | 415 | \r |
| | 416 | /*There are 8 different LFO PM depths available, they are:\r |
| | 417 | 0, 3.4, 6.7, 10, 14, 20, 40, 80 (cents)\r |
| | 418 | \r |
| | 419 | Modulation level at each depth depends on F-NUMBER bits: 4,5,6,7,8,9,10\r |
| | 420 | (bits 8,9,10 = FNUM MSB from OCT/FNUM register)\r |
| | 421 | \r |
| | 422 | Here we store only first quarter (positive one) of full waveform.\r |
| | 423 | Full table (lfo_pm_table) containing all 128 waveforms is build\r |
| | 424 | at run (init) time.\r |
| | 425 | \r |
| | 426 | One value in table below represents 4 (four) basic LFO steps\r |
| | 427 | (1 PM step = 4 AM steps).\r |
| | 428 | \r |
| | 429 | For example:\r |
| | 430 | at LFO SPEED=0 (which is 108 samples per basic LFO step)\r |
| | 431 | one value from "lfo_pm_output" table lasts for 432 consecutive\r |
| | 432 | samples (4*108=432) and one full LFO waveform cycle lasts for 13824\r |
| | 433 | samples (32*432=13824; 32 because we store only a quarter of whole\r |
| | 434 | waveform in the table below)\r |
| | 435 | */\r |
| | 436 | static const UINT8 lfo_pm_output[7*8][8]={ /* 7 bits meaningful (of F-NUMBER), 8 LFO output levels per one depth (out of 32), 8 LFO depths */\r |
| | 437 | /* FNUM BIT 4: 000 0001xxxx */\r |
| | 438 | /* DEPTH 0 */ {0, 0, 0, 0, 0, 0, 0, 0},\r |
| | 439 | /* DEPTH 1 */ {0, 0, 0, 0, 0, 0, 0, 0},\r |
| | 440 | /* DEPTH 2 */ {0, 0, 0, 0, 0, 0, 0, 0},\r |
| | 441 | /* DEPTH 3 */ {0, 0, 0, 0, 0, 0, 0, 0},\r |
| | 442 | /* DEPTH 4 */ {0, 0, 0, 0, 0, 0, 0, 0},\r |
| | 443 | /* DEPTH 5 */ {0, 0, 0, 0, 0, 0, 0, 0},\r |
| | 444 | /* DEPTH 6 */ {0, 0, 0, 0, 0, 0, 0, 0},\r |
| | 445 | /* DEPTH 7 */ {0, 0, 0, 0, 1, 1, 1, 1},\r |
| | 446 | \r |
| | 447 | /* FNUM BIT 5: 000 0010xxxx */\r |
| | 448 | /* DEPTH 0 */ {0, 0, 0, 0, 0, 0, 0, 0},\r |
| | 449 | /* DEPTH 1 */ {0, 0, 0, 0, 0, 0, 0, 0},\r |
| | 450 | /* DEPTH 2 */ {0, 0, 0, 0, 0, 0, 0, 0},\r |
| | 451 | /* DEPTH 3 */ {0, 0, 0, 0, 0, 0, 0, 0},\r |
| | 452 | /* DEPTH 4 */ {0, 0, 0, 0, 0, 0, 0, 0},\r |
| | 453 | /* DEPTH 5 */ {0, 0, 0, 0, 0, 0, 0, 0},\r |
| | 454 | /* DEPTH 6 */ {0, 0, 0, 0, 1, 1, 1, 1},\r |
| | 455 | /* DEPTH 7 */ {0, 0, 1, 1, 2, 2, 2, 3},\r |
| | 456 | \r |
| | 457 | /* FNUM BIT 6: 000 0100xxxx */\r |
| | 458 | /* DEPTH 0 */ {0, 0, 0, 0, 0, 0, 0, 0},\r |
| | 459 | /* DEPTH 1 */ {0, 0, 0, 0, 0, 0, 0, 0},\r |
| | 460 | /* DEPTH 2 */ {0, 0, 0, 0, 0, 0, 0, 0},\r |
| | 461 | /* DEPTH 3 */ {0, 0, 0, 0, 0, 0, 0, 0},\r |
| | 462 | /* DEPTH 4 */ {0, 0, 0, 0, 0, 0, 0, 1},\r |
| | 463 | /* DEPTH 5 */ {0, 0, 0, 0, 1, 1, 1, 1},\r |
| | 464 | /* DEPTH 6 */ {0, 0, 1, 1, 2, 2, 2, 3},\r |
| | 465 | /* DEPTH 7 */ {0, 0, 2, 3, 4, 4, 5, 6},\r |
| | 466 | \r |
| | 467 | /* FNUM BIT 7: 000 1000xxxx */\r |
| | 468 | /* DEPTH 0 */ {0, 0, 0, 0, 0, 0, 0, 0},\r |
| | 469 | /* DEPTH 1 */ {0, 0, 0, 0, 0, 0, 0, 0},\r |
| | 470 | /* DEPTH 2 */ {0, 0, 0, 0, 0, 0, 1, 1},\r |
| | 471 | /* DEPTH 3 */ {0, 0, 0, 0, 1, 1, 1, 1},\r |
| | 472 | /* DEPTH 4 */ {0, 0, 0, 1, 1, 1, 1, 2},\r |
| | 473 | /* DEPTH 5 */ {0, 0, 1, 1, 2, 2, 2, 3},\r |
| | 474 | /* DEPTH 6 */ {0, 0, 2, 3, 4, 4, 5, 6},\r |
| | 475 | /* DEPTH 7 */ {0, 0, 4, 6, 8, 8, 0xa, 0xc},\r |
| | 476 | \r |
| | 477 | /* FNUM BIT 8: 001 0000xxxx */\r |
| | 478 | /* DEPTH 0 */ {0, 0, 0, 0, 0, 0, 0, 0},\r |
| | 479 | /* DEPTH 1 */ {0, 0, 0, 0, 1, 1, 1, 1},\r |
| | 480 | /* DEPTH 2 */ {0, 0, 0, 1, 1, 1, 2, 2},\r |
| | 481 | /* DEPTH 3 */ {0, 0, 1, 1, 2, 2, 3, 3},\r |
| | 482 | /* DEPTH 4 */ {0, 0, 1, 2, 2, 2, 3, 4},\r |
| | 483 | /* DEPTH 5 */ {0, 0, 2, 3, 4, 4, 5, 6},\r |
| | 484 | /* DEPTH 6 */ {0, 0, 4, 6, 8, 8, 0xa, 0xc},\r |
| | 485 | /* DEPTH 7 */ {0, 0, 8, 0xc,0x10,0x10,0x14,0x18},\r |
| | 486 | \r |
| | 487 | /* FNUM BIT 9: 010 0000xxxx */\r |
| | 488 | /* DEPTH 0 */ {0, 0, 0, 0, 0, 0, 0, 0},\r |
| | 489 | /* DEPTH 1 */ {0, 0, 0, 0, 2, 2, 2, 2},\r |
| | 490 | /* DEPTH 2 */ {0, 0, 0, 2, 2, 2, 4, 4},\r |
| | 491 | /* DEPTH 3 */ {0, 0, 2, 2, 4, 4, 6, 6},\r |
| | 492 | /* DEPTH 4 */ {0, 0, 2, 4, 4, 4, 6, 8},\r |
| | 493 | /* DEPTH 5 */ {0, 0, 4, 6, 8, 8, 0xa, 0xc},\r |
| | 494 | /* DEPTH 6 */ {0, 0, 8, 0xc,0x10,0x10,0x14,0x18},\r |
| | 495 | /* DEPTH 7 */ {0, 0,0x10,0x18,0x20,0x20,0x28,0x30},\r |
| | 496 | \r |
| | 497 | /* FNUM BIT10: 100 0000xxxx */\r |
| | 498 | /* DEPTH 0 */ {0, 0, 0, 0, 0, 0, 0, 0},\r |
| | 499 | /* DEPTH 1 */ {0, 0, 0, 0, 4, 4, 4, 4},\r |
| | 500 | /* DEPTH 2 */ {0, 0, 0, 4, 4, 4, 8, 8},\r |
| | 501 | /* DEPTH 3 */ {0, 0, 4, 4, 8, 8, 0xc, 0xc},\r |
| | 502 | /* DEPTH 4 */ {0, 0, 4, 8, 8, 8, 0xc,0x10},\r |
| | 503 | /* DEPTH 5 */ {0, 0, 8, 0xc,0x10,0x10,0x14,0x18},\r |
| | 504 | /* DEPTH 6 */ {0, 0,0x10,0x18,0x20,0x20,0x28,0x30},\r |
| | 505 | /* DEPTH 7 */ {0, 0,0x20,0x30,0x40,0x40,0x50,0x60},\r |
| | 506 | \r |
| | 507 | };\r |
| | 508 | \r |
| | 509 | /* all 128 LFO PM waveforms */\r |
| | 510 | static INT32 lfo_pm_table[128*8*32]; /* 128 combinations of 7 bits meaningful (of F-NUMBER), 8 LFO depths, 32 LFO output levels per one depth */\r |
| | 511 | \r |
| | 512 | /* there are 2048 FNUMs that can be generated using FNUM/BLK registers\r |
| | 513 | but LFO works with one more bit of a precision so we really need 4096 elements */\r |
| | 514 | static UINT32 fn_table[4096]; /* fnumber->increment counter */\r |
| | 515 | \r |
| | 516 | /* register number to channel number , slot offset */\r |
| | 517 | #define OPN_CHAN(N) (N&3)\r |
| | 518 | #define OPN_SLOT(N) ((N>>2)&3)\r |
| | 519 | \r |
| | 520 | /* slot number */\r |
| | 521 | #define SLOT1 0\r |
| | 522 | #define SLOT2 2\r |
| | 523 | #define SLOT3 1\r |
| | 524 | #define SLOT4 3\r |
| | 525 | \r |
| | 526 | \r |
| | 527 | /* OPN Mode Register Write */\r |
| | 528 | static INLINE void set_timers( int v )\r |
| | 529 | {\r |
| | 530 | /* b7 = CSM MODE */\r |
| | 531 | /* b6 = 3 slot mode */\r |
| | 532 | /* b5 = reset b */\r |
| | 533 | /* b4 = reset a */\r |
| | 534 | /* b3 = timer enable b */\r |
| | 535 | /* b2 = timer enable a */\r |
| | 536 | /* b1 = load b */\r |
| | 537 | /* b0 = load a */\r |
| | 538 | ym2612.OPN.ST.mode = v;\r |
| | 539 | \r |
| | 540 | /* reset Timer b flag */\r |
| | 541 | if( v & 0x20 )\r |
| | 542 | ym2612.OPN.ST.status &= ~2;\r |
| | 543 | \r |
| | 544 | /* reset Timer a flag */\r |
| | 545 | if( v & 0x10 )\r |
| | 546 | ym2612.OPN.ST.status &= ~1;\r |
| | 547 | }\r |
| | 548 | \r |
| | 549 | static INLINE void recalc_volout(FM_SLOT *SLOT)\r |
| | 550 | {\r |
| | 551 | INT16 vol_out = SLOT->volume;\r |
| | 552 | if ((SLOT->ssg&0x0c) == 0x0c)\r |
| | 553 | vol_out = (0x200 - vol_out) & MAX_ATT_INDEX;\r |
| | 554 | SLOT->vol_out = vol_out + SLOT->tl;\r |
| | 555 | }\r |
| | 556 | \r |
| | 557 | static INLINE void FM_KEYON(int c , int s )\r |
| | 558 | {\r |
| | 559 | FM_SLOT *SLOT = &ym2612.CH[c].SLOT[s];\r |
| | 560 | if( !SLOT->key )\r |
| | 561 | {\r |
| | 562 | SLOT->key = 1;\r |
| | 563 | SLOT->phase = 0; /* restart Phase Generator */\r |
| | 564 | SLOT->ssg ^= SLOT->ssgn;\r |
| | 565 | SLOT->ssgn = 0;\r |
| | 566 | SLOT->state = (SLOT->sl == MIN_ATT_INDEX) ? EG_SUS : EG_DEC;\r |
| | 567 | if (SLOT->ar_ksr < 32+62) {\r |
| | 568 | if (SLOT->volume > MIN_ATT_INDEX) SLOT->state = EG_ATT;\r |
| | 569 | } else {\r |
| | 570 | SLOT->volume = MIN_ATT_INDEX;\r |
| | 571 | }\r |
| | 572 | recalc_volout(SLOT);\r |
| | 573 | ym2612.slot_mask |= (1<<s) << (c*4);\r |
| | 574 | }\r |
| | 575 | }\r |
| | 576 | \r |
| | 577 | static INLINE void FM_KEYOFF(int c , int s )\r |
| | 578 | {\r |
| | 579 | FM_SLOT *SLOT = &ym2612.CH[c].SLOT[s];\r |
| | 580 | if( SLOT->key )\r |
| | 581 | {\r |
| | 582 | SLOT->key = 0;\r |
| | 583 | if (SLOT->state>EG_REL) {\r |
| | 584 | SLOT->state = EG_REL;/* phase -> Release */\r |
| | 585 | if (SLOT->ssg&0x08) {\r |
| | 586 | if (SLOT->ssg&0x04)\r |
| | 587 | SLOT->volume = (0x200 - SLOT->volume);\r |
| | 588 | if (SLOT->volume >= 0x200) {\r |
| | 589 | SLOT->volume = MAX_ATT_INDEX;\r |
| | 590 | SLOT->state = EG_OFF;\r |
| | 591 | }\r |
| | 592 | }\r |
| | 593 | }\r |
| | 594 | SLOT->vol_out = SLOT->volume + SLOT->tl;\r |
| | 595 | }\r |
| | 596 | }\r |
| | 597 | \r |
| | 598 | \r |
| | 599 | /* set detune & multiple */\r |
| | 600 | static INLINE void set_det_mul(FM_CH *CH, FM_SLOT *SLOT, int v)\r |
| | 601 | {\r |
| | 602 | SLOT->mul = (v&0x0f)? (v&0x0f)*2 : 1;\r |
| | 603 | SLOT->DT = ym2612.OPN.ST.dt_tab[(v>>4)&7];\r |
| | 604 | CH->SLOT[SLOT1].Incr=-1;\r |
| | 605 | }\r |
| | 606 | \r |
| | 607 | /* set total level */\r |
| | 608 | static INLINE void set_tl(FM_SLOT *SLOT, int v)\r |
| | 609 | {\r |
| | 610 | SLOT->tl = (v&0x7f)<<(ENV_BITS-7); /* 7bit TL */\r |
| | 611 | if (SLOT->state > EG_REL)\r |
| | 612 | recalc_volout(SLOT);\r |
| | 613 | }\r |
| | 614 | \r |
| | 615 | /* set attack rate & key scale */\r |
| | 616 | static INLINE void set_ar_ksr(FM_CH *CH, FM_SLOT *SLOT, int v)\r |
| | 617 | {\r |
| | 618 | UINT8 old_KSR = SLOT->KSR;\r |
| | 619 | int eg_sh_ar, eg_sel_ar;\r |
| | 620 | \r |
| | 621 | SLOT->ar = (v&0x1f) ? 32 + ((v&0x1f)<<1) : 0;\r |
| | 622 | SLOT->ar_ksr = SLOT->ar + SLOT->ksr;\r |
| | 623 | \r |
| | 624 | SLOT->KSR = 3-(v>>6);\r |
| | 625 | if (SLOT->KSR != old_KSR)\r |
| | 626 | {\r |
| | 627 | CH->SLOT[SLOT1].Incr=-1;\r |
| | 628 | }\r |
| | 629 | \r |
| | 630 | /* refresh Attack rate */\r |
| | 631 | if ((SLOT->ar_ksr) < 32+62)\r |
| | 632 | {\r |
| | 633 | eg_sh_ar = eg_rate_shift [SLOT->ar_ksr];\r |
| | 634 | eg_sel_ar = eg_rate_select[SLOT->ar_ksr];\r |
| | 635 | }\r |
| | 636 | else\r |
| | 637 | {\r |
| | 638 | eg_sh_ar = 0;\r |
| | 639 | eg_sel_ar = 18;\r |
| | 640 | }\r |
| | 641 | \r |
| | 642 | SLOT->eg_pack_ar = eg_inc_pack[eg_sel_ar] | (eg_sh_ar<<24);\r |
| | 643 | }\r |
| | 644 | \r |
| | 645 | /* set decay rate */\r |
| | 646 | static INLINE void set_dr(FM_SLOT *SLOT, int v)\r |
| | 647 | {\r |
| | 648 | int eg_sh_d1r, eg_sel_d1r;\r |
| | 649 | \r |
| | 650 | SLOT->d1r = (v&0x1f) ? 32 + ((v&0x1f)<<1) : 0;\r |
| | 651 | \r |
| | 652 | eg_sh_d1r = eg_rate_shift [SLOT->d1r + SLOT->ksr];\r |
| | 653 | eg_sel_d1r= eg_rate_select[SLOT->d1r + SLOT->ksr];\r |
| | 654 | \r |
| | 655 | SLOT->eg_pack_d1r = eg_inc_pack[eg_sel_d1r] | (eg_sh_d1r<<24);\r |
| | 656 | }\r |
| | 657 | \r |
| | 658 | /* set sustain rate */\r |
| | 659 | static INLINE void set_sr(FM_SLOT *SLOT, int v)\r |
| | 660 | {\r |
| | 661 | int eg_sh_d2r, eg_sel_d2r;\r |
| | 662 | \r |
| | 663 | SLOT->d2r = (v&0x1f) ? 32 + ((v&0x1f)<<1) : 0;\r |
| | 664 | \r |
| | 665 | eg_sh_d2r = eg_rate_shift [SLOT->d2r + SLOT->ksr];\r |
| | 666 | eg_sel_d2r= eg_rate_select[SLOT->d2r + SLOT->ksr];\r |
| | 667 | \r |
| | 668 | SLOT->eg_pack_d2r = eg_inc_pack[eg_sel_d2r] | (eg_sh_d2r<<24);\r |
| | 669 | }\r |
| | 670 | \r |
| | 671 | /* set release rate */\r |
| | 672 | static INLINE void set_sl_rr(FM_SLOT *SLOT, int v)\r |
| | 673 | {\r |
| | 674 | int eg_sh_rr, eg_sel_rr;\r |
| | 675 | \r |
| | 676 | SLOT->sl = sl_table[ v>>4 ];\r |
| | 677 | \r |
| | 678 | if (SLOT->state == EG_DEC && (SLOT->volume >= (INT32)(SLOT->sl)))\r |
| | 679 | SLOT->state = EG_SUS;\r |
| | 680 | \r |
| | 681 | SLOT->rr = 34 + ((v&0x0f)<<2);\r |
| | 682 | \r |
| | 683 | eg_sh_rr = eg_rate_shift [SLOT->rr + SLOT->ksr];\r |
| | 684 | eg_sel_rr = eg_rate_select[SLOT->rr + SLOT->ksr];\r |
| | 685 | \r |
| | 686 | SLOT->eg_pack_rr = eg_inc_pack[eg_sel_rr] | (eg_sh_rr<<24);\r |
| | 687 | }\r |
| | 688 | \r |
| | 689 | \r |
| | 690 | \r |
| | 691 | static INLINE signed int op_calc(UINT32 phase, unsigned int env, signed int pm)\r |
| | 692 | {\r |
| | 693 | int ret, sin = (phase>>16) + (pm>>1);\r |
| | 694 | int neg = sin & 0x200;\r |
| | 695 | if (sin & 0x100) sin ^= 0xff;\r |
| | 696 | sin&=0xff;\r |
| | 697 | env&=~1;\r |
| | 698 | \r |
| | 699 | // this was already checked\r |
| | 700 | // if (env >= ENV_QUIET) // 384\r |
| | 701 | // return 0;\r |
| | 702 | \r |
| | 703 | ret = ym_tl_tab[sin | (env<<7)];\r |
| | 704 | \r |
| | 705 | return neg ? -ret : ret;\r |
| | 706 | }\r |
| | 707 | \r |
| | 708 | static INLINE signed int op_calc1(UINT32 phase, unsigned int env, signed int pm)\r |
| | 709 | {\r |
| | 710 | int ret, sin = (phase+pm)>>16;\r |
| | 711 | int neg = sin & 0x200;\r |
| | 712 | if (sin & 0x100) sin ^= 0xff;\r |
| | 713 | sin&=0xff;\r |
| | 714 | env&=~1;\r |
| | 715 | \r |
| | 716 | // if (env >= ENV_QUIET) // 384\r |
| | 717 | // return 0;\r |
| | 718 | \r |
| | 719 | ret = ym_tl_tab[sin | (env<<7)];\r |
| | 720 | \r |
| | 721 | return neg ? -ret : ret;\r |
| | 722 | }\r |
| | 723 | \r |
| | 724 | #if !defined(_ASM_YM2612_C) || defined(EXTERNAL_YM2612)\r |
| | 725 | /* advance LFO to next sample */\r |
| | 726 | static INLINE int advance_lfo(int lfo_ampm, UINT32 lfo_cnt_old, UINT32 lfo_cnt)\r |
| | 727 | {\r |
| | 728 | UINT8 pos;\r |
| | 729 | UINT8 prev_pos;\r |
| | 730 | \r |
| | 731 | prev_pos = (lfo_cnt_old >> LFO_SH) & 127;\r |
| | 732 | \r |
| | 733 | pos = (lfo_cnt >> LFO_SH) & 127;\r |
| | 734 | \r |
| | 735 | /* update AM when LFO output changes */\r |
| | 736 | \r |
| | 737 | if (prev_pos != pos)\r |
| | 738 | {\r |
| | 739 | lfo_ampm &= 0xff;\r |
| | 740 | /* triangle (inverted) */\r |
| | 741 | /* AM: 0 to 126 step +2, 126 to 0 step -2 */\r |
| | 742 | if (pos<64)\r |
| | 743 | lfo_ampm |= ((pos^63) * 2) << 8; /* 0 - 126 */\r |
| | 744 | else\r |
| | 745 | lfo_ampm |= ((pos&63) * 2) << 8;\r |
| | 746 | }\r |
| | 747 | else\r |
| | 748 | {\r |
| | 749 | return lfo_ampm;\r |
| | 750 | }\r |
| | 751 | \r |
| | 752 | /* PM works with 4 times slower clock */\r |
| | 753 | prev_pos >>= 2;\r |
| | 754 | pos >>= 2;\r |
| | 755 | /* update PM when LFO output changes */\r |
| | 756 | if (prev_pos != pos)\r |
| | 757 | {\r |
| | 758 | lfo_ampm &= ~0xff;\r |
| | 759 | lfo_ampm |= pos; /* 0 - 32 */\r |
| | 760 | }\r |
| | 761 | return lfo_ampm;\r |
| | 762 | }\r |
| | 763 | \r |
| | 764 | static INLINE void update_eg_phase(FM_SLOT *SLOT, UINT32 eg_cnt, UINT32 ssg_en)\r |
| | 765 | {\r |
| | 766 | INT32 volume = SLOT->volume;\r |
| | 767 | UINT32 pack = SLOT->eg_pack[SLOT->state - 1];\r |
| | 768 | UINT32 shift = pack >> 24;\r |
| | 769 | INT32 eg_inc_val;\r |
| | 770 | \r |
| | 771 | if (eg_cnt & ((1 << shift) - 1))\r |
| | 772 | return;\r |
| | 773 | \r |
| | 774 | eg_inc_val = pack >> ((eg_cnt >> shift) & 7) * 3;\r |
| | 775 | eg_inc_val = (1 << (eg_inc_val & 7)) >> 1;\r |
| | 776 | \r |
| | 777 | if ((SLOT->ssg&0x08) && ssg_en) {\r |
| | 778 | switch (SLOT->state)\r |
| | 779 | {\r |
| | 780 | case EG_ATT: /* attack phase */\r |
| | 781 | volume += ( ~volume * eg_inc_val ) >> 4;\r |
| | 782 | if ( volume <= MIN_ATT_INDEX )\r |
| | 783 | {\r |
| | 784 | volume = MIN_ATT_INDEX;\r |
| | 785 | SLOT->state = (SLOT->sl == MIN_ATT_INDEX) ? EG_SUS: EG_DEC;\r |
| | 786 | }\r |
| | 787 | break;\r |
| | 788 | \r |
| | 789 | case EG_DEC: /* decay phase */\r |
| | 790 | if (volume < 0x200)\r |
| | 791 | volume += 4*eg_inc_val;\r |
| | 792 | if ( volume >= (INT32) SLOT->sl )\r |
| | 793 | SLOT->state = EG_SUS;\r |
| | 794 | break;\r |
| | 795 | \r |
| | 796 | case EG_SUS: /* sustain phase */\r |
| | 797 | if (volume < 0x200)\r |
| | 798 | volume += 4*eg_inc_val;\r |
| | 799 | break;\r |
| | 800 | \r |
| | 801 | case EG_REL: /* release phase */\r |
| | 802 | if (volume < 0x200)\r |
| | 803 | volume += 4*eg_inc_val;\r |
| | 804 | if ( volume >= 0x200 )\r |
| | 805 | {\r |
| | 806 | volume = MAX_ATT_INDEX;\r |
| | 807 | SLOT->state = EG_OFF;\r |
| | 808 | }\r |
| | 809 | break;\r |
| | 810 | }\r |
| | 811 | \r |
| | 812 | SLOT->vol_out = volume + SLOT->tl;\r |
| | 813 | if ((SLOT->ssg&0x04) && (SLOT->state > EG_REL))\r |
| | 814 | SLOT->vol_out = ((0x200 - volume) & MAX_ATT_INDEX) + SLOT->tl;\r |
| | 815 | } else {\r |
| | 816 | switch (SLOT->state)\r |
| | 817 | {\r |
| | 818 | case EG_ATT: /* attack phase */\r |
| | 819 | volume += ( ~volume * eg_inc_val ) >> 4;\r |
| | 820 | if ( volume <= MIN_ATT_INDEX )\r |
| | 821 | {\r |
| | 822 | volume = MIN_ATT_INDEX;\r |
| | 823 | SLOT->state = (SLOT->sl == MIN_ATT_INDEX) ? EG_SUS: EG_DEC;\r |
| | 824 | }\r |
| | 825 | break;\r |
| | 826 | \r |
| | 827 | case EG_DEC: /* decay phase */\r |
| | 828 | volume += eg_inc_val;\r |
| | 829 | if ( volume >= (INT32) SLOT->sl )\r |
| | 830 | SLOT->state = EG_SUS;\r |
| | 831 | break;\r |
| | 832 | \r |
| | 833 | case EG_SUS: /* sustain phase */\r |
| | 834 | volume += eg_inc_val;\r |
| | 835 | if ( volume >= MAX_ATT_INDEX )\r |
| | 836 | {\r |
| | 837 | volume = MAX_ATT_INDEX;\r |
| | 838 | /* do not change SLOT->state (verified on real chip) */\r |
| | 839 | }\r |
| | 840 | break;\r |
| | 841 | \r |
| | 842 | case EG_REL: /* release phase */\r |
| | 843 | volume += eg_inc_val;\r |
| | 844 | if ( volume >= MAX_ATT_INDEX )\r |
| | 845 | {\r |
| | 846 | volume = MAX_ATT_INDEX;\r |
| | 847 | SLOT->state = EG_OFF;\r |
| | 848 | }\r |
| | 849 | break;\r |
| | 850 | }\r |
| | 851 | \r |
| | 852 | SLOT->vol_out = volume + SLOT->tl;\r |
| | 853 | }\r |
| | 854 | SLOT->volume = volume;\r |
| | 855 | }\r |
| | 856 | \r |
| | 857 | static INLINE UINT32 update_ssg_eg_phase(FM_SLOT *SLOT, UINT32 phase)\r |
| | 858 | {\r |
| | 859 | if (SLOT->ssg&0x01) {\r |
| | 860 | if (SLOT->ssg&0x02) {\r |
| | 861 | SLOT->ssg ^= SLOT->ssgn ^ 4;\r |
| | 862 | SLOT->ssgn = 4;\r |
| | 863 | }\r |
| | 864 | \r |
| | 865 | if (SLOT->state != EG_ATT && !(SLOT->ssg&0x04))\r |
| | 866 | SLOT->volume = MAX_ATT_INDEX;\r |
| | 867 | } else {\r |
| | 868 | if (SLOT->ssg&0x02) {\r |
| | 869 | SLOT->ssg ^= 4;\r |
| | 870 | SLOT->ssgn ^= 4;\r |
| | 871 | } else\r |
| | 872 | phase = 0;\r |
| | 873 | \r |
| | 874 | if (SLOT->state != EG_ATT) {\r |
| | 875 | SLOT->state = (SLOT->sl == MIN_ATT_INDEX) ? EG_SUS : EG_DEC;\r |
| | 876 | if (SLOT->ar_ksr < 32+62) {\r |
| | 877 | if (SLOT->volume > MIN_ATT_INDEX) SLOT->state = EG_ATT;\r |
| | 878 | } else {\r |
| | 879 | SLOT->volume = MIN_ATT_INDEX;\r |
| | 880 | }\r |
| | 881 | }\r |
| | 882 | }\r |
| | 883 | recalc_volout(SLOT);\r |
| | 884 | return phase;\r |
| | 885 | }\r |
| | 886 | #endif\r |
| | 887 | \r |
| | 888 | \r |
| | 889 | typedef struct\r |
| | 890 | {\r |
| | 891 | UINT16 vol_out1; /* 00: current output from EG circuit (without AM from LFO) */\r |
| | 892 | UINT16 vol_out2;\r |
| | 893 | UINT16 vol_out3;\r |
| | 894 | UINT16 vol_out4;\r |
| | 895 | UINT32 lfo_init_sft16;\r |
| | 896 | UINT32 pad;\r |
| | 897 | UINT32 phase1; /* 10 */\r |
| | 898 | UINT32 phase2;\r |
| | 899 | UINT32 phase3;\r |
| | 900 | UINT32 phase4;\r |
| | 901 | UINT32 incr1; /* 20: phase step */\r |
| | 902 | UINT32 incr2;\r |
| | 903 | UINT32 incr3;\r |
| | 904 | UINT32 incr4;\r |
| | 905 | UINT32 lfo_cnt; /* 30 */\r |
| | 906 | UINT32 lfo_inc;\r |
| | 907 | INT32 mem; /* one sample delay memory */\r |
| | 908 | UINT32 eg_cnt; /* envelope generator counter */\r |
| | 909 | FM_CH *CH; /* 40: envelope generator counter */\r |
| | 910 | UINT32 eg_timer;\r |
| | 911 | UINT32 eg_timer_add;\r |
| | 912 | UINT32 pack; // 4c: stereo, lastchan, disabled, lfo_enabled | pan_r, pan_l, ams[2] | AMmasks[4] | FB[4] | lfo_ampm[16]\r |
| | 913 | UINT32 algo; /* 50: algo[3], was_update, unused, upd_cnt[2], dac */\r |
| | 914 | INT32 op1_out;\r |
| | 915 | #ifdef _MIPS_ARCH_ALLEGREX\r |
| | 916 | UINT32 pad1[3+8];\r |
| | 917 | #endif\r |
| | 918 | } chan_rend_context;\r |
| | 919 | \r |
| | 920 | \r |
| | 921 | #if !defined(_ASM_YM2612_C) || defined(EXTERNAL_YM2612)\r |
| | 922 | #include <limits.h>\r |
| | 923 | static int clip(int n) \r |
| | 924 | {\r |
| | 925 | unsigned b = 14, s = n < 0;\r |
| | 926 | int m = s + INT_MAX;\r |
| | 927 | if (s + (n>>(b-1))) n = m >> (8*sizeof(int)-b);\r |
| | 928 | return n;\r |
| | 929 | }\r |
| | 930 | \r |
| | 931 | static void update_ssg_eg_channel(chan_rend_context *ct)\r |
| | 932 | {\r |
| | 933 | FM_SLOT *SLOT;\r |
| | 934 | \r |
| | 935 | SLOT = &ct->CH->SLOT[SLOT1];\r |
| | 936 | if ((SLOT->ssg&0x08) && SLOT->state > EG_REL && SLOT->volume >= 0x200)\r |
| | 937 | ct->phase1 = update_ssg_eg_phase(SLOT, ct->phase1);\r |
| | 938 | SLOT = &ct->CH->SLOT[SLOT2];\r |
| | 939 | if ((SLOT->ssg&0x08) && SLOT->state > EG_REL && SLOT->volume >= 0x200)\r |
| | 940 | ct->phase2 = update_ssg_eg_phase(SLOT, ct->phase2);\r |
| | 941 | SLOT = &ct->CH->SLOT[SLOT3];\r |
| | 942 | if ((SLOT->ssg&0x08) && SLOT->state > EG_REL && SLOT->volume >= 0x200)\r |
| | 943 | ct->phase3 = update_ssg_eg_phase(SLOT, ct->phase3);\r |
| | 944 | SLOT = &ct->CH->SLOT[SLOT4];\r |
| | 945 | if ((SLOT->ssg&0x08) && SLOT->state > EG_REL && SLOT->volume >= 0x200)\r |
| | 946 | ct->phase4 = update_ssg_eg_phase(SLOT, ct->phase4);\r |
| | 947 | }\r |
| | 948 | \r |
| | 949 | static void update_eg_phase_channel(chan_rend_context *ct)\r |
| | 950 | {\r |
| | 951 | FM_SLOT *SLOT;\r |
| | 952 | \r |
| | 953 | SLOT = &ct->CH->SLOT[SLOT1];\r |
| | 954 | if (SLOT->state != EG_OFF) update_eg_phase(SLOT, ct->eg_cnt, ct->pack & 2);\r |
| | 955 | SLOT = &ct->CH->SLOT[SLOT2];\r |
| | 956 | if (SLOT->state != EG_OFF) update_eg_phase(SLOT, ct->eg_cnt, ct->pack & 2);\r |
| | 957 | SLOT = &ct->CH->SLOT[SLOT3];\r |
| | 958 | if (SLOT->state != EG_OFF) update_eg_phase(SLOT, ct->eg_cnt, ct->pack & 2);\r |
| | 959 | SLOT = &ct->CH->SLOT[SLOT4];\r |
| | 960 | if (SLOT->state != EG_OFF) update_eg_phase(SLOT, ct->eg_cnt, ct->pack & 2);\r |
| | 961 | }\r |
| | 962 | \r |
| | 963 | static int update_algo_channel(chan_rend_context *ct, unsigned int eg_out, unsigned int eg_out2, unsigned int eg_out4)\r |
| | 964 | {\r |
| | 965 | int m2,c1,c2=0; /* Phase Modulation input for operators 2,3,4 */\r |
| | 966 | int smp = 0;\r |
| | 967 | \r |
| | 968 | switch( ct->algo&0x7 )\r |
| | 969 | {\r |
| | 970 | case 0:\r |
| | 971 | {\r |
| | 972 | /* M1---C1---MEM---M2---C2---OUT */\r |
| | 973 | m2 = ct->mem;\r |
| | 974 | c1 = ct->op1_out>>16;\r |
| | 975 | if( eg_out2 < ENV_QUIET ) { /* SLOT 2 */\r |
| | 976 | ct->mem = op_calc(ct->phase2, eg_out2, c1);\r |
| | 977 | }\r |
| | 978 | else ct->mem = 0;\r |
| | 979 | \r |
| | 980 | if( eg_out < ENV_QUIET ) { /* SLOT 3 */\r |
| | 981 | c2 = op_calc(ct->phase3, eg_out, m2);\r |
| | 982 | }\r |
| | 983 | if( eg_out4 < ENV_QUIET ) { /* SLOT 4 */\r |
| | 984 | smp = op_calc(ct->phase4, eg_out4, c2);\r |
| | 985 | }\r |
| | 986 | break;\r |
| | 987 | }\r |
| | 988 | case 1:\r |
| | 989 | {\r |
| | 990 | /* M1------+-MEM---M2---C2---OUT */\r |
| | 991 | /* C1-+ */\r |
| | 992 | m2 = ct->mem;\r |
| | 993 | ct->mem = ct->op1_out>>16;\r |
| | 994 | if( eg_out2 < ENV_QUIET ) { /* SLOT 2 */\r |
| | 995 | ct->mem+= op_calc(ct->phase2, eg_out2, 0);\r |
| | 996 | }\r |
| | 997 | \r |
| | 998 | if( eg_out < ENV_QUIET ) { /* SLOT 3 */\r |
| | 999 | c2 = op_calc(ct->phase3, eg_out, m2);\r |
| | 1000 | }\r |
| | 1001 | if( eg_out4 < ENV_QUIET ) { /* SLOT 4 */\r |
| | 1002 | smp = op_calc(ct->phase4, eg_out4, c2);\r |
| | 1003 | }\r |
| | 1004 | break;\r |
| | 1005 | }\r |
| | 1006 | case 2:\r |
| | 1007 | {\r |
| | 1008 | /* M1-----------------+-C2---OUT */\r |
| | 1009 | /* C1---MEM---M2-+ */\r |
| | 1010 | m2 = ct->mem;\r |
| | 1011 | c2 = ct->op1_out>>16;\r |
| | 1012 | if( eg_out2 < ENV_QUIET ) { /* SLOT 2 */\r |
| | 1013 | ct->mem = op_calc(ct->phase2, eg_out2, 0);\r |
| | 1014 | }\r |
| | 1015 | else ct->mem = 0;\r |
| | 1016 | \r |
| | 1017 | if( eg_out < ENV_QUIET ) { /* SLOT 3 */\r |
| | 1018 | c2 += op_calc(ct->phase3, eg_out, m2);\r |
| | 1019 | }\r |
| | 1020 | if( eg_out4 < ENV_QUIET ) { /* SLOT 4 */\r |
| | 1021 | smp = op_calc(ct->phase4, eg_out4, c2);\r |
| | 1022 | }\r |
| | 1023 | break;\r |
| | 1024 | }\r |
| | 1025 | case 3:\r |
| | 1026 | {\r |
| | 1027 | /* M1---C1---MEM------+-C2---OUT */\r |
| | 1028 | /* M2-+ */\r |
| | 1029 | c2 = ct->mem;\r |
| | 1030 | c1 = ct->op1_out>>16;\r |
| | 1031 | if( eg_out2 < ENV_QUIET ) { /* SLOT 2 */\r |
| | 1032 | ct->mem = op_calc(ct->phase2, eg_out2, c1);\r |
| | 1033 | }\r |
| | 1034 | else ct->mem = 0;\r |
| | 1035 | \r |
| | 1036 | if( eg_out < ENV_QUIET ) { /* SLOT 3 */\r |
| | 1037 | c2 += op_calc(ct->phase3, eg_out, 0);\r |
| | 1038 | }\r |
| | 1039 | if( eg_out4 < ENV_QUIET ) { /* SLOT 4 */\r |
| | 1040 | smp = op_calc(ct->phase4, eg_out4, c2);\r |
| | 1041 | }\r |
| | 1042 | break;\r |
| | 1043 | }\r |
| | 1044 | case 4:\r |
| | 1045 | {\r |
| | 1046 | /* M1---C1-+-OUT */\r |
| | 1047 | /* M2---C2-+ */\r |
| | 1048 | /* MEM: not used */\r |
| | 1049 | \r |
| | 1050 | c1 = ct->op1_out>>16;\r |
| | 1051 | if( eg_out < ENV_QUIET ) { /* SLOT 3 */\r |
| | 1052 | c2 = op_calc(ct->phase3, eg_out, 0);\r |
| | 1053 | }\r |
| | 1054 | if( eg_out2 < ENV_QUIET ) { /* SLOT 2 */\r |
| | 1055 | smp = op_calc(ct->phase2, eg_out2, c1);\r |
| | 1056 | }\r |
| | 1057 | if( eg_out4 < ENV_QUIET ) { /* SLOT 4 */\r |
| | 1058 | smp+= op_calc(ct->phase4, eg_out4, c2);\r |
| | 1059 | }\r |
| | 1060 | break;\r |
| | 1061 | }\r |
| | 1062 | case 5:\r |
| | 1063 | {\r |
| | 1064 | /* +----C1----+ */\r |
| | 1065 | /* M1-+-MEM---M2-+-OUT */\r |
| | 1066 | /* +----C2----+ */\r |
| | 1067 | m2 = ct->mem;\r |
| | 1068 | ct->mem = c1 = c2 = ct->op1_out>>16;\r |
| | 1069 | \r |
| | 1070 | if( eg_out < ENV_QUIET ) { /* SLOT 3 */\r |
| | 1071 | smp = op_calc(ct->phase3, eg_out, m2);\r |
| | 1072 | }\r |
| | 1073 | if( eg_out2 < ENV_QUIET ) { /* SLOT 2 */\r |
| | 1074 | smp+= op_calc(ct->phase2, eg_out2, c1);\r |
| | 1075 | }\r |
| | 1076 | if( eg_out4 < ENV_QUIET ) { /* SLOT 4 */\r |
| | 1077 | smp+= op_calc(ct->phase4, eg_out4, c2);\r |
| | 1078 | }\r |
| | 1079 | break;\r |
| | 1080 | }\r |
| | 1081 | case 6:\r |
| | 1082 | {\r |
| | 1083 | /* M1---C1-+ */\r |
| | 1084 | /* M2-+-OUT */\r |
| | 1085 | /* C2-+ */\r |
| | 1086 | /* MEM: not used */\r |
| | 1087 | \r |
| | 1088 | c1 = ct->op1_out>>16;\r |
| | 1089 | if( eg_out < ENV_QUIET ) { /* SLOT 3 */\r |
| | 1090 | smp = op_calc(ct->phase3, eg_out, 0);\r |
| | 1091 | }\r |
| | 1092 | if( eg_out2 < ENV_QUIET ) { /* SLOT 2 */\r |
| | 1093 | smp+= op_calc(ct->phase2, eg_out2, c1);\r |
| | 1094 | }\r |
| | 1095 | if( eg_out4 < ENV_QUIET ) { /* SLOT 4 */\r |
| | 1096 | smp+= op_calc(ct->phase4, eg_out4, 0);\r |
| | 1097 | }\r |
| | 1098 | break;\r |
| | 1099 | }\r |
| | 1100 | case 7:\r |
| | 1101 | {\r |
| | 1102 | /* M1-+ */\r |
| | 1103 | /* C1-+-OUT */\r |
| | 1104 | /* M2-+ */\r |
| | 1105 | /* C2-+ */\r |
| | 1106 | /* MEM: not used*/\r |
| | 1107 | \r |
| | 1108 | smp = ct->op1_out>>16;\r |
| | 1109 | if( eg_out < ENV_QUIET ) { /* SLOT 3 */\r |
| | 1110 | smp += op_calc(ct->phase3, eg_out, 0);\r |
| | 1111 | }\r |
| | 1112 | if( eg_out2 < ENV_QUIET ) { /* SLOT 2 */\r |
| | 1113 | smp += op_calc(ct->phase2, eg_out2, 0);\r |
| | 1114 | }\r |
| | 1115 | if( eg_out4 < ENV_QUIET ) { /* SLOT 4 */\r |
| | 1116 | smp += op_calc(ct->phase4, eg_out4, 0);\r |
| | 1117 | }\r |
| | 1118 | break;\r |
| | 1119 | }\r |
| | 1120 | }\r |
| | 1121 | return smp;\r |
| | 1122 | }\r |
| | 1123 | \r |
| | 1124 | static void chan_render_loop(chan_rend_context *ct, s32 *buffer, int length)\r |
| | 1125 | {\r |
| | 1126 | int scounter; /* sample counter */\r |
| | 1127 | \r |
| | 1128 | /* sample generating loop */\r |
| | 1129 | for (scounter = 0; scounter < length; scounter++)\r |
| | 1130 | {\r |
| | 1131 | int smp = 0; /* produced sample */\r |
| | 1132 | unsigned int eg_out, eg_out2, eg_out4;\r |
| | 1133 | \r |
| | 1134 | ct->eg_timer += ct->eg_timer_add;\r |
| | 1135 | \r |
| | 1136 | while (ct->eg_timer >= 1<<EG_SH) {\r |
| | 1137 | ct->eg_timer -= 1<<EG_SH;\r |
| | 1138 | \r |
| | 1139 | if (ct->pack & 2)\r |
| | 1140 | update_ssg_eg_channel(ct);\r |
| | 1141 | \r |
| | 1142 | if (ct->algo & 0x30)\r |
| | 1143 | ct->algo -= 0x10;\r |
| | 1144 | if (!(ct->algo & 0x30)) {\r |
| | 1145 | ct->algo |= 0x30;\r |
| | 1146 | ct->eg_cnt++;\r |
| | 1147 | if (ct->eg_cnt >= 4096) ct->eg_cnt = 1;\r |
| | 1148 | \r |
| | 1149 | update_eg_phase_channel(ct);\r |
| | 1150 | }\r |
| | 1151 | }\r |
| | 1152 | \r |
| | 1153 | ct->vol_out1 = ct->CH->SLOT[SLOT1].vol_out;\r |
| | 1154 | ct->vol_out2 = ct->CH->SLOT[SLOT2].vol_out;\r |
| | 1155 | ct->vol_out3 = ct->CH->SLOT[SLOT3].vol_out;\r |
| | 1156 | ct->vol_out4 = ct->CH->SLOT[SLOT4].vol_out;\r |
| | 1157 | \r |
| | 1158 | if (ct->pack & 4) goto disabled; /* output disabled */\r |
| | 1159 | \r |
| | 1160 | if (ct->pack & 8) { /* LFO enabled ? (test Earthworm Jim in between demo 1 and 2) */\r |
| | 1161 | ct->pack = (ct->pack&0xffff) | (advance_lfo(ct->pack >> 16, ct->lfo_cnt, ct->lfo_cnt + ct->lfo_inc) << 16);\r |
| | 1162 | ct->lfo_cnt += ct->lfo_inc;\r |
| | 1163 | }\r |
| | 1164 | \r |
| | 1165 | /* calculate channel sample */\r |
| | 1166 | eg_out = ct->vol_out1;\r |
| | 1167 | if ( (ct->pack & 8) && (ct->pack&(1<<(SLOT1+8))) )\r |
| | 1168 | eg_out += ct->pack >> (((ct->pack&0xc0)>>6)+24);\r |
| | 1169 | \r |
| | 1170 | if( eg_out < ENV_QUIET ) /* SLOT 1 */\r |
| | 1171 | {\r |
| | 1172 | int out = 0;\r |
| | 1173 | \r |
| | 1174 | if (ct->pack&0xf000) out = ((ct->op1_out + (ct->op1_out<<16))>>16) << ((ct->pack&0xf000)>>12); /* op1_out0 + op1_out1 */\r |
| | 1175 | ct->op1_out <<= 16;\r |
| | 1176 | ct->op1_out |= (unsigned short)op_calc1(ct->phase1, eg_out, out);\r |
| | 1177 | } else {\r |
| | 1178 | ct->op1_out <<= 16; /* op1_out0 = op1_out1; op1_out1 = 0; */\r |
| | 1179 | }\r |
| | 1180 | \r |
| | 1181 | eg_out = ct->vol_out3; // volume_calc(&CH->SLOT[SLOT3]);\r |
| | 1182 | eg_out2 = ct->vol_out2; // volume_calc(&CH->SLOT[SLOT2]);\r |
| | 1183 | eg_out4 = ct->vol_out4; // volume_calc(&CH->SLOT[SLOT4]);\r |
| | 1184 | \r |
| | 1185 | if (ct->pack & 8) {\r |
| | 1186 | unsigned int add = ct->pack >> (((ct->pack&0xc0)>>6)+24);\r |
| | 1187 | if (ct->pack & (1<<(SLOT3+8))) eg_out += add;\r |
| | 1188 | if (ct->pack & (1<<(SLOT2+8))) eg_out2 += add;\r |
| | 1189 | if (ct->pack & (1<<(SLOT4+8))) eg_out4 += add;\r |
| | 1190 | }\r |
| | 1191 | \r |
| | 1192 | smp = update_algo_channel(ct, eg_out, eg_out2, eg_out4);\r |
| | 1193 | /* done calculating channel sample */\r |
| | 1194 | disabled:\r |
| | 1195 | /* update phase counters AFTER output calculations */\r |
| | 1196 | ct->phase1 += ct->incr1;\r |
| | 1197 | ct->phase2 += ct->incr2;\r |
| | 1198 | ct->phase3 += ct->incr3;\r |
| | 1199 | ct->phase4 += ct->incr4;\r |
| | 1200 | \r |
| | 1201 | /* mix sample to output buffer */\r |
| | 1202 | if (smp) {\r |
| | 1203 | smp = clip(smp); /* saturate to 14 bit */\r |
| | 1204 | if (ct->algo & 0x80) {\r |
| | 1205 | smp &= ~0x1f; /* drop bits (DAC has 9 bits) */\r |
| | 1206 | smp -= (smp < 0 ? 7:0) << 5; /* discontinuity */\r |
| | 1207 | }\r |
| | 1208 | if (ct->pack & 1) { /* stereo */\r |
| | 1209 | if (ct->pack & 0x20) /* L */ /* TODO: check correctness */\r |
| | 1210 | buffer[scounter*2] += smp;\r |
| | 1211 | if (ct->pack & 0x10) /* R */\r |
| | 1212 | buffer[scounter*2+1] += smp;\r |
| | 1213 | } else {\r |
| | 1214 | buffer[scounter] += smp;\r |
| | 1215 | }\r |
| | 1216 | ct->algo |= 8;\r |
| | 1217 | }\r |
| | 1218 | }\r |
| | 1219 | }\r |
| | 1220 | #else\r |
| | 1221 | void chan_render_loop(chan_rend_context *ct, s32 *buffer, unsigned short length);\r |
| | 1222 | #endif\r |
| | 1223 | \r |
| | 1224 | static chan_rend_context crct;\r |
| | 1225 | \r |
| | 1226 | static void chan_render_prep(void)\r |
| | 1227 | {\r |
| | 1228 | crct.eg_timer_add = ym2612.OPN.eg_timer_add;\r |
| | 1229 | crct.lfo_init_sft16 = ym2612.OPN.lfo_ampm << 16;\r |
| | 1230 | crct.lfo_inc = ym2612.OPN.lfo_inc;\r |
| | 1231 | }\r |
| | 1232 | \r |
| | 1233 | static void chan_render_finish(s32 *buffer, int length, int active_chans)\r |
| | 1234 | {\r |
| | 1235 | ym2612.OPN.eg_cnt = crct.eg_cnt;\r |
| | 1236 | ym2612.OPN.eg_timer = crct.eg_timer;\r |
| | 1237 | ym2612.OPN.lfo_cnt += ym2612.OPN.lfo_inc * length;\r |
| | 1238 | }\r |
| | 1239 | \r |
| | 1240 | static UINT32 update_lfo_phase(const FM_SLOT *SLOT, UINT32 block_fnum)\r |
| | 1241 | {\r |
| | 1242 | UINT32 fnum_lfo;\r |
| | 1243 | INT32 lfo_fn_table_index_offset;\r |
| | 1244 | UINT8 blk;\r |
| | 1245 | UINT32 fn;\r |
| | 1246 | int fc,fdt;\r |
| | 1247 | \r |
| | 1248 | fnum_lfo = ((block_fnum & 0x7f0) >> 4) * 32 * 8;\r |
| | 1249 | lfo_fn_table_index_offset = lfo_pm_table[ fnum_lfo + crct.CH->pms + ((crct.pack>>16)&0xff) ];\r |
| | 1250 | if (lfo_fn_table_index_offset) /* LFO phase modulation active */\r |
| | 1251 | {\r |
| | 1252 | block_fnum = block_fnum*2 + lfo_fn_table_index_offset;\r |
| | 1253 | blk = (block_fnum&0x7000) >> 12;\r |
| | 1254 | fn = block_fnum & 0xfff;\r |
| | 1255 | \r |
| | 1256 | /* phase increment counter */\r |
| | 1257 | fc = (fn_table[fn]>>(7-blk));\r |
| | 1258 | \r |
| | 1259 | fdt = fc + SLOT->DT[crct.CH->kcode];\r |
| | 1260 | if (fdt < 0) fdt += fn_table[0x7ff*2] >> 2;\r |
| | 1261 | \r |
| | 1262 | return (fdt * SLOT->mul) >> 1;\r |
| | 1263 | } else\r |
| | 1264 | return SLOT->Incr;\r |
| | 1265 | }\r |
| | 1266 | \r |
| | 1267 | static int chan_render(s32 *buffer, int length, int c, UINT32 flags) // flags: stereo, ?, disabled, ?, pan_r, pan_l\r |
| | 1268 | {\r |
| | 1269 | crct.CH = &ym2612.CH[c];\r |
| | 1270 | crct.mem = crct.CH->mem_value; /* one sample delay memory */\r |
| | 1271 | crct.lfo_cnt = ym2612.OPN.lfo_cnt;\r |
| | 1272 | \r |
| | 1273 | flags &= 0x37;\r |
| | 1274 | \r |
| | 1275 | if (crct.lfo_inc) {\r |
| | 1276 | flags |= 8;\r |
| | 1277 | flags |= crct.lfo_init_sft16;\r |
| | 1278 | flags |= crct.CH->AMmasks << 8;\r |
| | 1279 | if (crct.CH->ams == 8) // no ams\r |
| | 1280 | flags &= ~0xf00;\r |
| | 1281 | else flags |= (crct.CH->ams&3)<<6;\r |
| | 1282 | }\r |
| | 1283 | flags |= (crct.CH->FB&0xf)<<12; /* feedback shift */\r |
| | 1284 | crct.pack = flags;\r |
| | 1285 | \r |
| | 1286 | crct.eg_cnt = ym2612.OPN.eg_cnt; /* envelope generator counter */\r |
| | 1287 | crct.eg_timer = ym2612.OPN.eg_timer;\r |
| | 1288 | \r |
| | 1289 | /* precalculate phase modulation incr */\r |
| | 1290 | crct.phase1 = crct.CH->SLOT[SLOT1].phase;\r |
| | 1291 | crct.phase2 = crct.CH->SLOT[SLOT2].phase;\r |
| | 1292 | crct.phase3 = crct.CH->SLOT[SLOT3].phase;\r |
| | 1293 | crct.phase4 = crct.CH->SLOT[SLOT4].phase;\r |
| | 1294 | \r |
| | 1295 | crct.op1_out = crct.CH->op1_out;\r |
| | 1296 | crct.algo = crct.CH->ALGO & 7;\r |
| | 1297 | crct.algo |= crct.CH->upd_cnt << 4;\r |
| | 1298 | if (ym2612.OPN.ST.flags & ST_DAC)\r |
| | 1299 | crct.algo |= 0x80;\r |
| | 1300 | \r |
| | 1301 | if(crct.CH->pms && (ym2612.OPN.ST.mode & 0xC0) && c == 2) {\r |
| | 1302 | /* 3 slot mode */\r |
| | 1303 | crct.incr1 = update_lfo_phase(&crct.CH->SLOT[SLOT1], ym2612.OPN.SL3.block_fnum[1]);\r |
| | 1304 | crct.incr2 = update_lfo_phase(&crct.CH->SLOT[SLOT2], ym2612.OPN.SL3.block_fnum[2]);\r |
| | 1305 | crct.incr3 = update_lfo_phase(&crct.CH->SLOT[SLOT3], ym2612.OPN.SL3.block_fnum[0]);\r |
| | 1306 | crct.incr4 = update_lfo_phase(&crct.CH->SLOT[SLOT4], crct.CH->block_fnum);\r |
| | 1307 | }\r |
| | 1308 | else if(crct.CH->pms)\r |
| | 1309 | {\r |
| | 1310 | crct.incr1 = update_lfo_phase(&crct.CH->SLOT[SLOT1], crct.CH->block_fnum);\r |
| | 1311 | crct.incr2 = update_lfo_phase(&crct.CH->SLOT[SLOT2], crct.CH->block_fnum);\r |
| | 1312 | crct.incr3 = update_lfo_phase(&crct.CH->SLOT[SLOT3], crct.CH->block_fnum);\r |
| | 1313 | crct.incr4 = update_lfo_phase(&crct.CH->SLOT[SLOT4], crct.CH->block_fnum);\r |
| | 1314 | }\r |
| | 1315 | else /* no LFO phase modulation */\r |
| | 1316 | {\r |
| | 1317 | crct.incr1 = crct.CH->SLOT[SLOT1].Incr;\r |
| | 1318 | crct.incr2 = crct.CH->SLOT[SLOT2].Incr;\r |
| | 1319 | crct.incr3 = crct.CH->SLOT[SLOT3].Incr;\r |
| | 1320 | crct.incr4 = crct.CH->SLOT[SLOT4].Incr;\r |
| | 1321 | }\r |
| | 1322 | \r |
| | 1323 | chan_render_loop(&crct, buffer, length);\r |
| | 1324 | \r |
| | 1325 | crct.CH->op1_out = crct.op1_out;\r |
| | 1326 | crct.CH->mem_value = crct.mem;\r |
| | 1327 | if (crct.CH->SLOT[SLOT1].state | crct.CH->SLOT[SLOT2].state | crct.CH->SLOT[SLOT3].state | crct.CH->SLOT[SLOT4].state)\r |
| | 1328 | {\r |
| | 1329 | crct.CH->SLOT[SLOT1].phase = crct.phase1;\r |
| | 1330 | crct.CH->SLOT[SLOT2].phase = crct.phase2;\r |
| | 1331 | crct.CH->SLOT[SLOT3].phase = crct.phase3;\r |
| | 1332 | crct.CH->SLOT[SLOT4].phase = crct.phase4;\r |
| | 1333 | }\r |
| | 1334 | else\r |
| | 1335 | ym2612.slot_mask &= ~(0xf << (c*4));\r |
| | 1336 | crct.CH->upd_cnt = (crct.algo >> 4) & 0x7;\r |
| | 1337 | \r |
| | 1338 | return (crct.algo & 8) >> 3; // had output\r |
| | 1339 | }\r |
| | 1340 | \r |
| | 1341 | /* update phase increment and envelope generator */\r |
| | 1342 | static INLINE void refresh_fc_eg_slot(FM_SLOT *SLOT, int fc, int kc)\r |
| | 1343 | {\r |
| | 1344 | int ksr, fdt;\r |
| | 1345 | \r |
| | 1346 | /* (frequency) phase increment counter */\r |
| | 1347 | fdt = fc+SLOT->DT[kc];\r |
| | 1348 | /* detect overflow */\r |
| | 1349 | // if (fdt < 0) fdt += fn_table[0x7ff*2] >> (7-blk-1);\r |
| | 1350 | if (fdt < 0) fdt += fn_table[0x7ff*2] >> 2;\r |
| | 1351 | SLOT->Incr = fdt*SLOT->mul >> 1;\r |
| | 1352 | \r |
| | 1353 | ksr = kc >> SLOT->KSR;\r |
| | 1354 | if( SLOT->ksr != ksr )\r |
| | 1355 | {\r |
| | 1356 | int eg_sh, eg_sel;\r |
| | 1357 | SLOT->ksr = ksr;\r |
| | 1358 | SLOT->ar_ksr = SLOT->ar + ksr;\r |
| | 1359 | \r |
| | 1360 | /* calculate envelope generator rates */\r |
| | 1361 | if ((SLOT->ar_ksr) < 32+62)\r |
| | 1362 | {\r |
| | 1363 | eg_sh = eg_rate_shift [SLOT->ar_ksr];\r |
| | 1364 | eg_sel = eg_rate_select[SLOT->ar_ksr];\r |
| | 1365 | }\r |
| | 1366 | else\r |
| | 1367 | {\r |
| | 1368 | eg_sh = 0;\r |
| | 1369 | eg_sel = 18;\r |
| | 1370 | }\r |
| | 1371 | \r |
| | 1372 | SLOT->eg_pack_ar = eg_inc_pack[eg_sel] | (eg_sh<<24);\r |
| | 1373 | \r |
| | 1374 | eg_sh = eg_rate_shift [SLOT->d1r + ksr];\r |
| | 1375 | eg_sel = eg_rate_select[SLOT->d1r + ksr];\r |
| | 1376 | \r |
| | 1377 | SLOT->eg_pack_d1r = eg_inc_pack[eg_sel] | (eg_sh<<24);\r |
| | 1378 | \r |
| | 1379 | eg_sh = eg_rate_shift [SLOT->d2r + ksr];\r |
| | 1380 | eg_sel = eg_rate_select[SLOT->d2r + ksr];\r |
| | 1381 | \r |
| | 1382 | SLOT->eg_pack_d2r = eg_inc_pack[eg_sel] | (eg_sh<<24);\r |
| | 1383 | \r |
| | 1384 | eg_sh = eg_rate_shift [SLOT->rr + ksr];\r |
| | 1385 | eg_sel = eg_rate_select[SLOT->rr + ksr];\r |
| | 1386 | \r |
| | 1387 | SLOT->eg_pack_rr = eg_inc_pack[eg_sel] | (eg_sh<<24);\r |
| | 1388 | }\r |
| | 1389 | }\r |
| | 1390 | \r |
| | 1391 | /* update phase increment counters */\r |
| | 1392 | static INLINE void refresh_fc_eg_chan(FM_CH *CH)\r |
| | 1393 | {\r |
| | 1394 | if( CH->SLOT[SLOT1].Incr==-1){\r |
| | 1395 | int fc = CH->fc;\r |
| | 1396 | int kc = CH->kcode;\r |
| | 1397 | refresh_fc_eg_slot(&CH->SLOT[SLOT1] , fc , kc );\r |
| | 1398 | refresh_fc_eg_slot(&CH->SLOT[SLOT2] , fc , kc );\r |
| | 1399 | refresh_fc_eg_slot(&CH->SLOT[SLOT3] , fc , kc );\r |
| | 1400 | refresh_fc_eg_slot(&CH->SLOT[SLOT4] , fc , kc );\r |
| | 1401 | }\r |
| | 1402 | }\r |
| | 1403 | \r |
| | 1404 | static INLINE void refresh_fc_eg_chan_sl3(void)\r |
| | 1405 | {\r |
| | 1406 | if( ym2612.CH[2].SLOT[SLOT1].Incr==-1)\r |
| | 1407 | {\r |
| | 1408 | refresh_fc_eg_slot(&ym2612.CH[2].SLOT[SLOT1], ym2612.OPN.SL3.fc[1], ym2612.OPN.SL3.kcode[1] );\r |
| | 1409 | refresh_fc_eg_slot(&ym2612.CH[2].SLOT[SLOT2], ym2612.OPN.SL3.fc[2], ym2612.OPN.SL3.kcode[2] );\r |
| | 1410 | refresh_fc_eg_slot(&ym2612.CH[2].SLOT[SLOT3], ym2612.OPN.SL3.fc[0], ym2612.OPN.SL3.kcode[0] );\r |
| | 1411 | refresh_fc_eg_slot(&ym2612.CH[2].SLOT[SLOT4], ym2612.CH[2].fc , ym2612.CH[2].kcode );\r |
| | 1412 | }\r |
| | 1413 | }\r |
| | 1414 | \r |
| | 1415 | /* initialize time tables */\r |
| | 1416 | static void init_timetables(const UINT8 *dttable)\r |
| | 1417 | {\r |
| | 1418 | int i,d;\r |
| | 1419 | double rate;\r |
| | 1420 | \r |
| | 1421 | /* DeTune table */\r |
| | 1422 | for (d = 0;d <= 3;d++){\r |
| | 1423 | for (i = 0;i <= 31;i++){\r |
| | 1424 | rate = ((double)dttable[d*32 + i]) * ym2612.OPN.ST.freqbase * (1<<(FREQ_SH-10));\r |
| | 1425 | ym2612.OPN.ST.dt_tab[d][i] = (INT32) rate;\r |
| | 1426 | ym2612.OPN.ST.dt_tab[d+4][i] = -ym2612.OPN.ST.dt_tab[d][i];\r |
| | 1427 | }\r |
| | 1428 | }\r |
| | 1429 | }\r |
| | 1430 | \r |
| | 1431 | \r |
| | 1432 | static void reset_channels(FM_CH *CH)\r |
| | 1433 | {\r |
| | 1434 | int c,s;\r |
| | 1435 | \r |
| | 1436 | ym2612.OPN.ST.mode = 0; /* normal mode */\r |
| | 1437 | ym2612.OPN.ST.TA = 0;\r |
| | 1438 | //ym2612.OPN.ST.TAC = 0;\r |
| | 1439 | ym2612.OPN.ST.TB = 0;\r |
| | 1440 | //ym2612.OPN.ST.TBC = 0;\r |
| | 1441 | \r |
| | 1442 | for( c = 0 ; c < 6 ; c++ )\r |
| | 1443 | {\r |
| | 1444 | CH[c].fc = 0;\r |
| | 1445 | for(s = 0 ; s < 4 ; s++ )\r |
| | 1446 | {\r |
| | 1447 | CH[c].SLOT[s].Incr = -1;\r |
| | 1448 | CH[c].SLOT[s].key = 0;\r |
| | 1449 | CH[c].SLOT[s].phase = 0;\r |
| | 1450 | CH[c].SLOT[s].ar = CH[c].SLOT[s].ksr = 0;\r |
| | 1451 | CH[c].SLOT[s].ar_ksr = 0;\r |
| | 1452 | CH[c].SLOT[s].ssg = CH[c].SLOT[s].ssgn = 0;\r |
| | 1453 | CH[c].SLOT[s].state= EG_OFF;\r |
| | 1454 | CH[c].SLOT[s].volume = MAX_ATT_INDEX;\r |
| | 1455 | CH[c].SLOT[s].vol_out = MAX_ATT_INDEX;\r |
| | 1456 | }\r |
| | 1457 | CH[c].mem_value = CH[c].op1_out = 0;\r |
| | 1458 | }\r |
| | 1459 | ym2612.slot_mask = 0;\r |
| | 1460 | ym2612.ssg_mask = 0;\r |
| | 1461 | }\r |
| | 1462 | \r |
| | 1463 | /* initialize generic tables */\r |
| | 1464 | static void init_tables(void)\r |
| | 1465 | {\r |
| | 1466 | signed int i,x,y,p;\r |
| | 1467 | signed int n;\r |
| | 1468 | double o,m;\r |
| | 1469 | \r |
| | 1470 | if (ym_init_tab) return;\r |
| | 1471 | ym_init_tab = 1;\r |
| | 1472 | \r |
| | 1473 | for (i=0; i < 256; i++)\r |
| | 1474 | {\r |
| | 1475 | /* non-standard sinus */\r |
| | 1476 | m = sin( ((i*2)+1) * M_PI / SIN_LEN ); /* checked against the real chip */\r |
| | 1477 | \r |
| | 1478 | /* we never reach zero here due to ((i*2)+1) */\r |
| | 1479 | \r |
| | 1480 | if (m>0.0)\r |
| | 1481 | o = 8*log(1.0/m)/log(2); /* convert to 'decibels' */\r |
| | 1482 | else\r |
| | 1483 | o = 8*log(-1.0/m)/log(2); /* convert to 'decibels' */\r |
| | 1484 | \r |
| | 1485 | o = o / (ENV_STEP/4);\r |
| | 1486 | \r |
| | 1487 | n = (int)(2.0*o);\r |
| | 1488 | if (n&1) /* round to nearest */\r |
| | 1489 | n = (n>>1)+1;\r |
| | 1490 | else\r |
| | 1491 | n = n>>1;\r |
| | 1492 | \r |
| | 1493 | ym_sin_tab[ i ] = n;\r |
| | 1494 | //dprintf("FM.C: sin [%4i]= %4i", i, ym_sin_tab[i]);\r |
| | 1495 | }\r |
| | 1496 | \r |
| | 1497 | //dprintf("FM.C: ENV_QUIET= %08x", ENV_QUIET );\r |
| | 1498 | \r |
| | 1499 | \r |
| | 1500 | for (x=0; x < TL_RES_LEN; x++)\r |
| | 1501 | {\r |
| | 1502 | m = (1<<16) / pow(2, (x+1) * (ENV_STEP/4.0) / 8.0);\r |
| | 1503 | m = floor(m);\r |
| | 1504 | \r |
| | 1505 | /* we never reach (1<<16) here due to the (x+1) */\r |
| | 1506 | /* result fits within 16 bits at maximum */\r |
| | 1507 | \r |
| | 1508 | n = (int)m; /* 16 bits here */\r |
| | 1509 | n >>= 4; /* 12 bits here */\r |
| | 1510 | if (n&1) /* round to nearest */\r |
| | 1511 | n = (n>>1)+1;\r |
| | 1512 | else\r |
| | 1513 | n = n>>1;\r |
| | 1514 | /* 11 bits here (rounded) */\r |
| | 1515 | n <<= 2; /* 13 bits here (as in real chip) */\r |
| | 1516 | ym_tl_tab2[ x ] = n;\r |
| | 1517 | \r |
| | 1518 | for (i=1; i < 13; i++)\r |
| | 1519 | {\r |
| | 1520 | ym_tl_tab2[ x + i*TL_RES_LEN ] = n >> i;\r |
| | 1521 | }\r |
| | 1522 | }\r |
| | 1523 | \r |
| | 1524 | for (x=0; x < 256; x++)\r |
| | 1525 | {\r |
| | 1526 | int sin = ym_sin_tab[ x ];\r |
| | 1527 | \r |
| | 1528 | for (y=0; y < 2*13*TL_RES_LEN/8; y+=2)\r |
| | 1529 | {\r |
| | 1530 | p = (y<<2) + sin;\r |
| | 1531 | if (p >= 13*TL_RES_LEN)\r |
| | 1532 | ym_tl_tab[(y<<7) | x] = 0;\r |
| | 1533 | else ym_tl_tab[(y<<7) | x] = ym_tl_tab2[p];\r |
| | 1534 | }\r |
| | 1535 | }\r |
| | 1536 | \r |
| | 1537 | \r |
| | 1538 | /* build LFO PM modulation table */\r |
| | 1539 | for(i = 0; i < 8; i++) /* 8 PM depths */\r |
| | 1540 | {\r |
| | 1541 | UINT8 fnum;\r |
| | 1542 | for (fnum=0; fnum<128; fnum++) /* 7 bits meaningful of F-NUMBER */\r |
| | 1543 | {\r |
| | 1544 | UINT8 value;\r |
| | 1545 | UINT8 step;\r |
| | 1546 | UINT32 offset_depth = i;\r |
| | 1547 | UINT32 offset_fnum_bit;\r |
| | 1548 | UINT32 bit_tmp;\r |
| | 1549 | \r |
| | 1550 | for (step=0; step<8; step++)\r |
| | 1551 | {\r |
| | 1552 | value = 0;\r |
| | 1553 | for (bit_tmp=0; bit_tmp<7; bit_tmp++) /* 7 bits */\r |
| | 1554 | {\r |
| | 1555 | if (fnum & (1<<bit_tmp)) /* only if bit "bit_tmp" is set */\r |
| | 1556 | {\r |
| | 1557 | offset_fnum_bit = bit_tmp * 8;\r |
| | 1558 | value += lfo_pm_output[offset_fnum_bit + offset_depth][step];\r |
| | 1559 | }\r |
| | 1560 | }\r |
| | 1561 | lfo_pm_table[(fnum*32*8) + (i*32) + step + 0] = value;\r |
| | 1562 | lfo_pm_table[(fnum*32*8) + (i*32) +(step^7)+ 8] = value;\r |
| | 1563 | lfo_pm_table[(fnum*32*8) + (i*32) + step +16] = -value;\r |
| | 1564 | lfo_pm_table[(fnum*32*8) + (i*32) +(step^7)+24] = -value;\r |
| | 1565 | }\r |
| | 1566 | }\r |
| | 1567 | }\r |
| | 1568 | }\r |
| | 1569 | \r |
| | 1570 | \r |
| | 1571 | /* CSM Key Controll */\r |
| | 1572 | #if 0\r |
| | 1573 | INLINE void CSMKeyControll(FM_CH *CH)\r |
| | 1574 | {\r |
| | 1575 | /* this is wrong, atm */\r |
| | 1576 | \r |
| | 1577 | /* all key on */\r |
| | 1578 | FM_KEYON(CH,SLOT1);\r |
| | 1579 | FM_KEYON(CH,SLOT2);\r |
| | 1580 | FM_KEYON(CH,SLOT3);\r |
| | 1581 | FM_KEYON(CH,SLOT4);\r |
| | 1582 | }\r |
| | 1583 | #endif\r |
| | 1584 | \r |
| | 1585 | \r |
| | 1586 | /* prescaler set (and make time tables) */\r |
| | 1587 | static void OPNSetPres(int pres)\r |
| | 1588 | {\r |
| | 1589 | int i;\r |
| | 1590 | \r |
| | 1591 | /* frequency base */\r |
| | 1592 | double freqbase = (ym2612.OPN.ST.rate) ? ((double)ym2612.OPN.ST.clock / ym2612.OPN.ST.rate) / pres : 0;\r |
| | 1593 | \r |
| | 1594 | ym2612.OPN.eg_timer_add = (1<<EG_SH) * freqbase;\r |
| | 1595 | ym2612.OPN.ST.freqbase = freqbase;\r |
| | 1596 | \r |
| | 1597 | /* make time tables */\r |
| | 1598 | init_timetables( dt_tab );\r |
| | 1599 | \r |
| | 1600 | /* there are 2048 FNUMs that can be generated using FNUM/BLK registers\r |
| | 1601 | but LFO works with one more bit of a precision so we really need 4096 elements */\r |
| | 1602 | /* calculate fnumber -> increment counter table */\r |
| | 1603 | for(i = 0; i < 4096; i++)\r |
| | 1604 | {\r |
| | 1605 | /* freq table for octave 7 */\r |
| | 1606 | /* OPN phase increment counter = 20bit */\r |
| | 1607 | fn_table[i] = (UINT32)( (double)i * 32 * ym2612.OPN.ST.freqbase * (1<<(FREQ_SH-10)) ); /* -10 because chip works with 10.10 fixed point, while we use 16.16 */\r |
| | 1608 | }\r |
| | 1609 | \r |
| | 1610 | /* LFO freq. table */\r |
| | 1611 | for(i = 0; i < 8; i++)\r |
| | 1612 | {\r |
| | 1613 | /* Amplitude modulation: 64 output levels (triangle waveform); 1 level lasts for one of "lfo_samples_per_step" samples */\r |
| | 1614 | /* Phase modulation: one entry from lfo_pm_output lasts for one of 4 * "lfo_samples_per_step" samples */\r |
| | 1615 | ym2612.OPN.lfo_freq[i] = (1.0 / lfo_samples_per_step[i]) * (1<<LFO_SH) * ym2612.OPN.ST.freqbase;\r |
| | 1616 | }\r |
| | 1617 | }\r |
| | 1618 | \r |
| | 1619 | \r |
| | 1620 | /* write a OPN register (0x30-0xff) */\r |
| | 1621 | static int OPNWriteReg(int r, int v)\r |
| | 1622 | {\r |
| | 1623 | int ret = 1;\r |
| | 1624 | FM_CH *CH;\r |
| | 1625 | FM_SLOT *SLOT;\r |
| | 1626 | \r |
| | 1627 | UINT8 c = OPN_CHAN(r);\r |
| | 1628 | \r |
| | 1629 | if (c == 3) return 0; /* 0xX3,0xX7,0xXB,0xXF */\r |
| | 1630 | \r |
| | 1631 | if (r >= 0x100) c+=3;\r |
| | 1632 | \r |
| | 1633 | CH = &ym2612.CH[c];\r |
| | 1634 | \r |
| | 1635 | SLOT = &(CH->SLOT[OPN_SLOT(r)]);\r |
| | 1636 | \r |
| | 1637 | switch( r & 0xf0 ) {\r |
| | 1638 | case 0x30: /* DET , MUL */\r |
| | 1639 | set_det_mul(CH,SLOT,v);\r |
| | 1640 | break;\r |
| | 1641 | \r |
| | 1642 | case 0x40: /* TL */\r |
| | 1643 | set_tl(SLOT,v);\r |
| | 1644 | break;\r |
| | 1645 | \r |
| | 1646 | case 0x50: /* KS, AR */\r |
| | 1647 | set_ar_ksr(CH,SLOT,v);\r |
| | 1648 | break;\r |
| | 1649 | \r |
| | 1650 | case 0x60: /* bit7 = AM ENABLE, DR | depends on ksr */\r |
| | 1651 | set_dr(SLOT,v);\r |
| | 1652 | if(v&0x80) CH->AMmasks |= 1<<OPN_SLOT(r);\r |
| | 1653 | else CH->AMmasks &= ~(1<<OPN_SLOT(r));\r |
| | 1654 | break;\r |
| | 1655 | \r |
| | 1656 | case 0x70: /* SR | depends on ksr */\r |
| | 1657 | set_sr(SLOT,v);\r |
| | 1658 | break;\r |
| | 1659 | \r |
| | 1660 | case 0x80: /* SL, RR | depends on ksr */\r |
| | 1661 | set_sl_rr(SLOT,v);\r |
| | 1662 | break;\r |
| | 1663 | \r |
| | 1664 | case 0x90: /* SSG-EG */\r |
| | 1665 | SLOT->ssg = v&0x0f;\r |
| | 1666 | SLOT->ssg ^= SLOT->ssgn;\r |
| | 1667 | if (v&0x08) ym2612.ssg_mask |= 1<<(OPN_SLOT(r) + c*4);\r |
| | 1668 | else ym2612.ssg_mask &= ~(1<<(OPN_SLOT(r) + c*4));\r |
| | 1669 | if (SLOT->state > EG_REL)\r |
| | 1670 | recalc_volout(SLOT);\r |
| | 1671 | break;\r |
| | 1672 | \r |
| | 1673 | case 0xa0:\r |
| | 1674 | switch( OPN_SLOT(r) ){\r |
| | 1675 | case 0: /* 0xa0-0xa2 : FNUM1 | depends on fn_h (below) */\r |
| | 1676 | {\r |
| | 1677 | UINT32 fn = ((UINT32)(ym2612.OPN.ST.fn_h & 7) << 8) | v;\r |
| | 1678 | UINT8 blk = ym2612.OPN.ST.fn_h >> 3;\r |
| | 1679 | /* keyscale code */\r |
| | 1680 | CH->kcode = (blk<<2) | opn_fktable[fn >> 7];\r |
| | 1681 | /* phase increment counter */\r |
| | 1682 | CH->fc = fn_table[fn*2]>>(7-blk);\r |
| | 1683 | \r |
| | 1684 | /* store fnum in clear form for LFO PM calculations */\r |
| | 1685 | CH->block_fnum = (blk<<11) | fn;\r |
| | 1686 | \r |
| | 1687 | CH->SLOT[SLOT1].Incr=-1;\r |
| | 1688 | }\r |
| | 1689 | break;\r |
| | 1690 | case 1: /* 0xa4-0xa6 : FNUM2,BLK */\r |
| | 1691 | ym2612.OPN.ST.fn_h = v & 0x3f;\r |
| | 1692 | ret = 0;\r |
| | 1693 | break;\r |
| | 1694 | case 2: /* 0xa8-0xaa : 3CH FNUM1 */\r |
| | 1695 | if(r < 0x100)\r |
| | 1696 | {\r |
| | 1697 | UINT32 fn = (((UINT32)(ym2612.OPN.SL3.fn_h&7))<<8) + v;\r |
| | 1698 | UINT8 blk = ym2612.OPN.SL3.fn_h>>3;\r |
| | 1699 | /* keyscale code */\r |
| | 1700 | ym2612.OPN.SL3.kcode[c]= (blk<<2) | opn_fktable[fn >> 7];\r |
| | 1701 | /* phase increment counter */\r |
| | 1702 | ym2612.OPN.SL3.fc[c] = fn_table[fn*2]>>(7-blk);\r |
| | 1703 | ym2612.OPN.SL3.block_fnum[c] = (blk<<11) | fn;\r |
| | 1704 | ym2612.CH[2].SLOT[SLOT1].Incr=-1;\r |
| | 1705 | }\r |
| | 1706 | break;\r |
| | 1707 | case 3: /* 0xac-0xae : 3CH FNUM2,BLK */\r |
| | 1708 | if(r < 0x100)\r |
| | 1709 | ym2612.OPN.SL3.fn_h = v&0x3f;\r |
| | 1710 | ret = 0;\r |
| | 1711 | break;\r |
| | 1712 | default:\r |
| | 1713 | ret = 0;\r |
| | 1714 | break;\r |
| | 1715 | }\r |
| | 1716 | break;\r |
| | 1717 | \r |
| | 1718 | case 0xb0:\r |
| | 1719 | switch( OPN_SLOT(r) ){\r |
| | 1720 | case 0: /* 0xb0-0xb2 : FB,ALGO */\r |
| | 1721 | {\r |
| | 1722 | int feedback = (v>>3)&7;\r |
| | 1723 | CH->ALGO = v&7;\r |
| | 1724 | CH->FB = feedback ? feedback+6 : 0;\r |
| | 1725 | }\r |
| | 1726 | break;\r |
| | 1727 | case 1: /* 0xb4-0xb6 : L , R , AMS , PMS (YM2612/YM2610B/YM2610/YM2608) */\r |
| | 1728 | {\r |
| | 1729 | int panshift = c<<1;\r |
| | 1730 | \r |
| | 1731 | /* b0-2 PMS */\r |
| | 1732 | CH->pms = (v & 7) * 32; /* CH->pms = PM depth * 32 (index in lfo_pm_table) */\r |
| | 1733 | \r |
| | 1734 | /* b4-5 AMS */\r |
| | 1735 | CH->ams = lfo_ams_depth_shift[(v>>4) & 3];\r |
| | 1736 | \r |
| | 1737 | /* PAN : b7 = L, b6 = R */\r |
| | 1738 | ym2612.OPN.pan &= ~(3<<panshift);\r |
| | 1739 | ym2612.OPN.pan |= ((v & 0xc0) >> 6) << panshift; // ..LRLR\r |
| | 1740 | }\r |
| | 1741 | break;\r |
| | 1742 | default:\r |
| | 1743 | ret = 0;\r |
| | 1744 | break;\r |
| | 1745 | }\r |
| | 1746 | break;\r |
| | 1747 | default:\r |
| | 1748 | ret = 0;\r |
| | 1749 | break;\r |
| | 1750 | }\r |
| | 1751 | \r |
| | 1752 | return ret;\r |
| | 1753 | }\r |
| | 1754 | \r |
| | 1755 | \r |
| | 1756 | /*******************************************************************************/\r |
| | 1757 | /* YM2612 local section */\r |
| | 1758 | /*******************************************************************************/\r |
| | 1759 | \r |
| | 1760 | /* Generate samples for YM2612 */\r |
| | 1761 | int YM2612UpdateOne_(s32 *buffer, int length, int stereo, int is_buf_empty)\r |
| | 1762 | {\r |
| | 1763 | int pan;\r |
| | 1764 | int active_chs = 0;\r |
| | 1765 | int flags = stereo ? 1:0;\r |
| | 1766 | \r |
| | 1767 | // if !is_buf_empty, it means it has valid samples to mix with, else it may contain trash\r |
| | 1768 | if (is_buf_empty) memset32(buffer, 0, length<<stereo);\r |
| | 1769 | \r |
| | 1770 | /*\r |
| | 1771 | {\r |
| | 1772 | int c, s;\r |
| | 1773 | ppp();\r |
| | 1774 | for (c = 0; c < 6; c++) {\r |
| | 1775 | int slr = 0, slm;\r |
| | 1776 | printf("%i: ", c);\r |
| | 1777 | for (s = 0; s < 4; s++) {\r |
| | 1778 | if (ym2612.CH[c].SLOT[s].state != EG_OFF) slr = 1;\r |
| | 1779 | printf(" %i", ym2612.CH[c].SLOT[s].state != EG_OFF);\r |
| | 1780 | }\r |
| | 1781 | slm = (ym2612.slot_mask&(0xf<<(c*4))) ? 1 : 0;\r |
| | 1782 | printf(" | %i", slm);\r |
| | 1783 | printf(" | %i\n", ym2612.CH[c].SLOT[SLOT1].Incr==-1);\r |
| | 1784 | if (slr != slm) exit(1);\r |
| | 1785 | }\r |
| | 1786 | }\r |
| | 1787 | */\r |
| | 1788 | /* refresh PG and EG */\r |
| | 1789 | refresh_fc_eg_chan( &ym2612.CH[0] );\r |
| | 1790 | refresh_fc_eg_chan( &ym2612.CH[1] );\r |
| | 1791 | if( (ym2612.OPN.ST.mode & 0xc0) )\r |
| | 1792 | /* 3SLOT MODE */\r |
| | 1793 | refresh_fc_eg_chan_sl3();\r |
| | 1794 | else\r |
| | 1795 | refresh_fc_eg_chan( &ym2612.CH[2] );\r |
| | 1796 | refresh_fc_eg_chan( &ym2612.CH[3] );\r |
| | 1797 | refresh_fc_eg_chan( &ym2612.CH[4] );\r |
| | 1798 | refresh_fc_eg_chan( &ym2612.CH[5] );\r |
| | 1799 | \r |
| | 1800 | pan = ym2612.OPN.pan;\r |
| | 1801 | \r |
| | 1802 | /* mix to 32bit dest */\r |
| | 1803 | // flags: stereo, ssg_enabled, disabled, _, pan_r, pan_l\r |
| | 1804 | chan_render_prep();\r |
| | 1805 | #define BIT_IF(v,b,c) { v &= ~(1<<(b)); if (c) v |= 1<<(b); }\r |
| | 1806 | BIT_IF(flags, 1, (ym2612.ssg_mask & 0x00000f) && (ym2612.OPN.ST.flags & 1));\r |
| | 1807 | if (ym2612.slot_mask & 0x00000f) active_chs |= chan_render(buffer, length, 0, flags|((pan&0x003)<<4)) << 0;\r |
| | 1808 | BIT_IF(flags, 1, (ym2612.ssg_mask & 0x0000f0) && (ym2612.OPN.ST.flags & 1));\r |
| | 1809 | if (ym2612.slot_mask & 0x0000f0) active_chs |= chan_render(buffer, length, 1, flags|((pan&0x00c)<<2)) << 1;\r |
| | 1810 | BIT_IF(flags, 1, (ym2612.ssg_mask & 0x000f00) && (ym2612.OPN.ST.flags & 1));\r |
| | 1811 | if (ym2612.slot_mask & 0x000f00) active_chs |= chan_render(buffer, length, 2, flags|((pan&0x030) )) << 2;\r |
| | 1812 | BIT_IF(flags, 1, (ym2612.ssg_mask & 0x00f000) && (ym2612.OPN.ST.flags & 1));\r |
| | 1813 | if (ym2612.slot_mask & 0x00f000) active_chs |= chan_render(buffer, length, 3, flags|((pan&0x0c0)>>2)) << 3;\r |
| | 1814 | BIT_IF(flags, 1, (ym2612.ssg_mask & 0x0f0000) && (ym2612.OPN.ST.flags & 1));\r |
| | 1815 | if (ym2612.slot_mask & 0x0f0000) active_chs |= chan_render(buffer, length, 4, flags|((pan&0x300)>>4)) << 4;\r |
| | 1816 | ym2612.OPN.lfo_ampm = crct.pack >> 16; // need_save; now because ch5 might skip updating it\r |
| | 1817 | BIT_IF(flags, 1, (ym2612.ssg_mask & 0xf00000) && (ym2612.OPN.ST.flags & 1));\r |
| | 1818 | if (ym2612.slot_mask & 0xf00000) active_chs |= chan_render(buffer, length, 5, flags|((pan&0xc00)>>6)|(!!ym2612.dacen<<2)) << 5;\r |
| | 1819 | #undef BIT_IF\r |
| | 1820 | chan_render_finish(buffer, length, active_chs);\r |
| | 1821 | \r |
| | 1822 | return active_chs; // 1 if buffer updated\r |
| | 1823 | }\r |
| | 1824 | \r |
| | 1825 | \r |
| | 1826 | /* initialize YM2612 emulator */\r |
| | 1827 | void YM2612Init_(int clock, int rate, int flags)\r |
| | 1828 | {\r |
| | 1829 | memset(&ym2612, 0, sizeof(ym2612));\r |
| | 1830 | init_tables();\r |
| | 1831 | \r |
| | 1832 | ym2612.OPN.ST.clock = clock;\r |
| | 1833 | ym2612.OPN.ST.rate = rate;\r |
| | 1834 | ym2612.OPN.ST.flags = flags;\r |
| | 1835 | \r |
| | 1836 | OPNSetPres( 6*24 );\r |
| | 1837 | \r |
| | 1838 | /* Extend handler */\r |
| | 1839 | YM2612ResetChip_();\r |
| | 1840 | }\r |
| | 1841 | \r |
| | 1842 | \r |
| | 1843 | /* reset */\r |
| | 1844 | void YM2612ResetChip_(void)\r |
| | 1845 | {\r |
| | 1846 | int i;\r |
| | 1847 | \r |
| | 1848 | memset(ym2612.REGS, 0, sizeof(ym2612.REGS));\r |
| | 1849 | \r |
| | 1850 | set_timers( 0x30 ); /* mode 0 , timer reset */\r |
| | 1851 | ym2612.REGS[0x27] = 0x30;\r |
| | 1852 | \r |
| | 1853 | ym2612.OPN.eg_timer = 0;\r |
| | 1854 | ym2612.OPN.eg_cnt = 0;\r |
| | 1855 | ym2612.OPN.lfo_inc = 0;\r |
| | 1856 | ym2612.OPN.lfo_cnt = 0;\r |
| | 1857 | ym2612.OPN.lfo_ampm = 126 << 8;\r |
| | 1858 | ym2612.OPN.ST.status = 0;\r |
| | 1859 | \r |
| | 1860 | reset_channels( &ym2612.CH[0] );\r |
| | 1861 | for(i = 0xb6 ; i >= 0xb4 ; i-- )\r |
| | 1862 | {\r |
| | 1863 | OPNWriteReg(i ,0xc0);\r |
| | 1864 | OPNWriteReg(i|0x100,0xc0);\r |
| | 1865 | ym2612.REGS[i ] = 0xc0;\r |
| | 1866 | ym2612.REGS[i|0x100] = 0xc0;\r |
| | 1867 | }\r |
| | 1868 | for(i = 0xb2 ; i >= 0x30 ; i-- )\r |
| | 1869 | {\r |
| | 1870 | OPNWriteReg(i ,0);\r |
| | 1871 | OPNWriteReg(i|0x100,0);\r |
| | 1872 | }\r |
| | 1873 | for(i = 0x26 ; i >= 0x20 ; i-- ) OPNWriteReg(i,0);\r |
| | 1874 | /* DAC mode clear */\r |
| | 1875 | ym2612.dacen = 0;\r |
| | 1876 | ym2612.dacout = 0;\r |
| | 1877 | ym2612.addr_A1 = 0;\r |
| | 1878 | }\r |
| | 1879 | \r |
| | 1880 | \r |
| | 1881 | /* YM2612 write */\r |
| | 1882 | /* a = address */\r |
| | 1883 | /* v = value */\r |
| | 1884 | /* returns 1 if sample affecting state changed */\r |
| | 1885 | int YM2612Write_(unsigned int a, unsigned int v)\r |
| | 1886 | {\r |
| | 1887 | int addr, ret=1;\r |
| | 1888 | \r |
| | 1889 | v &= 0xff; /* adjust to 8 bit bus */\r |
| | 1890 | \r |
| | 1891 | switch( a & 3 ){\r |
| | 1892 | case 0: /* address port 0 */\r |
| | 1893 | case 2: /* address port 1 */\r |
| | 1894 | /* reminder: this is not used, see ym2612_write_local() */\r |
| | 1895 | ym2612.OPN.ST.address = v;\r |
| | 1896 | ym2612.addr_A1 = (a & 2) >> 1;\r |
| | 1897 | ret = 0;\r |
| | 1898 | break;\r |
| | 1899 | \r |
| | 1900 | case 1:\r |
| | 1901 | case 3: /* data port */\r |
| | 1902 | addr = ym2612.OPN.ST.address | ((int)ym2612.addr_A1 << 8);\r |
| | 1903 | \r |
| | 1904 | switch( addr & 0x1f0 )\r |
| | 1905 | {\r |
| | 1906 | case 0x20: /* 0x20-0x2f Mode */\r |
| | 1907 | switch( addr )\r |
| | 1908 | {\r |
| | 1909 | case 0x22: /* LFO FREQ (YM2608/YM2610/YM2610B/YM2612) */\r |
| | 1910 | if (v&0x08) /* LFO enabled ? */\r |
| | 1911 | {\r |
| | 1912 | ym2612.OPN.lfo_inc = ym2612.OPN.lfo_freq[v&7];\r |
| | 1913 | }\r |
| | 1914 | else\r |
| | 1915 | {\r |
| | 1916 | ym2612.OPN.lfo_inc = 0;\r |
| | 1917 | ym2612.OPN.lfo_cnt = 0;\r |
| | 1918 | ym2612.OPN.lfo_ampm = 126 << 8;\r |
| | 1919 | }\r |
| | 1920 | break;\r |
| | 1921 | #if 0 // handled elsewhere\r |
| | 1922 | case 0x24: { // timer A High 8\r |
| | 1923 | int TAnew = (ym2612.OPN.ST.TA & 0x03)|(((int)v)<<2);\r |
| | 1924 | if(ym2612.OPN.ST.TA != TAnew) {\r |
| | 1925 | // we should reset ticker only if new value is written. Outrun requires this.\r |
| | 1926 | ym2612.OPN.ST.TA = TAnew;\r |
| | 1927 | ym2612.OPN.ST.TAC = (1024-TAnew)*18;\r |
| | 1928 | ym2612.OPN.ST.TAT = 0;\r |
| | 1929 | }\r |
| | 1930 | }\r |
| | 1931 | ret=0;\r |
| | 1932 | break;\r |
| | 1933 | case 0x25: { // timer A Low 2\r |
| | 1934 | int TAnew = (ym2612.OPN.ST.TA & 0x3fc)|(v&3);\r |
| | 1935 | if(ym2612.OPN.ST.TA != TAnew) {\r |
| | 1936 | ym2612.OPN.ST.TA = TAnew;\r |
| | 1937 | ym2612.OPN.ST.TAC = (1024-TAnew)*18;\r |
| | 1938 | ym2612.OPN.ST.TAT = 0;\r |
| | 1939 | }\r |
| | 1940 | }\r |
| | 1941 | ret=0;\r |
| | 1942 | break;\r |
| | 1943 | case 0x26: // timer B\r |
| | 1944 | if(ym2612.OPN.ST.TB != v) {\r |
| | 1945 | ym2612.OPN.ST.TB = v;\r |
| | 1946 | ym2612.OPN.ST.TBC = (256-v)<<4;\r |
| | 1947 | ym2612.OPN.ST.TBC *= 18;\r |
| | 1948 | ym2612.OPN.ST.TBT = 0;\r |
| | 1949 | }\r |
| | 1950 | ret=0;\r |
| | 1951 | break;\r |
| | 1952 | #endif\r |
| | 1953 | case 0x27: /* mode, timer control */\r |
| | 1954 | set_timers( v );\r |
| | 1955 | ret=0;\r |
| | 1956 | break;\r |
| | 1957 | case 0x28: /* key on / off */\r |
| | 1958 | {\r |
| | 1959 | UINT8 c;\r |
| | 1960 | \r |
| | 1961 | c = v & 0x03;\r |
| | 1962 | if( c == 3 ) { ret=0; break; }\r |
| | 1963 | if( v&0x04 ) c+=3;\r |
| | 1964 | if(v&0x10) FM_KEYON(c,SLOT1); else FM_KEYOFF(c,SLOT1);\r |
| | 1965 | if(v&0x20) FM_KEYON(c,SLOT2); else FM_KEYOFF(c,SLOT2);\r |
| | 1966 | if(v&0x40) FM_KEYON(c,SLOT3); else FM_KEYOFF(c,SLOT3);\r |
| | 1967 | if(v&0x80) FM_KEYON(c,SLOT4); else FM_KEYOFF(c,SLOT4);\r |
| | 1968 | break;\r |
| | 1969 | }\r |
| | 1970 | case 0x2a: /* DAC data (YM2612) */\r |
| | 1971 | ym2612.dacout = ((int)v - 0x80) << DAC_SHIFT;\r |
| | 1972 | ret=0;\r |
| | 1973 | break;\r |
| | 1974 | case 0x2b: /* DAC Sel (YM2612) */\r |
| | 1975 | /* b7 = dac enable */\r |
| | 1976 | ym2612.dacen = v & 0x80;\r |
| | 1977 | ret=0;\r |
| | 1978 | break;\r |
| | 1979 | default:\r |
| | 1980 | break;\r |
| | 1981 | }\r |
| | 1982 | break;\r |
| | 1983 | default: /* 0x30-0xff OPN section */\r |
| | 1984 | /* write register */\r |
| | 1985 | ret = OPNWriteReg(addr,v);\r |
| | 1986 | }\r |
| | 1987 | break;\r |
| | 1988 | }\r |
| | 1989 | \r |
| | 1990 | return ret;\r |
| | 1991 | }\r |
| | 1992 | \r |
| | 1993 | #if 0\r |
| | 1994 | UINT8 YM2612Read_(void)\r |
| | 1995 | {\r |
| | 1996 | return ym2612.OPN.ST.status;\r |
| | 1997 | }\r |
| | 1998 | \r |
| | 1999 | int YM2612PicoTick_(int n)\r |
| | 2000 | {\r |
| | 2001 | int ret = 0;\r |
| | 2002 | \r |
| | 2003 | // timer A\r |
| | 2004 | if(ym2612.OPN.ST.mode & 0x01 && (ym2612.OPN.ST.TAT+=64*n) >= ym2612.OPN.ST.TAC) {\r |
| | 2005 | ym2612.OPN.ST.TAT -= ym2612.OPN.ST.TAC;\r |
| | 2006 | if(ym2612.OPN.ST.mode & 0x04) ym2612.OPN.ST.status |= 1;\r |
| | 2007 | // CSM mode total level latch and auto key on\r |
| | 2008 | if(ym2612.OPN.ST.mode & 0x80) {\r |
| | 2009 | CSMKeyControll( &(ym2612.CH[2]) ); // Vectorman2, etc.\r |
| | 2010 | ret = 1;\r |
| | 2011 | }\r |
| | 2012 | }\r |
| | 2013 | \r |
| | 2014 | // timer B\r |
| | 2015 | if(ym2612.OPN.ST.mode & 0x02 && (ym2612.OPN.ST.TBT+=64*n) >= ym2612.OPN.ST.TBC) {\r |
| | 2016 | ym2612.OPN.ST.TBT -= ym2612.OPN.ST.TBC;\r |
| | 2017 | if(ym2612.OPN.ST.mode & 0x08) ym2612.OPN.ST.status |= 2;\r |
| | 2018 | }\r |
| | 2019 | \r |
| | 2020 | return ret;\r |
| | 2021 | }\r |
| | 2022 | #endif\r |
| | 2023 | \r |
| | 2024 | void YM2612PicoStateLoad_(void)\r |
| | 2025 | {\r |
| | 2026 | reset_channels( &ym2612.CH[0] );\r |
| | 2027 | ym2612.slot_mask = 0xffffff;\r |
| | 2028 | }\r |
| | 2029 | \r |
| | 2030 | /* rather stupid design because I wanted to fit in unused register "space" */\r |
| | 2031 | // TODO remove all this along with ym2612.REGS\r |
| | 2032 | typedef struct\r |
| | 2033 | {\r |
| | 2034 | UINT32 state_phase;\r |
| | 2035 | INT16 ssg_volume;\r |
| | 2036 | } ym_save_addon_slot;\r |
| | 2037 | \r |
| | 2038 | typedef struct\r |
| | 2039 | {\r |
| | 2040 | UINT32 magic;\r |
| | 2041 | UINT8 address;\r |
| | 2042 | UINT8 status;\r |
| | 2043 | UINT8 addr_A1;\r |
| | 2044 | UINT8 version;\r |
| | 2045 | INT32 TAT;\r |
| | 2046 | INT32 TBT;\r |
| | 2047 | UINT32 eg_cnt; // 10\r |
| | 2048 | UINT32 eg_timer;\r |
| | 2049 | UINT32 lfo_cnt;\r |
| | 2050 | UINT16 lfo_ampm;\r |
| | 2051 | INT16 busy_timer;\r |
| | 2052 | UINT32 keyon_field; // 20\r |
| | 2053 | INT16 mem_value[6];\r |
| | 2054 | } ym_save_addon;\r |
| | 2055 | \r |
| | 2056 | typedef struct\r |
| | 2057 | {\r |
| | 2058 | UINT16 op1_out_l[6];\r |
| | 2059 | UINT16 unused_sl3[3];\r |
| | 2060 | UINT16 op1_out_h[6];\r |
| | 2061 | UINT16 fn_h;\r |
| | 2062 | } ym_save_addon2;\r |
| | 2063 | #define _block_fnum op1_out_l\r |
| | 2064 | #define _block_fnum_sl3 unused_sl3\r |
| | 2065 | \r |
| | 2066 | void YM2612PicoStateSave2(int tat, int tbt, int busy)\r |
| | 2067 | {\r |
| | 2068 | ym_save_addon_slot ss;\r |
| | 2069 | ym_save_addon2 sa2 = { 0 };\r |
| | 2070 | ym_save_addon sa = { 0 };\r |
| | 2071 | unsigned char *ptr;\r |
| | 2072 | int c, s;\r |
| | 2073 | \r |
| | 2074 | sa.magic = 0x41534d59; // 'YMSA'\r |
| | 2075 | sa.version = 1;\r |
| | 2076 | \r |
| | 2077 | // chans 1,2,3\r |
| | 2078 | ptr = &ym2612.REGS[0x0b8];\r |
| | 2079 | for (c = 0; c < 3; c++)\r |
| | 2080 | {\r |
| | 2081 | for (s = 0; s < 4; s++) {\r |
| | 2082 | ss.state_phase = (ym2612.CH[c].SLOT[s].state << 29) | (ym2612.CH[c].SLOT[s].phase >> 3);\r |
| | 2083 | ss.ssg_volume = (ym2612.CH[c].SLOT[s].volume & 0x7ff);\r |
| | 2084 | if (sa.version)\r |
| | 2085 | ss.ssg_volume |= (ym2612.CH[c].SLOT[s].ssg << 11) | (ym2612.CH[c].SLOT[s].ssgn << 13);\r |
| | 2086 | if (ym2612.CH[c].SLOT[s].key)\r |
| | 2087 | sa.keyon_field |= 1 << (c*4 + s);\r |
| | 2088 | memcpy(ptr, &ss, 6);\r |
| | 2089 | ptr += 6;\r |
| | 2090 | }\r |
| | 2091 | if (sa.version) {\r |
| | 2092 | sa2.op1_out_h[c] = ym2612.CH[c].op1_out >> 16;\r |
| | 2093 | sa2.op1_out_l[c] = ym2612.CH[c].op1_out;\r |
| | 2094 | sa.mem_value[c] = ym2612.CH[c].mem_value;\r |
| | 2095 | } else {\r |
| | 2096 | sa2._block_fnum[c] = ym2612.CH[c].block_fnum;\r |
| | 2097 | sa2._block_fnum_sl3[c] = ym2612.OPN.SL3.block_fnum[c];\r |
| | 2098 | }\r |
| | 2099 | ym2612.REGS[0x63 + 4*c] = ym2612.CH[c].upd_cnt;\r |
| | 2100 | ym2612.REGS[0x43 + 4*c] = ym2612.CH[c].block_fnum >> 8;\r |
| | 2101 | ym2612.REGS[0x33 + 4*c] = ym2612.OPN.SL3.block_fnum[c] >> 8;\r |
| | 2102 | }\r |
| | 2103 | // chans 4,5,6\r |
| | 2104 | ptr = &ym2612.REGS[0x1b8];\r |
| | 2105 | for (; c < 6; c++)\r |
| | 2106 | {\r |
| | 2107 | for (s = 0; s < 4; s++) {\r |
| | 2108 | ss.state_phase = (ym2612.CH[c].SLOT[s].state << 29) | (ym2612.CH[c].SLOT[s].phase >> 3);\r |
| | 2109 | ss.ssg_volume = (ym2612.CH[c].SLOT[s].volume & 0x7ff);\r |
| | 2110 | if (sa.version)\r |
| | 2111 | ss.ssg_volume |= (ym2612.CH[c].SLOT[s].ssg << 11) | (ym2612.CH[c].SLOT[s].ssgn << 13);\r |
| | 2112 | if (ym2612.CH[c].SLOT[s].key)\r |
| | 2113 | sa.keyon_field |= 1 << (c*4 + s);\r |
| | 2114 | memcpy(ptr, &ss, 6);\r |
| | 2115 | ptr += 6;\r |
| | 2116 | }\r |
| | 2117 | if (sa.version) {\r |
| | 2118 | sa2.op1_out_h[c] = ym2612.CH[c].op1_out >> 16;\r |
| | 2119 | sa2.op1_out_l[c] = ym2612.CH[c].op1_out;\r |
| | 2120 | sa.mem_value[c] = ym2612.CH[c].mem_value;\r |
| | 2121 | } else {\r |
| | 2122 | sa2._block_fnum[c] = ym2612.CH[c].block_fnum;\r |
| | 2123 | }\r |
| | 2124 | ym2612.REGS[0x63 + 4*c] = ym2612.CH[c].upd_cnt;\r |
| | 2125 | ym2612.REGS[0x43 + 4*c] = ym2612.CH[c].block_fnum >> 8;\r |
| | 2126 | }\r |
| | 2127 | sa2.fn_h = ym2612.OPN.ST.fn_h | (ym2612.OPN.SL3.fn_h<<8);\r |
| | 2128 | \r |
| | 2129 | memcpy(&ym2612.REGS[0], &sa2, sizeof(sa2)); // 0x20 max\r |
| | 2130 | \r |
| | 2131 | // other things\r |
| | 2132 | ptr = &ym2612.REGS[0x100];\r |
| | 2133 | sa.address = ym2612.OPN.ST.address;\r |
| | 2134 | sa.status = ym2612.OPN.ST.status;\r |
| | 2135 | sa.addr_A1 = ym2612.addr_A1;\r |
| | 2136 | sa.TAT = tat;\r |
| | 2137 | sa.TBT = tbt;\r |
| | 2138 | sa.eg_cnt = ym2612.OPN.eg_cnt;\r |
| | 2139 | sa.eg_timer = ym2612.OPN.eg_timer;\r |
| | 2140 | sa.lfo_cnt = ym2612.OPN.lfo_cnt;\r |
| | 2141 | sa.lfo_ampm = ym2612.OPN.lfo_ampm;\r |
| | 2142 | sa.busy_timer = busy;\r |
| | 2143 | //sa.keyon_field = ym2612.slot_mask;\r |
| | 2144 | memcpy(ptr, &sa, sizeof(sa)); // 0x30 max\r |
| | 2145 | }\r |
| | 2146 | \r |
| | 2147 | int YM2612PicoStateLoad2(int *tat, int *tbt, int *busy)\r |
| | 2148 | {\r |
| | 2149 | ym_save_addon_slot ss;\r |
| | 2150 | ym_save_addon2 sa2;\r |
| | 2151 | ym_save_addon sa;\r |
| | 2152 | unsigned char *ptr;\r |
| | 2153 | int c, s;\r |
| | 2154 | UINT8 fn_h, fn_h_sl3;\r |
| | 2155 | \r |
| | 2156 | ptr = &ym2612.REGS[0x100];\r |
| | 2157 | memcpy(&sa, ptr, sizeof(sa)); // 0x30 max\r |
| | 2158 | if (sa.magic != 0x41534d59) return -1;\r |
| | 2159 | \r |
| | 2160 | ptr = &ym2612.REGS[0];\r |
| | 2161 | memcpy(&sa2, ptr, sizeof(sa2));\r |
| | 2162 | \r |
| | 2163 | ym2612.OPN.ST.address = sa.address;\r |
| | 2164 | ym2612.OPN.ST.status = sa.status;\r |
| | 2165 | ym2612.addr_A1 = sa.addr_A1;\r |
| | 2166 | ym2612.OPN.eg_cnt = sa.eg_cnt;\r |
| | 2167 | ym2612.OPN.eg_timer = sa.eg_timer;\r |
| | 2168 | ym2612.OPN.lfo_cnt = sa.lfo_cnt;\r |
| | 2169 | ym2612.OPN.lfo_ampm = sa.lfo_ampm;\r |
| | 2170 | ym2612.slot_mask = sa.keyon_field;\r |
| | 2171 | if (tat != NULL) *tat = sa.TAT;\r |
| | 2172 | if (tbt != NULL) *tbt = sa.TBT;\r |
| | 2173 | if (busy != NULL) *busy = sa.busy_timer;\r |
| | 2174 | \r |
| | 2175 | fn_h = ym2612.OPN.ST.fn_h;\r |
| | 2176 | fn_h_sl3 = ym2612.OPN.SL3.fn_h;\r |
| | 2177 | \r |
| | 2178 | // chans 1,2,3\r |
| | 2179 | ptr = &ym2612.REGS[0x0b8];\r |
| | 2180 | for (c = 0; c < 3; c++)\r |
| | 2181 | {\r |
| | 2182 | for (s = 0; s < 4; s++) {\r |
| | 2183 | memcpy(&ss, ptr, 6);\r |
| | 2184 | ym2612.CH[c].SLOT[s].state = (ss.state_phase >> 29) & 7;\r |
| | 2185 | ym2612.CH[c].SLOT[s].phase = ss.state_phase << 3;\r |
| | 2186 | ym2612.CH[c].SLOT[s].volume = ss.ssg_volume & 0x7ff;\r |
| | 2187 | ym2612.CH[c].SLOT[s].ssg = (ss.ssg_volume >> 11) & 0xf;\r |
| | 2188 | ym2612.CH[c].SLOT[s].ssgn = (ss.ssg_volume >> 13) & 0x4;\r |
| | 2189 | ym2612.CH[c].SLOT[s].key = (sa.keyon_field & (1 << (c*4 + s))) ? 1 : 0;\r |
| | 2190 | ym2612.CH[c].SLOT[s].ksr = (UINT8)-1;\r |
| | 2191 | recalc_volout( &ym2612.CH[c].SLOT[s] );\r |
| | 2192 | ptr += 6;\r |
| | 2193 | }\r |
| | 2194 | ym2612.CH[c].SLOT[SLOT1].Incr=-1;\r |
| | 2195 | if (sa.version) {\r |
| | 2196 | ym2612.CH[c].op1_out = (sa2.op1_out_h[c] << 16) | sa2.op1_out_l[c];\r |
| | 2197 | ym2612.CH[c].mem_value = sa.mem_value[c];\r |
| | 2198 | ym2612.CH[c].upd_cnt = ym2612.REGS[0x63 + 4*c] & 3;\r |
| | 2199 | ym2612.OPN.ST.fn_h = ym2612.REGS[0x43 + 4*c] & 0x3f;\r |
| | 2200 | ym2612.OPN.SL3.fn_h = ym2612.REGS[0x33 + 4*c] & 0x3f;\r |
| | 2201 | } else {\r |
| | 2202 | ym2612.OPN.ST.fn_h = sa2._block_fnum[c] >> 8;\r |
| | 2203 | ym2612.OPN.SL3.fn_h = sa2._block_fnum_sl3[c] >> 8;\r |
| | 2204 | }\r |
| | 2205 | \r |
| | 2206 | OPNWriteReg(0xa0 + (c&3), ym2612.REGS[0xa0 + (c&3)]);\r |
| | 2207 | OPNWriteReg(0xa8 + (c&3), ym2612.REGS[0xa8 + (c&3)]);\r |
| | 2208 | }\r |
| | 2209 | // chans 4,5,6\r |
| | 2210 | ptr = &ym2612.REGS[0x1b8];\r |
| | 2211 | for (; c < 6; c++)\r |
| | 2212 | {\r |
| | 2213 | for (s = 0; s < 4; s++) {\r |
| | 2214 | memcpy(&ss, ptr, 6);\r |
| | 2215 | ym2612.CH[c].SLOT[s].state = (ss.state_phase >> 29) & 7;\r |
| | 2216 | ym2612.CH[c].SLOT[s].phase = ss.state_phase << 3;\r |
| | 2217 | ym2612.CH[c].SLOT[s].volume = ss.ssg_volume & 0x7ff;\r |
| | 2218 | ym2612.CH[c].SLOT[s].ssg = (ss.ssg_volume >> 11) & 0xf;\r |
| | 2219 | ym2612.CH[c].SLOT[s].ssgn = (ss.ssg_volume >> 13) & 0x4;\r |
| | 2220 | ym2612.CH[c].SLOT[s].key = (sa.keyon_field & (1 << (c*4 + s))) ? 1 : 0;\r |
| | 2221 | ym2612.CH[c].SLOT[s].ksr = (UINT8)-1;\r |
| | 2222 | recalc_volout( &ym2612.CH[c].SLOT[s] );\r |
| | 2223 | ptr += 6;\r |
| | 2224 | }\r |
| | 2225 | ym2612.CH[c].SLOT[SLOT1].Incr=-1;\r |
| | 2226 | if (sa.version) {\r |
| | 2227 | ym2612.CH[c].op1_out = (sa2.op1_out_h[c] << 16) | sa2.op1_out_l[c];\r |
| | 2228 | ym2612.CH[c].mem_value = sa.mem_value[c];\r |
| | 2229 | ym2612.CH[c].upd_cnt = ym2612.REGS[0x63 + 4*c] & 3;\r |
| | 2230 | ym2612.OPN.ST.fn_h = ym2612.REGS[0x43 + 4*c] & 0x3f;\r |
| | 2231 | } else {\r |
| | 2232 | ym2612.OPN.ST.fn_h = sa2._block_fnum[c] >> 8;\r |
| | 2233 | }\r |
| | 2234 | \r |
| | 2235 | OPNWriteReg(0x1a0 + ((c-3)&3), ym2612.REGS[0x1a0 + ((c-3)&3)]);\r |
| | 2236 | }\r |
| | 2237 | if (sa.version) {\r |
| | 2238 | ym2612.OPN.ST.fn_h = sa2.fn_h;\r |
| | 2239 | ym2612.OPN.SL3.fn_h = sa2.fn_h >> 8;\r |
| | 2240 | } else {\r |
| | 2241 | ym2612.OPN.ST.fn_h = fn_h;\r |
| | 2242 | ym2612.OPN.SL3.fn_h = fn_h_sl3;\r |
| | 2243 | }\r |
| | 2244 | \r |
| | 2245 | return 0;\r |
| | 2246 | }\r |
| | 2247 | \r |
| | 2248 | #include "../state.h"\r |
| | 2249 | \r |
| | 2250 | #define SLOT_SIZE_MIN 22\r |
| | 2251 | #define CH_SIZE_MIN 16\r |
| | 2252 | #define OTHER_SIZE_MIN 35\r |
| | 2253 | \r |
| | 2254 | static size_t save_slot(u8 *buf, const FM_SLOT *slot)\r |
| | 2255 | {\r |
| | 2256 | size_t tmp, b = 0;\r |
| | 2257 | \r |
| | 2258 | b++; // length, assumes slot state won't grow beyond 255\r |
| | 2259 | tmp = (slot->DT - ym2612.OPN.ST.dt_tab[0]) / sizeof(ym2612.OPN.ST.dt_tab[0]);\r |
| | 2260 | save_u8_(buf, &b, tmp);\r |
| | 2261 | save_u8_(buf, &b, slot->ar);\r |
| | 2262 | save_u8_(buf, &b, slot->d1r);\r |
| | 2263 | save_u8_(buf, &b, slot->d2r);\r |
| | 2264 | save_u8_(buf, &b, slot->rr);\r |
| | 2265 | save_u8_(buf, &b, slot->mul);\r |
| | 2266 | save_u32(buf, &b, slot->phase);\r |
| | 2267 | save_u8_(buf, &b, slot->KSR);\r |
| | 2268 | save_u8_(buf, &b, slot->key);\r |
| | 2269 | save_u8_(buf, &b, slot->state);\r |
| | 2270 | save_u8_(buf, &b, slot->tl >> (ENV_BITS-7));\r |
| | 2271 | save_u16(buf, &b, slot->volume);\r |
| | 2272 | save_u32(buf, &b, slot->sl);\r |
| | 2273 | save_u8_(buf, &b, slot->ssg);\r |
| | 2274 | save_u8_(buf, &b, slot->ssgn);\r |
| | 2275 | \r |
| | 2276 | //printf("slot size: %zd\n", b);\r |
| | 2277 | assert(b >= SLOT_SIZE_MIN);\r |
| | 2278 | assert(b < 256u);\r |
| | 2279 | buf[0] = b - 1;\r |
| | 2280 | return b;\r |
| | 2281 | }\r |
| | 2282 | \r |
| | 2283 | static void load_slot(const u8 *buf, FM_SLOT *slot)\r |
| | 2284 | {\r |
| | 2285 | size_t b = 0;\r |
| | 2286 | u8 dt_reg;\r |
| | 2287 | \r |
| | 2288 | dt_reg = load_u8_(buf, &b);\r |
| | 2289 | slot->ar = load_u8_(buf, &b);\r |
| | 2290 | slot->d1r = load_u8_(buf, &b);\r |
| | 2291 | slot->d2r = load_u8_(buf, &b);\r |
| | 2292 | slot->rr = load_u8_(buf, &b);\r |
| | 2293 | slot->mul = load_u8_(buf, &b);\r |
| | 2294 | slot->phase = load_u32(buf, &b);\r |
| | 2295 | slot->KSR = load_u8_(buf, &b);\r |
| | 2296 | slot->key = load_u8_(buf, &b);\r |
| | 2297 | slot->state = load_u8_(buf, &b);\r |
| | 2298 | slot->tl = load_u8_(buf, &b) << (ENV_BITS-7);\r |
| | 2299 | slot->volume = load_s16(buf, &b);\r |
| | 2300 | slot->sl = load_u32(buf, &b);\r |
| | 2301 | slot->ssg = load_u8_(buf, &b);\r |
| | 2302 | slot->ssgn = load_u8_(buf, &b);\r |
| | 2303 | \r |
| | 2304 | assert(dt_reg < 8);\r |
| | 2305 | slot->DT = ym2612.OPN.ST.dt_tab[dt_reg & 7];\r |
| | 2306 | recalc_volout( slot );\r |
| | 2307 | \r |
| | 2308 | // trigger a refresh\r |
| | 2309 | slot->Incr = -1;\r |
| | 2310 | slot->ksr = -1;\r |
| | 2311 | }\r |
| | 2312 | \r |
| | 2313 | static size_t save_channel(u8 *buf, const FM_CH *ch)\r |
| | 2314 | {\r |
| | 2315 | int i, size_pos;\r |
| | 2316 | size_t b = 0;\r |
| | 2317 | \r |
| | 2318 | for (i = 0; i < 4; i++)\r |
| | 2319 | b += save_slot(&buf[b], &ch->SLOT[i]);\r |
| | 2320 | size_pos = b++;\r |
| | 2321 | save_u8_(buf, &b, ch->ALGO);\r |
| | 2322 | save_u8_(buf, &b, ch->FB);\r |
| | 2323 | save_u32(buf, &b, ch->op1_out);\r |
| | 2324 | save_s16(buf, &b, ch->mem_value); // fits in 16bit\r |
| | 2325 | save_u8_(buf, &b, ch->pms); // max 7*32\r |
| | 2326 | save_u8_(buf, &b, ch->ams);\r |
| | 2327 | save_u8_(buf, &b, ch->kcode);\r |
| | 2328 | save_u8_(buf, &b, ch->upd_cnt);\r |
| | 2329 | // ch->fc is derived from .block_fnum\r |
| | 2330 | save_u16(buf, &b, ch->block_fnum);\r |
| | 2331 | save_u8_(buf, &b, ch->AMmasks);\r |
| | 2332 | \r |
| | 2333 | assert(b - size_pos - 1 < 256u);\r |
| | 2334 | buf[size_pos] = b - size_pos - 1;\r |
| | 2335 | return b;\r |
| | 2336 | }\r |
| | 2337 | \r |
| | 2338 | static size_t load_channel(const u8 *buf, size_t size, FM_CH *ch)\r |
| | 2339 | {\r |
| | 2340 | size_t i, b = 0, slot_size = 0, ch_size;\r |
| | 2341 | u32 fn, blk;\r |
| | 2342 | \r |
| | 2343 | for (i = 0; i < 4; i++) {\r |
| | 2344 | u8 size_next = load_u8_(buf, &slot_size);\r |
| | 2345 | if (size_next < SLOT_SIZE_MIN)\r |
| | 2346 | return 0;\r |
| | 2347 | if (slot_size + size_next > size)\r |
| | 2348 | return 0;\r |
| | 2349 | load_slot(&buf[slot_size], &ch->SLOT[i]);\r |
| | 2350 | slot_size += size_next;\r |
| | 2351 | }\r |
| | 2352 | if (slot_size + CH_SIZE_MIN > size)\r |
| | 2353 | return 0;\r |
| | 2354 | b = slot_size;\r |
| | 2355 | ch_size = load_u8_(buf, &b);\r |
| | 2356 | ch->ALGO = load_u8_(buf, &b);\r |
| | 2357 | ch->FB = load_u8_(buf, &b);\r |
| | 2358 | ch->op1_out = load_u32(buf, &b);\r |
| | 2359 | ch->mem_value = load_s16(buf, &b);\r |
| | 2360 | ch->pms = load_u8_(buf, &b);\r |
| | 2361 | ch->ams = load_u8_(buf, &b);\r |
| | 2362 | ch->kcode = load_u8_(buf, &b);\r |
| | 2363 | ch->upd_cnt = load_u8_(buf, &b);\r |
| | 2364 | ch->block_fnum = load_u16(buf, &b) & 0x3fff;\r |
| | 2365 | ch->AMmasks = load_u8_(buf, &b);\r |
| | 2366 | \r |
| | 2367 | fn = ch->block_fnum & 0x7ff;\r |
| | 2368 | blk = ch->block_fnum >> 11;\r |
| | 2369 | ch->fc = fn_table[fn*2] >> (7 - blk);\r |
| | 2370 | \r |
| | 2371 | assert(ch_size >= b - slot_size - 1);\r |
| | 2372 | return slot_size + 1 + ch_size;\r |
| | 2373 | }\r |
| | 2374 | \r |
| | 2375 | size_t YM2612PicoStateSave3(void *buf_, size_t size)\r |
| | 2376 | {\r |
| | 2377 | size_t i, b = 0;\r |
| | 2378 | u8 *buf = buf_;\r |
| | 2379 | u8 lfo_inc_reg = 0;\r |
| | 2380 | \r |
| | 2381 | for (i = 0; i < 8; i++) {\r |
| | 2382 | if (ym2612.OPN.lfo_inc == ym2612.OPN.lfo_freq[i]) {\r |
| | 2383 | lfo_inc_reg = i + 1;\r |
| | 2384 | break;\r |
| | 2385 | }\r |
| | 2386 | }\r |
| | 2387 | assert(ym2612.OPN.lfo_inc == 0 || i < 8);\r |
| | 2388 | \r |
| | 2389 | for (i = 0; i < 6; i++)\r |
| | 2390 | b += save_channel(&buf[b], &ym2612.CH[i]);\r |
| | 2391 | save_u8_(buf, &b, ym2612.OPN.ST.address);\r |
| | 2392 | save_u8_(buf, &b, ym2612.OPN.ST.status);\r |
| | 2393 | save_u8_(buf, &b, ym2612.OPN.ST.mode);\r |
| | 2394 | save_u8_(buf, &b, ym2612.OPN.ST.flags);\r |
| | 2395 | // (timers are saved in CHUNK_FM_TIMERS)\r |
| | 2396 | save_u8_(buf, &b, ym2612.OPN.ST.fn_h);\r |
| | 2397 | save_u8_(buf, &b, ym2612.OPN.SL3.fn_h);\r |
| | 2398 | for (i = 0; i < 3; i++) {\r |
| | 2399 | // ym2612.OPN.SL3.fc is derived from .block_fnum\r |
| | 2400 | save_u8_(buf, &b, ym2612.OPN.SL3.kcode[i]);\r |
| | 2401 | save_u16(buf, &b, ym2612.OPN.SL3.block_fnum[i]);\r |
| | 2402 | }\r |
| | 2403 | save_u16(buf, &b, ym2612.OPN.pan);\r |
| | 2404 | save_u16(buf, &b, ym2612.OPN.eg_cnt);\r |
| | 2405 | save_u16(buf, &b, ym2612.OPN.eg_timer);\r |
| | 2406 | save_u32(buf, &b, ym2612.OPN.lfo_cnt);\r |
| | 2407 | save_u16(buf, &b, ym2612.OPN.lfo_ampm);\r |
| | 2408 | save_u8_(buf, &b, lfo_inc_reg);\r |
| | 2409 | save_u8_(buf, &b, ym2612.addr_A1);\r |
| | 2410 | save_u8_(buf, &b, ym2612.dacen);\r |
| | 2411 | save_s8_(buf, &b, ym2612.dacout >> DAC_SHIFT);\r |
| | 2412 | save_u32(buf, &b, ym2612.ssg_mask);\r |
| | 2413 | \r |
| | 2414 | //printf("ym2612 state size: %zu\n", b);\r |
| | 2415 | assert(b <= size);\r |
| | 2416 | return b;\r |
| | 2417 | }\r |
| | 2418 | \r |
| | 2419 | void YM2612PicoStateLoad3(const void *buf_, size_t size)\r |
| | 2420 | {\r |
| | 2421 | const u8 *buf = buf_;\r |
| | 2422 | size_t i, b = 0;\r |
| | 2423 | u8 lfo_inc_reg = 0;\r |
| | 2424 | \r |
| | 2425 | for (i = 0; i < 6; i++) {\r |
| | 2426 | size_t r = load_channel(&buf[b], size - b, &ym2612.CH[i]);\r |
| | 2427 | if (!r)\r |
| | 2428 | goto broken;\r |
| | 2429 | b += r;\r |
| | 2430 | }\r |
| | 2431 | if (b + OTHER_SIZE_MIN > size)\r |
| | 2432 | goto broken;\r |
| | 2433 | ym2612.OPN.ST.address = load_u8_(buf, &b);\r |
| | 2434 | ym2612.OPN.ST.status = load_u8_(buf, &b);\r |
| | 2435 | ym2612.OPN.ST.mode = load_u8_(buf, &b);\r |
| | 2436 | ym2612.OPN.ST.flags = load_u8_(buf, &b);\r |
| | 2437 | ym2612.OPN.ST.fn_h = load_u8_(buf, &b);\r |
| | 2438 | ym2612.OPN.SL3.fn_h = load_u8_(buf, &b);\r |
| | 2439 | for (i = 0; i < 3; i++) {\r |
| | 2440 | u32 fn, blk;\r |
| | 2441 | ym2612.OPN.SL3.kcode[i] = load_u8_(buf, &b);\r |
| | 2442 | ym2612.OPN.SL3.block_fnum[i] = load_u16(buf, &b) & 0x3fff;\r |
| | 2443 | \r |
| | 2444 | fn = ym2612.OPN.SL3.block_fnum[i] & 0x7ff;\r |
| | 2445 | blk = ym2612.OPN.SL3.block_fnum[i] >> 11;\r |
| | 2446 | ym2612.OPN.SL3.fc[i] = fn_table[fn*2] >> (7 - blk);\r |
| | 2447 | }\r |
| | 2448 | ym2612.OPN.pan = load_u16(buf, &b);\r |
| | 2449 | ym2612.OPN.eg_cnt = load_u16(buf, &b);\r |
| | 2450 | ym2612.OPN.eg_timer = load_u16(buf, &b);\r |
| | 2451 | ym2612.OPN.lfo_cnt = load_u32(buf, &b);\r |
| | 2452 | ym2612.OPN.lfo_ampm = load_u16(buf, &b);\r |
| | 2453 | lfo_inc_reg = load_u8_(buf, &b);\r |
| | 2454 | ym2612.addr_A1 = load_u8_(buf, &b);\r |
| | 2455 | ym2612.dacen = load_u8_(buf, &b);\r |
| | 2456 | ym2612.dacout = load_s8_(buf, &b);\r |
| | 2457 | ym2612.ssg_mask = load_u32(buf, &b);\r |
| | 2458 | \r |
| | 2459 | assert(lfo_inc_reg < 9u);\r |
| | 2460 | ym2612.OPN.lfo_inc = 0;\r |
| | 2461 | if (lfo_inc_reg)\r |
| | 2462 | ym2612.OPN.lfo_inc = ym2612.OPN.lfo_freq[--lfo_inc_reg & 7];\r |
| | 2463 | ym2612.dacout = (u32)ym2612.dacout << DAC_SHIFT;\r |
| | 2464 | ym2612.slot_mask = 0xffffff;\r |
| | 2465 | //printf("ym2612 state size: %zu\n", b);\r |
| | 2466 | return;\r |
| | 2467 | broken:\r |
| | 2468 | elprintf(EL_STATUS, "broken ym2612 state");\r |
| | 2469 | }\r |
| | 2470 | \r |
| | 2471 | void *YM2612GetRegs(void)\r |
| | 2472 | {\r |
| | 2473 | return ym2612.REGS;\r |
| | 2474 | }\r |
| | 2475 | \r |