Run SMP and DSP in less of a lockstep arrangement
parent
9211827957
commit
0a2dd30a51
|
@ -3,18 +3,25 @@
|
||||||
|
|
||||||
namespace SuperFamicom {
|
namespace SuperFamicom {
|
||||||
|
|
||||||
void DSP::step(unsigned clocks) {
|
void DSP::step(uint64_t clocks) {
|
||||||
clock += clocks;
|
clock += clocks;
|
||||||
}
|
}
|
||||||
|
|
||||||
void DSP::enter() {
|
void DSP::enter() {
|
||||||
spc_dsp.run(1);
|
int64_t dsp_clocks = (-clock) / (24 * 4096) + 1;
|
||||||
step(24 * 4096);
|
spc_dsp.run(dsp_clocks);
|
||||||
|
step(dsp_clocks * 24 * 4096);
|
||||||
|
|
||||||
signed count = spc_dsp.sample_count();
|
signed count = spc_dsp.sample_count();
|
||||||
if(count > 0) {
|
if(count > removed_samples) {
|
||||||
for(unsigned n = 0; n < count; n += 2) smp.sample(samplebuffer[n + 0], samplebuffer[n + 1]);
|
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);
|
spc_dsp.set_output(samplebuffer, 8192);
|
||||||
|
removed_samples = 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -34,11 +41,13 @@ void DSP::power() {
|
||||||
spc_dsp.init(smp.apuram);
|
spc_dsp.init(smp.apuram);
|
||||||
spc_dsp.reset();
|
spc_dsp.reset();
|
||||||
spc_dsp.set_output(samplebuffer, 8192);
|
spc_dsp.set_output(samplebuffer, 8192);
|
||||||
|
removed_samples = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
void DSP::reset() {
|
void DSP::reset() {
|
||||||
spc_dsp.soft_reset();
|
spc_dsp.soft_reset();
|
||||||
spc_dsp.set_output(samplebuffer, 8192);
|
spc_dsp.set_output(samplebuffer, 8192);
|
||||||
|
removed_samples = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
void DSP::channel_enable(unsigned channel, bool enable) {
|
void DSP::channel_enable(unsigned channel, bool enable) {
|
||||||
|
@ -55,7 +64,7 @@ void DSP::disable_surround(bool disable) {
|
||||||
}
|
}
|
||||||
|
|
||||||
DSP::DSP(struct SMP & p_smp)
|
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;
|
for(unsigned i = 0; i < 8; i++) channel_enabled[i] = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -9,8 +9,9 @@ namespace SuperFamicom {
|
||||||
|
|
||||||
struct DSP {
|
struct DSP {
|
||||||
int64_t clock;
|
int64_t clock;
|
||||||
|
unsigned long removed_samples;
|
||||||
|
|
||||||
inline void step(unsigned clocks);
|
inline void step(uint64_t clocks);
|
||||||
|
|
||||||
bool mute();
|
bool mute();
|
||||||
uint8_t read(uint8_t addr);
|
uint8_t read(uint8_t addr);
|
||||||
|
|
|
@ -22,6 +22,14 @@ void SMP::port_write(uint8_t port, uint8_t data) {
|
||||||
uint8_t SMP::op_busread(uint16_t addr) {
|
uint8_t SMP::op_busread(uint16_t addr) {
|
||||||
unsigned result;
|
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) {
|
switch(addr) {
|
||||||
case 0xf0: //TEST -- write-only register
|
case 0xf0: //TEST -- write-only register
|
||||||
return 0x00;
|
return 0x00;
|
||||||
|
@ -34,6 +42,7 @@ uint8_t SMP::op_busread(uint16_t addr) {
|
||||||
|
|
||||||
case 0xf3: //DSPDATA
|
case 0xf3: //DSPDATA
|
||||||
//0x80-0xff are read-only mirrors of 0x00-0x7f
|
//0x80-0xff are read-only mirrors of 0x00-0x7f
|
||||||
|
synchronize_dsp();
|
||||||
return dsp.read(status.dsp_addr & 0x7f);
|
return dsp.read(status.dsp_addr & 0x7f);
|
||||||
|
|
||||||
case 0xf4: //CPUIO0
|
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) {
|
void SMP::op_buswrite(uint16_t addr, uint8_t data) {
|
||||||
|
synchronize_dsp();
|
||||||
switch(addr) {
|
switch(addr) {
|
||||||
case 0xf0: //TEST
|
case 0xf0: //TEST
|
||||||
if(regs.p.p) break; //writes only valid when P flag is clear
|
if(regs.p.p) break; //writes only valid when P flag is clear
|
||||||
|
|
|
@ -14,21 +14,26 @@ void SMP::step(unsigned clocks) {
|
||||||
}
|
}
|
||||||
|
|
||||||
void SMP::synchronize_dsp() {
|
void SMP::synchronize_dsp() {
|
||||||
while(dsp.clock < 0 && sample_buffer < sample_buffer_end) dsp.enter();
|
while(dsp.clock < 0) dsp.enter();
|
||||||
}
|
}
|
||||||
|
|
||||||
void SMP::enter() {
|
void SMP::enter() {
|
||||||
while(status.clock_speed != 2 && sample_buffer < sample_buffer_end) op_step();
|
while(sample_buffer < sample_buffer_end) {
|
||||||
if (status.clock_speed == 2) {
|
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();
|
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) {
|
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 = buffer;
|
||||||
sample_buffer_end = buffer + count;
|
sample_buffer_end = buffer + count;
|
||||||
enter();
|
enter();
|
||||||
|
@ -46,14 +51,16 @@ void SMP::skip(unsigned count) {
|
||||||
enter();
|
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 > ((const int16_t *)0) + 4096 ) {
|
||||||
if ( sample_buffer < sample_buffer_end ) *sample_buffer++ = left;
|
*sample_buffer++ = left;
|
||||||
if ( sample_buffer < sample_buffer_end ) *sample_buffer++ = right;
|
*sample_buffer++ = right;
|
||||||
}
|
}
|
||||||
else if ( sample_buffer < sample_buffer_end ){
|
else {
|
||||||
sample_buffer += 2;
|
sample_buffer += 2;
|
||||||
}
|
}
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
void SMP::power() {
|
void SMP::power() {
|
||||||
|
|
|
@ -47,7 +47,7 @@ private:
|
||||||
int16_t * sample_buffer;
|
int16_t * sample_buffer;
|
||||||
int16_t const* sample_buffer_end;
|
int16_t const* sample_buffer_end;
|
||||||
public:
|
public:
|
||||||
void sample( int16_t, int16_t );
|
bool sample( int16_t, int16_t );
|
||||||
|
|
||||||
SMP();
|
SMP();
|
||||||
~SMP();
|
~SMP();
|
||||||
|
|
|
@ -2,7 +2,7 @@
|
||||||
|
|
||||||
void SMP::add_clocks(unsigned clocks) {
|
void SMP::add_clocks(unsigned clocks) {
|
||||||
step(clocks);
|
step(clocks);
|
||||||
synchronize_dsp();
|
//synchronize_dsp();
|
||||||
}
|
}
|
||||||
|
|
||||||
void SMP::cycle_edge() {
|
void SMP::cycle_edge() {
|
||||||
|
|
Loading…
Reference in New Issue