/* License: Zlib see https://gitlab.com/cam900/vgsound_emu/-/blob/main/LICENSE for more details Copyright holder(s): cam900 Ensoniq ES5504 emulation core */ #ifndef _VGSOUND_EMU_SRC_ES5504_HPP #define _VGSOUND_EMU_SRC_ES5504_HPP #pragma once #include "es550x.hpp" // ES5504 specific class es5504_core : public es550x_shared_core { private: // es5504 voice classes class voice_t : public es550x_voice_t { public: // constructor voice_t(es5504_core &host) : es550x_voice_t("es5504_voice", 20, 9, false) , m_host(host) , m_volume(0) , m_out(0) { } // internal state virtual void reset() override; virtual void fetch(u8 cycle) override; virtual void tick(u8 voice) override; // setters inline void set_volume(u16 volume) { m_volume = volume; } // getters inline u16 volume() { return m_volume; } inline s32 out() { return m_out; } private: void adc_exec(); // registers es5504_core &m_host; u16 m_volume = 0; // 12 bit Volume s32 m_out = 0; // channel outputs }; public: // constructor es5504_core(es550x_intf &intf) : es550x_shared_core("es5504", 25, intf) , m_voice{*this, *this, *this, *this, *this, *this, *this, *this, *this, *this, *this, *this, *this, *this, *this, *this, *this, *this, *this, *this, *this, *this, *this, *this, *this} , m_adc(0) { m_out.fill(0); } // host interface u16 host_r(u8 address); void host_w(u8 address, u16 data); // internal state virtual void reset() override; virtual void tick() override; // less cycle accurate, but also less cpu heavy update routine void tick_perf(); // 16 analog output channels inline s32 out(u8 ch) { return m_out[ch & 0xf]; } //----------------------------------------------------------------- // // for preview/debug purpose only, not for serious emulators // //----------------------------------------------------------------- // bypass chips host interface for debug purpose only u16 read(u8 address, bool cpu_access = false); void write(u8 address, u16 data, bool cpu_access = false); u16 regs_r(u8 page, u8 address, bool cpu_access = false); void regs_w(u8 page, u8 address, u16 data, bool cpu_access = false); u16 regs_r(u8 page, u8 address) { u8 prev = m_page; m_page = page; u16 ret = read(address, false); m_page = prev; return ret; } // per-voice outputs inline s32 voice_out(u8 voice) { return (voice < 25) ? m_voice[voice].out() : 0; } protected: virtual inline u8 max_voices() override { return 25; } virtual void voice_tick() override; private: std::array m_voice; // 25 voices u16 m_adc = 0; // ADC register std::array m_out; // 16 channel outputs }; #endif