SN: acquireDirect()

This commit is contained in:
tildearrow 2025-03-08 03:23:49 -05:00
parent b8f214020f
commit 9981ab7e43
4 changed files with 108 additions and 98 deletions

View file

@ -118,7 +118,9 @@ void DivPlatformSMS::acquire_nuked(short** buf, size_t len) {
}
}
void DivPlatformSMS::acquire_mame(short** buf, size_t len) {
void DivPlatformSMS::acquire_mame(blip_buffer_t** bb, size_t len) {
thread_local short outs[2];
while (!writes.empty()) {
QueuedWrite w=writes.front();
if (stereo && (w.addr==1))
@ -137,11 +139,28 @@ void DivPlatformSMS::acquire_mame(short** buf, size_t len) {
}
for (size_t h=0; h<len; h++) {
short* outs[2]={
&buf[0][h],
stereo?(&buf[1][h]):NULL
};
sn->sound_stream_update(outs,1);
// wahahaha heuristic...
int advance=len-h;
for (int i=0; i<4; i++) {
if (sn->m_count[i]<advance) advance=sn->m_count[i];
}
if (advance<1) advance=1;
sn->sound_stream_update(outs,advance);
h+=advance-1;
if (outs[0]!=lastOut[0]) {
blip_add_delta(bb[0],h,outs[0]-lastOut[0]);
lastOut[0]=outs[0];
}
if (stereo) {
if (outs[1]!=lastOut[1]) {
blip_add_delta(bb[1],h,outs[1]-lastOut[1]);
lastOut[1]=outs[1];
}
}
for (int i=0; i<4; i++) {
if (isMuted[i]) {
oscBuf[i]->putSample(h,0);
@ -159,11 +178,14 @@ void DivPlatformSMS::acquire_mame(short** buf, size_t len) {
void DivPlatformSMS::acquire(short** buf, size_t len) {
if (nuked) {
acquire_nuked(buf,len);
} else {
acquire_mame(buf,len);
}
}
void DivPlatformSMS::acquireDirect(blip_buffer_t** bb, size_t len) {
if (nuked) return;
acquire_mame(bb,len);
}
double DivPlatformSMS::NOTE_SN(int ch, int note) {
double CHIP_DIVIDER=toneDivider;
if (ch==3) CHIP_DIVIDER=noiseDivider;
@ -522,6 +544,8 @@ void DivPlatformSMS::reset() {
if (stereo) {
rWrite(1,0xff);
}
lastOut[0]=0;
lastOut[1]=0;
}
int DivPlatformSMS::getOutputCount() {
@ -536,6 +560,10 @@ bool DivPlatformSMS::keyOffAffectsPorta(int ch) {
return true;
}
bool DivPlatformSMS::hasAcquireDirect() {
return !nuked;
}
bool DivPlatformSMS::getLegacyAlwaysSetVolume() {
return false;
}
@ -597,7 +625,7 @@ void DivPlatformSMS::setFlags(const DivConfig& flags) {
noiseDivider=60.0; // 64 for match to tone frequency on non-Sega PSG but compatibility
break;
case 2: // TI+Atari
sn=new sn76496_base_device(0x4000, 0x0f35, 0x01, 0x02, true, false, 1/*8*/, false, true);
sn=new sn76496_base_device(0x4000, 0x0f35, 0x01, 0x02, true, false, false, true);
isRealSN=true;
stereo=false;
noiseDivider=60.0;

View file

@ -44,6 +44,7 @@ class DivPlatformSMS: public DivDispatch {
unsigned char snNoiseMode;
unsigned char regPool[16];
unsigned char chanLatch;
int lastOut[2];
int divider=16;
double toneDivider=64.0;
double noiseDivider=64.0;
@ -71,9 +72,10 @@ class DivPlatformSMS: public DivDispatch {
void poolWrite(unsigned short a, unsigned char v);
void acquire_nuked(short** buf, size_t len);
void acquire_mame(short** buf, size_t len);
void acquire_mame(blip_buffer_t** bb, size_t len);
public:
void acquire(short** buf, size_t len);
void acquireDirect(blip_buffer_t** bb, size_t len);
int dispatch(DivCommand c);
void* getChanState(int chan);
DivMacroInt* getChanMacroInt(int ch);
@ -90,6 +92,7 @@ class DivPlatformSMS: public DivDispatch {
int getOutputCount();
bool keyOffAffectsArp(int ch);
bool keyOffAffectsPorta(int ch);
bool hasAcquireDirect();
bool getLegacyAlwaysSetVolume();
float getPostAmp();
int getPortaFloor(int ch);

View file

@ -155,7 +155,6 @@ sn76496_base_device::sn76496_base_device(
int noisetap2,
bool negate,
bool stereo,
int clockdivider,
bool ncr,
bool sega)
: m_feedback_mask(feedbackmask)
@ -164,59 +163,58 @@ sn76496_base_device::sn76496_base_device(
, m_whitenoise_tap2(noisetap2)
, m_negate(negate)
, m_stereo(stereo)
, m_clock_divider(clockdivider)
, m_ncr_style_psg(ncr)
, m_sega_style_psg(sega)
{
}
sn76496_device::sn76496_device()
: sn76496_base_device(0x10000, 0x04, 0x08, false, false, 1/*8*/, false, true)
: sn76496_base_device(0x10000, 0x04, 0x08, false, false, false, true)
{
}
y2404_device::y2404_device()
: sn76496_base_device(0x10000, 0x04, 0x08, false, false, 1/*8*/, false, true)
: sn76496_base_device(0x10000, 0x04, 0x08, false, false, false, true)
{
}
sn76489_device::sn76489_device()
: sn76496_base_device(0x4000, 0x01, 0x02, true, false, 1/*8*/, false, true)
: sn76496_base_device(0x4000, 0x01, 0x02, true, false, false, true)
{
}
sn76489a_device::sn76489a_device()
: sn76496_base_device(0x10000, 0x04, 0x08, false, false, 1/*8*/, false, true)
: sn76496_base_device(0x10000, 0x04, 0x08, false, false, false, true)
{
}
sn76494_device::sn76494_device()
: sn76496_base_device(0x10000, 0x04, 0x08, false, false, 1, false, true)
: sn76496_base_device(0x10000, 0x04, 0x08, false, false, false, true)
{
}
sn94624_device::sn94624_device()
: sn76496_base_device(0x4000, 0x01, 0x02, true, false, 1, false, true)
: sn76496_base_device(0x4000, 0x01, 0x02, true, false, false, true)
{
}
ncr8496_device::ncr8496_device()
: sn76496_base_device(0x8000, 0x02, 0x20, true, false, 1/*8*/, true, true)
: sn76496_base_device(0x8000, 0x02, 0x20, true, false, true, true)
{
}
pssj3_device::pssj3_device()
: sn76496_base_device(0x8000, 0x02, 0x20, false, false, 1/*8*/, true, true)
: sn76496_base_device(0x8000, 0x02, 0x20, false, false, true, true)
{
}
gamegear_device::gamegear_device()
: sn76496_base_device(0x8000, 0x01, 0x08, true, true, 1/*8*/, false, false)
: sn76496_base_device(0x8000, 0x01, 0x08, true, true, false, false)
{
}
segapsg_device::segapsg_device()
: sn76496_base_device(0x8000, 0x01, 0x08, true, false, 1/*8*/, false, false)
: sn76496_base_device(0x8000, 0x01, 0x08, true, false, false, false)
{
}
@ -246,7 +244,6 @@ void sn76496_base_device::device_start()
m_output[3] = m_RNG & 1;
m_stereo_mask = 0xFF; // all channels enabled
m_current_clock = m_clock_divider-1;
// set gain
gain = 0;
@ -337,28 +334,17 @@ inline bool sn76496_base_device::in_noise_mode()
return ((m_register[6] & 4)!=0);
}
void sn76496_base_device::sound_stream_update(short** outputs, int outLen)
void sn76496_base_device::sound_stream_update(short* outputs, int advance)
{
int i;
int16_t out;
int16_t out2 = 0;
for (int sampindex = 0; sampindex < outLen; sampindex++)
{
// clock chip once
if (m_current_clock > 0) // not ready for new divided clock
{
m_current_clock--;
}
else // ready for new divided clock, make a new sample
{
m_current_clock = m_clock_divider-1;
// handle channels 0,1,2
for (i = 0; i < 3; i++)
{
m_count[i]--;
m_count[i]-=advance;
if (m_count[i] <= 0)
{
m_output[i] ^= 1;
@ -367,7 +353,7 @@ void sn76496_base_device::sound_stream_update(short** outputs, int outLen)
}
// handle channel 3
m_count[3]--;
m_count[3]-=advance;
if (m_count[3] <= 0)
{
// if noisemode is 1, both taps are enabled
@ -386,7 +372,6 @@ void sn76496_base_device::sound_stream_update(short** outputs, int outLen)
m_count[3] = m_period[3];
}
}
if (m_stereo)
{
@ -410,8 +395,7 @@ void sn76496_base_device::sound_stream_update(short** outputs, int outLen)
if (m_negate) { out = -out; out2 = -out2; }
outputs[0][sampindex]=out;
if (m_stereo && (outputs[1] != nullptr))
outputs[1][sampindex]=out2;
}
outputs[0]=out;
if (m_stereo)
outputs[1]=out2;
}

View file

@ -15,7 +15,7 @@ public:
void stereo_w(u8 data);
void write(u8 data);
void device_start();
void sound_stream_update(short** outputs, int outLen);
void sound_stream_update(short* outputs, int outLen);
inline int32_t get_channel_output(int ch) {
return ((m_output[ch]!=0)?m_volume[ch]:0);
}
@ -28,7 +28,6 @@ public:
int noisetap2,
bool negate,
bool stereo,
int clockdivider,
bool ncr,
bool sega);
@ -38,7 +37,6 @@ public:
int noisetap2,
bool negate,
bool stereo,
int clockdivider,
bool ncr,
bool sega)
: sn76496_base_device(
@ -48,12 +46,11 @@ public:
noisetap2,
negate,
stereo,
clockdivider,
ncr,
sega)
{}
private:
public: // SORRY....
inline bool in_noise_mode();
bool m_ready_state;
@ -64,7 +61,6 @@ private:
const int32_t m_whitenoise_tap2; // mask for white noise tap 2 (lower one, usually bit 13)
bool m_negate; // output negate flag
const bool m_stereo; // whether we're dealing with stereo or not
const int32_t m_clock_divider; // clock divider
const bool m_ncr_style_psg; // flag to ignore writes to regs 1,3,5,6,7 with bit 7 low
const bool m_sega_style_psg; // flag to make frequency zero acts as if it is one more than max (0x3ff+1) or if it acts like 0; the initial register is pointing to 0x3 instead of 0x0; the volume reg is preloaded with 0xF instead of 0x0
@ -73,7 +69,6 @@ private:
int32_t m_last_register; // last register written
int32_t m_volume[4]; // db volume of voice 0-2 and noise
uint32_t m_RNG; // noise generator LFSR
int32_t m_current_clock;
int32_t m_stereo_mask; // the stereo output mask
int32_t m_period[4]; // Length of 1/2 of waveform
int32_t m_count[4]; // Position within the waveform