SCC: acquireDirect()

This commit is contained in:
tildearrow 2025-03-06 19:06:45 -05:00
parent 7a6f6a6745
commit c2228cd74b
7 changed files with 94 additions and 105 deletions

View file

@ -5,61 +5,88 @@
Copyright holder(s): cam900 Copyright holder(s): cam900
Contributor(s): Natt Akuma, James Alan Nguyen, Laurens Holst Contributor(s): Natt Akuma, James Alan Nguyen, Laurens Holst
Konami SCC emulation core Konami SCC emulation core
modified by tildearrow...
*/ */
#include "scc.hpp" #include "scc.hpp"
#include "../../../../../src/engine/dispatch.h"
// shared SCC features // shared SCC features
void scc_core::tick(const int cycles) void scc_core::tick(const int cycles, blip_buffer_t* bb, DivDispatchOscBuffer** oscBuf)
{ {
m_out = 0;
for (int elem=0; elem<5; elem++) for (int elem=0; elem<5; elem++)
{ {
m_voice[elem].tick(cycles); m_voice[elem].tick(cycles,bb,oscBuf[elem]);
m_out += m_voice[elem].out();
} }
} }
void scc_core::voice_t::tick(const int cycles) void scc_core::voice_t::updateOut(const int pos) {
{ int out=0;
if (m_pitch >= 9) // or voice is halted // get output
{ if (m_enable)
// update counter - Post decrement {
const u16 temp = m_counter; out = (m_wave[m_addr] * m_volume) >> 4; // scale to 11 bit digital output
if (m_host.m_test.freq_4bit()) // 4 bit frequency mode }
{ else
m_counter = (m_counter & ~0x0ff) | (bitfield(bitfield(m_counter, 0, 8) - cycles, 0, 8) << 0); {
m_counter = (m_counter & ~0xf00) | (bitfield(bitfield(m_counter, 8, 4) - cycles, 0, 4) << 8); out = 0;
} }
else
{
m_counter = bitfield(m_counter - cycles, 0, 12);
}
// handle counter carry m_oscBuf->putSample(pos,out<<7);
const bool carry = (temp<cycles) || (m_host.m_test.freq_8bit()
? (bitfield(temp, 0, 8) == 0) if (out!=m_out) {
: (m_host.m_test.freq_4bit() ? (bitfield(temp, 8, 4) == 0) blip_add_delta(m_bb,pos,(out-m_out)<<5);
: (bitfield(temp, 0, 12) == 0))); m_out=out;
if (carry) }
{ }
m_addr = bitfield(m_addr + 1, 0, 5);
m_counter = m_pitch - ((temp<cycles)?(cycles-temp-1):0); void scc_core::voice_t::tick(const int amt, blip_buffer_t* bb, DivDispatchOscBuffer* oscBuf)
while (m_counter>m_pitch) { {
m_addr = bitfield(m_addr + 1, 0, 5); m_bb=bb;
m_counter+=m_pitch-1; m_oscBuf=oscBuf;
}
} if (m_pitch >= 9) // or voice is halted
} {
// get output int rem=amt;
if (m_enable) for (int pos=0; pos<amt; pos++) {
{ int cycles=m_host.m_test.freq_4bit()?(m_counter&15):(m_host.m_test.freq_8bit()?(m_counter&0xff):(m_counter&0xfff));
m_out = (m_wave[m_addr] * m_volume) >> 4; // scale to 11 bit digital output if (cycles>rem) cycles=rem;
} if (cycles<1) cycles=1;
else
{ // update counter - Post decrement
m_out = 0; const u16 temp = m_counter;
} if (m_host.m_test.freq_4bit()) // 4 bit frequency mode
{
m_counter = (m_counter & ~0x0ff) | (bitfield(bitfield(m_counter, 0, 8) - cycles, 0, 8) << 0);
m_counter = (m_counter & ~0xf00) | (bitfield(bitfield(m_counter, 8, 4) - cycles, 0, 4) << 8);
}
else
{
m_counter = bitfield(m_counter - cycles, 0, 12);
}
// handle counter carry
const bool carry = (temp<cycles) || (m_host.m_test.freq_8bit()
? (bitfield(temp, 0, 8) == 0)
: (m_host.m_test.freq_4bit() ? (bitfield(temp, 8, 4) == 0)
: (bitfield(temp, 0, 12) == 0)));
if (carry)
{
m_addr = bitfield(m_addr + 1, 0, 5);
m_counter = m_pitch - ((temp<cycles)?(cycles-temp-1):0);
while (m_counter>m_pitch) {
m_addr = bitfield(m_addr + 1, 0, 5);
m_counter+=m_pitch-1;
}
}
pos+=cycles-1;
rem-=cycles;
updateOut(pos);
}
} else {
updateOut(0);
}
} }
void scc_core::reset() void scc_core::reset()

