Merge pull request #354 from cam900/n163_demultiplex
Add support of N163 demultiplexed output
This commit is contained in:
commit
d2a8b028e8
|
@ -607,6 +607,7 @@ void DivPlatformN163::reset() {
|
||||||
memset(regPool,0,128);
|
memset(regPool,0,128);
|
||||||
|
|
||||||
n163.set_disable(false);
|
n163.set_disable(false);
|
||||||
|
n163.set_multiplex(multiplex);
|
||||||
chanMax=initChanMax;
|
chanMax=initChanMax;
|
||||||
loadWave=-1;
|
loadWave=-1;
|
||||||
loadPos=0;
|
loadPos=0;
|
||||||
|
@ -636,8 +637,10 @@ void DivPlatformN163::setFlags(unsigned int flags) {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
initChanMax=chanMax=(flags>>4)&7;
|
initChanMax=chanMax=(flags>>4)&7;
|
||||||
|
multiplex=((flags>>7)&1)?false:true; // not accurate in real hardware
|
||||||
chipClock=rate;
|
chipClock=rate;
|
||||||
rate/=15;
|
rate/=15;
|
||||||
|
n163.set_multiplex(multiplex);
|
||||||
rWrite(0x7f,initChanMax<<4);
|
rWrite(0x7f,initChanMax<<4);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -75,6 +75,7 @@ class DivPlatformN163: public DivDispatch {
|
||||||
unsigned char chanMax;
|
unsigned char chanMax;
|
||||||
short loadWave, loadPos, loadLen;
|
short loadWave, loadPos, loadLen;
|
||||||
unsigned char loadMode;
|
unsigned char loadMode;
|
||||||
|
bool multiplex;
|
||||||
|
|
||||||
n163_core n163;
|
n163_core n163;
|
||||||
unsigned char regPool[128];
|
unsigned char regPool[128];
|
||||||
|
|
|
@ -58,16 +58,27 @@
|
||||||
|
|
||||||
Frequency formula:
|
Frequency formula:
|
||||||
Frequency: Pitch input * ((Input clock * 15 * Number of activated voices) / 65536)
|
Frequency: Pitch input * ((Input clock * 15 * Number of activated voices) / 65536)
|
||||||
|
|
||||||
|
There's to way for reduce N163 noises: reduce channel limit and demultiplex
|
||||||
|
- Channel limit is runtime changeable and it makes some usable effects.
|
||||||
|
- Demultiplex is used for "non-ear destroyable" emulators, but less hardware accurate. (when LPF and RF filter is not considered)
|
||||||
|
This core is support both, You can choose output behavior
|
||||||
|
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include "n163.hpp"
|
#include "n163.hpp"
|
||||||
|
|
||||||
void n163_core::tick()
|
void n163_core::tick()
|
||||||
{
|
{
|
||||||
m_out = 0;
|
if (m_multiplex)
|
||||||
|
m_out = 0;
|
||||||
// 0xe000-0xe7ff Disable sound bits (bit 6, bit 0 to 5 are CPU ROM Bank 0x8000-0x9fff select.)
|
// 0xe000-0xe7ff Disable sound bits (bit 6, bit 0 to 5 are CPU ROM Bank 0x8000-0x9fff select.)
|
||||||
if (m_disable)
|
if (m_disable)
|
||||||
|
{
|
||||||
|
if (!m_multiplex)
|
||||||
|
m_out = 0;
|
||||||
return;
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
// tick per each clock
|
// tick per each clock
|
||||||
const u32 freq = m_ram[m_voice_cycle + 0] | (u32(m_ram[m_voice_cycle + 2]) << 8) | (bitfield<u32>(m_ram[m_voice_cycle + 4], 0, 2) << 16); // 18 bit frequency
|
const u32 freq = m_ram[m_voice_cycle + 0] | (u32(m_ram[m_voice_cycle + 2]) << 8) | (bitfield<u32>(m_ram[m_voice_cycle + 4], 0, 2) << 16); // 18 bit frequency
|
||||||
|
@ -88,22 +99,34 @@ void n163_core::tick()
|
||||||
m_ram[m_voice_cycle + 5] = bitfield(accum, 16, 8);
|
m_ram[m_voice_cycle + 5] = bitfield(accum, 16, 8);
|
||||||
|
|
||||||
// update voice cycle
|
// update voice cycle
|
||||||
|
bool flush = m_multiplex ? true : false;
|
||||||
m_voice_cycle -= 0x8;
|
m_voice_cycle -= 0x8;
|
||||||
if (m_voice_cycle < (0x78 - (bitfield(m_ram[0x7f], 4, 3) << 3)))
|
if (m_voice_cycle < (0x78 - (bitfield(m_ram[0x7f], 4, 3) << 3)))
|
||||||
|
{
|
||||||
|
if (!m_multiplex)
|
||||||
|
flush = true;
|
||||||
m_voice_cycle = 0x78;
|
m_voice_cycle = 0x78;
|
||||||
|
}
|
||||||
|
|
||||||
// output 4 bit waveform and volume, multiplexed
|
// output 4 bit waveform and volume, multiplexed
|
||||||
m_out = wave * volume;
|
m_acc += wave * volume;
|
||||||
|
if (flush)
|
||||||
|
{
|
||||||
|
m_out = m_acc / (m_multiplex ? 1 : (bitfield(m_ram[0x7f], 4, 3) + 1));
|
||||||
|
m_acc = 0;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void n163_core::reset()
|
void n163_core::reset()
|
||||||
{
|
{
|
||||||
// reset this chip
|
// reset this chip
|
||||||
m_disable = false;
|
m_disable = false;
|
||||||
|
m_multiplex = true;
|
||||||
std::fill(std::begin(m_ram), std::end(m_ram), 0);
|
std::fill(std::begin(m_ram), std::end(m_ram), 0);
|
||||||
m_voice_cycle = 0x78;
|
m_voice_cycle = 0x78;
|
||||||
m_addr_latch.reset();
|
m_addr_latch.reset();
|
||||||
m_out = 0;
|
m_out = 0;
|
||||||
|
m_acc = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
// accessor
|
// accessor
|
||||||
|
|
|
@ -48,6 +48,7 @@ public:
|
||||||
|
|
||||||
// register pool
|
// register pool
|
||||||
u8 reg(u8 addr) { return m_ram[addr & 0x7f]; }
|
u8 reg(u8 addr) { return m_ram[addr & 0x7f]; }
|
||||||
|
void set_multiplex(bool multiplex = true) { m_multiplex = multiplex; }
|
||||||
|
|
||||||
private:
|
private:
|
||||||
// Address latch
|
// Address latch
|
||||||
|
@ -73,6 +74,9 @@ private:
|
||||||
u8 m_voice_cycle = 0x78; // Voice cycle for processing
|
u8 m_voice_cycle = 0x78; // Voice cycle for processing
|
||||||
addr_latch_t m_addr_latch; // address latch
|
addr_latch_t m_addr_latch; // address latch
|
||||||
s16 m_out = 0; // output
|
s16 m_out = 0; // output
|
||||||
|
// demultiplex related
|
||||||
|
bool m_multiplex = true; // multiplex flag, but less noisy = inaccurate!
|
||||||
|
s16 m_acc = 0; // accumulated output
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -372,6 +372,11 @@ void FurnaceGUI::drawSysConf(int i) {
|
||||||
e->setSysFlags(i,(flags & ~(7 << 4)) | (((initialChannelLimit-1) & 7) << 4),restart);
|
e->setSysFlags(i,(flags & ~(7 << 4)) | (((initialChannelLimit-1) & 7) << 4),restart);
|
||||||
updateWindowTitle();
|
updateWindowTitle();
|
||||||
} rightClickable
|
} rightClickable
|
||||||
|
bool n163Multiplex=flags&128;
|
||||||
|
if (ImGui::Checkbox("Disable Multiplexed Output",&n163Multiplex)) {
|
||||||
|
e->setSysFlags(i,(flags&(~128))|(n163Multiplex<<7),restart);
|
||||||
|
updateWindowTitle();
|
||||||
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case DIV_SYSTEM_GB:
|
case DIV_SYSTEM_GB:
|
||||||
|
|
Loading…
Reference in a new issue