From 47f83c047217e4e6ac40eca65c6bfb627be5edd5 Mon Sep 17 00:00:00 2001 From: tildearrow Date: Sun, 1 May 2022 03:47:04 -0500 Subject: [PATCH] per-channel oscilloscope, part 7 YM2610 and YM2610B only TIA is left --- src/engine/platform/sound/ymfm/ymfm_adpcm.h | 4 ++ src/engine/platform/sound/ymfm/ymfm_opn.h | 6 +++ src/engine/platform/sound/ymfm/ymfm_ssg.cpp | 2 + src/engine/platform/sound/ymfm/ymfm_ssg.h | 4 ++ src/engine/platform/ym2610.cpp | 43 +++++++++++++++++++++ src/engine/platform/ym2610.h | 2 + src/engine/platform/ym2610b.cpp | 38 ++++++++++++++++++ src/engine/platform/ym2610b.h | 2 + src/engine/platform/ym2610bext.cpp | 7 +++- src/engine/platform/ym2610bext.h | 1 + src/engine/platform/ym2610ext.cpp | 6 +++ src/engine/platform/ym2610ext.h | 1 + 12 files changed, 115 insertions(+), 1 deletion(-) diff --git a/src/engine/platform/sound/ymfm/ymfm_adpcm.h b/src/engine/platform/sound/ymfm/ymfm_adpcm.h index 4b4af0fdd..b2732cb1e 100644 --- a/src/engine/platform/sound/ymfm/ymfm_adpcm.h +++ b/src/engine/platform/sound/ymfm/ymfm_adpcm.h @@ -203,11 +203,15 @@ public: // return a reference to our registers adpcm_a_registers ®s() { return m_regs; } + // debug functions + adpcm_a_channel* debug_channel(uint32_t index) const { return m_channel[index].get(); } + private: // internal state ymfm_interface &m_intf; // reference to the interface std::unique_ptr m_channel[CHANNELS]; // array of channels adpcm_a_registers m_regs; // registers + int32_t m_last_out[CHANNELS]; // last output of channels }; diff --git a/src/engine/platform/sound/ymfm/ymfm_opn.h b/src/engine/platform/sound/ymfm/ymfm_opn.h index 1a2f55805..1b47885b9 100644 --- a/src/engine/platform/sound/ymfm/ymfm_opn.h +++ b/src/engine/platform/sound/ymfm/ymfm_opn.h @@ -697,6 +697,12 @@ public: // generate one sample of sound void generate(output_data *output, uint32_t numsamples = 1); + // get the engine + fm_engine* debug_fm_engine() { return &m_fm; } + ssg_engine* debug_ssg_engine() { return &m_ssg; } + adpcm_a_engine* debug_adpcm_a_engine() { return &m_adpcm_a; } + adpcm_b_engine* debug_adpcm_b_engine() { return &m_adpcm_b; } + protected: // internal helpers void update_prescale(); diff --git a/src/engine/platform/sound/ymfm/ymfm_ssg.cpp b/src/engine/platform/sound/ymfm/ymfm_ssg.cpp index 3335d47c7..5a9a9d43e 100644 --- a/src/engine/platform/sound/ymfm/ymfm_ssg.cpp +++ b/src/engine/platform/sound/ymfm/ymfm_ssg.cpp @@ -232,6 +232,8 @@ void ssg_engine::output(output_data &output) // convert to amplitude output.data[chan] = s_amplitudes[volume]; } + + m_last_out=output; } diff --git a/src/engine/platform/sound/ymfm/ymfm_ssg.h b/src/engine/platform/sound/ymfm/ymfm_ssg.h index 9f31c92f5..55e748d6b 100644 --- a/src/engine/platform/sound/ymfm/ymfm_ssg.h +++ b/src/engine/platform/sound/ymfm/ymfm_ssg.h @@ -187,6 +187,9 @@ public: // indicate the prescale has changed void prescale_changed() { if (m_override != nullptr) m_override->ssg_prescale_changed(); } + // get the last output + void get_last_out(output_data& out) { out=m_last_out; } + private: // internal state ymfm_interface &m_intf; // reference to the interface @@ -198,6 +201,7 @@ private: uint32_t m_noise_state; // current noise state ssg_registers m_regs; // registers ssg_override *m_override; // override interface + output_data m_last_out; }; } diff --git a/src/engine/platform/ym2610.cpp b/src/engine/platform/ym2610.cpp index c4ae0ad80..1e5d1f2ab 100644 --- a/src/engine/platform/ym2610.cpp +++ b/src/engine/platform/ym2610.cpp @@ -30,6 +30,10 @@ static unsigned char konOffs[4]={ 1, 2, 5, 6 }; +static unsigned char bchOffs[4]={ + 1, 2, 4, 5 +}; + #define CHIP_DIVIDER 32 const char* regCheatSheetYM2610[]={ @@ -337,6 +341,14 @@ double DivPlatformYM2610::NOTE_ADPCMB(int note) { void DivPlatformYM2610::acquire(short* bufL, short* bufR, size_t start, size_t len) { static int os[2]; + ymfm::ym2612::fm_engine* fme=fm->debug_fm_engine(); + ymfm::ssg_engine* ssge=fm->debug_ssg_engine(); + ymfm::adpcm_a_engine* aae=fm->debug_adpcm_a_engine(); + ymfm::adpcm_b_engine* abe=fm->debug_adpcm_b_engine(); + + ymfm::ssg_engine::output_data ssgOut; + ymfm::ymfm_output<2> adpcmOut; + for (size_t h=start; hdata[oscBuf[i]->needle++]=(fme->debug_channel(ch)->debug_output(0)+fme->debug_channel(ch)->debug_output(1)); + } + + ssge->get_last_out(ssgOut); + for (int i=4; i<7; i++) { + oscBuf[i]->data[oscBuf[i]->needle++]=ssgOut.data[i-4]; + } + + for (int i=7; i<13; i++) { + adpcmOut.clear(); + aae->debug_channel(i-7)->output(adpcmOut); + oscBuf[i]->data[oscBuf[i]->needle++]=adpcmOut.data[0]+adpcmOut.data[1]; + } + + adpcmOut.clear(); + abe->output(adpcmOut,1); + oscBuf[13]->data[oscBuf[13]->needle++]=adpcmOut.data[0]+adpcmOut.data[1]; } } @@ -1058,6 +1090,10 @@ void* DivPlatformYM2610::getChanState(int ch) { return &chan[ch]; } +DivDispatchOscBuffer* DivPlatformYM2610::getOscBuffer(int ch) { + return oscBuf[ch]; +} + unsigned char* DivPlatformYM2610::getRegisterPool() { return regPool; } @@ -1153,9 +1189,13 @@ int DivPlatformYM2610::init(DivEngine* p, int channels, int sugRate, unsigned in skipRegisterWrites=false; for (int i=0; i<14; i++) { isMuted[i]=false; + oscBuf[i]=new DivDispatchOscBuffer; } chipClock=8000000; rate=chipClock/16; + for (int i=0; i<14; i++) { + oscBuf[i]->rate=rate; + } iface.parent=parent; iface.sampleBank=0; fm=new ymfm::ym2610(iface); @@ -1168,6 +1208,9 @@ int DivPlatformYM2610::init(DivEngine* p, int channels, int sugRate, unsigned in } void DivPlatformYM2610::quit() { + for (int i=0; i<14; i++) { + delete oscBuf[i]; + } ay->quit(); delete ay; delete fm; diff --git a/src/engine/platform/ym2610.h b/src/engine/platform/ym2610.h index 56f6824d0..c46bc3c43 100644 --- a/src/engine/platform/ym2610.h +++ b/src/engine/platform/ym2610.h @@ -82,6 +82,7 @@ class DivPlatformYM2610: public DivDispatch { pan(3) {} }; Channel chan[14]; + DivDispatchOscBuffer* oscBuf[14]; bool isMuted[14]; struct QueuedWrite { unsigned short addr; @@ -117,6 +118,7 @@ class DivPlatformYM2610: public DivDispatch { void acquire(short* bufL, short* bufR, size_t start, size_t len); int dispatch(DivCommand c); void* getChanState(int chan); + DivDispatchOscBuffer* getOscBuffer(int chan); unsigned char* getRegisterPool(); int getRegisterPoolSize(); void reset(); diff --git a/src/engine/platform/ym2610b.cpp b/src/engine/platform/ym2610b.cpp index 12e32ef8c..65b8d723d 100644 --- a/src/engine/platform/ym2610b.cpp +++ b/src/engine/platform/ym2610b.cpp @@ -401,6 +401,14 @@ double DivPlatformYM2610B::NOTE_ADPCMB(int note) { void DivPlatformYM2610B::acquire(short* bufL, short* bufR, size_t start, size_t len) { static int os[2]; + ymfm::ym2612::fm_engine* fme=fm->debug_fm_engine(); + ymfm::ssg_engine* ssge=fm->debug_ssg_engine(); + ymfm::adpcm_a_engine* aae=fm->debug_adpcm_a_engine(); + ymfm::adpcm_b_engine* abe=fm->debug_adpcm_b_engine(); + + ymfm::ssg_engine::output_data ssgOut; + ymfm::ymfm_output<2> adpcmOut; + for (size_t h=start; hdata[oscBuf[i]->needle++]=(fme->debug_channel(i)->debug_output(0)+fme->debug_channel(i)->debug_output(1)); + } + + ssge->get_last_out(ssgOut); + for (int i=6; i<9; i++) { + oscBuf[i]->data[oscBuf[i]->needle++]=ssgOut.data[i-6]; + } + + for (int i=9; i<15; i++) { + adpcmOut.clear(); + aae->debug_channel(i-9)->output(adpcmOut); + oscBuf[i]->data[oscBuf[i]->needle++]=adpcmOut.data[0]+adpcmOut.data[1]; + } + + adpcmOut.clear(); + abe->output(adpcmOut,1); + oscBuf[15]->data[oscBuf[15]->needle++]=adpcmOut.data[0]+adpcmOut.data[1]; } } @@ -1121,6 +1148,10 @@ void* DivPlatformYM2610B::getChanState(int ch) { return &chan[ch]; } +DivDispatchOscBuffer* DivPlatformYM2610B::getOscBuffer(int ch) { + return oscBuf[ch]; +} + unsigned char* DivPlatformYM2610B::getRegisterPool() { return regPool; } @@ -1216,9 +1247,13 @@ int DivPlatformYM2610B::init(DivEngine* p, int channels, int sugRate, unsigned i skipRegisterWrites=false; for (int i=0; i<16; i++) { isMuted[i]=false; + oscBuf[i]=new DivDispatchOscBuffer; } chipClock=8000000; rate=chipClock/16; + for (int i=0; i<16; i++) { + oscBuf[i]->rate=rate; + } iface.parent=parent; iface.sampleBank=0; fm=new ymfm::ym2610b(iface); @@ -1231,6 +1266,9 @@ int DivPlatformYM2610B::init(DivEngine* p, int channels, int sugRate, unsigned i } void DivPlatformYM2610B::quit() { + for (int i=0; i<16; i++) { + delete oscBuf[i]; + } ay->quit(); delete ay; delete fm; diff --git a/src/engine/platform/ym2610b.h b/src/engine/platform/ym2610b.h index c01b9515a..df0a83233 100644 --- a/src/engine/platform/ym2610b.h +++ b/src/engine/platform/ym2610b.h @@ -74,6 +74,7 @@ class DivPlatformYM2610B: public DivDispatch { pan(3) {} }; Channel chan[16]; + DivDispatchOscBuffer* oscBuf[16]; bool isMuted[16]; struct QueuedWrite { unsigned short addr; @@ -108,6 +109,7 @@ class DivPlatformYM2610B: public DivDispatch { void acquire(short* bufL, short* bufR, size_t start, size_t len); int dispatch(DivCommand c); void* getChanState(int chan); + DivDispatchOscBuffer* getOscBuffer(int chan); unsigned char* getRegisterPool(); int getRegisterPoolSize(); void reset(); diff --git a/src/engine/platform/ym2610bext.cpp b/src/engine/platform/ym2610bext.cpp index 5eec24ece..87c635736 100644 --- a/src/engine/platform/ym2610bext.cpp +++ b/src/engine/platform/ym2610bext.cpp @@ -336,13 +336,18 @@ void DivPlatformYM2610BExt::forceIns() { } } - void* DivPlatformYM2610BExt::getChanState(int ch) { if (ch>=6) return &chan[ch-3]; if (ch>=2) return &opChan[ch-2]; return &chan[ch]; } +DivDispatchOscBuffer* DivPlatformYM2610BExt::getOscBuffer(int ch) { + if (ch>=6) return oscBuf[ch-3]; + if (ch<3) return oscBuf[ch]; + return NULL; +} + void DivPlatformYM2610BExt::reset() { DivPlatformYM2610B::reset(); diff --git a/src/engine/platform/ym2610bext.h b/src/engine/platform/ym2610bext.h index 5dd98c87e..b416b5c70 100644 --- a/src/engine/platform/ym2610bext.h +++ b/src/engine/platform/ym2610bext.h @@ -38,6 +38,7 @@ class DivPlatformYM2610BExt: public DivPlatformYM2610B { public: int dispatch(DivCommand c); void* getChanState(int chan); + DivDispatchOscBuffer* getOscBuffer(int chan); void reset(); void forceIns(); void tick(bool sysTick=true); diff --git a/src/engine/platform/ym2610ext.cpp b/src/engine/platform/ym2610ext.cpp index 6ae911061..013e7b954 100644 --- a/src/engine/platform/ym2610ext.cpp +++ b/src/engine/platform/ym2610ext.cpp @@ -343,6 +343,12 @@ void* DivPlatformYM2610Ext::getChanState(int ch) { return &chan[ch]; } +DivDispatchOscBuffer* DivPlatformYM2610Ext::getOscBuffer(int ch) { + if (ch>=5) return oscBuf[ch-3]; + if (ch<2) return oscBuf[ch]; + return NULL; +} + void DivPlatformYM2610Ext::reset() { DivPlatformYM2610::reset(); diff --git a/src/engine/platform/ym2610ext.h b/src/engine/platform/ym2610ext.h index 0ff45981e..10be6638d 100644 --- a/src/engine/platform/ym2610ext.h +++ b/src/engine/platform/ym2610ext.h @@ -38,6 +38,7 @@ class DivPlatformYM2610Ext: public DivPlatformYM2610 { public: int dispatch(DivCommand c); void* getChanState(int chan); + DivDispatchOscBuffer* getOscBuffer(int chan); void reset(); void forceIns(); void tick(bool sysTick=true);