View file

@ -5,6 +5,8 @@
Copyright holder(s): cam900 Copyright holder(s): cam900
Contributor(s): Natt Akuma, James Alan Nguyen, Laurens Holst Contributor(s): Natt Akuma, James Alan Nguyen, Laurens Holst
Konami SCC emulation core Konami SCC emulation core
modified by tildearrow...
*/ */
#ifndef _VGSOUND_EMU_SRC_SCC_HPP #ifndef _VGSOUND_EMU_SRC_SCC_HPP
@ -12,10 +14,13 @@
#pragma once #pragma once
#include "blip_buf.h"
#include "../core/core.hpp" #include "../core/core.hpp"
#include "../core/util/mem_intf.hpp" #include "../core/util/mem_intf.hpp"
#include <string.h> #include <string.h>
struct DivDispatchOscBuffer;
using namespace vgsound_emu; using namespace vgsound_emu;
// shared for SCCs // shared for SCCs
@ -42,7 +47,8 @@ class scc_core : public vgsound_emu_core
// internal state // internal state
void reset(); void reset();
void tick(const int cycles=1); void tick(const int cycles, blip_buffer_t* bb, DivDispatchOscBuffer* oscBuf);
void updateOut(const int pos);
// accessors // accessors
inline void reset_addr() { m_addr = 0; } inline void reset_addr() { m_addr = 0; }
@ -70,6 +76,8 @@ class scc_core : public vgsound_emu_core
private: private:
// registers // registers
scc_core &m_host; scc_core &m_host;
blip_buffer_t* m_bb;
DivDispatchOscBuffer* m_oscBuf;
s8 m_wave[32]; // internal waveform s8 m_wave[32]; // internal waveform
bool m_enable = false; // output enable flag bool m_enable = false; // output enable flag
u16 m_pitch : 12; // pitch u16 m_pitch : 12; // pitch
@ -152,7 +160,7 @@ class scc_core : public vgsound_emu_core
// internal state // internal state
virtual void reset(); virtual void reset();
void tick(const int cycles=1); void tick(const int cycles, blip_buffer_t* bb, DivDispatchOscBuffer** oscBuf);
// getters // getters
inline s32 out() { return m_out; } // output to DA0...DA10 pin inline s32 out() { return m_out; } // output to DA0...DA10 pin

View file

