Merge branch 'master' of https://github.com/tildearrow/furnace into es5506_alt
* 'master' of https://github.com/tildearrow/furnace: YM2610: optimize oscilloscope fetch CPU usage GUI: add audio load meter to statistics GUI: put "OK" and "Cancel" buttons in the bottom better FM chip names sysDef refactor, part 3 - PLEASE READ NO Reduce unnecessary line Debug improvements AY8930: Fix VGM output. # Conflicts: # .gitignore # src/engine/playback.cpp # src/gui/debugWindow.cpp
This commit is contained in:
commit
4021abe495
18 changed files with 2519 additions and 1925 deletions
|
|
@ -25,7 +25,7 @@
|
|||
#include <math.h>
|
||||
|
||||
#define rWrite(a,v) if (!skipRegisterWrites) {pendingWrites[a]=v;}
|
||||
#define immWrite(a,v) if (!skipRegisterWrites) {writes.emplace(a,v); if (dumpWrites) {addWrite(a,v);} }
|
||||
#define immWrite2(a,v) if (!skipRegisterWrites) {writes.emplace(a,v); if (dumpWrites) {addWrite(a,v);} }
|
||||
|
||||
#define CHIP_DIVIDER 8
|
||||
|
||||
|
|
@ -61,6 +61,18 @@ const char* regCheatSheetAY8930[]={
|
|||
NULL
|
||||
};
|
||||
|
||||
void DivPlatformAY8930::immWrite(unsigned char a, unsigned char v) {
|
||||
if ((int)bank!=(a>>4)) {
|
||||
bank=a>>4;
|
||||
immWrite2(0x0d, 0xa0|(bank<<4)|ayEnvMode[0]);
|
||||
}
|
||||
if (a==0x0d) {
|
||||
immWrite2(0x0d,0xa0|(bank<<4)|(v&15));
|
||||
} else {
|
||||
immWrite2(a&15,v);
|
||||
}
|
||||
}
|
||||
|
||||
const char** DivPlatformAY8930::getRegisterSheet() {
|
||||
return regCheatSheetAY8930;
|
||||
}
|
||||
|
|
@ -123,18 +135,13 @@ void DivPlatformAY8930::acquire(short* bufL, short* bufR, size_t start, size_t l
|
|||
}
|
||||
while (!writes.empty()) {
|
||||
QueuedWrite w=writes.front();
|
||||
if ((int)bank!=(w.addr>>4)) {
|
||||
bank=w.addr>>4;
|
||||
ay->address_w(0x0d);
|
||||
ay->data_w(0xa0|(bank<<4)|ayEnvMode[0]);
|
||||
}
|
||||
ay->address_w(w.addr&15);
|
||||
if (w.addr==0x0d) {
|
||||
ay->data_w(0xa0|(bank<<4)|(w.val&15));
|
||||
ay->address_w(w.addr);
|
||||
ay->data_w(w.val);
|
||||
if (w.addr!=0x0d && (regPool[0x0d]&0xf0)==0xb0) {
|
||||
regPool[(w.addr&0x0f)|0x10]=w.val;
|
||||
} else {
|
||||
ay->data_w(w.val);
|
||||
regPool[w.addr&0x0f]=w.val;
|
||||
}
|
||||
regPool[w.addr&0x1f]=w.val;
|
||||
writes.pop();
|
||||
}
|
||||
ay->sound_stream_update(ayBuf,len);
|
||||
|
|
|
|||
|
|
@ -73,6 +73,7 @@ class DivPlatformAY8930: public DivDispatch {
|
|||
size_t ayBufLen;
|
||||
|
||||
void updateOutSel(bool immediate=false);
|
||||
void immWrite(unsigned char a, unsigned char v);
|
||||
|
||||
friend void putDispatchChan(void*,int,int);
|
||||
|
||||
|
|
|
|||
|
|
@ -269,7 +269,7 @@ void DivPlatformES5506::tick(bool sysTick) {
|
|||
signed int k1=chan[i].k1Prev,k2=chan[i].k2Prev;
|
||||
// volume/panning macros
|
||||
if (chan[i].std.vol.had) {
|
||||
const unsigned int nextVol=((chan[i].vol&0xff)*MIN(0xffff,chan[i].std.vol.val))/0xff;
|
||||
const unsigned int nextVol=((chan[i].vol&0xff)*MIN(0xffff,(0xffff*chan[i].std.vol.val)/chan[i].volMacroMax))/0xff;
|
||||
if (chan[i].outVol!=nextVol) {
|
||||
chan[i].outVol=nextVol;
|
||||
if (!isMuted[i]) {
|
||||
|
|
@ -278,7 +278,7 @@ void DivPlatformES5506::tick(bool sysTick) {
|
|||
}
|
||||
}
|
||||
if (chan[i].std.panL.had) {
|
||||
const unsigned int nextLVol=(((ins->es5506.lVol*(chan[i].lVol&0xff))/0xff)*MIN(0xffff,chan[i].std.panL.val))/0xffff;
|
||||
const unsigned int nextLVol=(((ins->es5506.lVol*(chan[i].lVol&0xff))/0xff)*MIN(0xffff,(0xffff*chan[i].std.panL.val)/chan[i].panMacroMax))/0xffff;
|
||||
if (chan[i].outLVol!=nextLVol) {
|
||||
chan[i].outLVol=nextLVol;
|
||||
if (!isMuted[i]) {
|
||||
|
|
@ -287,7 +287,7 @@ void DivPlatformES5506::tick(bool sysTick) {
|
|||
}
|
||||
}
|
||||
if (chan[i].std.panR.had) {
|
||||
const unsigned int nextRVol=(((ins->es5506.rVol*(chan[i].rVol&0xff))/0xff)*MIN(0xffff,chan[i].std.panR.val))/0xffff;
|
||||
const unsigned int nextRVol=(((ins->es5506.rVol*(chan[i].rVol&0xff))/0xff)*MIN(0xffff,(0xffff*chan[i].std.panR.val)/chan[i].panMacroMax))/0xffff;
|
||||
if (chan[i].outRVol!=nextRVol) {
|
||||
chan[i].outRVol=nextRVol;
|
||||
if (!isMuted[i]) {
|
||||
|
|
@ -644,11 +644,22 @@ int DivPlatformES5506::dispatch(DivCommand c) {
|
|||
chan[c.chan].pcm.length=length;
|
||||
chan[c.chan].pcm.loopStart=(start+(s->loopStart<<11))&0xfffff800;
|
||||
chan[c.chan].pcm.loopEnd=(start+((s->loopEnd-1)<<11))&0xffffff80;
|
||||
chan[c.chan].filter=ins->es5506.filter;
|
||||
chan[c.chan].envelope=ins->es5506.envelope;
|
||||
if (ins->type==DIV_INS_ES5506) { // Native format
|
||||
chan[c.chan].volMacroMax=0xffff;
|
||||
chan[c.chan].panMacroMax=0xffff;
|
||||
chan[c.chan].filter=ins->es5506.filter;
|
||||
chan[c.chan].envelope=ins->es5506.envelope;
|
||||
} else { // Amiga format
|
||||
chan[c.chan].volMacroMax=64;
|
||||
chan[c.chan].panMacroMax=127;
|
||||
chan[c.chan].filter=DivInstrumentES5506::Filter();
|
||||
chan[c.chan].envelope=DivInstrumentES5506::Envelope();
|
||||
}
|
||||
} else {
|
||||
chan[c.chan].sample=-1;
|
||||
chan[c.chan].pcm.index=-1;
|
||||
chan[c.chan].volMacroMax=0xffff;
|
||||
chan[c.chan].panMacroMax=0xffff;
|
||||
chan[c.chan].filter=DivInstrumentES5506::Filter();
|
||||
chan[c.chan].envelope=DivInstrumentES5506::Envelope();
|
||||
}
|
||||
|
|
|
|||
|
|
@ -56,6 +56,7 @@ class DivPlatformES5506: public DivDispatch, public es550x_intf {
|
|||
loopMode(DIV_SAMPLE_LOOPMODE_ONESHOT) {}
|
||||
} pcm;
|
||||
int freq, baseFreq, pitch, pitch2, note, ins, sample, wave;
|
||||
unsigned int volMacroMax, panMacroMax;
|
||||
bool active, insChanged, freqChanged, pcmChanged, keyOn, keyOff, inPorta, useWave, isReverseLoop;
|
||||
|
||||
struct VolChanged { // Volume changed flags
|
||||
|
|
@ -135,6 +136,8 @@ class DivPlatformES5506: public DivDispatch, public es550x_intf {
|
|||
ins(-1),
|
||||
sample(-1),
|
||||
wave(-1),
|
||||
volMacroMax(0xffff),
|
||||
panMacroMax(0xffff),
|
||||
active(false),
|
||||
insChanged(true),
|
||||
freqChanged(false),
|
||||
|
|
|
|||
|
|
@ -220,7 +220,7 @@ bool adpcm_a_channel::clock()
|
|||
//-------------------------------------------------
|
||||
|
||||
template<int NumOutputs>
|
||||
void adpcm_a_channel::output(ymfm_output<NumOutputs> &output) const
|
||||
void adpcm_a_channel::output(ymfm_output<NumOutputs> &output)
|
||||
{
|
||||
// volume combines instrument and total levels
|
||||
int vol = (m_regs.ch_instrument_level(m_choffs) ^ 0x1f) + (m_regs.total_level() ^ 0x3f);
|
||||
|
|
@ -239,14 +239,18 @@ void adpcm_a_channel::output(ymfm_output<NumOutputs> &output) const
|
|||
int16_t value = ((int16_t(m_accumulator << 4) * mul) >> shift) & ~3;
|
||||
|
||||
// apply to left/right as appropriate
|
||||
if (NumOutputs == 1 || m_regs.ch_pan_left(m_choffs))
|
||||
if (NumOutputs == 1 || m_regs.ch_pan_left(m_choffs)) {
|
||||
output.data[0] += value;
|
||||
if (NumOutputs > 1 && m_regs.ch_pan_right(m_choffs))
|
||||
m_lastOut[0] = value;
|
||||
}
|
||||
if (NumOutputs > 1 && m_regs.ch_pan_right(m_choffs)) {
|
||||
output.data[1] += value;
|
||||
m_lastOut[1] = value;
|
||||
}
|
||||
}
|
||||
|
||||
template void adpcm_a_channel::output<1>(ymfm_output<1> &output) const;
|
||||
template void adpcm_a_channel::output<2>(ymfm_output<2> &output) const;
|
||||
template void adpcm_a_channel::output<1>(ymfm_output<1> &output);
|
||||
template void adpcm_a_channel::output<2>(ymfm_output<2> &output);
|
||||
|
||||
|
||||
//*********************************************************
|
||||
|
|
@ -528,7 +532,7 @@ void adpcm_b_channel::clock()
|
|||
//-------------------------------------------------
|
||||
|
||||
template<int NumOutputs>
|
||||
void adpcm_b_channel::output(ymfm_output<NumOutputs> &output, uint32_t rshift) const
|
||||
void adpcm_b_channel::output(ymfm_output<NumOutputs> &output, uint32_t rshift)
|
||||
{
|
||||
// mask out some channels for debug purposes
|
||||
if ((debug::GLOBAL_ADPCM_B_CHANNEL_MASK & 1) == 0)
|
||||
|
|
@ -541,10 +545,14 @@ void adpcm_b_channel::output(ymfm_output<NumOutputs> &output, uint32_t rshift) c
|
|||
result = (result * int32_t(m_regs.level())) >> (8 + rshift);
|
||||
|
||||
// apply to left/right
|
||||
if (NumOutputs == 1 || m_regs.pan_left())
|
||||
if (NumOutputs == 1 || m_regs.pan_left()) {
|
||||
m_lastOut[0] = result;
|
||||
output.data[0] += result;
|
||||
if (NumOutputs > 1 && m_regs.pan_right())
|
||||
}
|
||||
if (NumOutputs > 1 && m_regs.pan_right()) {
|
||||
m_lastOut[1] = result;
|
||||
output.data[1] += result;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -146,7 +146,10 @@ public:
|
|||
|
||||
// return the computed output value, with panning applied
|
||||
template<int NumOutputs>
|
||||
void output(ymfm_output<NumOutputs> &output) const;
|
||||
void output(ymfm_output<NumOutputs> &output);
|
||||
|
||||
// return the last output
|
||||
int32_t get_last_out(int ch) { return m_lastOut[ch]; }
|
||||
|
||||
private:
|
||||
// internal state
|
||||
|
|
@ -158,6 +161,7 @@ private:
|
|||
uint32_t m_curaddress; // current address
|
||||
int32_t m_accumulator; // accumulator
|
||||
int32_t m_step_index; // index in the stepping table
|
||||
int32_t m_lastOut[2]; // last output
|
||||
adpcm_a_registers &m_regs; // reference to registers
|
||||
adpcm_a_engine &m_owner; // reference to our owner
|
||||
};
|
||||
|
|
@ -326,7 +330,7 @@ public:
|
|||
|
||||
// return the computed output value, with panning applied
|
||||
template<int NumOutputs>
|
||||
void output(ymfm_output<NumOutputs> &output, uint32_t rshift) const;
|
||||
void output(ymfm_output<NumOutputs> &output, uint32_t rshift);
|
||||
|
||||
// return the status register
|
||||
uint8_t status() const { return m_status; }
|
||||
|
|
@ -337,6 +341,9 @@ public:
|
|||
// handle special register writes
|
||||
void write(uint32_t regnum, uint8_t value);
|
||||
|
||||
// return the last output
|
||||
int32_t get_last_out(int ch) { return m_lastOut[ch]; }
|
||||
|
||||
private:
|
||||
// helper - return the current address shift
|
||||
uint32_t address_shift() const;
|
||||
|
|
@ -361,6 +368,7 @@ private:
|
|||
int32_t m_accumulator; // accumulator
|
||||
int32_t m_prev_accum; // previous accumulator (for linear interp)
|
||||
int32_t m_adpcm_step; // next forecast
|
||||
int32_t m_lastOut[2]; // last output
|
||||
adpcm_b_registers &m_regs; // reference to registers
|
||||
adpcm_b_engine &m_owner; // reference to our owner
|
||||
};
|
||||
|
|
@ -387,6 +395,9 @@ public:
|
|||
template<int NumOutputs>
|
||||
void output(ymfm_output<NumOutputs> &output, uint32_t rshift);
|
||||
|
||||
// get last output
|
||||
int32_t get_last_out(int ch) { return m_channel->get_last_out(ch); }
|
||||
|
||||
// read from the ADPCM-B registers
|
||||
uint32_t read(uint32_t regnum) { return m_channel->read(regnum); }
|
||||
|
||||
|
|
|
|||
|
|
@ -428,7 +428,15 @@ void DivPlatformYM2610::acquire(short* bufL, short* bufR, size_t start, size_t l
|
|||
ymfm::adpcm_b_engine* abe=fm->debug_adpcm_b_engine();
|
||||
|
||||
ymfm::ssg_engine::output_data ssgOut;
|
||||
ymfm::ymfm_output<2> adpcmOut;
|
||||
|
||||
ymfm::fm_channel<ymfm::opn_registers_base<true>>* fmChan[6];
|
||||
ymfm::adpcm_a_channel* adpcmAChan[6];
|
||||
for (int i=0; i<4; i++) {
|
||||
fmChan[i]=fme->debug_channel(bchOffs[i]);
|
||||
}
|
||||
for (int i=0; i<6; i++) {
|
||||
adpcmAChan[i]=aae->debug_channel(i);
|
||||
}
|
||||
|
||||
for (size_t h=start; h<start+len; h++) {
|
||||
os[0]=0; os[1]=0;
|
||||
|
|
@ -457,8 +465,7 @@ void DivPlatformYM2610::acquire(short* bufL, short* bufR, size_t start, size_t l
|
|||
bufR[h]=os[1];
|
||||
|
||||
for (int i=0; i<4; i++) {
|
||||
int ch=bchOffs[i];
|
||||
oscBuf[i]->data[oscBuf[i]->needle++]=(fme->debug_channel(ch)->debug_output(0)+fme->debug_channel(ch)->debug_output(1));
|
||||
oscBuf[i]->data[oscBuf[i]->needle++]=(fmChan[i]->debug_output(0)+fmChan[i]->debug_output(1));
|
||||
}
|
||||
|
||||
ssge->get_last_out(ssgOut);
|
||||
|
|
@ -467,14 +474,10 @@ void DivPlatformYM2610::acquire(short* bufL, short* bufR, size_t start, size_t l
|
|||
}
|
||||
|
||||
for (int i=7; i<13; i++) {
|
||||
adpcmOut.clear();
|
||||
aae->debug_channel(i-7)->output<2>(adpcmOut);
|
||||
oscBuf[i]->data[oscBuf[i]->needle++]=adpcmOut.data[0]+adpcmOut.data[1];
|
||||
oscBuf[i]->data[oscBuf[i]->needle++]=adpcmAChan[i-7]->get_last_out(0)+adpcmAChan[i-7]->get_last_out(1);
|
||||
}
|
||||
|
||||
adpcmOut.clear();
|
||||
abe->output(adpcmOut,1);
|
||||
oscBuf[13]->data[oscBuf[13]->needle++]=adpcmOut.data[0]+adpcmOut.data[1];
|
||||
oscBuf[13]->data[oscBuf[13]->needle++]=abe->get_last_out(0)+abe->get_last_out(1);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -408,7 +408,13 @@ void DivPlatformYM2610B::acquire(short* bufL, short* bufR, size_t start, size_t
|
|||
ymfm::adpcm_b_engine* abe=fm->debug_adpcm_b_engine();
|
||||
|
||||
ymfm::ssg_engine::output_data ssgOut;
|
||||
ymfm::ymfm_output<2> adpcmOut;
|
||||
|
||||
ymfm::fm_channel<ymfm::opn_registers_base<true>>* fmChan[6];
|
||||
ymfm::adpcm_a_channel* adpcmAChan[6];
|
||||
for (int i=0; i<6; i++) {
|
||||
fmChan[i]=fme->debug_channel(i);
|
||||
adpcmAChan[i]=aae->debug_channel(i);
|
||||
}
|
||||
|
||||
for (size_t h=start; h<start+len; h++) {
|
||||
os[0]=0; os[1]=0;
|
||||
|
|
@ -436,8 +442,9 @@ void DivPlatformYM2610B::acquire(short* bufL, short* bufR, size_t start, size_t
|
|||
bufL[h]=os[0];
|
||||
bufR[h]=os[1];
|
||||
|
||||
|
||||
for (int i=0; i<6; i++) {
|
||||
oscBuf[i]->data[oscBuf[i]->needle++]=(fme->debug_channel(i)->debug_output(0)+fme->debug_channel(i)->debug_output(1));
|
||||
oscBuf[i]->data[oscBuf[i]->needle++]=(fmChan[i]->debug_output(0)+fmChan[i]->debug_output(1));
|
||||
}
|
||||
|
||||
ssge->get_last_out(ssgOut);
|
||||
|
|
@ -446,14 +453,10 @@ void DivPlatformYM2610B::acquire(short* bufL, short* bufR, size_t start, size_t
|
|||
}
|
||||
|
||||
for (int i=9; i<15; i++) {
|
||||
adpcmOut.clear();
|
||||
aae->debug_channel(i-9)->output<2>(adpcmOut);
|
||||
oscBuf[i]->data[oscBuf[i]->needle++]=adpcmOut.data[0]+adpcmOut.data[1];
|
||||
oscBuf[i]->data[oscBuf[i]->needle++]=adpcmAChan[i-9]->get_last_out(0)+adpcmAChan[i-9]->get_last_out(1);
|
||||
}
|
||||
|
||||
adpcmOut.clear();
|
||||
abe->output(adpcmOut,1);
|
||||
oscBuf[15]->data[oscBuf[15]->needle++]=adpcmOut.data[0]+adpcmOut.data[1];
|
||||
oscBuf[15]->data[oscBuf[15]->needle++]=abe->get_last_out(0)+abe->get_last_out(1);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue