summaryrefslogtreecommitdiffstatshomepage
path: root/src/devices/sound/fmopl.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/devices/sound/fmopl.cpp')
-rw-r--r--src/devices/sound/fmopl.cpp1818
1 files changed, 913 insertions, 905 deletions
diff --git a/src/devices/sound/fmopl.cpp b/src/devices/sound/fmopl.cpp
index fe4d80a1bc6..a9c15478779 100644
--- a/src/devices/sound/fmopl.cpp
+++ b/src/devices/sound/fmopl.cpp
@@ -194,6 +194,14 @@ static FILE *sample[1];
#define OPL_TYPE_Y8950 (OPL_TYPE_ADPCM|OPL_TYPE_KEYBOARD|OPL_TYPE_IO)
+namespace {
+
+// TODO: make these static members
+
+#define RATE_STEPS (8)
+extern const unsigned char eg_rate_shift[16+64+16];
+extern const unsigned char eg_rate_select[16+64+16];
+
struct OPL_SLOT
{
@@ -234,6 +242,33 @@ struct OPL_SLOT
/* waveform select */
uint16_t wavetable;
+
+ void KEYON(uint32_t key_set)
+ {
+ if( !key )
+ {
+ /* restart Phase Generator */
+ Cnt = 0;
+ /* phase -> Attack */
+ state = EG_ATT;
+ }
+ key |= key_set;
+ }
+
+ void KEYOFF(uint32_t key_clr)
+ {
+ if( key )
+ {
+ key &= key_clr;
+
+ if( !key )
+ {
+ /* phase -> Release */
+ if (state>EG_REL)
+ state = EG_REL;
+ }
+ }
+ }
};
struct OPL_CH
@@ -244,6 +279,36 @@ struct OPL_CH
uint32_t fc; /* Freq. Increment base */
uint32_t ksl_base; /* KeyScaleLevel Base step */
uint8_t kcode; /* key code (for key scaling) */
+
+
+ /* update phase increment counter of operator (also update the EG rates if necessary) */
+ void CALC_FCSLOT(OPL_SLOT &SLOT)
+ {
+ /* (frequency) phase increment counter */
+ SLOT.Incr = fc * SLOT.mul;
+ int const ksr = kcode >> SLOT.KSR;
+
+ if( SLOT.ksr != ksr )
+ {
+ SLOT.ksr = ksr;
+
+ /* calculate envelope generator rates */
+ if ((SLOT.ar + SLOT.ksr) < 16+62)
+ {
+ SLOT.eg_sh_ar = eg_rate_shift [SLOT.ar + SLOT.ksr ];
+ SLOT.eg_sel_ar = eg_rate_select[SLOT.ar + SLOT.ksr ];
+ }
+ else
+ {
+ SLOT.eg_sh_ar = 0;
+ SLOT.eg_sel_ar = 13*RATE_STEPS;
+ }
+ SLOT.eg_sh_dr = eg_rate_shift [SLOT.dr + SLOT.ksr ];
+ SLOT.eg_sel_dr = eg_rate_select[SLOT.dr + SLOT.ksr ];
+ SLOT.eg_sh_rr = eg_rate_shift [SLOT.rr + SLOT.ksr ];
+ SLOT.eg_sel_rr = eg_rate_select[SLOT.rr + SLOT.ksr ];
+ }
+ }
};
/* OPL state */
@@ -291,19 +356,19 @@ struct FM_OPL
uint8_t portLatch;
OPL_PORTHANDLER_R porthandler_r;
OPL_PORTHANDLER_W porthandler_w;
- void * port_param;
+ device_t * port_param;
OPL_PORTHANDLER_R keyboardhandler_r;
OPL_PORTHANDLER_W keyboardhandler_w;
- void * keyboard_param;
+ device_t * keyboard_param;
#endif
/* external event callback handlers */
OPL_TIMERHANDLER timer_handler; /* TIMER handler */
- void *TimerParam; /* TIMER parameter */
+ device_t *TimerParam; /* TIMER parameter */
OPL_IRQHANDLER IRQHandler; /* IRQ handler */
- void *IRQParam; /* IRQ parameter */
+ device_t *IRQParam; /* IRQ parameter */
OPL_UPDATEHANDLER UpdateHandler;/* stream update handler */
- void *UpdateParam; /* stream update parameter */
+ device_t *UpdateParam; /* stream update parameter */
uint8_t type; /* chip type */
uint8_t address; /* address register */
@@ -322,6 +387,619 @@ struct FM_OPL
#if BUILD_Y8950
int32_t output_deltat[4]; /* for Y8950 DELTA-T, chip is mono, that 4 here is just for safety */
#endif
+
+
+ /* status set and IRQ handling */
+ void STATUS_SET(int flag)
+ {
+ /* set status flag */
+ status |= flag;
+ if(!(status & 0x80))
+ {
+ if(status & statusmask)
+ { /* IRQ on */
+ status |= 0x80;
+ /* callback user interrupt handler (IRQ is OFF to ON) */
+ if(IRQHandler) (IRQHandler)(IRQParam,1);
+ }
+ }
+ }
+
+ /* status reset and IRQ handling */
+ void STATUS_RESET(int flag)
+ {
+ /* reset status flag */
+ status &=~flag;
+ if(status & 0x80)
+ {
+ if (!(status & statusmask) )
+ {
+ status &= 0x7f;
+ /* callback user interrupt handler (IRQ is ON to OFF) */
+ if(IRQHandler) (IRQHandler)(IRQParam,0);
+ }
+ }
+ }
+
+ /* IRQ mask set */
+ void STATUSMASK_SET(int flag)
+ {
+ statusmask = flag;
+ /* IRQ handling check */
+ STATUS_SET(0);
+ STATUS_RESET(0);
+ }
+
+
+ /* advance LFO to next sample */
+ void advance_lfo()
+ {
+ /* LFO */
+ lfo_am_cnt += lfo_am_inc;
+ if (lfo_am_cnt >= (uint32_t(LFO_AM_TAB_ELEMENTS) << LFO_SH)) /* lfo_am_table is 210 elements long */
+ lfo_am_cnt -= (uint32_t(LFO_AM_TAB_ELEMENTS) << LFO_SH);
+
+ uint8_t const tmp = lfo_am_table[ lfo_am_cnt >> LFO_SH ];
+
+ LFO_AM = lfo_am_depth ? tmp : tmp >> 2;
+
+ lfo_pm_cnt += lfo_pm_inc;
+ LFO_PM = (lfo_pm_cnt>>LFO_SH & 7) | lfo_pm_depth_range;
+ }
+
+ /* advance to next sample */
+ void advance()
+ {
+ eg_timer += eg_timer_add;
+
+ while (eg_timer >= eg_timer_overflow)
+ {
+ eg_timer -= eg_timer_overflow;
+
+ eg_cnt++;
+
+ for (int i=0; i<9*2; i++)
+ {
+ OPL_CH &CH = P_CH[i/2];
+ OPL_SLOT &op = CH.SLOT[i&1];
+
+ /* Envelope Generator */
+ switch(op.state)
+ {
+ case EG_ATT: /* attack phase */
+ if ( !(eg_cnt & ((1<<op.eg_sh_ar)-1) ) )
+ {
+ op.volume += (~op.volume *
+ (eg_inc[op.eg_sel_ar + ((eg_cnt>>op.eg_sh_ar)&7)])
+ ) >>3;
+
+ if (op.volume <= MIN_ATT_INDEX)
+ {
+ op.volume = MIN_ATT_INDEX;
+ op.state = EG_DEC;
+ }
+
+ }
+ break;
+
+ case EG_DEC: /* decay phase */
+ if ( !(eg_cnt & ((1<<op.eg_sh_dr)-1) ) )
+ {
+ op.volume += eg_inc[op.eg_sel_dr + ((eg_cnt>>op.eg_sh_dr)&7)];
+
+ if ( op.volume >= op.sl )
+ op.state = EG_SUS;
+
+ }
+ break;
+
+ case EG_SUS: /* sustain phase */
+
+ /* this is important behaviour:
+ one can change percusive/non-percussive modes on the fly and
+ the chip will remain in sustain phase - verified on real YM3812 */
+
+ if(op.eg_type) /* non-percussive mode */
+ {
+ /* do nothing */
+ }
+ else /* percussive mode */
+ {
+ /* during sustain phase chip adds Release Rate (in percussive mode) */
+ if ( !(eg_cnt & ((1<<op.eg_sh_rr)-1) ) )
+ {
+ op.volume += eg_inc[op.eg_sel_rr + ((eg_cnt>>op.eg_sh_rr)&7)];
+
+ if ( op.volume >= MAX_ATT_INDEX )
+ op.volume = MAX_ATT_INDEX;
+ }
+ /* else do nothing in sustain phase */
+ }
+ break;
+
+ case EG_REL: /* release phase */
+ if ( !(eg_cnt & ((1<<op.eg_sh_rr)-1) ) )
+ {
+ op.volume += eg_inc[op.eg_sel_rr + ((eg_cnt>>op.eg_sh_rr)&7)];
+
+ if ( op.volume >= MAX_ATT_INDEX )
+ {
+ op.volume = MAX_ATT_INDEX;
+ op.state = EG_OFF;
+ }
+
+ }
+ break;
+
+ default:
+ break;
+ }
+ }
+ }
+
+ for (int i=0; i<9*2; i++)
+ {
+ OPL_CH &CH = P_CH[i/2];
+ OPL_SLOT &op = CH.SLOT[i&1];
+
+ /* Phase Generator */
+ if(op.vib)
+ {
+ unsigned int block_fnum = CH.block_fnum;
+ unsigned int const fnum_lfo = (block_fnum&0x0380) >> 7;
+
+ signed int const lfo_fn_table_index_offset = lfo_pm_table[LFO_PM + 16*fnum_lfo ];
+
+ if (lfo_fn_table_index_offset) /* LFO phase modulation active */
+ {
+ block_fnum += lfo_fn_table_index_offset;
+ uint8_t const block = (block_fnum&0x1c00) >> 10;
+ op.Cnt += (fn_tab[block_fnum&0x03ff] >> (7-block)) * op.mul;
+ }
+ else /* LFO phase modulation = zero */
+ {
+ op.Cnt += op.Incr;
+ }
+ }
+ else /* LFO phase modulation disabled for this operator */
+ {
+ op.Cnt += op.Incr;
+ }
+ }
+
+ /* The Noise Generator of the YM3812 is 23-bit shift register.
+ * Period is equal to 2^23-2 samples.
+ * Register works at sampling frequency of the chip, so output
+ * can change on every sample.
+ *
+ * Output of the register and input to the bit 22 is:
+ * bit0 XOR bit14 XOR bit15 XOR bit22
+ *
+ * Simply use bit 22 as the noise output.
+ */
+
+ noise_p += noise_f;
+ int i = noise_p >> FREQ_SH; /* number of events (shifts of the shift register) */
+ noise_p &= FREQ_MASK;
+ while (i)
+ {
+ /*
+ uint32_t j;
+ j = ( (noise_rng) ^ (noise_rng>>14) ^ (noise_rng>>15) ^ (noise_rng>>22) ) & 1;
+ noise_rng = (j<<22) | (noise_rng>>1);
+ */
+
+ /*
+ Instead of doing all the logic operations above, we
+ use a trick here (and use bit 0 as the noise output).
+ The difference is only that the noise bit changes one
+ step ahead. This doesn't matter since we don't know
+ what is real state of the noise_rng after the reset.
+ */
+
+ if (noise_rng & 1) noise_rng ^= 0x800302;
+ noise_rng >>= 1;
+
+ i--;
+ }
+ }
+
+ /* calculate output */
+ void CALC_CH(OPL_CH &CH)
+ {
+ OPL_SLOT *SLOT;
+ unsigned int env;
+ signed int out;
+
+ phase_modulation = 0;
+
+ /* SLOT 1 */
+ SLOT = &CH.SLOT[SLOT1];
+ env = volume_calc(*SLOT);
+ out = SLOT->op1_out[0] + SLOT->op1_out[1];
+ SLOT->op1_out[0] = SLOT->op1_out[1];
+ *SLOT->connect1 += SLOT->op1_out[0];
+ SLOT->op1_out[1] = 0;
+ if( env < ENV_QUIET )
+ {
+ if (!SLOT->FB)
+ out = 0;
+ SLOT->op1_out[1] = op_calc1(SLOT->Cnt, env, (out<<SLOT->FB), SLOT->wavetable );
+ }
+
+ /* SLOT 2 */
+ SLOT++;
+ env = volume_calc(*SLOT);
+ if( env < ENV_QUIET )
+ output[0] += op_calc(SLOT->Cnt, env, phase_modulation, SLOT->wavetable);
+ }
+
+ /*
+ operators used in the rhythm sounds generation process:
+
+ Envelope Generator:
+
+ channel operator register number Bass High Snare Tom Top
+ / slot number TL ARDR SLRR Wave Drum Hat Drum Tom Cymbal
+ 6 / 0 12 50 70 90 f0 +
+ 6 / 1 15 53 73 93 f3 +
+ 7 / 0 13 51 71 91 f1 +
+ 7 / 1 16 54 74 94 f4 +
+ 8 / 0 14 52 72 92 f2 +
+ 8 / 1 17 55 75 95 f5 +
+
+ Phase Generator:
+
+ channel operator register number Bass High Snare Tom Top
+ / slot number MULTIPLE Drum Hat Drum Tom Cymbal
+ 6 / 0 12 30 +
+ 6 / 1 15 33 +
+ 7 / 0 13 31 + + +
+ 7 / 1 16 34 ----- n o t u s e d -----
+ 8 / 0 14 32 +
+ 8 / 1 17 35 + +
+
+ channel operator register number Bass High Snare Tom Top
+ number number BLK/FNUM2 FNUM Drum Hat Drum Tom Cymbal
+ 6 12,15 B6 A6 +
+
+ 7 13,16 B7 A7 + + +
+
+ 8 14,17 B8 A8 + + +
+
+ */
+
+ /* calculate rhythm */
+
+ void CALC_RH()
+ {
+ unsigned int const noise = BIT(noise_rng, 0);
+
+ OPL_SLOT *SLOT;
+ signed int out;
+ unsigned int env;
+
+
+ /* Bass Drum (verified on real YM3812):
+ - depends on the channel 6 'connect' register:
+ when connect = 0 it works the same as in normal (non-rhythm) mode (op1->op2->out)
+ when connect = 1 _only_ operator 2 is present on output (op2->out), operator 1 is ignored
+ - output sample always is multiplied by 2
+ */
+
+ phase_modulation = 0;
+ /* SLOT 1 */
+ SLOT = &P_CH[6].SLOT[SLOT1];
+ env = volume_calc(*SLOT);
+
+ out = SLOT->op1_out[0] + SLOT->op1_out[1];
+ SLOT->op1_out[0] = SLOT->op1_out[1];
+
+ if (!SLOT->CON)
+ phase_modulation = SLOT->op1_out[0];
+ /* else ignore output of operator 1 */
+
+ SLOT->op1_out[1] = 0;
+ if( env < ENV_QUIET )
+ {
+ if (!SLOT->FB)
+ out = 0;
+ SLOT->op1_out[1] = op_calc1(SLOT->Cnt, env, (out<<SLOT->FB), SLOT->wavetable );
+ }
+
+ /* SLOT 2 */
+ SLOT++;
+ env = volume_calc(*SLOT);
+ if( env < ENV_QUIET )
+ output[0] += op_calc(SLOT->Cnt, env, phase_modulation, SLOT->wavetable) * 2;
+
+
+ /* Phase generation is based on: */
+ /* HH (13) channel 7->slot 1 combined with channel 8->slot 2 (same combination as TOP CYMBAL but different output phases) */
+ /* SD (16) channel 7->slot 1 */
+ /* TOM (14) channel 8->slot 1 */
+ /* TOP (17) channel 7->slot 1 combined with channel 8->slot 2 (same combination as HIGH HAT but different output phases) */
+
+ /* Envelope generation based on: */
+ /* HH channel 7->slot1 */
+ /* SD channel 7->slot2 */
+ /* TOM channel 8->slot1 */
+ /* TOP channel 8->slot2 */
+
+
+ /* The following formulas can be well optimized.
+ I leave them in direct form for now (in case I've missed something).
+ */
+
+ /* High Hat (verified on real YM3812) */
+ OPL_SLOT const &SLOT7_1 = P_CH[7].SLOT[SLOT1];
+ OPL_SLOT const &SLOT8_2 = P_CH[8].SLOT[SLOT2];
+ env = volume_calc(SLOT7_1);
+ if( env < ENV_QUIET )
+ {
+ /* high hat phase generation:
+ phase = d0 or 234 (based on frequency only)
+ phase = 34 or 2d0 (based on noise)
+ */
+
+ /* base frequency derived from operator 1 in channel 7 */
+ unsigned char const bit7 = BIT(SLOT7_1.Cnt >> FREQ_SH, 7);
+ unsigned char const bit3 = BIT(SLOT7_1.Cnt >> FREQ_SH, 3);
+ unsigned char const bit2 = BIT(SLOT7_1.Cnt >> FREQ_SH, 2);
+
+ unsigned char const res1 = (bit2 ^ bit7) | bit3;
+
+ /* when res1 = 0 phase = 0x000 | 0xd0; */
+ /* when res1 = 1 phase = 0x200 | (0xd0>>2); */
+ uint32_t phase = res1 ? (0x200|(0xd0>>2)) : 0xd0;
+
+ /* enable gate based on frequency of operator 2 in channel 8 */
+ unsigned char const bit5e= BIT(SLOT8_2.Cnt >> FREQ_SH, 5);
+ unsigned char const bit3e= BIT(SLOT8_2.Cnt >> FREQ_SH, 3);
+
+ unsigned char const res2 = bit3e ^ bit5e;
+
+ /* when res2 = 0 pass the phase from calculation above (res1); */
+ /* when res2 = 1 phase = 0x200 | (0xd0>>2); */
+ if (res2)
+ phase = (0x200|(0xd0>>2));
+
+
+ /* when phase & 0x200 is set and noise=1 then phase = 0x200|0xd0 */
+ /* when phase & 0x200 is set and noise=0 then phase = 0x200|(0xd0>>2), ie no change */
+ if (phase&0x200)
+ {
+ if (noise)
+ phase = 0x200|0xd0;
+ }
+ else
+ /* when phase & 0x200 is clear and noise=1 then phase = 0xd0>>2 */
+ /* when phase & 0x200 is clear and noise=0 then phase = 0xd0, ie no change */
+ {
+ if (noise)
+ phase = 0xd0>>2;
+ }
+
+ output[0] += op_calc(phase<<FREQ_SH, env, 0, SLOT7_1.wavetable) * 2;
+ }
+
+ /* Snare Drum (verified on real YM3812) */
+ OPL_SLOT const &SLOT7_2 = P_CH[7].SLOT[SLOT2];
+ env = volume_calc(SLOT7_2);
+ if( env < ENV_QUIET )
+ {
+ /* base frequency derived from operator 1 in channel 7 */
+ unsigned char const bit8 = BIT(SLOT7_1.Cnt >> FREQ_SH, 8);
+
+ /* when bit8 = 0 phase = 0x100; */
+ /* when bit8 = 1 phase = 0x200; */
+ uint32_t phase = bit8 ? 0x200 : 0x100;
+
+ /* Noise bit XOR'es phase by 0x100 */
+ /* when noisebit = 0 pass the phase from calculation above */
+ /* when noisebit = 1 phase ^= 0x100; */
+ /* in other words: phase ^= (noisebit<<8); */
+ if (noise)
+ phase ^= 0x100;
+
+ output[0] += op_calc(phase<<FREQ_SH, env, 0, SLOT7_2.wavetable) * 2;
+ }
+
+ /* Tom Tom (verified on real YM3812) */
+ OPL_SLOT const &SLOT8_1 = P_CH[8].SLOT[SLOT1];
+ env = volume_calc(SLOT8_1);
+ if( env < ENV_QUIET )
+ output[0] += op_calc(SLOT8_1.Cnt, env, 0, SLOT8_1.wavetable) * 2;
+
+ /* Top Cymbal (verified on real YM3812) */
+ env = volume_calc(SLOT8_2);
+ if( env < ENV_QUIET )
+ {
+ /* base frequency derived from operator 1 in channel 7 */
+ unsigned char const bit7 = BIT(SLOT7_1.Cnt >> FREQ_SH, 7);
+ unsigned char const bit3 = BIT(SLOT7_1.Cnt >> FREQ_SH, 3);
+ unsigned char const bit2 = BIT(SLOT7_1.Cnt >> FREQ_SH, 2);
+
+ unsigned char const res1 = (bit2 ^ bit7) | bit3;
+
+ /* when res1 = 0 phase = 0x000 | 0x100; */
+ /* when res1 = 1 phase = 0x200 | 0x100; */
+ uint32_t phase = res1 ? 0x300 : 0x100;
+
+ /* enable gate based on frequency of operator 2 in channel 8 */
+ unsigned char const bit5e= BIT(SLOT8_2.Cnt >> FREQ_SH, 5);
+ unsigned char const bit3e= BIT(SLOT8_2.Cnt >> FREQ_SH, 3);
+
+ unsigned char const res2 = bit3e ^ bit5e;
+ /* when res2 = 0 pass the phase from calculation above (res1); */
+ /* when res2 = 1 phase = 0x200 | 0x100; */
+ if (res2)
+ phase = 0x300;
+
+ output[0] += op_calc(phase<<FREQ_SH, env, 0, SLOT8_2.wavetable) * 2;
+ }
+ }
+
+
+ void initialize();
+
+
+ /* set multi,am,vib,EG-TYP,KSR,mul */
+ void set_mul(int slot, int v)
+ {
+ OPL_CH &CH = P_CH[slot/2];
+ OPL_SLOT &SLOT = CH.SLOT[slot&1];
+
+ SLOT.mul = mul_tab[v&0x0f];
+ SLOT.KSR = (v & 0x10) ? 0 : 2;
+ SLOT.eg_type = (v & 0x20);
+ SLOT.vib = (v & 0x40);
+ SLOT.AMmask = (v & 0x80) ? ~0 : 0;
+ CH.CALC_FCSLOT(SLOT);
+ }
+
+ /* set ksl & tl */
+ void set_ksl_tl(int slot, int v)
+ {
+ OPL_CH &CH = P_CH[slot/2];
+ OPL_SLOT &SLOT = CH.SLOT[slot&1];
+
+ SLOT.ksl = ksl_shift[v >> 6];
+ SLOT.TL = (v&0x3f)<<(ENV_BITS-1-7); /* 7 bits TL (bit 6 = always 0) */
+
+ SLOT.TLL = SLOT.TL + (CH.ksl_base >> SLOT.ksl);
+ }
+
+ /* set attack rate & decay rate */
+ void set_ar_dr(int slot, int v)
+ {
+ OPL_CH &CH = P_CH[slot/2];
+ OPL_SLOT &SLOT = CH.SLOT[slot&1];
+
+ SLOT.ar = (v>>4) ? 16 + ((v>>4) <<2) : 0;
+
+ if ((SLOT.ar + SLOT.ksr) < 16+62)
+ {
+ SLOT.eg_sh_ar = eg_rate_shift [SLOT.ar + SLOT.ksr ];
+ SLOT.eg_sel_ar = eg_rate_select[SLOT.ar + SLOT.ksr ];
+ }
+ else
+ {
+ SLOT.eg_sh_ar = 0;
+ SLOT.eg_sel_ar = 13*RATE_STEPS;
+ }
+
+ SLOT.dr = (v&0x0f)? 16 + ((v&0x0f)<<2) : 0;
+ SLOT.eg_sh_dr = eg_rate_shift [SLOT.dr + SLOT.ksr ];
+ SLOT.eg_sel_dr = eg_rate_select[SLOT.dr + SLOT.ksr ];
+ }
+
+ /* set sustain level & release rate */
+ void set_sl_rr(int slot, int v)
+ {
+ OPL_CH &CH = P_CH[slot/2];
+ OPL_SLOT &SLOT = CH.SLOT[slot&1];
+
+ SLOT.sl = sl_tab[ v>>4 ];
+
+ SLOT.rr = (v&0x0f)? 16 + ((v&0x0f)<<2) : 0;
+ SLOT.eg_sh_rr = eg_rate_shift [SLOT.rr + SLOT.ksr ];
+ SLOT.eg_sel_rr = eg_rate_select[SLOT.rr + SLOT.ksr ];
+ }
+
+
+ void WriteReg(int r, int v);
+ void ResetChip();
+ void postload();
+
+
+ /* lock/unlock for common table */
+ static int LockTable(device_t *device)
+ {
+ num_lock++;
+ if(num_lock>1) return 0;
+
+ /* first time */
+
+ /* allocate total level table (128kb space) */
+ if( !init_tables() )
+ {
+ num_lock--;
+ return -1;
+ }
+
+ return 0;
+ }
+
+ static void UnLockTable()
+ {
+ if(num_lock) num_lock--;
+ if(num_lock) return;
+
+ /* last time */
+ CloseTable();
+ }
+
+private:
+ uint32_t volume_calc(OPL_SLOT const &OP) const
+ {
+ return OP.TLL + uint32_t(OP.volume) + (LFO_AM & OP.AMmask);
+ }
+
+ static inline signed int op_calc(uint32_t phase, unsigned int env, signed int pm, unsigned int wave_tab)
+ {
+ uint32_t const p = (env<<4) + sin_tab[wave_tab + ((((signed int)((phase & ~FREQ_MASK) + (pm<<16))) >> FREQ_SH ) & SIN_MASK) ];
+
+ return (p >= TL_TAB_LEN) ? 0 : tl_tab[p];
+ }
+
+ static inline signed int op_calc1(uint32_t phase, unsigned int env, signed int pm, unsigned int wave_tab)
+ {
+ uint32_t const p = (env<<4) + sin_tab[wave_tab + ((((signed int)((phase & ~FREQ_MASK) + pm )) >> FREQ_SH ) & SIN_MASK) ];
+
+ return (p >= TL_TAB_LEN) ? 0 : tl_tab[p];
+ }
+
+
+ static int init_tables();
+
+ static void CloseTable()
+ {
+#ifdef SAVE_SAMPLE
+ fclose(sample[0]);
+#endif
+ }
+
+
+ static constexpr uint32_t SC(uint32_t db) { return uint32_t(db * (2.0 / ENV_STEP)); }
+
+
+ static constexpr double DV = 0.1875 / 2.0;
+
+
+ /* TL_TAB_LEN is calculated as:
+ * 12 - sinus amplitude bits (Y axis)
+ * 2 - sinus sign bit (Y axis)
+ * TL_RES_LEN - sinus resolution (X axis)
+ */
+ static constexpr unsigned TL_TAB_LEN = 12 * 2 * TL_RES_LEN;
+ static constexpr unsigned ENV_QUIET = TL_TAB_LEN >> 4;
+
+ static constexpr unsigned LFO_AM_TAB_ELEMENTS = 210;
+
+ static const double ksl_tab[8*16];
+ static const uint32_t ksl_shift[4];
+ static const uint32_t sl_tab[16];
+ static const unsigned char eg_inc[15 * RATE_STEPS];
+
+ static const uint8_t mul_tab[16];
+ static signed int tl_tab[TL_TAB_LEN];
+ static unsigned int sin_tab[SIN_LEN * 4];
+
+ static const uint8_t lfo_am_table[LFO_AM_TAB_ELEMENTS];
+ static const int8_t lfo_pm_table[8 * 8 * 2];
+
+ static int num_lock;
};
@@ -338,8 +1016,7 @@ static const int slot_array[32]=
/* key scale level */
/* table is 3dB/octave , DV converts this into 6dB/octave */
/* 0.1875 is bit 0 weight of the envelope counter (volume) expressed in the 'decibel' scale */
-#define DV (0.1875/2.0)
-static const double ksl_tab[8*16]=
+const double FM_OPL::ksl_tab[8*16]=
{
/* OCT 0 */
0.000/DV, 0.000/DV, 0.000/DV, 0.000/DV,
@@ -382,24 +1059,20 @@ static const double ksl_tab[8*16]=
18.000/DV,18.750/DV,19.125/DV,19.500/DV,
19.875/DV,20.250/DV,20.625/DV,21.000/DV
};
-#undef DV
/* 0 / 3.0 / 1.5 / 6.0 dB/OCT */
-static const uint32_t ksl_shift[4] = { 31, 1, 2, 0 };
+const uint32_t FM_OPL::ksl_shift[4] = { 31, 1, 2, 0 };
/* sustain level table (3dB per step) */
/* 0 - 15: 0, 3, 6, 9,12,15,18,21,24,27,30,33,36,39,42,93 (dB)*/
-#define SC(db) (uint32_t) ( db * (2.0/ENV_STEP) )
-static const uint32_t sl_tab[16]={
- SC( 0),SC( 1),SC( 2),SC(3 ),SC(4 ),SC(5 ),SC(6 ),SC( 7),
+const uint32_t FM_OPL::sl_tab[16]={
+ SC( 0),SC( 1),SC( 2),SC( 3),SC( 4),SC( 5),SC( 6),SC( 7),
SC( 8),SC( 9),SC(10),SC(11),SC(12),SC(13),SC(14),SC(31)
};
-#undef SC
-#define RATE_STEPS (8)
-static const unsigned char eg_inc[15*RATE_STEPS]={
+const unsigned char FM_OPL::eg_inc[15*RATE_STEPS]={
/*cycle:0 1 2 3 4 5 6 7*/
/* 0 */ 0,1, 0,1, 0,1, 0,1, /* rates 00..12 0 (increment by 0 or 1) */
@@ -426,7 +1099,7 @@ static const unsigned char eg_inc[15*RATE_STEPS]={
#define O(a) (a*RATE_STEPS)
/*note that there is no O(13) in this table - it's directly in the code */
-static const unsigned char eg_rate_select[16+64+16]={ /* Envelope Generator rates (16 + 64 rates + 16 RKS) */
+const unsigned char eg_rate_select[16+64+16]={ /* Envelope Generator rates (16 + 64 rates + 16 RKS) */
/* 16 infinite time rates */
O(14),O(14),O(14),O(14),O(14),O(14),O(14),O(14),
O(14),O(14),O(14),O(14),O(14),O(14),O(14),O(14),
@@ -467,7 +1140,7 @@ O(12),O(12),O(12),O(12),O(12),O(12),O(12),O(12),
/*mask 4095, 2047, 1023, 511, 255, 127, 63, 31, 15, 7, 3, 1, 0, 0, 0, 0 */
#define O(a) (a*1)
-static const unsigned char eg_rate_shift[16+64+16]={ /* Envelope Generator counter shifts (16 + 64 rates + 16 RKS) */
+const unsigned char eg_rate_shift[16+64+16]={ /* Envelope Generator counter shifts (16 + 64 rates + 16 RKS) */
/* 16 infinite time rates */
O(0),O(0),O(0),O(0),O(0),O(0),O(0),O(0),
O(0),O(0),O(0),O(0),O(0),O(0),O(0),O(0),
@@ -506,26 +1179,18 @@ O( 0),O( 0),O( 0),O( 0),O( 0),O( 0),O( 0),O( 0),
/* multiple table */
#define ML 2
-static const uint8_t mul_tab[16]= {
+const uint8_t FM_OPL::mul_tab[16]= {
/* 1/2, 1, 2, 3, 4, 5, 6, 7, 8, 9,10,10,12,12,15,15 */
ML/2, 1*ML, 2*ML, 3*ML, 4*ML, 5*ML, 6*ML, 7*ML,
8*ML, 9*ML,10*ML,10*ML,12*ML,12*ML,15*ML,15*ML
};
#undef ML
-/* TL_TAB_LEN is calculated as:
-* 12 - sinus amplitude bits (Y axis)
-* 2 - sinus sign bit (Y axis)
-* TL_RES_LEN - sinus resolution (X axis)
-*/
-#define TL_TAB_LEN (12*2*TL_RES_LEN)
-static signed int tl_tab[TL_TAB_LEN];
-
-#define ENV_QUIET (TL_TAB_LEN>>4)
+signed int FM_OPL::tl_tab[TL_TAB_LEN];
/* sin waveform table in 'decibel' scale */
/* four waveforms on OPL2 type chips */
-static unsigned int sin_tab[SIN_LEN * 4];
+unsigned int FM_OPL::sin_tab[SIN_LEN * 4];
/* LFO Amplitude Modulation table (verified on real YM3812)
@@ -541,9 +1206,7 @@ static unsigned int sin_tab[SIN_LEN * 4];
When AM = 0 data is divided by 4 before being used (losing precision is important)
*/
-#define LFO_AM_TAB_ELEMENTS 210
-
-static const uint8_t lfo_am_table[LFO_AM_TAB_ELEMENTS] = {
+const uint8_t FM_OPL::lfo_am_table[LFO_AM_TAB_ELEMENTS] = {
0,0,0,0,0,0,0,
1,1,1,1,
2,2,2,2,
@@ -599,7 +1262,7 @@ static const uint8_t lfo_am_table[LFO_AM_TAB_ELEMENTS] = {
};
/* LFO Phase Modulation table (verified on real YM3812) */
-static const int8_t lfo_pm_table[8*8*2] = {
+const int8_t FM_OPL::lfo_pm_table[8*8*2] = {
/* FNUM2/FNUM = 00 0xxxxxxx (0x0000) */
0, 0, 0, 0, 0, 0, 0, 0, /*LFO PM depth = 0*/
0, 0, 0, 0, 0, 0, 0, 0, /*LFO PM depth = 1*/
@@ -635,14 +1298,7 @@ static const int8_t lfo_pm_table[8*8*2] = {
/* lock level of common table */
-static int num_lock = 0;
-
-
-#define SLOT7_1 (&OPL->P_CH[7].SLOT[SLOT1])
-#define SLOT7_2 (&OPL->P_CH[7].SLOT[SLOT2])
-#define SLOT8_1 (&OPL->P_CH[8].SLOT[SLOT1])
-#define SLOT8_2 (&OPL->P_CH[8].SLOT[SLOT2])
-
+int FM_OPL::num_lock = 0;
@@ -656,491 +1312,8 @@ static inline int limit( int val, int max, int min ) {
}
-/* status set and IRQ handling */
-static inline void OPL_STATUS_SET(FM_OPL *OPL,int flag)
-{
- /* set status flag */
- OPL->status |= flag;
- if(!(OPL->status & 0x80))
- {
- if(OPL->status & OPL->statusmask)
- { /* IRQ on */
- OPL->status |= 0x80;
- /* callback user interrupt handler (IRQ is OFF to ON) */
- if(OPL->IRQHandler) (OPL->IRQHandler)(OPL->IRQParam,1);
- }
- }
-}
-
-/* status reset and IRQ handling */
-static inline void OPL_STATUS_RESET(FM_OPL *OPL,int flag)
-{
- /* reset status flag */
- OPL->status &=~flag;
- if((OPL->status & 0x80))
- {
- if (!(OPL->status & OPL->statusmask) )
- {
- OPL->status &= 0x7f;
- /* callback user interrupt handler (IRQ is ON to OFF) */
- if(OPL->IRQHandler) (OPL->IRQHandler)(OPL->IRQParam,0);
- }
- }
-}
-
-/* IRQ mask set */
-static inline void OPL_STATUSMASK_SET(FM_OPL *OPL,int flag)
-{
- OPL->statusmask = flag;
- /* IRQ handling check */
- OPL_STATUS_SET(OPL,0);
- OPL_STATUS_RESET(OPL,0);
-}
-
-
-/* advance LFO to next sample */
-static inline void advance_lfo(FM_OPL *OPL)
-{
- uint8_t tmp;
-
- /* LFO */
- OPL->lfo_am_cnt += OPL->lfo_am_inc;
- if (OPL->lfo_am_cnt >= ((uint32_t)LFO_AM_TAB_ELEMENTS<<LFO_SH) ) /* lfo_am_table is 210 elements long */
- OPL->lfo_am_cnt -= ((uint32_t)LFO_AM_TAB_ELEMENTS<<LFO_SH);
-
- tmp = lfo_am_table[ OPL->lfo_am_cnt >> LFO_SH ];
-
- if (OPL->lfo_am_depth)
- OPL->LFO_AM = tmp;
- else
- OPL->LFO_AM = tmp>>2;
-
- OPL->lfo_pm_cnt += OPL->lfo_pm_inc;
- OPL->LFO_PM = ((OPL->lfo_pm_cnt>>LFO_SH) & 7) | OPL->lfo_pm_depth_range;
-}
-
-/* advance to next sample */
-static inline void advance(FM_OPL *OPL)
-{
- OPL_CH *CH;
- OPL_SLOT *op;
- int i;
-
- OPL->eg_timer += OPL->eg_timer_add;
-
- while (OPL->eg_timer >= OPL->eg_timer_overflow)
- {
- OPL->eg_timer -= OPL->eg_timer_overflow;
-
- OPL->eg_cnt++;
-
- for (i=0; i<9*2; i++)
- {
- CH = &OPL->P_CH[i/2];
- op = &CH->SLOT[i&1];
-
- /* Envelope Generator */
- switch(op->state)
- {
- case EG_ATT: /* attack phase */
- if ( !(OPL->eg_cnt & ((1<<op->eg_sh_ar)-1) ) )
- {
- op->volume += (~op->volume *
- (eg_inc[op->eg_sel_ar + ((OPL->eg_cnt>>op->eg_sh_ar)&7)])
- ) >>3;
-
- if (op->volume <= MIN_ATT_INDEX)
- {
- op->volume = MIN_ATT_INDEX;
- op->state = EG_DEC;
- }
-
- }
- break;
-
- case EG_DEC: /* decay phase */
- if ( !(OPL->eg_cnt & ((1<<op->eg_sh_dr)-1) ) )
- {
- op->volume += eg_inc[op->eg_sel_dr + ((OPL->eg_cnt>>op->eg_sh_dr)&7)];
-
- if ( op->volume >= op->sl )
- op->state = EG_SUS;
-
- }
- break;
-
- case EG_SUS: /* sustain phase */
-
- /* this is important behaviour:
- one can change percusive/non-percussive modes on the fly and
- the chip will remain in sustain phase - verified on real YM3812 */
-
- if(op->eg_type) /* non-percussive mode */
- {
- /* do nothing */
- }
- else /* percussive mode */
- {
- /* during sustain phase chip adds Release Rate (in percussive mode) */
- if ( !(OPL->eg_cnt & ((1<<op->eg_sh_rr)-1) ) )
- {
- op->volume += eg_inc[op->eg_sel_rr + ((OPL->eg_cnt>>op->eg_sh_rr)&7)];
-
- if ( op->volume >= MAX_ATT_INDEX )
- op->volume = MAX_ATT_INDEX;
- }
- /* else do nothing in sustain phase */
- }
- break;
-
- case EG_REL: /* release phase */
- if ( !(OPL->eg_cnt & ((1<<op->eg_sh_rr)-1) ) )
- {
- op->volume += eg_inc[op->eg_sel_rr + ((OPL->eg_cnt>>op->eg_sh_rr)&7)];
-
- if ( op->volume >= MAX_ATT_INDEX )
- {
- op->volume = MAX_ATT_INDEX;
- op->state = EG_OFF;
- }
-
- }
- break;
-
- default:
- break;
- }
- }
- }
-
- for (i=0; i<9*2; i++)
- {
- CH = &OPL->P_CH[i/2];
- op = &CH->SLOT[i&1];
-
- /* Phase Generator */
- if(op->vib)
- {
- uint8_t block;
- unsigned int block_fnum = CH->block_fnum;
-
- unsigned int fnum_lfo = (block_fnum&0x0380) >> 7;
-
- signed int lfo_fn_table_index_offset = lfo_pm_table[OPL->LFO_PM + 16*fnum_lfo ];
-
- if (lfo_fn_table_index_offset) /* LFO phase modulation active */
- {
- block_fnum += lfo_fn_table_index_offset;
- block = (block_fnum&0x1c00) >> 10;
- op->Cnt += (OPL->fn_tab[block_fnum&0x03ff] >> (7-block)) * op->mul;
- }
- else /* LFO phase modulation = zero */
- {
- op->Cnt += op->Incr;
- }
- }
- else /* LFO phase modulation disabled for this operator */
- {
- op->Cnt += op->Incr;
- }
- }
-
- /* The Noise Generator of the YM3812 is 23-bit shift register.
- * Period is equal to 2^23-2 samples.
- * Register works at sampling frequency of the chip, so output
- * can change on every sample.
- *
- * Output of the register and input to the bit 22 is:
- * bit0 XOR bit14 XOR bit15 XOR bit22
- *
- * Simply use bit 22 as the noise output.
- */
-
- OPL->noise_p += OPL->noise_f;
- i = OPL->noise_p >> FREQ_SH; /* number of events (shifts of the shift register) */
- OPL->noise_p &= FREQ_MASK;
- while (i)
- {
- /*
- uint32_t j;
- j = ( (OPL->noise_rng) ^ (OPL->noise_rng>>14) ^ (OPL->noise_rng>>15) ^ (OPL->noise_rng>>22) ) & 1;
- OPL->noise_rng = (j<<22) | (OPL->noise_rng>>1);
- */
-
- /*
- Instead of doing all the logic operations above, we
- use a trick here (and use bit 0 as the noise output).
- The difference is only that the noise bit changes one
- step ahead. This doesn't matter since we don't know
- what is real state of the noise_rng after the reset.
- */
-
- if (OPL->noise_rng & 1) OPL->noise_rng ^= 0x800302;
- OPL->noise_rng >>= 1;
-
- i--;
- }
-}
-
-
-static inline signed int op_calc(uint32_t phase, unsigned int env, signed int pm, unsigned int wave_tab)
-{
- uint32_t p;
-
- p = (env<<4) + sin_tab[wave_tab + ((((signed int)((phase & ~FREQ_MASK) + (pm<<16))) >> FREQ_SH ) & SIN_MASK) ];
-
- if (p >= TL_TAB_LEN)
- return 0;
- return tl_tab[p];
-}
-
-static inline signed int op_calc1(uint32_t phase, unsigned int env, signed int pm, unsigned int wave_tab)
-{
- uint32_t p;
-
- p = (env<<4) + sin_tab[wave_tab + ((((signed int)((phase & ~FREQ_MASK) + pm )) >> FREQ_SH ) & SIN_MASK) ];
-
- if (p >= TL_TAB_LEN)
- return 0;
- return tl_tab[p];
-}
-
-
-#define volume_calc(OP) ((OP)->TLL + ((uint32_t)(OP)->volume) + (OPL->LFO_AM & (OP)->AMmask))
-
-/* calculate output */
-static inline void OPL_CALC_CH( FM_OPL *OPL, OPL_CH *CH )
-{
- OPL_SLOT *SLOT;
- unsigned int env;
- signed int out;
-
- OPL->phase_modulation = 0;
-
- /* SLOT 1 */
- SLOT = &CH->SLOT[SLOT1];
- env = volume_calc(SLOT);
- out = SLOT->op1_out[0] + SLOT->op1_out[1];
- SLOT->op1_out[0] = SLOT->op1_out[1];
- *SLOT->connect1 += SLOT->op1_out[0];
- SLOT->op1_out[1] = 0;
- if( env < ENV_QUIET )
- {
- if (!SLOT->FB)
- out = 0;
- SLOT->op1_out[1] = op_calc1(SLOT->Cnt, env, (out<<SLOT->FB), SLOT->wavetable );
- }
-
- /* SLOT 2 */
- SLOT++;
- env = volume_calc(SLOT);
- if( env < ENV_QUIET )
- OPL->output[0] += op_calc(SLOT->Cnt, env, OPL->phase_modulation, SLOT->wavetable);
-}
-
-/*
- operators used in the rhythm sounds generation process:
-
- Envelope Generator:
-
-channel operator register number Bass High Snare Tom Top
-/ slot number TL ARDR SLRR Wave Drum Hat Drum Tom Cymbal
- 6 / 0 12 50 70 90 f0 +
- 6 / 1 15 53 73 93 f3 +
- 7 / 0 13 51 71 91 f1 +
- 7 / 1 16 54 74 94 f4 +
- 8 / 0 14 52 72 92 f2 +
- 8 / 1 17 55 75 95 f5 +
-
- Phase Generator:
-
-channel operator register number Bass High Snare Tom Top
-/ slot number MULTIPLE Drum Hat Drum Tom Cymbal
- 6 / 0 12 30 +
- 6 / 1 15 33 +
- 7 / 0 13 31 + + +
- 7 / 1 16 34 ----- n o t u s e d -----
- 8 / 0 14 32 +
- 8 / 1 17 35 + +
-
-channel operator register number Bass High Snare Tom Top
-number number BLK/FNUM2 FNUM Drum Hat Drum Tom Cymbal
- 6 12,15 B6 A6 +
-
- 7 13,16 B7 A7 + + +
-
- 8 14,17 B8 A8 + + +
-
-*/
-
-/* calculate rhythm */
-
-static inline void OPL_CALC_RH( FM_OPL *OPL, OPL_CH *CH, unsigned int noise )
-{
- OPL_SLOT *SLOT;
- signed int out;
- unsigned int env;
-
-
- /* Bass Drum (verified on real YM3812):
- - depends on the channel 6 'connect' register:
- when connect = 0 it works the same as in normal (non-rhythm) mode (op1->op2->out)
- when connect = 1 _only_ operator 2 is present on output (op2->out), operator 1 is ignored
- - output sample always is multiplied by 2
- */
-
- OPL->phase_modulation = 0;
- /* SLOT 1 */
- SLOT = &CH[6].SLOT[SLOT1];
- env = volume_calc(SLOT);
-
- out = SLOT->op1_out[0] + SLOT->op1_out[1];
- SLOT->op1_out[0] = SLOT->op1_out[1];
-
- if (!SLOT->CON)
- OPL->phase_modulation = SLOT->op1_out[0];
- /* else ignore output of operator 1 */
-
- SLOT->op1_out[1] = 0;
- if( env < ENV_QUIET )
- {
- if (!SLOT->FB)
- out = 0;
- SLOT->op1_out[1] = op_calc1(SLOT->Cnt, env, (out<<SLOT->FB), SLOT->wavetable );
- }
-
- /* SLOT 2 */
- SLOT++;
- env = volume_calc(SLOT);
- if( env < ENV_QUIET )
- OPL->output[0] += op_calc(SLOT->Cnt, env, OPL->phase_modulation, SLOT->wavetable) * 2;
-
-
- /* Phase generation is based on: */
- /* HH (13) channel 7->slot 1 combined with channel 8->slot 2 (same combination as TOP CYMBAL but different output phases) */
- /* SD (16) channel 7->slot 1 */
- /* TOM (14) channel 8->slot 1 */
- /* TOP (17) channel 7->slot 1 combined with channel 8->slot 2 (same combination as HIGH HAT but different output phases) */
-
- /* Envelope generation based on: */
- /* HH channel 7->slot1 */
- /* SD channel 7->slot2 */
- /* TOM channel 8->slot1 */
- /* TOP channel 8->slot2 */
-
-
- /* The following formulas can be well optimized.
- I leave them in direct form for now (in case I've missed something).
- */
-
- /* High Hat (verified on real YM3812) */
- env = volume_calc(SLOT7_1);
- if( env < ENV_QUIET )
- {
- /* high hat phase generation:
- phase = d0 or 234 (based on frequency only)
- phase = 34 or 2d0 (based on noise)
- */
-
- /* base frequency derived from operator 1 in channel 7 */
- unsigned char bit7 = ((SLOT7_1->Cnt>>FREQ_SH)>>7)&1;
- unsigned char bit3 = ((SLOT7_1->Cnt>>FREQ_SH)>>3)&1;
- unsigned char bit2 = ((SLOT7_1->Cnt>>FREQ_SH)>>2)&1;
-
- unsigned char res1 = (bit2 ^ bit7) | bit3;
-
- /* when res1 = 0 phase = 0x000 | 0xd0; */
- /* when res1 = 1 phase = 0x200 | (0xd0>>2); */
- uint32_t phase = res1 ? (0x200|(0xd0>>2)) : 0xd0;
-
- /* enable gate based on frequency of operator 2 in channel 8 */
- unsigned char bit5e= ((SLOT8_2->Cnt>>FREQ_SH)>>5)&1;
- unsigned char bit3e= ((SLOT8_2->Cnt>>FREQ_SH)>>3)&1;
-
- unsigned char res2 = (bit3e ^ bit5e);
-
- /* when res2 = 0 pass the phase from calculation above (res1); */
- /* when res2 = 1 phase = 0x200 | (0xd0>>2); */
- if (res2)
- phase = (0x200|(0xd0>>2));
-
-
- /* when phase & 0x200 is set and noise=1 then phase = 0x200|0xd0 */
- /* when phase & 0x200 is set and noise=0 then phase = 0x200|(0xd0>>2), ie no change */
- if (phase&0x200)
- {
- if (noise)
- phase = 0x200|0xd0;
- }
- else
- /* when phase & 0x200 is clear and noise=1 then phase = 0xd0>>2 */
- /* when phase & 0x200 is clear and noise=0 then phase = 0xd0, ie no change */
- {
- if (noise)
- phase = 0xd0>>2;
- }
-
- OPL->output[0] += op_calc(phase<<FREQ_SH, env, 0, SLOT7_1->wavetable) * 2;
- }
-
- /* Snare Drum (verified on real YM3812) */
- env = volume_calc(SLOT7_2);
- if( env < ENV_QUIET )
- {
- /* base frequency derived from operator 1 in channel 7 */
- unsigned char bit8 = ((SLOT7_1->Cnt>>FREQ_SH)>>8)&1;
-
- /* when bit8 = 0 phase = 0x100; */
- /* when bit8 = 1 phase = 0x200; */
- uint32_t phase = bit8 ? 0x200 : 0x100;
-
- /* Noise bit XOR'es phase by 0x100 */
- /* when noisebit = 0 pass the phase from calculation above */
- /* when noisebit = 1 phase ^= 0x100; */
- /* in other words: phase ^= (noisebit<<8); */
- if (noise)
- phase ^= 0x100;
-
- OPL->output[0] += op_calc(phase<<FREQ_SH, env, 0, SLOT7_2->wavetable) * 2;
- }
-
- /* Tom Tom (verified on real YM3812) */
- env = volume_calc(SLOT8_1);
- if( env < ENV_QUIET )
- OPL->output[0] += op_calc(SLOT8_1->Cnt, env, 0, SLOT8_1->wavetable) * 2;
-
- /* Top Cymbal (verified on real YM3812) */
- env = volume_calc(SLOT8_2);
- if( env < ENV_QUIET )
- {
- /* base frequency derived from operator 1 in channel 7 */
- unsigned char bit7 = ((SLOT7_1->Cnt>>FREQ_SH)>>7)&1;
- unsigned char bit3 = ((SLOT7_1->Cnt>>FREQ_SH)>>3)&1;
- unsigned char bit2 = ((SLOT7_1->Cnt>>FREQ_SH)>>2)&1;
-
- unsigned char res1 = (bit2 ^ bit7) | bit3;
-
- /* when res1 = 0 phase = 0x000 | 0x100; */
- /* when res1 = 1 phase = 0x200 | 0x100; */
- uint32_t phase = res1 ? 0x300 : 0x100;
-
- /* enable gate based on frequency of operator 2 in channel 8 */
- unsigned char bit5e= ((SLOT8_2->Cnt>>FREQ_SH)>>5)&1;
- unsigned char bit3e= ((SLOT8_2->Cnt>>FREQ_SH)>>3)&1;
-
- unsigned char res2 = (bit3e ^ bit5e);
- /* when res2 = 0 pass the phase from calculation above (res1); */
- /* when res2 = 1 phase = 0x200 | 0x100; */
- if (res2)
- phase = 0x300;
-
- OPL->output[0] += op_calc(phase<<FREQ_SH, env, 0, SLOT8_2->wavetable) * 2;
- }
-}
-
-
/* generic table initialize */
-static int init_tables(void)
+int FM_OPL::init_tables()
{
signed int i,x;
signed int n;
@@ -1246,39 +1419,31 @@ static int init_tables(void)
return 1;
}
-static void OPLCloseTable( void )
-{
-#ifdef SAVE_SAMPLE
- fclose(sample[0]);
-#endif
-}
-
-
-static void OPL_initalize(FM_OPL *OPL)
+void FM_OPL::initialize()
{
int i;
/* frequency base */
- OPL->freqbase = (OPL->rate) ? ((double)OPL->clock / 72.0) / OPL->rate : 0;
+ freqbase = (rate) ? ((double)clock / 72.0) / rate : 0;
#if 0
- OPL->rate = (double)OPL->clock / 72.0;
- OPL->freqbase = 1.0;
+ rate = (double)clock / 72.0;
+ freqbase = 1.0;
#endif
- /*logerror("freqbase=%f\n", OPL->freqbase);*/
+ /*logerror("freqbase=%f\n", freqbase);*/
/* Timer base time */
- OPL->TimerBase = attotime::from_hz(OPL->clock) * 72;
+ TimerBase = attotime::from_hz(clock) * 72;
/* make fnumber -> increment counter table */
for( i=0 ; i < 1024 ; i++ )
{
/* opn phase increment counter = 20bit */
- OPL->fn_tab[i] = (uint32_t)( (double)i * 64 * OPL->freqbase * (1<<(FREQ_SH-10)) ); /* -10 because chip works with 10.10 fixed point, while we use 16.16 */
+ fn_tab[i] = (uint32_t)( (double)i * 64 * freqbase * (1<<(FREQ_SH-10)) ); /* -10 because chip works with 10.10 fixed point, while we use 16.16 */
#if 0
logerror("FMOPL.C: fn_tab[%4i] = %08x (dec=%8i)\n",
- i, OPL->fn_tab[i]>>6, OPL->fn_tab[i]>>6 );
+ i, fn_tab[i]>>6, fn_tab[i]>>6 );
#endif
}
@@ -1303,146 +1468,24 @@ static void OPL_initalize(FM_OPL *OPL)
/* Amplitude modulation: 27 output levels (triangle waveform); 1 level takes one of: 192, 256 or 448 samples */
/* One entry from LFO_AM_TABLE lasts for 64 samples */
- OPL->lfo_am_inc = (1.0 / 64.0 ) * (1<<LFO_SH) * OPL->freqbase;
+ lfo_am_inc = (1.0 / 64.0 ) * (1<<LFO_SH) * freqbase;
/* Vibrato: 8 output levels (triangle waveform); 1 level takes 1024 samples */
- OPL->lfo_pm_inc = (1.0 / 1024.0) * (1<<LFO_SH) * OPL->freqbase;
+ lfo_pm_inc = (1.0 / 1024.0) * (1<<LFO_SH) * freqbase;
- /*logerror ("OPL->lfo_am_inc = %8x ; OPL->lfo_pm_inc = %8x\n", OPL->lfo_am_inc, OPL->lfo_pm_inc);*/
+ /*logerror ("lfo_am_inc = %8x ; lfo_pm_inc = %8x\n", lfo_am_inc, lfo_pm_inc);*/
/* Noise generator: a step takes 1 sample */
- OPL->noise_f = (1.0 / 1.0) * (1<<FREQ_SH) * OPL->freqbase;
+ noise_f = (1.0 / 1.0) * (1<<FREQ_SH) * freqbase;
- OPL->eg_timer_add = (1<<EG_SH) * OPL->freqbase;
- OPL->eg_timer_overflow = ( 1 ) * (1<<EG_SH);
- /*logerror("OPLinit eg_timer_add=%8x eg_timer_overflow=%8x\n", OPL->eg_timer_add, OPL->eg_timer_overflow);*/
-
-}
-
-static inline void FM_KEYON(OPL_SLOT *SLOT, uint32_t key_set)
-{
- if( !SLOT->key )
- {
- /* restart Phase Generator */
- SLOT->Cnt = 0;
- /* phase -> Attack */
- SLOT->state = EG_ATT;
- }
- SLOT->key |= key_set;
-}
-
-static inline void FM_KEYOFF(OPL_SLOT *SLOT, uint32_t key_clr)
-{
- if( SLOT->key )
- {
- SLOT->key &= key_clr;
-
- if( !SLOT->key )
- {
- /* phase -> Release */
- if (SLOT->state>EG_REL)
- SLOT->state = EG_REL;
- }
- }
-}
-
-/* update phase increment counter of operator (also update the EG rates if necessary) */
-static inline void CALC_FCSLOT(OPL_CH *CH,OPL_SLOT *SLOT)
-{
- int ksr;
-
- /* (frequency) phase increment counter */
- SLOT->Incr = CH->fc * SLOT->mul;
- ksr = CH->kcode >> SLOT->KSR;
-
- if( SLOT->ksr != ksr )
- {
- SLOT->ksr = ksr;
-
- /* calculate envelope generator rates */
- if ((SLOT->ar + SLOT->ksr) < 16+62)
- {
- SLOT->eg_sh_ar = eg_rate_shift [SLOT->ar + SLOT->ksr ];
- SLOT->eg_sel_ar = eg_rate_select[SLOT->ar + SLOT->ksr ];
- }
- else
- {
- SLOT->eg_sh_ar = 0;
- SLOT->eg_sel_ar = 13*RATE_STEPS;
- }
- SLOT->eg_sh_dr = eg_rate_shift [SLOT->dr + SLOT->ksr ];
- SLOT->eg_sel_dr = eg_rate_select[SLOT->dr + SLOT->ksr ];
- SLOT->eg_sh_rr = eg_rate_shift [SLOT->rr + SLOT->ksr ];
- SLOT->eg_sel_rr = eg_rate_select[SLOT->rr + SLOT->ksr ];
- }
-}
-
-/* set multi,am,vib,EG-TYP,KSR,mul */
-static inline void set_mul(FM_OPL *OPL,int slot,int v)
-{
- OPL_CH *CH = &OPL->P_CH[slot/2];
- OPL_SLOT *SLOT = &CH->SLOT[slot&1];
-
- SLOT->mul = mul_tab[v&0x0f];
- SLOT->KSR = (v&0x10) ? 0 : 2;
- SLOT->eg_type = (v&0x20);
- SLOT->vib = (v&0x40);
- SLOT->AMmask = (v&0x80) ? ~0 : 0;
- CALC_FCSLOT(CH,SLOT);
-}
-
-/* set ksl & tl */
-static inline void set_ksl_tl(FM_OPL *OPL,int slot,int v)
-{
- OPL_CH *CH = &OPL->P_CH[slot/2];
- OPL_SLOT *SLOT = &CH->SLOT[slot&1];
-
- SLOT->ksl = ksl_shift[v >> 6];
- SLOT->TL = (v&0x3f)<<(ENV_BITS-1-7); /* 7 bits TL (bit 6 = always 0) */
-
- SLOT->TLL = SLOT->TL + (CH->ksl_base>>SLOT->ksl);
-}
-
-/* set attack rate & decay rate */
-static inline void set_ar_dr(FM_OPL *OPL,int slot,int v)
-{
- OPL_CH *CH = &OPL->P_CH[slot/2];
- OPL_SLOT *SLOT = &CH->SLOT[slot&1];
-
- SLOT->ar = (v>>4) ? 16 + ((v>>4) <<2) : 0;
-
- if ((SLOT->ar + SLOT->ksr) < 16+62)
- {
- SLOT->eg_sh_ar = eg_rate_shift [SLOT->ar + SLOT->ksr ];
- SLOT->eg_sel_ar = eg_rate_select[SLOT->ar + SLOT->ksr ];
- }
- else
- {
- SLOT->eg_sh_ar = 0;
- SLOT->eg_sel_ar = 13*RATE_STEPS;
- }
-
- SLOT->dr = (v&0x0f)? 16 + ((v&0x0f)<<2) : 0;
- SLOT->eg_sh_dr = eg_rate_shift [SLOT->dr + SLOT->ksr ];
- SLOT->eg_sel_dr = eg_rate_select[SLOT->dr + SLOT->ksr ];
-}
-
-/* set sustain level & release rate */
-static inline void set_sl_rr(FM_OPL *OPL,int slot,int v)
-{
- OPL_CH *CH = &OPL->P_CH[slot/2];
- OPL_SLOT *SLOT = &CH->SLOT[slot&1];
-
- SLOT->sl = sl_tab[ v>>4 ];
-
- SLOT->rr = (v&0x0f)? 16 + ((v&0x0f)<<2) : 0;
- SLOT->eg_sh_rr = eg_rate_shift [SLOT->rr + SLOT->ksr ];
- SLOT->eg_sel_rr = eg_rate_select[SLOT->rr + SLOT->ksr ];
+ eg_timer_add = (1<<EG_SH) * freqbase;
+ eg_timer_overflow = ( 1 ) * (1<<EG_SH);
+ /*logerror("OPLinit eg_timer_add=%8x eg_timer_overflow=%8x\n", eg_timer_add, eg_timer_overflow);*/
}
/* write a value v to register r on OPL chip */
-static void OPLWriteReg(FM_OPL *OPL, int r, int v)
+void FM_OPL::WriteReg(int r, int v)
{
OPL_CH *CH;
int slot;
@@ -1459,22 +1502,22 @@ static void OPLWriteReg(FM_OPL *OPL, int r, int v)
switch(r&0x1f)
{
case 0x01: /* waveform select enable */
- if(OPL->type&OPL_TYPE_WAVESEL)
+ if(type&OPL_TYPE_WAVESEL)
{
- OPL->wavesel = v&0x20;
+ wavesel = v&0x20;
/* do not change the waveform previously selected */
}
break;
case 0x02: /* Timer 1 */
- OPL->T[0] = (256-v)*4;
+ T[0] = (256-v)*4;
break;
case 0x03: /* Timer 2 */
- OPL->T[1] = (256-v)*16;
+ T[1] = (256-v)*16;
break;
case 0x04: /* IRQ clear / mask and Timer enable */
if(v&0x80)
{ /* IRQ flag clear */
- OPL_STATUS_RESET(OPL,0x7f-0x08); /* don't reset BFRDY flag or we will have to call deltat module to set the flag */
+ STATUS_RESET(0x7f-0x08); /* don't reset BFRDY flag or we will have to call deltat module to set the flag */
}
else
{ /* set IRQ mask ,timer enable*/
@@ -1482,45 +1525,45 @@ static void OPLWriteReg(FM_OPL *OPL, int r, int v)
uint8_t st2 = (v>>1)&1;
/* IRQRST,T1MSK,t2MSK,EOSMSK,BRMSK,x,ST2,ST1 */
- OPL_STATUS_RESET(OPL, v & (0x78-0x08) );
- OPL_STATUSMASK_SET(OPL, (~v) & 0x78 );
+ STATUS_RESET(v & (0x78-0x08));
+ STATUSMASK_SET((~v) & 0x78);
/* timer 2 */
- if(OPL->st[1] != st2)
+ if(st[1] != st2)
{
- attotime period = st2 ? (OPL->TimerBase * OPL->T[1]) : attotime::zero;
- OPL->st[1] = st2;
- if (OPL->timer_handler) (OPL->timer_handler)(OPL->TimerParam,1,period);
+ attotime period = st2 ? (TimerBase * T[1]) : attotime::zero;
+ st[1] = st2;
+ if (timer_handler) (timer_handler)(TimerParam,1,period);
}
/* timer 1 */
- if(OPL->st[0] != st1)
+ if(st[0] != st1)
{
- attotime period = st1 ? (OPL->TimerBase * OPL->T[0]) : attotime::zero;
- OPL->st[0] = st1;
- if (OPL->timer_handler) (OPL->timer_handler)(OPL->TimerParam,0,period);
+ attotime period = st1 ? (TimerBase * T[0]) : attotime::zero;
+ st[0] = st1;
+ if (timer_handler) (timer_handler)(TimerParam,0,period);
}
}
break;
#if BUILD_Y8950
case 0x06: /* Key Board OUT */
- if(OPL->type&OPL_TYPE_KEYBOARD)
+ if(type&OPL_TYPE_KEYBOARD)
{
- if(OPL->keyboardhandler_w)
- OPL->keyboardhandler_w(OPL->keyboard_param,v);
+ if(keyboardhandler_w)
+ keyboardhandler_w(keyboard_param,v);
else
- OPL->device->logerror("Y8950: write unmapped KEYBOARD port\n");
+ device->logerror("Y8950: write unmapped KEYBOARD port\n");
}
break;
case 0x07: /* DELTA-T control 1 : START,REC,MEMDATA,REPT,SPOFF,x,x,RST */
- if(OPL->type&OPL_TYPE_ADPCM)
- YM_DELTAT_ADPCM_Write(OPL->deltat,r-0x07,v);
+ if(type&OPL_TYPE_ADPCM)
+ deltat->ADPCM_Write(r-0x07,v);
break;
#endif
case 0x08: /* MODE,DELTA-T control 2 : CSM,NOTESEL,x,x,smpl,da/ad,64k,rom */
- OPL->mode = v;
+ mode = v;
#if BUILD_Y8950
- if(OPL->type&OPL_TYPE_ADPCM)
- YM_DELTAT_ADPCM_Write(OPL->deltat,r-0x07,v&0x0f); /* mask 4 LSBs in register 08 for DELTA-T unit */
+ if(type&OPL_TYPE_ADPCM)
+ deltat->ADPCM_Write(r-0x07,v&0x0f); /* mask 4 LSBs in register 08 for DELTA-T unit */
#endif
break;
@@ -1535,107 +1578,107 @@ static void OPLWriteReg(FM_OPL *OPL, int r, int v)
case 0x10: /* DELTA-N */
case 0x11: /* DELTA-N */
case 0x12: /* ADPCM volume */
- if(OPL->type&OPL_TYPE_ADPCM)
- YM_DELTAT_ADPCM_Write(OPL->deltat,r-0x07,v);
+ if(type&OPL_TYPE_ADPCM)
+ deltat->ADPCM_Write(r-0x07,v);
break;
case 0x15: /* DAC data high 8 bits (F7,F6...F2) */
case 0x16: /* DAC data low 2 bits (F1, F0 in bits 7,6) */
case 0x17: /* DAC data shift (S2,S1,S0 in bits 2,1,0) */
- OPL->device->logerror("FMOPL.C: DAC data register written, but not implemented reg=%02x val=%02x\n",r,v);
+ device->logerror("FMOPL.C: DAC data register written, but not implemented reg=%02x val=%02x\n",r,v);
break;
case 0x18: /* I/O CTRL (Direction) */
- if(OPL->type&OPL_TYPE_IO)
- OPL->portDirection = v&0x0f;
+ if(type&OPL_TYPE_IO)
+ portDirection = v&0x0f;
break;
case 0x19: /* I/O DATA */
- if(OPL->type&OPL_TYPE_IO)
+ if(type&OPL_TYPE_IO)
{
- OPL->portLatch = v;
- if(OPL->porthandler_w)
- OPL->porthandler_w(OPL->port_param,v&OPL->portDirection);
+ portLatch = v;
+ if(porthandler_w)
+ porthandler_w(port_param,v&portDirection);
}
break;
#endif
default:
- OPL->device->logerror("FMOPL.C: write to unknown register: %02x\n",r);
+ device->logerror("FMOPL.C: write to unknown register: %02x\n",r);
break;
}
break;
case 0x20: /* am ON, vib ON, ksr, eg_type, mul */
slot = slot_array[r&0x1f];
if(slot < 0) return;
- set_mul(OPL,slot,v);
+ set_mul(slot,v);
break;
case 0x40:
slot = slot_array[r&0x1f];
if(slot < 0) return;
- set_ksl_tl(OPL,slot,v);
+ set_ksl_tl(slot,v);
break;
case 0x60:
slot = slot_array[r&0x1f];
if(slot < 0) return;
- set_ar_dr(OPL,slot,v);
+ set_ar_dr(slot,v);
break;
case 0x80:
slot = slot_array[r&0x1f];
if(slot < 0) return;
- set_sl_rr(OPL,slot,v);
+ set_sl_rr(slot,v);
break;
case 0xa0:
if (r == 0xbd) /* am depth, vibrato depth, r,bd,sd,tom,tc,hh */
{
- OPL->lfo_am_depth = v & 0x80;
- OPL->lfo_pm_depth_range = (v&0x40) ? 8 : 0;
+ lfo_am_depth = v & 0x80;
+ lfo_pm_depth_range = (v&0x40) ? 8 : 0;
- OPL->rhythm = v&0x3f;
+ rhythm = v&0x3f;
- if(OPL->rhythm&0x20)
+ if(rhythm&0x20)
{
/* BD key on/off */
if(v&0x10)
{
- FM_KEYON (&OPL->P_CH[6].SLOT[SLOT1], 2);
- FM_KEYON (&OPL->P_CH[6].SLOT[SLOT2], 2);
+ P_CH[6].SLOT[SLOT1].KEYON(2);
+ P_CH[6].SLOT[SLOT2].KEYON(2);
}
else
{
- FM_KEYOFF(&OPL->P_CH[6].SLOT[SLOT1],~2);
- FM_KEYOFF(&OPL->P_CH[6].SLOT[SLOT2],~2);
+ P_CH[6].SLOT[SLOT1].KEYOFF(~2);
+ P_CH[6].SLOT[SLOT2].KEYOFF(~2);
}
/* HH key on/off */
- if(v&0x01) FM_KEYON (&OPL->P_CH[7].SLOT[SLOT1], 2);
- else FM_KEYOFF(&OPL->P_CH[7].SLOT[SLOT1],~2);
+ if(v&0x01) P_CH[7].SLOT[SLOT1].KEYON ( 2);
+ else P_CH[7].SLOT[SLOT1].KEYOFF(~2);
/* SD key on/off */
- if(v&0x08) FM_KEYON (&OPL->P_CH[7].SLOT[SLOT2], 2);
- else FM_KEYOFF(&OPL->P_CH[7].SLOT[SLOT2],~2);
+ if(v&0x08) P_CH[7].SLOT[SLOT2].KEYON ( 2);
+ else P_CH[7].SLOT[SLOT2].KEYOFF(~2);
/* TOM key on/off */
- if(v&0x04) FM_KEYON (&OPL->P_CH[8].SLOT[SLOT1], 2);
- else FM_KEYOFF(&OPL->P_CH[8].SLOT[SLOT1],~2);
+ if(v&0x04) P_CH[8].SLOT[SLOT1].KEYON ( 2);
+ else P_CH[8].SLOT[SLOT1].KEYOFF(~2);
/* TOP-CY key on/off */
- if(v&0x02) FM_KEYON (&OPL->P_CH[8].SLOT[SLOT2], 2);
- else FM_KEYOFF(&OPL->P_CH[8].SLOT[SLOT2],~2);
+ if(v&0x02) P_CH[8].SLOT[SLOT2].KEYON ( 2);
+ else P_CH[8].SLOT[SLOT2].KEYOFF(~2);
}
else
{
/* BD key off */
- FM_KEYOFF(&OPL->P_CH[6].SLOT[SLOT1],~2);
- FM_KEYOFF(&OPL->P_CH[6].SLOT[SLOT2],~2);
+ P_CH[6].SLOT[SLOT1].KEYOFF(~2);
+ P_CH[6].SLOT[SLOT2].KEYOFF(~2);
/* HH key off */
- FM_KEYOFF(&OPL->P_CH[7].SLOT[SLOT1],~2);
+ P_CH[7].SLOT[SLOT1].KEYOFF(~2);
/* SD key off */
- FM_KEYOFF(&OPL->P_CH[7].SLOT[SLOT2],~2);
+ P_CH[7].SLOT[SLOT2].KEYOFF(~2);
/* TOM key off */
- FM_KEYOFF(&OPL->P_CH[8].SLOT[SLOT1],~2);
+ P_CH[8].SLOT[SLOT1].KEYOFF(~2);
/* TOP-CY off */
- FM_KEYOFF(&OPL->P_CH[8].SLOT[SLOT2],~2);
+ P_CH[8].SLOT[SLOT2].KEYOFF(~2);
}
return;
}
/* keyon,block,fnum */
if( (r&0x0f) > 8) return;
- CH = &OPL->P_CH[r&0x0f];
+ CH = &P_CH[r&0x0f];
if(!(r&0x10))
{ /* a0-a8 */
block_fnum = (CH->block_fnum&0x1f00) | v;
@@ -1646,13 +1689,13 @@ static void OPLWriteReg(FM_OPL *OPL, int r, int v)
if(v&0x20)
{
- FM_KEYON (&CH->SLOT[SLOT1], 1);
- FM_KEYON (&CH->SLOT[SLOT2], 1);
+ CH->SLOT[SLOT1].KEYON ( 1);
+ CH->SLOT[SLOT2].KEYON ( 1);
}
else
{
- FM_KEYOFF(&CH->SLOT[SLOT1],~1);
- FM_KEYOFF(&CH->SLOT[SLOT2],~1);
+ CH->SLOT[SLOT1].KEYOFF(~1);
+ CH->SLOT[SLOT2].KEYOFF(~1);
}
}
/* update */
@@ -1663,7 +1706,7 @@ static void OPLWriteReg(FM_OPL *OPL, int r, int v)
CH->block_fnum = block_fnum;
CH->ksl_base = static_cast<uint32_t>(ksl_tab[block_fnum>>6]);
- CH->fc = OPL->fn_tab[block_fnum&0x03ff] >> (7-block);
+ CH->fc = fn_tab[block_fnum&0x03ff] >> (7-block);
/* BLK 2,1,0 bits -> bits 3,2,1 of kcode */
CH->kcode = (CH->block_fnum&0x1c00)>>9;
@@ -1671,7 +1714,7 @@ static void OPLWriteReg(FM_OPL *OPL, int r, int v)
/* the info below is actually opposite to what is stated in the Manuals (verifed on real YM3812) */
/* if notesel == 0 -> lsb of kcode is bit 10 (MSB) of fnum */
/* if notesel == 1 -> lsb of kcode is bit 9 (MSB-1) of fnum */
- if (OPL->mode&0x40)
+ if (mode&0x40)
CH->kcode |= (CH->block_fnum&0x100)>>8; /* notesel == 1 */
else
CH->kcode |= (CH->block_fnum&0x200)>>9; /* notesel == 0 */
@@ -1681,25 +1724,25 @@ static void OPLWriteReg(FM_OPL *OPL, int r, int v)
CH->SLOT[SLOT2].TLL = CH->SLOT[SLOT2].TL + (CH->ksl_base>>CH->SLOT[SLOT2].ksl);
/* refresh frequency counter in both SLOTs of this channel */
- CALC_FCSLOT(CH,&CH->SLOT[SLOT1]);
- CALC_FCSLOT(CH,&CH->SLOT[SLOT2]);
+ CH->CALC_FCSLOT(CH->SLOT[SLOT1]);
+ CH->CALC_FCSLOT(CH->SLOT[SLOT2]);
}
break;
case 0xc0:
/* FB,C */
if( (r&0x0f) > 8) return;
- CH = &OPL->P_CH[r&0x0f];
+ CH = &P_CH[r&0x0f];
CH->SLOT[SLOT1].FB = (v>>1)&7 ? ((v>>1)&7) + 7 : 0;
CH->SLOT[SLOT1].CON = v&1;
- CH->SLOT[SLOT1].connect1 = CH->SLOT[SLOT1].CON ? &OPL->output[0] : &OPL->phase_modulation;
+ CH->SLOT[SLOT1].connect1 = CH->SLOT[SLOT1].CON ? &output[0] : &phase_modulation;
break;
case 0xe0: /* waveform select */
/* simply ignore write to the waveform select register if selecting not enabled in test register */
- if(OPL->wavesel)
+ if(wavesel)
{
slot = slot_array[r&0x1f];
if(slot < 0) return;
- CH = &OPL->P_CH[slot/2];
+ CH = &P_CH[slot/2];
CH->SLOT[slot&1].wavetable = (v&0x03)*SIN_LEN;
}
@@ -1707,136 +1750,101 @@ static void OPLWriteReg(FM_OPL *OPL, int r, int v)
}
}
-/* lock/unlock for common table */
-static int OPL_LockTable(device_t *device)
-{
- num_lock++;
- if(num_lock>1) return 0;
-
- /* first time */
-
- /* allocate total level table (128kb space) */
- if( !init_tables() )
- {
- num_lock--;
- return -1;
- }
-
- return 0;
-}
-
-static void OPL_UnLockTable(void)
-{
- if(num_lock) num_lock--;
- if(num_lock) return;
-
- /* last time */
- OPLCloseTable();
-}
-
-static void OPLResetChip(FM_OPL *OPL)
+void FM_OPL::ResetChip()
{
- int c,s;
- int i;
-
- OPL->eg_timer = 0;
- OPL->eg_cnt = 0;
+ eg_timer = 0;
+ eg_cnt = 0;
- OPL->noise_rng = 1; /* noise shift register */
- OPL->mode = 0; /* normal mode */
- OPL_STATUS_RESET(OPL,0x7f);
+ noise_rng = 1; /* noise shift register */
+ mode = 0; /* normal mode */
+ STATUS_RESET(0x7f);
/* reset with register write */
- OPLWriteReg(OPL,0x01,0); /* wavesel disable */
- OPLWriteReg(OPL,0x02,0); /* Timer1 */
- OPLWriteReg(OPL,0x03,0); /* Timer2 */
- OPLWriteReg(OPL,0x04,0); /* IRQ mask clear */
- for(i = 0xff ; i >= 0x20 ; i-- ) OPLWriteReg(OPL,i,0);
+ WriteReg(0x01,0); /* wavesel disable */
+ WriteReg(0x02,0); /* Timer1 */
+ WriteReg(0x03,0); /* Timer2 */
+ WriteReg(0x04,0); /* IRQ mask clear */
+ for(int i = 0xff ; i >= 0x20 ; i-- ) WriteReg(i,0);
/* reset operator parameters */
- for( c = 0 ; c < 9 ; c++ )
+ for(OPL_CH &CH : P_CH)
{
- OPL_CH *CH = &OPL->P_CH[c];
- for(s = 0 ; s < 2 ; s++ )
+ for(OPL_SLOT &SLOT : CH.SLOT)
{
/* wave table */
- CH->SLOT[s].wavetable = 0;
- CH->SLOT[s].state = EG_OFF;
- CH->SLOT[s].volume = MAX_ATT_INDEX;
+ SLOT.wavetable = 0;
+ SLOT.state = EG_OFF;
+ SLOT.volume = MAX_ATT_INDEX;
}
}
#if BUILD_Y8950
- if(OPL->type&OPL_TYPE_ADPCM)
+ if(type&OPL_TYPE_ADPCM)
{
- YM_DELTAT *DELTAT = OPL->deltat;
+ YM_DELTAT *DELTAT = deltat;
- DELTAT->freqbase = OPL->freqbase;
- DELTAT->output_pointer = &OPL->output_deltat[0];
+ DELTAT->freqbase = freqbase;
+ DELTAT->output_pointer = &output_deltat[0];
DELTAT->portshift = 5;
DELTAT->output_range = 1<<23;
- YM_DELTAT_ADPCM_Reset(DELTAT,0,YM_DELTAT_EMULATION_MODE_NORMAL,OPL->device);
+ DELTAT->ADPCM_Reset(0,YM_DELTAT::EMULATION_MODE_NORMAL,device);
}
#endif
}
-static void OPL_postload(FM_OPL *OPL)
+void FM_OPL::postload()
{
- int slot, ch;
-
- for( ch=0 ; ch < 9 ; ch++ )
+ for(OPL_CH &CH : P_CH)
{
- OPL_CH *CH = &OPL->P_CH[ch];
-
/* Look up key scale level */
- uint32_t block_fnum = CH->block_fnum;
- CH->ksl_base = static_cast<uint32_t>(ksl_tab[block_fnum >> 6]);
- CH->fc = OPL->fn_tab[block_fnum & 0x03ff] >> (7 - (block_fnum >> 10));
+ uint32_t const block_fnum = CH.block_fnum;
+ CH.ksl_base = static_cast<uint32_t>(ksl_tab[block_fnum >> 6]);
+ CH.fc = fn_tab[block_fnum & 0x03ff] >> (7 - (block_fnum >> 10));
- for( slot=0 ; slot < 2 ; slot++ )
+ for(OPL_SLOT &SLOT : CH.SLOT)
{
- OPL_SLOT *SLOT = &CH->SLOT[slot];
-
/* Calculate key scale rate */
- SLOT->ksr = CH->kcode >> SLOT->KSR;
+ SLOT.ksr = CH.kcode >> SLOT.KSR;
/* Calculate attack, decay and release rates */
- if ((SLOT->ar + SLOT->ksr) < 16+62)
+ if ((SLOT.ar + SLOT.ksr) < 16+62)
{
- SLOT->eg_sh_ar = eg_rate_shift [SLOT->ar + SLOT->ksr ];
- SLOT->eg_sel_ar = eg_rate_select[SLOT->ar + SLOT->ksr ];
+ SLOT.eg_sh_ar = eg_rate_shift [SLOT.ar + SLOT.ksr ];
+ SLOT.eg_sel_ar = eg_rate_select[SLOT.ar + SLOT.ksr ];
}
else
{
- SLOT->eg_sh_ar = 0;
- SLOT->eg_sel_ar = 13*RATE_STEPS;
+ SLOT.eg_sh_ar = 0;
+ SLOT.eg_sel_ar = 13*RATE_STEPS;
}
- SLOT->eg_sh_dr = eg_rate_shift [SLOT->dr + SLOT->ksr ];
- SLOT->eg_sel_dr = eg_rate_select[SLOT->dr + SLOT->ksr ];
- SLOT->eg_sh_rr = eg_rate_shift [SLOT->rr + SLOT->ksr ];
- SLOT->eg_sel_rr = eg_rate_select[SLOT->rr + SLOT->ksr ];
+ SLOT.eg_sh_dr = eg_rate_shift [SLOT.dr + SLOT.ksr ];
+ SLOT.eg_sel_dr = eg_rate_select[SLOT.dr + SLOT.ksr ];
+ SLOT.eg_sh_rr = eg_rate_shift [SLOT.rr + SLOT.ksr ];
+ SLOT.eg_sel_rr = eg_rate_select[SLOT.rr + SLOT.ksr ];
/* Calculate phase increment */
- SLOT->Incr = CH->fc * SLOT->mul;
+ SLOT.Incr = CH.fc * SLOT.mul;
/* Total level */
- SLOT->TLL = SLOT->TL + (CH->ksl_base >> SLOT->ksl);
+ SLOT.TLL = SLOT.TL + (CH.ksl_base >> SLOT.ksl);
/* Connect output */
- SLOT->connect1 = SLOT->CON ? &OPL->output[0] : &OPL->phase_modulation;
+ SLOT.connect1 = SLOT.CON ? &output[0] : &phase_modulation;
}
}
#if BUILD_Y8950
- if ( (OPL->type & OPL_TYPE_ADPCM) && (OPL->deltat) )
+ if ( (type & OPL_TYPE_ADPCM) && (deltat) )
{
// We really should call the postlod function for the YM_DELTAT, but it's hard without registers
// (see the way the YM2610 does it)
- //YM_DELTAT_postload(OPL->deltat, REGS);
+ //deltat->postload(REGS);
}
#endif
}
+} // anonymous namespace
+
static void OPLsave_state_channel(device_t *device, OPL_CH *CH)
{
@@ -1910,7 +1918,7 @@ static void OPL_save_state(FM_OPL *OPL, device_t *device)
#if BUILD_Y8950
if ( (OPL->type & OPL_TYPE_ADPCM) && (OPL->deltat) )
{
- YM_DELTAT_savestate(device, OPL->deltat);
+ OPL->deltat->savestate(device);
}
if ( OPL->type & OPL_TYPE_IO )
@@ -1925,7 +1933,7 @@ static void OPL_save_state(FM_OPL *OPL, device_t *device)
device->save_item(NAME(OPL->statusmask));
device->save_item(NAME(OPL->mode));
- device->machine().save().register_postload(save_prepost_delegate(FUNC(OPL_postload), OPL));
+ device->machine().save().register_postload(save_prepost_delegate(FUNC(FM_OPL::postload), OPL));
}
static void OPL_clock_changed(FM_OPL *OPL, uint32_t clock, uint32_t rate)
@@ -1934,7 +1942,7 @@ static void OPL_clock_changed(FM_OPL *OPL, uint32_t clock, uint32_t rate)
OPL->rate = rate;
/* init global tables */
- OPL_initalize(OPL);
+ OPL->initialize();
}
@@ -1947,7 +1955,7 @@ static FM_OPL *OPLCreate(device_t *device, uint32_t clock, uint32_t rate, int ty
FM_OPL *OPL;
int state_size;
- if (OPL_LockTable(device) == -1) return nullptr;
+ if (FM_OPL::LockTable(device) == -1) return nullptr;
/* calculate OPL state size */
state_size = sizeof(FM_OPL);
@@ -1981,26 +1989,26 @@ static FM_OPL *OPLCreate(device_t *device, uint32_t clock, uint32_t rate, int ty
/* Destroy one of virtual YM3812 */
static void OPLDestroy(FM_OPL *OPL)
{
- OPL_UnLockTable();
+ FM_OPL::UnLockTable();
auto_free(OPL->device->machine(), OPL);
}
/* Optional handlers */
-static void OPLSetTimerHandler(FM_OPL *OPL,OPL_TIMERHANDLER timer_handler,void *param)
+static void OPLSetTimerHandler(FM_OPL *OPL,OPL_TIMERHANDLER timer_handler,device_t *device)
{
OPL->timer_handler = timer_handler;
- OPL->TimerParam = param;
+ OPL->TimerParam = device;
}
-static void OPLSetIRQHandler(FM_OPL *OPL,OPL_IRQHANDLER IRQHandler,void *param)
+static void OPLSetIRQHandler(FM_OPL *OPL,OPL_IRQHANDLER IRQHandler,device_t *device)
{
OPL->IRQHandler = IRQHandler;
- OPL->IRQParam = param;
+ OPL->IRQParam = device;
}
-static void OPLSetUpdateHandler(FM_OPL *OPL,OPL_UPDATEHANDLER UpdateHandler,void *param)
+static void OPLSetUpdateHandler(FM_OPL *OPL,OPL_UPDATEHANDLER UpdateHandler,device_t *device)
{
OPL->UpdateHandler = UpdateHandler;
- OPL->UpdateParam = param;
+ OPL->UpdateParam = device;
}
static int OPLWrite(FM_OPL *OPL,int a,int v)
@@ -2012,7 +2020,7 @@ static int OPLWrite(FM_OPL *OPL,int a,int v)
else
{ /* data port */
if(OPL->UpdateHandler) OPL->UpdateHandler(OPL->UpdateParam,0);
- OPLWriteReg(OPL,OPL->address,v);
+ OPL->WriteReg(OPL->address,v);
}
return OPL->status>>7;
}
@@ -2055,7 +2063,7 @@ static unsigned char OPLRead(FM_OPL *OPL,int a)
{
uint8_t val;
- val = YM_DELTAT_ADPCM_Read(OPL->deltat);
+ val = OPL->deltat->ADPCM_Read();
/*logerror("Y8950: read ADPCM value read=%02x\n",val);*/
return val;
}
@@ -2086,13 +2094,13 @@ static unsigned char OPLRead(FM_OPL *OPL,int a)
/* CSM Key Controll */
static inline void CSMKeyControll(OPL_CH *CH)
{
- FM_KEYON (&CH->SLOT[SLOT1], 4);
- FM_KEYON (&CH->SLOT[SLOT2], 4);
+ CH->SLOT[SLOT1].KEYON(4);
+ CH->SLOT[SLOT2].KEYON(4);
/* The key off should happen exactly one sample later - not implemented correctly yet */
- FM_KEYOFF(&CH->SLOT[SLOT1], ~4);
- FM_KEYOFF(&CH->SLOT[SLOT2], ~4);
+ CH->SLOT[SLOT1].KEYOFF(~4);
+ CH->SLOT[SLOT2].KEYOFF(~4);
}
@@ -2100,11 +2108,11 @@ static int OPLTimerOver(FM_OPL *OPL,int c)
{
if( c )
{ /* Timer B */
- OPL_STATUS_SET(OPL,0x20);
+ OPL->STATUS_SET(0x20);
}
else
{ /* Timer A */
- OPL_STATUS_SET(OPL,0x40);
+ OPL->STATUS_SET(0x40);
/* CSM mode key,TL controll */
if( OPL->mode & 0x80 )
{ /* CSM mode total level latch and auto key on */
@@ -2152,7 +2160,7 @@ void ym3812_shutdown(void *chip)
void ym3812_reset_chip(void *chip)
{
FM_OPL *YM3812 = (FM_OPL *)chip;
- OPLResetChip(YM3812);
+ YM3812->ResetChip();
}
int ym3812_write(void *chip, int a, int v)
@@ -2173,20 +2181,20 @@ int ym3812_timer_over(void *chip, int c)
return OPLTimerOver(YM3812, c);
}
-void ym3812_set_timer_handler(void *chip, OPL_TIMERHANDLER timer_handler, void *param)
+void ym3812_set_timer_handler(void *chip, OPL_TIMERHANDLER timer_handler, device_t *device)
{
FM_OPL *YM3812 = (FM_OPL *)chip;
- OPLSetTimerHandler(YM3812, timer_handler, param);
+ OPLSetTimerHandler(YM3812, timer_handler, device);
}
-void ym3812_set_irq_handler(void *chip,OPL_IRQHANDLER IRQHandler,void *param)
+void ym3812_set_irq_handler(void *chip,OPL_IRQHANDLER IRQHandler,device_t *device)
{
FM_OPL *YM3812 = (FM_OPL *)chip;
- OPLSetIRQHandler(YM3812, IRQHandler, param);
+ OPLSetIRQHandler(YM3812, IRQHandler, device);
}
-void ym3812_set_update_handler(void *chip,OPL_UPDATEHANDLER UpdateHandler,void *param)
+void ym3812_set_update_handler(void *chip,OPL_UPDATEHANDLER UpdateHandler,device_t *device)
{
FM_OPL *YM3812 = (FM_OPL *)chip;
- OPLSetUpdateHandler(YM3812, UpdateHandler, param);
+ OPLSetUpdateHandler(YM3812, UpdateHandler, device);
}
@@ -2210,25 +2218,25 @@ void ym3812_update_one(void *chip, OPLSAMPLE *buffer, int length)
OPL->output[0] = 0;
- advance_lfo(OPL);
+ OPL->advance_lfo();
/* FM part */
- OPL_CALC_CH(OPL, &OPL->P_CH[0]);
- OPL_CALC_CH(OPL, &OPL->P_CH[1]);
- OPL_CALC_CH(OPL, &OPL->P_CH[2]);
- OPL_CALC_CH(OPL, &OPL->P_CH[3]);
- OPL_CALC_CH(OPL, &OPL->P_CH[4]);
- OPL_CALC_CH(OPL, &OPL->P_CH[5]);
+ OPL->CALC_CH(OPL->P_CH[0]);
+ OPL->CALC_CH(OPL->P_CH[1]);
+ OPL->CALC_CH(OPL->P_CH[2]);
+ OPL->CALC_CH(OPL->P_CH[3]);
+ OPL->CALC_CH(OPL->P_CH[4]);
+ OPL->CALC_CH(OPL->P_CH[5]);
if(!rhythm)
{
- OPL_CALC_CH(OPL, &OPL->P_CH[6]);
- OPL_CALC_CH(OPL, &OPL->P_CH[7]);
- OPL_CALC_CH(OPL, &OPL->P_CH[8]);
+ OPL->CALC_CH(OPL->P_CH[6]);
+ OPL->CALC_CH(OPL->P_CH[7]);
+ OPL->CALC_CH(OPL->P_CH[8]);
}
else /* Rhythm part */
{
- OPL_CALC_RH(OPL, &OPL->P_CH[0], (OPL->noise_rng>>0)&1 );
+ OPL->CALC_RH();
}
lt = OPL->output[0];
@@ -2248,7 +2256,7 @@ void ym3812_update_one(void *chip, OPLSAMPLE *buffer, int length)
/* store to sound buffer */
buf[i] = lt;
- advance(OPL);
+ OPL->advance();
}
}
@@ -2284,7 +2292,7 @@ void ym3526_shutdown(void *chip)
void ym3526_reset_chip(void *chip)
{
FM_OPL *YM3526 = (FM_OPL *)chip;
- OPLResetChip(YM3526);
+ YM3526->ResetChip();
}
int ym3526_write(void *chip, int a, int v)
@@ -2305,20 +2313,20 @@ int ym3526_timer_over(void *chip, int c)
return OPLTimerOver(YM3526, c);
}
-void ym3526_set_timer_handler(void *chip, OPL_TIMERHANDLER timer_handler, void *param)
+void ym3526_set_timer_handler(void *chip, OPL_TIMERHANDLER timer_handler, device_t *device)
{
FM_OPL *YM3526 = (FM_OPL *)chip;
- OPLSetTimerHandler(YM3526, timer_handler, param);
+ OPLSetTimerHandler(YM3526, timer_handler, device);
}
-void ym3526_set_irq_handler(void *chip,OPL_IRQHANDLER IRQHandler,void *param)
+void ym3526_set_irq_handler(void *chip,OPL_IRQHANDLER IRQHandler,device_t *device)
{
FM_OPL *YM3526 = (FM_OPL *)chip;
- OPLSetIRQHandler(YM3526, IRQHandler, param);
+ OPLSetIRQHandler(YM3526, IRQHandler, device);
}
-void ym3526_set_update_handler(void *chip,OPL_UPDATEHANDLER UpdateHandler,void *param)
+void ym3526_set_update_handler(void *chip,OPL_UPDATEHANDLER UpdateHandler,device_t *device)
{
FM_OPL *YM3526 = (FM_OPL *)chip;
- OPLSetUpdateHandler(YM3526, UpdateHandler, param);
+ OPLSetUpdateHandler(YM3526, UpdateHandler, device);
}
@@ -2342,25 +2350,25 @@ void ym3526_update_one(void *chip, OPLSAMPLE *buffer, int length)
OPL->output[0] = 0;
- advance_lfo(OPL);
+ OPL->advance_lfo();
/* FM part */
- OPL_CALC_CH(OPL, &OPL->P_CH[0]);
- OPL_CALC_CH(OPL, &OPL->P_CH[1]);
- OPL_CALC_CH(OPL, &OPL->P_CH[2]);
- OPL_CALC_CH(OPL, &OPL->P_CH[3]);
- OPL_CALC_CH(OPL, &OPL->P_CH[4]);
- OPL_CALC_CH(OPL, &OPL->P_CH[5]);
+ OPL->CALC_CH(OPL->P_CH[0]);
+ OPL->CALC_CH(OPL->P_CH[1]);
+ OPL->CALC_CH(OPL->P_CH[2]);
+ OPL->CALC_CH(OPL->P_CH[3]);
+ OPL->CALC_CH(OPL->P_CH[4]);
+ OPL->CALC_CH(OPL->P_CH[5]);
if(!rhythm)
{
- OPL_CALC_CH(OPL, &OPL->P_CH[6]);
- OPL_CALC_CH(OPL, &OPL->P_CH[7]);
- OPL_CALC_CH(OPL, &OPL->P_CH[8]);
+ OPL->CALC_CH(OPL->P_CH[6]);
+ OPL->CALC_CH(OPL->P_CH[7]);
+ OPL->CALC_CH(OPL->P_CH[8]);
}
else /* Rhythm part */
{
- OPL_CALC_RH(OPL, &OPL->P_CH[0], (OPL->noise_rng>>0)&1 );
+ OPL->CALC_RH();
}
lt = OPL->output[0];
@@ -2380,7 +2388,7 @@ void ym3526_update_one(void *chip, OPLSAMPLE *buffer, int length)
/* store to sound buffer */
buf[i] = lt;
- advance(OPL);
+ OPL->advance();
}
}
@@ -2394,12 +2402,12 @@ void ym3526_update_one(void *chip, OPLSAMPLE *buffer, int length)
static void Y8950_deltat_status_set(void *chip, uint8_t changebits)
{
FM_OPL *Y8950 = (FM_OPL *)chip;
- OPL_STATUS_SET(Y8950, changebits);
+ Y8950->STATUS_SET(changebits);
}
static void Y8950_deltat_status_reset(void *chip, uint8_t changebits)
{
FM_OPL *Y8950 = (FM_OPL *)chip;
- OPL_STATUS_RESET(Y8950, changebits);
+ Y8950->STATUS_RESET(changebits);
}
void *y8950_init(device_t *device, uint32_t clock, uint32_t rate)
@@ -2433,7 +2441,7 @@ void y8950_shutdown(void *chip)
void y8950_reset_chip(void *chip)
{
FM_OPL *Y8950 = (FM_OPL *)chip;
- OPLResetChip(Y8950);
+ Y8950->ResetChip();
}
int y8950_write(void *chip, int a, int v)
@@ -2453,20 +2461,20 @@ int y8950_timer_over(void *chip, int c)
return OPLTimerOver(Y8950, c);
}
-void y8950_set_timer_handler(void *chip, OPL_TIMERHANDLER timer_handler, void *param)
+void y8950_set_timer_handler(void *chip, OPL_TIMERHANDLER timer_handler, device_t *device)
{
FM_OPL *Y8950 = (FM_OPL *)chip;
- OPLSetTimerHandler(Y8950, timer_handler, param);
+ OPLSetTimerHandler(Y8950, timer_handler, device);
}
-void y8950_set_irq_handler(void *chip,OPL_IRQHANDLER IRQHandler,void *param)
+void y8950_set_irq_handler(void *chip,OPL_IRQHANDLER IRQHandler,device_t *device)
{
FM_OPL *Y8950 = (FM_OPL *)chip;
- OPLSetIRQHandler(Y8950, IRQHandler, param);
+ OPLSetIRQHandler(Y8950, IRQHandler, device);
}
-void y8950_set_update_handler(void *chip,OPL_UPDATEHANDLER UpdateHandler,void *param)
+void y8950_set_update_handler(void *chip,OPL_UPDATEHANDLER UpdateHandler,device_t *device)
{
FM_OPL *Y8950 = (FM_OPL *)chip;
- OPLSetUpdateHandler(Y8950, UpdateHandler, param);
+ OPLSetUpdateHandler(Y8950, UpdateHandler, device);
}
void y8950_set_delta_t_memory(void *chip, void * deltat_mem_ptr, int deltat_mem_size )
@@ -2498,29 +2506,29 @@ void y8950_update_one(void *chip, OPLSAMPLE *buffer, int length)
OPL->output[0] = 0;
OPL->output_deltat[0] = 0;
- advance_lfo(OPL);
+ OPL->advance_lfo();
/* deltaT ADPCM */
if( DELTAT->portstate&0x80 )
- YM_DELTAT_ADPCM_CALC(DELTAT);
+ DELTAT->ADPCM_CALC();
/* FM part */
- OPL_CALC_CH(OPL, &OPL->P_CH[0]);
- OPL_CALC_CH(OPL, &OPL->P_CH[1]);
- OPL_CALC_CH(OPL, &OPL->P_CH[2]);
- OPL_CALC_CH(OPL, &OPL->P_CH[3]);
- OPL_CALC_CH(OPL, &OPL->P_CH[4]);
- OPL_CALC_CH(OPL, &OPL->P_CH[5]);
+ OPL->CALC_CH(OPL->P_CH[0]);
+ OPL->CALC_CH(OPL->P_CH[1]);
+ OPL->CALC_CH(OPL->P_CH[2]);
+ OPL->CALC_CH(OPL->P_CH[3]);
+ OPL->CALC_CH(OPL->P_CH[4]);
+ OPL->CALC_CH(OPL->P_CH[5]);
if(!rhythm)
{
- OPL_CALC_CH(OPL, &OPL->P_CH[6]);
- OPL_CALC_CH(OPL, &OPL->P_CH[7]);
- OPL_CALC_CH(OPL, &OPL->P_CH[8]);
+ OPL->CALC_CH(OPL->P_CH[6]);
+ OPL->CALC_CH(OPL->P_CH[7]);
+ OPL->CALC_CH(OPL->P_CH[8]);
}
else /* Rhythm part */
{
- OPL_CALC_RH(OPL, &OPL->P_CH[0], (OPL->noise_rng>>0)&1 );
+ OPL->CALC_RH();
}
lt = OPL->output[0] + (OPL->output_deltat[0]>>11);
@@ -2540,25 +2548,25 @@ void y8950_update_one(void *chip, OPLSAMPLE *buffer, int length)
/* store to sound buffer */
buf[i] = lt;
- advance(OPL);
+ OPL->advance();
}
}
-void y8950_set_port_handler(void *chip,OPL_PORTHANDLER_W PortHandler_w,OPL_PORTHANDLER_R PortHandler_r,void * param)
+void y8950_set_port_handler(void *chip,OPL_PORTHANDLER_W PortHandler_w,OPL_PORTHANDLER_R PortHandler_r,device_t *device)
{
FM_OPL *OPL = (FM_OPL *)chip;
OPL->porthandler_w = PortHandler_w;
OPL->porthandler_r = PortHandler_r;
- OPL->port_param = param;
+ OPL->port_param = device;
}
-void y8950_set_keyboard_handler(void *chip,OPL_PORTHANDLER_W KeyboardHandler_w,OPL_PORTHANDLER_R KeyboardHandler_r,void * param)
+void y8950_set_keyboard_handler(void *chip,OPL_PORTHANDLER_W KeyboardHandler_w,OPL_PORTHANDLER_R KeyboardHandler_r,device_t *device)
{
FM_OPL *OPL = (FM_OPL *)chip;
OPL->keyboardhandler_w = KeyboardHandler_w;
OPL->keyboardhandler_r = KeyboardHandler_r;
- OPL->keyboard_param = param;
+ OPL->keyboard_param = device;
}
#endif