@ -672,20 +672,10 @@ void DivDispatchContainer::init(DivSystem sys, DivEngine* eng, int chanCount, do
case DIV_SYSTEM_SCC: case DIV_SYSTEM_SCC:
dispatch=new DivPlatformSCC; dispatch=new DivPlatformSCC;
((DivPlatformSCC*)dispatch)->setChipModel(false); ((DivPlatformSCC*)dispatch)->setChipModel(false);
if (isRender) {
((DivPlatformSCC*)dispatch)->setCoreQuality(eng->getConfInt("sccQualityRender",3));
} else {
((DivPlatformSCC*)dispatch)->setCoreQuality(eng->getConfInt("sccQuality",3));
}
break; break;
case DIV_SYSTEM_SCC_PLUS: case DIV_SYSTEM_SCC_PLUS:
dispatch=new DivPlatformSCC; dispatch=new DivPlatformSCC;
((DivPlatformSCC*)dispatch)->setChipModel(true); ((DivPlatformSCC*)dispatch)->setChipModel(true);
if (isRender) {
((DivPlatformSCC*)dispatch)->setCoreQuality(eng->getConfInt("sccQualityRender",3));
} else {
((DivPlatformSCC*)dispatch)->setCoreQuality(eng->getConfInt("sccQuality",3));
}
break; break;
case DIV_SYSTEM_YMZ280B: case DIV_SYSTEM_YMZ280B:
dispatch=new DivPlatformYMZ280B; dispatch=new DivPlatformYMZ280B;

View file

@ -81,19 +81,17 @@ const char** DivPlatformSCC::getRegisterSheet() {
} }
void DivPlatformSCC::acquire(short** buf, size_t len) { void DivPlatformSCC::acquire(short** buf, size_t len) {
}
void DivPlatformSCC::acquireDirect(blip_buffer_t** bb, size_t len) {
for (int i=0; i<5; i++) { for (int i=0; i<5; i++) {
oscBuf[i]->begin(len); oscBuf[i]->begin(len);
} }
for (size_t h=0; h<len; h++) { scc->tick(len,bb[0],oscBuf);
scc->tick(coreQuality); //for (int i=0; i<5; i++) {
short out=(short)scc->out()<<5; // oscBuf[i]->putSample(h,scc->voice_out(i)<<7);
buf[0][h]=out; //}
for (int i=0; i<5; i++) {
oscBuf[i]->putSample(h,scc->voice_out(i)<<7);
}
}
for (int i=0; i<5; i++) { for (int i=0; i<5; i++) {
oscBuf[i]->end(len); oscBuf[i]->end(len);
@ -346,6 +344,10 @@ int DivPlatformSCC::getOutputCount() {
return 1; return 1;
} }
bool DivPlatformSCC::hasAcquireDirect() {
return true;
}
void DivPlatformSCC::notifyWaveChange(int wave) { void DivPlatformSCC::notifyWaveChange(int wave) {
for (int i=0; i<5; i++) { for (int i=0; i<5; i++) {
if (chan[i].wave==wave) { if (chan[i].wave==wave) {
@ -391,38 +393,12 @@ void DivPlatformSCC::setFlags(const DivConfig& flags) {
break; break;
} }
CHECK_CUSTOM_CLOCK; CHECK_CUSTOM_CLOCK;
rate=chipClock/(coreQuality>>1); rate=chipClock*2;
for (int i=0; i<5; i++) { for (int i=0; i<5; i++) {
oscBuf[i]->setRate(rate); oscBuf[i]->setRate(rate);
} }
} }
void DivPlatformSCC::setCoreQuality(unsigned char q) {
switch (q) {
case 0:
coreQuality=128;
break;
case 1:
coreQuality=64;
break;
case 2:
coreQuality=32;
break;
case 3:
coreQuality=16;
break;
case 4:
coreQuality=8;
break;
case 5:
coreQuality=2;
break;
default:
coreQuality=16;
break;
}
}
int DivPlatformSCC::init(DivEngine* p, int channels, int sugRate, const DivConfig& flags) { int DivPlatformSCC::init(DivEngine* p, int channels, int sugRate, const DivConfig& flags) {
parent=p; parent=p;
dumpWrites=false; dumpWrites=false;

View file

@ -41,7 +41,6 @@ class DivPlatformSCC: public DivDispatch {
unsigned char writeOscBuf; unsigned char writeOscBuf;
int lastUpdated34; int lastUpdated34;
int coreQuality;
scc_core* scc; scc_core* scc;
bool isPlus; bool isPlus;
unsigned char regBase; unsigned char regBase;
@ -51,6 +50,7 @@ class DivPlatformSCC: public DivDispatch {
friend void putDispatchChan(void*,int,int); friend void putDispatchChan(void*,int,int);
public: public:
void acquire(short** buf, size_t len); void acquire(short** buf, size_t len);
void acquireDirect(blip_buffer_t** bb, size_t len);
int dispatch(DivCommand c); int dispatch(DivCommand c);
void* getChanState(int chan); void* getChanState(int chan);
DivMacroInt* getChanMacroInt(int ch); DivMacroInt* getChanMacroInt(int ch);
@ -62,6 +62,7 @@ class DivPlatformSCC: public DivDispatch {
void tick(bool sysTick=true); void tick(bool sysTick=true);
void muteChannel(int ch, bool mute); void muteChannel(int ch, bool mute);
int getOutputCount(); int getOutputCount();
bool hasAcquireDirect();
void notifyWaveChange(int wave); void notifyWaveChange(int wave);
void notifyInsDeletion(void* ins); void notifyInsDeletion(void* ins);
void poke(unsigned int addr, unsigned short val); void poke(unsigned int addr, unsigned short val);
@ -69,7 +70,6 @@ class DivPlatformSCC: public DivDispatch {
const char** getRegisterSheet(); const char** getRegisterSheet();
void setFlags(const DivConfig& flags); void setFlags(const DivConfig& flags);
int init(DivEngine* parent, int channels, int sugRate, const DivConfig& flags); int init(DivEngine* parent, int channels, int sugRate, const DivConfig& flags);
void setCoreQuality(unsigned char q);
void setChipModel(bool isPlus); void setChipModel(bool isPlus);
void quit(); void quit();
~DivPlatformSCC(); ~DivPlatformSCC();

View file

@ -1801,7 +1801,6 @@ class FurnaceGUI {
int ndsQuality; int ndsQuality;
int pnQuality; int pnQuality;
int saaQuality; int saaQuality;
int sccQuality;
int smQuality; int smQuality;
int swanQuality; int swanQuality;
int vbQuality; int vbQuality;
@ -1827,7 +1826,6 @@ class FurnaceGUI {
int ndsQualityRender; int ndsQualityRender;
int pnQualityRender; int pnQualityRender;
int saaQualityRender; int saaQualityRender;
int sccQualityRender;
int smQualityRender; int smQualityRender;
int swanQualityRender; int swanQualityRender;
int vbQualityRender; int vbQualityRender;
@ -2064,7 +2062,6 @@ class FurnaceGUI {
ndsQuality(3), ndsQuality(3),
pnQuality(3), pnQuality(3),
saaQuality(3), saaQuality(3),
sccQuality(3),
smQuality(3), smQuality(3),
swanQuality(3), swanQuality(3),
vbQuality(3), vbQuality(3),
@ -2090,7 +2087,6 @@ class FurnaceGUI {
ndsQualityRender(3), ndsQualityRender(3),
pnQualityRender(3), pnQualityRender(3),
saaQualityRender(3), saaQualityRender(3),
sccQualityRender(3),
smQualityRender(3), smQualityRender(3),
swanQualityRender(3), swanQualityRender(3),
vbQualityRender(3), vbQualityRender(3),

View file

@ -2125,7 +2125,6 @@ void FurnaceGUI::drawSettings() {
CORE_QUALITY("Nintendo DS",ndsQuality,ndsQualityRender); CORE_QUALITY("Nintendo DS",ndsQuality,ndsQualityRender);
CORE_QUALITY("PowerNoise",pnQuality,pnQualityRender); CORE_QUALITY("PowerNoise",pnQuality,pnQualityRender);
CORE_QUALITY("SAA1099",saaQuality,saaQualityRender); CORE_QUALITY("SAA1099",saaQuality,saaQualityRender);
CORE_QUALITY("SCC",sccQuality,sccQualityRender);
CORE_QUALITY("SID (dSID)",dsidQuality,dsidQualityRender); CORE_QUALITY("SID (dSID)",dsidQuality,dsidQualityRender);
CORE_QUALITY("SM8521",smQuality,smQualityRender); CORE_QUALITY("SM8521",smQuality,smQualityRender);
CORE_QUALITY("Virtual Boy",vbQuality,vbQualityRender); CORE_QUALITY("Virtual Boy",vbQuality,vbQualityRender);
@ -5136,7 +5135,6 @@ void FurnaceGUI::readConfig(DivConfig& conf, FurnaceGUISettingGroups groups) {
settings.ndsQuality=conf.getInt("ndsQuality",3); settings.ndsQuality=conf.getInt("ndsQuality",3);
settings.pnQuality=conf.getInt("pnQuality",3); settings.pnQuality=conf.getInt("pnQuality",3);
settings.saaQuality=conf.getInt("saaQuality",3); settings.saaQuality=conf.getInt("saaQuality",3);
settings.sccQuality=conf.getInt("sccQuality",3);
settings.smQuality=conf.getInt("smQuality",3); settings.smQuality=conf.getInt("smQuality",3);
settings.swanQuality=conf.getInt("swanQuality",3); settings.swanQuality=conf.getInt("swanQuality",3);
settings.vbQuality=conf.getInt("vbQuality",3); settings.vbQuality=conf.getInt("vbQuality",3);
@ -5164,7 +5162,6 @@ void FurnaceGUI::readConfig(DivConfig& conf, FurnaceGUISettingGroups groups) {
settings.ndsQualityRender=conf.getInt("ndsQualityRender",3); settings.ndsQualityRender=conf.getInt("ndsQualityRender",3);
settings.pnQualityRender=conf.getInt("pnQualityRender",3); settings.pnQualityRender=conf.getInt("pnQualityRender",3);
settings.saaQualityRender=conf.getInt("saaQualityRender",3); settings.saaQualityRender=conf.getInt("saaQualityRender",3);
settings.sccQualityRender=conf.getInt("sccQualityRender",3);
settings.smQualityRender=conf.getInt("smQualityRender",3); settings.smQualityRender=conf.getInt("smQualityRender",3);
settings.swanQualityRender=conf.getInt("swanQualityRender",3); settings.swanQualityRender=conf.getInt("swanQualityRender",3);
settings.vbQualityRender=conf.getInt("vbQualityRender",3); settings.vbQualityRender=conf.getInt("vbQualityRender",3);
@ -5208,7 +5205,6 @@ void FurnaceGUI::readConfig(DivConfig& conf, FurnaceGUISettingGroups groups) {
clampSetting(settings.ndsQuality,0,5); clampSetting(settings.ndsQuality,0,5);
clampSetting(settings.pnQuality,0,5); clampSetting(settings.pnQuality,0,5);
clampSetting(settings.saaQuality,0,5); clampSetting(settings.saaQuality,0,5);
clampSetting(settings.sccQuality,0,5);
clampSetting(settings.smQuality,0,5); clampSetting(settings.smQuality,0,5);
clampSetting(settings.swanQuality,0,5); clampSetting(settings.swanQuality,0,5);
clampSetting(settings.vbQuality,0,5); clampSetting(settings.vbQuality,0,5);
@ -5234,7 +5230,6 @@ void FurnaceGUI::readConfig(DivConfig& conf, FurnaceGUISettingGroups groups) {
clampSetting(settings.ndsQualityRender,0,5); clampSetting(settings.ndsQualityRender,0,5);
clampSetting(settings.pnQualityRender,0,5); clampSetting(settings.pnQualityRender,0,5);
clampSetting(settings.saaQualityRender,0,5); clampSetting(settings.saaQualityRender,0,5);
clampSetting(settings.sccQualityRender,0,5);
clampSetting(settings.smQualityRender,0,5); clampSetting(settings.smQualityRender,0,5);
clampSetting(settings.swanQualityRender,0,5); clampSetting(settings.swanQualityRender,0,5);
clampSetting(settings.vbQualityRender,0,5); clampSetting(settings.vbQualityRender,0,5);
@ -5734,7 +5729,6 @@ void FurnaceGUI::writeConfig(DivConfig& conf, FurnaceGUISettingGroups groups) {
conf.set("ndsQuality",settings.ndsQuality); conf.set("ndsQuality",settings.ndsQuality);
conf.set("pnQuality",settings.pnQuality); conf.set("pnQuality",settings.pnQuality);
conf.set("saaQuality",settings.saaQuality); conf.set("saaQuality",settings.saaQuality);
conf.set("sccQuality",settings.sccQuality);
conf.set("smQuality",settings.smQuality); conf.set("smQuality",settings.smQuality);
conf.set("swanQuality",settings.swanQuality); conf.set("swanQuality",settings.swanQuality);
conf.set("vbQuality",settings.vbQuality); conf.set("vbQuality",settings.vbQuality);
@ -5762,7 +5756,6 @@ void FurnaceGUI::writeConfig(DivConfig& conf, FurnaceGUISettingGroups groups) {
conf.set("ndsQualityRender",settings.ndsQualityRender); conf.set("ndsQualityRender",settings.ndsQualityRender);
conf.set("pnQualityRender",settings.pnQualityRender); conf.set("pnQualityRender",settings.pnQualityRender);
conf.set("saaQualityRender",settings.saaQualityRender); conf.set("saaQualityRender",settings.saaQualityRender);
conf.set("sccQualityRender",settings.sccQualityRender);
conf.set("smQualityRender",settings.smQualityRender); conf.set("smQualityRender",settings.smQualityRender);
conf.set("swanQualityRender",settings.swanQualityRender); conf.set("swanQualityRender",settings.swanQualityRender);
conf.set("vbQualityRender",settings.vbQualityRender); conf.set("vbQualityRender",settings.vbQualityRender);
@ -5824,7 +5817,6 @@ void FurnaceGUI::commitSettings() {
settings.ndsQuality!=e->getConfInt("ndsQuality",3) || settings.ndsQuality!=e->getConfInt("ndsQuality",3) ||
settings.pnQuality!=e->getConfInt("pnQuality",3) || settings.pnQuality!=e->getConfInt("pnQuality",3) ||
settings.saaQuality!=e->getConfInt("saaQuality",3) || settings.saaQuality!=e->getConfInt("saaQuality",3) ||
settings.sccQuality!=e->getConfInt("sccQuality",3) ||
settings.smQuality!=e->getConfInt("smQuality",3) || settings.smQuality!=e->getConfInt("smQuality",3) ||
settings.swanQuality!=e->getConfInt("swanQuality",3) || settings.swanQuality!=e->getConfInt("swanQuality",3) ||
settings.vbQuality!=e->getConfInt("vbQuality",3) || settings.vbQuality!=e->getConfInt("vbQuality",3) ||