// license:GPL-2.0+
// copyright-holders:Jarek Burczynski,Ernesto Corvi
/*
** File: ym2151.h - header file for software implementation of YM2151
** FM Operator Type-M(OPM)
**
** (c) 1997-2002 Jarek Burczynski (s0246@poczta.onet.pl, bujar@mame.net)
** Some of the optimizing ideas by Tatsuyuki Satoh
**
** Version 2.150 final beta May, 11th 2002
**
**
** I would like to thank following people for making this project possible:
**
** Beauty Planets - for making a lot of real YM2151 samples and providing
** additional informations about the chip. Also for the time spent making
** the samples and the speed of replying to my endless requests.
**
** Shigeharu Isoda - for general help, for taking time to scan his YM2151
** Japanese Manual first of all, and answering MANY of my questions.
**
** Nao - for giving me some info about YM2151 and pointing me to Shigeharu.
** Also for creating fmemu (which I still use to test the emulator).
**
** Aaron Giles and Chris Hardy - they made some samples of one of my favourite
** arcade games so I could compare it to my emulator.
**
** Bryan McPhail and Tim (powerjaw) - for making some samples.
**
** Ishmair - for the datasheet and motivation.
*/
#ifndef MAME_SOUND_YM2151_H
#define MAME_SOUND_YM2151_H
#pragma once
//**************************************************************************
// INTERFACE CONFIGURATION MACROS
//**************************************************************************
#define MCFG_YM2151_IRQ_HANDLER(_devcb) \
downcast<ym2151_device &>(*device).set_irq_handler(DEVCB_##_devcb);
#define MCFG_YM2151_PORT_WRITE_HANDLER(_devcb) \
downcast<ym2151_device &>(*device).set_port_write_handler(DEVCB_##_devcb);
//**************************************************************************
// TYPE DEFINITIONS
//**************************************************************************
// ======================> ym2151_device
class ym2151_device : public device_t,
public device_sound_interface
{
public:
// construction/destruction
ym2151_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
// configuration helpers
template <class Object> devcb_base &set_irq_handler(Object &&cb) { return m_irqhandler.set_callback(std::forward<Object>(cb)); }
template <class Object> devcb_base &set_port_write_handler(Object &&cb) { return m_portwritehandler.set_callback(std::forward<Object>(cb)); }
auto irq_handler() { return m_irqhandler.bind(); }
auto port_write_handler() { return m_portwritehandler.bind(); }
// read/write
DECLARE_READ8_MEMBER(read);
DECLARE_WRITE8_MEMBER(write);
DECLARE_READ8_MEMBER(status_r);
DECLARE_WRITE8_MEMBER(register_w);
DECLARE_WRITE8_MEMBER(data_w);
DECLARE_WRITE_LINE_MEMBER(reset_w);
protected:
// device-level overrides
virtual void device_start() override;
virtual void device_reset() override;
virtual void device_timer(emu_timer &timer, device_timer_id id, int param, void *ptr) override;
virtual void device_post_load() override;
virtual void device_clock_changed() override;
// sound stream update overrides
virtual void sound_stream_update(sound_stream &stream, stream_sample_t **inputs, stream_sample_t **outputs, int samples) override;
private:
enum {
TIMER_IRQ_A_OFF,
TIMER_IRQ_B_OFF,
TIMER_A,
TIMER_B
};
enum {
RATE_STEPS = 8,
TL_RES_LEN = 256, /* 8 bits addressing (real chip) */
/* TL_TAB_LEN is calculated as:
* 13 - sinus amplitude bits (Y axis)
* 2 - sinus sign bit (Y axis)
* TL_RES_LEN - sinus resolution (X axis)
*/
TL_TAB_LEN = 13*2*TL_RES_LEN,
SIN_BITS = 10,
SIN_LEN = 1 << SIN_BITS,
SIN_MASK = SIN_LEN - 1
};
int tl_tab[TL_TAB_LEN];
unsigned int sin_tab[SIN_LEN];
uint32_t d1l_tab[16];
static const uint8_t eg_inc[19*RATE_STEPS];
static const uint8_t eg_rate_select[32+64+32];
static const uint8_t eg_rate_shift[32+64+32];
static const uint32_t dt2_tab[4];
static const uint8_t dt1_tab[4*32];
static const uint16_t phaseinc_rom[768];
static const uint8_t lfo_noise_waveform[256];
/* struct describing a single operator */
struct YM2151Operator
{
uint32_t phase; /* accumulated operator phase */
uint32_t freq; /* operator frequency count */
int32_t dt1; /* current DT1 (detune 1 phase inc/decrement) value */
uint32_t mul; /* frequency count multiply */
uint32_t dt1_i; /* DT1 index * 32 */
uint32_t dt2; /* current DT2 (detune 2) value */
signed int *connect; /* operator output 'direction' */
/* only M1 (operator 0) is filled with this data: */
signed int *mem_connect; /* where to put the delayed sample (MEM) */
int32_t mem_value; /* delayed sample (MEM) value */
/* channel specific data; note: each operator number 0 contains channel specific data */
uint32_t fb_shift; /* feedback shift value for operators 0 in each channel */
int32_t fb_out_curr; /* operator feedback value (used only by operators 0) */
int32_t fb_out_prev; /* previous feedback value (used only by operators 0) */
uint32_t kc; /* channel KC (copied to all operators) */
uint32_t kc_i; /* just for speedup */
uint32_t pms; /* channel PMS */
uint32_t ams; /* channel AMS */
/* end of channel specific data */
uint32_t AMmask; /* LFO Amplitude Modulation enable mask */
uint32_t state; /* Envelope state: 4-attack(AR) 3-decay(D1R) 2-sustain(D2R) 1-release(RR) 0-off */
uint8_t eg_sh_ar; /* (attack state) */
uint8_t eg_sel_ar; /* (attack state) */
uint32_t tl; /* Total attenuation Level */
int32_t volume; /* current envelope attenuation level */
uint8_t eg_sh_d1r; /* (decay state) */
uint8_t eg_sel_d1r; /* (decay state) */
uint32_t d1l; /* envelope switches to sustain state after reaching this level */
uint8_t eg_sh_d2r; /* (sustain state) */
uint8_t eg_sel_d2r; /* (sustain state) */
uint8_t eg_sh_rr; /* (release state) */
uint8_t eg_sel_rr; /* (release state) */
uint32_t key; /* 0=last key was KEY OFF, 1=last key was KEY ON */
uint32_t ks; /* key scale */
uint32_t ar; /* attack rate */
uint32_t d1r; /* decay rate */
uint32_t d2r; /* sustain rate */
uint32_t rr; /* release rate */
uint32_t reserved0; /**/
uint32_t reserved1; /**/
void key_on(uint32_t key_set, uint32_t eg_cnt);
void key_off(uint32_t key_set);
};
signed int chanout[8];
signed int m2,c1,c2; /* Phase Modulation input for operators 2,3,4 */
signed int mem; /* one sample delay memory */
YM2151Operator oper[32]; /* the 32 operators */
uint32_t pan[16]; /* channels output masks (0xffffffff = enable) */
uint32_t eg_cnt; /* global envelope generator counter */
uint32_t eg_timer; /* global envelope generator counter works at frequency = chipclock/64/3 */
uint32_t eg_timer_add; /* step of eg_timer */
uint32_t eg_timer_overflow; /* envelope generator timer overflows every 3 samples (on real chip) */
uint32_t lfo_phase; /* accumulated LFO phase (0 to 255) */
uint32_t lfo_timer; /* LFO timer */
uint32_t lfo_timer_add; /* step of lfo_timer */
uint32_t lfo_overflow; /* LFO generates new output when lfo_timer reaches this value */
uint32_t lfo_counter; /* LFO phase increment counter */
uint32_t lfo_counter_add; /* step of lfo_counter */
uint8_t lfo_wsel; /* LFO waveform (0-saw, 1-square, 2-triangle, 3-random noise) */
uint8_t amd; /* LFO Amplitude Modulation Depth */
int8_t pmd; /* LFO Phase Modulation Depth */
uint32_t lfa; /* LFO current AM output */
int32_t lfp; /* LFO current PM output */
uint8_t test; /* TEST register */
uint8_t ct; /* output control pins (bit1-CT2, bit0-CT1) */
uint32_t noise; /* noise enable/period register (bit 7 - noise enable, bits 4-0 - noise period */
uint32_t noise_rng; /* 17 bit noise shift register */
uint32_t noise_p; /* current noise 'phase'*/
uint32_t noise_f; /* current noise period */
uint32_t csm_req; /* CSM KEY ON / KEY OFF sequence request */
uint32_t irq_enable; /* IRQ enable for timer B (bit 3) and timer A (bit 2); bit 7 - CSM mode (keyon to all slots, everytime timer A overflows) */
uint32_t status; /* chip status (BUSY, IRQ Flags) */
uint8_t connect[8]; /* channels connections */
emu_timer *timer_A, *timer_A_irq_off;
emu_timer *timer_B, *timer_B_irq_off;
attotime timer_A_time[1024]; /* timer A times for MAME */
attotime timer_B_time[256]; /* timer B times for MAME */
int irqlinestate;
uint32_t timer_A_index; /* timer A index */
uint32_t timer_B_index; /* timer B index */
uint32_t timer_A_index_old; /* timer A previous index */
uint32_t timer_B_index_old; /* timer B previous index */
/* Frequency-deltas to get the closest frequency possible.
* There are 11 octaves because of DT2 (max 950 cents over base frequency)
* and LFO phase modulation (max 800 cents below AND over base frequency)
* Summary: octave explanation
* 0 note code - LFO PM
* 1 note code
* 2 note code
* 3 note code
* 4 note code
* 5 note code
* 6 note code
* 7 note code
* 8 note code
* 9 note code + DT2 + LFO PM
* 10 note code + DT2 + LFO PM
*/
uint32_t freq[11*768]; /* 11 octaves, 768 'cents' per octave */
/* Frequency deltas for DT1. These deltas alter operator frequency
* after it has been taken from frequency-deltas table.
*/
int32_t dt1_freq[8*32]; /* 8 DT1 levels, 32 KC values */
uint32_t noise_tab[32]; /* 17bit Noise Generator periods */
// internal state
sound_stream * m_stream;
uint8_t m_lastreg;
devcb_write_line m_irqhandler;
devcb_write8 m_portwritehandler;
bool m_reset_active;
void init_tables();
void calculate_timers();
void envelope_KONKOFF(YM2151Operator * op, int v);
void set_connect(YM2151Operator *om1, int cha, int v);
void advance();
void advance_eg();
void write_reg(int r, int v);
void chan_calc(unsigned int chan);
void chan7_calc();
int op_calc(YM2151Operator * OP, unsigned int env, signed int pm);
int op_calc1(YM2151Operator * OP, unsigned int env, signed int pm);
void refresh_EG(YM2151Operator * op);
};
// device type definition
DECLARE_DEVICE_TYPE(YM2151, ym2151_device)
#endif // MAME_SOUND_YM2151_H