Merge pull request #354 from cam900/n163_demultiplex

Add support of N163 demultiplexed output
This commit is contained in:
tildearrow 2022-04-11 02:38:17 -05:00 committed by GitHub
commit d2a8b028e8
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
5 changed files with 38 additions and 2 deletions

View File

@ -607,6 +607,7 @@ void DivPlatformN163::reset() {
memset(regPool,0,128);
n163.set_disable(false);
n163.set_multiplex(multiplex);
chanMax=initChanMax;
loadWave=-1;
loadPos=0;
@ -636,8 +637,10 @@ void DivPlatformN163::setFlags(unsigned int flags) {
break;
}
initChanMax=chanMax=(flags>>4)&7;
multiplex=((flags>>7)&1)?false:true; // not accurate in real hardware
chipClock=rate;
rate/=15;
n163.set_multiplex(multiplex);
rWrite(0x7f,initChanMax<<4);
}

View File

@ -75,6 +75,7 @@ class DivPlatformN163: public DivDispatch {
unsigned char chanMax;
short loadWave, loadPos, loadLen;
unsigned char loadMode;
bool multiplex;
n163_core n163;
unsigned char regPool[128];

View File

@ -58,16 +58,27 @@
Frequency formula:
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"
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.)
if (m_disable)
{
if (!m_multiplex)
m_out = 0;
return;
}
// 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
@ -88,22 +99,34 @@ void n163_core::tick()
m_ram[m_voice_cycle + 5] = bitfield(accum, 16, 8);
// update voice cycle
bool flush = m_multiplex ? true : false;
m_voice_cycle -= 0x8;
if (m_voice_cycle < (0x78 - (bitfield(m_ram[0x7f], 4, 3) << 3)))
{
if (!m_multiplex)
flush = true;
m_voice_cycle = 0x78;
}
// 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()
{
// reset this chip
m_disable = false;
m_multiplex = true;
std::fill(std::begin(m_ram), std::end(m_ram), 0);
m_voice_cycle = 0x78;
m_addr_latch.reset();
m_out = 0;
m_acc = 0;
}
// accessor

View File

@ -48,6 +48,7 @@ public:
// register pool
u8 reg(u8 addr) { return m_ram[addr & 0x7f]; }
void set_multiplex(bool multiplex = true) { m_multiplex = multiplex; }
private:
// Address latch
@ -73,6 +74,9 @@ private:
u8 m_voice_cycle = 0x78; // Voice cycle for processing
addr_latch_t m_addr_latch; // address latch
s16 m_out = 0; // output
// demultiplex related
bool m_multiplex = true; // multiplex flag, but less noisy = inaccurate!
s16 m_acc = 0; // accumulated output
};
#endif

View File

@ -372,6 +372,11 @@ void FurnaceGUI::drawSysConf(int i) {
e->setSysFlags(i,(flags & ~(7 << 4)) | (((initialChannelLimit-1) & 7) << 4),restart);
updateWindowTitle();
} rightClickable
bool n163Multiplex=flags&128;
if (ImGui::Checkbox("Disable Multiplexed Output",&n163Multiplex)) {
e->setSysFlags(i,(flags&(~128))|(n163Multiplex<<7),restart);
updateWindowTitle();
}
break;
}
case DIV_SYSTEM_GB: