SN: acquireDirect()
This commit is contained in:
parent
b8f214020f
commit
9981ab7e43
|
@ -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;
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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,81 +334,68 @@ 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;
|
||||
int i;
|
||||
|
||||
int16_t out;
|
||||
int16_t out2 = 0;
|
||||
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]-=advance;
|
||||
if (m_count[i] <= 0)
|
||||
{
|
||||
m_output[i] ^= 1;
|
||||
m_count[i] = m_period[i];
|
||||
}
|
||||
}
|
||||
|
||||
// handle channels 0,1,2
|
||||
for (i = 0; i < 3; i++)
|
||||
{
|
||||
m_count[i]--;
|
||||
if (m_count[i] <= 0)
|
||||
{
|
||||
m_output[i] ^= 1;
|
||||
m_count[i] = m_period[i];
|
||||
}
|
||||
}
|
||||
// handle channel 3
|
||||
m_count[3]-=advance;
|
||||
if (m_count[3] <= 0)
|
||||
{
|
||||
// if noisemode is 1, both taps are enabled
|
||||
// if noisemode is 0, the lower tap, whitenoisetap2, is held at 0
|
||||
// The != was a bit-XOR (^) before
|
||||
if (((m_RNG & m_whitenoise_tap1)!=0) != (((int32_t)(m_RNG & m_whitenoise_tap2)!=(m_ncr_style_psg?m_whitenoise_tap2:0)) && in_noise_mode()))
|
||||
{
|
||||
m_RNG >>= 1;
|
||||
m_RNG |= m_feedback_mask;
|
||||
}
|
||||
else
|
||||
{
|
||||
m_RNG >>= 1;
|
||||
}
|
||||
m_output[3] = m_RNG & 1;
|
||||
|
||||
// handle channel 3
|
||||
m_count[3]--;
|
||||
if (m_count[3] <= 0)
|
||||
{
|
||||
// if noisemode is 1, both taps are enabled
|
||||
// if noisemode is 0, the lower tap, whitenoisetap2, is held at 0
|
||||
// The != was a bit-XOR (^) before
|
||||
if (((m_RNG & m_whitenoise_tap1)!=0) != (((int32_t)(m_RNG & m_whitenoise_tap2)!=(m_ncr_style_psg?m_whitenoise_tap2:0)) && in_noise_mode()))
|
||||
{
|
||||
m_RNG >>= 1;
|
||||
m_RNG |= m_feedback_mask;
|
||||
}
|
||||
else
|
||||
{
|
||||
m_RNG >>= 1;
|
||||
}
|
||||
m_output[3] = m_RNG & 1;
|
||||
m_count[3] = m_period[3];
|
||||
}
|
||||
|
||||
m_count[3] = m_period[3];
|
||||
}
|
||||
}
|
||||
if (m_stereo)
|
||||
{
|
||||
out = ((((m_stereo_mask & 0x10)!=0) && (m_output[0]!=0))? m_volume[0] : 0)
|
||||
+ ((((m_stereo_mask & 0x20)!=0) && (m_output[1]!=0))? m_volume[1] : 0)
|
||||
+ ((((m_stereo_mask & 0x40)!=0) && (m_output[2]!=0))? m_volume[2] : 0)
|
||||
+ ((((m_stereo_mask & 0x80)!=0) && (m_output[3]!=0))? m_volume[3] : 0);
|
||||
|
||||
if (m_stereo)
|
||||
{
|
||||
out = ((((m_stereo_mask & 0x10)!=0) && (m_output[0]!=0))? m_volume[0] : 0)
|
||||
+ ((((m_stereo_mask & 0x20)!=0) && (m_output[1]!=0))? m_volume[1] : 0)
|
||||
+ ((((m_stereo_mask & 0x40)!=0) && (m_output[2]!=0))? m_volume[2] : 0)
|
||||
+ ((((m_stereo_mask & 0x80)!=0) && (m_output[3]!=0))? m_volume[3] : 0);
|
||||
out2= ((((m_stereo_mask & 0x1)!=0) && (m_output[0]!=0))? m_volume[0] : 0)
|
||||
+ ((((m_stereo_mask & 0x2)!=0) && (m_output[1]!=0))? m_volume[1] : 0)
|
||||
+ ((((m_stereo_mask & 0x4)!=0) && (m_output[2]!=0))? m_volume[2] : 0)
|
||||
+ ((((m_stereo_mask & 0x8)!=0) && (m_output[3]!=0))? m_volume[3] : 0);
|
||||
}
|
||||
else
|
||||
{
|
||||
out= ((m_output[0]!=0)? m_volume[0]:0)
|
||||
+((m_output[1]!=0)? m_volume[1]:0)
|
||||
+((m_output[2]!=0)? m_volume[2]:0)
|
||||
+((m_output[3]!=0)? m_volume[3]:0);
|
||||
}
|
||||
|
||||
out2= ((((m_stereo_mask & 0x1)!=0) && (m_output[0]!=0))? m_volume[0] : 0)
|
||||
+ ((((m_stereo_mask & 0x2)!=0) && (m_output[1]!=0))? m_volume[1] : 0)
|
||||
+ ((((m_stereo_mask & 0x4)!=0) && (m_output[2]!=0))? m_volume[2] : 0)
|
||||
+ ((((m_stereo_mask & 0x8)!=0) && (m_output[3]!=0))? m_volume[3] : 0);
|
||||
}
|
||||
else
|
||||
{
|
||||
out= ((m_output[0]!=0)? m_volume[0]:0)
|
||||
+((m_output[1]!=0)? m_volume[1]:0)
|
||||
+((m_output[2]!=0)? m_volume[2]:0)
|
||||
+((m_output[3]!=0)? m_volume[3]:0);
|
||||
}
|
||||
if (m_negate) { out = -out; out2 = -out2; }
|
||||
|
||||
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;
|
||||
}
|
||||
|
|
|
@ -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
|
||||
|
|
Loading…
Reference in a new issue