Run SMP and DSP in less of a lockstep arrangement

CQTexperiment
Chris Moeller 2013-10-27 15:00:13 -07:00
parent 9211827957
commit 0a2dd30a51
7 changed files with 51 additions and 24 deletions

View File

@ -198,9 +198,9 @@ public:
unsigned read_counter( int rate );
int interpolate( voice_t const* v );
int interpolate_cubic( voice_t const* v );
int interpolate_sinc( voice_t const* v );
int interpolate_linear( voice_t const* v );
int interpolate_cubic( voice_t const* v );
int interpolate_sinc( voice_t const* v );
int interpolate_linear( voice_t const* v );
int interpolate_nearest( voice_t const* v );
void run_envelope( voice_t* const v );
@ -250,7 +250,7 @@ public:
#include <assert.h>
inline int SPC_DSP::sample_count() const { return m.out - m.out_begin; }
inline int SPC_DSP::read( int addr ) const
{
assert( (unsigned) addr < register_count );

View File

@ -3,18 +3,25 @@
namespace SuperFamicom {
void DSP::step(unsigned clocks) {
void DSP::step(uint64_t clocks) {
clock += clocks;
}
void DSP::enter() {
spc_dsp.run(1);
step(24 * 4096);
int64_t dsp_clocks = (-clock) / (24 * 4096) + 1;
spc_dsp.run(dsp_clocks);
step(dsp_clocks * 24 * 4096);
signed count = spc_dsp.sample_count();
if(count > 0) {
for(unsigned n = 0; n < count; n += 2) smp.sample(samplebuffer[n + 0], samplebuffer[n + 1]);
if(count > removed_samples) {
for(unsigned n = removed_samples; n < count; n += 2) {
if (!smp.sample(samplebuffer[n + 0], samplebuffer[n + 1])) {
removed_samples = n;
return;
}
}
spc_dsp.set_output(samplebuffer, 8192);
removed_samples = 0;
}
}
@ -34,11 +41,13 @@ void DSP::power() {
spc_dsp.init(smp.apuram);
spc_dsp.reset();
spc_dsp.set_output(samplebuffer, 8192);
removed_samples = 0;
}
void DSP::reset() {
spc_dsp.soft_reset();
spc_dsp.set_output(samplebuffer, 8192);
removed_samples = 0;
}
void DSP::channel_enable(unsigned channel, bool enable) {
@ -55,7 +64,7 @@ void DSP::disable_surround(bool disable) {
}
DSP::DSP(struct SMP & p_smp)
: smp( p_smp ), clock( 0 ) {
: smp( p_smp ), clock( 0 ), removed_samples( 0 ) {
for(unsigned i = 0; i < 8; i++) channel_enabled[i] = true;
}

View File

@ -9,8 +9,9 @@ namespace SuperFamicom {
struct DSP {
int64_t clock;
unsigned long removed_samples;
inline void step(unsigned clocks);
inline void step(uint64_t clocks);
bool mute();
uint8_t read(uint8_t addr);

View File

@ -22,6 +22,14 @@ void SMP::port_write(uint8_t port, uint8_t data) {
uint8_t SMP::op_busread(uint16_t addr) {
unsigned result;
if ( !(dsp.read( SPC_DSP::r_flg ) & 0x20) ) {
int start = 0x100 * dsp.read( SPC_DSP::r_esa );
int end = start + 0x800 * (dsp.read( SPC_DSP::r_edl ) & 0x0F);
if ( end > 0x10000 )
end = 0x10000;
if ( addr >= start || addr < end) synchronize_dsp();
}
switch(addr) {
case 0xf0: //TEST -- write-only register
return 0x00;
@ -34,6 +42,7 @@ uint8_t SMP::op_busread(uint16_t addr) {
case 0xf3: //DSPDATA
//0x80-0xff are read-only mirrors of 0x00-0x7f
synchronize_dsp();
return dsp.read(status.dsp_addr & 0x7f);
case 0xf4: //CPUIO0
@ -77,6 +86,7 @@ uint8_t SMP::op_busread(uint16_t addr) {
}
void SMP::op_buswrite(uint16_t addr, uint8_t data) {
synchronize_dsp();
switch(addr) {
case 0xf0: //TEST
if(regs.p.p) break; //writes only valid when P flag is clear

View File

@ -14,21 +14,26 @@ void SMP::step(unsigned clocks) {
}
void SMP::synchronize_dsp() {
while(dsp.clock < 0 && sample_buffer < sample_buffer_end) dsp.enter();
while(dsp.clock < 0) dsp.enter();
}
void SMP::enter() {
while(status.clock_speed != 2 && sample_buffer < sample_buffer_end) op_step();
if (status.clock_speed == 2) {
while(sample_buffer < sample_buffer_end) {
clock -= (sample_buffer_end - sample_buffer) * 24 * 16;
while(status.clock_speed != 2 && clock < 0) op_step();
if(status.clock_speed == 2) step(-clock);
synchronize_dsp();
if (sample_buffer < sample_buffer_end) {
dsp.clock -= 24 * 32 * (sample_buffer_end - sample_buffer) / 2;
synchronize_dsp();
}
}
}
void SMP::render(int16_t * buffer, unsigned count) {
while (count > 4096) {
sample_buffer = buffer;
sample_buffer_end = buffer + 4096;
buffer += 4096;
count -= 4096;
enter();
}
sample_buffer = buffer;
sample_buffer_end = buffer + count;
enter();
@ -46,14 +51,16 @@ void SMP::skip(unsigned count) {
enter();
}
void SMP::sample(int16_t left, int16_t right) {
bool SMP::sample(int16_t left, int16_t right) {
if ( sample_buffer_end - sample_buffer < 2 ) return false;
if ( sample_buffer > ((const int16_t *)0) + 4096 ) {
if ( sample_buffer < sample_buffer_end ) *sample_buffer++ = left;
if ( sample_buffer < sample_buffer_end ) *sample_buffer++ = right;
*sample_buffer++ = left;
*sample_buffer++ = right;
}
else if ( sample_buffer < sample_buffer_end ){
else {
sample_buffer += 2;
}
return true;
}
void SMP::power() {

View File

@ -47,7 +47,7 @@ private:
int16_t * sample_buffer;
int16_t const* sample_buffer_end;
public:
void sample( int16_t, int16_t );
bool sample( int16_t, int16_t );
SMP();
~SMP();

View File

@ -2,7 +2,7 @@
void SMP::add_clocks(unsigned clocks) {
step(clocks);
synchronize_dsp();
//synchronize_dsp();
}
void SMP::cycle_edge() {