// license:BSD-3-Clause // copyright-holders:Olivier Galibert, R. Belmont, hap #pragma once #ifndef __YMF271_H__ #define __YMF271_H__ #define MCFG_YMF271_IRQ_HANDLER(_devcb) \ devcb = &ymf271_device::set_irq_handler(*device, DEVCB_##_devcb); #define MCFG_YMF271_EXT_READ_HANDLER(_devcb) \ devcb = &ymf271_device::set_ext_read_handler(*device, DEVCB_##_devcb); #define MCFG_YMF271_EXT_WRITE_HANDLER(_devcb) \ devcb = &ymf271_device::set_ext_write_handler(*device, DEVCB_##_devcb); class ymf271_device : public device_t, public device_sound_interface { public: ymf271_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock); // static configuration helpers template static devcb_base &set_irq_handler(device_t &device, _Object object) { return downcast(device).m_irq_handler.set_callback(object); } template static devcb_base &set_ext_read_handler(device_t &device, _Object object) { return downcast(device).m_ext_read_handler.set_callback(object); } template static devcb_base &set_ext_write_handler(device_t &device, _Object object) { return downcast(device).m_ext_write_handler.set_callback(object); } DECLARE_READ8_MEMBER( read ); DECLARE_WRITE8_MEMBER( write ); 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; // sound stream update overrides virtual void sound_stream_update(sound_stream &stream, stream_sample_t **inputs, stream_sample_t **outputs, int samples) override; private: struct YMF271Slot { uint8_t ext_en; uint8_t ext_out; uint8_t lfoFreq; uint8_t lfowave; uint8_t pms, ams; uint8_t detune; uint8_t multiple; uint8_t tl; uint8_t keyscale; uint8_t ar; uint8_t decay1rate, decay2rate; uint8_t decay1lvl; uint8_t relrate; uint8_t block; uint8_t fns_hi; uint32_t fns; uint8_t feedback; uint8_t waveform; uint8_t accon; uint8_t algorithm; uint8_t ch0_level, ch1_level, ch2_level, ch3_level; uint32_t startaddr; uint32_t loopaddr; uint32_t endaddr; uint8_t altloop; uint8_t fs; uint8_t srcnote, srcb; uint32_t step; uint64_t stepptr; uint8_t active; uint8_t bits; // envelope generator int32_t volume; int32_t env_state; int32_t env_attack_step; // volume increase step in attack state int32_t env_decay1_step; int32_t env_decay2_step; int32_t env_release_step; int64_t feedback_modulation0; int64_t feedback_modulation1; int lfo_phase, lfo_step; int lfo_amplitude; double lfo_phasemod; }; struct YMF271Group { uint8_t sync, pfm; }; void init_state(); void init_tables(); void calculate_step(YMF271Slot *slot); void update_envelope(YMF271Slot *slot); void init_envelope(YMF271Slot *slot); void init_lfo(YMF271Slot *slot); void update_lfo(YMF271Slot *slot); int64_t calculate_slot_volume(YMF271Slot *slot); void update_pcm(int slotnum, int32_t *mixp, int length); int64_t calculate_op(int slotnum, int64_t inp); void set_feedback(int slotnum, int64_t inp); void write_register(int slotnum, int reg, uint8_t data); void ymf271_write_fm(int bank, uint8_t address, uint8_t data); void ymf271_write_pcm(uint8_t address, uint8_t data); void ymf271_write_timer(uint8_t address, uint8_t data); uint8_t ymf271_read_memory(uint32_t offset); inline int get_keyscaled_rate(int rate, int keycode, int keyscale); inline int get_internal_keycode(int block, int fns); inline int get_external_keycode(int block, int fns); inline bool check_envelope_end(YMF271Slot *slot); // lookup tables std::unique_ptr m_lut_waves[8]; std::unique_ptr m_lut_plfo[4][8]; std::unique_ptr m_lut_alfo[4]; double m_lut_ar[64]; double m_lut_dc[64]; double m_lut_lfo[256]; int m_lut_attenuation[16]; int m_lut_total_level[128]; int m_lut_env_volume[256]; // internal state YMF271Slot m_slots[48]; YMF271Group m_groups[12]; uint8_t m_regs_main[0x10]; uint32_t m_timerA; uint32_t m_timerB; uint8_t m_irqstate; uint8_t m_status; uint8_t m_enable; uint32_t m_ext_address; uint8_t m_ext_rw; uint8_t m_ext_readlatch; optional_region_ptr m_mem_base; uint32_t m_mem_size; uint32_t m_clock; emu_timer *m_timA; emu_timer *m_timB; sound_stream *m_stream; std::unique_ptr m_mix_buffer; devcb_write_line m_irq_handler; devcb_read8 m_ext_read_handler; devcb_write8 m_ext_write_handler; }; extern const device_type YMF271; #endif /* __YMF271_H__ */